insertion.c revision 100513
1/* insertion.c -- insertions for Texinfo. 2 $Id: insertion.c,v 1.47 2002/04/01 14:01:36 karl Exp $ 3 4 Copyright (C) 1998, 99, 2000, 01, 02 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software Foundation, 18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20#include "system.h" 21#include "cmds.h" 22#include "defun.h" 23#include "insertion.h" 24#include "macro.h" 25#include "makeinfo.h" 26#include "xml.h" 27 28/* Must match list in insertion.h. */ 29static char *insertion_type_names[] = 30{ 31 "cartouche", "copying", "defcv", "deffn", "defivar", "defmac", 32 "defmethod", "defop", "defopt", "defspec", "deftp", "deftypefn", 33 "deftypefun", "deftypeivar", "deftypemethod", "deftypeop", 34 "deftypevar", "deftypevr", "defun", "defvar", "defvr", "detailmenu", 35 "direntry", "display", "documentdescription", "enumerate", "example", 36 "flushleft", "flushright", "format", "ftable", "group", "ifclear", 37 "ifhtml", "ifinfo", "ifnothtml", "ifnotinfo", "ifnotplaintext", "ifnottex", 38 "ifplaintext", "ifset", "iftex", "itemize", "lisp", "menu", 39 "multitable", "quotation", "rawhtml", "rawtex", "smalldisplay", 40 "smallexample", "smallformat", "smalllisp", "verbatim", "table", 41 "tex", "vtable", "bad_type" 42}; 43 44/* All nested environments. */ 45INSERTION_ELT *insertion_stack = NULL; 46 47/* How deeply we're nested. */ 48int insertion_level = 0; 49 50/* Set to 1 if we've processed (commentary) text in a @menu that 51 wasn't part of a menu item. */ 52int had_menu_commentary; 53 54/* How to examine menu lines. */ 55int in_detailmenu = 0; 56 57/* Whether to examine menu lines. */ 58int in_menu = 0; 59 60/* Set to 1 if <p> is written in normal context. 61 Used for menu and itemize. */ 62int in_paragraph = 0; 63 64static const char dl_tag[] = "<dl>\n"; 65extern void cm_insert_copying (); 66 67 68void 69init_insertion_stack () 70{ 71 insertion_stack = NULL; 72} 73 74/* Return the type of the current insertion. */ 75static enum insertion_type 76current_insertion_type () 77{ 78 return insertion_level ? insertion_stack->insertion : bad_type; 79} 80 81/* Return the string which is the function to wrap around items, or NULL 82 if we're not in an environment where @item is ok. */ 83static char * 84current_item_function () 85{ 86 int done = 0; 87 INSERTION_ELT *elt = insertion_stack; 88 89 /* Skip down through the stack until we find an insertion with an 90 itemize function defined, i.e., skip conditionals, @cartouche, etc. */ 91 while (!done && elt) 92 { 93 switch (elt->insertion) 94 { 95 /* This list should match the one in cm_item. */ 96 case ifclear: 97 case ifhtml: 98 case ifinfo: 99 case ifnothtml: 100 case ifnotinfo: 101 case ifnotplaintext: 102 case ifnottex: 103 case ifplaintext: 104 case ifset: 105 case iftex: 106 case rawhtml: 107 case rawtex: 108 case tex: 109 case cartouche: 110 elt = elt->next; 111 break; 112 113 default: 114 done = 1; 115 } 116 } 117 118 /* item_function usually gets assigned the empty string. */ 119 return done && (*elt->item_function) ? elt->item_function : NULL; 120} 121 122/* Parse the item marker function off the input. If result is just "@", 123 change it to "@ ", since "@" by itself is not a command. This makes 124 "@ ", "@\t", and "@\n" all the same, but their default meanings are 125 the same anyway, and let's not worry about supporting redefining them. */ 126char * 127get_item_function () 128{ 129 char *item_function; 130 get_rest_of_line (0, &item_function); 131 132 /* If we hit the end of text in get_rest_of_line, backing up 133 input pointer will cause the last character of the last line 134 be pushed back onto the input, which is wrong. */ 135 if (input_text_offset < input_text_length) 136 backup_input_pointer (); 137 138 if (STREQ (item_function, "@")) 139 { 140 free (item_function); 141 item_function = xstrdup ("@ "); 142 } 143 144 return item_function; 145} 146 147 /* Push the state of the current insertion on the stack. */ 148void 149push_insertion (type, item_function) 150 enum insertion_type type; 151 char *item_function; 152{ 153 INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT)); 154 155 new->item_function = item_function; 156 new->filling_enabled = filling_enabled; 157 new->indented_fill = indented_fill; 158 new->insertion = type; 159 new->line_number = line_number; 160 new->filename = xstrdup (input_filename); 161 new->inhibited = inhibit_paragraph_indentation; 162 new->in_fixed_width_font = in_fixed_width_font; 163 new->next = insertion_stack; 164 insertion_stack = new; 165 insertion_level++; 166} 167 168 /* Pop the value on top of the insertion stack into the 169 global variables. */ 170void 171pop_insertion () 172{ 173 INSERTION_ELT *temp = insertion_stack; 174 175 if (temp == NULL) 176 return; 177 178 in_fixed_width_font = temp->in_fixed_width_font; 179 inhibit_paragraph_indentation = temp->inhibited; 180 filling_enabled = temp->filling_enabled; 181 indented_fill = temp->indented_fill; 182 free_and_clear (&(temp->item_function)); 183 free_and_clear (&(temp->filename)); 184 insertion_stack = insertion_stack->next; 185 free (temp); 186 insertion_level--; 187} 188 189 /* Return a pointer to the print name of this 190 enumerated type. */ 191char * 192insertion_type_pname (type) 193 enum insertion_type type; 194{ 195 if ((int) type < (int) bad_type) 196 return insertion_type_names[(int) type]; 197 else 198 return _("Broken-Type in insertion_type_pname"); 199} 200 201/* Return the insertion_type associated with NAME. 202 If the type is not one of the known ones, return BAD_TYPE. */ 203enum insertion_type 204find_type_from_name (name) 205 char *name; 206{ 207 int index = 0; 208 while (index < (int) bad_type) 209 { 210 if (STREQ (name, insertion_type_names[index])) 211 return (enum insertion_type) index; 212 if (index == rawhtml && STREQ (name, "html")) 213 return rawhtml; 214 if (index == rawtex && STREQ (name, "tex")) 215 return rawtex; 216 index++; 217 } 218 return bad_type; 219} 220 221int 222defun_insertion (type) 223 enum insertion_type type; 224{ 225 return 0 226 || (type == defcv) 227 || (type == deffn) 228 || (type == defivar) 229 || (type == defmac) 230 || (type == defmethod) 231 || (type == defop) 232 || (type == defopt) 233 || (type == defspec) 234 || (type == deftp) 235 || (type == deftypefn) 236 || (type == deftypefun) 237 || (type == deftypeivar) 238 || (type == deftypemethod) 239 || (type == deftypeop) 240 || (type == deftypevar) 241 || (type == deftypevr) 242 || (type == defun) 243 || (type == defvar) 244 || (type == defvr) 245 ; 246} 247 248/* MAX_NS is the maximum nesting level for enumerations. I picked 100 249 which seemed reasonable. This doesn't control the number of items, 250 just the number of nested lists. */ 251#define max_stack_depth 100 252#define ENUM_DIGITS 1 253#define ENUM_ALPHA 2 254typedef struct { 255 int enumtype; 256 int enumval; 257} DIGIT_ALPHA; 258 259DIGIT_ALPHA enumstack[max_stack_depth]; 260int enumstack_offset = 0; 261int current_enumval = 1; 262int current_enumtype = ENUM_DIGITS; 263char *enumeration_arg = NULL; 264 265void 266start_enumerating (at, type) 267 int at, type; 268{ 269 if ((enumstack_offset + 1) == max_stack_depth) 270 { 271 line_error (_("Enumeration stack overflow")); 272 return; 273 } 274 enumstack[enumstack_offset].enumtype = current_enumtype; 275 enumstack[enumstack_offset].enumval = current_enumval; 276 enumstack_offset++; 277 current_enumval = at; 278 current_enumtype = type; 279} 280 281void 282stop_enumerating () 283{ 284 --enumstack_offset; 285 if (enumstack_offset < 0) 286 enumstack_offset = 0; 287 288 current_enumval = enumstack[enumstack_offset].enumval; 289 current_enumtype = enumstack[enumstack_offset].enumtype; 290} 291 292/* Place a letter or digits into the output stream. */ 293void 294enumerate_item () 295{ 296 char temp[10]; 297 298 if (current_enumtype == ENUM_ALPHA) 299 { 300 if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1)) 301 { 302 current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A'); 303 warning (_("lettering overflow, restarting at %c"), current_enumval); 304 } 305 sprintf (temp, "%c. ", current_enumval); 306 } 307 else 308 sprintf (temp, "%d. ", current_enumval); 309 310 indent (output_column += (current_indent - strlen (temp))); 311 add_word (temp); 312 current_enumval++; 313} 314 315static void 316enum_html () 317{ 318 char type; 319 int start; 320 321 if (isdigit (*enumeration_arg)) 322 { 323 type = '1'; 324 start = atoi (enumeration_arg); 325 } 326 else if (isupper (*enumeration_arg)) 327 { 328 type = 'A'; 329 start = *enumeration_arg - 'A' + 1; 330 } 331 else 332 { 333 type = 'a'; 334 start = *enumeration_arg - 'a' + 1; 335 } 336 337 add_word_args ("<ol type=%c start=%d>\n", type, start); 338} 339 340/* Conditionally parse based on the current command name. */ 341void 342command_name_condition () 343{ 344 char *discarder = xmalloc (8 + strlen (command)); 345 346 sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command); 347 discard_until (discarder); 348 discard_until ("\n"); 349 350 free (discarder); 351} 352 353/* This is where the work for all the "insertion" style 354 commands is done. A huge switch statement handles the 355 various setups, and generic code is on both sides. */ 356void 357begin_insertion (type) 358 enum insertion_type type; 359{ 360 int no_discard = 0; 361 362 if (defun_insertion (type)) 363 { 364 push_insertion (type, xstrdup ("")); 365 no_discard++; 366 } 367 else 368 { 369 push_insertion (type, get_item_function ()); 370 } 371 372 switch (type) 373 { 374 case menu: 375 if (!no_headers) 376 close_paragraph (); 377 378 filling_enabled = no_indent = 0; 379 inhibit_paragraph_indentation = 1; 380 381 if (html) 382 { 383 had_menu_commentary = 1; 384 } 385 else if (!no_headers && !xml) 386 add_word ("* Menu:\n"); 387 388 if (xml) 389 xml_insert_element (MENU, START); 390 391 next_menu_item_number = 1; 392 in_menu++; 393 in_fixed_width_font++; 394 no_discard++; 395 break; 396 397 case detailmenu: 398 if (!in_menu) 399 { 400 if (!no_headers) 401 close_paragraph (); 402 403 filling_enabled = no_indent = 0; 404 inhibit_paragraph_indentation = 1; 405 406 no_discard++; 407 } 408 409 in_fixed_width_font++; 410 in_detailmenu++; 411 break; 412 413 case direntry: 414 close_single_paragraph (); 415 filling_enabled = no_indent = 0; 416 inhibit_paragraph_indentation = 1; 417 insert_string ("START-INFO-DIR-ENTRY\n"); 418 break; 419 420 case documentdescription: 421 { 422 char *desc; 423 int start_of_end; 424 int save_fixed_width; 425 426 discard_until ("\n"); /* ignore the @documentdescription line */ 427 start_of_end = get_until ("\n@end documentdescription", &desc); 428 save_fixed_width = in_fixed_width_font; 429 430 in_fixed_width_font = 0; 431 document_description = expansion (desc, 0); 432 free (desc); 433 434 in_fixed_width_font = save_fixed_width; 435 input_text_offset = start_of_end; /* go back to the @end to match */ 436 } 437 break; 438 439 case copying: 440 { 441 /* Save the copying text away for @insertcopying, 442 typically used on the back of the @titlepage (for TeX) and 443 the Top node (for info/html). */ 444 char *text; 445 int start_of_end; 446 447 discard_until ("\n"); /* ignore remainder of @copying line */ 448 start_of_end = get_until ("\n@end copying", &text); 449 450 /* include all the output-format-specific markup. */ 451 copying_text = full_expansion (text, 0); 452 free (text); 453 454 input_text_offset = start_of_end; /* go back to the @end to match */ 455 } 456 457 /* For info, output the copying text right away, so it will end up 458 in the header of the Info file, before the first node, and thus 459 get copied automatically to all the split files. For xml, also 460 output it right away since xml output is never split. 461 For html, we output it specifically in html_output_head. 462 For plain text, there's no way to hide it, so the author must 463 use @insertcopying in the desired location. */ 464 if (!html && !no_headers) 465 cm_insert_copying (); 466 break; 467 468 case quotation: 469 /* @quotation does filling (@display doesn't). */ 470 if (html) 471 add_word ("<blockquote>\n"); 472 else 473 { 474 /* with close_single_paragraph, we get no blank line above 475 within @copying. */ 476 close_paragraph (); 477 last_char_was_newline = no_indent = 0; 478 indented_fill = filling_enabled = 1; 479 inhibit_paragraph_indentation = 1; 480 } 481 current_indent += default_indentation_increment; 482 break; 483 484 case display: 485 case smalldisplay: 486 case example: 487 case smallexample: 488 case lisp: 489 case smalllisp: 490 /* Like @display but without indentation. */ 491 case smallformat: 492 case format: 493 close_single_paragraph (); 494 inhibit_paragraph_indentation = 1; 495 in_fixed_width_font++; 496 filling_enabled = 0; 497 last_char_was_newline = 0; 498 499 if (html) 500 /* Kludge alert: if <pre> is followed by a newline, IE3 501 renders an extra blank line before the pre-formatted block. 502 Other browsers seem to not mind one way or the other. */ 503 add_word ("<br><pre>"); 504 505 if (type != format && type != smallformat) 506 current_indent += default_indentation_increment; 507 break; 508 509 case multitable: 510 do_multitable (); 511 break; 512 513 case table: 514 case ftable: 515 case vtable: 516 case itemize: 517 close_single_paragraph (); 518 current_indent += default_indentation_increment; 519 filling_enabled = indented_fill = 1; 520#if defined (INDENT_PARAGRAPHS_IN_TABLE) 521 inhibit_paragraph_indentation = 0; 522#else 523 inhibit_paragraph_indentation = 1; 524#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 525 526 /* Make things work for losers who forget the itemize syntax. */ 527 if (type == itemize) 528 { 529 if (!(*insertion_stack->item_function)) 530 { 531 free (insertion_stack->item_function); 532 insertion_stack->item_function = xstrdup ("@bullet"); 533 } 534 } 535 536 if (!*insertion_stack->item_function) 537 { 538 line_error (_("%s requires an argument: the formatter for %citem"), 539 insertion_type_pname (type), COMMAND_PREFIX); 540 } 541 542 if (html) 543 { 544 if (type == itemize) 545 { 546 add_word ("<ul>\n"); 547 in_paragraph = 0; 548 } 549 else 550 add_word (dl_tag); 551 } 552 if (xml) 553 xml_begin_table (type, insertion_stack->item_function); 554 break; 555 556 case enumerate: 557 close_single_paragraph (); 558 no_indent = 0; 559#if defined (INDENT_PARAGRAPHS_IN_TABLE) 560 inhibit_paragraph_indentation = 0; 561#else 562 inhibit_paragraph_indentation = 1; 563#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 564 565 current_indent += default_indentation_increment; 566 filling_enabled = indented_fill = 1; 567 568 if (html) 569 enum_html (); 570 571 if (xml) 572 xml_begin_enumerate (enumeration_arg); 573 574 if (isdigit (*enumeration_arg)) 575 start_enumerating (atoi (enumeration_arg), ENUM_DIGITS); 576 else 577 start_enumerating (*enumeration_arg, ENUM_ALPHA); 578 break; 579 580 /* @group does nothing special in makeinfo. */ 581 case group: 582 /* Only close the paragraph if we are not inside of an 583 @example-like environment. */ 584 if (xml) 585 xml_insert_element (GROUP, START); 586 else if (!insertion_stack->next 587 || (insertion_stack->next->insertion != display 588 && insertion_stack->next->insertion != smalldisplay 589 && insertion_stack->next->insertion != example 590 && insertion_stack->next->insertion != smallexample 591 && insertion_stack->next->insertion != lisp 592 && insertion_stack->next->insertion != smalllisp 593 && insertion_stack->next->insertion != format 594 && insertion_stack->next->insertion != smallformat 595 && insertion_stack->next->insertion != flushleft 596 && insertion_stack->next->insertion != flushright)) 597 close_single_paragraph (); 598 break; 599 600 /* Insertions that are no-ops in info, but do something in TeX. */ 601 case cartouche: 602 case ifclear: 603 case ifhtml: 604 case ifinfo: 605 case ifnothtml: 606 case ifnotinfo: 607 case ifnotplaintext: 608 case ifnottex: 609 case ifplaintext: 610 case ifset: 611 case iftex: 612 case rawtex: 613 if (in_menu) 614 no_discard++; 615 break; 616 617 case rawhtml: 618 escape_html = 0; 619 break; 620 621 case defcv: 622 case deffn: 623 case defivar: 624 case defmac: 625 case defmethod: 626 case defop: 627 case defopt: 628 case defspec: 629 case deftp: 630 case deftypefn: 631 case deftypefun: 632 case deftypeivar: 633 case deftypemethod: 634 case deftypeop: 635 case deftypevar: 636 case deftypevr: 637 case defun: 638 case defvar: 639 case defvr: 640 inhibit_paragraph_indentation = 1; 641 filling_enabled = indented_fill = 1; 642 current_indent += default_indentation_increment; 643 no_indent = 0; 644 break; 645 646 case flushleft: 647 close_single_paragraph (); 648 inhibit_paragraph_indentation = 1; 649 filling_enabled = indented_fill = no_indent = 0; 650 if (html) 651 add_word ("<div align=\"left\">"); 652 break; 653 654 case flushright: 655 close_single_paragraph (); 656 filling_enabled = indented_fill = no_indent = 0; 657 inhibit_paragraph_indentation = 1; 658 force_flush_right++; 659 if (html) 660 add_word ("<div align=\"right\">"); 661 break; 662 663 default: 664 line_error ("begin_insertion internal error: type=%d", type); 665 666 } 667 668 if (!no_discard) 669 discard_until ("\n"); 670} 671 672/* Try to end the insertion with the specified TYPE. With a value of 673 `bad_type', TYPE gets translated to match the value currently on top 674 of the stack. Otherwise, if TYPE doesn't match the top of the 675 insertion stack, give error. */ 676void 677end_insertion (type) 678 enum insertion_type type; 679{ 680 enum insertion_type temp_type; 681 682 if (!insertion_level) 683 return; 684 685 temp_type = current_insertion_type (); 686 687 if (type == bad_type) 688 type = temp_type; 689 690 if (type != temp_type) 691 { 692 line_error 693 (_("`@end' expected `%s', but saw `%s'"), 694 insertion_type_pname (temp_type), insertion_type_pname (type)); 695 return; 696 } 697 698 pop_insertion (); 699 700 if (xml) 701 { 702 switch (type) 703 { 704 case ifinfo: 705 case documentdescription: 706 break; 707 case copying: 708 xml_insert_element (COPYING, END); 709 break; 710 case quotation: 711 xml_insert_element (QUOTATION, END); 712 break; 713 case example: 714 xml_insert_element (EXAMPLE, END); 715 break; 716 case smallexample: 717 xml_insert_element (SMALLEXAMPLE, END); 718 break; 719 case lisp: 720 xml_insert_element (LISP, END); 721 break; 722 case smalllisp: 723 xml_insert_element (SMALLLISP, END); 724 break; 725 case cartouche: 726 xml_insert_element (CARTOUCHE, END); 727 break; 728 case format: 729 xml_insert_element (FORMAT, END); 730 break; 731 case smallformat: 732 xml_insert_element (SMALLFORMAT, END); 733 break; 734 case display: 735 xml_insert_element (DISPLAY, END); 736 break; 737 case smalldisplay: 738 xml_insert_element (SMALLDISPLAY, END); 739 break; 740 case table: 741 case ftable: 742 case vtable: 743 case itemize: 744 xml_end_table (type); 745 break; 746 case enumerate: 747 xml_end_enumerate (type); 748 break; 749 case group: 750 xml_insert_element (GROUP, END); 751 break; 752 } 753 } 754 switch (type) 755 { 756 /* Insertions which have no effect on paragraph formatting. */ 757 case copying: 758 case documentdescription: 759 case ifclear: 760 case ifinfo: 761 case ifhtml: 762 case ifnothtml: 763 case ifnotinfo: 764 case ifnotplaintext: 765 case ifnottex: 766 case ifplaintext: 767 case ifset: 768 case iftex: 769 case rawtex: 770 break; 771 772 case rawhtml: 773 escape_html = 1; 774 break; 775 776 case detailmenu: 777 in_detailmenu--; /* No longer hacking menus. */ 778 if (!in_menu) 779 { 780 if (!no_headers) 781 close_insertion_paragraph (); 782 } 783 break; 784 785 case direntry: /* Eaten if html. */ 786 insert_string ("END-INFO-DIR-ENTRY\n\n"); 787 close_insertion_paragraph (); 788 break; 789 790 case menu: 791 in_menu--; /* No longer hacking menus. */ 792 if (html) 793 add_word ("</ul>\n"); 794 else if (!no_headers) 795 close_insertion_paragraph (); 796 break; 797 798 case multitable: 799 end_multitable (); 800 break; 801 802 case enumerate: 803 stop_enumerating (); 804 close_insertion_paragraph (); 805 current_indent -= default_indentation_increment; 806 if (html) 807 add_word ("</ol>\n"); 808 break; 809 810 case flushleft: 811 if (html) 812 add_word ("</div>\n"); 813 close_insertion_paragraph (); 814 break; 815 816 case group: 817 case cartouche: 818 close_insertion_paragraph (); 819 break; 820 821 case format: 822 case smallformat: 823 case display: 824 case smalldisplay: 825 case example: 826 case smallexample: 827 case lisp: 828 case smalllisp: 829 case quotation: 830 /* @format and @smallformat are the only fixed_width insertion 831 without a change in indentation. */ 832 if (type != format && type != smallformat) 833 current_indent -= default_indentation_increment; 834 835 if (html) 836 add_word (type == quotation ? "</blockquote>\n" : "</pre>\n"); 837 838 /* The ending of one of these insertions always marks the 839 start of a new paragraph. */ 840 close_insertion_paragraph (); 841 break; 842 843 case table: 844 case ftable: 845 case vtable: 846 current_indent -= default_indentation_increment; 847 if (html) 848 add_word ("</dl>\n"); 849 break; 850 851 case itemize: 852 current_indent -= default_indentation_increment; 853 if (html) 854 add_word ("</ul>\n"); 855 close_insertion_paragraph (); 856 break; 857 858 case flushright: 859 force_flush_right--; 860 if (html) 861 add_word ("</div>\n"); 862 close_insertion_paragraph (); 863 break; 864 865 /* Handle the @defun insertions with this default clause. */ 866 default: 867 { 868 enum insertion_type base_type; 869 870 if (type < defcv || type > defvr) 871 line_error ("end_insertion internal error: type=%d", type); 872 873 base_type = get_base_type (type); 874 switch (base_type) 875 { 876 case deffn: 877 case defvr: 878 case deftp: 879 case deftypefn: 880 case deftypevr: 881 case defcv: 882 case defop: 883 case deftypemethod: 884 case deftypeop: 885 case deftypeivar: 886 if (html) 887 /* close the tables which has been opened in defun.c */ 888 add_word ("</td></tr>\n</table>\n"); 889 break; 890 } /* switch (base_type)... */ 891 892 current_indent -= default_indentation_increment; 893 close_insertion_paragraph (); 894 } 895 break; 896 897 } 898 899 if (current_indent < 0) 900 line_error ("end_insertion internal error: current indent=%d", 901 current_indent); 902} 903 904/* Insertions cannot cross certain boundaries, such as node beginnings. In 905 code that creates such boundaries, you should call `discard_insertions' 906 before doing anything else. It prints the errors for you, and cleans up 907 the insertion stack. 908 909 With nonzero SPECIALS_OK argument, allows unmatched 910 @if... conditionals, otherwise not. This is because conditionals can 911 cross node boundaries. Always happens with the @top node, for example. */ 912void 913discard_insertions (specials_ok) 914 int specials_ok; 915{ 916 int real_line_number = line_number; 917 while (insertion_stack) 918 { 919 if (specials_ok 920 && ((ifclear <= insertion_stack->insertion 921 && insertion_stack->insertion <= iftex) 922 || insertion_stack->insertion == rawhtml 923 || insertion_stack->insertion == rawtex)) 924 break; 925 else 926 { 927 char *offender = insertion_type_pname (insertion_stack->insertion); 928 929 file_line_error (insertion_stack->filename, 930 insertion_stack->line_number, 931 _("No matching `%cend %s'"), COMMAND_PREFIX, 932 offender); 933 pop_insertion (); 934 } 935 } 936 line_number = real_line_number; 937} 938 939/* Insertion (environment) commands. */ 940 941void 942cm_quotation () 943{ 944 if (xml) 945 xml_insert_element (QUOTATION, START); 946 begin_insertion (quotation); 947} 948 949void 950cm_example () 951{ 952 if (xml) 953 xml_insert_element (EXAMPLE, START); 954 begin_insertion (example); 955} 956 957void 958cm_smallexample () 959{ 960 if (xml) 961 xml_insert_element (SMALLEXAMPLE, START); 962 begin_insertion (smallexample); 963} 964 965void 966cm_lisp () 967{ 968 if (xml) 969 xml_insert_element (LISP, START); 970 begin_insertion (lisp); 971} 972 973void 974cm_smalllisp () 975{ 976 if (xml) 977 xml_insert_element (SMALLLISP, START); 978 begin_insertion (smalllisp); 979} 980 981void 982cm_cartouche () 983{ 984 if (xml) 985 xml_insert_element (CARTOUCHE, START); 986 begin_insertion (cartouche); 987} 988 989void 990cm_copying () 991{ 992 if (xml) 993 xml_insert_element (COPYING, START); 994 begin_insertion (copying); 995} 996 997/* Not an insertion, despite the name, but it goes with cm_copying. */ 998void 999cm_insert_copying () 1000{ 1001 if (copying_text) 1002 { /* insert_string rather than add_word because we've already done 1003 full expansion on copying_text when we saved it. */ 1004 insert_string (copying_text); 1005 insert ('\n'); 1006 } 1007} 1008 1009void 1010cm_format () 1011{ 1012 if (xml) 1013 xml_insert_element (FORMAT, START); 1014 begin_insertion (format); 1015} 1016 1017void 1018cm_smallformat () 1019{ 1020 if (xml) 1021 xml_insert_element (SMALLFORMAT, START); 1022 begin_insertion (smallformat); 1023} 1024 1025void 1026cm_display () 1027{ 1028 if (xml) 1029 xml_insert_element (DISPLAY, START); 1030 begin_insertion (display); 1031} 1032 1033void 1034cm_smalldisplay () 1035{ 1036 if (xml) 1037 xml_insert_element (SMALLDISPLAY, START); 1038 begin_insertion (smalldisplay); 1039} 1040 1041void 1042cm_direntry () 1043{ 1044 if (html || xml) 1045 command_name_condition (); 1046 else 1047 begin_insertion (direntry); 1048} 1049 1050void 1051cm_documentdescription () 1052{ 1053 if (html || xml) 1054 begin_insertion (documentdescription); 1055 else 1056 command_name_condition (); 1057} 1058 1059 1060void 1061cm_itemize () 1062{ 1063 begin_insertion (itemize); 1064} 1065 1066/* Start an enumeration insertion of type TYPE. If the user supplied 1067 no argument on the line, then use DEFAULT_STRING as the initial string. */ 1068static void 1069do_enumeration (type, default_string) 1070 int type; 1071 char *default_string; 1072{ 1073 get_until_in_line (0, ".", &enumeration_arg); 1074 canon_white (enumeration_arg); 1075 1076 if (!*enumeration_arg) 1077 { 1078 free (enumeration_arg); 1079 enumeration_arg = xstrdup (default_string); 1080 } 1081 1082 if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg)) 1083 { 1084 warning (_("%s requires letter or digit"), insertion_type_pname (type)); 1085 1086 switch (type) 1087 { 1088 case enumerate: 1089 default_string = "1"; 1090 break; 1091 } 1092 enumeration_arg = xstrdup (default_string); 1093 } 1094 begin_insertion (type); 1095} 1096 1097void 1098cm_enumerate () 1099{ 1100 do_enumeration (enumerate, "1"); 1101} 1102 1103/* Handle verbatim environment: 1104 find_end_verbatim == 0: process until end of file 1105 find_end_verbatim != 0: process until 'COMMAND_PREFIXend verbatim' 1106 or end of file 1107 1108 We cannot simply copy input stream onto output stream; as the 1109 verbatim environment may be encapsulated in an @example environment, 1110 for example. */ 1111void 1112handle_verbatim_environment (find_end_verbatim) 1113 int find_end_verbatim; 1114{ 1115 int character; 1116 int seen_end = 0; 1117 int save_filling_enabled = filling_enabled; 1118 int save_inhibit_paragraph_indentation = inhibit_paragraph_indentation; 1119 1120 close_single_paragraph (); 1121 inhibit_paragraph_indentation = 1; 1122 filling_enabled = 0; 1123 in_fixed_width_font++; 1124 last_char_was_newline = 0; 1125 1126 /* No indentation: this is verbatim after all 1127 If you want indent, enclose @verbatim in @example 1128 current_indent += default_indentation_increment; 1129 */ 1130 1131 if (html) 1132 add_word ("<pre>"); 1133 1134 while (input_text_offset < input_text_length) 1135 { 1136 character = curchar (); 1137 1138 if (character == '\n') 1139 line_number++; 1140 /* 1141 Assume no newlines in END_VERBATIM 1142 */ 1143 else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */ 1144 && (input_text_length - input_text_offset > sizeof (END_VERBATIM)) 1145 && !strncmp (&input_text[input_text_offset+1], END_VERBATIM, 1146 sizeof (END_VERBATIM)-1)) 1147 { 1148 input_text_offset += sizeof (END_VERBATIM); 1149 seen_end = 1; 1150 break; 1151 } 1152 1153 add_char (character); 1154 input_text_offset++; 1155 } 1156 1157 if (find_end_verbatim && !seen_end) 1158 warning (_("end of file inside verbatim block")); 1159 1160 if (html) 1161 add_word ("</pre>"); 1162 1163 in_fixed_width_font--; 1164 filling_enabled = save_filling_enabled; 1165 inhibit_paragraph_indentation = save_inhibit_paragraph_indentation; 1166} 1167 1168void 1169cm_verbatim () 1170{ 1171 handle_verbatim_environment (1); 1172} 1173 1174void 1175cm_table () 1176{ 1177 begin_insertion (table); 1178} 1179 1180void 1181cm_multitable () 1182{ 1183 begin_insertion (multitable); /* @@ */ 1184} 1185 1186void 1187cm_ftable () 1188{ 1189 begin_insertion (ftable); 1190} 1191 1192void 1193cm_vtable () 1194{ 1195 begin_insertion (vtable); 1196} 1197 1198void 1199cm_group () 1200{ 1201 begin_insertion (group); 1202} 1203 1204/* Insert raw HTML (no escaping of `<' etc.). */ 1205void 1206cm_html () 1207{ 1208 if (process_html) 1209 begin_insertion (rawhtml); 1210 else 1211 command_name_condition (); 1212} 1213 1214void 1215cm_ifhtml () 1216{ 1217 if (process_html) 1218 begin_insertion (ifhtml); 1219 else 1220 command_name_condition (); 1221} 1222 1223void 1224cm_ifnothtml () 1225{ 1226 if (!process_html) 1227 begin_insertion (ifnothtml); 1228 else 1229 command_name_condition (); 1230} 1231 1232 1233void 1234cm_ifinfo () 1235{ 1236 if (process_info) 1237 begin_insertion (ifinfo); 1238 else 1239 command_name_condition (); 1240} 1241 1242void 1243cm_ifnotinfo () 1244{ 1245 if (!process_info) 1246 begin_insertion (ifnotinfo); 1247 else 1248 command_name_condition (); 1249} 1250 1251 1252void 1253cm_ifplaintext () 1254{ 1255 if (process_plaintext) 1256 begin_insertion (ifplaintext); 1257 else 1258 command_name_condition (); 1259} 1260 1261void 1262cm_ifnotplaintext () 1263{ 1264 if (!process_plaintext) 1265 begin_insertion (ifnotplaintext); 1266 else 1267 command_name_condition (); 1268} 1269 1270 1271void 1272cm_tex () 1273{ 1274 if (process_tex) 1275 begin_insertion (rawtex); 1276 else 1277 command_name_condition (); 1278} 1279 1280void 1281cm_iftex () 1282{ 1283 if (process_tex) 1284 begin_insertion (iftex); 1285 else 1286 command_name_condition (); 1287} 1288 1289void 1290cm_ifnottex () 1291{ 1292 if (!process_tex) 1293 begin_insertion (ifnottex); 1294 else 1295 command_name_condition (); 1296} 1297 1298/* Begin an insertion where the lines are not filled or indented. */ 1299void 1300cm_flushleft () 1301{ 1302 begin_insertion (flushleft); 1303} 1304 1305/* Begin an insertion where the lines are not filled, and each line is 1306 forced to the right-hand side of the page. */ 1307void 1308cm_flushright () 1309{ 1310 begin_insertion (flushright); 1311} 1312 1313void 1314cm_menu () 1315{ 1316 if (current_node == NULL) 1317 { 1318 warning (_("@menu seen before first @node, creating `Top' node")); 1319 warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?")); 1320 /* Include @top command so we can construct the implicit node tree. */ 1321 execute_string ("@node top\n@top Top\n"); 1322 } 1323 begin_insertion (menu); 1324} 1325 1326void 1327cm_detailmenu () 1328{ 1329 if (current_node == NULL) 1330 { /* Problems anyway, @detailmenu should always be inside @menu. */ 1331 warning (_("@detailmenu seen before first node, creating `Top' node")); 1332 execute_string ("@node top\n@top Top\n"); 1333 } 1334 begin_insertion (detailmenu); 1335} 1336 1337/* End existing insertion block. */ 1338void 1339cm_end () 1340{ 1341 char *temp; 1342 enum insertion_type type; 1343 1344 if (!insertion_level) 1345 { 1346 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command); 1347 return; 1348 } 1349 1350 get_rest_of_line (0, &temp); 1351 1352 if (temp[0] == 0) 1353 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command); 1354 1355 type = find_type_from_name (temp); 1356 1357 if (type == bad_type) 1358 { 1359 line_error (_("Bad argument to `%s', `%s', using `%s'"), 1360 command, temp, insertion_type_pname (current_insertion_type ())); 1361 } 1362 if (xml && type == menu) /* fixme */ 1363 { 1364 xml_end_menu (); 1365 } 1366 end_insertion (type); 1367 free (temp); 1368} 1369 1370/* @itemx, @item. */ 1371 1372static int itemx_flag = 0; 1373 1374/* Return whether CMD takes a brace-delimited {arg}. */ 1375/*static */int 1376command_needs_braces (cmd) 1377 char *cmd; 1378{ 1379 int i; 1380 for (i = 0; command_table[i].name; i++) 1381 { 1382 if (STREQ (command_table[i].name, cmd)) 1383 return command_table[i].argument_in_braces == BRACE_ARGS; 1384 } 1385 1386 return 0; /* macro or alias */ 1387} 1388 1389 1390void 1391cm_item () 1392{ 1393 char *rest_of_line, *item_func; 1394 1395 /* Can only hack "@item" while inside of an insertion. */ 1396 if (insertion_level) 1397 { 1398 INSERTION_ELT *stack = insertion_stack; 1399 int original_input_text_offset; 1400 1401 skip_whitespace (); 1402 original_input_text_offset = input_text_offset; 1403 1404 get_rest_of_line (0, &rest_of_line); 1405 item_func = current_item_function (); 1406 1407 /* Do the right thing depending on which insertion function is active. */ 1408 switch_top: 1409 switch (stack->insertion) 1410 { 1411 case multitable: 1412 multitable_item (); 1413 /* Support text directly after the @item. */ 1414 if (*rest_of_line) 1415 { 1416 line_number--; 1417 input_text_offset = original_input_text_offset; 1418 } 1419 break; 1420 1421 case ifclear: 1422 case ifhtml: 1423 case ifinfo: 1424 case ifnothtml: 1425 case ifnotinfo: 1426 case ifnotplaintext: 1427 case ifnottex: 1428 case ifplaintext: 1429 case ifset: 1430 case iftex: 1431 case rawhtml: 1432 case rawtex: 1433 case tex: 1434 case cartouche: 1435 stack = stack->next; 1436 if (!stack) 1437 goto no_insertion; 1438 else 1439 goto switch_top; 1440 break; 1441 1442 case menu: 1443 case quotation: 1444 case example: 1445 case smallexample: 1446 case lisp: 1447 case smalllisp: 1448 case format: 1449 case smallformat: 1450 case display: 1451 case smalldisplay: 1452 case group: 1453 line_error (_("@%s not meaningful inside `@%s' block"), 1454 command, 1455 insertion_type_pname (current_insertion_type ())); 1456 break; 1457 1458 case itemize: 1459 case enumerate: 1460 if (itemx_flag) 1461 { 1462 line_error (_("@itemx not meaningful inside `%s' block"), 1463 insertion_type_pname (current_insertion_type ())); 1464 } 1465 else 1466 { 1467 if (html) 1468 { 1469 if (in_paragraph) 1470 { 1471 add_word ("</p>"); 1472 in_paragraph = 0; 1473 } 1474 add_word ("<li>"); 1475 } 1476 else if (xml) 1477 xml_begin_item (); 1478 else 1479 { 1480 start_paragraph (); 1481 kill_self_indent (-1); 1482 filling_enabled = indented_fill = 1; 1483 1484 if (current_item_function ()) 1485 { 1486 output_column = current_indent - 2; 1487 indent (output_column); 1488 1489 /* The item marker can be given with or without 1490 braces -- @bullet and @bullet{} are both ok. 1491 Or it might be something that doesn't take 1492 braces at all, such as "o" or "#" or "@ ". 1493 Thus, only supply braces if the item marker is 1494 a command, they haven't supplied braces 1495 themselves, and we know it needs them. */ 1496 if (item_func && *item_func) 1497 { 1498 if (*item_func == COMMAND_PREFIX 1499 && item_func[strlen (item_func) - 1] != '}' 1500 && command_needs_braces (item_func + 1)) 1501 execute_string ("%s{}", item_func); 1502 else 1503 execute_string ("%s", item_func); 1504 } 1505 insert (' '); 1506 output_column++; 1507 } 1508 else 1509 enumerate_item (); 1510 1511 /* Special hack. This makes `close_paragraph' a no-op until 1512 `start_paragraph' has been called. */ 1513 must_start_paragraph = 1; 1514 } 1515 1516 /* Handle text directly after the @item. */ 1517 if (*rest_of_line) 1518 { 1519 line_number--; 1520 input_text_offset = original_input_text_offset; 1521 } 1522 } 1523 break; 1524 1525 case table: 1526 case ftable: 1527 case vtable: 1528 if (html) 1529 { 1530 static int last_html_output_position = 0; 1531 1532 /* If nothing has been output since the last <dd>, 1533 remove the empty <dd> element. Some browsers render 1534 an extra empty line for <dd><dt>, which makes @itemx 1535 conversion look ugly. */ 1536 if (last_html_output_position == output_position 1537 && strncmp ((char *) output_paragraph, "<dd>", 1538 output_paragraph_offset) == 0) 1539 output_paragraph_offset = 0; 1540 1541 /* Force the browser to render one blank line before 1542 each new @item in a table. But don't do that unless 1543 this is the first <dt> after the <dl>, or if we are 1544 converting @itemx. 1545 1546 Note that there are some browsers which ignore <br> 1547 in this context, but I cannot find any way to force 1548 them all render exactly one blank line. */ 1549 if (!itemx_flag 1550 && strncmp ((char *) output_paragraph 1551 + output_paragraph_offset - sizeof (dl_tag) + 1, 1552 dl_tag, sizeof (dl_tag) - 1) != 0) 1553 add_word ("<br>"); 1554 1555 add_word ("<dt>"); 1556 if (item_func && *item_func) 1557 execute_string ("%s{%s}", item_func, rest_of_line); 1558 else 1559 execute_string ("%s", rest_of_line); 1560 1561 if (current_insertion_type () == ftable) 1562 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 1563 1564 if (current_insertion_type () == vtable) 1565 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 1566 /* Make sure output_position is updated, so we could 1567 remember it. */ 1568 close_single_paragraph (); 1569 last_html_output_position = output_position; 1570 add_word ("<dd>"); 1571 } 1572 else if (xml) /* && docbook)*/ /* 05-08 */ 1573 { 1574 xml_begin_table_item (); 1575 if (item_func && *item_func) 1576 execute_string ("%s{%s}", item_func, rest_of_line); 1577 else 1578 execute_string ("%s", rest_of_line); 1579 xml_continue_table_item (); 1580 } 1581 else 1582 { 1583 /* We need this to determine if we have two @item's in a row 1584 (see test just below). */ 1585 static int last_item_output_position = 0; 1586 1587 /* Get rid of extra characters. */ 1588 kill_self_indent (-1); 1589 1590 /* If we have one @item followed directly by another @item, 1591 we need to insert a blank line. This is not true for 1592 @itemx, though. */ 1593 if (!itemx_flag && last_item_output_position == output_position) 1594 insert ('\n'); 1595 1596 /* `close_paragraph' almost does what we want. The problem 1597 is when paragraph_is_open, and last_char_was_newline, and 1598 the last newline has been turned into a space, because 1599 filling_enabled. I handle it here. */ 1600 if (last_char_was_newline && filling_enabled && 1601 paragraph_is_open) 1602 insert ('\n'); 1603 close_paragraph (); 1604 1605#if defined (INDENT_PARAGRAPHS_IN_TABLE) 1606 /* Indent on a new line, but back up one indentation level. */ 1607 { 1608 int save = inhibit_paragraph_indentation; 1609 inhibit_paragraph_indentation = 1; 1610 /* At this point, inserting any non-whitespace character will 1611 force the existing indentation to be output. */ 1612 add_char ('i'); 1613 inhibit_paragraph_indentation = save; 1614 } 1615#else /* !INDENT_PARAGRAPHS_IN_TABLE */ 1616 add_char ('i'); 1617#endif /* !INDENT_PARAGRAPHS_IN_TABLE */ 1618 1619 output_paragraph_offset--; 1620 kill_self_indent (default_indentation_increment + 1); 1621 1622 /* Add item's argument to the line. */ 1623 filling_enabled = 0; 1624 if (item_func && *item_func) 1625 execute_string ("%s{%s}", item_func, rest_of_line); 1626 else 1627 execute_string ("%s", rest_of_line); 1628 1629 if (current_insertion_type () == ftable) 1630 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line); 1631 else if (current_insertion_type () == vtable) 1632 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); 1633 1634 /* Start a new line, and let start_paragraph () 1635 do the indenting of it for you. */ 1636 close_single_paragraph (); 1637 indented_fill = filling_enabled = 1; 1638 last_item_output_position = output_position; 1639 } 1640 } 1641 free (rest_of_line); 1642 } 1643 else 1644 { 1645 no_insertion: 1646 line_error (_("%c%s found outside of an insertion block"), 1647 COMMAND_PREFIX, command); 1648 } 1649} 1650 1651void 1652cm_itemx () 1653{ 1654 itemx_flag++; 1655 cm_item (); 1656 itemx_flag--; 1657} 1658