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