/* shortcontents in HTML; Should this produce a standalone file? */ static void shortcontents_update_html (char *contents_filename) { int i; char *toc_file = NULL; /* does exist any toc? */ if (!toc_counter) return; add_html_block_elt_args ("\n<div class=\"shortcontents\">\n<h2>%s</h2>\n<ul>\n", gdt("Short Contents")); if (contents_filename) toc_file = filename_part (contents_filename); for (i = 0; i < toc_counter; i++) { char *name = toc_entry_alist[i]->name; if (toc_entry_alist[i]->level == 0) { if (contents_filename) add_word_args ("<li><a href=\"%s#toc_%s</a></li>\n", splitting ? toc_file : "", name); else add_word_args ("<a href=\"%s#%s</a>\n", splitting ? toc_entry_alist[i]->html_file : "", name); } } add_word ("</ul>\n</div>\n\n"); if (contents_filename) free (toc_file); }
static void contents_update_html (void) { int i; int k; int last_level; /* does exist any toc? */ if (!toc_counter) /* no, so return to sender ;-) */ return; add_html_block_elt_args ("\n<div class=\"contents\">\n<h2>%s</h2>\n<ul>\n", gdt("Table of Contents")); last_level = toc_entry_alist[0]->level; for (i = 0; i < toc_counter; i++) { if (toc_entry_alist[i]->level > last_level) { /* unusual, but it is possible @chapter ... @subsubsection ... ? */ for (k = 0; k < (toc_entry_alist[i]->level-last_level); k++) add_html_block_elt ("<ul>\n"); } else if (toc_entry_alist[i]->level < last_level) { /* @subsubsection ... @chapter ... this IS usual.*/ for (k = 0; k < (last_level-toc_entry_alist[i]->level); k++) add_word ("</li></ul>\n"); } /* No double entries in TOC. */ if (!(i && strcmp (toc_entry_alist[i]->name, toc_entry_alist[i-1]->name) == 0)) { /* each toc entry is a list item. */ add_word ("<li>"); /* Insert link -- to an external file if splitting, or within the current document if not splitting. */ add_word ("<a "); /* For chapters (only), insert an anchor that the short contents will link to. */ if (toc_entry_alist[i]->level == 0) { char *p = toc_entry_alist[i]->name; /* toc_entry_alist[i]->name has the form `foo">bar', that is, it includes both the node name and anchor text. We need to find where `foo', the node name, ends, and use that in toc_FOO. */ while (*p && *p != '"') p++; add_word_args ("name=\"toc_%.*s\" ", p - toc_entry_alist[i]->name, toc_entry_alist[i]->name); /* save the link if necessary */ if (internal_links_stream) { fprintf (internal_links_stream, "%s#toc_%.*s\ttoc\t%s\n", splitting ? toc_entry_alist[i]->html_file : "", p - toc_entry_alist[i]->name, toc_entry_alist[i]->name, p + 2); } } add_word_args ("href=\"%s#%s</a>\n", splitting ? toc_entry_alist[i]->html_file : "", toc_entry_alist[i]->name); } last_level = toc_entry_alist[i]->level; } /* Go back to start level. */ if (toc_entry_alist[0]->level < last_level) for (k = 0; k < (last_level-toc_entry_alist[0]->level); k++) add_word ("</li></ul>\n"); add_word ("</li></ul>\n</div>\n\n"); }
/* 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_html_block_elt ("<hr></div>"); close_paragraph (); free (array); in_fixed_width_font = save_in_fixed_width_font; } free_pending_notes (); }
/* 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); }
/* Make a cross reference. */ void cm_xref (int arg) { if (arg == START) { char *arg1 = get_xref_token (1); /* expands all macros in xref */ char *arg2 = get_xref_token (0); char *arg3 = get_xref_token (0); char *arg4 = get_xref_token (0); char *arg5 = get_xref_token (0); char *tem; /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The first argument must never be blank." --rms. We hereby comply by disallowing such constructs. */ if (!*arg1) line_error (_("First argument to cross-reference may not be empty")); if (docbook) { if (!ref_flag) add_word (px_ref_flag || printing_index ? (char *) _("see ") : (char *) _("See ")); if (!*arg4 && !*arg5) { char *arg1_id = xml_id (arg1); if (*arg2 || *arg3) { xml_insert_element_with_attribute (XREFNODENAME, START, "linkend=\"%s\"", arg1_id); free (arg1_id); execute_string ("%s", *arg3 ? arg3 : arg2); xml_insert_element (XREFNODENAME, END); } else { xml_insert_element_with_attribute (XREF, START, "linkend=\"%s\"", arg1_id); xml_insert_element (XREF, END); free (arg1_id); } } else if (*arg5) { add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1); xml_insert_element (CITE, START); add_word (arg5); xml_insert_element (CITE, END); } else if (*arg4) { /* Very sad, we are losing xrefs made to ``info only'' books. */ } } else if (xml) { if (!ref_flag) add_word_args ("%s", px_ref_flag ? _("see ") : _("See ")); xml_insert_element (XREF, START); xml_insert_element (XREFNODENAME, START); execute_string ("%s", arg1); xml_insert_element (XREFNODENAME, END); if (*arg2) { xml_insert_element (XREFINFONAME, START); execute_string ("%s", arg2); xml_insert_element (XREFINFONAME, END); } if (*arg3) { xml_insert_element (XREFPRINTEDDESC, START); execute_string ("%s", arg3); xml_insert_element (XREFPRINTEDDESC, END); } if (*arg4) { xml_insert_element (XREFINFOFILE, START); execute_string ("%s", arg4); xml_insert_element (XREFINFOFILE, END); } if (*arg5) { xml_insert_element (XREFPRINTEDNAME, START); execute_string ("%s", arg5); xml_insert_element (XREFPRINTEDNAME, END); } xml_insert_element (XREF, END); } else if (html) { if (!ref_flag) add_word_args ("%s", px_ref_flag ? _("see ") : _("See ")); } else add_word_args ("%s", px_ref_flag ? "*note " : "*Note "); if (!xml) { if (*arg5 || *arg4) { /* arg1 - node name arg2 - reference name arg3 - title or topic (and reference name if arg2 is NULL) arg4 - info file name arg5 - printed manual title */ char *ref_name; if (!*arg2) { if (*arg3) ref_name = arg3; else ref_name = arg1; } else ref_name = arg2; if (html) { /* More to do eventually, down to Unicode Normalization Form C. See the HTML Xref nodes in the manual. */ char *file_arg = arg4; add_html_elt ("<a href="); { /* If there's a directory part, ignore it. */ char *p = strrchr (file_arg, '/'); if (p) file_arg = p + 1; /* If there's a dot, make it a NULL terminator, so the extension does not get into the way. */ p = strrchr (file_arg , '.'); if (p != NULL) *p = 0; } if (! *file_arg) warning (_("Empty file name for HTML cross reference in `%s'"), arg4); /* Note that if we are splitting, and the referenced tag is an anchor rather than a node, we will produce a reference to a file whose name is derived from the anchor name. However, only nodes create files, so we are referencing a non-existent file. cm_anchor, which see, deals with that problem. */ if (splitting) execute_string ("\"../%s/", file_arg); else execute_string ("\"%s.html", file_arg); /* Do not collapse -- to -, etc., in references. */ in_fixed_width_font++; tem = expansion (arg1, 0); /* expand @-commands in node */ in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); execute_string ("%s",ref_name); add_word ("</a>"); } else { execute_string ("%s:", ref_name); in_fixed_width_font++; execute_string (" (%s)%s", arg4, arg1); add_xref_punctuation (); in_fixed_width_font--; } /* Free all of the arguments found. */ if (arg1) free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); if (arg4) free (arg4); if (arg5) free (arg5); return; } else remember_node_reference (arg1, line_number, followed_reference); if (*arg3) { if (html) { add_html_elt ("<a href=\""); in_fixed_width_font++; tem = expansion (arg1, 0); in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); execute_string ("%s", *arg2 ? arg2 : arg3); add_word ("</a>"); } else { execute_string ("%s:", *arg2 ? arg2 : arg3); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } } else { if (html) { add_html_elt ("<a href=\""); in_fixed_width_font++; tem = expansion (arg1, 0); in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); if (*arg2) execute_string ("%s", arg2); else { char *fref = get_float_ref (arg1); execute_string ("%s", fref ? fref : arg1); free (fref); } add_word ("</a>"); } else { if (*arg2) { execute_string ("%s:", arg2); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } else { char *fref = get_float_ref (arg1); if (fref) { /* Reference is being made to a float. */ execute_string ("%s:", fref); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } else { in_fixed_width_font++; execute_string ("%s::", arg1); in_fixed_width_font--; } } } } } /* Free all of the arguments found. */ if (arg1) free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); if (arg4) free (arg4); if (arg5) free (arg5); } else { /* Check that the next non-whitespace character is valid to follow an xref (so Info readers can find the node names). `input_text_offset' is pointing at the "}" which ended the xref command. This is not used for @pxref or @ref, since we insert the necessary punctuation above, if needed. */ int temp = next_nonwhitespace_character (); if (temp == -1) warning (_("End of file reached while looking for `.' or `,'")); else if (temp != '.' && temp != ',') warning (_("`.' or `,' must follow @%s, not `%c'"), command, temp); } }
void sectioning_html (int level, char *cmd) { static int toc_ref_count = 0; int index; int old_no_indent; unsigned char *starting_pos, *ending_pos; char *temp, *toc_anchor = NULL; close_paragraph (); filling_enabled = indented_fill = 0; old_no_indent = no_indent; no_indent = 1; /* level 0 (chapter) is <h2>, and we go down from there. */ add_html_block_elt_args ("<h%d class=\"%s\">", level + 2, cmd); /* If we are outside of any node, produce an anchor that the TOC could refer to. */ if (!current_node || !*current_node) { static const char a_name[] = "<a name=\""; starting_pos = output_paragraph + output_paragraph_offset; add_word_args ("%sTOC%d\">", a_name, toc_ref_count++); toc_anchor = substring (starting_pos + sizeof (a_name) - 1, output_paragraph + output_paragraph_offset); /* This must be added after toc_anchor is extracted, since toc_anchor cannot include the closing </a>. For details, see toc.c:toc_add_entry and toc.c:contents_update_html. Also, the anchor close must be output before the section name in case the name itself contains an anchor. */ add_word ("</a>"); } starting_pos = output_paragraph + output_paragraph_offset; if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); get_rest_of_line (0, &temp); /* Use @settitle value if @top parameter is empty. */ if (STREQ (command, "top") && strlen(temp) == 0) temp = xstrdup (title ? title : ""); index = search_sectioning (cmd); if (index < 0) { /* should never happen, but a poor guy, named Murphy ... */ warning (_("Internal error (search_sectioning) \"%s\"!"), cmd); return; } /* Produce "X.Y" and add it to HTML output. */ { char *title_number = handle_enum_increment (level, index); if (strlen (title_number) > 0) add_word_args ("%s ", title_number); } /* add the section name to both HTML and macro-expanded output. */ if (macro_expansion_output_stream && !executing_string) { remember_itext (input_text, input_text_offset); me_execute_string (temp); write_region_to_macro_output ("\n", 0, 1); } else execute_string ("%s", temp); ending_pos = output_paragraph + output_paragraph_offset; /* Pluck ``X.Y SECTION-NAME'' from the output buffer and insert it into the TOC. */ if (section_alist[index].toc == TOC_YES) toc_add_entry (substring (starting_pos, ending_pos), level, current_node, toc_anchor); free (temp); if (outstanding_node) outstanding_node = 0; add_word_args ("</h%d>", level + 2); close_paragraph(); filling_enabled = 1; no_indent = old_no_indent; }
/* Insert the text following input_text_offset up to the end of the line in a new, separate paragraph. Directly underneath it, insert a line of WITH_CHAR, the same length of the inserted text. */ void insert_and_underscore (int level, char *cmd) { int i, len; int index; int old_no_indent; unsigned char *starting_pos, *ending_pos; char *temp; char with_char = scoring_characters[level]; close_paragraph (); filling_enabled = indented_fill = 0; old_no_indent = no_indent; no_indent = 1; if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); get_rest_of_line (0, &temp); /* Use @settitle value if @top parameter is empty. */ if (STREQ (command, "top") && strlen(temp) == 0) temp = xstrdup (title ? title : ""); starting_pos = output_paragraph + output_paragraph_offset; /* Poor man's cache for section title. */ if (strlen (last_sectioning_title)) free (last_sectioning_title); last_sectioning_title = xstrdup (temp); index = search_sectioning (cmd); if (index < 0) { /* should never happen, but a poor guy, named Murphy ... */ warning (_("Internal error (search_sectioning) `%s'!"), cmd); return; } /* This is a bit tricky: we must produce "X.Y SECTION-NAME" in the Info output and in TOC, but only SECTION-NAME in the macro-expanded output. */ /* Step 1: produce "X.Y" and add it to Info output. */ add_word_args ("%s ", handle_enum_increment (level, index)); /* Step 2: add "SECTION-NAME" to both Info and macro-expanded output. */ if (macro_expansion_output_stream && !executing_string) { char *temp1 = xmalloc (2 + strlen (temp)); sprintf (temp1, "%s\n", temp); remember_itext (input_text, input_text_offset); me_execute_string (temp1); free (temp1); } else execute_string ("%s\n", temp); /* Step 3: pluck "X.Y SECTION-NAME" from the output buffer and insert it into the TOC. */ ending_pos = output_paragraph + output_paragraph_offset; if (section_alist[index].toc == TOC_YES) toc_add_entry (substring (starting_pos, ending_pos - 1), level, current_node, NULL); free (temp); len = (ending_pos - starting_pos) - 1; for (i = 0; i < len; i++) add_char (with_char); insert ('\n'); close_paragraph (); filling_enabled = 1; no_indent = old_no_indent; }