Home | History | Annotate | Line # | Download | only in makeinfo
      1 /*	$NetBSD: insertion.c,v 1.4 2025/12/31 22:18:50 oster Exp $	*/
      2 
      3 /* insertion.c -- insertions for Texinfo.
      4    Id: insertion.c,v 1.55 2004/11/11 18:34:28 karl Exp
      5 
      6    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
      7    Foundation, Inc.
      8 
      9    This program is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 2, or (at your option)
     12    any later version.
     13 
     14    This program is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; if not, write to the Free Software Foundation,
     21    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     22 
     23 #include "system.h"
     24 #include "cmds.h"
     25 #include "defun.h"
     26 #include "float.h"
     27 #include "html.h"
     28 #include "insertion.h"
     29 #include "macro.h"
     30 #include "makeinfo.h"
     31 #include "multi.h"
     32 #include "xml.h"
     33 
     34 /* Must match list in insertion.h.  */
     35 static char *insertion_type_names[] =
     36 {
     37   "cartouche", "copying", "defcv", "deffn", "defivar", "defmac",
     38   "defmethod", "defop", "defopt", "defspec", "deftp", "deftypecv",
     39   "deftypefn", "deftypefun", "deftypeivar", "deftypemethod",
     40   "deftypeop", "deftypevar", "deftypevr", "defun", "defvar", "defvr",
     41   "detailmenu", "direntry", "display", "documentdescription",
     42   "enumerate", "example", "float", "flushleft", "flushright", "format",
     43   "ftable", "group", "ifclear", "ifdocbook", "ifhtml", "ifinfo",
     44   "ifnotdocbook", "ifnothtml", "ifnotinfo", "ifnotplaintext", "ifnottex",
     45   "ifnotxml", "ifplaintext", "ifset", "iftex", "ifxml", "itemize", "lisp",
     46   "menu", "multitable", "quotation", "rawdocbook", "rawhtml", "rawtex",
     47   "rawxml", "smalldisplay", "smallexample", "smallformat", "smalllisp",
     48   "verbatim", "table", "tex", "vtable", "titlepage", "bad_type"
     49 };
     50 
     51 /* All nested environments.  */
     52 INSERTION_ELT *insertion_stack = NULL;
     53 
     54 /* How deeply we're nested.  */
     55 int insertion_level = 0;
     56 
     57 /* Set to 1 if we've processed (commentary) text in a @menu that
     58    wasn't part of a menu item.  */
     59 int had_menu_commentary;
     60 
     61 /* How to examine menu lines.  */
     62 int in_detailmenu = 0;
     63 
     64 /* Whether to examine menu lines.  */
     65 int in_menu = 0;
     66 
     67 /* Set to 1 if <p> is written in normal context.
     68    Used for menu and itemize. */
     69 int in_paragraph = 0;
     70 
     71 /* Since an insertion is already in the stack before we reach the switch
     72    statement, we cannot use is_in_insertion_of_type (always returns true.) Also
     73    making it return the level found, and comparing it with the current level is
     74    no use, due to the order of stack.  */
     75 static int float_active = 0;
     76 
     77 /* Unsetting escape_html blindly causes text inside @html/etc. to be escaped if
     78    used within a rmacro.  */
     79 static int raw_output_block = 0;
     80 
     81 /* Non-zero if a <dl> element has a <dt> element in it.  We use this when
     82    deciding whether to insert a <br> or not.  */
     83 static int html_deflist_has_term = 0;
     84 
     85 void
     87 init_insertion_stack (void)
     88 {
     89   insertion_stack = NULL;
     90 }
     91 
     92 /* Return the type of the current insertion. */
     93 static enum insertion_type
     94 current_insertion_type (void)
     95 {
     96   return insertion_level ? insertion_stack->insertion : bad_type;
     97 }
     98 
     99 /* Return the string which is the function to wrap around items, or NULL
    100    if we're not in an environment where @item is ok.  */
    101 static char *
    102 current_item_function (void)
    103 {
    104   int done = 0;
    105   INSERTION_ELT *elt = insertion_stack;
    106 
    107   /* Skip down through the stack until we find an insertion with an
    108      itemize function defined, i.e., skip conditionals, @cartouche, etc.  */
    109   while (!done && elt)
    110     {
    111       switch (elt->insertion)
    112         {
    113         /* This list should match the one in cm_item.  */
    114         case ifclear:
    115         case ifhtml:
    116         case ifinfo:
    117         case ifnothtml:
    118         case ifnotinfo:
    119         case ifnotplaintext:
    120         case ifnottex:
    121 	case ifnotxml:
    122         case ifplaintext:
    123         case ifset:
    124         case iftex:
    125 	case ifxml:
    126         case rawdocbook:
    127         case rawhtml:
    128         case rawxml:
    129         case rawtex:
    130         case tex:
    131         case cartouche:
    132           elt = elt->next;
    133           break;
    134 
    135         default:
    136           done = 1;
    137         }
    138     }
    139 
    140   /* item_function usually gets assigned the empty string.  */
    141   return done && (*elt->item_function) ? elt->item_function : NULL;
    142 }
    143 
    144 /* Parse the item marker function off the input.  If result is just "@",
    145    change it to "@ ", since "@" by itself is not a command.  This makes
    146    "@ ", "@\t", and "@\n" all the same, but their default meanings are
    147    the same anyway, and let's not worry about supporting redefining them.  */
    148 static char *
    149 get_item_function (void)
    150 {
    151   char *item_function;
    152   char *item_loc;
    153 
    154   get_rest_of_line (0, &item_function);
    155 
    156   /* If the document erroneously says
    157        @itemize @bullet @item foobar
    158      it's nicer to give an error up front than repeat `@bullet expected
    159      braces' until we get a segmentation fault.  */
    160   item_loc = strstr (item_function, "@item");
    161   if (item_loc)
    162     {
    163       line_error (_("@item not allowed in argument to @itemize"));
    164       *item_loc = 0;
    165     }
    166 
    167   /* If we hit the end of text in get_rest_of_line, backing up
    168      input pointer will cause the last character of the last line
    169      be pushed back onto the input, which is wrong.  */
    170   if (input_text_offset < input_text_length)
    171     backup_input_pointer ();
    172 
    173   if (STREQ (item_function, "@"))
    174     {
    175       free (item_function);
    176       item_function = xstrdup ("@ ");
    177     }
    178 
    179   return item_function;
    180 }
    181 
    182  /* Push the state of the current insertion on the stack. */
    183 static void
    184 push_insertion (enum insertion_type type, char *item_function)
    185 {
    186   INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT));
    187 
    188   new->item_function = item_function;
    189   new->filling_enabled = filling_enabled;
    190   new->indented_fill = indented_fill;
    191   new->insertion = type;
    192   new->line_number = line_number;
    193   new->filename = xstrdup (input_filename);
    194   new->inhibited = inhibit_paragraph_indentation;
    195   new->in_fixed_width_font = in_fixed_width_font;
    196   new->next = insertion_stack;
    197   insertion_stack = new;
    198   insertion_level++;
    199 }
    200 
    201  /* Pop the value on top of the insertion stack into the
    202     global variables. */
    203 void
    204 pop_insertion (void)
    205 {
    206   INSERTION_ELT *temp = insertion_stack;
    207 
    208   if (temp == NULL)
    209     return;
    210 
    211   in_fixed_width_font = temp->in_fixed_width_font;
    212   inhibit_paragraph_indentation = temp->inhibited;
    213   filling_enabled = temp->filling_enabled;
    214   indented_fill = temp->indented_fill;
    215   free_and_clear (&(temp->item_function));
    216   free_and_clear (&(temp->filename));
    217   insertion_stack = insertion_stack->next;
    218   free (temp);
    219   insertion_level--;
    220 }
    221 
    222  /* Return a pointer to the print name of this
    223     enumerated type. */
    224 static const char *
    225 insertion_type_pname (enum insertion_type type)
    226 {
    227   if ((int) type < (int) bad_type)
    228   {
    229     if (type == rawdocbook)
    230       return "docbook";
    231     else if (type == rawhtml)
    232       return "html";
    233     else if (type == rawxml)
    234       return "xml";
    235     else if (type == rawtex)
    236       return "tex";
    237     else
    238       return insertion_type_names[(int) type];
    239   }
    240   else
    241     return _("Broken-Type in insertion_type_pname");
    242 }
    243 
    244 /* Return the insertion_type associated with NAME.
    245    If the type is not one of the known ones, return BAD_TYPE. */
    246 enum insertion_type
    247 find_type_from_name (char *name)
    248 {
    249   int index = 0;
    250   while (index < (int) bad_type)
    251     {
    252       if (STREQ (name, insertion_type_names[index]))
    253         return (enum insertion_type) index;
    254       if (index == rawdocbook && STREQ (name, "docbook"))
    255         return rawdocbook;
    256       if (index == rawhtml && STREQ (name, "html"))
    257         return rawhtml;
    258       if (index == rawxml && STREQ (name, "xml"))
    259         return rawxml;
    260       if (index == rawtex && STREQ (name, "tex"))
    261         return rawtex;
    262       index++;
    263     }
    264   return bad_type;
    265 }
    266 
    267 /* Simple function to query insertion_stack to see if we are inside a given
    268    insertion type. */
    269 int
    270 is_in_insertion_of_type (int type)
    271 {
    272   INSERTION_ELT *temp = insertion_stack;
    273 
    274   if (!insertion_level)
    275     return 0;
    276 
    277   while (temp)
    278     {
    279       if (temp->insertion == type)
    280         return 1;
    281       temp = temp->next;
    282     }
    283 
    284   return 0;
    285 }
    286 
    287 
    288 static int
    289 defun_insertion (enum insertion_type type)
    290 {
    291   return 0
    292      || (type == defcv)
    293      || (type == deffn)
    294      || (type == defivar)
    295      || (type == defmac)
    296      || (type == defmethod)
    297      || (type == defop)
    298      || (type == defopt)
    299      || (type == defspec)
    300      || (type == deftp)
    301      || (type == deftypecv)
    302      || (type == deftypefn)
    303      || (type == deftypefun)
    304      || (type == deftypeivar)
    305      || (type == deftypemethod)
    306      || (type == deftypeop)
    307      || (type == deftypevar)
    308      || (type == deftypevr)
    309      || (type == defun)
    310      || (type == defvar)
    311      || (type == defvr)
    312   ;
    313 }
    314 
    315 /* MAX_NS is the maximum nesting level for enumerations.  I picked 100
    316    which seemed reasonable.  This doesn't control the number of items,
    317    just the number of nested lists. */
    318 #define max_stack_depth 100
    319 #define ENUM_DIGITS 1
    320 #define ENUM_ALPHA  2
    321 typedef struct {
    322   int enumtype;
    323   int enumval;
    324 } DIGIT_ALPHA;
    325 
    326 DIGIT_ALPHA enumstack[max_stack_depth];
    327 int enumstack_offset = 0;
    328 int current_enumval = 1;
    329 int current_enumtype = ENUM_DIGITS;
    330 char *enumeration_arg = NULL;
    331 
    332 static void
    333 start_enumerating (int at, int type)
    334 {
    335   if ((enumstack_offset + 1) == max_stack_depth)
    336     {
    337       line_error (_("Enumeration stack overflow"));
    338       return;
    339     }
    340   enumstack[enumstack_offset].enumtype = current_enumtype;
    341   enumstack[enumstack_offset].enumval = current_enumval;
    342   enumstack_offset++;
    343   current_enumval = at;
    344   current_enumtype = type;
    345 }
    346 
    347 static void
    348 stop_enumerating (void)
    349 {
    350   --enumstack_offset;
    351   if (enumstack_offset < 0)
    352     enumstack_offset = 0;
    353 
    354   current_enumval = enumstack[enumstack_offset].enumval;
    355   current_enumtype = enumstack[enumstack_offset].enumtype;
    356 }
    357 
    358 /* Place a letter or digits into the output stream. */
    359 static void
    360 enumerate_item (void)
    361 {
    362   char temp[10];
    363 
    364   if (current_enumtype == ENUM_ALPHA)
    365     {
    366       if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
    367         {
    368           current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
    369           warning (_("lettering overflow, restarting at %c"), current_enumval);
    370         }
    371       sprintf (temp, "%c. ", current_enumval);
    372     }
    373   else
    374     sprintf (temp, "%d. ", current_enumval);
    375 
    376   indent (output_column += (current_indent - strlen (temp)));
    377   add_word (temp);
    378   current_enumval++;
    379 }
    380 
    381 static void
    382 enum_html (void)
    383 {
    384   char type;
    385   int start;
    386 
    387   if (isdigit (*enumeration_arg))
    388     {
    389       type = '1';
    390       start = atoi (enumeration_arg);
    391     }
    392   else if (isupper (*enumeration_arg))
    393     {
    394       type = 'A';
    395       start = *enumeration_arg - 'A' + 1;
    396     }
    397   else
    398     {
    399       type = 'a';
    400       start = *enumeration_arg - 'a' + 1;
    401     }
    402 
    403   add_html_block_elt_args ("<ol type=%c start=%d>\n", type, start);
    404 }
    405 
    406 /* Conditionally parse based on the current command name. */
    408 void
    409 command_name_condition (int arg, int arg2, int arg3)
    410 {
    411   char *discarder = xmalloc (8 + strlen (command));
    412 
    413   sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
    414   discard_until (discarder);
    415   discard_until ("\n");
    416 
    417   free (discarder);
    418 }
    419 
    420 /* This is where the work for all the "insertion" style
    421    commands is done.  A huge switch statement handles the
    422    various setups, and generic code is on both sides. */
    423 void
    424 begin_insertion (enum insertion_type type)
    425 {
    426   int no_discard = 0;
    427 
    428   if (defun_insertion (type))
    429     {
    430       push_insertion (type, xstrdup (""));
    431       no_discard++;
    432     }
    433   else
    434     {
    435       push_insertion (type, get_item_function ());
    436     }
    437 
    438   switch (type)
    439     {
    440     case menu:
    441       if (!no_headers)
    442         close_paragraph ();
    443 
    444       filling_enabled = no_indent = 0;
    445       inhibit_paragraph_indentation = 1;
    446 
    447       if (html)
    448         {
    449           had_menu_commentary = 1;
    450         }
    451       else if (!no_headers && !xml)
    452         add_word ("* Menu:\n");
    453 
    454       if (xml)
    455         xml_insert_element (MENU, START);
    456       else
    457         in_fixed_width_font++;
    458 
    459       next_menu_item_number = 1;
    460       in_menu++;
    461       no_discard++;
    462       break;
    463 
    464     case detailmenu:
    465       if (!in_menu)
    466         {
    467           if (!no_headers)
    468             close_paragraph ();
    469 
    470           filling_enabled = no_indent = 0;
    471           inhibit_paragraph_indentation = 1;
    472 
    473           no_discard++;
    474         }
    475 
    476       if (xml)
    477         {
    478           xml_insert_element (DETAILMENU, START);
    479           skip_whitespace_and_newlines();
    480         }
    481       else
    482         in_fixed_width_font++;
    483 
    484       in_detailmenu++;
    485       break;
    486 
    487     case direntry:
    488       close_single_paragraph ();
    489       filling_enabled = no_indent = 0;
    490       inhibit_paragraph_indentation = 1;
    491       insert_string ("START-INFO-DIR-ENTRY\n");
    492       break;
    493 
    494     case documentdescription:
    495       {
    496         char *desc;
    497         int start_of_end;
    498         int save_fixed_width;
    499 
    500         discard_until ("\n"); /* ignore the @documentdescription line */
    501         start_of_end = get_until ("\n@end documentdescription", &desc);
    502         save_fixed_width = in_fixed_width_font;
    503 
    504         in_fixed_width_font = 0;
    505         document_description = expansion (desc, 0);
    506         free (desc);
    507 
    508         in_fixed_width_font = save_fixed_width;
    509         input_text_offset = start_of_end; /* go back to the @end to match */
    510       }
    511       break;
    512 
    513     case copying:
    514         /* Save the copying text away for @insertcopying,
    515            typically used on the back of the @titlepage (for TeX) and
    516            the Top node (for info/html).  */
    517       if (input_text[input_text_offset] != '\n')
    518         discard_until ("\n"); /* ignore remainder of @copying line */
    519 
    520         input_text_offset = get_until ("\n@end copying", &copying_text);
    521         canon_white (copying_text);
    522 
    523       /* For info, output the copying text right away, so it will end up
    524          in the header of the Info file, before the first node, and thus
    525          get copied automatically to all the split files.  For xml, also
    526          output it right away since xml output is never split.
    527          For html, we output it specifically in html_output_head.
    528          For plain text, there's no way to hide it, so the author must
    529           use @insertcopying in the desired location.  */
    530       if (docbook)
    531 	{
    532 	  if (!xml_in_bookinfo)
    533 	    {
    534 	      xml_insert_element (BOOKINFO, START);
    535 	      xml_in_bookinfo = 1;
    536 	    }
    537           xml_insert_element (LEGALNOTICE, START);
    538 	}
    539 
    540       if (!html && !no_headers)
    541         cm_insert_copying (0, 0, 0);
    542 
    543       if (docbook)
    544         xml_insert_element (LEGALNOTICE, END);
    545 
    546       break;
    547 
    548     case quotation:
    549       /* @quotation does filling (@display doesn't).  */
    550       if (html)
    551         add_html_block_elt ("<blockquote>\n");
    552       else
    553         {
    554           /* with close_single_paragraph, we get no blank line above
    555              within @copying.  */
    556           close_paragraph ();
    557           last_char_was_newline = no_indent = 0;
    558           indented_fill = filling_enabled = 1;
    559           inhibit_paragraph_indentation = 1;
    560         }
    561       current_indent += default_indentation_increment;
    562       if (xml)
    563         xml_insert_quotation (insertion_stack->item_function, START);
    564       else if (strlen(insertion_stack->item_function))
    565         execute_string ("@b{%s:} ", insertion_stack->item_function);
    566       break;
    567 
    568     case example:
    569     case smallexample:
    570     case lisp:
    571     case smalllisp:
    572       in_fixed_width_font++;
    573       /* fall through */
    574 
    575       /* Like @example but no fixed width font. */
    576     case display:
    577     case smalldisplay:
    578       /* Like @display but without indentation. */
    579     case smallformat:
    580     case format:
    581       close_single_paragraph ();
    582       inhibit_paragraph_indentation = 1;
    583       filling_enabled = 0;
    584       last_char_was_newline = 0;
    585 
    586       if (html)
    587         /* Kludge alert: if <pre> is followed by a newline, IE3,
    588            mozilla, maybe others render an extra blank line before the
    589            pre-formatted block.  So don't output a newline.  */
    590         add_html_block_elt_args ("<pre class=\"%s\">", command);
    591 
    592       if (type != format && type != smallformat)
    593         {
    594           current_indent += example_indentation_increment;
    595           if (html)
    596             {
    597               /* Since we didn't put \n after <pre>, we need to insert
    598                  the indentation by hand.  */
    599               int i;
    600               for (i = current_indent; i > 0; i--)
    601                 add_char (' ');
    602             }
    603         }
    604       break;
    605 
    606     case multitable:
    607       do_multitable ();
    608       break;
    609 
    610     case table:
    611     case ftable:
    612     case vtable:
    613     case itemize:
    614       close_single_paragraph ();
    615       current_indent += default_indentation_increment;
    616       filling_enabled = indented_fill = 1;
    617 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
    618       inhibit_paragraph_indentation = 0;
    619 #else
    620       inhibit_paragraph_indentation = 1;
    621 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
    622 
    623       /* Make things work for losers who forget the itemize syntax. */
    624       if (type == itemize)
    625         {
    626           if (!(*insertion_stack->item_function))
    627             {
    628               free (insertion_stack->item_function);
    629               insertion_stack->item_function = xstrdup ("@bullet");
    630             }
    631         }
    632 
    633       if (!*insertion_stack->item_function)
    634         {
    635           line_error (_("%s requires an argument: the formatter for %citem"),
    636                       insertion_type_pname (type), COMMAND_PREFIX);
    637         }
    638 
    639       if (html)
    640         {
    641           if (type == itemize)
    642             {
    643               add_html_block_elt ("<ul>\n");
    644               in_paragraph = 0;
    645             }
    646           else
    647             { /* We are just starting, so this <dl>
    648                  has no <dt> children yet.  */
    649               html_deflist_has_term = 0;
    650               add_html_block_elt ("<dl>\n");
    651             }
    652         }
    653       if (xml)
    654         xml_begin_table (type, insertion_stack->item_function);
    655 
    656       while (input_text[input_text_offset] == '\n'
    657           && input_text[input_text_offset+1] == '\n')
    658         {
    659           line_number++;
    660           input_text_offset++;
    661         }
    662 
    663       break;
    664 
    665     case enumerate:
    666       close_single_paragraph ();
    667       no_indent = 0;
    668 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
    669       inhibit_paragraph_indentation = 0;
    670 #else
    671       inhibit_paragraph_indentation = 1;
    672 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
    673 
    674       current_indent += default_indentation_increment;
    675       filling_enabled = indented_fill = 1;
    676 
    677       if (html)
    678         {
    679           enum_html ();
    680           in_paragraph = 0;
    681         }
    682 
    683       if (xml)
    684         xml_begin_enumerate (enumeration_arg);
    685 
    686       if (isdigit (*enumeration_arg))
    687         start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
    688       else
    689         start_enumerating (*enumeration_arg, ENUM_ALPHA);
    690       break;
    691 
    692       /* @group produces no output in info. */
    693     case group:
    694       /* Only close the paragraph if we are not inside of an
    695          @example-like environment. */
    696       if (xml)
    697         xml_insert_element (GROUP, START);
    698       else if (!insertion_stack->next
    699           || (insertion_stack->next->insertion != display
    700               && insertion_stack->next->insertion != smalldisplay
    701               && insertion_stack->next->insertion != example
    702               && insertion_stack->next->insertion != smallexample
    703               && insertion_stack->next->insertion != lisp
    704               && insertion_stack->next->insertion != smalllisp
    705               && insertion_stack->next->insertion != format
    706               && insertion_stack->next->insertion != smallformat
    707               && insertion_stack->next->insertion != flushleft
    708               && insertion_stack->next->insertion != flushright))
    709         close_single_paragraph ();
    710       break;
    711 
    712     case cartouche:
    713       if (html)
    714 	add_html_block_elt ("<p><table class=\"cartouche\" summary=\"cartouche\" border=\"1\"><tr><td>\n");
    715       if (in_menu)
    716         no_discard++;
    717       break;
    718 
    719     case floatenv:
    720       /* Cannot nest floats, so complain.  */
    721       if (float_active)
    722         {
    723           line_error (_("%cfloat environments cannot be nested"), COMMAND_PREFIX);
    724           pop_insertion ();
    725           break;
    726         }
    727 
    728       float_active++;
    729 
    730       { /* Collect data about this float.  */
    731         /* Example: @float [FLOATTYPE][,XREFLABEL][,POSITION] */
    732         char floattype[200] = "";
    733         char xreflabel[200] = "";
    734         char position[200]  = "";
    735         char *text;
    736         char *caption;
    737         char *shortcaption;
    738         int start_of_end;
    739         int save_line_number = line_number;
    740         int save_input_text_offset = input_text_offset;
    741         int i;
    742 
    743         if (strlen (insertion_stack->item_function) > 0)
    744           {
    745             int i = 0, t = 0, c = 0;
    746             while (insertion_stack->item_function[i])
    747               {
    748                 if (insertion_stack->item_function[i] == ',')
    749                   {
    750                     switch (t)
    751                       {
    752                       case 0:
    753                         floattype[c] = '\0';
    754                         break;
    755                       case 1:
    756                         xreflabel[c] = '\0';
    757                         break;
    758                       case 2:
    759                         position[c] = '\0';
    760                         break;
    761                       }
    762                     c = 0;
    763                     t++;
    764                     i++;
    765                     continue;
    766                   }
    767 
    768                 switch (t)
    769                   {
    770                   case 0:
    771                     floattype[c] = insertion_stack->item_function[i];
    772                     break;
    773                   case 1:
    774                     xreflabel[c] = insertion_stack->item_function[i];
    775                     break;
    776                   case 2:
    777                     position[c] = insertion_stack->item_function[i];
    778                     break;
    779                   }
    780                 c++;
    781                 i++;
    782               }
    783           }
    784 
    785         skip_whitespace_and_newlines ();
    786 
    787         start_of_end = get_until ("\n@end float", &text);
    788 
    789         /* Get also the @caption.  */
    790         i = search_forward_until_pos ("\n@caption{",
    791             save_input_text_offset, start_of_end);
    792         if (i > -1)
    793           {
    794             input_text_offset = i + sizeof ("\n@caption{") - 1;
    795             get_until_in_braces ("\n@end float", &caption);
    796             input_text_offset = save_input_text_offset;
    797           }
    798         else
    799           caption = "";
    800 
    801         /* ... and the @shortcaption.  */
    802         i = search_forward_until_pos ("\n@shortcaption{",
    803             save_input_text_offset, start_of_end);
    804         if (i > -1)
    805           {
    806             input_text_offset = i + sizeof ("\n@shortcaption{") - 1;
    807             get_until_in_braces ("\n@end float", &shortcaption);
    808             input_text_offset = save_input_text_offset;
    809           }
    810         else
    811           shortcaption = "";
    812 
    813         canon_white (xreflabel);
    814         canon_white (floattype);
    815         canon_white (position);
    816         canon_white (caption);
    817         canon_white (shortcaption);
    818 
    819         add_new_float (xstrdup (xreflabel),
    820             xstrdup (caption), xstrdup (shortcaption),
    821             xstrdup (floattype), xstrdup (position));
    822 
    823         /* Move to the start of the @float so the contents get processed as
    824            usual.  */
    825         input_text_offset = save_input_text_offset;
    826         line_number = save_line_number;
    827       }
    828 
    829       if (html)
    830         add_html_block_elt ("<div class=\"float\">\n");
    831       else if (docbook)
    832         xml_insert_element (FLOAT, START);
    833       else if (xml)
    834         {
    835           xml_insert_element_with_attribute (FLOAT, START,
    836               "name=\"%s\"", current_float_id ());
    837 
    838           xml_insert_element (FLOATTYPE, START);
    839           execute_string ("%s", current_float_type ());
    840           xml_insert_element (FLOATTYPE, END);
    841 
    842           xml_insert_element (FLOATPOS, START);
    843           execute_string ("%s", current_float_position ());
    844           xml_insert_element (FLOATPOS, END);
    845         }
    846       else
    847         { /* Info */
    848           close_single_paragraph ();
    849           inhibit_paragraph_indentation = 1;
    850         }
    851 
    852       /* Anchor now.  Note that XML documents get their
    853          anchors with <float name="anchor"> tag.  */
    854       if ((!xml || docbook) && strlen (current_float_id ()) > 0)
    855         execute_string ("@anchor{%s}", current_float_id ());
    856 
    857       break;
    858 
    859       /* Insertions that are no-ops in info, but do something in TeX. */
    860     case ifclear:
    861     case ifdocbook:
    862     case ifhtml:
    863     case ifinfo:
    864     case ifnotdocbook:
    865     case ifnothtml:
    866     case ifnotinfo:
    867     case ifnotplaintext:
    868     case ifnottex:
    869     case ifnotxml:
    870     case ifplaintext:
    871     case ifset:
    872     case iftex:
    873     case ifxml:
    874     case rawtex:
    875       if (in_menu)
    876         no_discard++;
    877       break;
    878 
    879     case rawdocbook:
    880     case rawhtml:
    881     case rawxml:
    882       raw_output_block++;
    883 
    884       if (raw_output_block > 0)
    885         {
    886           xml_no_para = 1;
    887           escape_html = 0;
    888           xml_keep_space++;
    889         }
    890 
    891       {
    892         /* Some deuglification for improved readability.  */
    893         extern int xml_in_para;
    894         if (xml && !xml_in_para && xml_indentation_increment > 0)
    895           add_char ('\n');
    896       }
    897 
    898       break;
    899 
    900     case defcv:
    901     case deffn:
    902     case defivar:
    903     case defmac:
    904     case defmethod:
    905     case defop:
    906     case defopt:
    907     case defspec:
    908     case deftp:
    909     case deftypecv:
    910     case deftypefn:
    911     case deftypefun:
    912     case deftypeivar:
    913     case deftypemethod:
    914     case deftypeop:
    915     case deftypevar:
    916     case deftypevr:
    917     case defun:
    918     case defvar:
    919     case defvr:
    920       inhibit_paragraph_indentation = 1;
    921       filling_enabled = indented_fill = 1;
    922       current_indent += default_indentation_increment;
    923       no_indent = 0;
    924       if (xml)
    925 	xml_begin_definition ();
    926       break;
    927 
    928     case flushleft:
    929       close_single_paragraph ();
    930       inhibit_paragraph_indentation = 1;
    931       filling_enabled = indented_fill = no_indent = 0;
    932       if (html)
    933         add_html_block_elt ("<div align=\"left\">");
    934       break;
    935 
    936     case flushright:
    937       close_single_paragraph ();
    938       filling_enabled = indented_fill = no_indent = 0;
    939       inhibit_paragraph_indentation = 1;
    940       force_flush_right++;
    941       if (html)
    942         add_html_block_elt ("<div align=\"right\">");
    943       break;
    944 
    945     case titlepage:
    946       xml_insert_element (TITLEPAGE, START);
    947       break;
    948 
    949     default:
    950       line_error ("begin_insertion internal error: type=%d", type);
    951     }
    952 
    953   if (!no_discard)
    954     discard_until ("\n");
    955 }
    956 
    957 /* Try to end the insertion with the specified TYPE.  With a value of
    958    `bad_type', TYPE gets translated to match the value currently on top
    959    of the stack.  Otherwise, if TYPE doesn't match the top of the
    960    insertion stack, give error. */
    961 static void
    962 end_insertion (int type)
    963 {
    964   int temp_type;
    965 
    966   if (!insertion_level)
    967     return;
    968 
    969   temp_type = current_insertion_type ();
    970 
    971   if (type == bad_type)
    972     type = temp_type;
    973 
    974   if (type != temp_type)
    975     {
    976       line_error
    977         (_("`@end' expected `%s', but saw `%s'"),
    978          insertion_type_pname (temp_type), insertion_type_pname (type));
    979       return;
    980     }
    981 
    982   pop_insertion ();
    983 
    984   if (xml)
    985     {
    986       switch (type)
    987         {
    988         case ifinfo:
    989         case documentdescription:
    990           break;
    991         case quotation:
    992           xml_insert_quotation ("", END);
    993           break;
    994         case example:
    995           xml_insert_element (EXAMPLE, END);
    996           if (docbook && current_insertion_type () == floatenv)
    997             xml_insert_element (FLOATEXAMPLE, END);
    998           break;
    999         case smallexample:
   1000           xml_insert_element (SMALLEXAMPLE, END);
   1001           if (docbook && current_insertion_type () == floatenv)
   1002             xml_insert_element (FLOATEXAMPLE, END);
   1003           break;
   1004         case lisp:
   1005           xml_insert_element (LISP, END);
   1006           if (docbook && current_insertion_type () == floatenv)
   1007             xml_insert_element (FLOATEXAMPLE, END);
   1008           break;
   1009         case smalllisp:
   1010           xml_insert_element (SMALLLISP, END);
   1011           if (docbook && current_insertion_type () == floatenv)
   1012             xml_insert_element (FLOATEXAMPLE, END);
   1013           break;
   1014         case cartouche:
   1015           xml_insert_element (CARTOUCHE, END);
   1016           break;
   1017         case format:
   1018 	  if (docbook && xml_in_bookinfo && xml_in_abstract)
   1019 	    {
   1020 	      xml_insert_element (ABSTRACT, END);
   1021 	      xml_in_abstract = 0;
   1022 	    }
   1023 	  else
   1024 	    xml_insert_element (FORMAT, END);
   1025           break;
   1026         case smallformat:
   1027           xml_insert_element (SMALLFORMAT, END);
   1028           break;
   1029         case display:
   1030           xml_insert_element (DISPLAY, END);
   1031           break;
   1032         case smalldisplay:
   1033           xml_insert_element (SMALLDISPLAY, END);
   1034           break;
   1035         case table:
   1036         case ftable:
   1037         case vtable:
   1038         case itemize:
   1039           xml_end_table (type);
   1040           break;
   1041         case enumerate:
   1042           xml_end_enumerate ();
   1043           break;
   1044         case group:
   1045           xml_insert_element (GROUP, END);
   1046           break;
   1047 	case titlepage:
   1048 	  xml_insert_element (TITLEPAGE, END);
   1049 	  break;
   1050         }
   1051     }
   1052   switch (type)
   1053     {
   1054       /* Insertions which have no effect on paragraph formatting. */
   1055     case copying:
   1056       line_number--;
   1057       break;
   1058 
   1059     case ifclear:
   1060     case ifdocbook:
   1061     case ifinfo:
   1062     case ifhtml:
   1063     case ifnotdocbook:
   1064     case ifnothtml:
   1065     case ifnotinfo:
   1066     case ifnotplaintext:
   1067     case ifnottex:
   1068     case ifnotxml:
   1069     case ifplaintext:
   1070     case ifset:
   1071     case iftex:
   1072     case ifxml:
   1073     case rawtex:
   1074     case titlepage:
   1075       break;
   1076 
   1077     case rawdocbook:
   1078     case rawhtml:
   1079     case rawxml:
   1080       raw_output_block--;
   1081 
   1082       if (raw_output_block <= 0)
   1083         {
   1084           xml_no_para = 0;
   1085           escape_html = 1;
   1086           xml_keep_space--;
   1087         }
   1088 
   1089       if ((xml || html) && output_paragraph[output_paragraph_offset-1] == '\n')
   1090         output_paragraph_offset--;
   1091       break;
   1092 
   1093     case detailmenu:
   1094       if (xml)
   1095         xml_insert_element (DETAILMENU, END);
   1096 
   1097       in_detailmenu--;          /* No longer hacking menus. */
   1098       if (!in_menu)
   1099         {
   1100           if (!no_headers)
   1101             close_insertion_paragraph ();
   1102         }
   1103       break;
   1104 
   1105     case direntry:              /* Eaten if html. */
   1106       insert_string ("END-INFO-DIR-ENTRY\n\n");
   1107       close_insertion_paragraph ();
   1108       break;
   1109 
   1110     case documentdescription:
   1111       if (xml)
   1112         insert_string (document_description);
   1113         xml_insert_element (DOCUMENTDESCRIPTION, END);
   1114       break;
   1115 
   1116     case menu:
   1117       in_menu--;                /* No longer hacking menus. */
   1118       if (html && !no_headers)
   1119         add_html_block_elt ("</ul>\n");
   1120       else if (!no_headers && !xml)
   1121         close_insertion_paragraph ();
   1122       break;
   1123 
   1124     case multitable:
   1125       end_multitable ();
   1126       break;
   1127 
   1128     case enumerate:
   1129       stop_enumerating ();
   1130       close_insertion_paragraph ();
   1131       current_indent -= default_indentation_increment;
   1132       if (html)
   1133         add_html_block_elt ("</ol>\n");
   1134       break;
   1135 
   1136     case flushleft:
   1137       if (html)
   1138         add_html_block_elt ("</div>\n");
   1139       close_insertion_paragraph ();
   1140       break;
   1141 
   1142     case cartouche:
   1143       if (html)
   1144 	add_html_block_elt ("</td></tr></table>\n");
   1145       close_insertion_paragraph ();
   1146       break;
   1147 
   1148     case group:
   1149       if (!xml || docbook)
   1150         close_insertion_paragraph ();
   1151       break;
   1152 
   1153     case floatenv:
   1154       if (xml)
   1155         xml_insert_element (FLOAT, END);
   1156       else
   1157         {
   1158           if (html)
   1159             add_html_block_elt ("<p><strong class=\"float-caption\">");
   1160           else
   1161             close_paragraph ();
   1162 
   1163           no_indent = 1;
   1164 
   1165           /* Legend:
   1166                1) @float Foo,lbl & no caption:    Foo 1.1
   1167                2) @float Foo & no caption:        Foo
   1168                3) @float ,lbl & no caption:       1.1
   1169                4) @float & no caption:                    */
   1170 
   1171           if (!xml && !html)
   1172             indent (current_indent);
   1173 
   1174           if (strlen (current_float_type ()))
   1175             execute_string ("%s", current_float_type ());
   1176 
   1177           if (strlen (current_float_id ()) > 0)
   1178             {
   1179               if (strlen (current_float_type ()) > 0)
   1180                 add_char (' ');
   1181 
   1182               add_word (current_float_number ());
   1183             }
   1184 
   1185           if (strlen (current_float_title ()) > 0)
   1186             {
   1187               if (strlen (current_float_type ()) > 0
   1188                   || strlen (current_float_id ()) > 0)
   1189                 insert_string (": ");
   1190 
   1191               execute_string ("%s", current_float_title ());
   1192             }
   1193 
   1194           /* Indent the following paragraph. */
   1195           inhibit_paragraph_indentation = 0;
   1196 
   1197           if (html)
   1198             add_word ("</strong></p></div>\n");
   1199           else
   1200             close_paragraph ();
   1201         }
   1202       float_active--;
   1203       break;
   1204 
   1205     case format:
   1206     case smallformat:
   1207     case display:
   1208     case smalldisplay:
   1209     case example:
   1210     case smallexample:
   1211     case lisp:
   1212     case smalllisp:
   1213     case quotation:
   1214       /* @format and @smallformat are the only fixed_width insertion
   1215          without a change in indentation. */
   1216       if (type != format && type != smallformat && type != quotation)
   1217         current_indent -= example_indentation_increment;
   1218       else if (type == quotation)
   1219         current_indent -= default_indentation_increment;
   1220 
   1221       if (html)
   1222         { /* The complex code in close_paragraph that kills whitespace
   1223              does not function here, since we've inserted non-whitespace
   1224              (the </whatever>) before it.  The indentation already got
   1225              inserted at the end of the last example line, so we have to
   1226              delete it, or browsers wind up showing an extra blank line.  */
   1227           kill_self_indent (default_indentation_increment);
   1228           add_html_block_elt (type == quotation
   1229               ? "</blockquote>\n" : "</pre>\n");
   1230         }
   1231 
   1232       /* The ending of one of these insertions always marks the
   1233          start of a new paragraph, except for the XML output. */
   1234       if (!xml || docbook)
   1235         close_insertion_paragraph ();
   1236 
   1237       /* </pre> closes paragraph without messing with </p>.  */
   1238       if (html && type != quotation)
   1239           paragraph_is_open = 0;
   1240       break;
   1241 
   1242     case table:
   1243     case ftable:
   1244     case vtable:
   1245       current_indent -= default_indentation_increment;
   1246       if (html)
   1247         add_html_block_elt ("</dl>\n");
   1248       close_insertion_paragraph ();
   1249       break;
   1250 
   1251     case itemize:
   1252       current_indent -= default_indentation_increment;
   1253       if (html)
   1254         add_html_block_elt ("</ul>\n");
   1255       close_insertion_paragraph ();
   1256       break;
   1257 
   1258     case flushright:
   1259       force_flush_right--;
   1260       if (html)
   1261         add_html_block_elt ("</div>\n");
   1262       close_insertion_paragraph ();
   1263       break;
   1264 
   1265     /* Handle the @defun insertions with this default clause. */
   1266     default:
   1267       {
   1268         int base_type;
   1269 
   1270         if (type < defcv || type > defvr)
   1271           line_error ("end_insertion internal error: type=%d", type);
   1272 
   1273         base_type = get_base_type (type);
   1274         switch (base_type)
   1275           {
   1276           case deffn:
   1277           case defvr:
   1278           case deftp:
   1279           case deftypecv:
   1280           case deftypefn:
   1281           case deftypevr:
   1282           case defcv:
   1283           case defop:
   1284           case deftypemethod:
   1285           case deftypeop:
   1286           case deftypeivar:
   1287             if (html)
   1288               {
   1289                 if (paragraph_is_open)
   1290                   add_html_block_elt ("</p>");
   1291                 /* close the div and blockquote which has been opened in defun.c */
   1292                 if (!rollback_empty_tag ("blockquote"))
   1293                   add_html_block_elt ("</blockquote>");
   1294                 add_html_block_elt ("</div>\n");
   1295               }
   1296 	    if (xml)
   1297 	      xml_end_definition ();
   1298             break;
   1299           } /* switch (base_type)... */
   1300 
   1301         current_indent -= default_indentation_increment;
   1302         close_insertion_paragraph ();
   1303       }
   1304       break;
   1305 
   1306     }
   1307 
   1308   if (current_indent < 0)
   1309     line_error ("end_insertion internal error: current indent=%d",
   1310                 current_indent);
   1311 }
   1312 
   1313 /* Insertions cannot cross certain boundaries, such as node beginnings.  In
   1314    code that creates such boundaries, you should call `discard_insertions'
   1315    before doing anything else.  It prints the errors for you, and cleans up
   1316    the insertion stack.
   1317 
   1318    With nonzero SPECIALS_OK argument, allows unmatched
   1319    @if... conditionals, otherwise not.  This is because conditionals can
   1320    cross node boundaries.  Always happens with the @top node, for example.  */
   1321 void
   1322 discard_insertions (int specials_ok)
   1323 {
   1324   int real_line_number = line_number;
   1325   while (insertion_stack)
   1326     {
   1327       if (specials_ok
   1328           && ((ifclear <= insertion_stack->insertion
   1329                && insertion_stack->insertion <= iftex)
   1330               || insertion_stack->insertion == rawdocbook
   1331               || insertion_stack->insertion == rawhtml
   1332               || insertion_stack->insertion == rawxml
   1333               || insertion_stack->insertion == rawtex))
   1334         break;
   1335       else
   1336         {
   1337           const char *offender = insertion_type_pname (insertion_stack->insertion);
   1338 
   1339           file_line_error (insertion_stack->filename,
   1340                            insertion_stack->line_number,
   1341                            _("No matching `%cend %s'"), COMMAND_PREFIX,
   1342                            offender);
   1343           pop_insertion ();
   1344         }
   1345     }
   1346   line_number = real_line_number;
   1347 }
   1348 
   1349 /* Insertion (environment) commands.  */
   1351 
   1352 void
   1353 cm_quotation (int arg, int arg2, int arg3)
   1354 {
   1355   /* We start the blockquote element in the insertion.  */
   1356   begin_insertion (quotation);
   1357 }
   1358 
   1359 void
   1360 cm_example (int arg, int arg2, int arg3)
   1361 {
   1362   if (docbook && current_insertion_type () == floatenv)
   1363     xml_begin_docbook_float (FLOATEXAMPLE);
   1364 
   1365   if (xml)
   1366     {
   1367       /* Rollback previous newlines.  These occur between
   1368          </para> and <example>.  */
   1369       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1370         output_paragraph_offset--;
   1371 
   1372       xml_insert_element (EXAMPLE, START);
   1373 
   1374       /* Make sure example text is starting on a new line
   1375          for improved readability.  */
   1376       if (docbook)
   1377         add_char ('\n');
   1378     }
   1379 
   1380   begin_insertion (example);
   1381 }
   1382 
   1383 void
   1384 cm_smallexample (int arg, int arg2, int arg3)
   1385 {
   1386   if (docbook && current_insertion_type () == floatenv)
   1387     xml_begin_docbook_float (FLOATEXAMPLE);
   1388 
   1389   if (xml)
   1390     {
   1391       /* See cm_example comments about newlines.  */
   1392       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1393         output_paragraph_offset--;
   1394       xml_insert_element (SMALLEXAMPLE, START);
   1395       if (docbook)
   1396         add_char ('\n');
   1397     }
   1398 
   1399   begin_insertion (smallexample);
   1400 }
   1401 
   1402 void
   1403 cm_lisp (int arg, int arg2, int arg3)
   1404 {
   1405   if (docbook && current_insertion_type () == floatenv)
   1406     xml_begin_docbook_float (FLOATEXAMPLE);
   1407 
   1408   if (xml)
   1409     {
   1410       /* See cm_example comments about newlines.  */
   1411       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1412         output_paragraph_offset--;
   1413       xml_insert_element (LISP, START);
   1414       if (docbook)
   1415         add_char ('\n');
   1416     }
   1417 
   1418   begin_insertion (lisp);
   1419 }
   1420 
   1421 void
   1422 cm_smalllisp (int arg, int arg2, int arg3)
   1423 {
   1424   if (docbook && current_insertion_type () == floatenv)
   1425     xml_begin_docbook_float (FLOATEXAMPLE);
   1426 
   1427   if (xml)
   1428     {
   1429       /* See cm_example comments about newlines.  */
   1430       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1431         output_paragraph_offset--;
   1432       xml_insert_element (SMALLLISP, START);
   1433       if (docbook)
   1434         add_char ('\n');
   1435     }
   1436 
   1437   begin_insertion (smalllisp);
   1438 }
   1439 
   1440 void
   1441 cm_cartouche (int arg, int arg2, int arg3)
   1442 {
   1443   if (docbook && current_insertion_type () == floatenv)
   1444     xml_begin_docbook_float (CARTOUCHE);
   1445 
   1446   if (xml)
   1447     xml_insert_element (CARTOUCHE, START);
   1448   begin_insertion (cartouche);
   1449 }
   1450 
   1451 void
   1452 cm_copying (int arg, int arg2, int arg3)
   1453 {
   1454   begin_insertion (copying);
   1455 }
   1456 
   1457 /* Not an insertion, despite the name, but it goes with cm_copying.  */
   1458 void
   1459 cm_insert_copying (int arg, int arg2, int arg3)
   1460 {
   1461   if (!copying_text)
   1462     {
   1463       warning ("@copying not used before %s", command);
   1464       return;
   1465     }
   1466 
   1467   execute_string ("%s", copying_text);
   1468 
   1469   if (!xml && !html)
   1470     {
   1471       add_word ("\n\n");
   1472       /* Update output_position so that the node positions in the tag
   1473          tables will take account of the copying text.  */
   1474       flush_output ();
   1475     }
   1476 }
   1477 
   1478 void
   1479 cm_format (int arg, int arg2, int arg3)
   1480 {
   1481   if (xml)
   1482     {
   1483       if (docbook && xml_in_bookinfo)
   1484 	{
   1485 	  xml_insert_element (ABSTRACT, START);
   1486 	  xml_in_abstract = 1;
   1487 	}
   1488       else
   1489         {
   1490           /* See cm_example comments about newlines.  */
   1491           if (output_paragraph[output_paragraph_offset-1] == '\n')
   1492             output_paragraph_offset--;
   1493           xml_insert_element (FORMAT, START);
   1494           if (docbook)
   1495             add_char ('\n');
   1496         }
   1497     }
   1498   begin_insertion (format);
   1499 }
   1500 
   1501 void
   1502 cm_smallformat (int arg, int arg2, int arg3)
   1503 {
   1504   if (xml)
   1505     {
   1506       /* See cm_example comments about newlines.  */
   1507       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1508         output_paragraph_offset--;
   1509       xml_insert_element (SMALLFORMAT, START);
   1510       if (docbook)
   1511         add_char ('\n');
   1512     }
   1513 
   1514   begin_insertion (smallformat);
   1515 }
   1516 
   1517 void
   1518 cm_display (int arg, int arg2, int arg3)
   1519 {
   1520   if (xml)
   1521     {
   1522       /* See cm_example comments about newlines.  */
   1523       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1524         output_paragraph_offset--;
   1525       xml_insert_element (DISPLAY, START);
   1526       if (docbook)
   1527         add_char ('\n');
   1528     }
   1529 
   1530   begin_insertion (display);
   1531 }
   1532 
   1533 void
   1534 cm_smalldisplay (int arg, int arg2, int arg3)
   1535 {
   1536   if (xml)
   1537     {
   1538       /* See cm_example comments about newlines.  */
   1539       if (output_paragraph[output_paragraph_offset-1] == '\n')
   1540         output_paragraph_offset--;
   1541       xml_insert_element (SMALLDISPLAY, START);
   1542       if (docbook)
   1543         add_char ('\n');
   1544     }
   1545 
   1546   begin_insertion (smalldisplay);
   1547 }
   1548 
   1549 void
   1550 cm_direntry (int arg, int arg2, int arg3)
   1551 {
   1552   if (html || xml || no_headers)
   1553     command_name_condition (0, 0, 0);
   1554   else
   1555     begin_insertion (direntry);
   1556 }
   1557 
   1558 void
   1559 cm_documentdescription (int arg, int arg2, int arg3)
   1560 {
   1561   if (html)
   1562     begin_insertion (documentdescription);
   1563 
   1564   else if (xml)
   1565     {
   1566       xml_insert_element (DOCUMENTDESCRIPTION, START);
   1567       begin_insertion (documentdescription);
   1568     }
   1569 
   1570   else
   1571     command_name_condition (0, 0, 0);
   1572 }
   1573 
   1574 
   1575 void
   1576 cm_itemize (int arg, int arg2, int arg3)
   1577 {
   1578   begin_insertion (itemize);
   1579 }
   1580 
   1581 /* Start an enumeration insertion of type TYPE.  If the user supplied
   1582    no argument on the line, then use DEFAULT_STRING as the initial string. */
   1583 static void
   1584 do_enumeration (int type, char *default_string)
   1585 {
   1586   get_until_in_line (0, ".", &enumeration_arg);
   1587   canon_white (enumeration_arg);
   1588 
   1589   if (!*enumeration_arg)
   1590     {
   1591       free (enumeration_arg);
   1592       enumeration_arg = xstrdup (default_string);
   1593     }
   1594 
   1595   if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
   1596     {
   1597       warning (_("%s requires letter or digit"), insertion_type_pname (type));
   1598 
   1599       switch (type)
   1600         {
   1601         case enumerate:
   1602           default_string = "1";
   1603           break;
   1604         }
   1605       enumeration_arg = xstrdup (default_string);
   1606     }
   1607   begin_insertion (type);
   1608 }
   1609 
   1610 void
   1611 cm_enumerate (int arg, int arg2, int arg3)
   1612 {
   1613   do_enumeration (enumerate, "1");
   1614 }
   1615 
   1616 /*  Handle verbatim environment:
   1617     find_end_verbatim == 0:  process until end of file
   1618     find_end_verbatim != 0:  process until 'COMMAND_PREFIXend verbatim'
   1619                              or end of file
   1620 
   1621   We cannot simply copy input stream onto output stream; as the
   1622   verbatim environment may be encapsulated in an @example environment,
   1623   for example. */
   1624 void
   1625 handle_verbatim_environment (int find_end_verbatim)
   1626 {
   1627   int character;
   1628   int seen_end = 0;
   1629   int save_filling_enabled = filling_enabled;
   1630   int save_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
   1631   int save_escape_html = escape_html;
   1632 
   1633   if (!insertion_stack)
   1634     close_single_paragraph (); /* no blank lines if not at outer level */
   1635   inhibit_paragraph_indentation = 1;
   1636   filling_enabled = 0;
   1637   in_fixed_width_font++;
   1638   last_char_was_newline = 0;
   1639 
   1640   /* No indentation: this is verbatim after all
   1641      If you want indent, enclose @verbatim in @example
   1642        current_indent += default_indentation_increment;
   1643    */
   1644 
   1645   if (html)
   1646     { /* If inside @example, we'll be preceded by the indentation
   1647          already.  Browsers will ignore those spaces because we're about
   1648          to start another <pre> (don't ask me).  So, wipe them out for
   1649          cleanliness, and re-insert.  */
   1650       int i;
   1651       kill_self_indent (default_indentation_increment);
   1652       add_html_block_elt ("<pre class=\"verbatim\">");
   1653       for (i = current_indent; i > 0; i--)
   1654         add_char (' ');
   1655     }
   1656   else if (xml)
   1657     {
   1658       xml_insert_element (VERBATIM, START);
   1659       escape_html = 0;
   1660       add_word ("<![CDATA[");
   1661     }
   1662 
   1663   while (input_text_offset < input_text_length)
   1664     {
   1665       character = curchar ();
   1666 
   1667       if (character == '\n')
   1668         line_number++;
   1669 
   1670       /* Assume no newlines in END_VERBATIM. */
   1671       else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */
   1672           && (input_text_length - input_text_offset > sizeof (END_VERBATIM))
   1673           && !strncmp (&input_text[input_text_offset+1], END_VERBATIM,
   1674                        sizeof (END_VERBATIM)-1))
   1675         {
   1676           input_text_offset += sizeof (END_VERBATIM);
   1677           seen_end = 1;
   1678           break;
   1679         }
   1680 
   1681       if (html && character == '&' && escape_html)
   1682         add_word ("&amp;");
   1683       else if (html && character == '<' && escape_html)
   1684         add_word ("&lt;");
   1685       else
   1686         add_char (character);
   1687 
   1688       input_text_offset++;
   1689     }
   1690 
   1691   if (find_end_verbatim && !seen_end)
   1692     warning (_("end of file inside verbatim block"));
   1693 
   1694   if (html)
   1695     { /* See comments in example case above.  */
   1696       kill_self_indent (default_indentation_increment);
   1697       add_word ("</pre>");
   1698     }
   1699   else if (xml)
   1700     {
   1701       add_word ("]]>");
   1702       xml_insert_element (VERBATIM, END);
   1703       escape_html = save_escape_html;
   1704     }
   1705 
   1706   in_fixed_width_font--;
   1707   filling_enabled = save_filling_enabled;
   1708   inhibit_paragraph_indentation = save_inhibit_paragraph_indentation;
   1709 }
   1710 
   1711 void
   1712 cm_verbatim (int arg, int arg2, int arg3)
   1713 {
   1714   handle_verbatim_environment (1);
   1715 }
   1716 
   1717 void
   1718 cm_table (int arg, int arg2, int arg3)
   1719 {
   1720   begin_insertion (table);
   1721 }
   1722 
   1723 void
   1724 cm_multitable (int arg, int arg2, int arg3)
   1725 {
   1726   begin_insertion (multitable); /* @@ */
   1727 }
   1728 
   1729 void
   1730 cm_ftable (int arg, int arg2, int arg3)
   1731 {
   1732   begin_insertion (ftable);
   1733 }
   1734 
   1735 void
   1736 cm_vtable (int arg, int arg2, int arg3)
   1737 {
   1738   begin_insertion (vtable);
   1739 }
   1740 
   1741 void
   1742 cm_group (int arg, int arg2, int arg3)
   1743 {
   1744   begin_insertion (group);
   1745 }
   1746 
   1747 /* Insert raw HTML (no escaping of `<' etc.). */
   1749 void
   1750 cm_html (int arg, int arg2, int arg3)
   1751 {
   1752   if (process_html)
   1753     begin_insertion (rawhtml);
   1754   else
   1755     command_name_condition (0, 0, 0);
   1756 }
   1757 
   1758 void
   1759 cm_xml (int arg, int arg2, int arg3)
   1760 {
   1761   if (process_xml)
   1762     begin_insertion (rawxml);
   1763   else
   1764     command_name_condition (0, 0, 0);
   1765 }
   1766 
   1767 void
   1768 cm_docbook (int arg, int arg2, int arg3)
   1769 {
   1770   if (process_docbook)
   1771     begin_insertion (rawdocbook);
   1772   else
   1773     command_name_condition (0, 0, 0);
   1774 }
   1775 
   1776 void
   1777 cm_ifdocbook (int arg, int arg2, int arg3)
   1778 {
   1779   if (process_docbook)
   1780     begin_insertion (ifdocbook);
   1781   else
   1782     command_name_condition (0, 0, 0);
   1783 }
   1784 
   1785 void
   1786 cm_ifnotdocbook (int arg, int arg2, int arg3)
   1787 {
   1788   if (!process_docbook)
   1789     begin_insertion (ifnotdocbook);
   1790   else
   1791     command_name_condition (0, 0, 0);
   1792 }
   1793 
   1794 void
   1795 cm_ifhtml (int arg, int arg2, int arg3)
   1796 {
   1797   if (process_html)
   1798     begin_insertion (ifhtml);
   1799   else
   1800     command_name_condition (0, 0, 0);
   1801 }
   1802 
   1803 void
   1804 cm_ifnothtml (int arg, int arg2, int arg3)
   1805 {
   1806   if (!process_html)
   1807     begin_insertion (ifnothtml);
   1808   else
   1809     command_name_condition (0, 0, 0);
   1810 }
   1811 
   1812 
   1813 void
   1814 cm_ifinfo (int arg, int arg2, int arg3)
   1815 {
   1816   if (process_info)
   1817     begin_insertion (ifinfo);
   1818   else
   1819     command_name_condition (0, 0, 0);
   1820 }
   1821 
   1822 void
   1823 cm_ifnotinfo (int arg, int arg2, int arg3)
   1824 {
   1825   if (!process_info)
   1826     begin_insertion (ifnotinfo);
   1827   else
   1828     command_name_condition (0, 0, 0);
   1829 }
   1830 
   1831 
   1832 void
   1833 cm_ifplaintext (int arg, int arg2, int arg3)
   1834 {
   1835   if (process_plaintext)
   1836     begin_insertion (ifplaintext);
   1837   else
   1838     command_name_condition (0, 0, 0);
   1839 }
   1840 
   1841 void
   1842 cm_ifnotplaintext (int arg, int arg2, int arg3)
   1843 {
   1844   if (!process_plaintext)
   1845     begin_insertion (ifnotplaintext);
   1846   else
   1847     command_name_condition (0, 0, 0);
   1848 }
   1849 
   1850 
   1851 void
   1852 cm_tex (int arg, int arg2, int arg3)
   1853 {
   1854   if (process_tex)
   1855     begin_insertion (rawtex);
   1856   else
   1857     command_name_condition (0, 0, 0);
   1858 }
   1859 
   1860 void
   1861 cm_iftex (int arg, int arg2, int arg3)
   1862 {
   1863   if (process_tex)
   1864     begin_insertion (iftex);
   1865   else
   1866     command_name_condition (0, 0, 0);
   1867 }
   1868 
   1869 void
   1870 cm_ifnottex (int arg, int arg2, int arg3)
   1871 {
   1872   if (!process_tex)
   1873     begin_insertion (ifnottex);
   1874   else
   1875     command_name_condition (0, 0, 0);
   1876 }
   1877 
   1878 void
   1879 cm_ifxml (int arg, int arg2, int arg3)
   1880 {
   1881   if (process_xml)
   1882     begin_insertion (ifxml);
   1883   else
   1884     command_name_condition (0, 0, 0);
   1885 }
   1886 
   1887 void
   1888 cm_ifnotxml (int arg, int arg2, int arg3)
   1889 {
   1890   if (!process_xml)
   1891     begin_insertion (ifnotxml);
   1892   else
   1893     command_name_condition (0, 0, 0);
   1894 }
   1895 
   1896 
   1897 /* Generic xrefable block with a caption.  */
   1899 void
   1900 cm_float (int arg, int arg2, int arg3)
   1901 {
   1902   begin_insertion (floatenv);
   1903 }
   1904 
   1905 void
   1906 cm_caption (int arg, int arg2, int arg3)
   1907 {
   1908   char *temp;
   1909 
   1910   /* This is a no_op command for most formats, as we handle it during @float
   1911      insertion.  For XML though, we handle it here to keep document structure
   1912      as close as possible, to the Texinfo source.  */
   1913 
   1914   /* Everything is already handled at START.  */
   1915   if (arg == END)
   1916     return;
   1917 
   1918   /* Check if it's mislocated.  */
   1919   if (current_insertion_type () != floatenv)
   1920     line_error (_("@%s not meaningful outside `@float' environment"), command);
   1921 
   1922   get_until_in_braces ("\n@end float", &temp);
   1923 
   1924   if (xml)
   1925     {
   1926       int elt = STREQ (command, "shortcaption") ? SHORTCAPTION : CAPTION;
   1927       xml_insert_element (elt, START);
   1928       if (!docbook)
   1929         execute_string ("%s", temp);
   1930       xml_insert_element (elt, END);
   1931     }
   1932 
   1933   free (temp);
   1934 }
   1935 
   1936 /* Begin an insertion where the lines are not filled or indented. */
   1937 void
   1938 cm_flushleft (int arg, int arg2, int arg3)
   1939 {
   1940   begin_insertion (flushleft);
   1941 }
   1942 
   1943 /* Begin an insertion where the lines are not filled, and each line is
   1944    forced to the right-hand side of the page. */
   1945 void
   1946 cm_flushright (int arg, int arg2, int arg3)
   1947 {
   1948   begin_insertion (flushright);
   1949 }
   1950 
   1951 void
   1952 cm_menu (int arg, int arg2, int arg3)
   1953 {
   1954   if (current_node == NULL && !macro_expansion_output_stream)
   1955     {
   1956       warning (_("@menu seen before first @node, creating `Top' node"));
   1957       warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?"));
   1958       /* Include @top command so we can construct the implicit node tree.  */
   1959       execute_string ("@node top\n@top Top\n");
   1960     }
   1961   begin_insertion (menu);
   1962 }
   1963 
   1964 void
   1965 cm_detailmenu (int arg, int arg2, int arg3)
   1966 {
   1967   if (current_node == NULL && !macro_expansion_output_stream)
   1968     { /* Problems anyway, @detailmenu should always be inside @menu.  */
   1969       warning (_("@detailmenu seen before first node, creating `Top' node"));
   1970       execute_string ("@node top\n@top Top\n");
   1971     }
   1972   begin_insertion (detailmenu);
   1973 }
   1974 
   1975 /* Title page commands. */
   1977 
   1978 void
   1979 cm_titlepage (int arg, int arg2, int arg3)
   1980 {
   1981   titlepage_cmd_present = 1;
   1982   if (xml && !docbook)
   1983     begin_insertion (titlepage);
   1984   else
   1985     command_name_condition (0, 0, 0);
   1986 }
   1987 
   1988 void
   1989 cm_author (int arg, int arg2, int arg3)
   1990 {
   1991   char *rest;
   1992   get_rest_of_line (1, &rest);
   1993 
   1994   if (is_in_insertion_of_type (quotation))
   1995     {
   1996       if (html)
   1997         add_word_args ("&mdash; %s", rest);
   1998       else if (docbook)
   1999         {
   2000           /* FIXME Ideally, we should use an attribution element,
   2001              but they are supposed to be at the start of quotation
   2002              blocks.  So to avoid looking ahead mess, let's just
   2003              use mdash like HTML for now.  */
   2004           xml_insert_entity ("mdash");
   2005           add_word (rest);
   2006         }
   2007       else if (xml)
   2008         {
   2009           xml_insert_element (AUTHOR, START);
   2010           add_word (rest);
   2011           xml_insert_element (AUTHOR, END);
   2012         }
   2013       else
   2014         add_word_args ("-- %s", rest);
   2015     }
   2016   else if (is_in_insertion_of_type (titlepage))
   2017     {
   2018       if (xml && !docbook)
   2019         {
   2020           xml_insert_element (AUTHOR, START);
   2021           add_word (rest);
   2022           xml_insert_element (AUTHOR, END);
   2023         }
   2024     }
   2025   else
   2026     line_error (_("@%s not meaningful outside `@titlepage' and `@quotation' environments"),
   2027         command);
   2028 
   2029   free (rest);
   2030 }
   2031 
   2032 void
   2033 cm_titlepage_cmds (int arg, int arg2, int arg3)
   2034 {
   2035   char *rest;
   2036 
   2037   get_rest_of_line (1, &rest);
   2038 
   2039   if (!is_in_insertion_of_type (titlepage))
   2040     line_error (_("@%s not meaningful outside `@titlepage' environment"),
   2041         command);
   2042 
   2043   if (xml && !docbook)
   2044     {
   2045       int elt = 0;
   2046 
   2047       if (STREQ (command, "title"))
   2048         elt = BOOKTITLE;
   2049       else if (STREQ (command, "subtitle"))
   2050         elt = BOOKSUBTITLE;
   2051 
   2052       xml_insert_element (elt, START);
   2053       add_word (rest);
   2054       xml_insert_element (elt, END);
   2055     }
   2056 
   2057     free (rest);
   2058 }
   2059 
   2060 /* End existing insertion block. */
   2061 void
   2062 cm_end (int arg, int arg2, int arg3)
   2063 {
   2064   char *temp;
   2065   int type;
   2066 
   2067   get_rest_of_line (0, &temp);
   2068 
   2069   if (!insertion_level)
   2070     {
   2071       line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
   2072       return;
   2073     }
   2074 
   2075   if (temp[0] == 0)
   2076     line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
   2077 
   2078   type = find_type_from_name (temp);
   2079 
   2080   if (type == bad_type)
   2081     {
   2082       line_error (_("Bad argument `%s' to `@%s', using `%s'"),
   2083            temp, command, insertion_type_pname (current_insertion_type ()));
   2084     }
   2085   if (xml && type == menu) /* fixme */
   2086     {
   2087       xml_end_menu ();
   2088     }
   2089   end_insertion (type);
   2090   free (temp);
   2091 }
   2092 
   2093 /* @itemx, @item. */
   2095 
   2096 static int itemx_flag = 0;
   2097 
   2098 /* Return whether CMD takes a brace-delimited {arg}.  */
   2099 int
   2100 command_needs_braces (char *cmd)
   2101 {
   2102   int i;
   2103   for (i = 0; command_table[i].name; i++)
   2104     {
   2105       if (STREQ (command_table[i].name, cmd))
   2106         return command_table[i].argument_in_braces == BRACE_ARGS;
   2107     }
   2108 
   2109   return 0; /* macro or alias */
   2110 }
   2111 
   2112 
   2113 void
   2114 cm_item (int arg, int arg2, int arg3)
   2115 {
   2116   char *rest_of_line, *item_func;
   2117 
   2118   /* Can only hack "@item" while inside of an insertion. */
   2119   if (insertion_level)
   2120     {
   2121       INSERTION_ELT *stack = insertion_stack;
   2122       int original_input_text_offset;
   2123 
   2124       skip_whitespace ();
   2125       original_input_text_offset = input_text_offset;
   2126 
   2127       get_rest_of_line (0, &rest_of_line);
   2128       item_func = current_item_function ();
   2129 
   2130     /* Do the right thing depending on which insertion function is active. */
   2131     switch_top:
   2132       switch (stack->insertion)
   2133         {
   2134         case multitable:
   2135           multitable_item ();
   2136           /* Support text directly after the @item.  */
   2137           if (*rest_of_line)
   2138             {
   2139               line_number--;
   2140               input_text_offset = original_input_text_offset;
   2141             }
   2142           break;
   2143 
   2144         case ifclear:
   2145         case ifhtml:
   2146         case ifinfo:
   2147         case ifnothtml:
   2148         case ifnotinfo:
   2149         case ifnotplaintext:
   2150         case ifnottex:
   2151 	case ifnotxml:
   2152         case ifplaintext:
   2153         case ifset:
   2154         case iftex:
   2155 	case ifxml:
   2156         case rawdocbook:
   2157         case rawhtml:
   2158         case rawxml:
   2159         case rawtex:
   2160         case tex:
   2161         case cartouche:
   2162           stack = stack->next;
   2163           if (!stack)
   2164             goto no_insertion;
   2165           else
   2166             goto switch_top;
   2167           break;
   2168 
   2169         case menu:
   2170         case quotation:
   2171         case example:
   2172         case smallexample:
   2173         case lisp:
   2174         case smalllisp:
   2175         case format:
   2176         case smallformat:
   2177         case display:
   2178         case smalldisplay:
   2179         case group:
   2180           line_error (_("@%s not meaningful inside `@%s' block"),
   2181                       command,
   2182                       insertion_type_pname (current_insertion_type ()));
   2183           break;
   2184 
   2185         case itemize:
   2186         case enumerate:
   2187           if (itemx_flag)
   2188             {
   2189               line_error (_("@itemx not meaningful inside `%s' block"),
   2190                           insertion_type_pname (current_insertion_type ()));
   2191             }
   2192           else
   2193             {
   2194               if (html)
   2195                 add_html_block_elt ("<li>");
   2196               else if (xml)
   2197                 xml_begin_item ();
   2198               else
   2199                 {
   2200                   start_paragraph ();
   2201                   kill_self_indent (-1);
   2202                   filling_enabled = indented_fill = 1;
   2203 
   2204                   if (current_item_function ())
   2205                     {
   2206                       output_column = current_indent - 2;
   2207                       indent (output_column);
   2208 
   2209                       /* The item marker can be given with or without
   2210                          braces -- @bullet and @bullet{} are both ok.
   2211                          Or it might be something that doesn't take
   2212                          braces at all, such as "o" or "#" or "@ ".
   2213                          Thus, only supply braces if the item marker is
   2214                          a command, they haven't supplied braces
   2215                          themselves, and we know it needs them.  */
   2216                       if (item_func && *item_func)
   2217                         {
   2218                           if (*item_func == COMMAND_PREFIX
   2219                               && item_func[strlen (item_func) - 1] != '}'
   2220                               && command_needs_braces (item_func + 1))
   2221                             execute_string ("%s{}", item_func);
   2222                           else
   2223                             execute_string ("%s", item_func);
   2224                         }
   2225                       insert (' ');
   2226                       output_column++;
   2227                     }
   2228                   else
   2229                     enumerate_item ();
   2230 
   2231                   /* Special hack.  This makes `close_paragraph' a no-op until
   2232                      `start_paragraph' has been called. */
   2233                   must_start_paragraph = 1;
   2234                 }
   2235 
   2236               /* Handle text directly after the @item.  */
   2237               if (*rest_of_line)
   2238                 {
   2239                   line_number--;
   2240                   input_text_offset = original_input_text_offset;
   2241                 }
   2242             }
   2243           break;
   2244 
   2245         case table:
   2246         case ftable:
   2247         case vtable:
   2248           if (html)
   2249             { /* If nothing has been output since the last <dd>,
   2250                  remove the empty <dd> element.  Some browsers render
   2251                  an extra empty line for <dd><dt>, which makes @itemx
   2252                  conversion look ugly.  */
   2253               rollback_empty_tag ("dd");
   2254 
   2255               /* Force the browser to render one blank line before
   2256                  each new @item in a table.  But don't do that if
   2257                  this is the first <dt> after the <dl>, or if we are
   2258                  converting @itemx.
   2259 
   2260                  Note that there are some browsers which ignore <br>
   2261                  in this context, but I cannot find any way to force
   2262                  them all render exactly one blank line.  */
   2263               if (!itemx_flag && html_deflist_has_term)
   2264                 add_html_block_elt ("<br>");
   2265 
   2266               /* We are about to insert a <dt>, so this <dl> has a term.
   2267                  Feel free to insert a <br> next time. :)  */
   2268               html_deflist_has_term = 1;
   2269 
   2270               add_html_block_elt ("<dt>");
   2271               if (item_func && *item_func)
   2272                 execute_string ("%s{%s}", item_func, rest_of_line);
   2273               else
   2274                 execute_string ("%s", rest_of_line);
   2275 
   2276               if (current_insertion_type () == ftable)
   2277                 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
   2278 
   2279               if (current_insertion_type () == vtable)
   2280                 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
   2281 
   2282               add_html_block_elt ("<dd>");
   2283             }
   2284           else if (xml) /* && docbook)*/ /* 05-08 */
   2285             {
   2286               xml_begin_table_item ();
   2287 
   2288               if (!docbook && current_insertion_type () == ftable)
   2289                 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
   2290 
   2291               if (!docbook && current_insertion_type () == vtable)
   2292                 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
   2293 
   2294               if (item_func && *item_func)
   2295                 execute_string ("%s{%s}", item_func, rest_of_line);
   2296               else
   2297                 execute_string ("%s", rest_of_line);
   2298               xml_continue_table_item ();
   2299             }
   2300           else
   2301             {
   2302               /* We need this to determine if we have two @item's in a row
   2303                  (see test just below).  */
   2304               static int last_item_output_position = 0;
   2305 
   2306               /* Get rid of extra characters. */
   2307               kill_self_indent (-1);
   2308 
   2309               /* If we have one @item followed directly by another @item,
   2310                  we need to insert a blank line.  This is not true for
   2311                  @itemx, though.  */
   2312               if (!itemx_flag && last_item_output_position == output_position)
   2313                 insert ('\n');
   2314 
   2315               /* `close_paragraph' almost does what we want.  The problem
   2316                  is when paragraph_is_open, and last_char_was_newline, and
   2317                  the last newline has been turned into a space, because
   2318                  filling_enabled. I handle it here. */
   2319               if (last_char_was_newline && filling_enabled &&
   2320                   paragraph_is_open)
   2321                 insert ('\n');
   2322               close_paragraph ();
   2323 
   2324 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
   2325               /* Indent on a new line, but back up one indentation level. */
   2326               {
   2327                 int save = inhibit_paragraph_indentation;
   2328                 inhibit_paragraph_indentation = 1;
   2329                 /* At this point, inserting any non-whitespace character will
   2330                    force the existing indentation to be output. */
   2331                 add_char ('i');
   2332                 inhibit_paragraph_indentation = save;
   2333               }
   2334 #else /* !INDENT_PARAGRAPHS_IN_TABLE */
   2335               add_char ('i');
   2336 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
   2337 
   2338               output_paragraph_offset--;
   2339               kill_self_indent (default_indentation_increment + 1);
   2340 
   2341               /* Add item's argument to the line. */
   2342               filling_enabled = 0;
   2343               if (item_func && *item_func)
   2344                 execute_string ("%s{%s}", item_func, rest_of_line);
   2345               else
   2346                 execute_string ("%s", rest_of_line);
   2347 
   2348               if (current_insertion_type () == ftable)
   2349                 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
   2350               else if (current_insertion_type () == vtable)
   2351                 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
   2352 
   2353               /* Start a new line, and let start_paragraph ()
   2354                  do the indenting of it for you. */
   2355               close_single_paragraph ();
   2356               indented_fill = filling_enabled = 1;
   2357               last_item_output_position = output_position;
   2358             }
   2359         }
   2360       free (rest_of_line);
   2361     }
   2362   else
   2363     {
   2364     no_insertion:
   2365       line_error (_("%c%s found outside of an insertion block"),
   2366                   COMMAND_PREFIX, command);
   2367     }
   2368 }
   2369 
   2370 void
   2371 cm_itemx (int arg, int arg2, int arg3)
   2372 {
   2373   itemx_flag++;
   2374   cm_item (0, 0, 0);
   2375   itemx_flag--;
   2376 }
   2377 
   2378 int headitem_flag = 0;
   2379 
   2380 void
   2381 cm_headitem (int arg, int arg2, int arg3)
   2382 {
   2383   headitem_flag = 1;
   2384   cm_item (0, 0, 0);
   2385 }
   2386