From 34d5cbe5edd971f0145bee057a4c4b1909e4386f Mon Sep 17 00:00:00 2001
From: Peter Avalos is written in normal context.
- Used for menu and itemize. */
-int in_paragraph = 0;
-
-static const char dl_tag[] = "\n";
-extern void cm_insert_copying ();
-
-
-void
-init_insertion_stack ()
-{
- insertion_stack = NULL;
-}
-
-/* Return the type of the current insertion. */
-static enum insertion_type
-current_insertion_type ()
-{
- return insertion_level ? insertion_stack->insertion : bad_type;
-}
-
-/* Return the string which is the function to wrap around items, or NULL
- if we're not in an environment where @item is ok. */
-static char *
-current_item_function ()
-{
- int done = 0;
- INSERTION_ELT *elt = insertion_stack;
-
- /* Skip down through the stack until we find an insertion with an
- itemize function defined, i.e., skip conditionals, @cartouche, etc. */
- while (!done && elt)
- {
- switch (elt->insertion)
- {
- /* This list should match the one in cm_item. */
- case ifclear:
- case ifhtml:
- case ifinfo:
- case ifnothtml:
- case ifnotinfo:
- case ifnotplaintext:
- case ifnottex:
- case ifplaintext:
- case ifset:
- case iftex:
- case rawhtml:
- case rawtex:
- case tex:
- case cartouche:
- elt = elt->next;
- break;
-
- default:
- done = 1;
- }
- }
-
- /* item_function usually gets assigned the empty string. */
- return done && (*elt->item_function) ? elt->item_function : NULL;
-}
-
-/* Parse the item marker function off the input. If result is just "@",
- change it to "@ ", since "@" by itself is not a command. This makes
- "@ ", "@\t", and "@\n" all the same, but their default meanings are
- the same anyway, and let's not worry about supporting redefining them. */
-char *
-get_item_function ()
-{
- char *item_function;
- get_rest_of_line (0, &item_function);
-
- /* If we hit the end of text in get_rest_of_line, backing up
- input pointer will cause the last character of the last line
- be pushed back onto the input, which is wrong. */
- if (input_text_offset < input_text_length)
- backup_input_pointer ();
-
- if (STREQ (item_function, "@"))
- {
- free (item_function);
- item_function = xstrdup ("@ ");
- }
-
- return item_function;
-}
-
- /* Push the state of the current insertion on the stack. */
-void
-push_insertion (type, item_function)
- enum insertion_type type;
- char *item_function;
-{
- INSERTION_ELT *new = xmalloc (sizeof (INSERTION_ELT));
-
- new->item_function = item_function;
- new->filling_enabled = filling_enabled;
- new->indented_fill = indented_fill;
- new->insertion = type;
- new->line_number = line_number;
- new->filename = xstrdup (input_filename);
- new->inhibited = inhibit_paragraph_indentation;
- new->in_fixed_width_font = in_fixed_width_font;
- new->next = insertion_stack;
- insertion_stack = new;
- insertion_level++;
-}
-
- /* Pop the value on top of the insertion stack into the
- global variables. */
-void
-pop_insertion ()
-{
- INSERTION_ELT *temp = insertion_stack;
-
- if (temp == NULL)
- return;
-
- in_fixed_width_font = temp->in_fixed_width_font;
- inhibit_paragraph_indentation = temp->inhibited;
- filling_enabled = temp->filling_enabled;
- indented_fill = temp->indented_fill;
- free_and_clear (&(temp->item_function));
- free_and_clear (&(temp->filename));
- insertion_stack = insertion_stack->next;
- free (temp);
- insertion_level--;
-}
-
- /* Return a pointer to the print name of this
- enumerated type. */
-char *
-insertion_type_pname (type)
- enum insertion_type type;
-{
- if ((int) type < (int) bad_type)
- return insertion_type_names[(int) type];
- else
- return _("Broken-Type in insertion_type_pname");
-}
-
-/* Return the insertion_type associated with NAME.
- If the type is not one of the known ones, return BAD_TYPE. */
-enum insertion_type
-find_type_from_name (name)
- char *name;
-{
- int index = 0;
- while (index < (int) bad_type)
- {
- if (STREQ (name, insertion_type_names[index]))
- return (enum insertion_type) index;
- if (index == rawhtml && STREQ (name, "html"))
- return rawhtml;
- if (index == rawtex && STREQ (name, "tex"))
- return rawtex;
- index++;
- }
- return bad_type;
-}
-
-int
-defun_insertion (type)
- enum insertion_type type;
-{
- return 0
- || (type == defcv)
- || (type == deffn)
- || (type == defivar)
- || (type == defmac)
- || (type == defmethod)
- || (type == defop)
- || (type == defopt)
- || (type == defspec)
- || (type == deftp)
- || (type == deftypefn)
- || (type == deftypefun)
- || (type == deftypeivar)
- || (type == deftypemethod)
- || (type == deftypeop)
- || (type == deftypevar)
- || (type == deftypevr)
- || (type == defun)
- || (type == defvar)
- || (type == defvr)
- ;
-}
-
-/* MAX_NS is the maximum nesting level for enumerations. I picked 100
- which seemed reasonable. This doesn't control the number of items,
- just the number of nested lists. */
-#define max_stack_depth 100
-#define ENUM_DIGITS 1
-#define ENUM_ALPHA 2
-typedef struct {
- int enumtype;
- int enumval;
-} DIGIT_ALPHA;
-
-DIGIT_ALPHA enumstack[max_stack_depth];
-int enumstack_offset = 0;
-int current_enumval = 1;
-int current_enumtype = ENUM_DIGITS;
-char *enumeration_arg = NULL;
-
-void
-start_enumerating (at, type)
- int at, type;
-{
- if ((enumstack_offset + 1) == max_stack_depth)
- {
- line_error (_("Enumeration stack overflow"));
- return;
- }
- enumstack[enumstack_offset].enumtype = current_enumtype;
- enumstack[enumstack_offset].enumval = current_enumval;
- enumstack_offset++;
- current_enumval = at;
- current_enumtype = type;
-}
-
-void
-stop_enumerating ()
-{
- --enumstack_offset;
- if (enumstack_offset < 0)
- enumstack_offset = 0;
-
- current_enumval = enumstack[enumstack_offset].enumval;
- current_enumtype = enumstack[enumstack_offset].enumtype;
-}
-
-/* Place a letter or digits into the output stream. */
-void
-enumerate_item ()
-{
- char temp[10];
-
- if (current_enumtype == ENUM_ALPHA)
- {
- if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
- {
- current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
- warning (_("lettering overflow, restarting at %c"), current_enumval);
- }
- sprintf (temp, "%c. ", current_enumval);
- }
- else
- sprintf (temp, "%d. ", current_enumval);
-
- indent (output_column += (current_indent - strlen (temp)));
- add_word (temp);
- current_enumval++;
-}
-
-static void
-enum_html ()
-{
- char type;
- int start;
-
- if (isdigit (*enumeration_arg))
- {
- type = '1';
- start = atoi (enumeration_arg);
- }
- else if (isupper (*enumeration_arg))
- {
- type = 'A';
- start = *enumeration_arg - 'A' + 1;
- }
- else
- {
- type = 'a';
- start = *enumeration_arg - 'a' + 1;
- }
-
- add_word_args ("
\n", type, start);
-}
-
-/* Conditionally parse based on the current command name. */
-void
-command_name_condition ()
-{
- char *discarder = xmalloc (8 + strlen (command));
-
- sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
- discard_until (discarder);
- discard_until ("\n");
-
- free (discarder);
-}
-
-/* This is where the work for all the "insertion" style
- commands is done. A huge switch statement handles the
- various setups, and generic code is on both sides. */
-void
-begin_insertion (type)
- enum insertion_type type;
-{
- int no_discard = 0;
-
- if (defun_insertion (type))
- {
- push_insertion (type, xstrdup (""));
- no_discard++;
- }
- else
- {
- push_insertion (type, get_item_function ());
- }
-
- switch (type)
- {
- case menu:
- if (!no_headers)
- close_paragraph ();
-
- filling_enabled = no_indent = 0;
- inhibit_paragraph_indentation = 1;
-
- if (html)
- {
- had_menu_commentary = 1;
- }
- else if (!no_headers && !xml)
- add_word ("* Menu:\n");
-
- if (xml)
- xml_insert_element (MENU, START);
-
- next_menu_item_number = 1;
- in_menu++;
- in_fixed_width_font++;
- no_discard++;
- break;
-
- case detailmenu:
- if (!in_menu)
- {
- if (!no_headers)
- close_paragraph ();
-
- filling_enabled = no_indent = 0;
- inhibit_paragraph_indentation = 1;
-
- no_discard++;
- }
-
- in_fixed_width_font++;
- in_detailmenu++;
- break;
-
- case direntry:
- close_single_paragraph ();
- filling_enabled = no_indent = 0;
- inhibit_paragraph_indentation = 1;
- insert_string ("START-INFO-DIR-ENTRY\n");
- break;
-
- case documentdescription:
- {
- char *desc;
- int start_of_end;
- int save_fixed_width;
-
- discard_until ("\n"); /* ignore the @documentdescription line */
- start_of_end = get_until ("\n@end documentdescription", &desc);
- save_fixed_width = in_fixed_width_font;
-
- in_fixed_width_font = 0;
- document_description = expansion (desc, 0);
- free (desc);
-
- in_fixed_width_font = save_fixed_width;
- input_text_offset = start_of_end; /* go back to the @end to match */
- }
- break;
-
- case copying:
- {
- /* Save the copying text away for @insertcopying,
- typically used on the back of the @titlepage (for TeX) and
- the Top node (for info/html). */
- char *text;
- int start_of_end;
-
- discard_until ("\n"); /* ignore remainder of @copying line */
- start_of_end = get_until ("\n@end copying", &text);
-
- /* include all the output-format-specific markup. */
- copying_text = full_expansion (text, 0);
- free (text);
-
- input_text_offset = start_of_end; /* go back to the @end to match */
- }
-
- /* For info, output the copying text right away, so it will end up
- in the header of the Info file, before the first node, and thus
- get copied automatically to all the split files. For xml, also
- output it right away since xml output is never split.
- For html, we output it specifically in html_output_head.
- For plain text, there's no way to hide it, so the author must
- use @insertcopying in the desired location. */
- if (!html && !no_headers)
- cm_insert_copying ();
- break;
-
- case quotation:
- /* @quotation does filling (@display doesn't). */
- if (html)
- add_word ("
\n");
- else
- {
- /* with close_single_paragraph, we get no blank line above
- within @copying. */
- close_paragraph ();
- last_char_was_newline = no_indent = 0;
- indented_fill = filling_enabled = 1;
- inhibit_paragraph_indentation = 1;
- }
- current_indent += default_indentation_increment;
- break;
-
- case display:
- case smalldisplay:
- case example:
- case smallexample:
- case lisp:
- case smalllisp:
- /* Like @display but without indentation. */
- case smallformat:
- case format:
- close_single_paragraph ();
- inhibit_paragraph_indentation = 1;
- in_fixed_width_font++;
- filling_enabled = 0;
- last_char_was_newline = 0;
-
- if (html)
- /* Kludge alert: if
is followed by a newline, IE3
- renders an extra blank line before the pre-formatted block.
- Other browsers seem to not mind one way or the other. */
- add_word ("
");
-
- if (type != format && type != smallformat)
- current_indent += default_indentation_increment;
- break;
-
- case multitable:
- do_multitable ();
- break;
-
- case table:
- case ftable:
- case vtable:
- case itemize:
- close_single_paragraph ();
- current_indent += default_indentation_increment;
- filling_enabled = indented_fill = 1;
-#if defined (INDENT_PARAGRAPHS_IN_TABLE)
- inhibit_paragraph_indentation = 0;
-#else
- inhibit_paragraph_indentation = 1;
-#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
-
- /* Make things work for losers who forget the itemize syntax. */
- if (type == itemize)
- {
- if (!(*insertion_stack->item_function))
- {
- free (insertion_stack->item_function);
- insertion_stack->item_function = xstrdup ("@bullet");
- }
- }
-
- if (!*insertion_stack->item_function)
- {
- line_error (_("%s requires an argument: the formatter for %citem"),
- insertion_type_pname (type), COMMAND_PREFIX);
- }
-
- if (html)
- {
- if (type == itemize)
- {
- add_word ("
\n");
- in_paragraph = 0;
- }
- else
- add_word (dl_tag);
- }
- if (xml)
- xml_begin_table (type, insertion_stack->item_function);
- break;
-
- case enumerate:
- close_single_paragraph ();
- no_indent = 0;
-#if defined (INDENT_PARAGRAPHS_IN_TABLE)
- inhibit_paragraph_indentation = 0;
-#else
- inhibit_paragraph_indentation = 1;
-#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
-
- current_indent += default_indentation_increment;
- filling_enabled = indented_fill = 1;
-
- if (html)
- enum_html ();
-
- if (xml)
- xml_begin_enumerate (enumeration_arg);
-
- if (isdigit (*enumeration_arg))
- start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
- else
- start_enumerating (*enumeration_arg, ENUM_ALPHA);
- break;
-
- /* @group does nothing special in makeinfo. */
- case group:
- /* Only close the paragraph if we are not inside of an
- @example-like environment. */
- if (xml)
- xml_insert_element (GROUP, START);
- else if (!insertion_stack->next
- || (insertion_stack->next->insertion != display
- && insertion_stack->next->insertion != smalldisplay
- && insertion_stack->next->insertion != example
- && insertion_stack->next->insertion != smallexample
- && insertion_stack->next->insertion != lisp
- && insertion_stack->next->insertion != smalllisp
- && insertion_stack->next->insertion != format
- && insertion_stack->next->insertion != smallformat
- && insertion_stack->next->insertion != flushleft
- && insertion_stack->next->insertion != flushright))
- close_single_paragraph ();
- break;
-
- /* Insertions that are no-ops in info, but do something in TeX. */
- case cartouche:
- case ifclear:
- case ifhtml:
- case ifinfo:
- case ifnothtml:
- case ifnotinfo:
- case ifnotplaintext:
- case ifnottex:
- case ifplaintext:
- case ifset:
- case iftex:
- case rawtex:
- if (in_menu)
- no_discard++;
- break;
-
- case rawhtml:
- escape_html = 0;
- break;
-
- case defcv:
- case deffn:
- case defivar:
- case defmac:
- case defmethod:
- case defop:
- case defopt:
- case defspec:
- case deftp:
- case deftypefn:
- case deftypefun:
- case deftypeivar:
- case deftypemethod:
- case deftypeop:
- case deftypevar:
- case deftypevr:
- case defun:
- case defvar:
- case defvr:
- inhibit_paragraph_indentation = 1;
- filling_enabled = indented_fill = 1;
- current_indent += default_indentation_increment;
- no_indent = 0;
- break;
-
- case flushleft:
- close_single_paragraph ();
- inhibit_paragraph_indentation = 1;
- filling_enabled = indented_fill = no_indent = 0;
- if (html)
- add_word ("
");
-
- while (input_text_offset < input_text_length)
- {
- character = curchar ();
-
- if (character == '\n')
- line_number++;
- /*
- Assume no newlines in END_VERBATIM
- */
- else if (find_end_verbatim && (character == COMMAND_PREFIX) /* @ */
- && (input_text_length - input_text_offset > sizeof (END_VERBATIM))
- && !strncmp (&input_text[input_text_offset+1], END_VERBATIM,
- sizeof (END_VERBATIM)-1))
- {
- input_text_offset += sizeof (END_VERBATIM);
- seen_end = 1;
- break;
- }
-
- add_char (character);
- input_text_offset++;
- }
-
- if (find_end_verbatim && !seen_end)
- warning (_("end of file inside verbatim block"));
-
- if (html)
- add_word ("
");
-
- in_fixed_width_font--;
- filling_enabled = save_filling_enabled;
- inhibit_paragraph_indentation = save_inhibit_paragraph_indentation;
-}
-
-void
-cm_verbatim ()
-{
- handle_verbatim_environment (1);
-}
-
-void
-cm_table ()
-{
- begin_insertion (table);
-}
-
-void
-cm_multitable ()
-{
- begin_insertion (multitable); /* @@ */
-}
-
-void
-cm_ftable ()
-{
- begin_insertion (ftable);
-}
-
-void
-cm_vtable ()
-{
- begin_insertion (vtable);
-}
-
-void
-cm_group ()
-{
- begin_insertion (group);
-}
-
-/* Insert raw HTML (no escaping of `<' etc.). */
-void
-cm_html ()
-{
- if (process_html)
- begin_insertion (rawhtml);
- else
- command_name_condition ();
-}
-
-void
-cm_ifhtml ()
-{
- if (process_html)
- begin_insertion (ifhtml);
- else
- command_name_condition ();
-}
-
-void
-cm_ifnothtml ()
-{
- if (!process_html)
- begin_insertion (ifnothtml);
- else
- command_name_condition ();
-}
-
-
-void
-cm_ifinfo ()
-{
- if (process_info)
- begin_insertion (ifinfo);
- else
- command_name_condition ();
-}
-
-void
-cm_ifnotinfo ()
-{
- if (!process_info)
- begin_insertion (ifnotinfo);
- else
- command_name_condition ();
-}
-
-
-void
-cm_ifplaintext ()
-{
- if (process_plaintext)
- begin_insertion (ifplaintext);
- else
- command_name_condition ();
-}
-
-void
-cm_ifnotplaintext ()
-{
- if (!process_plaintext)
- begin_insertion (ifnotplaintext);
- else
- command_name_condition ();
-}
-
-
-void
-cm_tex ()
-{
- if (process_tex)
- begin_insertion (rawtex);
- else
- command_name_condition ();
-}
-
-void
-cm_iftex ()
-{
- if (process_tex)
- begin_insertion (iftex);
- else
- command_name_condition ();
-}
-
-void
-cm_ifnottex ()
-{
- if (!process_tex)
- begin_insertion (ifnottex);
- else
- command_name_condition ();
-}
-
-/* Begin an insertion where the lines are not filled or indented. */
-void
-cm_flushleft ()
-{
- begin_insertion (flushleft);
-}
-
-/* Begin an insertion where the lines are not filled, and each line is
- forced to the right-hand side of the page. */
-void
-cm_flushright ()
-{
- begin_insertion (flushright);
-}
-
-void
-cm_menu ()
-{
- if (current_node == NULL)
- {
- warning (_("@menu seen before first @node, creating `Top' node"));
- warning (_("perhaps your @top node should be wrapped in @ifnottex rather than @ifinfo?"));
- /* Include @top command so we can construct the implicit node tree. */
- execute_string ("@node top\n@top Top\n");
- }
- begin_insertion (menu);
-}
-
-void
-cm_detailmenu ()
-{
- if (current_node == NULL)
- { /* Problems anyway, @detailmenu should always be inside @menu. */
- warning (_("@detailmenu seen before first node, creating `Top' node"));
- execute_string ("@node top\n@top Top\n");
- }
- begin_insertion (detailmenu);
-}
-
-/* End existing insertion block. */
-void
-cm_end ()
-{
- char *temp;
- enum insertion_type type;
-
- if (!insertion_level)
- {
- line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
- return;
- }
-
- get_rest_of_line (0, &temp);
-
- if (temp[0] == 0)
- line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
-
- type = find_type_from_name (temp);
-
- if (type == bad_type)
- {
- line_error (_("Bad argument to `%s', `%s', using `%s'"),
- command, temp, insertion_type_pname (current_insertion_type ()));
- }
- if (xml && type == menu) /* fixme */
- {
- xml_end_menu ();
- }
- end_insertion (type);
- free (temp);
-}
-
-/* @itemx, @item. */
-
-static int itemx_flag = 0;
-
-/* Return whether CMD takes a brace-delimited {arg}. */
-/*static */int
-command_needs_braces (cmd)
- char *cmd;
-{
- int i;
- for (i = 0; command_table[i].name; i++)
- {
- if (STREQ (command_table[i].name, cmd))
- return command_table[i].argument_in_braces == BRACE_ARGS;
- }
-
- return 0; /* macro or alias */
-}
-
-
-void
-cm_item ()
-{
- char *rest_of_line, *item_func;
-
- /* Can only hack "@item" while inside of an insertion. */
- if (insertion_level)
- {
- INSERTION_ELT *stack = insertion_stack;
- int original_input_text_offset;
-
- skip_whitespace ();
- original_input_text_offset = input_text_offset;
-
- get_rest_of_line (0, &rest_of_line);
- item_func = current_item_function ();
-
- /* Do the right thing depending on which insertion function is active. */
- switch_top:
- switch (stack->insertion)
- {
- case multitable:
- multitable_item ();
- /* Support text directly after the @item. */
- if (*rest_of_line)
- {
- line_number--;
- input_text_offset = original_input_text_offset;
- }
- break;
-
- case ifclear:
- case ifhtml:
- case ifinfo:
- case ifnothtml:
- case ifnotinfo:
- case ifnotplaintext:
- case ifnottex:
- case ifplaintext:
- case ifset:
- case iftex:
- case rawhtml:
- case rawtex:
- case tex:
- case cartouche:
- stack = stack->next;
- if (!stack)
- goto no_insertion;
- else
- goto switch_top;
- break;
-
- case menu:
- case quotation:
- case example:
- case smallexample:
- case lisp:
- case smalllisp:
- case format:
- case smallformat:
- case display:
- case smalldisplay:
- case group:
- line_error (_("@%s not meaningful inside `@%s' block"),
- command,
- insertion_type_pname (current_insertion_type ()));
- break;
-
- case itemize:
- case enumerate:
- if (itemx_flag)
- {
- line_error (_("@itemx not meaningful inside `%s' block"),
- insertion_type_pname (current_insertion_type ()));
- }
- else
- {
- if (html)
- {
- if (in_paragraph)
- {
- add_word ("