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; }
/* 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); }
/* 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; }