source: trunk/essentials/sys-apps/texinfo/makeinfo/insertion.c

Last change on this file was 2617, checked in by bird, 19 years ago

GNU Texinfo 4.8

File size: 60.8 KB
Line 
1/* insertion.c -- insertions for Texinfo.
2 $Id: insertion.c,v 1.55 2004/11/11 18:34:28 karl 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. */
33static 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. */
50INSERTION_ELT *insertion_stack = NULL;
51
52/* How deeply we're nested. */
53int 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. */
57int had_menu_commentary;
58
59/* How to examine menu lines. */
60int in_detailmenu = 0;
61
62/* Whether to examine menu lines. */
63int in_menu = 0;
64
65/* Set to 1 if <p> is written in normal context.
66 Used for menu and itemize. */
67int 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. */
73static int float_active = 0;
74
75/* Unsetting escape_html blindly causes text inside @html/etc. to be escaped if
76 used within a rmacro. */
77static 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. */
81static int html_deflist_has_term = 0;
82
83
84void
85init_insertion_stack (void)
86{
87 insertion_stack = NULL;
88}
89
90/* Return the type of the current insertion. */
91static enum insertion_type
92current_insertion_type (void)
93{
94 return insertion_level ? insertion_stack->insertion : bad_type;
95}
96
97/* Return the string which is the function to wrap around items, or NULL
98 if we're not in an environment where @item is ok. */
99static char *
100current_item_function (void)
101{
102 int done = 0;
103 INSERTION_ELT *elt = insertion_stack;
104
105 /* Skip down through the stack until we find an insertion with an
106 itemize function defined, i.e., skip conditionals, @cartouche, etc. */
107 while (!done && elt)
108 {
109 switch (elt->insertion)
110 {
111 /* This list should match the one in cm_item. */
112 case ifclear:
113 case ifhtml:
114 case ifinfo:
115 case ifnothtml:
116 case ifnotinfo:
117 case ifnotplaintext:
118 case ifnottex:
119 case ifnotxml:
120 case ifplaintext:
121 case ifset:
122 case iftex:
123 case ifxml:
124 case rawdocbook:
125 case rawhtml:
126 case rawxml:
127 case rawtex:
128 case tex:
129 case cartouche:
130 elt = elt->next;
131 break;
132
133 default:
134 done = 1;
135 }
136 }
137
138 /* item_function usually gets assigned the empty string. */
139 return done && (*elt->item_function) ? elt->item_function : NULL;
140}
141
142/* Parse the item marker function off the input. If result is just "@",
143 change it to "@ ", since "@" by itself is not a command. This makes
144 "@ ", "@\t", and "@\n" all the same, but their default meanings are
145 the same anyway, and let's not worry about supporting redefining them. */
146static char *
147get_item_function (void)
148{
149 char *item_function;
150 char *item_loc;
151
152 get_rest_of_line (0, &item_function);
153
154 /* If the document erroneously says
155 @itemize @bullet @item foobar
156 it's nicer to give an error up front than repeat `@bullet expected
157 braces' until we get a segmentation fault. */
158 item_loc = strstr (item_function, "@item");
159 if (item_loc)
160 {
161 line_error (_("@item not allowed in argument to @itemize"));
162 *item_loc = 0;
163 }
164
165 /* If we hit the end of text in get_rest_of_line, backing up
166 input pointer will cause the last character of the last line
167 be pushed back onto the input, which is wrong. */
168 if (input_text_offset < input_text_length)
169 backup_input_pointer ();
170
171 if (STREQ (item_function, "@"))
172 {
173 free (item_function);
174 item_function = xstrdup ("@ ");
175 }
176
177 return item_function;
178}
179
180 /* Push the state of the current insertion on the stack. */
181static void
182push_insertion (enum insertion_type type, char *item_function)
183{
184 INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT));
185
186 new->item_function = item_function;
187 new->filling_enabled = filling_enabled;
188 new->indented_fill = indented_fill;
189 new->insertion = type;
190 new->line_number = line_number;
191 new->filename = xstrdup (input_filename);
192 new->inhibited = inhibit_paragraph_indentation;
193 new->in_fixed_width_font = in_fixed_width_font;
194 new->next = insertion_stack;
195 insertion_stack = new;
196 insertion_level++;
197}
198
199 /* Pop the value on top of the insertion stack into the
200 global variables. */
201void
202pop_insertion (void)
203{
204 INSERTION_ELT *temp = insertion_stack;
205
206 if (temp == NULL)
207 return;
208
209 in_fixed_width_font = temp->in_fixed_width_font;
210 inhibit_paragraph_indentation = temp->inhibited;
211 filling_enabled = temp->filling_enabled;
212 indented_fill = temp->indented_fill;
213 free_and_clear (&(temp->item_function));
214 free_and_clear (&(temp->filename));
215 insertion_stack = insertion_stack->next;
216 free (temp);
217 insertion_level--;
218}
219
220 /* Return a pointer to the print name of this
221 enumerated type. */
222static const char *
223insertion_type_pname (enum insertion_type type)
224{
225 if ((int) type < (int) bad_type)
226 {
227 if (type == rawdocbook)
228 return "docbook";
229 else if (type == rawhtml)
230 return "html";
231 else if (type == rawxml)
232 return "xml";
233 else if (type == rawtex)
234 return "tex";
235 else
236 return insertion_type_names[(int) type];
237 }
238 else
239 return _("Broken-Type in insertion_type_pname");
240}
241
242/* Return the insertion_type associated with NAME.
243 If the type is not one of the known ones, return BAD_TYPE. */
244enum insertion_type
245find_type_from_name (char *name)
246{
247 int index = 0;
248 while (index < (int) bad_type)
249 {
250 if (STREQ (name, insertion_type_names[index]))
251 return (enum insertion_type) index;
252 if (index == rawdocbook && STREQ (name, "docbook"))
253 return rawdocbook;
254 if (index == rawhtml && STREQ (name, "html"))
255 return rawhtml;
256 if (index == rawxml && STREQ (name, "xml"))
257 return rawxml;
258 if (index == rawtex && STREQ (name, "tex"))
259 return rawtex;
260 index++;
261 }
262 return bad_type;
263}
264
265/* Simple function to query insertion_stack to see if we are inside a given
266 insertion type. */
267int
268is_in_insertion_of_type (int type)
269{
270 INSERTION_ELT *temp = insertion_stack;
271
272 if (!insertion_level)
273 return 0;
274
275 while (temp)
276 {
277 if (temp->insertion == type)
278 return 1;
279 temp = temp->next;
280 }
281
282 return 0;
283}
284
285
286static int
287defun_insertion (enum insertion_type type)
288{
289 return 0
290 || (type == defcv)
291 || (type == deffn)
292 || (type == defivar)
293 || (type == defmac)
294 || (type == defmethod)
295 || (type == defop)
296 || (type == defopt)
297 || (type == defspec)
298 || (type == deftp)
299 || (type == deftypecv)
300 || (type == deftypefn)
301 || (type == deftypefun)
302 || (type == deftypeivar)
303 || (type == deftypemethod)
304 || (type == deftypeop)
305 || (type == deftypevar)
306 || (type == deftypevr)
307 || (type == defun)
308 || (type == defvar)
309 || (type == defvr)
310 ;
311}
312
313/* MAX_NS is the maximum nesting level for enumerations. I picked 100
314 which seemed reasonable. This doesn't control the number of items,
315 just the number of nested lists. */
316#define max_stack_depth 100
317#define ENUM_DIGITS 1
318#define ENUM_ALPHA 2
319typedef struct {
320 int enumtype;
321 int enumval;
322} DIGIT_ALPHA;
323
324DIGIT_ALPHA enumstack[max_stack_depth];
325int enumstack_offset = 0;
326int current_enumval = 1;
327int current_enumtype = ENUM_DIGITS;
328char *enumeration_arg = NULL;
329
330static void
331start_enumerating (int at, int type)
332{
333 if ((enumstack_offset + 1) == max_stack_depth)
334 {
335 line_error (_("Enumeration stack overflow"));
336 return;
337 }
338 enumstack[enumstack_offset].enumtype = current_enumtype;
339 enumstack[enumstack_offset].enumval = current_enumval;
340 enumstack_offset++;
341 current_enumval = at;
342 current_enumtype = type;
343}
344
345static void
346stop_enumerating (void)
347{
348 --enumstack_offset;
349 if (enumstack_offset < 0)
350 enumstack_offset = 0;
351
352 current_enumval = enumstack[enumstack_offset].enumval;
353 current_enumtype = enumstack[enumstack_offset].enumtype;
354}
355
356/* Place a letter or digits into the output stream. */
357static void
358enumerate_item (void)
359{
360 char temp[10];
361
362 if (current_enumtype == ENUM_ALPHA)
363 {
364 if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
365 {
366 current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
367 warning (_("lettering overflow, restarting at %c"), current_enumval);
368 }
369 sprintf (temp, "%c. ", current_enumval);
370 }
371 else
372 sprintf (temp, "%d. ", current_enumval);
373
374 indent (output_column += (current_indent - strlen (temp)));
375 add_word (temp);
376 current_enumval++;
377}
378
379static void
380enum_html (void)
381{
382 char type;
383 int start;
384
385 if (isdigit (*enumeration_arg))
386 {
387 type = '1';
388 start = atoi (enumeration_arg);
389 }
390 else if (isupper (*enumeration_arg))
391 {
392 type = 'A';
393 start = *enumeration_arg - 'A' + 1;
394 }
395 else
396 {
397 type = 'a';
398 start = *enumeration_arg - 'a' + 1;
399 }
400
401 add_html_block_elt_args ("<ol type=%c start=%d>\n", type, start);
402}
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", &copying_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
1348/* Insertion (environment) commands. */
1349
1350void
1351cm_quotation (void)
1352{
1353 /* We start the blockquote element in the insertion. */
1354 begin_insertion (quotation);
1355}
1356
1357void
1358cm_example (void)
1359{
1360 if (docbook && current_insertion_type () == floatenv)
1361 xml_begin_docbook_float (FLOATEXAMPLE);
1362
1363 if (xml)
1364 {
1365 /* Rollback previous newlines. These occur between
1366 </para> and <example>. */
1367 if (output_paragraph[output_paragraph_offset-1] == '\n')
1368 output_paragraph_offset--;
1369
1370 xml_insert_element (EXAMPLE, START);
1371
1372 /* Make sure example text is starting on a new line
1373 for improved readability. */
1374 if (docbook)
1375 add_char ('\n');
1376 }
1377
1378 begin_insertion (example);
1379}
1380
1381void
1382cm_smallexample (void)
1383{
1384 if (docbook && current_insertion_type () == floatenv)
1385 xml_begin_docbook_float (FLOATEXAMPLE);
1386
1387 if (xml)
1388 {
1389 /* See cm_example comments about newlines. */
1390 if (output_paragraph[output_paragraph_offset-1] == '\n')
1391 output_paragraph_offset--;
1392 xml_insert_element (SMALLEXAMPLE, START);
1393 if (docbook)
1394 add_char ('\n');
1395 }
1396
1397 begin_insertion (smallexample);
1398}
1399
1400void
1401cm_lisp (void)
1402{
1403 if (docbook && current_insertion_type () == floatenv)
1404 xml_begin_docbook_float (FLOATEXAMPLE);
1405
1406 if (xml)
1407 {
1408 /* See cm_example comments about newlines. */
1409 if (output_paragraph[output_paragraph_offset-1] == '\n')
1410 output_paragraph_offset--;
1411 xml_insert_element (LISP, START);
1412 if (docbook)
1413 add_char ('\n');
1414 }
1415
1416 begin_insertion (lisp);
1417}
1418
1419void
1420cm_smalllisp (void)
1421{
1422 if (docbook && current_insertion_type () == floatenv)
1423 xml_begin_docbook_float (FLOATEXAMPLE);
1424
1425 if (xml)
1426 {
1427 /* See cm_example comments about newlines. */
1428 if (output_paragraph[output_paragraph_offset-1] == '\n')
1429 output_paragraph_offset--;
1430 xml_insert_element (SMALLLISP, START);
1431 if (docbook)
1432 add_char ('\n');
1433 }
1434
1435 begin_insertion (smalllisp);
1436}
1437
1438void
1439cm_cartouche (void)
1440{
1441 if (docbook && current_insertion_type () == floatenv)
1442 xml_begin_docbook_float (CARTOUCHE);
1443
1444 if (xml)
1445 xml_insert_element (CARTOUCHE, START);
1446 begin_insertion (cartouche);
1447}
1448
1449void
1450cm_copying (void)
1451{
1452 begin_insertion (copying);
1453}
1454
1455/* Not an insertion, despite the name, but it goes with cm_copying. */
1456void
1457cm_insert_copying (void)
1458{
1459 if (!copying_text)
1460 {
1461 warning ("@copying not used before %s", command);
1462 return;
1463 }
1464
1465 execute_string ("%s", copying_text);
1466
1467 if (!xml && !html)
1468 {
1469 add_word ("\n\n");
1470 /* Update output_position so that the node positions in the tag
1471 tables will take account of the copying text. */
1472 flush_output ();
1473 }
1474}
1475
1476void
1477cm_format (void)
1478{
1479 if (xml)
1480 {
1481 if (docbook && xml_in_bookinfo)
1482 {
1483 xml_insert_element (ABSTRACT, START);
1484 xml_in_abstract = 1;
1485 }
1486 else
1487 {
1488 /* See cm_example comments about newlines. */
1489 if (output_paragraph[output_paragraph_offset-1] == '\n')
1490 output_paragraph_offset--;
1491 xml_insert_element (FORMAT, START);
1492 if (docbook)
1493 add_char ('\n');
1494 }
1495 }
1496 begin_insertion (format);
1497}
1498
1499void
1500cm_smallformat (void)
1501{
1502 if (xml)
1503 {
1504 /* See cm_example comments about newlines. */
1505 if (output_paragraph[output_paragraph_offset-1] == '\n')
1506 output_paragraph_offset--;
1507 xml_insert_element (SMALLFORMAT, START);
1508 if (docbook)
1509 add_char ('\n');
1510 }
1511
1512 begin_insertion (smallformat);
1513}
1514
1515void
1516cm_display (void)
1517{
1518 if (xml)
1519 {
1520 /* See cm_example comments about newlines. */
1521 if (output_paragraph[output_paragraph_offset-1] == '\n')
1522 output_paragraph_offset--;
1523 xml_insert_element (DISPLAY, START);
1524 if (docbook)
1525 add_char ('\n');
1526 }
1527
1528 begin_insertion (display);
1529}
1530
1531void
1532cm_smalldisplay (void)
1533{
1534 if (xml)
1535 {
1536 /* See cm_example comments about newlines. */
1537 if (output_paragraph[output_paragraph_offset-1] == '\n')
1538 output_paragraph_offset--;
1539 xml_insert_element (SMALLDISPLAY, START);
1540 if (docbook)
1541 add_char ('\n');
1542 }
1543
1544 begin_insertion (smalldisplay);
1545}
1546
1547void
1548cm_direntry (void)
1549{
1550 if (html || xml || no_headers)
1551 command_name_condition ();
1552 else
1553 begin_insertion (direntry);
1554}
1555
1556void
1557cm_documentdescription (void)
1558{
1559 if (html)
1560 begin_insertion (documentdescription);
1561
1562 else if (xml)
1563 {
1564 xml_insert_element (DOCUMENTDESCRIPTION, START);
1565 begin_insertion (documentdescription);
1566 }
1567
1568 else
1569 command_name_condition ();
1570}
1571
1572
1573void
1574cm_itemize (void)
1575{
1576 begin_insertion (itemize);
1577}
1578
1579/* Start an enumeration insertion of type TYPE. If the user supplied
1580 no argument on the line, then use DEFAULT_STRING as the initial string. */
1581static void
1582do_enumeration (int type, char *default_string)
1583{
1584 get_until_in_line (0, ".", &enumeration_arg);
1585 canon_white (enumeration_arg);
1586
1587 if (!*enumeration_arg)
1588 {
1589 free (enumeration_arg);
1590 enumeration_arg = xstrdup (default_string);
1591 }
1592
1593 if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
1594 {
1595 warning (_("%s requires letter or digit"), insertion_type_pname (type));
1596
1597 switch (type)
1598 {
1599 case enumerate:
1600 default_string = "1";
1601 break;
1602 }
1603 enumeration_arg = xstrdup (default_string);
1604 }
1605 begin_insertion (type);
1606}
1607
1608void
1609cm_enumerate (void)
1610{
1611 do_enumeration (enumerate, "1");
1612}
1613
1614/* Handle verbatim environment:
1615 find_end_verbatim == 0: process until end of file
1616 find_end_verbatim != 0: process until 'COMMAND_PREFIXend verbatim'
1617 or end of file
1618
1619 We cannot simply copy input stream onto output stream; as the
1620 verbatim environment may be encapsulated in an @example environment,
1621 for example. */
1622void
1623handle_verbatim_environment (int find_end_verbatim)
1624{
1625 int character;
1626 int seen_end = 0;
1627 int save_filling_enabled = filling_enabled;
1628 int save_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
1629 int save_escape_html = escape_html;
1630
1631 if (!insertion_stack)
1632 close_single_paragraph (); /* no blank lines if not at outer level */
1633 inhibit_paragraph_indentation = 1;
1634 filling_enabled = 0;
1635 in_fixed_width_font++;
1636 last_char_was_newline = 0;
1637
1638 /* No indentation: this is verbatim after all
1639 If you want indent, enclose @verbatim in @example
1640 current_indent += default_indentation_increment;
1641 */
1642
1643 if (html)
1644 { /* If inside @example, we'll be preceded by the indentation
1645 already. Browsers will ignore those spaces because we're about
1646 to start another <pre> (don't ask me). So, wipe them out for
1647 cleanliness, and re-insert. */
1648 int i;
1649 kill_self_indent (default_indentation_increment);
1650 add_html_block_elt ("<pre class=\"verbatim\">");
1651 for (i = current_indent; i > 0; i--)
1652 add_char (' ');
1653 }
1654 else if (xml)
1655 {
1656 xml_insert_element (VERBATIM, START);
1657 escape_html = 0;
1658 add_word ("<![CDATA[");
1659 }
1660
1661 while (input_text_offset < input_text_length)
1662 {
1663 character = curchar ();
1664
1665 if (character == '\n')
1666 line_number++;
1667
1668 /* Assume no newlines in END_VERBATIM. */
1669 else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */
1670 && (input_text_length - input_text_offset > sizeof (END_VERBATIM))
1671 && !strncmp (&input_text[input_text_offset+1], END_VERBATIM,
1672 sizeof (END_VERBATIM)-1))
1673 {
1674 input_text_offset += sizeof (END_VERBATIM);
1675 seen_end = 1;
1676 break;
1677 }
1678
1679 if (html && character == '&' && escape_html)
1680 add_word ("&amp;");
1681 else if (html && character == '<' && escape_html)
1682 add_word ("&lt;");
1683 else
1684 add_char (character);
1685
1686 input_text_offset++;
1687 }
1688
1689 if (find_end_verbatim && !seen_end)
1690 warning (_("end of file inside verbatim block"));
1691
1692 if (html)
1693 { /* See comments in example case above. */
1694 kill_self_indent (default_indentation_increment);
1695 add_word ("</pre>");
1696 }
1697 else if (xml)
1698 {
1699 add_word ("]]>");
1700 xml_insert_element (VERBATIM, END);
1701 escape_html = save_escape_html;
1702 }
1703
1704 in_fixed_width_font--;
1705 filling_enabled = save_filling_enabled;
1706 inhibit_paragraph_indentation = save_inhibit_paragraph_indentation;
1707}
1708
1709void
1710cm_verbatim (void)
1711{
1712 handle_verbatim_environment (1);
1713}
1714
1715void
1716cm_table (void)
1717{
1718 begin_insertion (table);
1719}
1720
1721void
1722cm_multitable (void)
1723{
1724 begin_insertion (multitable); /* @@ */
1725}
1726
1727void
1728cm_ftable (void)
1729{
1730 begin_insertion (ftable);
1731}
1732
1733void
1734cm_vtable (void)
1735{
1736 begin_insertion (vtable);
1737}
1738
1739void
1740cm_group (void)
1741{
1742 begin_insertion (group);
1743}
1744
1745
1746/* Insert raw HTML (no escaping of `<' etc.). */
1747void
1748cm_html (int arg)
1749{
1750 if (process_html)
1751 begin_insertion (rawhtml);
1752 else
1753 command_name_condition ();
1754}
1755
1756void
1757cm_xml (int arg)
1758{
1759 if (process_xml)
1760 begin_insertion (rawxml);
1761 else
1762 command_name_condition ();
1763}
1764
1765void
1766cm_docbook (int arg)
1767{
1768 if (process_docbook)
1769 begin_insertion (rawdocbook);
1770 else
1771 command_name_condition ();
1772}
1773
1774void
1775cm_ifdocbook (void)
1776{
1777 if (process_docbook)
1778 begin_insertion (ifdocbook);
1779 else
1780 command_name_condition ();
1781}
1782
1783void
1784cm_ifnotdocbook (void)
1785{
1786 if (!process_docbook)
1787 begin_insertion (ifnotdocbook);
1788 else
1789 command_name_condition ();
1790}
1791
1792void
1793cm_ifhtml (void)
1794{
1795 if (process_html)
1796 begin_insertion (ifhtml);
1797 else
1798 command_name_condition ();
1799}
1800
1801void
1802cm_ifnothtml (void)
1803{
1804 if (!process_html)
1805 begin_insertion (ifnothtml);
1806 else
1807 command_name_condition ();
1808}
1809
1810
1811void
1812cm_ifinfo (void)
1813{
1814 if (process_info)
1815 begin_insertion (ifinfo);
1816 else
1817 command_name_condition ();
1818}
1819
1820void
1821cm_ifnotinfo (void)
1822{
1823 if (!process_info)
1824 begin_insertion (ifnotinfo);
1825 else
1826 command_name_condition ();
1827}
1828
1829
1830void
1831cm_ifplaintext (void)
1832{
1833 if (process_plaintext)
1834 begin_insertion (ifplaintext);
1835 else
1836 command_name_condition ();
1837}
1838
1839void
1840cm_ifnotplaintext (void)
1841{
1842 if (!process_plaintext)
1843 begin_insertion (ifnotplaintext);
1844 else
1845 command_name_condition ();
1846}
1847
1848
1849void
1850cm_tex (void)
1851{
1852 if (process_tex)
1853 begin_insertion (rawtex);
1854 else
1855 command_name_condition ();
1856}
1857
1858void
1859cm_iftex (void)
1860{
1861 if (process_tex)
1862 begin_insertion (iftex);
1863 else
1864 command_name_condition ();
1865}
1866
1867void
1868cm_ifnottex (void)
1869{
1870 if (!process_tex)
1871 begin_insertion (ifnottex);
1872 else
1873 command_name_condition ();
1874}
1875
1876void
1877cm_ifxml (void)
1878{
1879 if (process_xml)
1880 begin_insertion (ifxml);
1881 else
1882 command_name_condition ();
1883}
1884
1885void
1886cm_ifnotxml (void)
1887{
1888 if (!process_xml)
1889 begin_insertion (ifnotxml);
1890 else
1891 command_name_condition ();
1892}
1893
1894
1895
1896/* Generic xrefable block with a caption. */
1897void
1898cm_float (void)
1899{
1900 begin_insertion (floatenv);
1901}
1902
1903void
1904cm_caption (int arg)
1905{
1906 char *temp;
1907
1908 /* This is a no_op command for most formats, as we handle it during @float
1909 insertion. For XML though, we handle it here to keep document structure
1910 as close as possible, to the Texinfo source. */
1911
1912 /* Everything is already handled at START. */
1913 if (arg == END)
1914 return;
1915
1916 /* Check if it's mislocated. */
1917 if (current_insertion_type () != floatenv)
1918 line_error (_("@%s not meaningful outside `@float' environment"), command);
1919
1920 get_until_in_braces ("\n@end float", &temp);
1921
1922 if (xml)
1923 {
1924 int elt = STREQ (command, "shortcaption") ? SHORTCAPTION : CAPTION;
1925 xml_insert_element (elt, START);
1926 if (!docbook)
1927 execute_string ("%s", temp);
1928 xml_insert_element (elt, END);
1929 }
1930
1931 free (temp);
1932}
1933
1934/* Begin an insertion where the lines are not filled or indented. */
1935void
1936cm_flushleft (void)
1937{
1938 begin_insertion (flushleft);
1939}
1940
1941/* Begin an insertion where the lines are not filled, and each line is
1942 forced to the right-hand side of the page. */
1943void
1944cm_flushright (void)
1945{
1946 begin_insertion (flushright);
1947}
1948
1949void
1950cm_menu (void)
1951{
1952 if (current_node == NULL && !macro_expansion_output_stream)
1953 {
1954 warning (_("@menu seen before first @node, creating `Top' node"));
1955 warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?"));
1956 /* Include @top command so we can construct the implicit node tree. */
1957 execute_string ("@node top\n@top Top\n");
1958 }
1959 begin_insertion (menu);
1960}
1961
1962void
1963cm_detailmenu (void)
1964{
1965 if (current_node == NULL && !macro_expansion_output_stream)
1966 { /* Problems anyway, @detailmenu should always be inside @menu. */
1967 warning (_("@detailmenu seen before first node, creating `Top' node"));
1968 execute_string ("@node top\n@top Top\n");
1969 }
1970 begin_insertion (detailmenu);
1971}
1972
1973
1974/* Title page commands. */
1975
1976void
1977cm_titlepage (void)
1978{
1979 titlepage_cmd_present = 1;
1980 if (xml && !docbook)
1981 begin_insertion (titlepage);
1982 else
1983 command_name_condition ();
1984}
1985
1986void
1987cm_author (void)
1988{
1989 char *rest;
1990 get_rest_of_line (1, &rest);
1991
1992 if (is_in_insertion_of_type (quotation))
1993 {
1994 if (html)
1995 add_word_args ("&mdash; %s", rest);
1996 else if (docbook)
1997 {
1998 /* FIXME Ideally, we should use an attribution element,
1999 but they are supposed to be at the start of quotation
2000 blocks. So to avoid looking ahead mess, let's just
2001 use mdash like HTML for now. */
2002 xml_insert_entity ("mdash");
2003 add_word (rest);
2004 }
2005 else if (xml)
2006 {
2007 xml_insert_element (AUTHOR, START);
2008 add_word (rest);
2009 xml_insert_element (AUTHOR, END);
2010 }
2011 else
2012 add_word_args ("-- %s", rest);
2013 }
2014 else if (is_in_insertion_of_type (titlepage))
2015 {
2016 if (xml && !docbook)
2017 {
2018 xml_insert_element (AUTHOR, START);
2019 add_word (rest);
2020 xml_insert_element (AUTHOR, END);
2021 }
2022 }
2023 else
2024 line_error (_("@%s not meaningful outside `@titlepage' and `@quotation' environments"),
2025 command);
2026
2027 free (rest);
2028}
2029
2030void
2031cm_titlepage_cmds (void)
2032{
2033 char *rest;
2034
2035 get_rest_of_line (1, &rest);
2036
2037 if (!is_in_insertion_of_type (titlepage))
2038 line_error (_("@%s not meaningful outside `@titlepage' environment"),
2039 command);
2040
2041 if (xml && !docbook)
2042 {
2043 int elt = 0;
2044
2045 if (STREQ (command, "title"))
2046 elt = BOOKTITLE;
2047 else if (STREQ (command, "subtitle"))
2048 elt = BOOKSUBTITLE;
2049
2050 xml_insert_element (elt, START);
2051 add_word (rest);
2052 xml_insert_element (elt, END);
2053 }
2054
2055 free (rest);
2056}
2057
2058/* End existing insertion block. */
2059void
2060cm_end (void)
2061{
2062 char *temp;
2063 int type;
2064
2065 get_rest_of_line (0, &temp);
2066
2067 if (!insertion_level)
2068 {
2069 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
2070 return;
2071 }
2072
2073 if (temp[0] == 0)
2074 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
2075
2076 type = find_type_from_name (temp);
2077
2078 if (type == bad_type)
2079 {
2080 line_error (_("Bad argument `%s' to `@%s', using `%s'"),
2081 temp, command, insertion_type_pname (current_insertion_type ()));
2082 }
2083 if (xml && type == menu) /* fixme */
2084 {
2085 xml_end_menu ();
2086 }
2087 end_insertion (type);
2088 free (temp);
2089}
2090
2091
2092/* @itemx, @item. */
2093
2094static int itemx_flag = 0;
2095
2096/* Return whether CMD takes a brace-delimited {arg}. */
2097int
2098command_needs_braces (char *cmd)
2099{
2100 int i;
2101 for (i = 0; command_table[i].name; i++)
2102 {
2103 if (STREQ (command_table[i].name, cmd))
2104 return command_table[i].argument_in_braces == BRACE_ARGS;
2105 }
2106
2107 return 0; /* macro or alias */
2108}
2109
2110
2111void
2112cm_item (void)
2113{
2114 char *rest_of_line, *item_func;
2115
2116 /* Can only hack "@item" while inside of an insertion. */
2117 if (insertion_level)
2118 {
2119 INSERTION_ELT *stack = insertion_stack;
2120 int original_input_text_offset;
2121
2122 skip_whitespace ();
2123 original_input_text_offset = input_text_offset;
2124
2125 get_rest_of_line (0, &rest_of_line);
2126 item_func = current_item_function ();
2127
2128 /* Do the right thing depending on which insertion function is active. */
2129 switch_top:
2130 switch (stack->insertion)
2131 {
2132 case multitable:
2133 multitable_item ();
2134 /* Support text directly after the @item. */
2135 if (*rest_of_line)
2136 {
2137 line_number--;
2138 input_text_offset = original_input_text_offset;
2139 }
2140 break;
2141
2142 case ifclear:
2143 case ifhtml:
2144 case ifinfo:
2145 case ifnothtml:
2146 case ifnotinfo:
2147 case ifnotplaintext:
2148 case ifnottex:
2149 case ifnotxml:
2150 case ifplaintext:
2151 case ifset:
2152 case iftex:
2153 case ifxml:
2154 case rawdocbook:
2155 case rawhtml:
2156 case rawxml:
2157 case rawtex:
2158 case tex:
2159 case cartouche:
2160 stack = stack->next;
2161 if (!stack)
2162 goto no_insertion;
2163 else
2164 goto switch_top;
2165 break;
2166
2167 case menu:
2168 case quotation:
2169 case example:
2170 case smallexample:
2171 case lisp:
2172 case smalllisp:
2173 case format:
2174 case smallformat:
2175 case display:
2176 case smalldisplay:
2177 case group:
2178 line_error (_("@%s not meaningful inside `@%s' block"),
2179 command,
2180 insertion_type_pname (current_insertion_type ()));
2181 break;
2182
2183 case itemize:
2184 case enumerate:
2185 if (itemx_flag)
2186 {
2187 line_error (_("@itemx not meaningful inside `%s' block"),
2188 insertion_type_pname (current_insertion_type ()));
2189 }
2190 else
2191 {
2192 if (html)
2193 add_html_block_elt ("<li>");
2194 else if (xml)
2195 xml_begin_item ();
2196 else
2197 {
2198 start_paragraph ();
2199 kill_self_indent (-1);
2200 filling_enabled = indented_fill = 1;
2201
2202 if (current_item_function ())
2203 {
2204 output_column = current_indent - 2;
2205 indent (output_column);
2206
2207 /* The item marker can be given with or without
2208 braces -- @bullet and @bullet{} are both ok.
2209 Or it might be something that doesn't take
2210 braces at all, such as "o" or "#" or "@ ".
2211 Thus, only supply braces if the item marker is
2212 a command, they haven't supplied braces
2213 themselves, and we know it needs them. */
2214 if (item_func && *item_func)
2215 {
2216 if (*item_func == COMMAND_PREFIX
2217 && item_func[strlen (item_func) - 1] != '}'
2218 && command_needs_braces (item_func + 1))
2219 execute_string ("%s{}", item_func);
2220 else
2221 execute_string ("%s", item_func);
2222 }
2223 insert (' ');
2224 output_column++;
2225 }
2226 else
2227 enumerate_item ();
2228
2229 /* Special hack. This makes `close_paragraph' a no-op until
2230 `start_paragraph' has been called. */
2231 must_start_paragraph = 1;
2232 }
2233
2234 /* Handle text directly after the @item. */
2235 if (*rest_of_line)
2236 {
2237 line_number--;
2238 input_text_offset = original_input_text_offset;
2239 }
2240 }
2241 break;
2242
2243 case table:
2244 case ftable:
2245 case vtable:
2246 if (html)
2247 { /* If nothing has been output since the last <dd>,
2248 remove the empty <dd> element. Some browsers render
2249 an extra empty line for <dd><dt>, which makes @itemx
2250 conversion look ugly. */
2251 rollback_empty_tag ("dd");
2252
2253 /* Force the browser to render one blank line before
2254 each new @item in a table. But don't do that if
2255 this is the first <dt> after the <dl>, or if we are
2256 converting @itemx.
2257
2258 Note that there are some browsers which ignore <br>
2259 in this context, but I cannot find any way to force
2260 them all render exactly one blank line. */
2261 if (!itemx_flag && html_deflist_has_term)
2262 add_html_block_elt ("<br>");
2263
2264 /* We are about to insert a <dt>, so this <dl> has a term.
2265 Feel free to insert a <br> next time. :) */
2266 html_deflist_has_term = 1;
2267
2268 add_html_block_elt ("<dt>");
2269 if (item_func && *item_func)
2270 execute_string ("%s{%s}", item_func, rest_of_line);
2271 else
2272 execute_string ("%s", rest_of_line);
2273
2274 if (current_insertion_type () == ftable)
2275 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
2276
2277 if (current_insertion_type () == vtable)
2278 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
2279
2280 add_html_block_elt ("<dd>");
2281 }
2282 else if (xml) /* && docbook)*/ /* 05-08 */
2283 {
2284 xml_begin_table_item ();
2285
2286 if (!docbook && current_insertion_type () == ftable)
2287 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
2288
2289 if (!docbook && current_insertion_type () == vtable)
2290 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
2291
2292 if (item_func && *item_func)
2293 execute_string ("%s{%s}", item_func, rest_of_line);
2294 else
2295 execute_string ("%s", rest_of_line);
2296 xml_continue_table_item ();
2297 }
2298 else
2299 {
2300 /* We need this to determine if we have two @item's in a row
2301 (see test just below). */
2302 static int last_item_output_position = 0;
2303
2304 /* Get rid of extra characters. */
2305 kill_self_indent (-1);
2306
2307 /* If we have one @item followed directly by another @item,
2308 we need to insert a blank line. This is not true for
2309 @itemx, though. */
2310 if (!itemx_flag && last_item_output_position == output_position)
2311 insert ('\n');
2312
2313 /* `close_paragraph' almost does what we want. The problem
2314 is when paragraph_is_open, and last_char_was_newline, and
2315 the last newline has been turned into a space, because
2316 filling_enabled. I handle it here. */
2317 if (last_char_was_newline && filling_enabled &&
2318 paragraph_is_open)
2319 insert ('\n');
2320 close_paragraph ();
2321
2322#if defined (INDENT_PARAGRAPHS_IN_TABLE)
2323 /* Indent on a new line, but back up one indentation level. */
2324 {
2325 int save = inhibit_paragraph_indentation;
2326 inhibit_paragraph_indentation = 1;
2327 /* At this point, inserting any non-whitespace character will
2328 force the existing indentation to be output. */
2329 add_char ('i');
2330 inhibit_paragraph_indentation = save;
2331 }
2332#else /* !INDENT_PARAGRAPHS_IN_TABLE */
2333 add_char ('i');
2334#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
2335
2336 output_paragraph_offset--;
2337 kill_self_indent (default_indentation_increment + 1);
2338
2339 /* Add item's argument to the line. */
2340 filling_enabled = 0;
2341 if (item_func && *item_func)
2342 execute_string ("%s{%s}", item_func, rest_of_line);
2343 else
2344 execute_string ("%s", rest_of_line);
2345
2346 if (current_insertion_type () == ftable)
2347 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
2348 else if (current_insertion_type () == vtable)
2349 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
2350
2351 /* Start a new line, and let start_paragraph ()
2352 do the indenting of it for you. */
2353 close_single_paragraph ();
2354 indented_fill = filling_enabled = 1;
2355 last_item_output_position = output_position;
2356 }
2357 }
2358 free (rest_of_line);
2359 }
2360 else
2361 {
2362 no_insertion:
2363 line_error (_("%c%s found outside of an insertion block"),
2364 COMMAND_PREFIX, command);
2365 }
2366}
2367
2368void
2369cm_itemx (void)
2370{
2371 itemx_flag++;
2372 cm_item ();
2373 itemx_flag--;
2374}
2375
2376int headitem_flag = 0;
2377
2378void
2379cm_headitem (void)
2380{
2381 headitem_flag = 1;
2382 cm_item ();
2383}
Note: See TracBrowser for help on using the repository browser.