2003-05-02 00:48:41 +00:00
|
|
|
|
/* sectioning.c -- for @chapter, @section, ..., @contents ...
|
2003-06-18 12:57:43 +00:00
|
|
|
|
$Id: sectioning.c,v 1.10 2003/05/13 16:37:54 karl Exp $
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
2003-06-18 12:57:43 +00:00
|
|
|
|
Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
Originally written by Karl Heinz Marbaise <kama@hippo.fido.de>. */
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
|
|
|
|
#include "system.h"
|
|
|
|
|
#include "cmds.h"
|
|
|
|
|
#include "macro.h"
|
|
|
|
|
#include "makeinfo.h"
|
|
|
|
|
#include "node.h"
|
|
|
|
|
#include "toc.h"
|
|
|
|
|
#include "sectioning.h"
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#include "xml.h"
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
|
|
|
|
/* See comment in sectioning.h. */
|
|
|
|
|
section_alist_type section_alist[] = {
|
|
|
|
|
{ "unnumberedsubsubsec", 5, ENUM_SECT_NO, TOC_YES },
|
|
|
|
|
{ "unnumberedsubsec", 4, ENUM_SECT_NO, TOC_YES },
|
|
|
|
|
{ "unnumberedsec", 3, ENUM_SECT_NO, TOC_YES },
|
|
|
|
|
{ "unnumbered", 2, ENUM_SECT_NO, TOC_YES },
|
|
|
|
|
|
|
|
|
|
{ "appendixsubsubsec", 5, ENUM_SECT_APP, TOC_YES }, /* numbered like A.X.X.X */
|
|
|
|
|
{ "appendixsubsec", 4, ENUM_SECT_APP, TOC_YES },
|
|
|
|
|
{ "appendixsec", 3, ENUM_SECT_APP, TOC_YES },
|
|
|
|
|
{ "appendixsection", 3, ENUM_SECT_APP, TOC_YES },
|
|
|
|
|
{ "appendix", 2, ENUM_SECT_APP, TOC_YES },
|
|
|
|
|
|
|
|
|
|
{ "subsubsec", 5, ENUM_SECT_YES, TOC_YES },
|
|
|
|
|
{ "subsubsection", 5, ENUM_SECT_YES, TOC_YES },
|
|
|
|
|
{ "subsection", 4, ENUM_SECT_YES, TOC_YES },
|
|
|
|
|
{ "section", 3, ENUM_SECT_YES, TOC_YES },
|
|
|
|
|
{ "chapter", 2, ENUM_SECT_YES, TOC_YES },
|
|
|
|
|
|
|
|
|
|
{ "subsubheading", 5, ENUM_SECT_NO, TOC_NO },
|
|
|
|
|
{ "subheading", 4, ENUM_SECT_NO, TOC_NO },
|
|
|
|
|
{ "heading", 3, ENUM_SECT_NO, TOC_NO },
|
|
|
|
|
{ "chapheading", 2, ENUM_SECT_NO, TOC_NO },
|
|
|
|
|
{ "majorheading", 2, ENUM_SECT_NO, TOC_NO },
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
{ "top", 1, ENUM_SECT_NO, TOC_YES },
|
|
|
|
|
{ NULL, 0, 0, 0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* The argument of @settitle, used for HTML. */
|
|
|
|
|
char *title = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define APPENDIX_MAGIC 1024
|
|
|
|
|
#define UNNUMBERED_MAGIC 2048
|
|
|
|
|
|
|
|
|
|
/* Number memory for every level @chapter, @section,
|
|
|
|
|
@subsection, @subsubsection. */
|
|
|
|
|
static int numbers [] = { 0, 0, 0, 0 };
|
|
|
|
|
|
|
|
|
|
/* enum_marker == APPENDIX_MAGIC then we are counting appendencies
|
|
|
|
|
enum_marker == UNNUMBERED_MAGIC then we are within unnumbered area.
|
|
|
|
|
Handling situations like this:
|
|
|
|
|
@unnumbered ..
|
|
|
|
|
@section ... */
|
|
|
|
|
static int enum_marker = 0;
|
|
|
|
|
|
|
|
|
|
/* Organized by level commands. That is, "*" == chapter, "=" == section. */
|
|
|
|
|
static char *scoring_characters = "*=-.";
|
|
|
|
|
|
|
|
|
|
/* Amount to offset the name of sectioning commands to levels by. */
|
|
|
|
|
static int section_alist_offset = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* num == ENUM_SECT_NO means unnumbered (should never call this)
|
|
|
|
|
num == ENUM_SECT_YES means numbered
|
|
|
|
|
num == ENUM_SECT_APP means numbered like A.1 and so on */
|
|
|
|
|
char *
|
|
|
|
|
get_sectioning_number (level, num)
|
|
|
|
|
int level;
|
|
|
|
|
int num;
|
|
|
|
|
{
|
|
|
|
|
static char s[100]; /* should ever be enough for 99.99.99.99
|
|
|
|
|
Appendix A.1 */
|
|
|
|
|
|
|
|
|
|
char *p;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
s[0] = 0;
|
|
|
|
|
|
|
|
|
|
/* create enumeration in front of chapter, section, subsection and so on. */
|
|
|
|
|
for (i = 0; i < level; i++)
|
|
|
|
|
{
|
|
|
|
|
p = s + strlen (s);
|
|
|
|
|
if ((i == 0) && (enum_marker == APPENDIX_MAGIC))
|
2003-05-02 00:48:41 +00:00
|
|
|
|
sprintf (p, "%c.", numbers[i] + 64); /* Should be changed to
|
2000-01-17 10:39:58 +00:00
|
|
|
|
be more portable */
|
|
|
|
|
else
|
2003-05-02 00:48:41 +00:00
|
|
|
|
sprintf (p, "%d.", numbers[i]);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* the last number is never followed by a dot */
|
|
|
|
|
p = s + strlen (s);
|
|
|
|
|
if ((num == ENUM_SECT_APP)
|
|
|
|
|
&& (i == 0)
|
|
|
|
|
&& (enum_marker == APPENDIX_MAGIC))
|
|
|
|
|
sprintf (p, _("Appendix %c "), numbers[i] + 64);
|
|
|
|
|
else
|
|
|
|
|
sprintf (p, "%d ", numbers[i]);
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the level of @top to LEVEL. Return the old level of @top. */
|
|
|
|
|
int
|
|
|
|
|
set_top_section_level (level)
|
|
|
|
|
int level;
|
|
|
|
|
{
|
|
|
|
|
int i, result = -1;
|
|
|
|
|
|
|
|
|
|
for (i = 0; section_alist[i].name; i++)
|
|
|
|
|
if (strcmp (section_alist[i].name, "top") == 0)
|
|
|
|
|
{
|
|
|
|
|
result = section_alist[i].level;
|
|
|
|
|
section_alist[i].level = level;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* return the index of the given sectioning command in section_alist */
|
|
|
|
|
int
|
|
|
|
|
search_sectioning (text)
|
|
|
|
|
char *text;
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
char *t;
|
|
|
|
|
|
|
|
|
|
/* ignore the optional command prefix */
|
|
|
|
|
if (text[0] == COMMAND_PREFIX)
|
|
|
|
|
text++;
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
for (i = 0; (t = section_alist[i].name); i++)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (t, text) == 0)
|
|
|
|
|
{
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* Return an integer which identifies the type section present in TEXT. */
|
|
|
|
|
int
|
|
|
|
|
what_section (text)
|
|
|
|
|
char *text;
|
|
|
|
|
{
|
|
|
|
|
int index, j;
|
|
|
|
|
char *temp;
|
|
|
|
|
int return_val;
|
|
|
|
|
|
|
|
|
|
find_section_command:
|
|
|
|
|
for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
|
|
|
|
|
if (text[j] != COMMAND_PREFIX)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
text = text + j + 1;
|
|
|
|
|
|
|
|
|
|
/* We skip @c, @comment, and @?index commands. */
|
|
|
|
|
if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
|
|
|
|
|
(text[0] == 'c' && cr_or_whitespace (text[1])) ||
|
|
|
|
|
(strcmp (text + 1, "index") == 0))
|
|
|
|
|
{
|
|
|
|
|
while (*text++ != '\n');
|
|
|
|
|
goto find_section_command;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handle italicized sectioning commands. */
|
|
|
|
|
if (*text == 'i')
|
|
|
|
|
text++;
|
|
|
|
|
|
|
|
|
|
for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
|
|
|
|
|
|
|
|
|
|
temp = xmalloc (1 + j);
|
|
|
|
|
strncpy (temp, text, j);
|
|
|
|
|
temp[j] = 0;
|
|
|
|
|
|
|
|
|
|
index = search_sectioning (temp);
|
|
|
|
|
free (temp);
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
{
|
|
|
|
|
return_val = section_alist[index].level + section_alist_offset;
|
|
|
|
|
if (return_val < 0)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
return_val = 0;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
else if (return_val > 5)
|
|
|
|
|
return_val = 5;
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sectioning_underscore (cmd)
|
|
|
|
|
char *cmd;
|
|
|
|
|
{
|
2003-06-18 12:57:43 +00:00
|
|
|
|
/* If we're not indenting the first paragraph, we shall make it behave
|
|
|
|
|
like @noindent is called directly after the section heading. */
|
|
|
|
|
if (! do_first_par_indent)
|
|
|
|
|
cm_noindent ();
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (xml)
|
|
|
|
|
{
|
|
|
|
|
char *temp;
|
|
|
|
|
int level;
|
|
|
|
|
temp = xmalloc (2 + strlen (cmd));
|
|
|
|
|
temp[0] = COMMAND_PREFIX;
|
|
|
|
|
strcpy (&temp[1], cmd);
|
|
|
|
|
level = what_section (temp);
|
|
|
|
|
level -= 2;
|
|
|
|
|
free (temp);
|
|
|
|
|
xml_close_sections (level);
|
|
|
|
|
/* Mark the beginning of the section
|
2003-05-02 00:48:41 +00:00
|
|
|
|
If the next command is printindex, we will remove
|
|
|
|
|
the section and put an Index instead */
|
2002-03-25 13:08:32 +00:00
|
|
|
|
flush_output ();
|
|
|
|
|
xml_last_section_output_position = output_paragraph_offset;
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
xml_insert_element (xml_element (cmd), START);
|
|
|
|
|
xml_insert_element (TITLE, START);
|
|
|
|
|
xml_open_section (level, cmd);
|
|
|
|
|
get_rest_of_line (0, &temp);
|
|
|
|
|
execute_string ("%s\n", temp);
|
|
|
|
|
free (temp);
|
|
|
|
|
xml_insert_element (TITLE, END);
|
2003-06-18 12:57:43 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2002-03-25 13:08:32 +00:00
|
|
|
|
{
|
2000-01-17 10:39:58 +00:00
|
|
|
|
char character;
|
|
|
|
|
char *temp;
|
|
|
|
|
int level;
|
|
|
|
|
|
|
|
|
|
temp = xmalloc (2 + strlen (cmd));
|
|
|
|
|
temp[0] = COMMAND_PREFIX;
|
|
|
|
|
strcpy (&temp[1], cmd);
|
|
|
|
|
level = what_section (temp);
|
|
|
|
|
free (temp);
|
|
|
|
|
level -= 2;
|
|
|
|
|
|
|
|
|
|
if (level < 0)
|
|
|
|
|
level = 0;
|
|
|
|
|
|
|
|
|
|
if (html)
|
|
|
|
|
sectioning_html (level, cmd);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
character = scoring_characters[level];
|
|
|
|
|
insert_and_underscore (level, character, cmd);
|
2003-05-02 00:48:41 +00:00
|
|
|
|
}
|
2000-01-17 10:39:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* insert_and_underscore and sectioning_html are the
|
|
|
|
|
only functions which call this.
|
|
|
|
|
I have created this, because it was exactly the same
|
|
|
|
|
code in both functions. */
|
|
|
|
|
static char *
|
|
|
|
|
handle_enum_increment (level, index)
|
|
|
|
|
int level;
|
|
|
|
|
int index;
|
|
|
|
|
{
|
|
|
|
|
/* special for unnumbered */
|
|
|
|
|
if (number_sections && section_alist[index].num == ENUM_SECT_NO)
|
|
|
|
|
{
|
|
|
|
|
if (level == 0
|
2003-05-02 00:48:41 +00:00
|
|
|
|
&& enum_marker != UNNUMBERED_MAGIC)
|
|
|
|
|
enum_marker = UNNUMBERED_MAGIC;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
}
|
|
|
|
|
/* enumerate only things which are allowed */
|
|
|
|
|
if (number_sections && section_alist[index].num)
|
|
|
|
|
{
|
|
|
|
|
/* reset the marker if we get into enumerated areas */
|
|
|
|
|
if (section_alist[index].num == ENUM_SECT_YES
|
2003-05-02 00:48:41 +00:00
|
|
|
|
&& level == 0
|
|
|
|
|
&& enum_marker == UNNUMBERED_MAGIC)
|
|
|
|
|
enum_marker = 0;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* This is special for appendix; if we got the first
|
|
|
|
|
time an appendix command then we are entering appendix.
|
|
|
|
|
Thats the point we have to start countint with A, B and so on. */
|
|
|
|
|
if (section_alist[index].num == ENUM_SECT_APP
|
2003-05-02 00:48:41 +00:00
|
|
|
|
&& level == 0
|
|
|
|
|
&& enum_marker != APPENDIX_MAGIC)
|
|
|
|
|
{
|
|
|
|
|
enum_marker = APPENDIX_MAGIC;
|
|
|
|
|
numbers [0] = 0; /* this means we start with Appendix A */
|
|
|
|
|
}
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* only increment counters if we are not in unnumbered
|
|
|
|
|
area. This handles situations like this:
|
|
|
|
|
@unnumbered .... This sets enum_marker to UNNUMBERED_MAGIC
|
|
|
|
|
@section .... */
|
|
|
|
|
if (enum_marker != UNNUMBERED_MAGIC)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
/* reset all counters which are one level deeper */
|
|
|
|
|
for (i = level; i < 3; i++)
|
|
|
|
|
numbers [i + 1] = 0;
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
numbers[level]++;
|
|
|
|
|
return xstrdup
|
|
|
|
|
(get_sectioning_number (level, section_alist[index].num));
|
|
|
|
|
}
|
2000-01-17 10:39:58 +00:00
|
|
|
|
} /* if (number_sections)... */
|
|
|
|
|
|
|
|
|
|
return xstrdup ("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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 (level, with_char, cmd)
|
|
|
|
|
int level;
|
|
|
|
|
int with_char;
|
|
|
|
|
char *cmd;
|
|
|
|
|
{
|
|
|
|
|
int i, len;
|
|
|
|
|
int index;
|
|
|
|
|
int old_no_indent;
|
|
|
|
|
unsigned char *starting_pos, *ending_pos;
|
|
|
|
|
char *temp;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
starting_pos = output_paragraph + output_paragraph_offset;
|
|
|
|
|
|
|
|
|
|
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 (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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insert the text following input_text_offset up to the end of the
|
|
|
|
|
line as an HTML heading element of the appropriate `level' and
|
|
|
|
|
tagged as an anchor for the current node.. */
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
void
|
|
|
|
|
sectioning_html (level, cmd)
|
|
|
|
|
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;
|
|
|
|
|
|
2003-06-18 12:57:43 +00:00
|
|
|
|
/* level 0 (chapter) is <h2>, everything else is <h3>. We don't want
|
|
|
|
|
to go lower than that because browsers then start rendering the
|
|
|
|
|
headings smaller than the text. */
|
|
|
|
|
add_word_args ("<h%d class=\"%s\">", MIN (3, level + 2), cmd);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
|
|
|
|
/* If we are outside of any node, produce an anchor that
|
|
|
|
|
the TOC could refer to. */
|
|
|
|
|
if (!current_node || !*current_node)
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
static const char a_name[] = "<a name=\"";
|
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
starting_pos = output_paragraph + output_paragraph_offset;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
add_word_args ("%sTOC%d\">", a_name, toc_ref_count++);
|
|
|
|
|
toc_anchor = substring (starting_pos + sizeof (a_name) - 1,
|
2000-01-17 10:39:58 +00:00
|
|
|
|
output_paragraph + output_paragraph_offset);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* This must be added after toc_anchor is extracted, since
|
2003-05-02 00:48:41 +00:00
|
|
|
|
toc_anchor cannot include the closing </a>. For details,
|
|
|
|
|
see toc.c:toc_add_entry and toc.c:contents_update_html.
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
Also, the anchor close must be output before the section name
|
|
|
|
|
in case the name itself contains an anchor. */
|
2002-03-25 13:08:32 +00:00
|
|
|
|
add_word ("</a>");
|
2000-01-17 10:39:58 +00:00
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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. */
|
|
|
|
|
add_word (handle_enum_increment (level, index));
|
|
|
|
|
|
|
|
|
|
/* 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);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
free (temp);
|
|
|
|
|
|
|
|
|
|
if (outstanding_node)
|
|
|
|
|
outstanding_node = 0;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
add_word_args ("</h%d>", level + 2);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
close_paragraph();
|
|
|
|
|
filling_enabled = 1;
|
|
|
|
|
no_indent = old_no_indent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Shift the meaning of @section to @chapter. */
|
|
|
|
|
void
|
|
|
|
|
cm_raisesections ()
|
|
|
|
|
{
|
|
|
|
|
discard_until ("\n");
|
|
|
|
|
section_alist_offset--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Shift the meaning of @chapter to @section. */
|
|
|
|
|
void
|
|
|
|
|
cm_lowersections ()
|
|
|
|
|
{
|
|
|
|
|
discard_until ("\n");
|
|
|
|
|
section_alist_offset++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The command still works, but prints a warning message in addition. */
|
|
|
|
|
void
|
|
|
|
|
cm_ideprecated (arg, start, end)
|
|
|
|
|
int arg, start, end;
|
|
|
|
|
{
|
|
|
|
|
warning (_("%c%s is obsolete; use %c%s instead"),
|
|
|
|
|
COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
|
|
|
|
|
sectioning_underscore (command + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Treat this just like @unnumbered. The only difference is
|
|
|
|
|
in node defaulting. */
|
|
|
|
|
void
|
|
|
|
|
cm_top ()
|
|
|
|
|
{
|
|
|
|
|
/* It is an error to have more than one @top. */
|
|
|
|
|
if (top_node_seen && strcmp (current_node, "Top") != 0)
|
|
|
|
|
{
|
|
|
|
|
TAG_ENTRY *tag = tag_table;
|
|
|
|
|
|
|
|
|
|
line_error (_("Node with %ctop as a section already exists"),
|
|
|
|
|
COMMAND_PREFIX);
|
|
|
|
|
|
|
|
|
|
while (tag)
|
|
|
|
|
{
|
|
|
|
|
if (tag->flags & TAG_FLAG_IS_TOP)
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
file_line_error (tag->filename, tag->line_no,
|
2003-05-02 00:48:41 +00:00
|
|
|
|
_("Here is the %ctop node"), COMMAND_PREFIX);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
tag = tag->next_ent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
top_node_seen = 1;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* It is an error to use @top before using @node. */
|
2000-01-17 10:39:58 +00:00
|
|
|
|
if (!tag_table)
|
|
|
|
|
{
|
|
|
|
|
char *top_name;
|
|
|
|
|
|
|
|
|
|
get_rest_of_line (0, &top_name);
|
|
|
|
|
line_error (_("%ctop used before %cnode, defaulting to %s"),
|
|
|
|
|
COMMAND_PREFIX, COMMAND_PREFIX, top_name);
|
|
|
|
|
execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
|
|
|
|
|
free (top_name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cm_unnumbered ();
|
|
|
|
|
|
|
|
|
|
/* The most recently defined node is the top node. */
|
|
|
|
|
tag_table->flags |= TAG_FLAG_IS_TOP;
|
|
|
|
|
|
|
|
|
|
/* Now set the logical hierarchical level of the Top node. */
|
|
|
|
|
{
|
|
|
|
|
int orig_offset = input_text_offset;
|
|
|
|
|
|
|
|
|
|
input_text_offset = search_forward (node_search_string, orig_offset);
|
|
|
|
|
|
|
|
|
|
if (input_text_offset > 0)
|
|
|
|
|
{
|
|
|
|
|
int this_section;
|
|
|
|
|
|
|
|
|
|
/* We have encountered a non-top node, so mark that one exists. */
|
|
|
|
|
non_top_node_seen = 1;
|
|
|
|
|
|
|
|
|
|
/* Move to the end of this line, and find out what the
|
|
|
|
|
sectioning command is here. */
|
|
|
|
|
while (input_text[input_text_offset] != '\n')
|
|
|
|
|
input_text_offset++;
|
|
|
|
|
|
|
|
|
|
if (input_text_offset < input_text_length)
|
|
|
|
|
input_text_offset++;
|
|
|
|
|
|
|
|
|
|
this_section = what_section (input_text + input_text_offset);
|
|
|
|
|
|
|
|
|
|
/* If we found a sectioning command, then give the top section
|
|
|
|
|
a level of this section - 1. */
|
|
|
|
|
if (this_section != -1)
|
|
|
|
|
set_top_section_level (this_section - 1);
|
|
|
|
|
}
|
|
|
|
|
input_text_offset = orig_offset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is a chapter heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_chapter ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("chapter");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is a section heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_section ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("section");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is a subsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_subsection ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("subsection");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is a subsubsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_subsubsection ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("subsubsection");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an unnumbered heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_unnumbered ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("unnumbered");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an unnumbered section heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_unnumberedsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("unnumberedsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an unnumbered
|
|
|
|
|
subsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_unnumberedsubsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("unnumberedsubsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an unnumbered
|
|
|
|
|
subsubsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_unnumberedsubsubsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("unnumberedsubsubsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an appendix heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_appendix ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("appendix");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an appendix section heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_appendixsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("appendixsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an appendix subsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_appendixsubsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("appendixsubsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The remainder of the text on this line is an appendix
|
|
|
|
|
subsubsection heading. */
|
|
|
|
|
void
|
|
|
|
|
cm_appendixsubsubsec ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("appendixsubsubsec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Compatibility functions substitute for chapter, section, etc. */
|
|
|
|
|
void
|
|
|
|
|
cm_majorheading ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("majorheading");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cm_chapheading ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("chapheading");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cm_heading ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("heading");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cm_subheading ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("subheading");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cm_subsubheading ()
|
|
|
|
|
{
|
|
|
|
|
sectioning_underscore ("subsubheading");
|
|
|
|
|
}
|