insertion.c revision 114472
11590Srgrimes/* insertion.c -- insertions for Texinfo. 21590Srgrimes $Id: insertion.c,v 1.14 2003/01/02 23:46:29 karl Exp $ 31590Srgrimes 41590Srgrimes Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software 51590Srgrimes Foundation, Inc. 61590Srgrimes 71590Srgrimes This program is free software; you can redistribute it and/or modify 81590Srgrimes it under the terms of the GNU General Public License as published by 91590Srgrimes the Free Software Foundation; either version 2, or (at your option) 101590Srgrimes any later version. 111590Srgrimes 121590Srgrimes This program is distributed in the hope that it will be useful, 131590Srgrimes but WITHOUT ANY WARRANTY; without even the implied warranty of 141590Srgrimes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151590Srgrimes GNU General Public License for more details. 161590Srgrimes 171590Srgrimes You should have received a copy of the GNU General Public License 181590Srgrimes along with this program; if not, write to the Free Software Foundation, 191590Srgrimes Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 201590Srgrimes 211590Srgrimes#include "system.h" 221590Srgrimes#include "cmds.h" 231590Srgrimes#include "defun.h" 241590Srgrimes#include "insertion.h" 251590Srgrimes#include "macro.h" 261590Srgrimes#include "makeinfo.h" 271590Srgrimes#include "xml.h" 281590Srgrimes 291590Srgrimes/* Must match list in insertion.h. */ 301590Srgrimesstatic char *insertion_type_names[] = 3174769Smikeh{ 321590Srgrimes "cartouche", "copying", "defcv", "deffn", "defivar", "defmac", 3374769Smikeh "defmethod", "defop", "defopt", "defspec", "deftp", "deftypefn", 341590Srgrimes "deftypefun", "deftypeivar", "deftypemethod", "deftypeop", 3599112Sobrien "deftypevar", "deftypevr", "defun", "defvar", "defvr", "detailmenu", 3699112Sobrien "direntry", "display", "documentdescription", "enumerate", "example", 371590Srgrimes "flushleft", "flushright", "format", "ftable", "group", "ifclear", 3891227Sbde "ifhtml", "ifinfo", "ifnothtml", "ifnotinfo", "ifnotplaintext", "ifnottex", "ifnotxml", 3991227Sbde "ifplaintext", "ifset", "iftex", "ifxml", "itemize", "lisp", "menu", 401590Srgrimes "multitable", "quotation", "rawhtml", "rawtex", "smalldisplay", 411590Srgrimes "smallexample", "smallformat", "smalllisp", "verbatim", "table", 421590Srgrimes "tex", "vtable", "bad_type" 431590Srgrimes}; 441590Srgrimes 451590Srgrimes/* All nested environments. */ 461590SrgrimesINSERTION_ELT *insertion_stack = NULL; 471590Srgrimes 481590Srgrimes/* How deeply we're nested. */ 4992921Simpint insertion_level = 0; 5077274Smikeh 511590Srgrimes/* Set to 1 if we've processed (commentary) text in a @menu that 521590Srgrimes wasn't part of a menu item. */ 531590Srgrimesint had_menu_commentary; 541590Srgrimes 55216564Scharnier/* How to examine menu lines. */ 561590Srgrimesint in_detailmenu = 0; 571590Srgrimes 581590Srgrimes/* Whether to examine menu lines. */ 591590Srgrimesint in_menu = 0; 6077274Smikeh 611590Srgrimes/* Set to 1 if <p> is written in normal context. 6277274Smikeh Used for menu and itemize. */ 631590Srgrimesint in_paragraph = 0; 641590Srgrimes 651590Srgrimesstatic const char dl_tag[] = "<dl>\n"; 661590Srgrimesextern void cm_insert_copying (); 671590Srgrimes 68173438Sdds 69216564Scharniervoid 701590Srgrimesinit_insertion_stack () 711590Srgrimes{ 721590Srgrimes insertion_stack = NULL; 731590Srgrimes} 741590Srgrimes 7577274Smikeh/* Return the type of the current insertion. */ 761590Srgrimesstatic enum insertion_type 771590Srgrimescurrent_insertion_type () 781590Srgrimes{ 791590Srgrimes return insertion_level ? insertion_stack->insertion : bad_type; 801590Srgrimes} 811590Srgrimes 8277274Smikeh/* Return the string which is the function to wrap around items, or NULL 831590Srgrimes if we're not in an environment where @item is ok. */ 841590Srgrimesstatic char * 851590Srgrimescurrent_item_function () 861590Srgrimes{ 871590Srgrimes int done = 0; 881590Srgrimes INSERTION_ELT *elt = insertion_stack; 891590Srgrimes 901590Srgrimes /* Skip down through the stack until we find an insertion with an 91216564Scharnier itemize function defined, i.e., skip conditionals, @cartouche, etc. */ 921590Srgrimes while (!done && elt) 931590Srgrimes { 941590Srgrimes switch (elt->insertion) 951590Srgrimes { 961590Srgrimes /* This list should match the one in cm_item. */ 971590Srgrimes case ifclear: 981590Srgrimes case ifhtml: 991590Srgrimes case ifinfo: 1001590Srgrimes case ifnothtml: 1011590Srgrimes case ifnotinfo: 1021590Srgrimes case ifnotplaintext: 1031590Srgrimes case ifnottex: 104216564Scharnier case ifnotxml: 1051590Srgrimes case ifplaintext: 1061590Srgrimes case ifset: 1071590Srgrimes case iftex: 1081590Srgrimes case ifxml: 10977274Smikeh case rawhtml: 11077274Smikeh case rawtex: 1111590Srgrimes case tex: 1121590Srgrimes case cartouche: 1131590Srgrimes elt = elt->next; 1141590Srgrimes break; 1151590Srgrimes 1161590Srgrimes default: 117216564Scharnier done = 1; 1181590Srgrimes } 11977274Smikeh } 1201590Srgrimes 12177274Smikeh /* item_function usually gets assigned the empty string. */ 1228874Srgrimes return done && (*elt->item_function) ? elt->item_function : NULL; 12377274Smikeh} 1241590Srgrimes 1251590Srgrimes/* Parse the item marker function off the input. If result is just "@", 1261590Srgrimes change it to "@ ", since "@" by itself is not a command. This makes 1271590Srgrimes "@ ", "@\t", and "@\n" all the same, but their default meanings are 12877274Smikeh the same anyway, and let's not worry about supporting redefining them. */ 1291590Srgrimeschar * 1301590Srgrimesget_item_function () 131216564Scharnier{ 1321590Srgrimes char *item_function; 13377274Smikeh get_rest_of_line (0, &item_function); 1341590Srgrimes 13577274Smikeh /* If we hit the end of text in get_rest_of_line, backing up 13677274Smikeh input pointer will cause the last character of the last line 13777274Smikeh be pushed back onto the input, which is wrong. */ 1381590Srgrimes if (input_text_offset < input_text_length) 1391590Srgrimes backup_input_pointer (); 1401590Srgrimes 14177274Smikeh if (STREQ (item_function, "@")) 1421590Srgrimes { 14377274Smikeh free (item_function); 1441590Srgrimes item_function = xstrdup ("@ "); 1451590Srgrimes } 14677274Smikeh 14727643Scharnier return item_function; 1481590Srgrimes} 1491590Srgrimes 15077274Smikeh /* Push the state of the current insertion on the stack. */ 1511590Srgrimesvoid 1521590Srgrimespush_insertion (type, item_function) 1531590Srgrimes enum insertion_type type; 1541590Srgrimes char *item_function; 1551590Srgrimes{ 1561590Srgrimes INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT)); 1571590Srgrimes 1581590Srgrimes new->item_function = item_function; 1591590Srgrimes new->filling_enabled = filling_enabled; 160216564Scharnier new->indented_fill = indented_fill; 1611590Srgrimes new->insertion = type; 1621590Srgrimes new->line_number = line_number; 16377274Smikeh new->filename = xstrdup (input_filename); 16477274Smikeh new->inhibited = inhibit_paragraph_indentation; 1651590Srgrimes new->in_fixed_width_font = in_fixed_width_font; 1661590Srgrimes new->next = insertion_stack; 1671590Srgrimes insertion_stack = new; 16877274Smikeh insertion_level++; 1691590Srgrimes} 17077274Smikeh 17188227Sache /* Pop the value on top of the insertion stack into the 17277274Smikeh global variables. */ 1731590Srgrimesvoid 1741590Srgrimespop_insertion () 1751590Srgrimes{ 1761590Srgrimes INSERTION_ELT *temp = insertion_stack; 1771590Srgrimes 1781590Srgrimes if (temp == NULL) 1791590Srgrimes return; 1801590Srgrimes 1811590Srgrimes in_fixed_width_font = temp->in_fixed_width_font; 1821590Srgrimes inhibit_paragraph_indentation = temp->inhibited; 1831590Srgrimes filling_enabled = temp->filling_enabled; 1841590Srgrimes indented_fill = temp->indented_fill; 1851590Srgrimes free_and_clear (&(temp->item_function)); 1861590Srgrimes free_and_clear (&(temp->filename)); 1871590Srgrimes insertion_stack = insertion_stack->next; 1881590Srgrimes free (temp); 1891590Srgrimes insertion_level--; 1901590Srgrimes} 1911590Srgrimes 1921590Srgrimes /* Return a pointer to the print name of this 1931590Srgrimes enumerated type. */ 1941590Srgrimeschar * 1951590Srgrimesinsertion_type_pname (type) 1961590Srgrimes enum insertion_type type; 1971590Srgrimes{ 1981590Srgrimes if ((int) type < (int) bad_type) 1991590Srgrimes return insertion_type_names[(int) type]; 2001590Srgrimes else 2011590Srgrimes return _("Broken-Type in insertion_type_pname"); 2021590Srgrimes} 2031590Srgrimes 20477274Smikeh/* Return the insertion_type associated with NAME. 2051590Srgrimes If the type is not one of the known ones, return BAD_TYPE. */ 2061590Srgrimesenum insertion_type 2071590Srgrimesfind_type_from_name (name) 2081590Srgrimes char *name; 2091590Srgrimes{ 2101590Srgrimes int index = 0; 2111590Srgrimes while (index < (int) bad_type) 2121590Srgrimes { 2131590Srgrimes if (STREQ (name, insertion_type_names[index])) 2141590Srgrimes return (enum insertion_type) index; 215216564Scharnier if (index == rawhtml && STREQ (name, "html")) 2161590Srgrimes return rawhtml; 21777274Smikeh if (index == rawhtml && STREQ (name, "xml")) 2181590Srgrimes return rawhtml; 2191590Srgrimes if (index == rawtex && STREQ (name, "tex")) 2201590Srgrimes return rawtex; 2211590Srgrimes index++; 22277274Smikeh } 2231590Srgrimes return bad_type; 2241590Srgrimes} 2251590Srgrimes 2261590Srgrimesint 22777274Smikehdefun_insertion (type) 2281590Srgrimes enum insertion_type type; 2291590Srgrimes{ 2301590Srgrimes return 0 23174769Smikeh || (type == defcv) 23274769Smikeh || (type == deffn) 2331590Srgrimes || (type == defivar) 2341590Srgrimes || (type == defmac) 235216564Scharnier || (type == defmethod) 2361590Srgrimes || (type == defop) 2371590Srgrimes || (type == defopt) 23874769Smikeh || (type == defspec) 23974769Smikeh || (type == deftp) 24088227Sache || (type == deftypefn) 2411590Srgrimes || (type == deftypefun) 2421590Srgrimes || (type == deftypeivar) 2431590Srgrimes || (type == deftypemethod) 2441590Srgrimes || (type == deftypeop) 2451590Srgrimes || (type == deftypevar) 2461590Srgrimes || (type == deftypevr) 2471590Srgrimes || (type == defun) 2481590Srgrimes || (type == defvar) 2491590Srgrimes || (type == defvr) 2501590Srgrimes ; 2511590Srgrimes} 2521590Srgrimes 2531590Srgrimes/* MAX_NS is the maximum nesting level for enumerations. I picked 100 25418532Sbde which seemed reasonable. This doesn't control the number of items, 25518532Sbde just the number of nested lists. */ 25618532Sbde#define max_stack_depth 100 2571590Srgrimes#define ENUM_DIGITS 1 2581590Srgrimes#define ENUM_ALPHA 2 2591590Srgrimestypedef struct { 2601590Srgrimes int enumtype; 2611590Srgrimes int enumval; 2621590Srgrimes} DIGIT_ALPHA; 2631590Srgrimes 264216564ScharnierDIGIT_ALPHA enumstack[max_stack_depth]; 2651590Srgrimesint enumstack_offset = 0; 2661590Srgrimesint current_enumval = 1; 2671590Srgrimesint current_enumtype = ENUM_DIGITS; 2681590Srgrimeschar *enumeration_arg = NULL; 26977274Smikeh 27077274Smikehvoid 2711590Srgrimesstart_enumerating (at, type) 27274769Smikeh int at, type; 27377274Smikeh{ 2741590Srgrimes if ((enumstack_offset + 1) == max_stack_depth) 27518532Sbde { 2761590Srgrimes line_error (_("Enumeration stack overflow")); 27777274Smikeh return; 27877274Smikeh } 2791590Srgrimes enumstack[enumstack_offset].enumtype = current_enumtype; 2801590Srgrimes enumstack[enumstack_offset].enumval = current_enumval; 2811590Srgrimes enumstack_offset++; 2821590Srgrimes current_enumval = at; 2831590Srgrimes current_enumtype = type; 2841590Srgrimes} 2851590Srgrimes 2861590Srgrimesvoid 2871590Srgrimesstop_enumerating () 28877274Smikeh{ 2891590Srgrimes --enumstack_offset; 2901590Srgrimes if (enumstack_offset < 0) 2911590Srgrimes enumstack_offset = 0; 2921590Srgrimes 2931590Srgrimes current_enumval = enumstack[enumstack_offset].enumval; 2941590Srgrimes current_enumtype = enumstack[enumstack_offset].enumtype; 2951590Srgrimes} 296216564Scharnier 2971590Srgrimes/* Place a letter or digits into the output stream. */ 2981590Srgrimesvoid 2991590Srgrimesenumerate_item () 3001590Srgrimes{ 30177274Smikeh char temp[10]; 3021590Srgrimes 30377274Smikeh if (current_enumtype == ENUM_ALPHA) 3041590Srgrimes { 3051590Srgrimes if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1)) 3061590Srgrimes { 3071590Srgrimes current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A'); 3081590Srgrimes warning (_("lettering overflow, restarting at %c"), current_enumval); 3091590Srgrimes } 3101590Srgrimes sprintf (temp, "%c. ", current_enumval); 3111590Srgrimes } 31277274Smikeh else 3131590Srgrimes sprintf (temp, "%d. ", current_enumval); 3141590Srgrimes 3151590Srgrimes indent (output_column += (current_indent - strlen (temp))); 3161590Srgrimes add_word (temp); 3171590Srgrimes current_enumval++; 3181590Srgrimes} 3191590Srgrimes 320216564Scharnierstatic void 3211590Srgrimesenum_html () 3221590Srgrimes{ 3231590Srgrimes char type; 3241590Srgrimes int start; 3251590Srgrimes 3261590Srgrimes if (isdigit (*enumeration_arg)) 32788150Smikeh { 32888150Smikeh type = '1'; 329205793Sed start = atoi (enumeration_arg); 3301590Srgrimes } 3311590Srgrimes else if (isupper (*enumeration_arg)) 3321590Srgrimes { 3331590Srgrimes type = 'A'; 3341590Srgrimes start = *enumeration_arg - 'A' + 1; 3351590Srgrimes } 3361590Srgrimes else 3371590Srgrimes { 3381590Srgrimes type = 'a'; 339216564Scharnier start = *enumeration_arg - 'a' + 1; 3401590Srgrimes } 34177274Smikeh 3421590Srgrimes add_word_args ("<ol type=%c start=%d>\n", type, start); 3431590Srgrimes} 3441590Srgrimes 34577274Smikeh/* Conditionally parse based on the current command name. */ 34674769Smikehvoid 3471590Srgrimescommand_name_condition () 3481590Srgrimes{ 3491590Srgrimes char *discarder = xmalloc (8 + strlen (command)); 3501590Srgrimes 35177274Smikeh sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command); 35277274Smikeh discard_until (discarder); 3531590Srgrimes discard_until ("\n"); 3541590Srgrimes 3551590Srgrimes free (discarder); 3561590Srgrimes} 3571590Srgrimes 3581590Srgrimes/* This is where the work for all the "insertion" style 3591590Srgrimes commands is done. A huge switch statement handles the 360216564Scharnier various setups, and generic code is on both sides. */ 3611590Srgrimesvoid 36277274Smikehbegin_insertion (type) 3631590Srgrimes enum insertion_type type; 3641590Srgrimes{ 3651590Srgrimes int no_discard = 0; 3661590Srgrimes 3671590Srgrimes if (defun_insertion (type)) 3681590Srgrimes { 3691590Srgrimes push_insertion (type, xstrdup ("")); 3701590Srgrimes no_discard++; 3711590Srgrimes } 3721590Srgrimes else 3731590Srgrimes { 3741590Srgrimes push_insertion (type, get_item_function ()); 3751590Srgrimes } 3761590Srgrimes 3771590Srgrimes switch (type) 37877274Smikeh { 3791590Srgrimes case menu: 3801590Srgrimes if (!no_headers) 3811590Srgrimes close_paragraph (); 3821590Srgrimes 3831590Srgrimes filling_enabled = no_indent = 0; 3841590Srgrimes inhibit_paragraph_indentation = 1; 3851590Srgrimes 386216564Scharnier if (html) 3871590Srgrimes { 38877274Smikeh had_menu_commentary = 1; 38977274Smikeh } 3901590Srgrimes else if (!no_headers && !xml) 39177274Smikeh add_word ("* Menu:\n"); 39277274Smikeh 39377274Smikeh if (xml) 39477274Smikeh xml_insert_element (MENU, START); 39577274Smikeh 39674769Smikeh next_menu_item_number = 1; 39774769Smikeh in_menu++; 39877274Smikeh in_fixed_width_font++; 39974769Smikeh no_discard++; 4001590Srgrimes break; 4011590Srgrimes 4021590Srgrimes case detailmenu: 40377274Smikeh if (!in_menu) 4041590Srgrimes { 4051590Srgrimes if (!no_headers) 4061590Srgrimes close_paragraph (); 4071590Srgrimes 4081590Srgrimes filling_enabled = no_indent = 0; 4091590Srgrimes inhibit_paragraph_indentation = 1; 4101590Srgrimes 4111590Srgrimes no_discard++; 4121590Srgrimes } 4131590Srgrimes 4141590Srgrimes in_fixed_width_font++; 41577274Smikeh in_detailmenu++; 4161590Srgrimes break; 4171590Srgrimes 4181590Srgrimes case direntry: 4191590Srgrimes close_single_paragraph (); 4201590Srgrimes filling_enabled = no_indent = 0; 42177274Smikeh inhibit_paragraph_indentation = 1; 4221590Srgrimes insert_string ("START-INFO-DIR-ENTRY\n"); 4231590Srgrimes break; 4241590Srgrimes 4251590Srgrimes case documentdescription: 4261590Srgrimes { 4271590Srgrimes char *desc; 4281590Srgrimes int start_of_end; 4291590Srgrimes int save_fixed_width; 4301590Srgrimes 4311590Srgrimes discard_until ("\n"); /* ignore the @documentdescription line */ 4321590Srgrimes start_of_end = get_until ("\n@end documentdescription", &desc); 4331590Srgrimes save_fixed_width = in_fixed_width_font; 4341590Srgrimes 4351590Srgrimes in_fixed_width_font = 0; 4361590Srgrimes document_description = expansion (desc, 0); 4371590Srgrimes free (desc); 4381590Srgrimes 4391590Srgrimes in_fixed_width_font = save_fixed_width; 4401590Srgrimes input_text_offset = start_of_end; /* go back to the @end to match */ 4411590Srgrimes } 4421590Srgrimes break; 4431590Srgrimes 4441590Srgrimes case copying: 4451590Srgrimes { 4461590Srgrimes /* Save the copying text away for @insertcopying, 4471590Srgrimes typically used on the back of the @titlepage (for TeX) and 44877274Smikeh the Top node (for info/html). */ 4491590Srgrimes char *text; 4501590Srgrimes int start_of_end; 4511590Srgrimes int save_paragraph_indentation; 4521590Srgrimes 45377274Smikeh discard_until ("\n"); /* ignore remainder of @copying line */ 4541590Srgrimes start_of_end = get_until ("\n@end copying", &text); 4551590Srgrimes 4561590Srgrimes /* include all the output-format-specific markup. */ 45777274Smikeh if (docbook) 4581590Srgrimes { 4591590Srgrimes save_paragraph_indentation = inhibit_paragraph_indentation; 4601590Srgrimes inhibit_paragraph_indentation = 1; 4611590Srgrimes } 4621590Srgrimes copying_text = full_expansion (text, 0); 4631590Srgrimes free (text); 464102412Scharnier 4651590Srgrimes if (docbook) 4661590Srgrimes inhibit_paragraph_indentation = save_paragraph_indentation; 4671590Srgrimes 4681590Srgrimes input_text_offset = start_of_end; /* go back to the @end to match */ 4691590Srgrimes } 4701590Srgrimes 4711590Srgrimes /* For info, output the copying text right away, so it will end up 472208592Suqs in the header of the Info file, before the first node, and thus 473208592Suqs get copied automatically to all the split files. For xml, also 4741590Srgrimes output it right away since xml output is never split. 475208592Suqs For html, we output it specifically in html_output_head. 476208592Suqs For plain text, there's no way to hide it, so the author must 4771590Srgrimes use @insertcopying in the desired location. */ 4781590Srgrimes if (docbook) 4791590Srgrimes { 4801590Srgrimes if (!xml_in_bookinfo) 4811590Srgrimes { 48277274Smikeh xml_insert_element (BOOKINFO, START); 4831590Srgrimes xml_in_bookinfo = 1; 48483848Smikeh } 48583848Smikeh if (!xml_in_abstract) 48677274Smikeh { 4871590Srgrimes xml_insert_element (ABSTRACT, START); 4881590Srgrimes xml_in_abstract = 1; 4891590Srgrimes } 4901590Srgrimes } 4911590Srgrimes if (!html && !no_headers) 4921590Srgrimes cm_insert_copying (); 4931590Srgrimes if (docbook && xml_in_abstract) 4941590Srgrimes { 4951590Srgrimes xml_insert_element (ABSTRACT, END); 4961590Srgrimes xml_in_abstract = 0; 497216564Scharnier } 4981590Srgrimes break; 4991590Srgrimes 5001590Srgrimes case quotation: 50177274Smikeh /* @quotation does filling (@display doesn't). */ 50277274Smikeh if (html) 5031590Srgrimes add_word ("<blockquote>\n"); 5041590Srgrimes else 50577274Smikeh { 50677274Smikeh /* with close_single_paragraph, we get no blank line above 50777274Smikeh within @copying. */ 50877274Smikeh close_paragraph (); 5091590Srgrimes last_char_was_newline = no_indent = 0; 51027643Scharnier indented_fill = filling_enabled = 1; 5111590Srgrimes inhibit_paragraph_indentation = 1; 51277274Smikeh } 5131590Srgrimes current_indent += default_indentation_increment; 51477274Smikeh break; 5151590Srgrimes 5161590Srgrimes case display: 5171590Srgrimes case smalldisplay: 5181590Srgrimes case example: 51977274Smikeh case smallexample: 52077274Smikeh case lisp: 5211590Srgrimes case smalllisp: 5221590Srgrimes /* Like @display but without indentation. */ 5231590Srgrimes case smallformat: 52477274Smikeh case format: 52574769Smikeh close_single_paragraph (); 52677274Smikeh inhibit_paragraph_indentation = 1; 5271590Srgrimes in_fixed_width_font++; 52877274Smikeh filling_enabled = 0; 52974769Smikeh last_char_was_newline = 0; 5301590Srgrimes 53174769Smikeh if (html) 5321590Srgrimes /* Kludge alert: if <pre> is followed by a newline, IE3 5331590Srgrimes renders an extra blank line before the pre-formatted block. 5341590Srgrimes Other browsers seem to not mind one way or the other. */ 53574769Smikeh add_word_args ("<pre class=\"%s\">", command); 5361590Srgrimes 5371590Srgrimes if (type != format && type != smallformat) 5381590Srgrimes { 53974769Smikeh current_indent += default_indentation_increment; 5401590Srgrimes if (html) 5411590Srgrimes { 54274769Smikeh /* Since we didn't put \n after <pre>, we need to insert 54374769Smikeh the indentation by hand. */ 5441590Srgrimes int i; 5451590Srgrimes for (i = current_indent; i > 0; i--) 5461590Srgrimes add_char (' '); 5471590Srgrimes } 5481590Srgrimes } 54977274Smikeh 5501590Srgrimes break; 5511590Srgrimes 5521590Srgrimes case multitable: 553229655Suqs do_multitable (); 5541590Srgrimes break; 5551590Srgrimes 556216564Scharnier case table: 5571590Srgrimes case ftable: 55877274Smikeh case vtable: 55977274Smikeh case itemize: 5601590Srgrimes close_single_paragraph (); 56177274Smikeh current_indent += default_indentation_increment; 5621590Srgrimes filling_enabled = indented_fill = 1; 5631590Srgrimes#if defined (INDENT_PARAGRAPHS_IN_TABLE) 56477274Smikeh inhibit_paragraph_indentation = 0; 5651590Srgrimes#else 5661590Srgrimes inhibit_paragraph_indentation = 1; 5671590Srgrimes#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 5681590Srgrimes 5691590Srgrimes /* Make things work for losers who forget the itemize syntax. */ 5701590Srgrimes if (type == itemize) 571216564Scharnier { 5721590Srgrimes if (!(*insertion_stack->item_function)) 57374769Smikeh { 5741590Srgrimes free (insertion_stack->item_function); 5751590Srgrimes insertion_stack->item_function = xstrdup ("@bullet"); 57677274Smikeh } 5771590Srgrimes } 5781590Srgrimes 5791590Srgrimes if (!*insertion_stack->item_function) 5801590Srgrimes { 58174769Smikeh line_error (_("%s requires an argument: the formatter for %citem"), 5821590Srgrimes insertion_type_pname (type), COMMAND_PREFIX); 5831590Srgrimes } 5841590Srgrimes 5851590Srgrimes if (html) 5861590Srgrimes { 5871590Srgrimes if (type == itemize) 5881590Srgrimes { 589216564Scharnier add_word ("<ul>\n"); 5901590Srgrimes in_paragraph = 0; 59177274Smikeh } 5921590Srgrimes else 59377274Smikeh add_word (dl_tag); 5941590Srgrimes } 5951590Srgrimes if (xml) 5961590Srgrimes xml_begin_table (type, insertion_stack->item_function); 5971590Srgrimes break; 5981590Srgrimes 599 case enumerate: 600 close_single_paragraph (); 601 no_indent = 0; 602#if defined (INDENT_PARAGRAPHS_IN_TABLE) 603 inhibit_paragraph_indentation = 0; 604#else 605 inhibit_paragraph_indentation = 1; 606#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 607 608 current_indent += default_indentation_increment; 609 filling_enabled = indented_fill = 1; 610 611 if (html) 612 { 613 enum_html (); 614 in_paragraph = 0; 615 } 616 617 if (xml) 618 xml_begin_enumerate (enumeration_arg); 619 620 if (isdigit (*enumeration_arg)) 621 start_enumerating (atoi (enumeration_arg), ENUM_DIGITS); 622 else 623 start_enumerating (*enumeration_arg, ENUM_ALPHA); 624 break; 625 626 /* @group does nothing special in makeinfo. */ 627 case group: 628 /* Only close the paragraph if we are not inside of an 629 @example-like environment. */ 630 if (xml) 631 xml_insert_element (GROUP, START); 632 else if (!insertion_stack->next 633 || (insertion_stack->next->insertion != display 634 && insertion_stack->next->insertion != smalldisplay 635 && insertion_stack->next->insertion != example 636 && insertion_stack->next->insertion != smallexample 637 && insertion_stack->next->insertion != lisp 638 && insertion_stack->next->insertion != smalllisp 639 && insertion_stack->next->insertion != format 640 && insertion_stack->next->insertion != smallformat 641 && insertion_stack->next->insertion != flushleft 642 && insertion_stack->next->insertion != flushright)) 643 close_single_paragraph (); 644 break; 645 646 /* Insertions that are no-ops in info, but do something in TeX. */ 647 case cartouche: 648 case ifclear: 649 case ifhtml: 650 case ifinfo: 651 case ifnothtml: 652 case ifnotinfo: 653 case ifnotplaintext: 654 case ifnottex: 655 case ifnotxml: 656 case ifplaintext: 657 case ifset: 658 case iftex: 659 case ifxml: 660 case rawtex: 661 if (in_menu) 662 no_discard++; 663 break; 664 665 case rawhtml: 666 escape_html = 0; 667 break; 668 669 case defcv: 670 case deffn: 671 case defivar: 672 case defmac: 673 case defmethod: 674 case defop: 675 case defopt: 676 case defspec: 677 case deftp: 678 case deftypefn: 679 case deftypefun: 680 case deftypeivar: 681 case deftypemethod: 682 case deftypeop: 683 case deftypevar: 684 case deftypevr: 685 case defun: 686 case defvar: 687 case defvr: 688 inhibit_paragraph_indentation = 1; 689 filling_enabled = indented_fill = 1; 690 current_indent += default_indentation_increment; 691 no_indent = 0; 692 break; 693 694 case flushleft: 695 close_single_paragraph (); 696 inhibit_paragraph_indentation = 1; 697 filling_enabled = indented_fill = no_indent = 0; 698 if (html) 699 add_word ("<div align=\"left\">"); 700 break; 701 702 case flushright: 703 close_single_paragraph (); 704 filling_enabled = indented_fill = no_indent = 0; 705 inhibit_paragraph_indentation = 1; 706 force_flush_right++; 707 if (html) 708 add_word ("<div align=\"right\">"); 709 break; 710 711 default: 712 line_error ("begin_insertion internal error: type=%d", type); 713 714 } 715 716 if (!no_discard) 717 discard_until ("\n"); 718} 719 720/* Try to end the insertion with the specified TYPE. With a value of 721 `bad_type', TYPE gets translated to match the value currently on top 722 of the stack. Otherwise, if TYPE doesn't match the top of the 723 insertion stack, give error. */ 724void 725end_insertion (type) 726 enum insertion_type type; 727{ 728 enum insertion_type temp_type; 729 730 if (!insertion_level) 731 return; 732 733 temp_type = current_insertion_type (); 734 735 if (type == bad_type) 736 type = temp_type; 737 738 if (type != temp_type) 739 { 740 line_error 741 (_("`@end' expected `%s', but saw `%s'"), 742 insertion_type_pname (temp_type), insertion_type_pname (type)); 743 return; 744 } 745 746 pop_insertion (); 747 748 if (xml) 749 { 750 switch (type) 751 { 752 case ifinfo: 753 case documentdescription: 754 break; 755 case copying: 756 xml_insert_element (COPYING, END); 757 break; 758 case quotation: 759 xml_insert_element (QUOTATION, END); 760 break; 761 case example: 762 xml_insert_element (EXAMPLE, END); 763 break; 764 case smallexample: 765 xml_insert_element (SMALLEXAMPLE, END); 766 break; 767 case lisp: 768 xml_insert_element (LISP, END); 769 break; 770 case smalllisp: 771 xml_insert_element (SMALLLISP, END); 772 break; 773 case cartouche: 774 xml_insert_element (CARTOUCHE, END); 775 break; 776 case format: 777 if (docbook && xml_in_bookinfo && xml_in_abstract) 778 { 779 xml_insert_element (ABSTRACT, END); 780 xml_in_abstract = 0; 781 } 782 else 783 xml_insert_element (FORMAT, END); 784 break; 785 case smallformat: 786 xml_insert_element (SMALLFORMAT, END); 787 break; 788 case display: 789 xml_insert_element (DISPLAY, END); 790 break; 791 case smalldisplay: 792 xml_insert_element (SMALLDISPLAY, END); 793 break; 794 case table: 795 case ftable: 796 case vtable: 797 case itemize: 798 xml_end_table (type); 799 break; 800 case enumerate: 801 xml_end_enumerate (type); 802 break; 803 case group: 804 xml_insert_element (GROUP, END); 805 break; 806 } 807 } 808 switch (type) 809 { 810 /* Insertions which have no effect on paragraph formatting. */ 811 case copying: 812 case documentdescription: 813 case ifclear: 814 case ifinfo: 815 case ifhtml: 816 case ifnothtml: 817 case ifnotinfo: 818 case ifnotplaintext: 819 case ifnottex: 820 case ifnotxml: 821 case ifplaintext: 822 case ifset: 823 case iftex: 824 case ifxml: 825 case rawtex: 826 break; 827 828 case rawhtml: 829 escape_html = 1; 830 break; 831 832 case detailmenu: 833 in_detailmenu--; /* No longer hacking menus. */ 834 if (!in_menu) 835 { 836 if (!no_headers) 837 close_insertion_paragraph (); 838 } 839 break; 840 841 case direntry: /* Eaten if html. */ 842 insert_string ("END-INFO-DIR-ENTRY\n\n"); 843 close_insertion_paragraph (); 844 break; 845 846 case menu: 847 in_menu--; /* No longer hacking menus. */ 848 if (html) 849 add_word ("</ul>\n"); 850 else if (!no_headers) 851 close_insertion_paragraph (); 852 break; 853 854 case multitable: 855 end_multitable (); 856 break; 857 858 case enumerate: 859 stop_enumerating (); 860 close_insertion_paragraph (); 861 current_indent -= default_indentation_increment; 862 if (html) 863 add_word ("</ol>\n"); 864 break; 865 866 case flushleft: 867 if (html) 868 add_word ("</div>\n"); 869 close_insertion_paragraph (); 870 break; 871 872 case group: 873 case cartouche: 874 close_insertion_paragraph (); 875 break; 876 877 case format: 878 case smallformat: 879 case display: 880 case smalldisplay: 881 case example: 882 case smallexample: 883 case lisp: 884 case smalllisp: 885 case quotation: 886 /* @format and @smallformat are the only fixed_width insertion 887 without a change in indentation. */ 888 if (type != format && type != smallformat) 889 current_indent -= default_indentation_increment; 890 891 if (html) 892 add_word (type == quotation ? "</blockquote>\n" : "</pre>\n"); 893 894 /* The ending of one of these insertions always marks the 895 start of a new paragraph. */ 896 close_insertion_paragraph (); 897 break; 898 899 case table: 900 case ftable: 901 case vtable: 902 current_indent -= default_indentation_increment; 903 if (html) 904 add_word ("</dl>\n"); 905 close_insertion_paragraph (); 906 break; 907 908 case itemize: 909 current_indent -= default_indentation_increment; 910 if (html) 911 add_word ("</ul>\n"); 912 close_insertion_paragraph (); 913 break; 914 915 case flushright: 916 force_flush_right--; 917 if (html) 918 add_word ("</div>\n"); 919 close_insertion_paragraph (); 920 break; 921 922 /* Handle the @defun insertions with this default clause. */ 923 default: 924 { 925 enum insertion_type base_type; 926 927 if (type < defcv || type > defvr) 928 line_error ("end_insertion internal error: type=%d", type); 929 930 base_type = get_base_type (type); 931 switch (base_type) 932 { 933 case deffn: 934 case defvr: 935 case deftp: 936 case deftypefn: 937 case deftypevr: 938 case defcv: 939 case defop: 940 case deftypemethod: 941 case deftypeop: 942 case deftypeivar: 943 if (html) 944 /* close the tables which has been opened in defun.c */ 945 add_word ("</td></tr>\n</table>\n"); 946 break; 947 } /* switch (base_type)... */ 948 949 current_indent -= default_indentation_increment; 950 close_insertion_paragraph (); 951 } 952 break; 953 954 } 955 956 if (current_indent < 0) 957 line_error ("end_insertion internal error: current indent=%d", 958 current_indent); 959} 960 961/* Insertions cannot cross certain boundaries, such as node beginnings. In 962 code that creates such boundaries, you should call `discard_insertions' 963 before doing anything else. It prints the errors for you, and cleans up 964 the insertion stack. 965 966 With nonzero SPECIALS_OK argument, allows unmatched 967 @if... conditionals, otherwise not. This is because conditionals can 968 cross node boundaries. Always happens with the @top node, for example. */ 969void 970discard_insertions (specials_ok) 971 int specials_ok; 972{ 973 int real_line_number = line_number; 974 while (insertion_stack) 975 { 976 if (specials_ok 977 && ((ifclear <= insertion_stack->insertion 978 && insertion_stack->insertion <= iftex) 979 || insertion_stack->insertion == rawhtml 980 || insertion_stack->insertion == rawtex)) 981 break; 982 else 983 { 984 char *offender = insertion_type_pname (insertion_stack->insertion); 985 986 file_line_error (insertion_stack->filename, 987 insertion_stack->line_number, 988 _("No matching `%cend %s'"), COMMAND_PREFIX, 989 offender); 990 pop_insertion (); 991 } 992 } 993 line_number = real_line_number; 994} 995 996/* Insertion (environment) commands. */ 997 998void 999cm_quotation () 1000{ 1001 if (xml) 1002 xml_insert_element (QUOTATION, START); 1003 begin_insertion (quotation); 1004} 1005 1006void 1007cm_example () 1008{ 1009 if (xml) 1010 xml_insert_element (EXAMPLE, START); 1011 begin_insertion (example); 1012} 1013 1014void 1015cm_smallexample () 1016{ 1017 if (xml) 1018 xml_insert_element (SMALLEXAMPLE, START); 1019 begin_insertion (smallexample); 1020} 1021 1022void 1023cm_lisp () 1024{ 1025 if (xml) 1026 xml_insert_element (LISP, START); 1027 begin_insertion (lisp); 1028} 1029 1030void 1031cm_smalllisp () 1032{ 1033 if (xml) 1034 xml_insert_element (SMALLLISP, START); 1035 begin_insertion (smalllisp); 1036} 1037 1038void 1039cm_cartouche () 1040{ 1041 if (xml) 1042 xml_insert_element (CARTOUCHE, START); 1043 begin_insertion (cartouche); 1044} 1045 1046void 1047cm_copying () 1048{ 1049 if (xml) 1050 xml_insert_element (COPYING, START); 1051 begin_insertion (copying); 1052} 1053 1054/* Not an insertion, despite the name, but it goes with cm_copying. */ 1055void 1056cm_insert_copying () 1057{ 1058 if (copying_text) 1059 { /* insert_string rather than add_word because we've already done 1060 full expansion on copying_text when we saved it. */ 1061 insert_string (copying_text); 1062 insert ('\n'); 1063 1064 /* Update output_position so that the node positions in the tag 1065 tables will take account of the copying text. */ 1066 flush_output (); 1067 } 1068} 1069 1070void 1071cm_format () 1072{ 1073 if (xml) 1074 { 1075 if (docbook && xml_in_bookinfo) 1076 { 1077 xml_insert_element (ABSTRACT, START); 1078 xml_in_abstract = 1; 1079 } 1080 else 1081 xml_insert_element (FORMAT, START); 1082 } 1083 begin_insertion (format); 1084} 1085 1086void 1087cm_smallformat () 1088{ 1089 if (xml) 1090 xml_insert_element (SMALLFORMAT, START); 1091 begin_insertion (smallformat); 1092} 1093 1094void 1095cm_display () 1096{ 1097 if (xml) 1098 xml_insert_element (DISPLAY, START); 1099 begin_insertion (display); 1100} 1101 1102void 1103cm_smalldisplay () 1104{ 1105 if (xml) 1106 xml_insert_element (SMALLDISPLAY, START); 1107 begin_insertion (smalldisplay); 1108} 1109 1110void 1111cm_direntry () 1112{ 1113 if (html || xml) 1114 command_name_condition (); 1115 else 1116 begin_insertion (direntry); 1117} 1118 1119void 1120cm_documentdescription () 1121{ 1122 if (html || xml) 1123 begin_insertion (documentdescription); 1124 else 1125 command_name_condition (); 1126} 1127 1128 1129void 1130cm_itemize () 1131{ 1132 begin_insertion (itemize); 1133} 1134 1135/* Start an enumeration insertion of type TYPE. If the user supplied 1136 no argument on the line, then use DEFAULT_STRING as the initial string. */ 1137static void 1138do_enumeration (type, default_string) 1139 int type; 1140 char *default_string; 1141{ 1142 get_until_in_line (0, ".", &enumeration_arg); 1143 canon_white (enumeration_arg); 1144 1145 if (!*enumeration_arg) 1146 { 1147 free (enumeration_arg); 1148 enumeration_arg = xstrdup (default_string); 1149 } 1150 1151 if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg)) 1152 { 1153 warning (_("%s requires letter or digit"), insertion_type_pname (type)); 1154 1155 switch (type) 1156 { 1157 case enumerate: 1158 default_string = "1"; 1159 break; 1160 } 1161 enumeration_arg = xstrdup (default_string); 1162 } 1163 begin_insertion (type); 1164} 1165 1166void 1167cm_enumerate () 1168{ 1169 do_enumeration (enumerate, "1"); 1170} 1171 1172/* Handle verbatim environment: 1173 find_end_verbatim == 0: process until end of file 1174 find_end_verbatim != 0: process until 'COMMAND_PREFIXend verbatim' 1175 or end of file 1176 1177 We cannot simply copy input stream onto output stream; as the 1178 verbatim environment may be encapsulated in an @example environment, 1179 for example. */ 1180void 1181handle_verbatim_environment (find_end_verbatim) 1182 int find_end_verbatim; 1183{ 1184 int character; 1185 int seen_end = 0; 1186 int save_filling_enabled = filling_enabled; 1187 int save_inhibit_paragraph_indentation = inhibit_paragraph_indentation; 1188 1189 close_single_paragraph (); 1190 inhibit_paragraph_indentation = 1; 1191 filling_enabled = 0; 1192 in_fixed_width_font++; 1193 last_char_was_newline = 0; 1194 1195 /* No indentation: this is verbatim after all 1196 If you want indent, enclose @verbatim in @example 1197 current_indent += default_indentation_increment; 1198 */ 1199 1200 if (html) 1201 add_word ("<pre class=\"verbatim\">"); 1202 1203 while (input_text_offset < input_text_length) 1204 { 1205 character = curchar (); 1206 1207 if (character == '\n') 1208 line_number++; 1209 /* 1210 Assume no newlines in END_VERBATIM 1211 */ 1212 else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */ 1213 && (input_text_length - input_text_offset > sizeof (END_VERBATIM)) 1214 && !strncmp (&input_text[input_text_offset+1], END_VERBATIM, 1215 sizeof (END_VERBATIM)-1)) 1216 { 1217 input_text_offset += sizeof (END_VERBATIM); 1218 seen_end = 1; 1219 break; 1220 } 1221 1222 if (html && character == '&' && escape_html) 1223 add_word ("&"); 1224 else if (html && character == '<' && escape_html) 1225 add_word ("<"); 1226 else 1227 add_char (character); 1228 1229 input_text_offset++; 1230 } 1231 1232 if (find_end_verbatim && !seen_end) 1233 warning (_("end of file inside verbatim block")); 1234 1235 if (html) 1236 add_word ("</pre>"); 1237 1238 in_fixed_width_font--; 1239 filling_enabled = save_filling_enabled; 1240 inhibit_paragraph_indentation = save_inhibit_paragraph_indentation; 1241} 1242 1243void 1244cm_verbatim () 1245{ 1246 handle_verbatim_environment (1); 1247} 1248 1249void 1250cm_table () 1251{ 1252 begin_insertion (table); 1253} 1254 1255void 1256cm_multitable () 1257{ 1258 begin_insertion (multitable); /* @@ */ 1259} 1260 1261void 1262cm_ftable () 1263{ 1264 begin_insertion (ftable); 1265} 1266 1267void 1268cm_vtable () 1269{ 1270 begin_insertion (vtable); 1271} 1272 1273void 1274cm_group () 1275{ 1276 begin_insertion (group); 1277} 1278 1279/* Insert raw HTML (no escaping of `<' etc.). */ 1280void 1281cm_html () 1282{ 1283 if (process_html || process_xml) 1284 begin_insertion (rawhtml); 1285 else 1286 command_name_condition (); 1287} 1288 1289void 1290cm_ifhtml () 1291{ 1292 if (process_html) 1293 begin_insertion (ifhtml); 1294 else 1295 command_name_condition (); 1296} 1297 1298void 1299cm_ifnothtml () 1300{ 1301 if (!process_html) 1302 begin_insertion (ifnothtml); 1303 else 1304 command_name_condition (); 1305} 1306 1307 1308void 1309cm_ifinfo () 1310{ 1311 if (process_info) 1312 begin_insertion (ifinfo); 1313 else 1314 command_name_condition (); 1315} 1316 1317void 1318cm_ifnotinfo () 1319{ 1320 if (!process_info) 1321 begin_insertion (ifnotinfo); 1322 else 1323 command_name_condition (); 1324} 1325 1326 1327void 1328cm_ifplaintext () 1329{ 1330 if (process_plaintext) 1331 begin_insertion (ifplaintext); 1332 else 1333 command_name_condition (); 1334} 1335 1336void 1337cm_ifnotplaintext () 1338{ 1339 if (!process_plaintext) 1340 begin_insertion (ifnotplaintext); 1341 else 1342 command_name_condition (); 1343} 1344 1345 1346void 1347cm_tex () 1348{ 1349 if (process_tex) 1350 begin_insertion (rawtex); 1351 else 1352 command_name_condition (); 1353} 1354 1355void 1356cm_iftex () 1357{ 1358 if (process_tex) 1359 begin_insertion (iftex); 1360 else 1361 command_name_condition (); 1362} 1363 1364void 1365cm_ifnottex () 1366{ 1367 if (!process_tex) 1368 begin_insertion (ifnottex); 1369 else 1370 command_name_condition (); 1371} 1372 1373void 1374cm_ifxml () 1375{ 1376 if (process_xml) 1377 begin_insertion (ifxml); 1378 else 1379 command_name_condition (); 1380} 1381 1382void 1383cm_ifnotxml () 1384{ 1385 if (!process_xml) 1386 begin_insertion (ifnotxml); 1387 else 1388 command_name_condition (); 1389} 1390 1391 1392/* Begin an insertion where the lines are not filled or indented. */ 1393void 1394cm_flushleft () 1395{ 1396 begin_insertion (flushleft); 1397} 1398 1399/* Begin an insertion where the lines are not filled, and each line is 1400 forced to the right-hand side of the page. */ 1401void 1402cm_flushright () 1403{ 1404 begin_insertion (flushright); 1405} 1406 1407void 1408cm_menu () 1409{ 1410 if (current_node == NULL) 1411 { 1412 warning (_("@menu seen before first @node, creating `Top' node")); 1413 warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?")); 1414 /* Include @top command so we can construct the implicit node tree. */ 1415 execute_string ("@node top\n@top Top\n"); 1416 } 1417 begin_insertion (menu); 1418} 1419 1420void 1421cm_detailmenu () 1422{ 1423 if (current_node == NULL) 1424 { /* Problems anyway, @detailmenu should always be inside @menu. */ 1425 warning (_("@detailmenu seen before first node, creating `Top' node")); 1426 execute_string ("@node top\n@top Top\n"); 1427 } 1428 begin_insertion (detailmenu); 1429} 1430 1431/* End existing insertion block. */ 1432void 1433cm_end () 1434{ 1435 char *temp; 1436 enum insertion_type type; 1437 1438 if (!insertion_level) 1439 { 1440 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command); 1441 return; 1442 } 1443 1444 get_rest_of_line (0, &temp); 1445 1446 if (temp[0] == 0) 1447 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command); 1448 1449 type = find_type_from_name (temp); 1450 1451 if (type == bad_type) 1452 { 1453 line_error (_("Bad argument to `%s', `%s', using `%s'"), 1454 command, temp, insertion_type_pname (current_insertion_type ())); 1455 } 1456 if (xml && type == menu) /* fixme */ 1457 { 1458 xml_end_menu (); 1459 } 1460 end_insertion (type); 1461 free (temp); 1462} 1463 1464/* @itemx, @item. */ 1465 1466static int itemx_flag = 0; 1467 1468/* Return whether CMD takes a brace-delimited {arg}. */ 1469/*static */int 1470command_needs_braces (cmd) 1471 char *cmd; 1472{ 1473 int i; 1474 for (i = 0; command_table[i].name; i++) 1475 { 1476 if (STREQ (command_table[i].name, cmd)) 1477 return command_table[i].argument_in_braces == BRACE_ARGS; 1478 } 1479 1480 return 0; /* macro or alias */ 1481} 1482 1483 1484void 1485cm_item () 1486{ 1487 char *rest_of_line, *item_func; 1488 1489 /* Can only hack "@item" while inside of an insertion. */ 1490 if (insertion_level) 1491 { 1492 INSERTION_ELT *stack = insertion_stack; 1493 int original_input_text_offset; 1494 1495 skip_whitespace (); 1496 original_input_text_offset = input_text_offset; 1497 1498 get_rest_of_line (0, &rest_of_line); 1499 item_func = current_item_function (); 1500 1501 /* Do the right thing depending on which insertion function is active. */ 1502 switch_top: 1503 switch (stack->insertion) 1504 { 1505 case multitable: 1506 multitable_item (); 1507 /* Support text directly after the @item. */ 1508 if (*rest_of_line) 1509 { 1510 line_number--; 1511 input_text_offset = original_input_text_offset; 1512 } 1513 break; 1514 1515 case ifclear: 1516 case ifhtml: 1517 case ifinfo: 1518 case ifnothtml: 1519 case ifnotinfo: 1520 case ifnotplaintext: 1521 case ifnottex: 1522 case ifnotxml: 1523 case ifplaintext: 1524 case ifset: 1525 case iftex: 1526 case ifxml: 1527 case rawhtml: 1528 case rawtex: 1529 case tex: 1530 case cartouche: 1531 stack = stack->next; 1532 if (!stack) 1533 goto no_insertion; 1534 else 1535 goto switch_top; 1536 break; 1537 1538 case menu: 1539 case quotation: 1540 case example: 1541 case smallexample: 1542 case lisp: 1543 case smalllisp: 1544 case format: 1545 case smallformat: 1546 case display: 1547 case smalldisplay: 1548 case group: 1549 line_error (_("@%s not meaningful inside `@%s' block"), 1550 command, 1551 insertion_type_pname (current_insertion_type ())); 1552 break; 1553 1554 case itemize: 1555 case enumerate: 1556 if (itemx_flag) 1557 { 1558 line_error (_("@itemx not meaningful inside `%s' block"), 1559 insertion_type_pname (current_insertion_type ())); 1560 } 1561 else 1562 { 1563 if (html) 1564 { 1565 if (in_paragraph) 1566 { 1567 add_word ("</p>"); 1568 in_paragraph = 0; 1569 } 1570 add_word ("<li>"); 1571 } 1572 else if (xml) 1573 xml_begin_item (); 1574 else 1575 { 1576 start_paragraph (); 1577 kill_self_indent (-1); 1578 filling_enabled = indented_fill = 1; 1579 1580 if (current_item_function ()) 1581 { 1582 output_column = current_indent - 2; 1583 indent (output_column); 1584 1585 /* The item marker can be given with or without 1586 braces -- @bullet and @bullet{} are both ok. 1587 Or it might be something that doesn't take 1588 braces at all, such as "o" or "#" or "@ ". 1589 Thus, only supply braces if the item marker is 1590 a command, they haven't supplied braces 1591 themselves, and we know it needs them. */ 1592 if (item_func && *item_func) 1593 { 1594 if (*item_func == COMMAND_PREFIX 1595 && item_func[strlen (item_func) - 1] != '}' 1596 && command_needs_braces (item_func + 1)) 1597 execute_string ("%s{}", item_func); 1598 else 1599 execute_string ("%s", item_func); 1600 } 1601 insert (' '); 1602 output_column++; 1603 } 1604 else 1605 enumerate_item (); 1606 1607 /* Special hack. This makes `close_paragraph' a no-op until 1608 `start_paragraph' has been called. */ 1609 must_start_paragraph = 1; 1610 } 1611 1612 /* Handle text directly after the @item. */ 1613 if (*rest_of_line) 1614 { 1615 line_number--; 1616 input_text_offset = original_input_text_offset; 1617 } 1618 } 1619 break; 1620 1621 case table: 1622 case ftable: 1623 case vtable: 1624 if (html) 1625 { 1626 static int last_html_output_position = 0; 1627 1628 /* If nothing has been output since the last <dd>, 1629 remove the empty <dd> element. Some browsers render 1630 an extra empty line for <dd><dt>, which makes @itemx 1631 conversion look ugly. */ 1632 if (last_html_output_position == output_position 1633 && strncmp ((char *) output_paragraph, "<dd>", 1634 output_paragraph_offset) == 0) 1635 output_paragraph_offset = 0; 1636 1637 /* Force the browser to render one blank line before 1638 each new @item in a table. But don't do that if 1639 this is the first <dt> after the <dl>, or if we are 1640 converting @itemx. 1641 1642 Note that there are some browsers which ignore <br> 1643 in this context, but I cannot find any way to force 1644 them all render exactly one blank line. */ 1645 if (!itemx_flag 1646 && strncmp ((char *) output_paragraph 1647 + output_paragraph_offset - sizeof (dl_tag) + 1, 1648 dl_tag, sizeof (dl_tag) - 1) != 0) 1649 add_word ("<br>"); 1650 1651 add_word ("<dt>"); 1652 if (item_func && *item_func) 1653 execute_string ("%s{%s}", item_func, rest_of_line); 1654 else 1655 execute_string ("%s", rest_of_line); 1656 1657 if (current_insertion_type () == ftable) 1658 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 1659 1660 if (current_insertion_type () == vtable) 1661 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 1662 /* Make sure output_position is updated, so we could 1663 remember it. */ 1664 close_single_paragraph (); 1665 last_html_output_position = output_position; 1666 add_word ("<dd>"); 1667 } 1668 else if (xml) /* && docbook)*/ /* 05-08 */ 1669 { 1670 xml_begin_table_item (); 1671 if (item_func && *item_func) 1672 execute_string ("%s{%s}", item_func, rest_of_line); 1673 else 1674 execute_string ("%s", rest_of_line); 1675 xml_continue_table_item (); 1676 } 1677 else 1678 { 1679 /* We need this to determine if we have two @item's in a row 1680 (see test just below). */ 1681 static int last_item_output_position = 0; 1682 1683 /* Get rid of extra characters. */ 1684 kill_self_indent (-1); 1685 1686 /* If we have one @item followed directly by another @item, 1687 we need to insert a blank line. This is not true for 1688 @itemx, though. */ 1689 if (!itemx_flag && last_item_output_position == output_position) 1690 insert ('\n'); 1691 1692 /* `close_paragraph' almost does what we want. The problem 1693 is when paragraph_is_open, and last_char_was_newline, and 1694 the last newline has been turned into a space, because 1695 filling_enabled. I handle it here. */ 1696 if (last_char_was_newline && filling_enabled && 1697 paragraph_is_open) 1698 insert ('\n'); 1699 close_paragraph (); 1700 1701#if defined (INDENT_PARAGRAPHS_IN_TABLE) 1702 /* Indent on a new line, but back up one indentation level. */ 1703 { 1704 int save = inhibit_paragraph_indentation; 1705 inhibit_paragraph_indentation = 1; 1706 /* At this point, inserting any non-whitespace character will 1707 force the existing indentation to be output. */ 1708 add_char ('i'); 1709 inhibit_paragraph_indentation = save; 1710 } 1711#else /* !INDENT_PARAGRAPHS_IN_TABLE */ 1712 add_char ('i'); 1713#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 1714 1715 output_paragraph_offset--; 1716 kill_self_indent (default_indentation_increment + 1); 1717 1718 /* Add item's argument to the line. */ 1719 filling_enabled = 0; 1720 if (item_func && *item_func) 1721 execute_string ("%s{%s}", item_func, rest_of_line); 1722 else 1723 execute_string ("%s", rest_of_line); 1724 1725 if (current_insertion_type () == ftable) 1726 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 1727 else if (current_insertion_type () == vtable) 1728 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 1729 1730 /* Start a new line, and let start_paragraph () 1731 do the indenting of it for you. */ 1732 close_single_paragraph (); 1733 indented_fill = filling_enabled = 1; 1734 last_item_output_position = output_position; 1735 } 1736 } 1737 free (rest_of_line); 1738 } 1739 else 1740 { 1741 no_insertion: 1742 line_error (_("%c%s found outside of an insertion block"), 1743 COMMAND_PREFIX, command); 1744 } 1745} 1746 1747void 1748cm_itemx () 1749{ 1750 itemx_flag++; 1751 cm_item (); 1752 itemx_flag--; 1753} 1754