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