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