diff options
Diffstat (limited to 'Build/source/utils/texinfo/makeinfo/footnote.c')
-rw-r--r-- | Build/source/utils/texinfo/makeinfo/footnote.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/Build/source/utils/texinfo/makeinfo/footnote.c b/Build/source/utils/texinfo/makeinfo/footnote.c new file mode 100644 index 00000000000..e5a7f4c08f5 --- /dev/null +++ b/Build/source/utils/texinfo/makeinfo/footnote.c @@ -0,0 +1,391 @@ +/* footnote.c -- footnotes for Texinfo. + $Id: footnote.c,v 1.7 2004/04/11 17:56:47 karl Exp $ + + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "system.h" +#include "footnote.h" +#include "macro.h" +#include "makeinfo.h" +#include "node.h" +#include "xml.h" +#include "xref.h" + +/* Nonzero means that the footnote style for this document was set on + the command line, which overrides any other settings. */ +int footnote_style_preset = 0; + +/* The current footnote number in this node. Each time a new node is + started this is reset to 1. */ +int current_footnote_number = 1; + +/* Nonzero means we automatically number footnotes with no specified marker. */ +int number_footnotes = 1; + +/* Nonzero means we are currently outputting footnotes. */ +int already_outputting_pending_notes = 0; + + +/* Footnotes can be handled in one of two ways: + + separate_node: + Make them look like followed references, with the reference + destinations in a makeinfo manufactured node or, + end_node: + Make them appear at the bottom of the node that they originally + appeared in. */ + +#define separate_node 0 +#define end_node 1 + +int footnote_style = end_node; +int first_footnote_this_node = 1; +int footnote_count = 0; + +/* Set the footnote style based on the style identifier in STRING. */ +int +set_footnote_style (char *string) +{ + if (strcasecmp (string, "separate") == 0) + footnote_style = separate_node; + else if (strcasecmp (string, "end") == 0) + footnote_style = end_node; + else + return -1; + + return 0; +} + +void +cm_footnotestyle (void) +{ + char *arg; + + get_rest_of_line (1, &arg); + + /* If set on command line, do not change the footnote style. */ + if (!footnote_style_preset && set_footnote_style (arg) != 0) + line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command); + + free (arg); +} + +typedef struct fn +{ + struct fn *next; + char *marker; + char *note; + int number; +} FN; + +FN *pending_notes = NULL; + +/* A method for remembering footnotes. Note that this list gets output + at the end of the current node. */ +static void +remember_note (char *marker, char *note) +{ + FN *temp = xmalloc (sizeof (FN)); + + temp->marker = xstrdup (marker); + temp->note = xstrdup (note); + temp->next = pending_notes; + temp->number = current_footnote_number; + pending_notes = temp; + footnote_count++; +} + +/* How to get rid of existing footnotes. */ +static void +free_pending_notes (void) +{ + FN *temp; + + while ((temp = pending_notes)) + { + free (temp->marker); + free (temp->note); + pending_notes = pending_notes->next; + free (temp); + } + first_footnote_this_node = 1; + footnote_count = 0; + current_footnote_number = 1; /* for html */ +} + +/* What to do when you see a @footnote construct. */ + + /* Handle a "footnote". + footnote *{this is a footnote} + where "*" is the (optional) marker character for this note. */ +void +cm_footnote (void) +{ + char *marker; + char *note; + + get_until ("{", &marker); + canon_white (marker); + + if (macro_expansion_output_stream && !executing_string) + append_to_expansion_output (input_text_offset + 1); /* include the { */ + + /* Read the argument in braces. */ + if (curchar () != '{') + { + line_error (_("`%c%s' needs an argument `{...}', not just `%s'"), + COMMAND_PREFIX, command, marker); + free (marker); + return; + } + else + { + int len; + int braces = 1; + int loc = ++input_text_offset; + + while (braces) + { + if (loc == input_text_length) + { + line_error (_("No closing brace for footnote `%s'"), marker); + return; + } + + if (input_text[loc] == '{') + braces++; + else if (input_text[loc] == '}') + braces--; + else if (input_text[loc] == '\n') + line_number++; + + loc++; + } + + len = (loc - input_text_offset) - 1; + note = xmalloc (len + 1); + memcpy (note, &input_text[input_text_offset], len); + note[len] = 0; + input_text_offset = loc; + } + + /* Must write the macro-expanded argument to the macro expansion + output stream. This is like the case in index_add_arg. */ + if (macro_expansion_output_stream && !executing_string) + { + /* Calling me_execute_string on a lone } provokes an error, since + as far as the reader knows there is no matching {. We wrote + the { above in the call to append_to_expansion_output. */ + me_execute_string_keep_state (note, "}"); + } + + if (!current_node || !*current_node) + { + line_error (_("Footnote defined without parent node")); + free (marker); + free (note); + return; + } + + /* output_pending_notes is non-reentrant (it uses a global data + structure pending_notes, which it frees before it returns), and + TeX doesn't grok footnotes inside footnotes anyway. Disallow + that. */ + if (already_outputting_pending_notes) + { + line_error (_("Footnotes inside footnotes are not allowed")); + free (marker); + free (note); + return; + } + + if (!*marker) + { + free (marker); + + if (number_footnotes) + { + marker = xmalloc (10); + sprintf (marker, "%d", current_footnote_number); + } + else + marker = xstrdup ("*"); + } + + if (xml) + xml_insert_footnote (note); + else + { + remember_note (marker, note); + + /* fixme: html: footnote processing needs work; we currently ignore + the style requested; we could clash with a node name of the form + `fn-<n>', though that's unlikely. */ + if (html) + { + /* Hyperlink also serves as an anchor (mnemonic: fnd is footnote + definition.) */ + add_html_elt ("<a rel=\"footnote\" href="); + add_word_args ("\"#fn-%d\" name=\"fnd-%d\"><sup>%s</sup></a>", + current_footnote_number, current_footnote_number, + marker); + } + else + /* Your method should at least insert MARKER. */ + switch (footnote_style) + { + case separate_node: + add_word_args ("(%s)", marker); + execute_string (" (*note %s-Footnote-%d::)", + current_node, current_footnote_number); + if (first_footnote_this_node) + { + char *temp_string, *expanded_ref; + + temp_string = xmalloc (strlen (current_node) + + strlen ("-Footnotes") + 1); + + strcpy (temp_string, current_node); + strcat (temp_string, "-Footnotes"); + expanded_ref = expansion (temp_string, 0); + remember_node_reference (expanded_ref, line_number, + followed_reference); + free (temp_string); + free (expanded_ref); + first_footnote_this_node = 0; + } + break; + + case end_node: + add_word_args ("(%s)", marker); + break; + + default: + break; + } + current_footnote_number++; + } + free (marker); + free (note); +} + +/* Output the footnotes. We are at the end of the current node. */ +void +output_pending_notes (void) +{ + FN *footnote = pending_notes; + + if (!pending_notes) + return; + + if (html) + { + add_html_block_elt ("<div class=\"footnote\">\n<hr>\n"); + /* We add an anchor here so @printindex can refer to this point + (as the node name) for entries defined in footnotes. */ + if (!splitting) + add_word ("<a name=\"texinfo-footnotes-in-document\"></a>"); + add_word_args ("<h4>%s</h4>", (char *) _("Footnotes")); + } + else + switch (footnote_style) + { + case separate_node: + { + char *old_current_node = current_node; + char *old_command = xstrdup (command); + + already_outputting_pending_notes++; + execute_string ("%cnode %s-Footnotes,,,%s\n", + COMMAND_PREFIX, current_node, current_node); + already_outputting_pending_notes--; + current_node = old_current_node; + free (command); + command = old_command; + } + break; + + case end_node: + close_paragraph (); + in_fixed_width_font++; + /* This string should be translated according to the + @documentlanguage, not the current LANG. We can't do that + yet, so leave it in English. */ + execute_string ("---------- Footnotes ----------\n\n"); + in_fixed_width_font--; + break; + } + + /* Handle the footnotes in reverse order. */ + { + int save_in_fixed_width_font = in_fixed_width_font; + FN **array = xmalloc ((footnote_count + 1) * sizeof (FN *)); + array[footnote_count] = NULL; + + while (--footnote_count > -1) + { + array[footnote_count] = footnote; + footnote = footnote->next; + } + + filling_enabled = 1; + indented_fill = 1; + in_fixed_width_font = 0; + + while ((footnote = array[++footnote_count])) + { + if (html) + { + /* Make the text of every footnote begin a separate paragraph. */ + add_html_block_elt ("<p class=\"footnote\"><small>"); + /* Make footnote number a link to its definition. */ + add_word_args ("[<a name=\"fn-%d\" href=\"#fnd-%d\">%d</a>]", + footnote->number, footnote->number, footnote->number); + add_word ("</small> "); + already_outputting_pending_notes++; + execute_string ("%s", footnote->note); + already_outputting_pending_notes--; + add_word ("</p>\n"); + } + else + { + char *old_current_node = current_node; + char *old_command = xstrdup (command); + + already_outputting_pending_notes++; + execute_string ("%canchor{%s-Footnote-%d}(%s) %s", + COMMAND_PREFIX, current_node, footnote->number, + footnote->marker, footnote->note); + already_outputting_pending_notes--; + current_node = old_current_node; + free (command); + command = old_command; + } + + close_paragraph (); + } + + if (html) + add_word ("<hr></div>"); + close_paragraph (); + free (array); + + in_fixed_width_font = save_in_fixed_width_font; + } + + free_pending_notes (); +} |