156160Sru/* insertion.c -- insertions for Texinfo. 2146515Sru $Id: insertion.c,v 1.55 2004/11/11 18:34:28 karl Exp $ 356160Sru 4146515Sru Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software 5114472Sru Foundation, Inc. 656160Sru 756160Sru This program is free software; you can redistribute it and/or modify 856160Sru it under the terms of the GNU General Public License as published by 956160Sru the Free Software Foundation; either version 2, or (at your option) 1056160Sru any later version. 1156160Sru 1256160Sru This program is distributed in the hope that it will be useful, 1356160Sru but WITHOUT ANY WARRANTY; without even the implied warranty of 1456160Sru MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1556160Sru GNU General Public License for more details. 1656160Sru 1756160Sru You should have received a copy of the GNU General Public License 1856160Sru along with this program; if not, write to the Free Software Foundation, 1956160Sru Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2056160Sru 2156160Sru#include "system.h" 2256160Sru#include "cmds.h" 2356160Sru#include "defun.h" 24146515Sru#include "float.h" 25146515Sru#include "html.h" 2656160Sru#include "insertion.h" 2756160Sru#include "macro.h" 2856160Sru#include "makeinfo.h" 29146515Sru#include "multi.h" 3093139Sru#include "xml.h" 3156160Sru 3256160Sru/* Must match list in insertion.h. */ 3356160Srustatic char *insertion_type_names[] = 3493139Sru{ 35100513Sru "cartouche", "copying", "defcv", "deffn", "defivar", "defmac", 36146515Sru "defmethod", "defop", "defopt", "defspec", "deftp", "deftypecv", 37146515Sru "deftypefn", "deftypefun", "deftypeivar", "deftypemethod", 38146515Sru "deftypeop", "deftypevar", "deftypevr", "defun", "defvar", "defvr", 39146515Sru "detailmenu", "direntry", "display", "documentdescription", 40146515Sru "enumerate", "example", "float", "flushleft", "flushright", "format", 41146515Sru "ftable", "group", "ifclear", "ifdocbook", "ifhtml", "ifinfo", 42146515Sru "ifnotdocbook", "ifnothtml", "ifnotinfo", "ifnotplaintext", "ifnottex", 43146515Sru "ifnotxml", "ifplaintext", "ifset", "iftex", "ifxml", "itemize", "lisp", 44146515Sru "menu", "multitable", "quotation", "rawdocbook", "rawhtml", "rawtex", 45146515Sru "rawxml", "smalldisplay", "smallexample", "smallformat", "smalllisp", 46146515Sru "verbatim", "table", "tex", "vtable", "titlepage", "bad_type" 4756160Sru}; 4856160Sru 4956160Sru/* All nested environments. */ 5056160SruINSERTION_ELT *insertion_stack = NULL; 5156160Sru 5256160Sru/* How deeply we're nested. */ 5356160Sruint insertion_level = 0; 5456160Sru 55100513Sru/* Set to 1 if we've processed (commentary) text in a @menu that 56100513Sru wasn't part of a menu item. */ 57100513Sruint had_menu_commentary; 5856160Sru 5956160Sru/* How to examine menu lines. */ 6056160Sruint in_detailmenu = 0; 6156160Sru 62100513Sru/* Whether to examine menu lines. */ 63100513Sruint in_menu = 0; 6456160Sru 6556160Sru/* Set to 1 if <p> is written in normal context. 6656160Sru Used for menu and itemize. */ 6756160Sruint in_paragraph = 0; 6856160Sru 69146515Sru/* Since an insertion is already in the stack before we reach the switch 70146515Sru statement, we cannot use is_in_insertion_of_type (always returns true.) Also 71146515Sru making it return the level found, and comparing it with the current level is 72146515Sru no use, due to the order of stack. */ 73146515Srustatic int float_active = 0; 74100513Sru 75146515Sru/* Unsetting escape_html blindly causes text inside @html/etc. to be escaped if 76146515Sru used within a rmacro. */ 77146515Srustatic int raw_output_block = 0; 78146515Sru 79146515Sru/* Non-zero if a <dl> element has a <dt> element in it. We use this when 80146515Sru deciding whether to insert a <br> or not. */ 81146515Srustatic int html_deflist_has_term = 0; 8256160Sru 8356160Sruvoid 84146515Sruinit_insertion_stack (void) 8556160Sru{ 8656160Sru insertion_stack = NULL; 8756160Sru} 8856160Sru 8956160Sru/* Return the type of the current insertion. */ 9056160Srustatic enum insertion_type 91146515Srucurrent_insertion_type (void) 9256160Sru{ 9356160Sru return insertion_level ? insertion_stack->insertion : bad_type; 9456160Sru} 9556160Sru 9656160Sru/* Return the string which is the function to wrap around items, or NULL 9756160Sru if we're not in an environment where @item is ok. */ 9856160Srustatic char * 99146515Srucurrent_item_function (void) 10056160Sru{ 10156160Sru int done = 0; 10256160Sru INSERTION_ELT *elt = insertion_stack; 10356160Sru 10456160Sru /* Skip down through the stack until we find an insertion with an 10556160Sru itemize function defined, i.e., skip conditionals, @cartouche, etc. */ 10656160Sru while (!done && elt) 10756160Sru { 10856160Sru switch (elt->insertion) 10956160Sru { 11056160Sru /* This list should match the one in cm_item. */ 11156160Sru case ifclear: 11256160Sru case ifhtml: 11356160Sru case ifinfo: 11456160Sru case ifnothtml: 11556160Sru case ifnotinfo: 116100513Sru case ifnotplaintext: 11756160Sru case ifnottex: 118114472Sru case ifnotxml: 119100513Sru case ifplaintext: 12056160Sru case ifset: 12156160Sru case iftex: 122114472Sru case ifxml: 123146515Sru case rawdocbook: 12456160Sru case rawhtml: 125146515Sru case rawxml: 12656160Sru case rawtex: 12756160Sru case tex: 12856160Sru case cartouche: 129114472Sru elt = elt->next; 130114472Sru break; 13156160Sru 13256160Sru default: 13356160Sru done = 1; 13456160Sru } 13556160Sru } 13656160Sru 13756160Sru /* item_function usually gets assigned the empty string. */ 13856160Sru return done && (*elt->item_function) ? elt->item_function : NULL; 13956160Sru} 14056160Sru 14156160Sru/* Parse the item marker function off the input. If result is just "@", 14256160Sru change it to "@ ", since "@" by itself is not a command. This makes 14356160Sru "@ ", "@\t", and "@\n" all the same, but their default meanings are 14456160Sru the same anyway, and let's not worry about supporting redefining them. */ 145146515Srustatic char * 146146515Sruget_item_function (void) 14756160Sru{ 14856160Sru char *item_function; 149116525Sru char *item_loc; 150116525Sru 15156160Sru get_rest_of_line (0, &item_function); 15256160Sru 153116525Sru /* If the document erroneously says 154116525Sru @itemize @bullet @item foobar 155116525Sru it's nicer to give an error up front than repeat `@bullet expected 156116525Sru braces' until we get a segmentation fault. */ 157116525Sru item_loc = strstr (item_function, "@item"); 158116525Sru if (item_loc) 159116525Sru { 160116525Sru line_error (_("@item not allowed in argument to @itemize")); 161116525Sru *item_loc = 0; 162116525Sru } 163116525Sru 16456160Sru /* If we hit the end of text in get_rest_of_line, backing up 16556160Sru input pointer will cause the last character of the last line 16656160Sru be pushed back onto the input, which is wrong. */ 16756160Sru if (input_text_offset < input_text_length) 16856160Sru backup_input_pointer (); 16956160Sru 17056160Sru if (STREQ (item_function, "@")) 17156160Sru { 17256160Sru free (item_function); 17356160Sru item_function = xstrdup ("@ "); 17456160Sru } 17556160Sru 17656160Sru return item_function; 17756160Sru} 17856160Sru 17956160Sru /* Push the state of the current insertion on the stack. */ 180146515Srustatic void 181146515Srupush_insertion (enum insertion_type type, char *item_function) 18256160Sru{ 18356160Sru INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT)); 18456160Sru 18556160Sru new->item_function = item_function; 18656160Sru new->filling_enabled = filling_enabled; 18756160Sru new->indented_fill = indented_fill; 18856160Sru new->insertion = type; 18956160Sru new->line_number = line_number; 19056160Sru new->filename = xstrdup (input_filename); 19156160Sru new->inhibited = inhibit_paragraph_indentation; 19256160Sru new->in_fixed_width_font = in_fixed_width_font; 19356160Sru new->next = insertion_stack; 19456160Sru insertion_stack = new; 19556160Sru insertion_level++; 19656160Sru} 19756160Sru 19856160Sru /* Pop the value on top of the insertion stack into the 19956160Sru global variables. */ 20056160Sruvoid 201146515Srupop_insertion (void) 20256160Sru{ 20356160Sru INSERTION_ELT *temp = insertion_stack; 20456160Sru 20556160Sru if (temp == NULL) 20656160Sru return; 20756160Sru 20856160Sru in_fixed_width_font = temp->in_fixed_width_font; 20956160Sru inhibit_paragraph_indentation = temp->inhibited; 21056160Sru filling_enabled = temp->filling_enabled; 21156160Sru indented_fill = temp->indented_fill; 21256160Sru free_and_clear (&(temp->item_function)); 21356160Sru free_and_clear (&(temp->filename)); 21456160Sru insertion_stack = insertion_stack->next; 21556160Sru free (temp); 21656160Sru insertion_level--; 21756160Sru} 21856160Sru 21956160Sru /* Return a pointer to the print name of this 22056160Sru enumerated type. */ 221146515Srustatic const char * 222146515Sruinsertion_type_pname (enum insertion_type type) 22356160Sru{ 22456160Sru if ((int) type < (int) bad_type) 225146515Sru { 226146515Sru if (type == rawdocbook) 227146515Sru return "docbook"; 228146515Sru else if (type == rawhtml) 229146515Sru return "html"; 230146515Sru else if (type == rawxml) 231146515Sru return "xml"; 232146515Sru else if (type == rawtex) 233146515Sru return "tex"; 234146515Sru else 235146515Sru return insertion_type_names[(int) type]; 236146515Sru } 23756160Sru else 23856160Sru return _("Broken-Type in insertion_type_pname"); 23956160Sru} 24056160Sru 24156160Sru/* Return the insertion_type associated with NAME. 24256160Sru If the type is not one of the known ones, return BAD_TYPE. */ 24356160Sruenum insertion_type 244146515Srufind_type_from_name (char *name) 24556160Sru{ 24656160Sru int index = 0; 24756160Sru while (index < (int) bad_type) 24856160Sru { 24956160Sru if (STREQ (name, insertion_type_names[index])) 25056160Sru return (enum insertion_type) index; 251146515Sru if (index == rawdocbook && STREQ (name, "docbook")) 252146515Sru return rawdocbook; 25356160Sru if (index == rawhtml && STREQ (name, "html")) 25456160Sru return rawhtml; 255146515Sru if (index == rawxml && STREQ (name, "xml")) 256146515Sru return rawxml; 25756160Sru if (index == rawtex && STREQ (name, "tex")) 25856160Sru return rawtex; 25956160Sru index++; 26056160Sru } 26156160Sru return bad_type; 26256160Sru} 26356160Sru 264146515Sru/* Simple function to query insertion_stack to see if we are inside a given 265146515Sru insertion type. */ 26656160Sruint 267146515Sruis_in_insertion_of_type (int type) 26856160Sru{ 269146515Sru INSERTION_ELT *temp = insertion_stack; 270146515Sru 271146515Sru if (!insertion_level) 272146515Sru return 0; 273146515Sru 274146515Sru while (temp) 275146515Sru { 276146515Sru if (temp->insertion == type) 277146515Sru return 1; 278146515Sru temp = temp->next; 279146515Sru } 280146515Sru 281146515Sru return 0; 282146515Sru} 283146515Sru 284146515Sru 285146515Srustatic int 286146515Srudefun_insertion (enum insertion_type type) 287146515Sru{ 28856160Sru return 0 28956160Sru || (type == defcv) 29056160Sru || (type == deffn) 29156160Sru || (type == defivar) 29256160Sru || (type == defmac) 29356160Sru || (type == defmethod) 29456160Sru || (type == defop) 29556160Sru || (type == defopt) 29656160Sru || (type == defspec) 29756160Sru || (type == deftp) 298146515Sru || (type == deftypecv) 29956160Sru || (type == deftypefn) 30056160Sru || (type == deftypefun) 30156160Sru || (type == deftypeivar) 30256160Sru || (type == deftypemethod) 30356160Sru || (type == deftypeop) 30456160Sru || (type == deftypevar) 30556160Sru || (type == deftypevr) 30656160Sru || (type == defun) 30756160Sru || (type == defvar) 30856160Sru || (type == defvr) 30956160Sru ; 31056160Sru} 31156160Sru 31256160Sru/* MAX_NS is the maximum nesting level for enumerations. I picked 100 31356160Sru which seemed reasonable. This doesn't control the number of items, 31456160Sru just the number of nested lists. */ 31556160Sru#define max_stack_depth 100 31656160Sru#define ENUM_DIGITS 1 31756160Sru#define ENUM_ALPHA 2 31856160Srutypedef struct { 31956160Sru int enumtype; 32056160Sru int enumval; 32156160Sru} DIGIT_ALPHA; 32256160Sru 32356160SruDIGIT_ALPHA enumstack[max_stack_depth]; 32456160Sruint enumstack_offset = 0; 32556160Sruint current_enumval = 1; 32656160Sruint current_enumtype = ENUM_DIGITS; 32756160Sruchar *enumeration_arg = NULL; 32856160Sru 329146515Srustatic void 330146515Srustart_enumerating (int at, int type) 33156160Sru{ 33256160Sru if ((enumstack_offset + 1) == max_stack_depth) 33356160Sru { 33456160Sru line_error (_("Enumeration stack overflow")); 33556160Sru return; 33656160Sru } 33756160Sru enumstack[enumstack_offset].enumtype = current_enumtype; 33856160Sru enumstack[enumstack_offset].enumval = current_enumval; 33956160Sru enumstack_offset++; 34056160Sru current_enumval = at; 34156160Sru current_enumtype = type; 34256160Sru} 34356160Sru 344146515Srustatic void 345146515Srustop_enumerating (void) 34656160Sru{ 34756160Sru --enumstack_offset; 34856160Sru if (enumstack_offset < 0) 34956160Sru enumstack_offset = 0; 35056160Sru 35156160Sru current_enumval = enumstack[enumstack_offset].enumval; 35256160Sru current_enumtype = enumstack[enumstack_offset].enumtype; 35356160Sru} 35456160Sru 35556160Sru/* Place a letter or digits into the output stream. */ 356146515Srustatic void 357146515Sruenumerate_item (void) 35856160Sru{ 35956160Sru char temp[10]; 36056160Sru 36156160Sru if (current_enumtype == ENUM_ALPHA) 36256160Sru { 36356160Sru if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1)) 36456160Sru { 36556160Sru current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A'); 36656160Sru warning (_("lettering overflow, restarting at %c"), current_enumval); 36756160Sru } 36856160Sru sprintf (temp, "%c. ", current_enumval); 36956160Sru } 37056160Sru else 37156160Sru sprintf (temp, "%d. ", current_enumval); 37256160Sru 37356160Sru indent (output_column += (current_indent - strlen (temp))); 37456160Sru add_word (temp); 37556160Sru current_enumval++; 37656160Sru} 37756160Sru 37856160Srustatic void 379146515Sruenum_html (void) 38056160Sru{ 38156160Sru char type; 38256160Sru int start; 38356160Sru 38456160Sru if (isdigit (*enumeration_arg)) 38556160Sru { 38656160Sru type = '1'; 38756160Sru start = atoi (enumeration_arg); 38856160Sru } 38956160Sru else if (isupper (*enumeration_arg)) 39056160Sru { 39156160Sru type = 'A'; 39256160Sru start = *enumeration_arg - 'A' + 1; 39356160Sru } 39456160Sru else 39556160Sru { 39656160Sru type = 'a'; 39756160Sru start = *enumeration_arg - 'a' + 1; 39856160Sru } 39956160Sru 400146515Sru add_html_block_elt_args ("<ol type=%c start=%d>\n", type, start); 40156160Sru} 40256160Sru 40356160Sru/* Conditionally parse based on the current command name. */ 40456160Sruvoid 405146515Srucommand_name_condition (void) 40656160Sru{ 40756160Sru char *discarder = xmalloc (8 + strlen (command)); 40856160Sru 40956160Sru sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command); 41056160Sru discard_until (discarder); 41156160Sru discard_until ("\n"); 41256160Sru 41356160Sru free (discarder); 41456160Sru} 41556160Sru 41656160Sru/* This is where the work for all the "insertion" style 41756160Sru commands is done. A huge switch statement handles the 41856160Sru various setups, and generic code is on both sides. */ 41956160Sruvoid 420146515Srubegin_insertion (enum insertion_type type) 42156160Sru{ 42256160Sru int no_discard = 0; 42356160Sru 42456160Sru if (defun_insertion (type)) 42556160Sru { 42656160Sru push_insertion (type, xstrdup ("")); 42756160Sru no_discard++; 42856160Sru } 42956160Sru else 43093139Sru { 43193139Sru push_insertion (type, get_item_function ()); 43293139Sru } 43356160Sru 43456160Sru switch (type) 43556160Sru { 43656160Sru case menu: 43756160Sru if (!no_headers) 43856160Sru close_paragraph (); 43956160Sru 44056160Sru filling_enabled = no_indent = 0; 44156160Sru inhibit_paragraph_indentation = 1; 44256160Sru 44356160Sru if (html) 44456160Sru { 44556160Sru had_menu_commentary = 1; 44656160Sru } 44793139Sru else if (!no_headers && !xml) 44856160Sru add_word ("* Menu:\n"); 44956160Sru 45093139Sru if (xml) 451114472Sru xml_insert_element (MENU, START); 452146515Sru else 453146515Sru in_fixed_width_font++; 454100513Sru 455100513Sru next_menu_item_number = 1; 45656160Sru in_menu++; 45756160Sru no_discard++; 45856160Sru break; 45956160Sru 46056160Sru case detailmenu: 46156160Sru if (!in_menu) 46256160Sru { 46356160Sru if (!no_headers) 46456160Sru close_paragraph (); 46556160Sru 46656160Sru filling_enabled = no_indent = 0; 46756160Sru inhibit_paragraph_indentation = 1; 46856160Sru 46956160Sru no_discard++; 47056160Sru } 47156160Sru 472146515Sru if (xml) 473146515Sru { 474146515Sru xml_insert_element (DETAILMENU, START); 475146515Sru skip_whitespace_and_newlines(); 476146515Sru } 477146515Sru else 478146515Sru in_fixed_width_font++; 479146515Sru 48056160Sru in_detailmenu++; 48156160Sru break; 48256160Sru 48356160Sru case direntry: 48493139Sru close_single_paragraph (); 48593139Sru filling_enabled = no_indent = 0; 48693139Sru inhibit_paragraph_indentation = 1; 48793139Sru insert_string ("START-INFO-DIR-ENTRY\n"); 48856160Sru break; 48956160Sru 49093139Sru case documentdescription: 49193139Sru { 49293139Sru char *desc; 49393139Sru int start_of_end; 49493139Sru int save_fixed_width; 49593139Sru 49693139Sru discard_until ("\n"); /* ignore the @documentdescription line */ 49793139Sru start_of_end = get_until ("\n@end documentdescription", &desc); 49893139Sru save_fixed_width = in_fixed_width_font; 49993139Sru 50093139Sru in_fixed_width_font = 0; 50193139Sru document_description = expansion (desc, 0); 50293139Sru free (desc); 50393139Sru 50493139Sru in_fixed_width_font = save_fixed_width; 50593139Sru input_text_offset = start_of_end; /* go back to the @end to match */ 50693139Sru } 50793139Sru break; 50893139Sru 509100513Sru case copying: 510100513Sru /* Save the copying text away for @insertcopying, 511100513Sru typically used on the back of the @titlepage (for TeX) and 512100513Sru the Top node (for info/html). */ 513146515Sru if (input_text[input_text_offset] != '\n') 514100513Sru discard_until ("\n"); /* ignore remainder of @copying line */ 515100513Sru 516146515Sru input_text_offset = get_until ("\n@end copying", ©ing_text); 517146515Sru canon_white (copying_text); 518100513Sru 519100513Sru /* For info, output the copying text right away, so it will end up 520100513Sru in the header of the Info file, before the first node, and thus 521100513Sru get copied automatically to all the split files. For xml, also 522100513Sru output it right away since xml output is never split. 523100513Sru For html, we output it specifically in html_output_head. 524100513Sru For plain text, there's no way to hide it, so the author must 525100513Sru use @insertcopying in the desired location. */ 526114472Sru if (docbook) 527114472Sru { 528114472Sru if (!xml_in_bookinfo) 529114472Sru { 530114472Sru xml_insert_element (BOOKINFO, START); 531114472Sru xml_in_bookinfo = 1; 532114472Sru } 533146515Sru xml_insert_element (LEGALNOTICE, START); 534114472Sru } 535146515Sru 536100513Sru if (!html && !no_headers) 537100513Sru cm_insert_copying (); 538146515Sru 539146515Sru if (docbook) 540146515Sru xml_insert_element (LEGALNOTICE, END); 541146515Sru 542100513Sru break; 543146515Sru 54456160Sru case quotation: 54556160Sru /* @quotation does filling (@display doesn't). */ 54656160Sru if (html) 547146515Sru add_html_block_elt ("<blockquote>\n"); 54856160Sru else 54956160Sru { 550100513Sru /* with close_single_paragraph, we get no blank line above 551100513Sru within @copying. */ 552100513Sru close_paragraph (); 55356160Sru last_char_was_newline = no_indent = 0; 55456160Sru indented_fill = filling_enabled = 1; 55556160Sru inhibit_paragraph_indentation = 1; 55656160Sru } 55756160Sru current_indent += default_indentation_increment; 558146515Sru if (xml) 559146515Sru xml_insert_quotation (insertion_stack->item_function, START); 560146515Sru else if (strlen(insertion_stack->item_function)) 561146515Sru execute_string ("@b{%s:} ", insertion_stack->item_function); 56256160Sru break; 56356160Sru 56456160Sru case example: 56556160Sru case smallexample: 56656160Sru case lisp: 56756160Sru case smalllisp: 568146515Sru in_fixed_width_font++; 569146515Sru /* fall through */ 570146515Sru 571146515Sru /* Like @example but no fixed width font. */ 572146515Sru case display: 573146515Sru case smalldisplay: 57456160Sru /* Like @display but without indentation. */ 57556160Sru case smallformat: 57656160Sru case format: 57756160Sru close_single_paragraph (); 57856160Sru inhibit_paragraph_indentation = 1; 57956160Sru filling_enabled = 0; 58056160Sru last_char_was_newline = 0; 58156160Sru 58256160Sru if (html) 583146515Sru /* Kludge alert: if <pre> is followed by a newline, IE3, 584146515Sru mozilla, maybe others render an extra blank line before the 585146515Sru pre-formatted block. So don't output a newline. */ 586146515Sru add_html_block_elt_args ("<pre class=\"%s\">", command); 58756160Sru 58856160Sru if (type != format && type != smallformat) 589114472Sru { 590146515Sru current_indent += example_indentation_increment; 591114472Sru if (html) 592114472Sru { 593114472Sru /* Since we didn't put \n after <pre>, we need to insert 594114472Sru the indentation by hand. */ 595114472Sru int i; 596114472Sru for (i = current_indent; i > 0; i--) 597114472Sru add_char (' '); 598114472Sru } 599114472Sru } 60056160Sru break; 60156160Sru 60256160Sru case multitable: 60356160Sru do_multitable (); 60456160Sru break; 60556160Sru 60656160Sru case table: 60756160Sru case ftable: 60856160Sru case vtable: 60956160Sru case itemize: 61056160Sru close_single_paragraph (); 61156160Sru current_indent += default_indentation_increment; 61256160Sru filling_enabled = indented_fill = 1; 61356160Sru#if defined (INDENT_PARAGRAPHS_IN_TABLE) 61456160Sru inhibit_paragraph_indentation = 0; 61556160Sru#else 61656160Sru inhibit_paragraph_indentation = 1; 61756160Sru#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 61856160Sru 61956160Sru /* Make things work for losers who forget the itemize syntax. */ 62056160Sru if (type == itemize) 62156160Sru { 62256160Sru if (!(*insertion_stack->item_function)) 62356160Sru { 62456160Sru free (insertion_stack->item_function); 62556160Sru insertion_stack->item_function = xstrdup ("@bullet"); 62656160Sru } 62756160Sru } 62856160Sru 62956160Sru if (!*insertion_stack->item_function) 63056160Sru { 63156160Sru line_error (_("%s requires an argument: the formatter for %citem"), 63256160Sru insertion_type_pname (type), COMMAND_PREFIX); 63356160Sru } 63456160Sru 63556160Sru if (html) 63656160Sru { 63756160Sru if (type == itemize) 638114472Sru { 639146515Sru add_html_block_elt ("<ul>\n"); 640114472Sru in_paragraph = 0; 641114472Sru } 64256160Sru else 643146515Sru { /* We are just starting, so this <dl> 644146515Sru has no <dt> children yet. */ 645146515Sru html_deflist_has_term = 0; 646146515Sru add_html_block_elt ("<dl>\n"); 647146515Sru } 64856160Sru } 64993139Sru if (xml) 650114472Sru xml_begin_table (type, insertion_stack->item_function); 651146515Sru 652146515Sru while (input_text[input_text_offset] == '\n' 653146515Sru && input_text[input_text_offset+1] == '\n') 654146515Sru { 655146515Sru line_number++; 656146515Sru input_text_offset++; 657146515Sru } 658146515Sru 65956160Sru break; 66056160Sru 66156160Sru case enumerate: 66256160Sru close_single_paragraph (); 66356160Sru no_indent = 0; 66456160Sru#if defined (INDENT_PARAGRAPHS_IN_TABLE) 66556160Sru inhibit_paragraph_indentation = 0; 66656160Sru#else 66756160Sru inhibit_paragraph_indentation = 1; 66856160Sru#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 66956160Sru 67056160Sru current_indent += default_indentation_increment; 67156160Sru filling_enabled = indented_fill = 1; 67256160Sru 67356160Sru if (html) 674114472Sru { 675114472Sru enum_html (); 676114472Sru in_paragraph = 0; 677114472Sru } 67856160Sru 67993139Sru if (xml) 680114472Sru xml_begin_enumerate (enumeration_arg); 68193139Sru 68256160Sru if (isdigit (*enumeration_arg)) 68356160Sru start_enumerating (atoi (enumeration_arg), ENUM_DIGITS); 68456160Sru else 68556160Sru start_enumerating (*enumeration_arg, ENUM_ALPHA); 68656160Sru break; 68756160Sru 688146515Sru /* @group produces no output in info. */ 68956160Sru case group: 69056160Sru /* Only close the paragraph if we are not inside of an 69156160Sru @example-like environment. */ 69293139Sru if (xml) 693114472Sru xml_insert_element (GROUP, START); 69493139Sru else if (!insertion_stack->next 69556160Sru || (insertion_stack->next->insertion != display 69656160Sru && insertion_stack->next->insertion != smalldisplay 69756160Sru && insertion_stack->next->insertion != example 69856160Sru && insertion_stack->next->insertion != smallexample 69956160Sru && insertion_stack->next->insertion != lisp 70056160Sru && insertion_stack->next->insertion != smalllisp 70156160Sru && insertion_stack->next->insertion != format 70256160Sru && insertion_stack->next->insertion != smallformat 70356160Sru && insertion_stack->next->insertion != flushleft 70456160Sru && insertion_stack->next->insertion != flushright)) 70556160Sru close_single_paragraph (); 70656160Sru break; 70756160Sru 708116525Sru case cartouche: 709116525Sru if (html) 710146515Sru add_html_block_elt ("<p><table class=\"cartouche\" summary=\"cartouche\" border=\"1\"><tr><td>\n"); 711116525Sru if (in_menu) 712116525Sru no_discard++; 713116525Sru break; 714116525Sru 715146515Sru case floatenv: 716146515Sru /* Cannot nest floats, so complain. */ 717146515Sru if (float_active) 718146515Sru { 719146515Sru line_error (_("%cfloat environments cannot be nested"), COMMAND_PREFIX); 720146515Sru pop_insertion (); 721146515Sru break; 722146515Sru } 723146515Sru 724146515Sru float_active++; 725146515Sru 726146515Sru { /* Collect data about this float. */ 727146515Sru /* Example: @float [FLOATTYPE][,XREFLABEL][,POSITION] */ 728146515Sru char floattype[200] = ""; 729146515Sru char xreflabel[200] = ""; 730146515Sru char position[200] = ""; 731146515Sru char *text; 732146515Sru char *caption; 733146515Sru char *shortcaption; 734146515Sru int start_of_end; 735146515Sru int save_line_number = line_number; 736146515Sru int save_input_text_offset = input_text_offset; 737146515Sru int i; 738146515Sru 739146515Sru if (strlen (insertion_stack->item_function) > 0) 740146515Sru { 741146515Sru int i = 0, t = 0, c = 0; 742146515Sru while (insertion_stack->item_function[i]) 743146515Sru { 744146515Sru if (insertion_stack->item_function[i] == ',') 745146515Sru { 746146515Sru switch (t) 747146515Sru { 748146515Sru case 0: 749146515Sru floattype[c] = '\0'; 750146515Sru break; 751146515Sru case 1: 752146515Sru xreflabel[c] = '\0'; 753146515Sru break; 754146515Sru case 2: 755146515Sru position[c] = '\0'; 756146515Sru break; 757146515Sru } 758146515Sru c = 0; 759146515Sru t++; 760146515Sru i++; 761146515Sru continue; 762146515Sru } 763146515Sru 764146515Sru switch (t) 765146515Sru { 766146515Sru case 0: 767146515Sru floattype[c] = insertion_stack->item_function[i]; 768146515Sru break; 769146515Sru case 1: 770146515Sru xreflabel[c] = insertion_stack->item_function[i]; 771146515Sru break; 772146515Sru case 2: 773146515Sru position[c] = insertion_stack->item_function[i]; 774146515Sru break; 775146515Sru } 776146515Sru c++; 777146515Sru i++; 778146515Sru } 779146515Sru } 780146515Sru 781146515Sru skip_whitespace_and_newlines (); 782146515Sru 783146515Sru start_of_end = get_until ("\n@end float", &text); 784146515Sru 785146515Sru /* Get also the @caption. */ 786146515Sru i = search_forward_until_pos ("\n@caption{", 787146515Sru save_input_text_offset, start_of_end); 788146515Sru if (i > -1) 789146515Sru { 790146515Sru input_text_offset = i + sizeof ("\n@caption{") - 1; 791146515Sru get_until_in_braces ("\n@end float", &caption); 792146515Sru input_text_offset = save_input_text_offset; 793146515Sru } 794146515Sru else 795146515Sru caption = ""; 796146515Sru 797146515Sru /* ... and the @shortcaption. */ 798146515Sru i = search_forward_until_pos ("\n@shortcaption{", 799146515Sru save_input_text_offset, start_of_end); 800146515Sru if (i > -1) 801146515Sru { 802146515Sru input_text_offset = i + sizeof ("\n@shortcaption{") - 1; 803146515Sru get_until_in_braces ("\n@end float", &shortcaption); 804146515Sru input_text_offset = save_input_text_offset; 805146515Sru } 806146515Sru else 807146515Sru shortcaption = ""; 808146515Sru 809146515Sru canon_white (xreflabel); 810146515Sru canon_white (floattype); 811146515Sru canon_white (position); 812146515Sru canon_white (caption); 813146515Sru canon_white (shortcaption); 814146515Sru 815146515Sru add_new_float (xstrdup (xreflabel), 816146515Sru xstrdup (caption), xstrdup (shortcaption), 817146515Sru xstrdup (floattype), xstrdup (position)); 818146515Sru 819146515Sru /* Move to the start of the @float so the contents get processed as 820146515Sru usual. */ 821146515Sru input_text_offset = save_input_text_offset; 822146515Sru line_number = save_line_number; 823146515Sru } 824146515Sru 825146515Sru if (html) 826146515Sru add_html_block_elt ("<div class=\"float\">\n"); 827146515Sru else if (docbook) 828146515Sru xml_insert_element (FLOAT, START); 829146515Sru else if (xml) 830146515Sru { 831146515Sru xml_insert_element_with_attribute (FLOAT, START, 832146515Sru "name=\"%s\"", current_float_id ()); 833146515Sru 834146515Sru xml_insert_element (FLOATTYPE, START); 835146515Sru execute_string ("%s", current_float_type ()); 836146515Sru xml_insert_element (FLOATTYPE, END); 837146515Sru 838146515Sru xml_insert_element (FLOATPOS, START); 839146515Sru execute_string ("%s", current_float_position ()); 840146515Sru xml_insert_element (FLOATPOS, END); 841146515Sru } 842146515Sru else 843146515Sru { /* Info */ 844146515Sru close_single_paragraph (); 845146515Sru inhibit_paragraph_indentation = 1; 846146515Sru } 847146515Sru 848146515Sru /* Anchor now. Note that XML documents get their 849146515Sru anchors with <float name="anchor"> tag. */ 850146515Sru if ((!xml || docbook) && strlen (current_float_id ()) > 0) 851146515Sru execute_string ("@anchor{%s}", current_float_id ()); 852146515Sru 853146515Sru break; 854146515Sru 85556160Sru /* Insertions that are no-ops in info, but do something in TeX. */ 85656160Sru case ifclear: 857146515Sru case ifdocbook: 85856160Sru case ifhtml: 85956160Sru case ifinfo: 860146515Sru case ifnotdocbook: 86156160Sru case ifnothtml: 86256160Sru case ifnotinfo: 863100513Sru case ifnotplaintext: 86456160Sru case ifnottex: 865114472Sru case ifnotxml: 866100513Sru case ifplaintext: 86756160Sru case ifset: 86856160Sru case iftex: 869114472Sru case ifxml: 87056160Sru case rawtex: 87156160Sru if (in_menu) 87256160Sru no_discard++; 87356160Sru break; 87456160Sru 875146515Sru case rawdocbook: 87656160Sru case rawhtml: 877146515Sru case rawxml: 878146515Sru raw_output_block++; 879146515Sru 880146515Sru if (raw_output_block > 0) 881146515Sru { 882146515Sru xml_no_para = 1; 883146515Sru escape_html = 0; 884146515Sru xml_keep_space++; 885146515Sru } 886146515Sru 887146515Sru { 888146515Sru /* Some deuglification for improved readability. */ 889146515Sru extern int xml_in_para; 890146515Sru if (xml && !xml_in_para && xml_indentation_increment > 0) 891146515Sru add_char ('\n'); 892146515Sru } 893146515Sru 89456160Sru break; 89556160Sru 89656160Sru case defcv: 89756160Sru case deffn: 89856160Sru case defivar: 89956160Sru case defmac: 90056160Sru case defmethod: 90156160Sru case defop: 90256160Sru case defopt: 90356160Sru case defspec: 90456160Sru case deftp: 905146515Sru case deftypecv: 90656160Sru case deftypefn: 90756160Sru case deftypefun: 90856160Sru case deftypeivar: 90956160Sru case deftypemethod: 91056160Sru case deftypeop: 91156160Sru case deftypevar: 91256160Sru case deftypevr: 91356160Sru case defun: 91456160Sru case defvar: 91556160Sru case defvr: 91656160Sru inhibit_paragraph_indentation = 1; 91756160Sru filling_enabled = indented_fill = 1; 91856160Sru current_indent += default_indentation_increment; 91956160Sru no_indent = 0; 920146515Sru if (xml) 921146515Sru xml_begin_definition (); 92256160Sru break; 92356160Sru 92456160Sru case flushleft: 92556160Sru close_single_paragraph (); 92656160Sru inhibit_paragraph_indentation = 1; 92756160Sru filling_enabled = indented_fill = no_indent = 0; 92893139Sru if (html) 929146515Sru add_html_block_elt ("<div align=\"left\">"); 93056160Sru break; 93156160Sru 93256160Sru case flushright: 93356160Sru close_single_paragraph (); 93456160Sru filling_enabled = indented_fill = no_indent = 0; 93556160Sru inhibit_paragraph_indentation = 1; 93656160Sru force_flush_right++; 93793139Sru if (html) 938146515Sru add_html_block_elt ("<div align=\"right\">"); 93956160Sru break; 94056160Sru 941146515Sru case titlepage: 942146515Sru xml_insert_element (TITLEPAGE, START); 943146515Sru break; 944146515Sru 94556160Sru default: 94656160Sru line_error ("begin_insertion internal error: type=%d", type); 94756160Sru } 94856160Sru 94956160Sru if (!no_discard) 95056160Sru discard_until ("\n"); 95156160Sru} 95256160Sru 95356160Sru/* Try to end the insertion with the specified TYPE. With a value of 95456160Sru `bad_type', TYPE gets translated to match the value currently on top 95556160Sru of the stack. Otherwise, if TYPE doesn't match the top of the 95656160Sru insertion stack, give error. */ 957146515Srustatic void 958146515Sruend_insertion (int type) 95956160Sru{ 960146515Sru int temp_type; 96156160Sru 96256160Sru if (!insertion_level) 96356160Sru return; 96456160Sru 96556160Sru temp_type = current_insertion_type (); 96656160Sru 96756160Sru if (type == bad_type) 96856160Sru type = temp_type; 96956160Sru 97056160Sru if (type != temp_type) 97156160Sru { 97256160Sru line_error 97356160Sru (_("`@end' expected `%s', but saw `%s'"), 97456160Sru insertion_type_pname (temp_type), insertion_type_pname (type)); 97556160Sru return; 97656160Sru } 97756160Sru 97856160Sru pop_insertion (); 97956160Sru 98093139Sru if (xml) 98193139Sru { 98293139Sru switch (type) 983114472Sru { 984114472Sru case ifinfo: 985114472Sru case documentdescription: 986114472Sru break; 987114472Sru case quotation: 988146515Sru xml_insert_quotation ("", END); 989114472Sru break; 990114472Sru case example: 991114472Sru xml_insert_element (EXAMPLE, END); 992146515Sru if (docbook && current_insertion_type () == floatenv) 993146515Sru xml_insert_element (FLOATEXAMPLE, END); 994114472Sru break; 995114472Sru case smallexample: 996114472Sru xml_insert_element (SMALLEXAMPLE, END); 997146515Sru if (docbook && current_insertion_type () == floatenv) 998146515Sru xml_insert_element (FLOATEXAMPLE, END); 999114472Sru break; 1000114472Sru case lisp: 1001114472Sru xml_insert_element (LISP, END); 1002146515Sru if (docbook && current_insertion_type () == floatenv) 1003146515Sru xml_insert_element (FLOATEXAMPLE, END); 1004114472Sru break; 1005114472Sru case smalllisp: 1006114472Sru xml_insert_element (SMALLLISP, END); 1007146515Sru if (docbook && current_insertion_type () == floatenv) 1008146515Sru xml_insert_element (FLOATEXAMPLE, END); 1009114472Sru break; 1010114472Sru case cartouche: 1011114472Sru xml_insert_element (CARTOUCHE, END); 1012114472Sru break; 1013114472Sru case format: 1014114472Sru if (docbook && xml_in_bookinfo && xml_in_abstract) 1015114472Sru { 1016114472Sru xml_insert_element (ABSTRACT, END); 1017114472Sru xml_in_abstract = 0; 1018114472Sru } 1019114472Sru else 1020114472Sru xml_insert_element (FORMAT, END); 1021114472Sru break; 1022114472Sru case smallformat: 1023114472Sru xml_insert_element (SMALLFORMAT, END); 1024114472Sru break; 1025114472Sru case display: 1026114472Sru xml_insert_element (DISPLAY, END); 1027114472Sru break; 1028114472Sru case smalldisplay: 1029114472Sru xml_insert_element (SMALLDISPLAY, END); 1030114472Sru break; 1031114472Sru case table: 1032114472Sru case ftable: 1033114472Sru case vtable: 1034114472Sru case itemize: 1035114472Sru xml_end_table (type); 1036114472Sru break; 1037114472Sru case enumerate: 1038146515Sru xml_end_enumerate (); 1039114472Sru break; 1040114472Sru case group: 1041114472Sru xml_insert_element (GROUP, END); 1042114472Sru break; 1043146515Sru case titlepage: 1044146515Sru xml_insert_element (TITLEPAGE, END); 1045146515Sru break; 1046114472Sru } 104793139Sru } 104856160Sru switch (type) 104956160Sru { 105056160Sru /* Insertions which have no effect on paragraph formatting. */ 1051100513Sru case copying: 1052146515Sru line_number--; 1053146515Sru break; 1054146515Sru 105556160Sru case ifclear: 1056146515Sru case ifdocbook: 105793139Sru case ifinfo: 105856160Sru case ifhtml: 1059146515Sru case ifnotdocbook: 106056160Sru case ifnothtml: 106156160Sru case ifnotinfo: 1062100513Sru case ifnotplaintext: 106356160Sru case ifnottex: 1064114472Sru case ifnotxml: 1065100513Sru case ifplaintext: 106656160Sru case ifset: 106756160Sru case iftex: 1068114472Sru case ifxml: 106956160Sru case rawtex: 1070146515Sru case titlepage: 107156160Sru break; 107256160Sru 1073146515Sru case rawdocbook: 107456160Sru case rawhtml: 1075146515Sru case rawxml: 1076146515Sru raw_output_block--; 1077146515Sru 1078146515Sru if (raw_output_block <= 0) 1079146515Sru { 1080146515Sru xml_no_para = 0; 1081146515Sru escape_html = 1; 1082146515Sru xml_keep_space--; 1083146515Sru } 1084146515Sru 1085146515Sru if ((xml || html) && output_paragraph[output_paragraph_offset-1] == '\n') 1086146515Sru output_paragraph_offset--; 108756160Sru break; 108856160Sru 108956160Sru case detailmenu: 1090146515Sru if (xml) 1091146515Sru xml_insert_element (DETAILMENU, END); 1092146515Sru 109356160Sru in_detailmenu--; /* No longer hacking menus. */ 109456160Sru if (!in_menu) 109556160Sru { 109656160Sru if (!no_headers) 109756160Sru close_insertion_paragraph (); 109856160Sru } 109956160Sru break; 110056160Sru 1101100513Sru case direntry: /* Eaten if html. */ 1102100513Sru insert_string ("END-INFO-DIR-ENTRY\n\n"); 1103100513Sru close_insertion_paragraph (); 1104100513Sru break; 1105100513Sru 1106146515Sru case documentdescription: 1107146515Sru if (xml) 1108146515Sru insert_string (document_description); 1109146515Sru xml_insert_element (DOCUMENTDESCRIPTION, END); 1110146515Sru break; 1111146515Sru 111256160Sru case menu: 111356160Sru in_menu--; /* No longer hacking menus. */ 1114116525Sru if (html && !no_headers) 1115146515Sru add_html_block_elt ("</ul>\n"); 1116146515Sru else if (!no_headers && !xml) 111756160Sru close_insertion_paragraph (); 111856160Sru break; 111956160Sru 112056160Sru case multitable: 112156160Sru end_multitable (); 112256160Sru break; 112356160Sru 112456160Sru case enumerate: 112556160Sru stop_enumerating (); 112656160Sru close_insertion_paragraph (); 112756160Sru current_indent -= default_indentation_increment; 112856160Sru if (html) 1129146515Sru add_html_block_elt ("</ol>\n"); 113056160Sru break; 113156160Sru 113256160Sru case flushleft: 113393139Sru if (html) 1134146515Sru add_html_block_elt ("</div>\n"); 113593139Sru close_insertion_paragraph (); 113693139Sru break; 113793139Sru 113856160Sru case cartouche: 1139116525Sru if (html) 1140146515Sru add_html_block_elt ("</td></tr></table>\n"); 114156160Sru close_insertion_paragraph (); 114256160Sru break; 114356160Sru 1144116525Sru case group: 1145146515Sru if (!xml || docbook) 1146146515Sru close_insertion_paragraph (); 1147116525Sru break; 1148116525Sru 1149146515Sru case floatenv: 1150146515Sru if (xml) 1151146515Sru xml_insert_element (FLOAT, END); 1152146515Sru else 1153146515Sru { 1154146515Sru if (html) 1155146515Sru add_html_block_elt ("<p><strong class=\"float-caption\">"); 1156146515Sru else 1157146515Sru close_paragraph (); 1158146515Sru 1159146515Sru no_indent = 1; 1160146515Sru 1161146515Sru /* Legend: 1162146515Sru 1) @float Foo,lbl & no caption: Foo 1.1 1163146515Sru 2) @float Foo & no caption: Foo 1164146515Sru 3) @float ,lbl & no caption: 1.1 1165146515Sru 4) @float & no caption: */ 1166146515Sru 1167146515Sru if (!xml && !html) 1168146515Sru indent (current_indent); 1169146515Sru 1170146515Sru if (strlen (current_float_type ())) 1171146515Sru execute_string ("%s", current_float_type ()); 1172146515Sru 1173146515Sru if (strlen (current_float_id ()) > 0) 1174146515Sru { 1175146515Sru if (strlen (current_float_type ()) > 0) 1176146515Sru add_char (' '); 1177146515Sru 1178146515Sru add_word (current_float_number ()); 1179146515Sru } 1180146515Sru 1181146515Sru if (strlen (current_float_title ()) > 0) 1182146515Sru { 1183146515Sru if (strlen (current_float_type ()) > 0 1184146515Sru || strlen (current_float_id ()) > 0) 1185146515Sru insert_string (": "); 1186146515Sru 1187146515Sru execute_string ("%s", current_float_title ()); 1188146515Sru } 1189146515Sru 1190146515Sru /* Indent the following paragraph. */ 1191146515Sru inhibit_paragraph_indentation = 0; 1192146515Sru 1193146515Sru if (html) 1194146515Sru add_word ("</strong></p></div>\n"); 1195146515Sru else 1196146515Sru close_paragraph (); 1197146515Sru } 1198146515Sru float_active--; 1199146515Sru break; 1200146515Sru 120156160Sru case format: 120256160Sru case smallformat: 120356160Sru case display: 120456160Sru case smalldisplay: 120556160Sru case example: 120656160Sru case smallexample: 120756160Sru case lisp: 120856160Sru case smalllisp: 120956160Sru case quotation: 121056160Sru /* @format and @smallformat are the only fixed_width insertion 121156160Sru without a change in indentation. */ 1212146515Sru if (type != format && type != smallformat && type != quotation) 1213146515Sru current_indent -= example_indentation_increment; 1214146515Sru else if (type == quotation) 121556160Sru current_indent -= default_indentation_increment; 121656160Sru 121756160Sru if (html) 1218146515Sru { /* The complex code in close_paragraph that kills whitespace 1219146515Sru does not function here, since we've inserted non-whitespace 1220146515Sru (the </whatever>) before it. The indentation already got 1221146515Sru inserted at the end of the last example line, so we have to 1222146515Sru delete it, or browsers wind up showing an extra blank line. */ 1223146515Sru kill_self_indent (default_indentation_increment); 1224146515Sru add_html_block_elt (type == quotation 1225146515Sru ? "</blockquote>\n" : "</pre>\n"); 1226146515Sru } 122756160Sru 122856160Sru /* The ending of one of these insertions always marks the 1229146515Sru start of a new paragraph, except for the XML output. */ 1230146515Sru if (!xml || docbook) 1231146515Sru close_insertion_paragraph (); 1232146515Sru 1233146515Sru /* </pre> closes paragraph without messing with </p>. */ 1234146515Sru if (html && type != quotation) 1235146515Sru paragraph_is_open = 0; 123656160Sru break; 123756160Sru 123856160Sru case table: 123956160Sru case ftable: 124056160Sru case vtable: 124156160Sru current_indent -= default_indentation_increment; 124256160Sru if (html) 1243146515Sru add_html_block_elt ("</dl>\n"); 1244114472Sru close_insertion_paragraph (); 124556160Sru break; 124656160Sru 124756160Sru case itemize: 124856160Sru current_indent -= default_indentation_increment; 124956160Sru if (html) 1250146515Sru add_html_block_elt ("</ul>\n"); 125156160Sru close_insertion_paragraph (); 125256160Sru break; 125356160Sru 125456160Sru case flushright: 125556160Sru force_flush_right--; 125693139Sru if (html) 1257146515Sru add_html_block_elt ("</div>\n"); 125856160Sru close_insertion_paragraph (); 125956160Sru break; 126056160Sru 126156160Sru /* Handle the @defun insertions with this default clause. */ 126256160Sru default: 126356160Sru { 1264146515Sru int base_type; 126556160Sru 126656160Sru if (type < defcv || type > defvr) 126756160Sru line_error ("end_insertion internal error: type=%d", type); 126856160Sru 126956160Sru base_type = get_base_type (type); 127056160Sru switch (base_type) 127156160Sru { 127256160Sru case deffn: 127356160Sru case defvr: 127456160Sru case deftp: 1275146515Sru case deftypecv: 127656160Sru case deftypefn: 127756160Sru case deftypevr: 127856160Sru case defcv: 127956160Sru case defop: 1280114472Sru case deftypemethod: 1281114472Sru case deftypeop: 1282114472Sru case deftypeivar: 1283114472Sru if (html) 1284146515Sru { 1285146515Sru if (paragraph_is_open) 1286146515Sru add_html_block_elt ("</p>"); 1287146515Sru /* close the div and blockquote which has been opened in defun.c */ 1288146515Sru if (!rollback_empty_tag ("blockquote")) 1289146515Sru add_html_block_elt ("</blockquote>"); 1290146515Sru add_html_block_elt ("</div>\n"); 1291146515Sru } 1292146515Sru if (xml) 1293146515Sru xml_end_definition (); 129456160Sru break; 129556160Sru } /* switch (base_type)... */ 129656160Sru 129756160Sru current_indent -= default_indentation_increment; 129856160Sru close_insertion_paragraph (); 129956160Sru } 130056160Sru break; 130156160Sru 130256160Sru } 130356160Sru 130456160Sru if (current_indent < 0) 130556160Sru line_error ("end_insertion internal error: current indent=%d", 130656160Sru current_indent); 130756160Sru} 130856160Sru 130956160Sru/* Insertions cannot cross certain boundaries, such as node beginnings. In 131056160Sru code that creates such boundaries, you should call `discard_insertions' 131156160Sru before doing anything else. It prints the errors for you, and cleans up 131256160Sru the insertion stack. 131356160Sru 131456160Sru With nonzero SPECIALS_OK argument, allows unmatched 131556160Sru @if... conditionals, otherwise not. This is because conditionals can 131656160Sru cross node boundaries. Always happens with the @top node, for example. */ 131756160Sruvoid 1318146515Srudiscard_insertions (int specials_ok) 131956160Sru{ 132056160Sru int real_line_number = line_number; 132156160Sru while (insertion_stack) 132256160Sru { 132356160Sru if (specials_ok 132456160Sru && ((ifclear <= insertion_stack->insertion 132556160Sru && insertion_stack->insertion <= iftex) 1326146515Sru || insertion_stack->insertion == rawdocbook 132756160Sru || insertion_stack->insertion == rawhtml 1328146515Sru || insertion_stack->insertion == rawxml 132956160Sru || insertion_stack->insertion == rawtex)) 133056160Sru break; 133156160Sru else 133256160Sru { 1333116525Sru const char *offender = insertion_type_pname (insertion_stack->insertion); 133456160Sru 133593139Sru file_line_error (insertion_stack->filename, 1336114472Sru insertion_stack->line_number, 1337114472Sru _("No matching `%cend %s'"), COMMAND_PREFIX, 1338114472Sru offender); 133956160Sru pop_insertion (); 134056160Sru } 134156160Sru } 134256160Sru line_number = real_line_number; 134356160Sru} 134456160Sru 134556160Sru/* Insertion (environment) commands. */ 134656160Sru 134756160Sruvoid 1348146515Srucm_quotation (void) 134956160Sru{ 1350146515Sru /* We start the blockquote element in the insertion. */ 135156160Sru begin_insertion (quotation); 135256160Sru} 135356160Sru 135456160Sruvoid 1355146515Srucm_example (void) 135656160Sru{ 1357146515Sru if (docbook && current_insertion_type () == floatenv) 1358146515Sru xml_begin_docbook_float (FLOATEXAMPLE); 1359146515Sru 136093139Sru if (xml) 1361146515Sru { 1362146515Sru /* Rollback previous newlines. These occur between 1363146515Sru </para> and <example>. */ 1364146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1365146515Sru output_paragraph_offset--; 1366146515Sru 1367146515Sru xml_insert_element (EXAMPLE, START); 1368146515Sru 1369146515Sru /* Make sure example text is starting on a new line 1370146515Sru for improved readability. */ 1371146515Sru if (docbook) 1372146515Sru add_char ('\n'); 1373146515Sru } 1374146515Sru 137556160Sru begin_insertion (example); 137656160Sru} 137756160Sru 137856160Sruvoid 1379146515Srucm_smallexample (void) 138056160Sru{ 1381146515Sru if (docbook && current_insertion_type () == floatenv) 1382146515Sru xml_begin_docbook_float (FLOATEXAMPLE); 1383146515Sru 138493139Sru if (xml) 1385146515Sru { 1386146515Sru /* See cm_example comments about newlines. */ 1387146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1388146515Sru output_paragraph_offset--; 1389146515Sru xml_insert_element (SMALLEXAMPLE, START); 1390146515Sru if (docbook) 1391146515Sru add_char ('\n'); 1392146515Sru } 1393146515Sru 139456160Sru begin_insertion (smallexample); 139556160Sru} 139656160Sru 139756160Sruvoid 1398146515Srucm_lisp (void) 139956160Sru{ 1400146515Sru if (docbook && current_insertion_type () == floatenv) 1401146515Sru xml_begin_docbook_float (FLOATEXAMPLE); 1402146515Sru 140393139Sru if (xml) 1404146515Sru { 1405146515Sru /* See cm_example comments about newlines. */ 1406146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1407146515Sru output_paragraph_offset--; 1408146515Sru xml_insert_element (LISP, START); 1409146515Sru if (docbook) 1410146515Sru add_char ('\n'); 1411146515Sru } 1412146515Sru 141356160Sru begin_insertion (lisp); 141456160Sru} 141556160Sru 141656160Sruvoid 1417146515Srucm_smalllisp (void) 141856160Sru{ 1419146515Sru if (docbook && current_insertion_type () == floatenv) 1420146515Sru xml_begin_docbook_float (FLOATEXAMPLE); 1421146515Sru 142293139Sru if (xml) 1423146515Sru { 1424146515Sru /* See cm_example comments about newlines. */ 1425146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1426146515Sru output_paragraph_offset--; 1427146515Sru xml_insert_element (SMALLLISP, START); 1428146515Sru if (docbook) 1429146515Sru add_char ('\n'); 1430146515Sru } 1431146515Sru 143256160Sru begin_insertion (smalllisp); 143356160Sru} 143456160Sru 143556160Sruvoid 1436146515Srucm_cartouche (void) 143756160Sru{ 1438146515Sru if (docbook && current_insertion_type () == floatenv) 1439146515Sru xml_begin_docbook_float (CARTOUCHE); 1440146515Sru 144193139Sru if (xml) 144293139Sru xml_insert_element (CARTOUCHE, START); 144356160Sru begin_insertion (cartouche); 144456160Sru} 144556160Sru 144656160Sruvoid 1447146515Srucm_copying (void) 1448100513Sru{ 1449100513Sru begin_insertion (copying); 1450100513Sru} 1451100513Sru 1452100513Sru/* Not an insertion, despite the name, but it goes with cm_copying. */ 1453100513Sruvoid 1454146515Srucm_insert_copying (void) 1455100513Sru{ 1456146515Sru if (!copying_text) 1457146515Sru { 1458146515Sru warning ("@copying not used before %s", command); 1459146515Sru return; 1460146515Sru } 1461146515Sru 1462146515Sru execute_string ("%s", copying_text); 1463146515Sru 1464146515Sru if (!xml && !html) 1465146515Sru { 1466146515Sru add_word ("\n\n"); 1467114472Sru /* Update output_position so that the node positions in the tag 1468114472Sru tables will take account of the copying text. */ 1469114472Sru flush_output (); 1470100513Sru } 1471100513Sru} 1472100513Sru 1473100513Sruvoid 1474146515Srucm_format (void) 147556160Sru{ 147693139Sru if (xml) 1477114472Sru { 1478114472Sru if (docbook && xml_in_bookinfo) 1479114472Sru { 1480114472Sru xml_insert_element (ABSTRACT, START); 1481114472Sru xml_in_abstract = 1; 1482114472Sru } 1483114472Sru else 1484146515Sru { 1485146515Sru /* See cm_example comments about newlines. */ 1486146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1487146515Sru output_paragraph_offset--; 1488146515Sru xml_insert_element (FORMAT, START); 1489146515Sru if (docbook) 1490146515Sru add_char ('\n'); 1491146515Sru } 1492114472Sru } 149356160Sru begin_insertion (format); 149456160Sru} 149556160Sru 149656160Sruvoid 1497146515Srucm_smallformat (void) 149856160Sru{ 149993139Sru if (xml) 1500146515Sru { 1501146515Sru /* See cm_example comments about newlines. */ 1502146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1503146515Sru output_paragraph_offset--; 1504146515Sru xml_insert_element (SMALLFORMAT, START); 1505146515Sru if (docbook) 1506146515Sru add_char ('\n'); 1507146515Sru } 1508146515Sru 150956160Sru begin_insertion (smallformat); 151056160Sru} 151156160Sru 151256160Sruvoid 1513146515Srucm_display (void) 151456160Sru{ 151593139Sru if (xml) 1516146515Sru { 1517146515Sru /* See cm_example comments about newlines. */ 1518146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1519146515Sru output_paragraph_offset--; 1520146515Sru xml_insert_element (DISPLAY, START); 1521146515Sru if (docbook) 1522146515Sru add_char ('\n'); 1523146515Sru } 1524146515Sru 152556160Sru begin_insertion (display); 152656160Sru} 152756160Sru 152856160Sruvoid 1529146515Srucm_smalldisplay (void) 153056160Sru{ 153193139Sru if (xml) 1532146515Sru { 1533146515Sru /* See cm_example comments about newlines. */ 1534146515Sru if (output_paragraph[output_paragraph_offset-1] == '\n') 1535146515Sru output_paragraph_offset--; 1536146515Sru xml_insert_element (SMALLDISPLAY, START); 1537146515Sru if (docbook) 1538146515Sru add_char ('\n'); 1539146515Sru } 1540146515Sru 154156160Sru begin_insertion (smalldisplay); 154256160Sru} 154356160Sru 154456160Sruvoid 1545146515Srucm_direntry (void) 154656160Sru{ 1547146515Sru if (html || xml || no_headers) 154856160Sru command_name_condition (); 154956160Sru else 155056160Sru begin_insertion (direntry); 155156160Sru} 155256160Sru 155356160Sruvoid 1554146515Srucm_documentdescription (void) 155593139Sru{ 1556146515Sru if (html) 155793139Sru begin_insertion (documentdescription); 1558146515Sru 1559146515Sru else if (xml) 1560146515Sru { 1561146515Sru xml_insert_element (DOCUMENTDESCRIPTION, START); 1562146515Sru begin_insertion (documentdescription); 1563146515Sru } 1564146515Sru 156593139Sru else 156693139Sru command_name_condition (); 156793139Sru} 156893139Sru 156993139Sru 157093139Sruvoid 1571146515Srucm_itemize (void) 157256160Sru{ 157356160Sru begin_insertion (itemize); 157456160Sru} 157556160Sru 157656160Sru/* Start an enumeration insertion of type TYPE. If the user supplied 157756160Sru no argument on the line, then use DEFAULT_STRING as the initial string. */ 157856160Srustatic void 1579146515Srudo_enumeration (int type, char *default_string) 158056160Sru{ 158156160Sru get_until_in_line (0, ".", &enumeration_arg); 158256160Sru canon_white (enumeration_arg); 158356160Sru 158456160Sru if (!*enumeration_arg) 158556160Sru { 158656160Sru free (enumeration_arg); 158756160Sru enumeration_arg = xstrdup (default_string); 158856160Sru } 158956160Sru 159056160Sru if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg)) 159156160Sru { 159256160Sru warning (_("%s requires letter or digit"), insertion_type_pname (type)); 159356160Sru 159456160Sru switch (type) 159556160Sru { 159656160Sru case enumerate: 159756160Sru default_string = "1"; 159856160Sru break; 159956160Sru } 160056160Sru enumeration_arg = xstrdup (default_string); 160156160Sru } 160256160Sru begin_insertion (type); 160356160Sru} 160456160Sru 160556160Sruvoid 1606146515Srucm_enumerate (void) 160756160Sru{ 160856160Sru do_enumeration (enumerate, "1"); 160956160Sru} 161056160Sru 161193139Sru/* Handle verbatim environment: 161293139Sru find_end_verbatim == 0: process until end of file 161393139Sru find_end_verbatim != 0: process until 'COMMAND_PREFIXend verbatim' 161493139Sru or end of file 161593139Sru 161693139Sru We cannot simply copy input stream onto output stream; as the 161793139Sru verbatim environment may be encapsulated in an @example environment, 161893139Sru for example. */ 161956160Sruvoid 1620146515Sruhandle_verbatim_environment (int find_end_verbatim) 162193139Sru{ 162293139Sru int character; 162393139Sru int seen_end = 0; 162493139Sru int save_filling_enabled = filling_enabled; 162593139Sru int save_inhibit_paragraph_indentation = inhibit_paragraph_indentation; 1626146515Sru int save_escape_html = escape_html; 162793139Sru 1628146515Sru if (!insertion_stack) 1629146515Sru close_single_paragraph (); /* no blank lines if not at outer level */ 163093139Sru inhibit_paragraph_indentation = 1; 163193139Sru filling_enabled = 0; 163293139Sru in_fixed_width_font++; 163393139Sru last_char_was_newline = 0; 163493139Sru 163593139Sru /* No indentation: this is verbatim after all 163693139Sru If you want indent, enclose @verbatim in @example 163793139Sru current_indent += default_indentation_increment; 163893139Sru */ 163993139Sru 164093139Sru if (html) 1641146515Sru { /* If inside @example, we'll be preceded by the indentation 1642146515Sru already. Browsers will ignore those spaces because we're about 1643146515Sru to start another <pre> (don't ask me). So, wipe them out for 1644146515Sru cleanliness, and re-insert. */ 1645146515Sru int i; 1646146515Sru kill_self_indent (default_indentation_increment); 1647146515Sru add_html_block_elt ("<pre class=\"verbatim\">"); 1648146515Sru for (i = current_indent; i > 0; i--) 1649146515Sru add_char (' '); 1650146515Sru } 1651146515Sru else if (xml) 1652146515Sru { 1653146515Sru xml_insert_element (VERBATIM, START); 1654146515Sru escape_html = 0; 1655146515Sru add_word ("<![CDATA["); 1656146515Sru } 165793139Sru 165893139Sru while (input_text_offset < input_text_length) 165993139Sru { 166093139Sru character = curchar (); 166193139Sru 166293139Sru if (character == '\n') 166393139Sru line_number++; 1664146515Sru 1665146515Sru /* Assume no newlines in END_VERBATIM. */ 166693139Sru else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */ 1667114472Sru && (input_text_length - input_text_offset > sizeof (END_VERBATIM)) 1668114472Sru && !strncmp (&input_text[input_text_offset+1], END_VERBATIM, 1669114472Sru sizeof (END_VERBATIM)-1)) 1670114472Sru { 1671114472Sru input_text_offset += sizeof (END_VERBATIM); 1672114472Sru seen_end = 1; 1673114472Sru break; 1674114472Sru } 167593139Sru 1676114472Sru if (html && character == '&' && escape_html) 1677114472Sru add_word ("&"); 1678114472Sru else if (html && character == '<' && escape_html) 1679114472Sru add_word ("<"); 1680114472Sru else 1681114472Sru add_char (character); 1682114472Sru 168393139Sru input_text_offset++; 168493139Sru } 168593139Sru 168693139Sru if (find_end_verbatim && !seen_end) 168793139Sru warning (_("end of file inside verbatim block")); 168893139Sru 168993139Sru if (html) 1690146515Sru { /* See comments in example case above. */ 1691146515Sru kill_self_indent (default_indentation_increment); 1692146515Sru add_word ("</pre>"); 1693146515Sru } 1694146515Sru else if (xml) 1695146515Sru { 1696146515Sru add_word ("]]>"); 1697146515Sru xml_insert_element (VERBATIM, END); 1698146515Sru escape_html = save_escape_html; 1699146515Sru } 170093139Sru 170193139Sru in_fixed_width_font--; 170293139Sru filling_enabled = save_filling_enabled; 170393139Sru inhibit_paragraph_indentation = save_inhibit_paragraph_indentation; 170493139Sru} 170593139Sru 170693139Sruvoid 1707146515Srucm_verbatim (void) 170893139Sru{ 170993139Sru handle_verbatim_environment (1); 171093139Sru} 171193139Sru 171293139Sruvoid 1713146515Srucm_table (void) 171456160Sru{ 171556160Sru begin_insertion (table); 171656160Sru} 171756160Sru 171856160Sruvoid 1719146515Srucm_multitable (void) 172056160Sru{ 172156160Sru begin_insertion (multitable); /* @@ */ 172256160Sru} 172356160Sru 172456160Sruvoid 1725146515Srucm_ftable (void) 172656160Sru{ 172756160Sru begin_insertion (ftable); 172856160Sru} 172956160Sru 173056160Sruvoid 1731146515Srucm_vtable (void) 173256160Sru{ 173356160Sru begin_insertion (vtable); 173456160Sru} 173556160Sru 173656160Sruvoid 1737146515Srucm_group (void) 173856160Sru{ 173956160Sru begin_insertion (group); 174056160Sru} 174156160Sru 1742100513Sru/* Insert raw HTML (no escaping of `<' etc.). */ 174356160Sruvoid 1744146515Srucm_html (int arg) 1745100513Sru{ 1746146515Sru if (process_html) 1747100513Sru begin_insertion (rawhtml); 1748100513Sru else 1749100513Sru command_name_condition (); 1750100513Sru} 1751100513Sru 1752100513Sruvoid 1753146515Srucm_xml (int arg) 1754100513Sru{ 1755146515Sru if (process_xml) 1756146515Sru begin_insertion (rawxml); 1757146515Sru else 1758146515Sru command_name_condition (); 1759146515Sru} 1760146515Sru 1761146515Sruvoid 1762146515Srucm_docbook (int arg) 1763146515Sru{ 1764146515Sru if (process_docbook) 1765146515Sru begin_insertion (rawdocbook); 1766146515Sru else 1767146515Sru command_name_condition (); 1768146515Sru} 1769146515Sru 1770146515Sruvoid 1771146515Srucm_ifdocbook (void) 1772146515Sru{ 1773146515Sru if (process_docbook) 1774146515Sru begin_insertion (ifdocbook); 1775146515Sru else 1776146515Sru command_name_condition (); 1777146515Sru} 1778146515Sru 1779146515Sruvoid 1780146515Srucm_ifnotdocbook (void) 1781146515Sru{ 1782146515Sru if (!process_docbook) 1783146515Sru begin_insertion (ifnotdocbook); 1784146515Sru else 1785146515Sru command_name_condition (); 1786146515Sru} 1787146515Sru 1788146515Sruvoid 1789146515Srucm_ifhtml (void) 1790146515Sru{ 1791100513Sru if (process_html) 1792100513Sru begin_insertion (ifhtml); 1793100513Sru else 1794100513Sru command_name_condition (); 1795100513Sru} 1796100513Sru 1797100513Sruvoid 1798146515Srucm_ifnothtml (void) 1799100513Sru{ 1800100513Sru if (!process_html) 1801100513Sru begin_insertion (ifnothtml); 1802100513Sru else 1803100513Sru command_name_condition (); 1804100513Sru} 1805100513Sru 1806100513Sru 1807100513Sruvoid 1808146515Srucm_ifinfo (void) 180956160Sru{ 181056160Sru if (process_info) 181156160Sru begin_insertion (ifinfo); 181256160Sru else 181356160Sru command_name_condition (); 181456160Sru} 181556160Sru 181656160Sruvoid 1817146515Srucm_ifnotinfo (void) 181856160Sru{ 181956160Sru if (!process_info) 182056160Sru begin_insertion (ifnotinfo); 182156160Sru else 182256160Sru command_name_condition (); 182356160Sru} 182456160Sru 182556160Sru 182656160Sruvoid 1827146515Srucm_ifplaintext (void) 182856160Sru{ 1829100513Sru if (process_plaintext) 1830100513Sru begin_insertion (ifplaintext); 183156160Sru else 183256160Sru command_name_condition (); 183356160Sru} 183456160Sru 183556160Sruvoid 1836146515Srucm_ifnotplaintext (void) 183756160Sru{ 1838100513Sru if (!process_plaintext) 1839100513Sru begin_insertion (ifnotplaintext); 184056160Sru else 184156160Sru command_name_condition (); 184256160Sru} 184356160Sru 184456160Sru 184556160Sruvoid 1846146515Srucm_tex (void) 184756160Sru{ 184856160Sru if (process_tex) 184956160Sru begin_insertion (rawtex); 185056160Sru else 185156160Sru command_name_condition (); 185256160Sru} 185356160Sru 185456160Sruvoid 1855146515Srucm_iftex (void) 185656160Sru{ 185756160Sru if (process_tex) 185856160Sru begin_insertion (iftex); 185956160Sru else 186056160Sru command_name_condition (); 186156160Sru} 186256160Sru 186356160Sruvoid 1864146515Srucm_ifnottex (void) 186556160Sru{ 186656160Sru if (!process_tex) 186756160Sru begin_insertion (ifnottex); 186856160Sru else 186956160Sru command_name_condition (); 187056160Sru} 1871114472Sru 1872114472Sruvoid 1873146515Srucm_ifxml (void) 1874114472Sru{ 1875114472Sru if (process_xml) 1876114472Sru begin_insertion (ifxml); 1877114472Sru else 1878114472Sru command_name_condition (); 1879114472Sru} 1880114472Sru 1881114472Sruvoid 1882146515Srucm_ifnotxml (void) 1883114472Sru{ 1884114472Sru if (!process_xml) 1885114472Sru begin_insertion (ifnotxml); 1886114472Sru else 1887114472Sru command_name_condition (); 1888114472Sru} 1889114472Sru 189056160Sru 1891146515Sru/* Generic xrefable block with a caption. */ 1892146515Sruvoid 1893146515Srucm_float (void) 1894146515Sru{ 1895146515Sru begin_insertion (floatenv); 1896146515Sru} 1897146515Sru 1898146515Sruvoid 1899146515Srucm_caption (int arg) 1900146515Sru{ 1901146515Sru char *temp; 1902146515Sru 1903146515Sru /* This is a no_op command for most formats, as we handle it during @float 1904146515Sru insertion. For XML though, we handle it here to keep document structure 1905146515Sru as close as possible, to the Texinfo source. */ 1906146515Sru 1907146515Sru /* Everything is already handled at START. */ 1908146515Sru if (arg == END) 1909146515Sru return; 1910146515Sru 1911146515Sru /* Check if it's mislocated. */ 1912146515Sru if (current_insertion_type () != floatenv) 1913146515Sru line_error (_("@%s not meaningful outside `@float' environment"), command); 1914146515Sru 1915146515Sru get_until_in_braces ("\n@end float", &temp); 1916146515Sru 1917146515Sru if (xml) 1918146515Sru { 1919146515Sru int elt = STREQ (command, "shortcaption") ? SHORTCAPTION : CAPTION; 1920146515Sru xml_insert_element (elt, START); 1921146515Sru if (!docbook) 1922146515Sru execute_string ("%s", temp); 1923146515Sru xml_insert_element (elt, END); 1924146515Sru } 1925146515Sru 1926146515Sru free (temp); 1927146515Sru} 1928146515Sru 192956160Sru/* Begin an insertion where the lines are not filled or indented. */ 193056160Sruvoid 1931146515Srucm_flushleft (void) 193256160Sru{ 193356160Sru begin_insertion (flushleft); 193456160Sru} 193556160Sru 193656160Sru/* Begin an insertion where the lines are not filled, and each line is 193756160Sru forced to the right-hand side of the page. */ 193856160Sruvoid 1939146515Srucm_flushright (void) 194056160Sru{ 194156160Sru begin_insertion (flushright); 194256160Sru} 194356160Sru 194456160Sruvoid 1945146515Srucm_menu (void) 194656160Sru{ 1947146515Sru if (current_node == NULL && !macro_expansion_output_stream) 194856160Sru { 194956160Sru warning (_("@menu seen before first @node, creating `Top' node")); 195056160Sru warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?")); 195156160Sru /* Include @top command so we can construct the implicit node tree. */ 195256160Sru execute_string ("@node top\n@top Top\n"); 195356160Sru } 195456160Sru begin_insertion (menu); 195556160Sru} 195656160Sru 195756160Sruvoid 1958146515Srucm_detailmenu (void) 195956160Sru{ 1960146515Sru if (current_node == NULL && !macro_expansion_output_stream) 196156160Sru { /* Problems anyway, @detailmenu should always be inside @menu. */ 196256160Sru warning (_("@detailmenu seen before first node, creating `Top' node")); 196356160Sru execute_string ("@node top\n@top Top\n"); 196456160Sru } 196556160Sru begin_insertion (detailmenu); 196656160Sru} 1967146515Sru 1968146515Sru/* Title page commands. */ 196956160Sru 1970146515Sruvoid 1971146515Srucm_titlepage (void) 1972146515Sru{ 1973146515Sru titlepage_cmd_present = 1; 1974146515Sru if (xml && !docbook) 1975146515Sru begin_insertion (titlepage); 1976146515Sru else 1977146515Sru command_name_condition (); 1978146515Sru} 1979146515Sru 1980146515Sruvoid 1981146515Srucm_author (void) 1982146515Sru{ 1983146515Sru char *rest; 1984146515Sru get_rest_of_line (1, &rest); 1985146515Sru 1986146515Sru if (is_in_insertion_of_type (quotation)) 1987146515Sru { 1988146515Sru if (html) 1989146515Sru add_word_args ("— %s", rest); 1990146515Sru else if (docbook) 1991146515Sru { 1992146515Sru /* FIXME Ideally, we should use an attribution element, 1993146515Sru but they are supposed to be at the start of quotation 1994146515Sru blocks. So to avoid looking ahead mess, let's just 1995146515Sru use mdash like HTML for now. */ 1996146515Sru xml_insert_entity ("mdash"); 1997146515Sru add_word (rest); 1998146515Sru } 1999146515Sru else if (xml) 2000146515Sru { 2001146515Sru xml_insert_element (AUTHOR, START); 2002146515Sru add_word (rest); 2003146515Sru xml_insert_element (AUTHOR, END); 2004146515Sru } 2005146515Sru else 2006146515Sru add_word_args ("-- %s", rest); 2007146515Sru } 2008146515Sru else if (is_in_insertion_of_type (titlepage)) 2009146515Sru { 2010146515Sru if (xml && !docbook) 2011146515Sru { 2012146515Sru xml_insert_element (AUTHOR, START); 2013146515Sru add_word (rest); 2014146515Sru xml_insert_element (AUTHOR, END); 2015146515Sru } 2016146515Sru } 2017146515Sru else 2018146515Sru line_error (_("@%s not meaningful outside `@titlepage' and `@quotation' environments"), 2019146515Sru command); 2020146515Sru 2021146515Sru free (rest); 2022146515Sru} 2023146515Sru 2024146515Sruvoid 2025146515Srucm_titlepage_cmds (void) 2026146515Sru{ 2027146515Sru char *rest; 2028146515Sru 2029146515Sru get_rest_of_line (1, &rest); 2030146515Sru 2031146515Sru if (!is_in_insertion_of_type (titlepage)) 2032146515Sru line_error (_("@%s not meaningful outside `@titlepage' environment"), 2033146515Sru command); 2034146515Sru 2035146515Sru if (xml && !docbook) 2036146515Sru { 2037146515Sru int elt = 0; 2038146515Sru 2039146515Sru if (STREQ (command, "title")) 2040146515Sru elt = BOOKTITLE; 2041146515Sru else if (STREQ (command, "subtitle")) 2042146515Sru elt = BOOKSUBTITLE; 2043146515Sru 2044146515Sru xml_insert_element (elt, START); 2045146515Sru add_word (rest); 2046146515Sru xml_insert_element (elt, END); 2047146515Sru } 2048146515Sru 2049146515Sru free (rest); 2050146515Sru} 2051146515Sru 205256160Sru/* End existing insertion block. */ 205356160Sruvoid 2054146515Srucm_end (void) 205556160Sru{ 205656160Sru char *temp; 2057146515Sru int type; 205856160Sru 2059146515Sru get_rest_of_line (0, &temp); 2060146515Sru 206156160Sru if (!insertion_level) 206256160Sru { 206356160Sru line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command); 206456160Sru return; 206556160Sru } 206656160Sru 206756160Sru if (temp[0] == 0) 206856160Sru line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command); 206956160Sru 207056160Sru type = find_type_from_name (temp); 207156160Sru 207256160Sru if (type == bad_type) 207356160Sru { 2074146515Sru line_error (_("Bad argument `%s' to `@%s', using `%s'"), 2075146515Sru temp, command, insertion_type_pname (current_insertion_type ())); 207656160Sru } 207793139Sru if (xml && type == menu) /* fixme */ 207893139Sru { 207993139Sru xml_end_menu (); 208093139Sru } 208156160Sru end_insertion (type); 208256160Sru free (temp); 208356160Sru} 208456160Sru 208556160Sru/* @itemx, @item. */ 208656160Sru 208756160Srustatic int itemx_flag = 0; 208856160Sru 208956160Sru/* Return whether CMD takes a brace-delimited {arg}. */ 2090146515Sruint 2091146515Srucommand_needs_braces (char *cmd) 209256160Sru{ 209356160Sru int i; 209456160Sru for (i = 0; command_table[i].name; i++) 209556160Sru { 209656160Sru if (STREQ (command_table[i].name, cmd)) 209756160Sru return command_table[i].argument_in_braces == BRACE_ARGS; 209856160Sru } 209956160Sru 210056160Sru return 0; /* macro or alias */ 210156160Sru} 210256160Sru 210356160Sru 210456160Sruvoid 2105146515Srucm_item (void) 210656160Sru{ 210756160Sru char *rest_of_line, *item_func; 210856160Sru 210956160Sru /* Can only hack "@item" while inside of an insertion. */ 211056160Sru if (insertion_level) 211156160Sru { 211256160Sru INSERTION_ELT *stack = insertion_stack; 211356160Sru int original_input_text_offset; 211456160Sru 211556160Sru skip_whitespace (); 211656160Sru original_input_text_offset = input_text_offset; 211756160Sru 211856160Sru get_rest_of_line (0, &rest_of_line); 211956160Sru item_func = current_item_function (); 212056160Sru 212156160Sru /* Do the right thing depending on which insertion function is active. */ 212256160Sru switch_top: 212356160Sru switch (stack->insertion) 212456160Sru { 212556160Sru case multitable: 212656160Sru multitable_item (); 212756160Sru /* Support text directly after the @item. */ 212856160Sru if (*rest_of_line) 212956160Sru { 213056160Sru line_number--; 213156160Sru input_text_offset = original_input_text_offset; 213256160Sru } 213356160Sru break; 213456160Sru 213556160Sru case ifclear: 213656160Sru case ifhtml: 213756160Sru case ifinfo: 213856160Sru case ifnothtml: 213956160Sru case ifnotinfo: 2140100513Sru case ifnotplaintext: 214156160Sru case ifnottex: 2142114472Sru case ifnotxml: 2143100513Sru case ifplaintext: 214456160Sru case ifset: 214556160Sru case iftex: 2146114472Sru case ifxml: 2147146515Sru case rawdocbook: 214856160Sru case rawhtml: 2149146515Sru case rawxml: 215056160Sru case rawtex: 215156160Sru case tex: 215256160Sru case cartouche: 215356160Sru stack = stack->next; 215456160Sru if (!stack) 215556160Sru goto no_insertion; 215656160Sru else 215756160Sru goto switch_top; 215856160Sru break; 215956160Sru 216056160Sru case menu: 216156160Sru case quotation: 216256160Sru case example: 216356160Sru case smallexample: 216456160Sru case lisp: 216556160Sru case smalllisp: 216656160Sru case format: 216756160Sru case smallformat: 216856160Sru case display: 216956160Sru case smalldisplay: 217056160Sru case group: 217156160Sru line_error (_("@%s not meaningful inside `@%s' block"), 217256160Sru command, 217356160Sru insertion_type_pname (current_insertion_type ())); 217456160Sru break; 217556160Sru 217656160Sru case itemize: 217756160Sru case enumerate: 217856160Sru if (itemx_flag) 217956160Sru { 218056160Sru line_error (_("@itemx not meaningful inside `%s' block"), 218156160Sru insertion_type_pname (current_insertion_type ())); 218256160Sru } 218356160Sru else 218456160Sru { 218556160Sru if (html) 2186146515Sru add_html_block_elt ("<li>"); 2187114472Sru else if (xml) 2188114472Sru xml_begin_item (); 218956160Sru else 219056160Sru { 219156160Sru start_paragraph (); 219256160Sru kill_self_indent (-1); 219356160Sru filling_enabled = indented_fill = 1; 219456160Sru 219556160Sru if (current_item_function ()) 219656160Sru { 219756160Sru output_column = current_indent - 2; 219856160Sru indent (output_column); 219956160Sru 220056160Sru /* The item marker can be given with or without 220156160Sru braces -- @bullet and @bullet{} are both ok. 220256160Sru Or it might be something that doesn't take 220356160Sru braces at all, such as "o" or "#" or "@ ". 220456160Sru Thus, only supply braces if the item marker is 220556160Sru a command, they haven't supplied braces 220656160Sru themselves, and we know it needs them. */ 220756160Sru if (item_func && *item_func) 220856160Sru { 220956160Sru if (*item_func == COMMAND_PREFIX 221056160Sru && item_func[strlen (item_func) - 1] != '}' 221156160Sru && command_needs_braces (item_func + 1)) 221256160Sru execute_string ("%s{}", item_func); 221356160Sru else 221456160Sru execute_string ("%s", item_func); 221556160Sru } 221656160Sru insert (' '); 221756160Sru output_column++; 221856160Sru } 221956160Sru else 222056160Sru enumerate_item (); 222156160Sru 222256160Sru /* Special hack. This makes `close_paragraph' a no-op until 222356160Sru `start_paragraph' has been called. */ 222456160Sru must_start_paragraph = 1; 222556160Sru } 222656160Sru 2227114472Sru /* Handle text directly after the @item. */ 2228114472Sru if (*rest_of_line) 2229114472Sru { 2230114472Sru line_number--; 2231114472Sru input_text_offset = original_input_text_offset; 2232114472Sru } 223356160Sru } 223456160Sru break; 223556160Sru 223656160Sru case table: 223756160Sru case ftable: 223856160Sru case vtable: 223956160Sru if (html) 2240146515Sru { /* If nothing has been output since the last <dd>, 224156160Sru remove the empty <dd> element. Some browsers render 224256160Sru an extra empty line for <dd><dt>, which makes @itemx 224356160Sru conversion look ugly. */ 2244146515Sru rollback_empty_tag ("dd"); 224556160Sru 224656160Sru /* Force the browser to render one blank line before 2247114472Sru each new @item in a table. But don't do that if 224856160Sru this is the first <dt> after the <dl>, or if we are 224956160Sru converting @itemx. 225056160Sru 225156160Sru Note that there are some browsers which ignore <br> 225256160Sru in this context, but I cannot find any way to force 225356160Sru them all render exactly one blank line. */ 2254146515Sru if (!itemx_flag && html_deflist_has_term) 2255146515Sru add_html_block_elt ("<br>"); 2256146515Sru 2257146515Sru /* We are about to insert a <dt>, so this <dl> has a term. 2258146515Sru Feel free to insert a <br> next time. :) */ 2259146515Sru html_deflist_has_term = 1; 226056160Sru 2261146515Sru add_html_block_elt ("<dt>"); 226256160Sru if (item_func && *item_func) 226356160Sru execute_string ("%s{%s}", item_func, rest_of_line); 226456160Sru else 226556160Sru execute_string ("%s", rest_of_line); 226656160Sru 226756160Sru if (current_insertion_type () == ftable) 226856160Sru execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 226956160Sru 227056160Sru if (current_insertion_type () == vtable) 227156160Sru execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 2272146515Sru 2273146515Sru add_html_block_elt ("<dd>"); 227456160Sru } 2275114472Sru else if (xml) /* && docbook)*/ /* 05-08 */ 2276114472Sru { 2277114472Sru xml_begin_table_item (); 2278146515Sru 2279146515Sru if (!docbook && current_insertion_type () == ftable) 2280146515Sru execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 2281146515Sru 2282146515Sru if (!docbook && current_insertion_type () == vtable) 2283146515Sru execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 2284146515Sru 228593139Sru if (item_func && *item_func) 228693139Sru execute_string ("%s{%s}", item_func, rest_of_line); 228793139Sru else 228893139Sru execute_string ("%s", rest_of_line); 2289114472Sru xml_continue_table_item (); 2290114472Sru } 229156160Sru else 229256160Sru { 229356160Sru /* We need this to determine if we have two @item's in a row 229456160Sru (see test just below). */ 229556160Sru static int last_item_output_position = 0; 229656160Sru 229756160Sru /* Get rid of extra characters. */ 229856160Sru kill_self_indent (-1); 229956160Sru 230056160Sru /* If we have one @item followed directly by another @item, 230156160Sru we need to insert a blank line. This is not true for 230256160Sru @itemx, though. */ 230356160Sru if (!itemx_flag && last_item_output_position == output_position) 230456160Sru insert ('\n'); 230556160Sru 230656160Sru /* `close_paragraph' almost does what we want. The problem 230756160Sru is when paragraph_is_open, and last_char_was_newline, and 230856160Sru the last newline has been turned into a space, because 230956160Sru filling_enabled. I handle it here. */ 231056160Sru if (last_char_was_newline && filling_enabled && 231156160Sru paragraph_is_open) 231256160Sru insert ('\n'); 231356160Sru close_paragraph (); 231456160Sru 231556160Sru#if defined (INDENT_PARAGRAPHS_IN_TABLE) 231656160Sru /* Indent on a new line, but back up one indentation level. */ 231756160Sru { 231856160Sru int save = inhibit_paragraph_indentation; 231956160Sru inhibit_paragraph_indentation = 1; 232056160Sru /* At this point, inserting any non-whitespace character will 232156160Sru force the existing indentation to be output. */ 232256160Sru add_char ('i'); 232356160Sru inhibit_paragraph_indentation = save; 232456160Sru } 232556160Sru#else /* !INDENT_PARAGRAPHS_IN_TABLE */ 232656160Sru add_char ('i'); 232756160Sru#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 232856160Sru 232956160Sru output_paragraph_offset--; 233056160Sru kill_self_indent (default_indentation_increment + 1); 233156160Sru 233256160Sru /* Add item's argument to the line. */ 233356160Sru filling_enabled = 0; 233456160Sru if (item_func && *item_func) 233556160Sru execute_string ("%s{%s}", item_func, rest_of_line); 233656160Sru else 233756160Sru execute_string ("%s", rest_of_line); 233856160Sru 233956160Sru if (current_insertion_type () == ftable) 234056160Sru execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 234156160Sru else if (current_insertion_type () == vtable) 234256160Sru execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 234356160Sru 234456160Sru /* Start a new line, and let start_paragraph () 234556160Sru do the indenting of it for you. */ 234656160Sru close_single_paragraph (); 234756160Sru indented_fill = filling_enabled = 1; 234856160Sru last_item_output_position = output_position; 234956160Sru } 235056160Sru } 235156160Sru free (rest_of_line); 235256160Sru } 235356160Sru else 235456160Sru { 235556160Sru no_insertion: 235656160Sru line_error (_("%c%s found outside of an insertion block"), 235756160Sru COMMAND_PREFIX, command); 235856160Sru } 235956160Sru} 236056160Sru 236156160Sruvoid 2362146515Srucm_itemx (void) 236356160Sru{ 236456160Sru itemx_flag++; 236556160Sru cm_item (); 236656160Sru itemx_flag--; 236756160Sru} 2368146515Sru 2369146515Sruint headitem_flag = 0; 2370146515Sru 2371146515Sruvoid 2372146515Srucm_headitem (void) 2373146515Sru{ 2374146515Sru headitem_flag = 1; 2375146515Sru cm_item (); 2376146515Sru} 2377