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