gcc41: update README.DELETED
[dragonfly.git] / contrib / texinfo-4 / makeinfo / footnote.c
blobe5a7f4c08f56656a4681ec8b78f0a295f1bca206
1 /* footnote.c -- footnotes for Texinfo.
2 $Id: footnote.c,v 1.7 2004/04/11 17:56:47 karl Exp $
4 Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include "system.h"
21 #include "footnote.h"
22 #include "macro.h"
23 #include "makeinfo.h"
24 #include "node.h"
25 #include "xml.h"
26 #include "xref.h"
28 /* Nonzero means that the footnote style for this document was set on
29 the command line, which overrides any other settings. */
30 int footnote_style_preset = 0;
32 /* The current footnote number in this node. Each time a new node is
33 started this is reset to 1. */
34 int current_footnote_number = 1;
36 /* Nonzero means we automatically number footnotes with no specified marker. */
37 int number_footnotes = 1;
39 /* Nonzero means we are currently outputting footnotes. */
40 int already_outputting_pending_notes = 0;
43 /* Footnotes can be handled in one of two ways:
45 separate_node:
46 Make them look like followed references, with the reference
47 destinations in a makeinfo manufactured node or,
48 end_node:
49 Make them appear at the bottom of the node that they originally
50 appeared in. */
52 #define separate_node 0
53 #define end_node 1
55 int footnote_style = end_node;
56 int first_footnote_this_node = 1;
57 int footnote_count = 0;
59 /* Set the footnote style based on the style identifier in STRING. */
60 int
61 set_footnote_style (char *string)
63 if (strcasecmp (string, "separate") == 0)
64 footnote_style = separate_node;
65 else if (strcasecmp (string, "end") == 0)
66 footnote_style = end_node;
67 else
68 return -1;
70 return 0;
73 void
74 cm_footnotestyle (void)
76 char *arg;
78 get_rest_of_line (1, &arg);
80 /* If set on command line, do not change the footnote style. */
81 if (!footnote_style_preset && set_footnote_style (arg) != 0)
82 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
84 free (arg);
87 typedef struct fn
89 struct fn *next;
90 char *marker;
91 char *note;
92 int number;
93 } FN;
95 FN *pending_notes = NULL;
97 /* A method for remembering footnotes. Note that this list gets output
98 at the end of the current node. */
99 static void
100 remember_note (char *marker, char *note)
102 FN *temp = xmalloc (sizeof (FN));
104 temp->marker = xstrdup (marker);
105 temp->note = xstrdup (note);
106 temp->next = pending_notes;
107 temp->number = current_footnote_number;
108 pending_notes = temp;
109 footnote_count++;
112 /* How to get rid of existing footnotes. */
113 static void
114 free_pending_notes (void)
116 FN *temp;
118 while ((temp = pending_notes))
120 free (temp->marker);
121 free (temp->note);
122 pending_notes = pending_notes->next;
123 free (temp);
125 first_footnote_this_node = 1;
126 footnote_count = 0;
127 current_footnote_number = 1; /* for html */
130 /* What to do when you see a @footnote construct. */
132 /* Handle a "footnote".
133 footnote *{this is a footnote}
134 where "*" is the (optional) marker character for this note. */
135 void
136 cm_footnote (void)
138 char *marker;
139 char *note;
141 get_until ("{", &marker);
142 canon_white (marker);
144 if (macro_expansion_output_stream && !executing_string)
145 append_to_expansion_output (input_text_offset + 1); /* include the { */
147 /* Read the argument in braces. */
148 if (curchar () != '{')
150 line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
151 COMMAND_PREFIX, command, marker);
152 free (marker);
153 return;
155 else
157 int len;
158 int braces = 1;
159 int loc = ++input_text_offset;
161 while (braces)
163 if (loc == input_text_length)
165 line_error (_("No closing brace for footnote `%s'"), marker);
166 return;
169 if (input_text[loc] == '{')
170 braces++;
171 else if (input_text[loc] == '}')
172 braces--;
173 else if (input_text[loc] == '\n')
174 line_number++;
176 loc++;
179 len = (loc - input_text_offset) - 1;
180 note = xmalloc (len + 1);
181 memcpy (note, &input_text[input_text_offset], len);
182 note[len] = 0;
183 input_text_offset = loc;
186 /* Must write the macro-expanded argument to the macro expansion
187 output stream. This is like the case in index_add_arg. */
188 if (macro_expansion_output_stream && !executing_string)
190 /* Calling me_execute_string on a lone } provokes an error, since
191 as far as the reader knows there is no matching {. We wrote
192 the { above in the call to append_to_expansion_output. */
193 me_execute_string_keep_state (note, "}");
196 if (!current_node || !*current_node)
198 line_error (_("Footnote defined without parent node"));
199 free (marker);
200 free (note);
201 return;
204 /* output_pending_notes is non-reentrant (it uses a global data
205 structure pending_notes, which it frees before it returns), and
206 TeX doesn't grok footnotes inside footnotes anyway. Disallow
207 that. */
208 if (already_outputting_pending_notes)
210 line_error (_("Footnotes inside footnotes are not allowed"));
211 free (marker);
212 free (note);
213 return;
216 if (!*marker)
218 free (marker);
220 if (number_footnotes)
222 marker = xmalloc (10);
223 sprintf (marker, "%d", current_footnote_number);
225 else
226 marker = xstrdup ("*");
229 if (xml)
230 xml_insert_footnote (note);
231 else
233 remember_note (marker, note);
235 /* fixme: html: footnote processing needs work; we currently ignore
236 the style requested; we could clash with a node name of the form
237 `fn-<n>', though that's unlikely. */
238 if (html)
240 /* Hyperlink also serves as an anchor (mnemonic: fnd is footnote
241 definition.) */
242 add_html_elt ("<a rel=\"footnote\" href=");
243 add_word_args ("\"#fn-%d\" name=\"fnd-%d\"><sup>%s</sup></a>",
244 current_footnote_number, current_footnote_number,
245 marker);
247 else
248 /* Your method should at least insert MARKER. */
249 switch (footnote_style)
251 case separate_node:
252 add_word_args ("(%s)", marker);
253 execute_string (" (*note %s-Footnote-%d::)",
254 current_node, current_footnote_number);
255 if (first_footnote_this_node)
257 char *temp_string, *expanded_ref;
259 temp_string = xmalloc (strlen (current_node)
260 + strlen ("-Footnotes") + 1);
262 strcpy (temp_string, current_node);
263 strcat (temp_string, "-Footnotes");
264 expanded_ref = expansion (temp_string, 0);
265 remember_node_reference (expanded_ref, line_number,
266 followed_reference);
267 free (temp_string);
268 free (expanded_ref);
269 first_footnote_this_node = 0;
271 break;
273 case end_node:
274 add_word_args ("(%s)", marker);
275 break;
277 default:
278 break;
280 current_footnote_number++;
282 free (marker);
283 free (note);
286 /* Output the footnotes. We are at the end of the current node. */
287 void
288 output_pending_notes (void)
290 FN *footnote = pending_notes;
292 if (!pending_notes)
293 return;
295 if (html)
297 add_html_block_elt ("<div class=\"footnote\">\n<hr>\n");
298 /* We add an anchor here so @printindex can refer to this point
299 (as the node name) for entries defined in footnotes. */
300 if (!splitting)
301 add_word ("<a name=\"texinfo-footnotes-in-document\"></a>");
302 add_word_args ("<h4>%s</h4>", (char *) _("Footnotes"));
304 else
305 switch (footnote_style)
307 case separate_node:
309 char *old_current_node = current_node;
310 char *old_command = xstrdup (command);
312 already_outputting_pending_notes++;
313 execute_string ("%cnode %s-Footnotes,,,%s\n",
314 COMMAND_PREFIX, current_node, current_node);
315 already_outputting_pending_notes--;
316 current_node = old_current_node;
317 free (command);
318 command = old_command;
320 break;
322 case end_node:
323 close_paragraph ();
324 in_fixed_width_font++;
325 /* This string should be translated according to the
326 @documentlanguage, not the current LANG. We can't do that
327 yet, so leave it in English. */
328 execute_string ("---------- Footnotes ----------\n\n");
329 in_fixed_width_font--;
330 break;
333 /* Handle the footnotes in reverse order. */
335 int save_in_fixed_width_font = in_fixed_width_font;
336 FN **array = xmalloc ((footnote_count + 1) * sizeof (FN *));
337 array[footnote_count] = NULL;
339 while (--footnote_count > -1)
341 array[footnote_count] = footnote;
342 footnote = footnote->next;
345 filling_enabled = 1;
346 indented_fill = 1;
347 in_fixed_width_font = 0;
349 while ((footnote = array[++footnote_count]))
351 if (html)
353 /* Make the text of every footnote begin a separate paragraph. */
354 add_html_block_elt ("<p class=\"footnote\"><small>");
355 /* Make footnote number a link to its definition. */
356 add_word_args ("[<a name=\"fn-%d\" href=\"#fnd-%d\">%d</a>]",
357 footnote->number, footnote->number, footnote->number);
358 add_word ("</small> ");
359 already_outputting_pending_notes++;
360 execute_string ("%s", footnote->note);
361 already_outputting_pending_notes--;
362 add_word ("</p>\n");
364 else
366 char *old_current_node = current_node;
367 char *old_command = xstrdup (command);
369 already_outputting_pending_notes++;
370 execute_string ("%canchor{%s-Footnote-%d}(%s) %s",
371 COMMAND_PREFIX, current_node, footnote->number,
372 footnote->marker, footnote->note);
373 already_outputting_pending_notes--;
374 current_node = old_current_node;
375 free (command);
376 command = old_command;
379 close_paragraph ();
382 if (html)
383 add_word ("<hr></div>");
384 close_paragraph ();
385 free (array);
387 in_fixed_width_font = save_in_fixed_width_font;
390 free_pending_notes ();