aboutsummaryrefslogtreecommitdiff
path: root/texinfo/info
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1998-03-23 04:41:58 +0000
committerJeffrey A Law <law@cygnus.com>1998-03-23 04:41:58 +0000
commit38abfe9d7c4355745c1c4df99585dc6d1384f9df (patch)
tree9bc386a0875ecd26d247a4eb18407b6c59020a25 /texinfo/info
parent6d8c878f9451b10f660a977b9bfdf43a452a9d4c (diff)
Initial revision
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@18770 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'texinfo/info')
-rw-r--r--texinfo/info/Makefile.am44
-rw-r--r--texinfo/info/doc.c129
-rw-r--r--texinfo/info/echo-area.c1505
-rw-r--r--texinfo/info/echo-area.h64
-rw-r--r--texinfo/info/funs.h111
5 files changed, 1853 insertions, 0 deletions
diff --git a/texinfo/info/Makefile.am b/texinfo/info/Makefile.am
new file mode 100644
index 00000000000..b4c96d5d9e9
--- /dev/null
+++ b/texinfo/info/Makefile.am
@@ -0,0 +1,44 @@
+## Makefile.am for texinfo/info.
+## $Id: Makefile.am,v 1.1 1998/03/23 04:42:20 law Exp $
+## Run automake in .. to produce Makefile.in from this.
+
+noinst_PROGRAMS = makedoc
+
+# Use `ginfo' for building to avoid confusion with the standard `info'
+# target. The install rule removes the `g' before applying any
+# user-specified name transformations.
+bin_PROGRAMS = ginfo
+transform = s/ginfo/info/; @program_transform_name@
+
+localedir = $(datadir)/locale
+
+# -I. for funs.h.
+INCLUDES = -I. -I$(top_srcdir)/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
+LDADD = ../lib/libtxi.a @TERMLIBS@ @INTLLIBS@
+
+makedoc_SOURCES = makedoc.c
+ginfo_SOURCES = dir.c display.c display.h doc.c doc.h dribble.c dribble.h \
+ echo-area.c echo-area.h \
+ filesys.c filesys.h footnotes.c footnotes.h funs.h gc.c gc.h \
+ indices.c indices.h info-utils.c info-utils.h info.c info.h infodoc.c \
+ infomap.c infomap.h m-x.c man.c man.h nodemenu.c nodes.c nodes.h \
+ search.c search.h session.c session.h signals.c signals.h \
+ termdep.h terminal.c terminal.h tilde.c tilde.h \
+ variables.c variables.h window.c window.h
+
+EXTRA_DIST = README
+
+# The files `doc.c' and `funs.h' are created by ./makedoc run over the source
+# files which contain DECLARE_INFO_COMMAND. `funs.h' is a header file
+# listing the functions found. `doc.c' is a structure containing pointers
+# to those functions along with completable names and documentation strings.
+#
+# I do not know how to get this right.
+# BUILT_SOURCES = doc.c funs.h
+#
+#cmd_sources = $(srcdir)/session.c $(srcdir)/echo-area.c $(srcdir)/infodoc.c \
+# $(srcdir)/m-x.c $(srcdir)/indices.c $(srcdir)/nodemenu.c \
+# $(srcdir)/footnotes.c $(srcdir)/variables.c
+#
+#$(BUILTSOURCES): makedoc $(cmd_sources)
+# ./makedoc $(cmd_sources)
diff --git a/texinfo/info/doc.c b/texinfo/info/doc.c
new file mode 100644
index 00000000000..3859b7fd66a
--- /dev/null
+++ b/texinfo/info/doc.c
@@ -0,0 +1,129 @@
+/* doc.c -- Generated structure containing function names and doc strings.
+
+ This file was automatically made from various source files with the
+ command "./makedoc". DO NOT EDIT THIS FILE, only "./makedoc.c".
+ Source files groveled to make this file include:
+
+ ./session.c
+ ./echo-area.c
+ ./infodoc.c
+ ./m-x.c
+ ./indices.c
+ ./nodemenu.c
+ ./footnotes.c
+ ./variables.c
+
+ An entry in the array FUNCTION_DOC_ARRAY is made for each command
+ found in the above files; each entry consists of a function pointer,
+ a string which is the user-visible name of the function,
+ and a string which documents its purpose. */
+
+#include "doc.h"
+#include "funs.h"
+
+FUNCTION_DOC function_doc_array[] = {
+
+/* Commands found in "./session.c". */
+ { info_next_line, "next-line", N_("Move down to the next line") },
+ { info_prev_line, "prev-line", N_("Move up to the previous line") },
+ { info_end_of_line, "end-of-line", N_("Move to the end of the line") },
+ { info_beginning_of_line, "beginning-of-line", N_("Move to the start of the line") },
+ { info_forward_char, "forward-char", N_("Move forward a character") },
+ { info_backward_char, "backward-char", N_("Move backward a character") },
+ { info_forward_word, "forward-word", N_("Move forward a word") },
+ { info_backward_word, "backward-word", N_("Move backward a word") },
+ { info_global_next_node, "global-next-node", N_("Move forwards or down through node structure") },
+ { info_global_prev_node, "global-prev-node", N_("Move backwards or up through node structure") },
+ { info_scroll_forward, "scroll-forward", N_("Scroll forward in this window") },
+ { info_scroll_backward, "scroll-backward", N_("Scroll backward in this window") },
+ { info_beginning_of_node, "beginning-of-node", N_("Move to the start of this node") },
+ { info_end_of_node, "end-of-node", N_("Move to the end of this node") },
+ { info_next_window, "next-window", N_("Select the next window") },
+ { info_prev_window, "prev-window", N_("Select the previous window") },
+ { info_split_window, "split-window", N_("Split the current window") },
+ { info_delete_window, "delete-window", N_("Delete the current window") },
+ { info_keep_one_window, "keep-one-window", N_("Delete all other windows") },
+ { info_scroll_other_window, "scroll-other-window", N_("Scroll the other window") },
+ { info_grow_window, "grow-window", N_("Grow (or shrink) this window") },
+ { info_tile_windows, "tile-windows", N_("Divide the available screen space among the visible windows") },
+ { info_toggle_wrap, "toggle-wrap", N_("Toggle the state of line wrapping in the current window") },
+ { info_next_node, "next-node", N_("Select the `Next' node") },
+ { info_prev_node, "prev-node", N_("Select the `Prev' node") },
+ { info_up_node, "up-node", N_("Select the `Up' node") },
+ { info_last_node, "last-node", N_("Select the last node in this file") },
+ { info_first_node, "first-node", N_("Select the first node in this file") },
+ { info_history_node, "history-node", N_("Select the most recently selected node") },
+ { info_last_menu_item, "last-menu-item", N_("Select the last item in this node's menu") },
+ { info_menu_digit, "menu-digit", N_("Select this menu item") },
+ { info_menu_item, "menu-item", N_("Read a menu item and select its node") },
+ { info_xref_item, "xref-item", N_("Read a footnote or cross reference and select its node") },
+ { info_find_menu, "find-menu", N_("Move to the start of this node's menu") },
+ { info_visit_menu, "visit-menu", N_("Visit as many menu items at once as possible") },
+ { info_goto_node, "goto-node", N_("Read a node name and select it") },
+ { info_man, "man", N_("Read a manpage reference and select it") },
+ { info_top_node, "top-node", N_("Select the node `Top' in this file") },
+ { info_dir_node, "dir-node", N_("Select the node `(dir)'") },
+ { info_kill_node, "kill-node", N_("Kill this node") },
+ { info_view_file, "view-file", N_("Read the name of a file and select it") },
+ { info_print_node, "print-node", N_("Pipe the contents of this node through INFO_PRINT_COMMAND") },
+ { info_search, "search", N_("Read a string and search for it") },
+ { isearch_forward, "isearch-forward", N_("Search interactively for a string as you type it") },
+ { isearch_backward, "isearch-backward", N_("Search interactively for a string as you type it") },
+ { info_move_to_prev_xref, "move-to-prev-xref", N_("Move to the previous cross reference") },
+ { info_move_to_next_xref, "move-to-next-xref", N_("Move to the next cross reference") },
+ { info_select_reference_this_line, "select-reference-this-line", N_("Select reference or menu item appearing on this line") },
+ { info_abort_key, "abort-key", N_("Cancel current operation") },
+ { info_move_to_window_line, "move-to-window-line", N_("Move to the cursor to a specific line of the window") },
+ { info_redraw_display, "redraw-display", N_("Redraw the display") },
+ { info_quit, "quit", N_("Quit using Info") },
+ { info_do_lowercase_version, "do-lowercase-version", "" },
+ { info_add_digit_to_numeric_arg, "add-digit-to-numeric-arg", N_("Add this digit to the current numeric argument") },
+ { info_universal_argument, N_("universal-argument"), N_("Start (or multiply by 4) the current numeric argument") },
+ { info_numeric_arg_digit_loop, "numeric-arg-digit-loop", N_("Internally used by \\[universal-argument]") },
+/* Commands found in "./echo-area.c". */
+ { ea_forward, "echo-area-forward", N_("Move forward a character") },
+ { ea_backward, "echo-area-backward", N_("Move backward a character") },
+ { ea_beg_of_line, "echo-area-beg-of-line", N_("Move to the start of this line") },
+ { ea_end_of_line, "echo-area-end-of-line", N_("Move to the end of this line") },
+ { ea_forward_word, "echo-area-forward-word", N_("Move forward a word") },
+ { ea_backward_word, "echo-area-backward-word", N_("Move backward a word") },
+ { ea_delete, "echo-area-delete", N_("Delete the character under the cursor") },
+ { ea_rubout, "echo-area-rubout", N_("Delete the character behind the cursor") },
+ { ea_abort, "echo-area-abort", N_("Cancel or quit operation") },
+ { ea_newline, "echo-area-newline", N_("Accept (or force completion of) this line") },
+ { ea_quoted_insert, "echo-area-quoted-insert", N_("Insert next character verbatim") },
+ { ea_insert, "echo-area-insert", N_("Insert this character") },
+ { ea_tab_insert, "echo-area-tab-insert", N_("Insert a TAB character") },
+ { ea_transpose_chars, "echo-area-transpose-chars", N_("Transpose characters at point") },
+ { ea_yank, "echo-area-yank", N_("Yank back the contents of the last kill") },
+ { ea_yank_pop, "echo-area-yank-pop", N_("Yank back a previous kill") },
+ { ea_kill_line, "echo-area-kill-line", N_("Kill to the end of the line") },
+ { ea_backward_kill_line, "echo-area-backward-kill-line", N_("Kill to the beginning of the line") },
+ { ea_kill_word, "echo-area-kill-word", N_("Kill the word following the cursor") },
+ { ea_backward_kill_word, "echo-area-backward-kill-word", N_("Kill the word preceding the cursor") },
+ { ea_possible_completions, "echo-area-possible-completions", N_("List possible completions") },
+ { ea_complete, "echo-area-complete", N_("Insert completion") },
+ { ea_scroll_completions_window, "echo-area-scroll-completions-window", N_("Scroll the completions window") },
+/* Commands found in "./infodoc.c". */
+ { info_get_help_window, "get-help-window", N_("Display help message") },
+ { info_get_info_help_node, "get-info-help-node", N_("Visit Info node `(info)Help'") },
+ { describe_key, "describe-key", N_("Print documentation for KEY") },
+ { info_where_is, "where-is", N_("Show what to type to execute a given command") },
+/* Commands found in "./m-x.c". */
+ { describe_command, "describe-command", N_("Read the name of an Info command and describe it") },
+ { info_execute_command, "execute-command", N_("Read a command name in the echo area and execute it") },
+ { set_screen_height, "set-screen-height", N_("Set the height of the displayed window") },
+/* Commands found in "./indices.c". */
+ { info_index_search, "index-search", N_("Look up a string in the index for this file") },
+ { info_next_index_match, "next-index-match", N_("Go to the next matching index item from the last `\\[index-search]' command") },
+ { info_index_apropos, "index-apropos", N_("Grovel all known info file's indices for a string and build a menu") },
+/* Commands found in "./nodemenu.c". */
+ { list_visited_nodes, "list-visited-nodes", N_("Make a window containing a menu of all of the currently visited nodes") },
+ { select_visited_node, "select-visited-node", N_("Select a node which has been previously visited in a visible window") },
+/* Commands found in "./footnotes.c". */
+ { info_show_footnotes, "show-footnotes", N_("Show the footnotes associated with this node in another window") },
+/* Commands found in "./variables.c". */
+ { describe_variable, "describe-variable", N_("Explain the use of a variable") },
+ { set_variable, "set-variable", N_("Set the value of an Info variable") },
+ { (VFunction *)NULL, (char *)NULL, (char *)NULL }
+};
diff --git a/texinfo/info/echo-area.c b/texinfo/info/echo-area.c
new file mode 100644
index 00000000000..6f97a14d693
--- /dev/null
+++ b/texinfo/info/echo-area.c
@@ -0,0 +1,1505 @@
+/* echo-area.c -- How to read a line in the echo area.
+ $Id: echo-area.c,v 1.1 1998/03/23 04:42:27 law Exp $
+
+ Copyright (C) 1993, 97 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+#if defined (FD_SET)
+# if defined (hpux)
+# define fd_set_cast(x) (int *)(x)
+# else
+# define fd_set_cast(x) (fd_set *)(x)
+# endif /* !hpux */
+#endif /* FD_SET */
+
+/* Non-zero means that C-g was used to quit reading input. */
+int info_aborted_echo_area = 0;
+
+/* Non-zero means that the echo area is being used to read input. */
+int echo_area_is_active = 0;
+
+/* The address of the last command executed in the echo area. */
+VFunction *ea_last_executed_command = (VFunction *)NULL;
+
+/* Non-zero means that the last command executed while reading input
+ killed some text. */
+int echo_area_last_command_was_kill = 0;
+
+/* Variables which hold on to the current state of the input line. */
+static char input_line[1 + EA_MAX_INPUT];
+static char *input_line_prompt;
+static int input_line_point;
+static int input_line_beg;
+static int input_line_end;
+static NODE input_line_node = {
+ (char *)NULL, (char *)NULL, (char *)NULL, input_line, EA_MAX_INPUT, 0
+};
+
+static void echo_area_initialize_node ();
+static void push_echo_area (), pop_echo_area ();
+static int echo_area_stack_contains_completions_p ();
+
+static void ea_kill_text ();
+
+/* Non-zero means we force the user to complete. */
+static int echo_area_must_complete_p = 0;
+static int completions_window_p ();
+
+/* If non-null, this is a window which was specifically created to display
+ possible completions output. We remember it so we can delete it when
+ appropriate. */
+static WINDOW *echo_area_completions_window = (WINDOW *)NULL;
+
+/* Variables which keep track of the window which was active prior to
+ entering the echo area. */
+static WINDOW *calling_window = (WINDOW *)NULL;
+static NODE *calling_window_node = (NODE *)NULL;
+static long calling_window_point = 0;
+static long calling_window_pagetop = 0;
+
+/* Remember the node and pertinent variables of the calling window. */
+static void
+remember_calling_window (window)
+ WINDOW *window;
+{
+ /* Only do this if the calling window is not the completions window, or,
+ if it is the completions window and there is no other window. */
+ if (!completions_window_p (window) ||
+ ((window == windows) && !(window->next)))
+ {
+ calling_window = window;
+ calling_window_node = window->node;
+ calling_window_point = window->point;
+ calling_window_pagetop = window->pagetop;
+ }
+}
+
+/* Restore the caller's window so that it shows the node that it was showing
+ on entry to info_read_xxx_echo_area (). */
+static void
+restore_calling_window ()
+{
+ register WINDOW *win, *compwin = (WINDOW *)NULL;
+
+ /* If the calling window is still visible, and it is the window that
+ we used for completions output, then restore the calling window. */
+ for (win = windows; win; win = win->next)
+ {
+ if (completions_window_p (win))
+ compwin = win;
+
+ if (win == calling_window && win == compwin)
+ {
+ window_set_node_of_window (calling_window, calling_window_node);
+ calling_window->point = calling_window_point;
+ calling_window->pagetop = calling_window_pagetop;
+ compwin = (WINDOW *)NULL;
+ break;
+ }
+ }
+
+ /* Delete the completions window if it is still present, it isn't the
+ last window on the screen, and there aren't any prior echo area reads
+ pending which created a completions window. */
+ if (compwin)
+ {
+ if ((compwin != windows || windows->next) &&
+ !echo_area_stack_contains_completions_p ())
+ {
+ WINDOW *next;
+ int pagetop, start, end, amount;
+
+ next = compwin->next;
+ if (next)
+ {
+ start = next->first_row;
+ end = start + next->height;
+ amount = - (compwin->height + 1);
+ pagetop = next->pagetop;
+ }
+
+ info_delete_window_internal (compwin);
+
+ /* This is not necessary because info_delete_window_internal ()
+ calls echo_area_inform_of_deleted_window (), which does the
+ right thing. */
+#if defined (UNNECESSARY)
+ echo_area_completions_window = (WINDOW *)NULL;
+#endif /* UNNECESSARY */
+
+ if (next)
+ {
+ display_scroll_display (start, end, amount);
+ next->pagetop = pagetop;
+ display_update_display (windows);
+ }
+ }
+ }
+}
+
+/* Set up a new input line with PROMPT. */
+static void
+initialize_input_line (prompt)
+ char *prompt;
+{
+ input_line_prompt = prompt;
+ if (prompt)
+ strcpy (input_line, prompt);
+ else
+ input_line[0] = '\0';
+
+ input_line_beg = input_line_end = input_line_point = strlen (prompt);
+}
+
+static char *
+echo_area_after_read ()
+{
+ char *return_value;
+
+ if (info_aborted_echo_area)
+ {
+ info_aborted_echo_area = 0;
+ return_value = (char *)NULL;
+ }
+ else
+ {
+ if (input_line_beg == input_line_end)
+ return_value = xstrdup ("");
+ else
+ {
+ int line_len = input_line_end - input_line_beg;
+ return_value = (char *) xmalloc (1 + line_len);
+ strncpy (return_value, &input_line[input_line_beg], line_len);
+ return_value[line_len] = '\0';
+ }
+ }
+ return (return_value);
+}
+
+/* Read a line of text in the echo area. Return a malloc ()'ed string,
+ or NULL if the user aborted out of this read. WINDOW is the currently
+ active window, so that we can restore it when we need to. PROMPT, if
+ non-null, is a prompt to print before reading the line. */
+char *
+info_read_in_echo_area (window, prompt)
+ WINDOW *window;
+ char *prompt;
+{
+ char *line;
+
+ /* If the echo area is already active, remember the current state. */
+ if (echo_area_is_active)
+ push_echo_area ();
+
+ /* Initialize our local variables. */
+ initialize_input_line (prompt);
+
+ /* Initialize the echo area for the first (but maybe not the last) time. */
+ echo_area_initialize_node ();
+
+ /* Save away the original node of this window, and the window itself,
+ so echo area commands can temporarily use this window. */
+ remember_calling_window (window);
+
+ /* Let the rest of Info know that the echo area is active. */
+ echo_area_is_active++;
+ active_window = the_echo_area;
+
+ /* Read characters in the echo area. */
+ info_read_and_dispatch ();
+
+ echo_area_is_active--;
+
+ /* Restore the original active window and show point in it. */
+ active_window = calling_window;
+ restore_calling_window ();
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+
+ /* Get the value of the line. */
+ line = echo_area_after_read ();
+
+ /* If there is a previous loop waiting for us, restore it now. */
+ if (echo_area_is_active)
+ pop_echo_area ();
+
+ /* Return the results to the caller. */
+ return (line);
+}
+
+/* (re) Initialize the echo area node. */
+static void
+echo_area_initialize_node ()
+{
+ register int i;
+
+ for (i = input_line_end; i < sizeof (input_line); i++)
+ input_line[i] = ' ';
+
+ input_line[i - 1] = '\n';
+ window_set_node_of_window (the_echo_area, &input_line_node);
+ input_line[input_line_end] = '\n';
+}
+
+/* Prepare to read characters in the echo area. This can initialize the
+ echo area node, but its primary purpose is to side effect the input
+ line buffer contents. */
+void
+echo_area_prep_read ()
+{
+ if (the_echo_area->node != &input_line_node)
+ echo_area_initialize_node ();
+
+ the_echo_area->point = input_line_point;
+ input_line[input_line_end] = '\n';
+ display_update_one_window (the_echo_area);
+ display_cursor_at_point (active_window);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Echo Area Movement Commands */
+/* */
+/* **************************************************************** */
+
+DECLARE_INFO_COMMAND (ea_forward, _("Move forward a character"))
+{
+ if (count < 0)
+ ea_backward (window, -count, key);
+ else
+ {
+ input_line_point += count;
+ if (input_line_point > input_line_end)
+ input_line_point = input_line_end;
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_backward, _("Move backward a character"))
+{
+ if (count < 0)
+ ea_forward (window, -count, key);
+ else
+ {
+ input_line_point -= count;
+ if (input_line_point < input_line_beg)
+ input_line_point = input_line_beg;
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line"))
+{
+ input_line_point = input_line_beg;
+}
+
+DECLARE_INFO_COMMAND (ea_end_of_line, _("Move to the end of this line"))
+{
+ input_line_point = input_line_end;
+}
+
+#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c))
+
+/* Move forward a word in the input line. */
+DECLARE_INFO_COMMAND (ea_forward_word, _("Move forward a word"))
+{
+ int c;
+
+ if (count < 0)
+ ea_backward_word (window, -count, key);
+ else
+ {
+ while (count--)
+ {
+ if (input_line_point == input_line_end)
+ return;
+
+ /* If we are not in a word, move forward until we are in one.
+ Then, move forward until we hit a non-alphabetic character. */
+ c = input_line[input_line_point];
+
+ if (!alphabetic (c))
+ {
+ while (++input_line_point < input_line_end)
+ {
+ c = input_line[input_line_point];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ if (input_line_point == input_line_end)
+ return;
+
+ while (++input_line_point < input_line_end)
+ {
+ c = input_line[input_line_point];
+ if (!alphabetic (c))
+ break;
+ }
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_backward_word, _("Move backward a word"))
+{
+ int c;
+
+ if (count < 0)
+ ea_forward_word (window, -count, key);
+ else
+ {
+ while (count--)
+ {
+ if (input_line_point == input_line_beg)
+ return;
+
+ /* Like ea_forward_word (), except that we look at the
+ characters just before point. */
+
+ c = input_line[input_line_point - 1];
+
+ if (!alphabetic (c))
+ {
+ while ((--input_line_point) != input_line_beg)
+ {
+ c = input_line[input_line_point - 1];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ while (input_line_point != input_line_beg)
+ {
+ c = input_line[input_line_point - 1];
+ if (!alphabetic (c))
+ break;
+ else
+ --input_line_point;
+ }
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_delete, _("Delete the character under the cursor"))
+{
+ register int i;
+
+ if (count < 0)
+ ea_rubout (window, -count, key);
+ else
+ {
+ if (input_line_point == input_line_end)
+ return;
+
+ if (info_explicit_arg || count > 1)
+ {
+ int orig_point;
+
+ orig_point = input_line_point;
+ ea_forward (window, count, key);
+ ea_kill_text (orig_point, input_line_point);
+ input_line_point = orig_point;
+ }
+ else
+ {
+ for (i = input_line_point; i < input_line_end; i++)
+ input_line[i] = input_line[i + 1];
+
+ input_line_end--;
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_rubout, _("Delete the character behind the cursor"))
+{
+ if (count < 0)
+ ea_delete (window, -count, key);
+ else
+ {
+ int start;
+
+ if (input_line_point == input_line_beg)
+ return;
+
+ start = input_line_point;
+ ea_backward (window, count, key);
+
+ if (info_explicit_arg || count > 1)
+ ea_kill_text (start, input_line_point);
+ else
+ ea_delete (window, count, key);
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_abort, _("Cancel or quit operation"))
+{
+ /* If any text, just discard it, and restore the calling window's node.
+ If no text, quit. */
+ if (input_line_end != input_line_beg)
+ {
+ terminal_ring_bell ();
+ input_line_end = input_line_point = input_line_beg;
+ if (calling_window->node != calling_window_node)
+ restore_calling_window ();
+ }
+ else
+ info_aborted_echo_area = 1;
+}
+
+DECLARE_INFO_COMMAND (ea_newline, _("Accept (or force completion of) this line"))
+{
+ /* Stub does nothing. Simply here to see if it has been executed. */
+}
+
+DECLARE_INFO_COMMAND (ea_quoted_insert, _("Insert next character verbatim"))
+{
+ unsigned char character;
+
+ character = info_get_another_input_char ();
+ ea_insert (window, count, character);
+}
+
+DECLARE_INFO_COMMAND (ea_insert, _("Insert this character"))
+{
+ register int i;
+
+ if ((input_line_end + 1) == EA_MAX_INPUT)
+ {
+ terminal_ring_bell ();
+ return;
+ }
+
+ for (i = input_line_end + 1; i != input_line_point; i--)
+ input_line[i] = input_line[i - 1];
+
+ input_line[input_line_point] = key;
+ input_line_point++;
+ input_line_end++;
+}
+
+DECLARE_INFO_COMMAND (ea_tab_insert, _("Insert a TAB character"))
+{
+ ea_insert (window, count, '\t');
+}
+
+/* Transpose the characters at point. If point is at the end of the line,
+ then transpose the characters before point. */
+DECLARE_INFO_COMMAND (ea_transpose_chars, _("Transpose characters at point"))
+{
+ /* Handle conditions that would make it impossible to transpose
+ characters. */
+ if (!count || !input_line_point || (input_line_end - input_line_beg) < 2)
+ return;
+
+ while (count)
+ {
+ int t;
+ if (input_line_point == input_line_end)
+ {
+ t = input_line[input_line_point - 1];
+
+ input_line[input_line_point - 1] = input_line[input_line_point - 2];
+ input_line[input_line_point - 2] = t;
+ }
+ else
+ {
+ t = input_line[input_line_point];
+
+ input_line[input_line_point] = input_line[input_line_point - 1];
+ input_line[input_line_point - 1] = t;
+
+ if (count < 0 && input_line_point != input_line_beg)
+ input_line_point--;
+ else
+ input_line_point++;
+ }
+
+ if (count < 0)
+ count++;
+ else
+ count--;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Echo Area Killing and Yanking */
+/* */
+/* **************************************************************** */
+
+static char **kill_ring = (char **)NULL;
+static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */
+static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */
+static int kill_ring_loc = 0; /* Location of current yank pointer. */
+
+/* The largest number of kills that we remember at one time. */
+static int max_retained_kills = 15;
+
+DECLARE_INFO_COMMAND (ea_yank, _("Yank back the contents of the last kill"))
+{
+ register int i;
+ register char *text;
+
+ if (!kill_ring_index)
+ {
+ inform_in_echo_area (_("Kill ring is empty"));
+ return;
+ }
+
+ text = kill_ring[kill_ring_loc];
+
+ for (i = 0; text[i]; i++)
+ ea_insert (window, 1, text[i]);
+}
+
+/* If the last command was yank, or yank_pop, and the text just before
+ point is identical to the current kill item, then delete that text
+ from the line, rotate the index down, and yank back some other text. */
+DECLARE_INFO_COMMAND (ea_yank_pop, _("Yank back a previous kill"))
+{
+ register int len;
+
+ if (((ea_last_executed_command != ea_yank) &&
+ (ea_last_executed_command != ea_yank_pop)) ||
+ (kill_ring_index == 0))
+ return;
+
+ len = strlen (kill_ring[kill_ring_loc]);
+
+ /* Delete the last yanked item from the line. */
+ {
+ register int i, counter;
+
+ counter = input_line_end - input_line_point;
+
+ for (i = input_line_point - len; counter; i++, counter--)
+ input_line[i] = input_line[i + len];
+
+ input_line_end -= len;
+ input_line_point -= len;
+ }
+
+ /* Get a previous kill, and yank that. */
+ kill_ring_loc--;
+ if (kill_ring_loc < 0)
+ kill_ring_loc = kill_ring_index - 1;
+
+ ea_yank (window, count, key);
+}
+
+/* Delete the text from point to end of line. */
+DECLARE_INFO_COMMAND (ea_kill_line, _("Kill to the end of the line"))
+{
+ if (count < 0)
+ {
+ ea_kill_text (input_line_point, input_line_beg);
+ input_line_point = input_line_beg;
+ }
+ else
+ ea_kill_text (input_line_point, input_line_end);
+}
+
+/* Delete the text from point to beg of line. */
+DECLARE_INFO_COMMAND (ea_backward_kill_line,
+ _("Kill to the beginning of the line"))
+{
+ if (count < 0)
+ ea_kill_text (input_line_point, input_line_end);
+ else
+ {
+ ea_kill_text (input_line_point, input_line_beg);
+ input_line_point = input_line_beg;
+ }
+}
+
+/* Delete from point to the end of the current word. */
+DECLARE_INFO_COMMAND (ea_kill_word, _("Kill the word following the cursor"))
+{
+ int orig_point = input_line_point;
+
+ if (count < 0)
+ ea_backward_kill_word (window, -count, key);
+ else
+ {
+ ea_forward_word (window, count, key);
+
+ if (input_line_point != orig_point)
+ ea_kill_text (orig_point, input_line_point);
+
+ input_line_point = orig_point;
+ }
+}
+
+/* Delete from point to the start of the current word. */
+DECLARE_INFO_COMMAND (ea_backward_kill_word,
+ _("Kill the word preceding the cursor"))
+{
+ int orig_point = input_line_point;
+
+ if (count < 0)
+ ea_kill_word (window, -count, key);
+ else
+ {
+ ea_backward_word (window, count, key);
+
+ if (input_line_point != orig_point)
+ ea_kill_text (orig_point, input_line_point);
+ }
+}
+
+/* The way to kill something. This appends or prepends to the last
+ kill, if the last command was a kill command. If FROM is less
+ than TO, then the killed text is appended to the most recent kill,
+ otherwise it is prepended. If the last command was not a kill command,
+ then a new slot is made for this kill. */
+static void
+ea_kill_text (from, to)
+ int from, to;
+{
+ register int i, counter, distance;
+ int killing_backwards, slot;
+ char *killed_text;
+
+ killing_backwards = (from > to);
+
+ /* If killing backwards, reverse the values of FROM and TO. */
+ if (killing_backwards)
+ {
+ int temp = from;
+ from = to;
+ to = temp;
+ }
+
+ /* Remember the text that we are about to delete. */
+ distance = to - from;
+ killed_text = (char *)xmalloc (1 + distance);
+ strncpy (killed_text, &input_line[from], distance);
+ killed_text[distance] = '\0';
+
+ /* Actually delete the text from the line. */
+ counter = input_line_end - to;
+
+ for (i = from; counter; i++, counter--)
+ input_line[i] = input_line[i + distance];
+
+ input_line_end -= distance;
+
+ /* If the last command was a kill, append or prepend the killed text to
+ the last command's killed text. */
+ if (echo_area_last_command_was_kill)
+ {
+ char *old, *new;
+
+ slot = kill_ring_loc;
+ old = kill_ring[slot];
+ new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text));
+
+ if (killing_backwards)
+ {
+ /* Prepend TEXT to current kill. */
+ strcpy (new, killed_text);
+ strcat (new, old);
+ }
+ else
+ {
+ /* Append TEXT to current kill. */
+ strcpy (new, old);
+ strcat (new, killed_text);
+ }
+
+ free (old);
+ free (killed_text);
+ kill_ring[slot] = new;
+ }
+ else
+ {
+ /* Try to store the kill in a new slot, unless that would cause there
+ to be too many remembered kills. */
+ slot = kill_ring_index;
+
+ if (slot == max_retained_kills)
+ slot = 0;
+
+ if (slot + 1 > kill_ring_slots)
+ kill_ring = (char **) xrealloc
+ (kill_ring,
+ (kill_ring_slots += max_retained_kills) * sizeof (char *));
+
+ if (slot != kill_ring_index)
+ free (kill_ring[slot]);
+ else
+ kill_ring_index++;
+
+ kill_ring[slot] = killed_text;
+
+ kill_ring_loc = slot;
+ }
+
+ /* Notice that the last command was a kill. */
+ echo_area_last_command_was_kill++;
+}
+
+/* **************************************************************** */
+/* */
+/* Echo Area Completion */
+/* */
+/* **************************************************************** */
+
+/* Pointer to an array of REFERENCE to complete over. */
+static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL;
+
+/* Sorted array of REFERENCE * which is the possible completions found in
+ the variable echo_area_completion_items. If there is only one element,
+ it is the only possible completion. */
+static REFERENCE **completions_found = (REFERENCE **)NULL;
+static int completions_found_index = 0;
+static int completions_found_slots = 0;
+
+/* The lowest common denominator found while completing. */
+static REFERENCE *LCD_completion;
+
+/* Internal functions used by the user calls. */
+static void build_completions (), completions_must_be_rebuilt ();
+
+/* Variable which holds the output of completions. */
+static NODE *possible_completions_output_node = (NODE *)NULL;
+
+static char *compwin_name = "*Completions*";
+
+/* Return non-zero if WINDOW is a window used for completions output. */
+static int
+completions_window_p (window)
+ WINDOW *window;
+{
+ int result = 0;
+
+ if (internal_info_node_p (window->node) &&
+ (strcmp (window->node->nodename, compwin_name) == 0))
+ result = 1;
+
+ return (result);
+}
+
+/* Workhorse for completion readers. If FORCE is non-zero, the user cannot
+ exit unless the line read completes, or is empty. */
+char *
+info_read_completing_internal (window, prompt, completions, force)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+ int force;
+{
+ char *line;
+
+ /* If the echo area is already active, remember the current state. */
+ if (echo_area_is_active)
+ push_echo_area ();
+
+ echo_area_must_complete_p = force;
+
+ /* Initialize our local variables. */
+ initialize_input_line (prompt);
+
+ /* Initialize the echo area for the first (but maybe not the last) time. */
+ echo_area_initialize_node ();
+
+ /* Save away the original node of this window, and the window itself,
+ so echo area commands can temporarily use this window. */
+ remember_calling_window (window);
+
+ /* Save away the list of items to complete over. */
+ echo_area_completion_items = completions;
+ completions_must_be_rebuilt ();
+
+ active_window = the_echo_area;
+ echo_area_is_active++;
+
+ /* Read characters in the echo area. */
+ while (1)
+ {
+ info_read_and_dispatch ();
+
+ line = echo_area_after_read ();
+
+ /* Force the completion to take place if the user hasn't accepted
+ a default or aborted, and if FORCE is active. */
+ if (force && line && *line && completions)
+ {
+ register int i;
+
+ build_completions ();
+
+ /* If there is only one completion, then make the line be that
+ completion. */
+ if (completions_found_index == 1)
+ {
+ free (line);
+ line = xstrdup (completions_found[0]->label);
+ break;
+ }
+
+ /* If one of the completions matches exactly, then that is okay, so
+ return the current line. */
+ for (i = 0; i < completions_found_index; i++)
+ if (strcasecmp (completions_found[i]->label, line) == 0)
+ {
+ free (line);
+ line = xstrdup (completions_found[i]->label);
+ break;
+ }
+
+ /* If no match, go back and try again. */
+ if (i == completions_found_index)
+ {
+ inform_in_echo_area (_("Not complete"));
+ continue;
+ }
+ }
+ break;
+ }
+ echo_area_is_active--;
+
+ /* Restore the original active window and show point in it. */
+ active_window = calling_window;
+ restore_calling_window ();
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+
+ echo_area_completion_items = (REFERENCE **)NULL;
+ completions_must_be_rebuilt ();
+
+ /* If there is a previous loop waiting for us, restore it now. */
+ if (echo_area_is_active)
+ pop_echo_area ();
+
+ return (line);
+}
+
+/* Read a line in the echo area with completion over COMPLETIONS. */
+char *
+info_read_completing_in_echo_area (window, prompt, completions)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+{
+ return (info_read_completing_internal (window, prompt, completions, 1));
+}
+
+/* Read a line in the echo area allowing completion over COMPLETIONS, but
+ not requiring it. */
+char *
+info_read_maybe_completing (window, prompt, completions)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+{
+ return (info_read_completing_internal (window, prompt, completions, 0));
+}
+
+DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions"))
+{
+ if (!echo_area_completion_items)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ build_completions ();
+
+ if (!completions_found_index)
+ {
+ terminal_ring_bell ();
+ inform_in_echo_area (_("No completions"));
+ }
+ else if ((completions_found_index == 1) && (key != '?'))
+ {
+ inform_in_echo_area (_("Sole completion"));
+ }
+ else
+ {
+ register int i, l;
+ int limit, count, max_label = 0;
+
+ initialize_message_buffer ();
+ printf_to_message_buffer
+ (_("There %s %d "), completions_found_index == 1 ? _("is") : _("are"),
+ completions_found_index);
+ printf_to_message_buffer
+ (_("completion%s:\n"), completions_found_index == 1 ? "" : "s");
+
+ /* Find the maximum length of a label. */
+ for (i = 0; i < completions_found_index; i++)
+ {
+ int len = strlen (completions_found[i]->label);
+ if (len > max_label)
+ max_label = len;
+ }
+
+ max_label += 4;
+
+ /* Find out how many columns we should print in. */
+ limit = calling_window->width / max_label;
+ if (limit != 1 && (limit * max_label == calling_window->width))
+ limit--;
+
+ /* Avoid a possible floating exception. If max_label > width then
+ the limit will be 0 and a divide-by-zero fault will result. */
+ if (limit == 0)
+ limit = 1;
+
+ /* How many iterations of the printing loop? */
+ count = (completions_found_index + (limit - 1)) / limit;
+
+ /* Watch out for special case. If the number of completions is less
+ than LIMIT, then just do the inner printing loop. */
+ if (completions_found_index < limit)
+ count = 1;
+
+ /* Print the sorted items, up-and-down alphabetically. */
+ for (i = 0; i < count; i++)
+ {
+ register int j;
+
+ for (j = 0, l = i; j < limit; j++)
+ {
+ if (l >= completions_found_index)
+ break;
+ else
+ {
+ char *label;
+ int printed_length, k;
+
+ label = completions_found[l]->label;
+ printed_length = strlen (label);
+ printf_to_message_buffer ("%s", label);
+
+ if (j + 1 < limit)
+ {
+ for (k = 0; k < max_label - printed_length; k++)
+ printf_to_message_buffer (" ");
+ }
+ }
+ l += count;
+ }
+ printf_to_message_buffer ("\n");
+ }
+
+ /* Make a new node to hold onto possible completions. Don't destroy
+ dangling pointers. */
+ {
+ NODE *temp;
+
+ temp = message_buffer_to_node ();
+ add_gcable_pointer (temp->contents);
+ name_internal_node (temp, compwin_name);
+ possible_completions_output_node = temp;
+ }
+
+ /* Find a suitable window for displaying the completions output.
+ First choice is an existing window showing completions output.
+ If there is only one window, and it is large, make another
+ (smaller) window, and use that one. Otherwise, use the caller's
+ window. */
+ {
+ WINDOW *compwin;
+
+ compwin = get_internal_info_window (compwin_name);
+
+ if (!compwin)
+ {
+ /* If we can split the window to display most of the completion
+ items, then do so. */
+ if (calling_window->height > (count * 2)
+ && calling_window->height / 2 >= WINDOW_MIN_SIZE)
+ {
+ int start, pagetop;
+#ifdef SPLIT_BEFORE_ACTIVE
+ int end;
+#endif
+
+ active_window = calling_window;
+
+ /* Perhaps we can scroll this window on redisplay. */
+ start = calling_window->first_row;
+ pagetop = calling_window->pagetop;
+
+ compwin =
+ window_make_window (possible_completions_output_node);
+ active_window = the_echo_area;
+ window_change_window_height
+ (compwin, -(compwin->height - (count + 2)));
+
+ window_adjust_pagetop (calling_window);
+ remember_calling_window (calling_window);
+
+#if defined (SPLIT_BEFORE_ACTIVE)
+ /* If the pagetop hasn't changed, scrolling the calling
+ window is a reasonable thing to do. */
+ if (pagetop == calling_window->pagetop)
+ {
+ end = start + calling_window->height;
+ display_scroll_display
+ (start, end, calling_window->prev->height + 1);
+ }
+#else /* !SPLIT_BEFORE_ACTIVE */
+ /* If the pagetop has changed, set the new pagetop here. */
+ if (pagetop != calling_window->pagetop)
+ {
+ int newtop = calling_window->pagetop;
+ calling_window->pagetop = pagetop;
+ set_window_pagetop (calling_window, newtop);
+ }
+#endif /* !SPLIT_BEFORE_ACTIVE */
+
+ echo_area_completions_window = compwin;
+ remember_window_and_node (compwin, compwin->node);
+ }
+ else
+ compwin = calling_window;
+ }
+
+ if (compwin->node != possible_completions_output_node)
+ {
+ window_set_node_of_window
+ (compwin, possible_completions_output_node);
+ remember_window_and_node (compwin, compwin->node);
+ }
+
+ display_update_display (windows);
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_complete, _("Insert completion"))
+{
+ if (!echo_area_completion_items)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ /* If KEY is SPC, and we are not forcing completion to take place, simply
+ insert the key. */
+ if (!echo_area_must_complete_p && key == SPC)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ if (ea_last_executed_command == ea_complete)
+ {
+ /* If the keypress is a SPC character, and we have already tried
+ completing once, and there are several completions, then check
+ the batch of completions to see if any continue with a space.
+ If there are some, insert the space character and continue. */
+ if (key == SPC && completions_found_index > 1)
+ {
+ register int i, offset;
+
+ offset = input_line_end - input_line_beg;
+
+ for (i = 0; i < completions_found_index; i++)
+ if (completions_found[i]->label[offset] == ' ')
+ break;
+
+ if (completions_found[i])
+ ea_insert (window, 1, ' ');
+ else
+ {
+ ea_possible_completions (window, count, key);
+ return;
+ }
+ }
+ else
+ {
+ ea_possible_completions (window, count, key);
+ return;
+ }
+ }
+
+ input_line_point = input_line_end;
+ build_completions ();
+
+ if (!completions_found_index)
+ terminal_ring_bell ();
+ else if (LCD_completion->label[0] == '\0')
+ ea_possible_completions (window, count, key);
+ else
+ {
+ register int i;
+ input_line_point = input_line_end = input_line_beg;
+ for (i = 0; LCD_completion->label[i]; i++)
+ ea_insert (window, 1, LCD_completion->label[i]);
+ }
+}
+
+/* Utility REFERENCE used to store possible LCD. */
+static REFERENCE LCD_reference = { (char *)NULL, (char *)NULL, (char *)NULL };
+
+static void remove_completion_duplicates ();
+
+/* Variables which remember the state of the most recent call
+ to build_completions (). */
+static char *last_completion_request = (char *)NULL;
+static REFERENCE **last_completion_items = (REFERENCE **)NULL;
+
+/* How to tell the completion builder to reset internal state. */
+static void
+completions_must_be_rebuilt ()
+{
+ maybe_free (last_completion_request);
+ last_completion_request = (char *)NULL;
+ last_completion_items = (REFERENCE **)NULL;
+}
+
+/* Build a list of possible completions from echo_area_completion_items,
+ and the contents of input_line. */
+static void
+build_completions ()
+{
+ register int i, len;
+ register REFERENCE *entry;
+ char *request;
+ int informed_of_lengthy_job = 0;
+
+ /* If there are no items to complete over, exit immediately. */
+ if (!echo_area_completion_items)
+ {
+ completions_found_index = 0;
+ LCD_completion = (REFERENCE *)NULL;
+ return;
+ }
+
+ /* Check to see if this call to build completions is the same as the last
+ call to build completions. */
+ len = input_line_end - input_line_beg;
+ request = (char *)xmalloc (1 + len);
+ strncpy (request, &input_line[input_line_beg], len);
+ request[len] = '\0';
+
+ if (last_completion_request && last_completion_items &&
+ last_completion_items == echo_area_completion_items &&
+ (strcmp (last_completion_request, request) == 0))
+ {
+ free (request);
+ return;
+ }
+
+ maybe_free (last_completion_request);
+ last_completion_request = request;
+ last_completion_items = echo_area_completion_items;
+
+ /* Always start at the beginning of the list. */
+ completions_found_index = 0;
+ LCD_completion = (REFERENCE *)NULL;
+
+ for (i = 0; (entry = echo_area_completion_items[i]); i++)
+ {
+ if (strncasecmp (request, entry->label, len) == 0)
+ add_pointer_to_array (entry, completions_found_index,
+ completions_found, completions_found_slots,
+ 20, REFERENCE *);
+
+ if (!informed_of_lengthy_job && completions_found_index > 100)
+ {
+ informed_of_lengthy_job = 1;
+ window_message_in_echo_area (_("Building completions..."));
+ }
+ }
+
+ if (!completions_found_index)
+ return;
+
+ /* Sort and prune duplicate entries from the completions array. */
+ remove_completion_duplicates ();
+
+ /* If there is only one completion, just return that. */
+ if (completions_found_index == 1)
+ {
+ LCD_completion = completions_found[0];
+ return;
+ }
+
+ /* Find the least common denominator. */
+ {
+ long shortest = 100000;
+
+ for (i = 1; i < completions_found_index; i++)
+ {
+ register int j;
+ int c1, c2;
+
+ for (j = 0;
+ (c1 = info_tolower (completions_found[i - 1]->label[j])) &&
+ (c2 = info_tolower (completions_found[i]->label[j]));
+ j++)
+ if (c1 != c2)
+ break;
+
+ if (shortest > j)
+ shortest = j;
+ }
+
+ maybe_free (LCD_reference.label);
+ LCD_reference.label = (char *)xmalloc (1 + shortest);
+ strncpy (LCD_reference.label, completions_found[0]->label, shortest);
+ LCD_reference.label[shortest] = '\0';
+ LCD_completion = &LCD_reference;
+ }
+
+ if (informed_of_lengthy_job)
+ echo_area_initialize_node ();
+}
+
+/* Function called by qsort. */
+static int
+compare_references (entry1, entry2)
+ REFERENCE **entry1, **entry2;
+{
+ return (strcasecmp ((*entry1)->label, (*entry2)->label));
+}
+
+/* Prune duplicate entries from COMPLETIONS_FOUND. */
+static void
+remove_completion_duplicates ()
+{
+ register int i, j;
+ REFERENCE **temp;
+ int newlen;
+
+ if (!completions_found_index)
+ return;
+
+ /* Sort the items. */
+ qsort (completions_found, completions_found_index, sizeof (REFERENCE *),
+ compare_references);
+
+ for (i = 0, newlen = 1; i < completions_found_index - 1; i++)
+ {
+ if (strcmp (completions_found[i]->label,
+ completions_found[i + 1]->label) == 0)
+ completions_found[i] = (REFERENCE *)NULL;
+ else
+ newlen++;
+ }
+
+ /* We have marked all the dead slots. It is faster to copy the live slots
+ twice than to prune the dead slots one by one. */
+ temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *));
+ for (i = 0, j = 0; i < completions_found_index; i++)
+ if (completions_found[i])
+ temp[j++] = completions_found[i];
+
+ for (i = 0; i < newlen; i++)
+ completions_found[i] = temp[i];
+
+ completions_found[i] = (REFERENCE *)NULL;
+ completions_found_index = newlen;
+ free (temp);
+}
+
+/* Scroll the "other" window. If there is a window showing completions, scroll
+ that one, otherwise scroll the window which was active on entering the read
+ function. */
+DECLARE_INFO_COMMAND (ea_scroll_completions_window, _("Scroll the completions window"))
+{
+ WINDOW *compwin;
+ int old_pagetop;
+
+ compwin = get_internal_info_window (compwin_name);
+
+ if (!compwin)
+ compwin = calling_window;
+
+ old_pagetop = compwin->pagetop;
+
+ /* Let info_scroll_forward () do the work, and print any messages that
+ need to be displayed. */
+ info_scroll_forward (compwin, count, key);
+}
+
+/* Function which gets called when an Info window is deleted while the
+ echo area is active. WINDOW is the window which has just been deleted. */
+void
+echo_area_inform_of_deleted_window (window)
+ WINDOW *window;
+{
+ /* If this is the calling_window, forget what we remembered about it. */
+ if (window == calling_window)
+ {
+ if (active_window != the_echo_area)
+ remember_calling_window (active_window);
+ else
+ remember_calling_window (windows);
+ }
+
+ /* If this window was the echo_area_completions_window, then notice that
+ the window has been deleted. */
+ if (window == echo_area_completions_window)
+ echo_area_completions_window = (WINDOW *)NULL;
+}
+
+/* **************************************************************** */
+/* */
+/* Pushing and Popping the Echo Area */
+/* */
+/* **************************************************************** */
+
+/* Push and Pop the echo area. */
+typedef struct {
+ char *line;
+ char *prompt;
+ REFERENCE **comp_items;
+ int point, beg, end;
+ int must_complete;
+ NODE node;
+ WINDOW *compwin;
+} PUSHED_EA;
+
+static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;
+static int pushed_echo_areas_index = 0;
+static int pushed_echo_areas_slots = 0;
+
+/* Pushing the echo_area has a side effect of zeroing the completion_items. */
+static void
+push_echo_area ()
+{
+ PUSHED_EA *pushed;
+
+ pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA));
+ pushed->line = xstrdup (input_line);
+ pushed->prompt = input_line_prompt;
+ pushed->point = input_line_point;
+ pushed->beg = input_line_beg;
+ pushed->end = input_line_end;
+ pushed->node = input_line_node;
+ pushed->comp_items = echo_area_completion_items;
+ pushed->must_complete = echo_area_must_complete_p;
+ pushed->compwin = echo_area_completions_window;
+
+ add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas,
+ pushed_echo_areas_slots, 4, PUSHED_EA *);
+
+ echo_area_completion_items = (REFERENCE **)NULL;
+}
+
+static void
+pop_echo_area ()
+{
+ PUSHED_EA *popped;
+
+ popped = pushed_echo_areas[--pushed_echo_areas_index];
+
+ strcpy (input_line, popped->line);
+ free (popped->line);
+ input_line_prompt = popped->prompt;
+ input_line_point = popped->point;
+ input_line_beg = popped->beg;
+ input_line_end = popped->end;
+ input_line_node = popped->node;
+ echo_area_completion_items = popped->comp_items;
+ echo_area_must_complete_p = popped->must_complete;
+ echo_area_completions_window = popped->compwin;
+ completions_must_be_rebuilt ();
+
+ /* If the completion window no longer exists, forget about it. */
+ if (echo_area_completions_window)
+ {
+ register WINDOW *win;
+
+ for (win = windows; win; win = win->next)
+ if (echo_area_completions_window == win)
+ break;
+
+ /* If the window wasn't found, then it has already been deleted. */
+ if (!win)
+ echo_area_completions_window = (WINDOW *)NULL;
+ }
+
+ free (popped);
+}
+
+/* Returns non-zero if any of the prior stacked calls to read in the echo
+ area produced a completions window. */
+static int
+echo_area_stack_contains_completions_p ()
+{
+ register int i;
+
+ for (i = 0; i < pushed_echo_areas_index; i++)
+ if (pushed_echo_areas[i]->compwin)
+ return (1);
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Error Messages While Reading in Echo Area */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_SYS_TIME_H)
+# include <sys/time.h>
+# define HAVE_STRUCT_TIMEVAL
+#endif /* HAVE_SYS_TIME_H */
+
+static void
+pause_or_input ()
+{
+#if defined (FD_SET)
+ struct timeval timer;
+ fd_set readfds;
+ int ready;
+
+ FD_ZERO (&readfds);
+ FD_SET (fileno (stdin), &readfds);
+ timer.tv_sec = 2;
+ timer.tv_usec = 750;
+ ready = select (fileno (stdin) + 1, &readfds, (fd_set *) NULL,
+ (fd_set *) NULL, &timer);
+#endif /* FD_SET */
+}
+
+/* Print MESSAGE right after the end of the current line, and wait
+ for input or 2.75 seconds, whichever comes first. Then flush the
+ informational message that was printed. */
+void
+inform_in_echo_area (message)
+ char *message;
+{
+ register int i;
+ char *text;
+
+ text = xstrdup (message);
+ for (i = 0; text[i] && text[i] != '\n'; i++);
+ text[i] = '\0';
+
+ echo_area_initialize_node ();
+ sprintf (&input_line[input_line_end], "%s[%s]\n",
+ echo_area_is_active ? " ": "", text);
+ free (text);
+ the_echo_area->point = input_line_point;
+ display_update_one_window (the_echo_area);
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+ pause_or_input ();
+ echo_area_initialize_node ();
+}
diff --git a/texinfo/info/echo-area.h b/texinfo/info/echo-area.h
new file mode 100644
index 00000000000..b2386790c61
--- /dev/null
+++ b/texinfo/info/echo-area.h
@@ -0,0 +1,64 @@
+/* echo-area.h -- Functions used in reading information from the echo area.
+ $Id: echo-area.h,v 1.1 1998/03/23 04:42:27 law Exp $
+
+ This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 97 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#ifndef INFO_ECHO_AREA_H
+#define INFO_ECHO_AREA_H
+
+#define EA_MAX_INPUT 256
+
+extern int echo_area_is_active, info_aborted_echo_area;
+
+/* Non-zero means that the last command executed while reading input
+ killed some text. */
+extern int echo_area_last_command_was_kill;
+
+extern void inform_in_echo_area (), echo_area_inform_of_deleted_window ();
+extern void echo_area_prep_read ();
+extern VFunction *ea_last_executed_command;
+
+/* Read a line of text in the echo area. Return a malloc ()'ed string,
+ or NULL if the user aborted out of this read. WINDOW is the currently
+ active window, so that we can restore it when we need to. PROMPT, if
+ non-null, is a prompt to print before reading the line. */
+extern char *info_read_in_echo_area ();
+
+/* Read a line in the echo area with completion over COMPLETIONS.
+ Takes arguments of WINDOW, PROMPT, and COMPLETIONS, a REFERENCE **. */
+char *info_read_completing_in_echo_area ();
+
+/* Read a line in the echo area allowing completion over COMPLETIONS, but
+ not requiring it. Takes arguments of WINDOW, PROMPT, and COMPLETIONS,
+ a REFERENCE **. */
+extern char *info_read_maybe_completing ();
+
+extern void ea_insert (), ea_quoted_insert ();
+extern void ea_beg_of_line (), ea_backward (), ea_delete (), ea_end_of_line ();
+extern void ea_forward (), ea_abort (), ea_rubout (), ea_complete ();
+extern void ea_newline (), ea_kill_line (), ea_transpose_chars ();
+extern void ea_yank (), ea_tab_insert (), ea_possible_completions ();
+extern void ea_backward_word (), ea_kill_word (), ea_forward_word ();
+extern void ea_yank_pop (), ea_backward_kill_word ();
+extern void ea_scroll_completions_window ();
+
+#endif /* not INFO_ECHO_AREA_H */
diff --git a/texinfo/info/funs.h b/texinfo/info/funs.h
new file mode 100644
index 00000000000..45fcb6ae274
--- /dev/null
+++ b/texinfo/info/funs.h
@@ -0,0 +1,111 @@
+/* funs.h -- Generated declarations for Info commands. */
+
+/* Functions declared in "./session.c". */
+extern void info_next_line ();
+extern void info_prev_line ();
+extern void info_end_of_line ();
+extern void info_beginning_of_line ();
+extern void info_forward_char ();
+extern void info_backward_char ();
+extern void info_forward_word ();
+extern void info_backward_word ();
+extern void info_global_next_node ();
+extern void info_global_prev_node ();
+extern void info_scroll_forward ();
+extern void info_scroll_backward ();
+extern void info_beginning_of_node ();
+extern void info_end_of_node ();
+extern void info_next_window ();
+extern void info_prev_window ();
+extern void info_split_window ();
+extern void info_delete_window ();
+extern void info_keep_one_window ();
+extern void info_scroll_other_window ();
+extern void info_grow_window ();
+extern void info_tile_windows ();
+extern void info_toggle_wrap ();
+extern void info_next_node ();
+extern void info_prev_node ();
+extern void info_up_node ();
+extern void info_last_node ();
+extern void info_first_node ();
+extern void info_history_node ();
+extern void info_last_menu_item ();
+extern void info_menu_digit ();
+extern void info_menu_item ();
+extern void info_xref_item ();
+extern void info_find_menu ();
+extern void info_visit_menu ();
+extern void info_goto_node ();
+extern void info_man ();
+extern void info_top_node ();
+extern void info_dir_node ();
+extern void info_kill_node ();
+extern void info_view_file ();
+extern void info_print_node ();
+extern void info_search ();
+extern void isearch_forward ();
+extern void isearch_backward ();
+extern void info_move_to_prev_xref ();
+extern void info_move_to_next_xref ();
+extern void info_select_reference_this_line ();
+extern void info_abort_key ();
+extern void info_move_to_window_line ();
+extern void info_redraw_display ();
+extern void info_quit ();
+extern void info_do_lowercase_version ();
+extern void info_add_digit_to_numeric_arg ();
+extern void info_universal_argument ();
+extern void info_numeric_arg_digit_loop ();
+
+/* Functions declared in "./echo-area.c". */
+extern void ea_forward ();
+extern void ea_backward ();
+extern void ea_beg_of_line ();
+extern void ea_end_of_line ();
+extern void ea_forward_word ();
+extern void ea_backward_word ();
+extern void ea_delete ();
+extern void ea_rubout ();
+extern void ea_abort ();
+extern void ea_newline ();
+extern void ea_quoted_insert ();
+extern void ea_insert ();
+extern void ea_tab_insert ();
+extern void ea_transpose_chars ();
+extern void ea_yank ();
+extern void ea_yank_pop ();
+extern void ea_kill_line ();
+extern void ea_backward_kill_line ();
+extern void ea_kill_word ();
+extern void ea_backward_kill_word ();
+extern void ea_possible_completions ();
+extern void ea_complete ();
+extern void ea_scroll_completions_window ();
+
+/* Functions declared in "./infodoc.c". */
+extern void info_get_help_window ();
+extern void info_get_info_help_node ();
+extern void describe_key ();
+extern void info_where_is ();
+
+/* Functions declared in "./m-x.c". */
+extern void describe_command ();
+extern void info_execute_command ();
+extern void set_screen_height ();
+
+/* Functions declared in "./indices.c". */
+extern void info_index_search ();
+extern void info_next_index_match ();
+extern void info_index_apropos ();
+
+/* Functions declared in "./nodemenu.c". */
+extern void list_visited_nodes ();
+extern void select_visited_node ();
+
+/* Functions declared in "./footnotes.c". */
+extern void info_show_footnotes ();
+
+/* Functions declared in "./variables.c". */
+extern void describe_variable ();
+extern void set_variable ();