3 /* footnote.c -- footnotes for Texinfo.
4 Id: footnote.c,v 1.7 2004/04/11 17:56:47 karl Exp
6 Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
30 /* Nonzero means that the footnote style for this document was set on
31 the command line, which overrides any other settings. */
32 int footnote_style_preset
= 0;
34 /* The current footnote number in this node. Each time a new node is
35 started this is reset to 1. */
36 int current_footnote_number
= 1;
38 /* Nonzero means we automatically number footnotes with no specified marker. */
39 int number_footnotes
= 1;
41 /* Nonzero means we are currently outputting footnotes. */
42 int already_outputting_pending_notes
= 0;
45 /* Footnotes can be handled in one of two ways:
48 Make them look like followed references, with the reference
49 destinations in a makeinfo manufactured node or,
51 Make them appear at the bottom of the node that they originally
54 #define separate_node 0
57 int footnote_style
= end_node
;
58 int first_footnote_this_node
= 1;
59 int footnote_count
= 0;
61 /* Set the footnote style based on the style identifier in STRING. */
63 set_footnote_style (char *string
)
65 if (strcasecmp (string
, "separate") == 0)
66 footnote_style
= separate_node
;
67 else if (strcasecmp (string
, "end") == 0)
68 footnote_style
= end_node
;
76 cm_footnotestyle (void)
80 get_rest_of_line (1, &arg
);
82 /* If set on command line, do not change the footnote style. */
83 if (!footnote_style_preset
&& set_footnote_style (arg
) != 0)
84 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX
, command
);
97 FN
*pending_notes
= NULL
;
99 /* A method for remembering footnotes. Note that this list gets output
100 at the end of the current node. */
102 remember_note (char *marker
, char *note
)
104 FN
*temp
= xmalloc (sizeof (FN
));
106 temp
->marker
= xstrdup (marker
);
107 temp
->note
= xstrdup (note
);
108 temp
->next
= pending_notes
;
109 temp
->number
= current_footnote_number
;
110 pending_notes
= temp
;
114 /* How to get rid of existing footnotes. */
116 free_pending_notes (void)
120 while ((temp
= pending_notes
))
124 pending_notes
= pending_notes
->next
;
127 first_footnote_this_node
= 1;
129 current_footnote_number
= 1; /* for html */
132 /* What to do when you see a @footnote construct. */
134 /* Handle a "footnote".
135 footnote *{this is a footnote}
136 where "*" is the (optional) marker character for this note. */
143 get_until ("{", &marker
);
144 canon_white (marker
);
146 if (macro_expansion_output_stream
&& !executing_string
)
147 append_to_expansion_output (input_text_offset
+ 1); /* include the { */
149 /* Read the argument in braces. */
150 if (curchar () != '{')
152 line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
153 COMMAND_PREFIX
, command
, marker
);
161 int loc
= ++input_text_offset
;
165 if (loc
== input_text_length
)
167 line_error (_("No closing brace for footnote `%s'"), marker
);
171 if (input_text
[loc
] == '{')
173 else if (input_text
[loc
] == '}')
175 else if (input_text
[loc
] == '\n')
181 len
= (loc
- input_text_offset
) - 1;
182 note
= xmalloc (len
+ 1);
183 memcpy (note
, &input_text
[input_text_offset
], len
);
185 input_text_offset
= loc
;
188 /* Must write the macro-expanded argument to the macro expansion
189 output stream. This is like the case in index_add_arg. */
190 if (macro_expansion_output_stream
&& !executing_string
)
192 /* Calling me_execute_string on a lone } provokes an error, since
193 as far as the reader knows there is no matching {. We wrote
194 the { above in the call to append_to_expansion_output. */
195 me_execute_string_keep_state (note
, "}");
198 if (!current_node
|| !*current_node
)
200 line_error (_("Footnote defined without parent node"));
206 /* output_pending_notes is non-reentrant (it uses a global data
207 structure pending_notes, which it frees before it returns), and
208 TeX doesn't grok footnotes inside footnotes anyway. Disallow
210 if (already_outputting_pending_notes
)
212 line_error (_("Footnotes inside footnotes are not allowed"));
222 if (number_footnotes
)
224 marker
= xmalloc (10);
225 sprintf (marker
, "%d", current_footnote_number
);
228 marker
= xstrdup ("*");
232 xml_insert_footnote (note
);
235 remember_note (marker
, note
);
237 /* fixme: html: footnote processing needs work; we currently ignore
238 the style requested; we could clash with a node name of the form
239 `fn-<n>', though that's unlikely. */
242 /* Hyperlink also serves as an anchor (mnemonic: fnd is footnote
244 add_html_elt ("<a rel=\"footnote\" href=");
245 add_word_args ("\"#fn-%d\" name=\"fnd-%d\"><sup>%s</sup></a>",
246 current_footnote_number
, current_footnote_number
,
250 /* Your method should at least insert MARKER. */
251 switch (footnote_style
)
254 add_word_args ("(%s)", marker
);
255 execute_string (" (*note %s-Footnote-%d::)",
256 current_node
, current_footnote_number
);
257 if (first_footnote_this_node
)
259 char *temp_string
, *expanded_ref
;
261 temp_string
= xmalloc (strlen (current_node
)
262 + strlen ("-Footnotes") + 1);
264 strcpy (temp_string
, current_node
);
265 strcat (temp_string
, "-Footnotes");
266 expanded_ref
= expansion (temp_string
, 0);
267 remember_node_reference (expanded_ref
, line_number
,
271 first_footnote_this_node
= 0;
276 add_word_args ("(%s)", marker
);
282 current_footnote_number
++;
288 /* Output the footnotes. We are at the end of the current node. */
290 output_pending_notes (void)
292 FN
*footnote
= pending_notes
;
299 add_html_block_elt ("<div class=\"footnote\">\n<hr>\n");
300 /* We add an anchor here so @printindex can refer to this point
301 (as the node name) for entries defined in footnotes. */
303 add_word ("<a name=\"texinfo-footnotes-in-document\"></a>");
304 add_word_args ("<h4>%s</h4>", (char *) _("Footnotes"));
307 switch (footnote_style
)
311 char *old_current_node
= current_node
;
312 char *old_command
= xstrdup (command
);
314 already_outputting_pending_notes
++;
315 execute_string ("%cnode %s-Footnotes,,,%s\n",
316 COMMAND_PREFIX
, current_node
, current_node
);
317 already_outputting_pending_notes
--;
318 current_node
= old_current_node
;
320 command
= old_command
;
326 in_fixed_width_font
++;
327 /* This string should be translated according to the
328 @documentlanguage, not the current LANG. We can't do that
329 yet, so leave it in English. */
330 execute_string ("---------- Footnotes ----------\n\n");
331 in_fixed_width_font
--;
335 /* Handle the footnotes in reverse order. */
337 int save_in_fixed_width_font
= in_fixed_width_font
;
338 FN
**array
= xmalloc ((footnote_count
+ 1) * sizeof (FN
*));
339 array
[footnote_count
] = NULL
;
341 while (--footnote_count
> -1)
343 array
[footnote_count
] = footnote
;
344 footnote
= footnote
->next
;
349 in_fixed_width_font
= 0;
351 while ((footnote
= array
[++footnote_count
]))
355 /* Make the text of every footnote begin a separate paragraph. */
356 add_html_block_elt ("<p class=\"footnote\"><small>");
357 /* Make footnote number a link to its definition. */
358 add_word_args ("[<a name=\"fn-%d\" href=\"#fnd-%d\">%d</a>]",
359 footnote
->number
, footnote
->number
, footnote
->number
);
360 add_word ("</small> ");
361 already_outputting_pending_notes
++;
362 execute_string ("%s", footnote
->note
);
363 already_outputting_pending_notes
--;
368 char *old_current_node
= current_node
;
369 char *old_command
= xstrdup (command
);
371 already_outputting_pending_notes
++;
372 execute_string ("%canchor{%s-Footnote-%d}(%s) %s",
373 COMMAND_PREFIX
, current_node
, footnote
->number
,
374 footnote
->marker
, footnote
->note
);
375 already_outputting_pending_notes
--;
376 current_node
= old_current_node
;
378 command
= old_command
;
385 add_word ("<hr></div>");
389 in_fixed_width_font
= save_in_fixed_width_font
;
392 free_pending_notes ();