Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / lib / readline / readline.c
index 8ff6e98..28801f1 100644 (file)
@@ -1,14 +1,14 @@
 /* readline.c -- a general facility for reading lines of input
    with emacs style editing and completion. */
 
 /* readline.c -- a general facility for reading lines of input
    with emacs style editing and completion. */
 
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
 
    The GNU Readline Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU General Public License
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
 
    The GNU Readline Library 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 1, or
+   as published by the Free Software Foundation; either version 2, or
    (at your option) any later version.
 
    The GNU Readline Library is distributed in the hope that it will be
    (at your option) any later version.
 
    The GNU Readline Library is distributed in the hope that it will be
@@ -19,7 +19,7 @@
    The GNU General Public License is often shipped with GNU software, and
    is generally kept in a file called COPYING or LICENSE.  If you do not
    have a copy of the license, write to the Free Software Foundation,
    The GNU General Public License is often shipped with GNU software, and
    is generally kept in a file called COPYING or LICENSE.  If you do not
    have a copy of the license, write to the Free Software Foundation,
-   675 Mass Ave, Cambridge, MA 02139, USA. */
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #define READLINE_LIBRARY
 
 #if defined (HAVE_CONFIG_H)
 #define READLINE_LIBRARY
 
 #if defined (HAVE_CONFIG_H)
 #  include <locale.h>
 #endif
 
 #  include <locale.h>
 #endif
 
-#include <signal.h>
 #include <stdio.h>
 #include "posixjmp.h"
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
 #include <stdio.h>
 #include "posixjmp.h"
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 #if defined (__EMX__)
 #  define INCL_DOSPROCESS
 
 #if defined (__EMX__)
 #  define INCL_DOSPROCESS
 #include "readline.h"
 #include "history.h"
 
 #include "readline.h"
 #include "history.h"
 
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
 #ifndef RL_LIBRARY_VERSION
 #ifndef RL_LIBRARY_VERSION
-#  define RL_LIBRARY_VERSION "2.2-bash"
+#  define RL_LIBRARY_VERSION "4.3"
 #endif
 
 #endif
 
-/* Evaluates its arguments multiple times. */
-#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
-
-/* NOTE: Functions and variables prefixed with `_rl_' are
-   pseudo-global: they are global so they can be shared
-   between files in the readline library, but are not intended
-   to be visible to readline callers. */
-
-/* Variables and functions imported from terminal.c */
-extern int _rl_init_terminal_io ();
-extern void _rl_enable_meta_key ();
-#ifdef _MINIX
-extern void _rl_output_character_function ();
-#else
-extern int _rl_output_character_function ();
+#ifndef RL_READLINE_VERSION
+#  define RL_READLINE_VERSION  0x0403
 #endif
 #endif
-extern void _rl_get_screen_size ();
-
-extern int _rl_enable_meta;
-extern int _rl_term_autowrap;
-extern int screenwidth, screenheight, screenchars;
-
-/* Variables and functions imported from rltty.c. */
-extern void rl_prep_terminal (), rl_deprep_terminal ();
-extern void rltty_set_default_bindings ();
-
-/* Functions imported from util.c. */
-extern void _rl_abort_internal ();
-extern void rl_extend_line_buffer ();
-extern int alphabetic ();
-
-/* Functions imported from bind.c. */
-extern void _rl_bind_if_unbound ();
-extern int rl_set_keymap_from_edit_mode ();
-
-/* Functions imported from input.c. */
-extern int _rl_any_typein ();
-extern void _rl_insert_typein ();
-extern int rl_read_key ();
-
-/* Functions imported from nls.c */
-extern int _rl_init_eightbit ();
-
-/* Functions imported from shell.c */
-extern char *get_env_value ();
-
-/* External redisplay functions and variables from display.c */
-extern void _rl_move_vert ();
-extern void _rl_update_final ();
-extern void _rl_clear_to_eol ();
-extern void _rl_clear_screen ();
-
-extern void _rl_save_prompt ();
-extern void _rl_restore_prompt ();
-
-extern void _rl_erase_at_end_of_line ();
-extern void _rl_move_cursor_relative ();
-
-extern int _rl_vis_botlin;
-extern int _rl_last_c_pos;
-extern int _rl_horizontal_scroll_mode;
-extern int rl_display_fixed;
-extern int _rl_suppress_redisplay;
-extern char *rl_display_prompt;
-
-/* Variables imported from complete.c. */
-extern char *rl_completer_word_break_characters;
-extern char *rl_basic_word_break_characters;
-extern int rl_completion_query_items;
-extern int rl_complete_with_tilde_expansion;
-
-/* Variables and functions from macro.c. */
-extern void _rl_add_macro_char ();
-extern void _rl_with_macro_input ();
-extern int _rl_next_macro_key ();
-extern int _rl_defining_kbd_macro;
 
 
-#if defined (VI_MODE)
-/* Functions imported from vi_mode.c. */
-extern void _rl_vi_set_last ();
-extern void _rl_vi_reset_last ();
-extern void _rl_vi_done_inserting ();
-extern int _rl_vi_textmod_command ();
-extern void _rl_vi_initialize_line ();
-#endif /* VI_MODE */
-
-extern UNDO_LIST *rl_undo_list;
-extern int _rl_doing_an_undo;
+extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
 
 /* Forward declarations used in this file. */
 
 /* Forward declarations used in this file. */
-void _rl_free_history_entry ();
-
-int _rl_dispatch ();
-int _rl_init_argument ();
+static char *readline_internal PARAMS((void));
+static void readline_initialize_everything PARAMS((void));
 
 
-static char *readline_internal ();
-static void readline_initialize_everything ();
-static void start_using_history ();
-static void bind_arrow_keys ();
+static void bind_arrow_keys_internal PARAMS((Keymap));
+static void bind_arrow_keys PARAMS((void));
 
 
-#if !defined (__GO32__)
-static void readline_default_bindings ();
-#endif /* !__GO32__ */
-
-#if defined (__GO32__)
-#  include <go32.h>
-#  include <pc.h>
-#  undef HANDLE_SIGNALS
-#endif /* __GO32__ */
-
-extern char *xmalloc (), *xrealloc ();
+static void readline_default_bindings PARAMS((void));
 
 /* **************************************************************** */
 /*                                                                 */
 
 /* **************************************************************** */
 /*                                                                 */
@@ -185,7 +92,12 @@ extern char *xmalloc (), *xrealloc ();
 /*                                                                 */
 /* **************************************************************** */
 
 /*                                                                 */
 /* **************************************************************** */
 
-char *rl_library_version = RL_LIBRARY_VERSION;
+const char *rl_library_version = RL_LIBRARY_VERSION;
+
+int rl_readline_version = RL_READLINE_VERSION;
+
+/* True if this is `real' readline as opposed to some stub substitute. */
+int rl_gnu_readline_p = 1;
 
 /* A pointer to the keymap that is currently in use.
    By default, it is the standard emacs keymap. */
 
 /* A pointer to the keymap that is currently in use.
    By default, it is the standard emacs keymap. */
@@ -194,6 +106,9 @@ Keymap _rl_keymap = emacs_standard_keymap;
 /* The current style of editing. */
 int rl_editing_mode = emacs_mode;
 
 /* The current style of editing. */
 int rl_editing_mode = emacs_mode;
 
+/* The current insert mode:  input (the default) or overwrite */
+int rl_insert_mode = RL_IM_DEFAULT;
+
 /* Non-zero if we called this function from _rl_dispatch().  It's present
    so functions can find out whether they were called from a key binding
    or directly from an application. */
 /* Non-zero if we called this function from _rl_dispatch().  It's present
    so functions can find out whether they were called from a key binding
    or directly from an application. */
@@ -214,8 +129,13 @@ int rl_arg_sign = 1;
 /* Non-zero means we have been called at least once before. */
 static int rl_initialized;
 
 /* Non-zero means we have been called at least once before. */
 static int rl_initialized;
 
+#if 0
 /* If non-zero, this program is running in an EMACS buffer. */
 static int running_in_emacs;
 /* If non-zero, this program is running in an EMACS buffer. */
 static int running_in_emacs;
+#endif
+
+/* Flags word encapsulating the current readline state. */
+int rl_readline_state = RL_STATE_NONE;
 
 /* The current offset in the current input line. */
 int rl_point;
 
 /* The current offset in the current input line. */
 int rl_point;
@@ -230,7 +150,7 @@ int rl_end;
 int rl_done;
 
 /* The last function executed by readline. */
 int rl_done;
 
 /* The last function executed by readline. */
-Function *rl_last_func = (Function *)NULL;
+rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL;
 
 /* Top level environment for readline_internal (). */
 procenv_t readline_top_level;
 
 /* Top level environment for readline_internal (). */
 procenv_t readline_top_level;
@@ -242,19 +162,31 @@ FILE *_rl_in_stream, *_rl_out_stream;
 FILE *rl_instream = (FILE *)NULL;
 FILE *rl_outstream = (FILE *)NULL;
 
 FILE *rl_instream = (FILE *)NULL;
 FILE *rl_outstream = (FILE *)NULL;
 
-/* Non-zero means echo characters as they are read. */
-int readline_echoing_p = 1;
+/* Non-zero means echo characters as they are read.  Defaults to no echo;
+   set to 1 if there is a controlling terminal, we can get its attributes,
+   and the attributes include `echo'.  Look at rltty.c:prepare_terminal_settings
+   for the code that sets it. */
+int readline_echoing_p = 0;
 
 /* Current prompt. */
 
 /* Current prompt. */
-char *rl_prompt;
+char *rl_prompt = (char *)NULL;
 int rl_visible_prompt_length = 0;
 
 int rl_visible_prompt_length = 0;
 
+/* Set to non-zero by calling application if it has already printed rl_prompt
+   and does not want readline to do it the first time. */
+int rl_already_prompted = 0;
+
 /* The number of characters read in order to type this complete command. */
 int rl_key_sequence_length = 0;
 
 /* If non-zero, then this is the address of a function to call just
 /* The number of characters read in order to type this complete command. */
 int rl_key_sequence_length = 0;
 
 /* If non-zero, then this is the address of a function to call just
-   before readline_internal () prints the first prompt. */
-Function *rl_startup_hook = (Function *)NULL;
+   before readline_internal_setup () prints the first prompt. */
+rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
+
+/* If non-zero, this is the address of a function to call just before
+   readline_internal_setup () returns and readline_internal starts
+   reading input characters. */
+rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL;
 
 /* What we use internally.  You should always refer to RL_LINE_BUFFER. */
 static char *the_line;
 
 /* What we use internally.  You should always refer to RL_LINE_BUFFER. */
 static char *the_line;
@@ -267,7 +199,7 @@ int _rl_eof_char = CTRL ('D');
 int rl_pending_input = 0;
 
 /* Pointer to a useful terminal name. */
 int rl_pending_input = 0;
 
 /* Pointer to a useful terminal name. */
-char *rl_terminal_name = (char *)NULL;
+const char *rl_terminal_name = (const char *)NULL;
 
 /* Non-zero means to always use horizontal scrolling in line display. */
 int _rl_horizontal_scroll_mode = 0;
 
 /* Non-zero means to always use horizontal scrolling in line display. */
 int _rl_horizontal_scroll_mode = 0;
@@ -286,11 +218,18 @@ char *_rl_comment_begin;
 /* Keymap holding the function currently being executed. */
 Keymap rl_executing_keymap;
 
 /* Keymap holding the function currently being executed. */
 Keymap rl_executing_keymap;
 
+/* Non-zero means to erase entire line, including prompt, on empty input lines. */
+int rl_erase_empty_line = 0;
+
+/* Non-zero means to read only this many characters rather than up to a
+   character bound to accept-line. */
+int rl_num_chars_to_read;
+
 /* Line buffer and maintenence. */
 char *rl_line_buffer = (char *)NULL;
 int rl_line_buffer_len = 0;
 
 /* Line buffer and maintenence. */
 char *rl_line_buffer = (char *)NULL;
 int rl_line_buffer_len = 0;
 
-/* Forward declarations used by the display and termcap code. */
+/* Forward declarations used by the display, termcap, and history code. */
 
 /* **************************************************************** */
 /*                                                                 */
 
 /* **************************************************************** */
 /*                                                                 */
@@ -320,24 +259,35 @@ int _rl_output_meta_chars = 0;
 /* Non-zero means treat 0200 bit in terminal input as Meta bit. */
 int _rl_meta_flag = 0; /* Forward declaration */
 
 /* Non-zero means treat 0200 bit in terminal input as Meta bit. */
 int _rl_meta_flag = 0; /* Forward declaration */
 
+/* Set up the prompt and expand it.  Called from readline() and
+   rl_callback_handler_install (). */
+int
+rl_set_prompt (prompt)
+     const char *prompt;
+{
+  FREE (rl_prompt);
+  rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
+
+  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+  return 0;
+}
+  
 /* Read a line of input.  Prompt with PROMPT.  An empty PROMPT means
    none.  A return value of NULL means that EOF was encountered. */
 char *
 readline (prompt)
 /* Read a line of input.  Prompt with PROMPT.  An empty PROMPT means
    none.  A return value of NULL means that EOF was encountered. */
 char *
 readline (prompt)
-     char *prompt;
+     const char *prompt;
 {
   char *value;
 
 {
   char *value;
 
-  rl_prompt = prompt;
-
   /* If we are at EOF return a NULL string. */
   if (rl_pending_input == EOF)
     {
   /* If we are at EOF return a NULL string. */
   if (rl_pending_input == EOF)
     {
-      rl_pending_input = 0;
+      rl_clear_pending_input ();
       return ((char *)NULL);
     }
 
       return ((char *)NULL);
     }
 
-  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+  rl_set_prompt (prompt);
 
   rl_initialize ();
   (*rl_prep_term_function) (_rl_meta_flag);
 
   rl_initialize ();
   (*rl_prep_term_function) (_rl_meta_flag);
@@ -365,29 +315,43 @@ readline (prompt)
 STATIC_CALLBACK void
 readline_internal_setup ()
 {
 STATIC_CALLBACK void
 readline_internal_setup ()
 {
+  char *nprompt;
+
   _rl_in_stream = rl_instream;
   _rl_out_stream = rl_outstream;
 
   if (rl_startup_hook)
     (*rl_startup_hook) ();
 
   _rl_in_stream = rl_instream;
   _rl_out_stream = rl_outstream;
 
   if (rl_startup_hook)
     (*rl_startup_hook) ();
 
-  if (readline_echoing_p == 0)
+  /* If we're not echoing, we still want to at least print a prompt, because
+     rl_redisplay will not do it for us.  If the calling application has a
+     custom redisplay function, though, let that function handle it. */
+  if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
     {
     {
-      if (rl_prompt)
+      if (rl_prompt && rl_already_prompted == 0)
        {
        {
-         fprintf (_rl_out_stream, "%s", rl_prompt);
+         nprompt = _rl_strip_prompt (rl_prompt);
+         fprintf (_rl_out_stream, "%s", nprompt);
          fflush (_rl_out_stream);
          fflush (_rl_out_stream);
+         free (nprompt);
        }
     }
   else
     {
        }
     }
   else
     {
-      rl_on_new_line ();
+      if (rl_prompt && rl_already_prompted)
+       rl_on_new_line_with_prompt ();
+      else
+       rl_on_new_line ();
       (*rl_redisplay_function) ();
       (*rl_redisplay_function) ();
+    }
+
 #if defined (VI_MODE)
 #if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_vi_insertion_mode (1, 0);
+  if (rl_editing_mode == vi_mode)
+    rl_vi_insertion_mode (1, 0);
 #endif /* VI_MODE */
 #endif /* VI_MODE */
-    }
+
+  if (rl_pre_input_hook)
+    (*rl_pre_input_hook) ();
 }
 
 STATIC_CALLBACK char *
 }
 
 STATIC_CALLBACK char *
@@ -405,7 +369,7 @@ readline_internal_teardown (eof)
     {
       temp = savestring (the_line);
       rl_revert_line (1, 0);
     {
       temp = savestring (the_line);
       rl_revert_line (1, 0);
-      entry = replace_history_entry (where_history (), the_line, (HIST_ENTRY *)NULL);
+      entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
       _rl_free_history_entry (entry);
 
       strcpy (the_line, temp);
       _rl_free_history_entry (entry);
 
       strcpy (the_line, temp);
@@ -415,7 +379,10 @@ readline_internal_teardown (eof)
   /* At any rate, it is highly likely that this line has an undo list.  Get
      rid of it now. */
   if (rl_undo_list)
   /* At any rate, it is highly likely that this line has an undo list.  Get
      rid of it now. */
   if (rl_undo_list)
-    free_undo_list ();
+    rl_free_undo_list ();
+
+  /* Restore normal cursor, if available. */
+  _rl_set_insert_mode (RL_IM_INSERT, 0);
 
   return (eof ? (char *)NULL : savestring (the_line));
 }
 
   return (eof ? (char *)NULL : savestring (the_line));
 }
@@ -451,7 +418,9 @@ readline_internal_charloop ()
          rl_key_sequence_length = 0;
        }
 
          rl_key_sequence_length = 0;
        }
 
+      RL_SETSTATE(RL_STATE_READCMD);
       c = rl_read_key ();
       c = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_READCMD);
 
       /* EOF typed to a non-blank line is a <NL>. */
       if (c == EOF && rl_end)
 
       /* EOF typed to a non-blank line is a <NL>. */
       if (c == EOF && rl_end)
@@ -462,6 +431,7 @@ readline_internal_charloop ()
       if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
        {
 #if defined (READLINE_CALLBACKS)
       if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
        {
 #if defined (READLINE_CALLBACKS)
+         RL_SETSTATE(RL_STATE_DONE);
          return (rl_done = 1);
 #else
          eof_found = 1;
          return (rl_done = 1);
 #else
          eof_found = 1;
@@ -470,7 +440,7 @@ readline_internal_charloop ()
        }
 
       lastc = c;
        }
 
       lastc = c;
-      _rl_dispatch (c, _rl_keymap);
+      _rl_dispatch ((unsigned char)c, _rl_keymap);
 
       /* If there was no change in _rl_last_command_was_kill, then no kill
         has taken place.  Note that if input is pending we are reading
 
       /* If there was no change in _rl_last_command_was_kill, then no kill
         has taken place.  Note that if input is pending we are reading
@@ -485,9 +455,21 @@ readline_internal_charloop ()
        rl_vi_check ();
 #endif /* VI_MODE */
 
        rl_vi_check ();
 #endif /* VI_MODE */
 
+      if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
+        {
+          (*rl_redisplay_function) ();
+          rl_newline (1, '\n');
+        }
+
       if (rl_done == 0)
        (*rl_redisplay_function) ();
 
       if (rl_done == 0)
        (*rl_redisplay_function) ();
 
+      /* If the application writer has told us to erase the entire line if
+         the only character typed was something bound to rl_newline, do so. */
+      if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
+         rl_point == 0 && rl_end == 0)
+       _rl_erase_entire_line ();
+
 #if defined (READLINE_CALLBACKS)
       return 0;
 #else
 #if defined (READLINE_CALLBACKS)
       return 0;
 #else
@@ -501,7 +483,7 @@ readline_internal_charloop ()
 static int
 readline_internal_charloop ()
 {
 static int
 readline_internal_charloop ()
 {
-  int eof;
+  int eof = 1;
 
   while (rl_done == 0)
     eof = readline_internal_char ();
 
   while (rl_done == 0)
     eof = readline_internal_char ();
@@ -525,7 +507,7 @@ readline_internal ()
 void
 _rl_init_line_state ()
 {
 void
 _rl_init_line_state ()
 {
-  rl_point = rl_end = 0;
+  rl_point = rl_end = rl_mark = 0;
   the_line = rl_line_buffer;
   the_line[0] = 0;
 }
   the_line = rl_line_buffer;
   the_line[0] = 0;
 }
@@ -544,15 +526,24 @@ _rl_dispatch (key, map)
      register int key;
      Keymap map;
 {
      register int key;
      Keymap map;
 {
+  return _rl_dispatch_subseq (key, map, 0);
+}
+
+int
+_rl_dispatch_subseq (key, map, got_subseq)
+     register int key;
+     Keymap map;
+     int got_subseq;
+{
   int r, newkey;
   char *macro;
   int r, newkey;
   char *macro;
-  Function *func;
+  rl_command_func_t *func;
 
   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
     {
       if (map[ESC].type == ISKMAP)
        {
 
   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
     {
       if (map[ESC].type == ISKMAP)
        {
-         if (_rl_defining_kbd_macro)
+         if (RL_ISSTATE (RL_STATE_MACRODEF))
            _rl_add_macro_char (ESC);
          map = FUNCTION_TO_KEYMAP (map, ESC);
          key = UNMETA (key);
            _rl_add_macro_char (ESC);
          map = FUNCTION_TO_KEYMAP (map, ESC);
          key = UNMETA (key);
@@ -560,11 +551,11 @@ _rl_dispatch (key, map)
          return (_rl_dispatch (key, map));
        }
       else
          return (_rl_dispatch (key, map));
        }
       else
-       ding ();
+       rl_ding ();
       return 0;
     }
 
       return 0;
     }
 
-  if (_rl_defining_kbd_macro)
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
     _rl_add_macro_char (key);
 
   r = 0;
     _rl_add_macro_char (key);
 
   r = 0;
@@ -572,7 +563,7 @@ _rl_dispatch (key, map)
     {
     case ISFUNC:
       func = map[key].function;
     {
     case ISFUNC:
       func = map[key].function;
-      if (func != (Function *)NULL)
+      if (func)
        {
          /* Special case rl_do_lowercase_version (). */
          if (func == rl_do_lowercase_version)
        {
          /* Special case rl_do_lowercase_version (). */
          if (func == rl_do_lowercase_version)
@@ -585,15 +576,34 @@ _rl_dispatch (key, map)
 #endif
 
          rl_dispatching = 1;
 #endif
 
          rl_dispatching = 1;
+         RL_SETSTATE(RL_STATE_DISPATCHING);
          r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
          r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
+         RL_UNSETSTATE(RL_STATE_DISPATCHING);
          rl_dispatching = 0;
 
          /* If we have input pending, then the last command was a prefix
             command.  Don't change the state of rl_last_func.  Otherwise,
             remember the last command executed in this variable. */
          rl_dispatching = 0;
 
          /* If we have input pending, then the last command was a prefix
             command.  Don't change the state of rl_last_func.  Otherwise,
             remember the last command executed in this variable. */
-         if (!rl_pending_input && map[key].function != rl_digit_argument)
+         if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
            rl_last_func = map[key].function;
        }
            rl_last_func = map[key].function;
        }
+      else if (map[ANYOTHERKEY].function)
+       {
+         /* OK, there's no function bound in this map, but there is a
+            shadow function that was overridden when the current keymap
+            was created.  Return -2 to note  that. */
+         _rl_unget_char  (key);
+         return -2;
+       }
+      else if (got_subseq)
+       {
+         /* Return -1 to note that we're in a subsequence, but  we don't
+            have a matching key, nor was one overridden.  This means
+            we need to back up the recursion chain and find the last
+            subsequence that is bound to a function. */
+         _rl_unget_char (key);
+         return -1;
+       }
       else
        {
          _rl_abort_internal ();
       else
        {
          _rl_abort_internal ();
@@ -602,11 +612,59 @@ _rl_dispatch (key, map)
       break;
 
     case ISKMAP:
       break;
 
     case ISKMAP:
-      if (map[key].function != (Function *)NULL)
+      if (map[key].function != 0)
        {
        {
+#if defined (VI_MODE)
+         /* The only way this test will be true is if a subsequence has been
+            bound starting with ESC, generally the arrow keys.  What we do is
+            check whether there's input in the queue, which there generally
+            will be if an arrow key has been pressed, and, if there's not,
+            just dispatch to (what we assume is) rl_vi_movement_mode right
+            away.  This is essentially an input test with a zero timeout. */
+         if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
+             && _rl_input_queued (0) == 0)
+           return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
+#endif
+
          rl_key_sequence_length++;
          rl_key_sequence_length++;
+
+         if (key == ESC)
+           RL_SETSTATE(RL_STATE_METANEXT);
+         RL_SETSTATE(RL_STATE_MOREINPUT);
          newkey = rl_read_key ();
          newkey = rl_read_key ();
-         r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
+         RL_UNSETSTATE(RL_STATE_MOREINPUT);
+         if (key == ESC)
+           RL_UNSETSTATE(RL_STATE_METANEXT);
+
+         if (newkey < 0)
+           {
+             _rl_abort_internal ();
+             return -1;
+           }
+
+         r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function);
+
+         if (r == -2)
+           /* We didn't match anything, and the keymap we're indexed into
+              shadowed a function previously bound to that prefix.  Call
+              the function.  The recursive call to _rl_dispatch_subseq has
+              already taken care of pushing any necessary input back onto
+              the input queue with _rl_unget_char. */
+           r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
+         else if (r && map[ANYOTHERKEY].function)
+           {
+             /* We didn't match (r is probably -1), so return something to
+                tell the caller that it should try ANYOTHERKEY for an
+                overridden function. */
+             _rl_unget_char (key);
+             return -2;
+           }
+         else if (r && got_subseq)
+           {
+             /* OK, back up the chain. */
+             _rl_unget_char (key);
+             return -1;
+           }
        }
       else
        {
        }
       else
        {
@@ -616,7 +674,7 @@ _rl_dispatch (key, map)
       break;
 
     case ISMACR:
       break;
 
     case ISMACR:
-      if (map[key].function != (Function *)NULL)
+      if (map[key].function != 0)
        {
          macro = savestring ((char *)map[key].function);
          _rl_with_macro_input (macro);
        {
          macro = savestring ((char *)map[key].function);
          _rl_with_macro_input (macro);
@@ -646,8 +704,11 @@ rl_initialize ()
      terminal and data structures. */
   if (!rl_initialized)
     {
      terminal and data structures. */
   if (!rl_initialized)
     {
+      RL_SETSTATE(RL_STATE_INITIALIZING);
       readline_initialize_everything ();
       readline_initialize_everything ();
+      RL_UNSETSTATE(RL_STATE_INITIALIZING);
       rl_initialized++;
       rl_initialized++;
+      RL_SETSTATE(RL_STATE_INITIALIZED);
     }
 
   /* Initalize the current line information. */
     }
 
   /* Initalize the current line information. */
@@ -655,15 +716,16 @@ rl_initialize ()
 
   /* We aren't done yet.  We haven't even gotten started yet! */
   rl_done = 0;
 
   /* We aren't done yet.  We haven't even gotten started yet! */
   rl_done = 0;
+  RL_UNSETSTATE(RL_STATE_DONE);
 
   /* Tell the history routines what is going on. */
 
   /* Tell the history routines what is going on. */
-  start_using_history ();
+  _rl_start_using_history ();
 
   /* Make the display buffer match the state of the line. */
   rl_reset_line_state ();
 
   /* No such function typed yet. */
 
   /* Make the display buffer match the state of the line. */
   rl_reset_line_state ();
 
   /* No such function typed yet. */
-  rl_last_func = (Function *)NULL;
+  rl_last_func = (rl_command_func_t *)NULL;
 
   /* Parsing of key-bindings begins in an enabled state. */
   _rl_parsing_conditionalized_out = 0;
 
   /* Parsing of key-bindings begins in an enabled state. */
   _rl_parsing_conditionalized_out = 0;
@@ -673,9 +735,13 @@ rl_initialize ()
     _rl_vi_initialize_line ();
 #endif
 
     _rl_vi_initialize_line ();
 #endif
 
+  /* Each line starts in insert mode (the default). */
+  _rl_set_insert_mode (RL_IM_DEFAULT, 1);
+
   return 0;
 }
 
   return 0;
 }
 
+#if 0
 #if defined (__EMX__)
 static void
 _emx_build_environ ()
 #if defined (__EMX__)
 static void
 _emx_build_environ ()
@@ -699,18 +765,23 @@ _emx_build_environ ()
   *tp = 0;
 }
 #endif /* __EMX__ */
   *tp = 0;
 }
 #endif /* __EMX__ */
+#endif
 
 /* Initialize the entire state of the world. */
 static void
 readline_initialize_everything ()
 {
 
 /* Initialize the entire state of the world. */
 static void
 readline_initialize_everything ()
 {
+#if 0
 #if defined (__EMX__)
   if (environ == 0)
     _emx_build_environ ();
 #endif
 #if defined (__EMX__)
   if (environ == 0)
     _emx_build_environ ();
 #endif
+#endif
 
 
-  /* Find out if we are running in Emacs. */
-  running_in_emacs = get_env_value ("EMACS") != (char *)0;
+#if 0
+  /* Find out if we are running in Emacs -- UNUSED. */
+  running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
+#endif
 
   /* Set up input and output if they are not already set up. */
   if (!rl_instream)
 
   /* Set up input and output if they are not already set up. */
   if (!rl_instream)
@@ -727,15 +798,15 @@ readline_initialize_everything ()
 
   /* Allocate data structures. */
   if (rl_line_buffer == 0)
 
   /* Allocate data structures. */
   if (rl_line_buffer == 0)
-    rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+    rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
 
   /* Initialize the terminal interface. */
 
   /* Initialize the terminal interface. */
-  _rl_init_terminal_io ((char *)NULL);
+  if (rl_terminal_name == 0)
+    rl_terminal_name = sh_get_env_value ("TERM");
+  _rl_init_terminal_io (rl_terminal_name);
 
 
-#if !defined (__GO32__)
   /* Bind tty characters to readline functions. */
   readline_default_bindings ();
   /* Bind tty characters to readline functions. */
   readline_default_bindings ();
-#endif /* !__GO32__ */
 
   /* Initialize the function names. */
   rl_initialize_funmap ();
 
   /* Initialize the function names. */
   rl_initialize_funmap ();
@@ -749,8 +820,8 @@ readline_initialize_everything ()
   /* XXX */
   if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
     {
   /* XXX */
   if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
     {
-      screenwidth--;
-      screenchars -= screenheight;
+      _rl_screenwidth--;
+      _rl_screenchars -= _rl_screenheight;
     }
 
   /* Override the effect of any `set keymap' assignments in the
     }
 
   /* Override the effect of any `set keymap' assignments in the
@@ -776,1328 +847,127 @@ readline_initialize_everything ()
 static void
 readline_default_bindings ()
 {
 static void
 readline_default_bindings ()
 {
-  rltty_set_default_bindings (_rl_keymap);
-}
-
-static void
-bind_arrow_keys_internal ()
-{
-  Function *f;
-
-  f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
-  if (!f || f == rl_do_lowercase_version)
-    {
-      _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
-      _rl_bind_if_unbound ("\033[B", rl_get_next_history);
-      _rl_bind_if_unbound ("\033[C", rl_forward);
-      _rl_bind_if_unbound ("\033[D", rl_backward);
-    }
-
-  f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
-  if (!f || f == rl_do_lowercase_version)
-    {
-      _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
-      _rl_bind_if_unbound ("\033OB", rl_get_next_history);
-      _rl_bind_if_unbound ("\033OC", rl_forward);
-      _rl_bind_if_unbound ("\033OD", rl_backward);
-    }
+  rl_tty_set_default_bindings (_rl_keymap);
 }
 
 }
 
-/* Try and bind the common arrow key prefix after giving termcap and
-   the inputrc file a chance to bind them and create `real' keymaps
-   for the arrow key prefix. */
+/* Bind some common arrow key sequences in MAP. */
 static void
 static void
-bind_arrow_keys ()
+bind_arrow_keys_internal (map)
+     Keymap map;
 {
   Keymap xkeymap;
 
   xkeymap = _rl_keymap;
 {
   Keymap xkeymap;
 
   xkeymap = _rl_keymap;
+  _rl_keymap = map;
 
 
-  _rl_keymap = emacs_standard_keymap;
-  bind_arrow_keys_internal ();
-
-#if defined (VI_MODE)
-  _rl_keymap = vi_movement_keymap;
-  bind_arrow_keys_internal ();
+#if defined (__MSDOS__)
+   _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
+   _rl_bind_if_unbound ("\033[0B", rl_backward_char);
+   _rl_bind_if_unbound ("\033[0C", rl_forward_char);
+   _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
 #endif
 
 #endif
 
-  _rl_keymap = xkeymap;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Numeric Arguments                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Handle C-u style numeric args, as well as M--, and M-digits. */
-static int
-rl_digit_loop ()
-{
-  int key, c, sawminus, sawdigits;
-
-  _rl_save_prompt ();
-
-  sawminus = sawdigits = 0;
-  while (1)
-    {
-      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
-      key = c = rl_read_key ();
-
-      /* If we see a key bound to `universal-argument' after seeing digits,
-        it ends the argument but is otherwise ignored. */
-      if (_rl_keymap[c].type == ISFUNC &&
-         _rl_keymap[c].function == rl_universal_argument)
-       {
-         if (sawdigits == 0)
-           {
-             rl_numeric_arg *= 4;
-             continue;
-           }
-         else
-           {
-             key = rl_read_key ();
-             _rl_restore_prompt ();
-             rl_clear_message ();
-             return (_rl_dispatch (key, _rl_keymap));
-           }
-       }
-
-      c = UNMETA (c);
-
-      if (_rl_digit_p (c))
-       {
-         rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
-         sawdigits = rl_explicit_arg = 1;
-       }
-      else if (c == '-' && rl_explicit_arg == 0)
-       {
-         rl_numeric_arg = sawminus = 1;
-         rl_arg_sign = -1;
-       }
-      else
-       {
-         /* Make M-- command equivalent to M--1 command. */
-         if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
-           rl_explicit_arg = 1;
-         _rl_restore_prompt ();
-         rl_clear_message ();
-         return (_rl_dispatch (key, _rl_keymap));
-       }
-    }
-
-  return 0;
-}
-
-/* Add the current digit to the argument in progress. */
-int
-rl_digit_argument (ignore, key)
-     int ignore, key;
-{
-  rl_pending_input = key;
-  return (rl_digit_loop ());
-}
-
-/* What to do when you abort reading an argument. */
-int
-rl_discard_argument ()
-{
-  ding ();
-  rl_clear_message ();
-  _rl_init_argument ();
-  return 0;
-}
-
-/* Create a default argument. */
-int
-_rl_init_argument ()
-{
-  rl_numeric_arg = rl_arg_sign = 1;
-  rl_explicit_arg = 0;
-  return 0;
-}
-
-/* C-u, universal argument.  Multiply the current argument by 4.
-   Read a key.  If the key has nothing to do with arguments, then
-   dispatch on it.  If the key is the abort character then abort. */
-int
-rl_universal_argument (count, key)
-     int count, key;
-{
-  rl_numeric_arg *= 4;
-  return (rl_digit_loop ());
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Insert and Delete                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Insert a string of text into the line at point.  This is the only
-   way that you should do insertion.  rl_insert () calls this
-   function. */
-int
-rl_insert_text (string)
-     char *string;
-{
-  register int i, l = strlen (string);
-
-  if (rl_end + l >= rl_line_buffer_len)
-    rl_extend_line_buffer (rl_end + l);
-
-  for (i = rl_end; i >= rl_point; i--)
-    the_line[i + l] = the_line[i];
-  strncpy (the_line + rl_point, string, l);
-
-  /* Remember how to undo this if we aren't undoing something. */
-  if (!_rl_doing_an_undo)
-    {
-      /* If possible and desirable, concatenate the undos. */
-      if ((l == 1) &&
-         rl_undo_list &&
-         (rl_undo_list->what == UNDO_INSERT) &&
-         (rl_undo_list->end == rl_point) &&
-         (rl_undo_list->end - rl_undo_list->start < 20))
-       rl_undo_list->end++;
-      else
-       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
-    }
-  rl_point += l;
-  rl_end += l;
-  the_line[rl_end] = '\0';
-  return l;
-}
-
-/* Delete the string between FROM and TO.  FROM is
-   inclusive, TO is not. */
-int
-rl_delete_text (from, to)
-     int from, to;
-{
-  register char *text;
-  register int diff, i;
-
-  /* Fix it if the caller is confused. */
-  if (from > to)
-    SWAP (from, to);
-
-  /* fix boundaries */
-  if (to > rl_end)
-    {
-      to = rl_end;
-      if (from > to)
-        from = to;
-    }
-
-  text = rl_copy_text (from, to);
-
-  /* Some versions of strncpy() can't handle overlapping arguments. */
-  diff = to - from;
-  for (i = from; i < rl_end - diff; i++)
-    the_line[i] = the_line[i + diff];
+  _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
+  _rl_bind_if_unbound ("\033[B", rl_get_next_history);
+  _rl_bind_if_unbound ("\033[C", rl_forward_char);
+  _rl_bind_if_unbound ("\033[D", rl_backward_char);
+  _rl_bind_if_unbound ("\033[H", rl_beg_of_line);
+  _rl_bind_if_unbound ("\033[F", rl_end_of_line);
 
 
-  /* Remember how to undo this delete. */
-  if (_rl_doing_an_undo == 0)
-    rl_add_undo (UNDO_DELETE, from, to, text);
-  else
-    free (text);
+  _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
+  _rl_bind_if_unbound ("\033OB", rl_get_next_history);
+  _rl_bind_if_unbound ("\033OC", rl_forward_char);
+  _rl_bind_if_unbound ("\033OD", rl_backward_char);
+  _rl_bind_if_unbound ("\033OH", rl_beg_of_line);
+  _rl_bind_if_unbound ("\033OF", rl_end_of_line);
 
 
-  rl_end -= diff;
-  the_line[rl_end] = '\0';
-  return (diff);
+  _rl_keymap = xkeymap;
 }
 
 }
 
-/* Fix up point so that it is within the line boundaries after killing
-   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
-   boundaries also. */
-
-#define _RL_FIX_POINT(x) \
-       do { \
-       if (x > rl_end) \
-         x = rl_end; \
-       else if (x < 0) \
-         x = 0; \
-       } while (0)
-
-void
-_rl_fix_point (fix_mark_too)
-     int fix_mark_too;
+/* Try and bind the common arrow key prefixes after giving termcap and
+   the inputrc file a chance to bind them and create `real' keymaps
+   for the arrow key prefix. */
+static void
+bind_arrow_keys ()
 {
 {
-  _RL_FIX_POINT (rl_point);
-  if (fix_mark_too)
-    _RL_FIX_POINT (rl_mark);
-}
-#undef _RL_FIX_POINT
+  bind_arrow_keys_internal (emacs_standard_keymap);
 
 
-void
-_rl_replace_text (text, start, end)
-     char *text;
-     int start, end;
-{
-  rl_begin_undo_group ();
-  rl_delete_text (start, end + 1);
-  rl_point = start;
-  rl_insert_text (text);
-  rl_end_undo_group ();
+#if defined (VI_MODE)
+  bind_arrow_keys_internal (vi_movement_keymap);
+  bind_arrow_keys_internal (vi_insertion_keymap);
+#endif
 }
 
 /* **************************************************************** */
 /*                                                                 */
 }
 
 /* **************************************************************** */
 /*                                                                 */
-/*                     Readline character functions                */
+/*             Saving and Restoring Readline's state               */
 /*                                                                 */
 /* **************************************************************** */
 
 /*                                                                 */
 /* **************************************************************** */
 
-/* This is not a gap editor, just a stupid line input routine.  No hair
-   is involved in writing any of the functions, and none should be. */
-
-/* Note that:
-
-   rl_end is the place in the string that we would place '\0';
-   i.e., it is always safe to place '\0' there.
-
-   rl_point is the place in the string where the cursor is.  Sometimes
-   this is the same as rl_end.
-
-   Any command that is called interactively receives two arguments.
-   The first is a count: the numeric arg pased to this command.
-   The second is the key which invoked this command.
-*/
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Movement Commands                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Note that if you `optimize' the display for these functions, you cannot
-   use said functions in other functions which do not do optimizing display.
-   I.e., you will have to update the data base for rl_redisplay, and you
-   might as well let rl_redisplay do that job. */
-
-/* Move forward COUNT characters. */
-int
-rl_forward (count, key)
-     int count, key;
-{
-  if (count < 0)
-    rl_backward (-count, key);
-  else if (count > 0)
-    {
-      int end = rl_point + count;
-#if defined (VI_MODE)
-      int lend = rl_end - (rl_editing_mode == vi_mode);
-#else
-      int lend = rl_end;
-#endif
-
-      if (end > lend)
-       {
-         rl_point = lend;
-         ding ();
-       }
-      else
-       rl_point = end;
-    }
-  return 0;
-}
-
-/* Move backward COUNT characters. */
-int
-rl_backward (count, key)
-     int count, key;
-{
-  if (count < 0)
-    rl_forward (-count, key);
-  else if (count > 0)
-    {
-      if (rl_point < count)
-       {
-         rl_point = 0;
-         ding ();
-       }
-      else
-        rl_point -= count;
-    }
-  return 0;
-}
-
-/* Move to the beginning of the line. */
-int
-rl_beg_of_line (count, key)
-     int count, key;
-{
-  rl_point = 0;
-  return 0;
-}
-
-/* Move to the end of the line. */
 int
 int
-rl_end_of_line (count, key)
-     int count, key;
+rl_save_state (sp)
+     struct readline_state *sp;
 {
 {
-  rl_point = rl_end;
-  return 0;
-}
-
-/* Move forward a word.  We do what Emacs does. */
-int
-rl_forward_word (count, key)
-     int count, key;
-{
-  int c;
-
-  if (count < 0)
-    {
-      rl_backward_word (-count, key);
-      return 0;
-    }
+  if (sp == 0)
+    return -1;
 
 
-  while (count)
-    {
-      if (rl_point == rl_end)
-       return 0;
+  sp->point = rl_point;
+  sp->end = rl_end;
+  sp->mark = rl_mark;
+  sp->buffer = rl_line_buffer;
+  sp->buflen = rl_line_buffer_len;
+  sp->ul = rl_undo_list;
+  sp->prompt = rl_prompt;
+
+  sp->rlstate = rl_readline_state;
+  sp->done = rl_done;
+  sp->kmap = _rl_keymap;
+
+  sp->lastfunc = rl_last_func;
+  sp->insmode = rl_insert_mode;
+  sp->edmode = rl_editing_mode;
+  sp->kseqlen = rl_key_sequence_length;
+  sp->inf = rl_instream;
+  sp->outf = rl_outstream;
+  sp->pendingin = rl_pending_input;
+  sp->macro = rl_executing_macro;
+
+  sp->catchsigs = rl_catch_signals;
+  sp->catchsigwinch = rl_catch_sigwinch;
 
 
-      /* 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 = the_line[rl_point];
-      if (alphabetic (c) == 0)
-       {
-         while (++rl_point < rl_end)
-           {
-             c = the_line[rl_point];
-             if (alphabetic (c))
-               break;
-           }
-       }
-      if (rl_point == rl_end)
-       return 0;
-      while (++rl_point < rl_end)
-       {
-         c = the_line[rl_point];
-         if (alphabetic (c) == 0)
-           break;
-       }
-      --count;
-    }
-  return 0;
+  return (0);
 }
 
 }
 
-/* Move backward a word.  We do what Emacs does. */
 int
 int
-rl_backward_word (count, key)
-     int count, key;
+rl_restore_state (sp)
+     struct readline_state *sp;
 {
 {
-  int c;
-
-  if (count < 0)
-    {
-      rl_forward_word (-count, key);
-      return 0;
-    }
-
-  while (count)
-    {
-      if (!rl_point)
-       return 0;
-
-      /* Like rl_forward_word (), except that we look at the characters
-        just before point. */
-
-      c = the_line[rl_point - 1];
-      if (alphabetic (c) == 0)
-       {
-         while (--rl_point)
-           {
-             c = the_line[rl_point - 1];
-             if (alphabetic (c))
-               break;
-           }
-       }
+  if (sp == 0)
+    return -1;
 
 
-      while (rl_point)
-       {
-         c = the_line[rl_point - 1];
-         if (alphabetic (c) == 0)
-           break;
-         else
-           --rl_point;
-       }
-      --count;
-    }
-  return 0;
-}
+  rl_point = sp->point;
+  rl_end = sp->end;
+  rl_mark = sp->mark;
+  the_line = rl_line_buffer = sp->buffer;
+  rl_line_buffer_len = sp->buflen;
+  rl_undo_list = sp->ul;
+  rl_prompt = sp->prompt;
+
+  rl_readline_state = sp->rlstate;
+  rl_done = sp->done;
+  _rl_keymap = sp->kmap;
+
+  rl_last_func = sp->lastfunc;
+  rl_insert_mode = sp->insmode;
+  rl_editing_mode = sp->edmode;
+  rl_key_sequence_length = sp->kseqlen;
+  rl_instream = sp->inf;
+  rl_outstream = sp->outf;
+  rl_pending_input = sp->pendingin;
+  rl_executing_macro = sp->macro;
+
+  rl_catch_signals = sp->catchsigs;
+  rl_catch_sigwinch = sp->catchsigwinch;
 
 
-/* Clear the current line.  Numeric argument to C-l does this. */
-int
-rl_refresh_line ()
-{
-  int curr_line, nleft;
-
-  /* Find out whether or not there might be invisible characters in the
-     editing buffer. */
-  if (rl_display_prompt == rl_prompt)
-    nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
-  else
-    nleft = _rl_last_c_pos - screenwidth;
-
-  if (nleft > 0)
-    curr_line = 1 + nleft / screenwidth;
-  else
-    curr_line = 0;
-
-  _rl_move_vert (curr_line);
-  _rl_move_cursor_relative (0, the_line);   /* XXX is this right */
-
-#if defined (__GO32__)
-  {
-    int row, col, width, row_start;
-
-    ScreenGetCursor (&row, &col);
-    width = ScreenCols ();
-    row_start = ScreenPrimary + (row * width);
-    memset (row_start + col, 0, (width - col) * 2);
-  }
-#else /* !__GO32__ */
-  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
-#endif /* !__GO32__ */
-
-  rl_forced_update_display ();
-  rl_display_fixed = 1;
-
-  return 0;
-}
-
-/* C-l typed to a line without quoting clears the screen, and then reprints
-   the prompt and the current input line.  Given a numeric arg, redraw only
-   the current line. */
-int
-rl_clear_screen (count, key)
-     int count, key;
-{
-  if (rl_explicit_arg)
-    {
-      rl_refresh_line ();
-      return 0;
-    }
-
-  _rl_clear_screen ();         /* calls termcap function to clear screen */
-  rl_forced_update_display ();
-  rl_display_fixed = 1;
-
-  return 0;
-}
-
-int
-rl_arrow_keys (count, c)
-     int count, c;
-{
-  int ch;
-
-  ch = rl_read_key ();
-
-  switch (_rl_to_upper (ch))
-    {
-    case 'A':
-      rl_get_previous_history (count, ch);
-      break;
-
-    case 'B':
-      rl_get_next_history (count, ch);
-      break;
-
-    case 'C':
-      rl_forward (count, ch);
-      break;
-
-    case 'D':
-      rl_backward (count, ch);
-      break;
-
-    default:
-      ding ();
-    }
-  return 0;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Text commands                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Insert the character C at the current location, moving point forward. */
-int
-rl_insert (count, c)
-     int count, c;
-{
-  register int i;
-  char *string;
-
-  if (count <= 0)
-    return 0;
-
-  /* If we can optimize, then do it.  But don't let people crash
-     readline because of extra large arguments. */
-  if (count > 1 && count <= 1024)
-    {
-      string = xmalloc (1 + count);
-
-      for (i = 0; i < count; i++)
-       string[i] = c;
-
-      string[i] = '\0';
-      rl_insert_text (string);
-      free (string);
-
-      return 0;
-    }
-
-  if (count > 1024)
-    {
-      int decreaser;
-      char str[1024+1];
-
-      for (i = 0; i < 1024; i++)
-       str[i] = c;
-
-      while (count)
-       {
-         decreaser = (count > 1024 ? 1024 : count);
-         str[decreaser] = '\0';
-         rl_insert_text (str);
-         count -= decreaser;
-       }
-
-      return 0;
-    }
-
-  /* We are inserting a single character.
-     If there is pending input, then make a string of all of the
-     pending characters that are bound to rl_insert, and insert
-     them all. */
-  if (_rl_any_typein ())
-    _rl_insert_typein (c);
-  else
-    {
-      /* Inserting a single character. */
-      char str[2];
-
-      str[1] = '\0';
-      str[0] = c;
-      rl_insert_text (str);
-    }
-  return 0;
-}
-
-/* Insert the next typed character verbatim. */
-int
-rl_quoted_insert (count, key)
-     int count, key;
-{
-  int c;
-
-  c = rl_read_key ();
-  return (rl_insert (count, c));  
-}
-
-/* Insert a tab character. */
-int
-rl_tab_insert (count, key)
-     int count, key;
-{
-  return (rl_insert (count, '\t'));
-}
-
-/* What to do when a NEWLINE is pressed.  We accept the whole line.
-   KEY is the key that invoked this command.  I guess it could have
-   meaning in the future. */
-int
-rl_newline (count, key)
-     int count, key;
-{
-  rl_done = 1;
-
-#if defined (VI_MODE)
-  if (rl_editing_mode == vi_mode)
-    {
-      _rl_vi_done_inserting ();
-      _rl_vi_reset_last ();
-    }
-#endif /* VI_MODE */
-
-  if (readline_echoing_p)
-    _rl_update_final ();
-  return 0;
-}
-
-/* What to do for some uppercase characters, like meta characters,
-   and some characters appearing in emacs_ctlx_keymap.  This function
-   is just a stub, you bind keys to it and the code in _rl_dispatch ()
-   is special cased. */
-int
-rl_do_lowercase_version (ignore1, ignore2)
-     int ignore1, ignore2;
-{
-  return 0;
-}
-
-/* Rubout the character behind point. */
-int
-rl_rubout (count, key)
-     int count, key;
-{
-  if (count < 0)
-    {
-      rl_delete (-count, key);
-      return 0;
-    }
-
-  if (!rl_point)
-    {
-      ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_backward (count, key);
-      rl_kill_text (orig_point, rl_point);
-    }
-  else
-    {
-      int c = the_line[--rl_point];
-      rl_delete_text (rl_point, rl_point + 1);
-
-      if (rl_point == rl_end && isprint (c) && _rl_last_c_pos)
-       {
-         int l;
-         l = rl_character_len (c, rl_point);
-         _rl_erase_at_end_of_line (l);
-       }
-    }
-  return 0;
-}
-
-/* Delete the character under the cursor.  Given a numeric argument,
-   kill that many characters instead. */
-int
-rl_delete (count, key)
-     int count, key;
-{
-  if (count < 0)
-    return (rl_rubout (-count, key));
-
-  if (rl_point == rl_end)
-    {
-      ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_forward (count, key);
-      rl_kill_text (orig_point, rl_point);
-      rl_point = orig_point;
-      return 0;
-    }
-  else
-    return (rl_delete_text (rl_point, rl_point + 1));
-  
-}
-
-/* Delete all spaces and tabs around point. */
-int
-rl_delete_horizontal_space (count, ignore)
-     int count, ignore;
-{
-  int start = rl_point;
-
-  while (rl_point && whitespace (the_line[rl_point - 1]))
-    rl_point--;
-
-  start = rl_point;
-
-  while (rl_point < rl_end && whitespace (the_line[rl_point]))
-    rl_point++;
-
-  if (start != rl_point)
-    {
-      rl_delete_text (start, rl_point);
-      rl_point = start;
-    }
-  return 0;
-}
-
-#ifndef RL_COMMENT_BEGIN_DEFAULT
-#define RL_COMMENT_BEGIN_DEFAULT "#"
-#endif
-
-/* Turn the current line into a comment in shell history.
-   A K*rn shell style function. */
-int
-rl_insert_comment (count, key)
-     int count, key;
-{
-  rl_beg_of_line (1, key);
-  rl_insert_text (_rl_comment_begin ? _rl_comment_begin
-                                   : RL_COMMENT_BEGIN_DEFAULT);
-  (*rl_redisplay_function) ();
-  rl_newline (1, '\n');
-  return (0);
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Changing Case                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* The three kinds of things that we know how to do. */
-#define UpCase 1
-#define DownCase 2
-#define CapCase 3
-
-static int rl_change_case ();
-
-/* Uppercase the word at point. */
-int
-rl_upcase_word (count, key)
-     int count, key;
-{
-  return (rl_change_case (count, UpCase));
-}
-
-/* Lowercase the word at point. */
-int
-rl_downcase_word (count, key)
-     int count, key;
-{
-  return (rl_change_case (count, DownCase));
-}
-
-/* Upcase the first letter, downcase the rest. */
-int
-rl_capitalize_word (count, key)
-     int count, key;
-{
- return (rl_change_case (count, CapCase));
-}
-
-/* The meaty function.
-   Change the case of COUNT words, performing OP on them.
-   OP is one of UpCase, DownCase, or CapCase.
-   If a negative argument is given, leave point where it started,
-   otherwise, leave it where it moves to. */
-static int
-rl_change_case (count, op)
-     int count, op;
-{
-  register int start, end;
-  int inword, c;
-
-  start = rl_point;
-  rl_forward_word (count, 0);
-  end = rl_point;
-
-  if (count < 0)
-    SWAP (start, end);
-
-  /* We are going to modify some text, so let's prepare to undo it. */
-  rl_modifying (start, end);
-
-  for (inword = 0; start < end; start++)
-    {
-      c = the_line[start];
-      switch (op)
-       {
-       case UpCase:
-         the_line[start] = _rl_to_upper (c);
-         break;
-
-       case DownCase:
-         the_line[start] = _rl_to_lower (c);
-         break;
-
-       case CapCase:
-         the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
-         inword = alphabetic (the_line[start]);
-         break;
-
-       default:
-         ding ();
-         return -1;
-       }
-    }
-  rl_point = end;
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Transposition                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Transpose the words at point. */
-int
-rl_transpose_words (count, key)
-     int count, key;
-{
-  char *word1, *word2;
-  int w1_beg, w1_end, w2_beg, w2_end;
-  int orig_point = rl_point;
-
-  if (!count)
-    return 0;
-
-  /* Find the two words. */
-  rl_forward_word (count, key);
-  w2_end = rl_point;
-  rl_backward_word (1, key);
-  w2_beg = rl_point;
-  rl_backward_word (count, key);
-  w1_beg = rl_point;
-  rl_forward_word (1, key);
-  w1_end = rl_point;
-
-  /* Do some check to make sure that there really are two words. */
-  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
-    {
-      ding ();
-      rl_point = orig_point;
-      return -1;
-    }
-
-  /* Get the text of the words. */
-  word1 = rl_copy_text (w1_beg, w1_end);
-  word2 = rl_copy_text (w2_beg, w2_end);
-
-  /* We are about to do many insertions and deletions.  Remember them
-     as one operation. */
-  rl_begin_undo_group ();
-
-  /* Do the stuff at word2 first, so that we don't have to worry
-     about word1 moving. */
-  rl_point = w2_beg;
-  rl_delete_text (w2_beg, w2_end);
-  rl_insert_text (word1);
-
-  rl_point = w1_beg;
-  rl_delete_text (w1_beg, w1_end);
-  rl_insert_text (word2);
-
-  /* This is exactly correct since the text before this point has not
-     changed in length. */
-  rl_point = w2_end;
-
-  /* I think that does it. */
-  rl_end_undo_group ();
-  free (word1);
-  free (word2);
-
-  return 0;
-}
-
-/* Transpose the characters at point.  If point is at the end of the line,
-   then transpose the characters before point. */
-int
-rl_transpose_chars (count, key)
-     int count, key;
-{
-  char dummy[2];
-
-  if (!count)
-    return 0;
-
-  if (!rl_point || rl_end < 2)
-    {
-      ding ();
-      return -1;
-    }
-
-  rl_begin_undo_group ();
-
-  if (rl_point == rl_end)
-    {
-      --rl_point;
-      count = 1;
-    }
-  rl_point--;
-
-  dummy[0] = the_line[rl_point];
-  dummy[1] = '\0';
-
-  rl_delete_text (rl_point, rl_point + 1);
-
-  rl_point += count;
-  _rl_fix_point (0);
-  rl_insert_text (dummy);
-
-  rl_end_undo_group ();
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Character Searching                         */
-/*                                                                 */
-/* **************************************************************** */
-
-int
-_rl_char_search_internal (count, dir, schar)
-     int count, dir, schar;
-{
-  int pos, inc;
-
-  pos = rl_point;
-  inc = (dir < 0) ? -1 : 1;
-  while (count)
-    {
-      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
-       {
-         ding ();
-         return -1;
-       }
-
-      pos += inc;
-      do
-       {
-         if (rl_line_buffer[pos] == schar)
-           {
-             count--;
-             if (dir < 0)
-               rl_point = (dir == BTO) ? pos + 1 : pos;
-             else
-               rl_point = (dir == FTO) ? pos - 1 : pos;
-             break;
-           }
-       }
-      while ((dir < 0) ? pos-- : ++pos < rl_end);
-    }
   return (0);
 }
   return (0);
 }
-
-/* Search COUNT times for a character read from the current input stream.
-   FDIR is the direction to search if COUNT is non-negative; otherwise
-   the search goes in BDIR. */
-static int
-_rl_char_search (count, fdir, bdir)
-     int count, fdir, bdir;
-{
-  int c;
-
-  c = rl_read_key ();
-  if (count < 0)
-    return (_rl_char_search_internal (-count, bdir, c));
-  else
-    return (_rl_char_search_internal (count, fdir, c));
-}
-
-int
-rl_char_search (count, key)
-     int count, key;
-{
-  return (_rl_char_search (count, FFIND, BFIND));
-}
-
-int
-rl_backward_char_search (count, key)
-     int count, key;
-{
-  return (_rl_char_search (count, BFIND, FFIND));
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     History Utilities                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* We already have a history library, and that is what we use to control
-   the history features of readline.  This is our local interface to
-   the history mechanism. */
-
-/* While we are editing the history, this is the saved
-   version of the original line. */
-HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
-
-/* Set the history pointer back to the last entry in the history. */
-static void
-start_using_history ()
-{
-  using_history ();
-  if (saved_line_for_history)
-    _rl_free_history_entry (saved_line_for_history);
-
-  saved_line_for_history = (HIST_ENTRY *)NULL;
-}
-
-/* Free the contents (and containing structure) of a HIST_ENTRY. */
-void
-_rl_free_history_entry (entry)
-     HIST_ENTRY *entry;
-{
-  if (entry == 0)
-    return;
-  if (entry->line)
-    free (entry->line);
-  free (entry);
-}
-
-/* Perhaps put back the current line if it has changed. */
-int
-maybe_replace_line ()
-{
-  HIST_ENTRY *temp;
-
-  temp = current_history ();
-  /* If the current line has changed, save the changes. */
-  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
-    {
-      temp = replace_history_entry (where_history (), the_line, rl_undo_list);
-      free (temp->line);
-      free (temp);
-    }
-  return 0;
-}
-
-/* Put back the saved_line_for_history if there is one. */
-int
-maybe_unsave_line ()
-{
-  int line_len;
-
-  if (saved_line_for_history)
-    {
-      line_len = strlen (saved_line_for_history->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, saved_line_for_history->line);
-      rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
-      _rl_free_history_entry (saved_line_for_history);
-      saved_line_for_history = (HIST_ENTRY *)NULL;
-      rl_end = rl_point = strlen (the_line);
-    }
-  else
-    ding ();
-  return 0;
-}
-
-/* Save the current line in saved_line_for_history. */
-int
-maybe_save_line ()
-{
-  if (saved_line_for_history == 0)
-    {
-      saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
-      saved_line_for_history->line = savestring (the_line);
-      saved_line_for_history->data = (char *)rl_undo_list;
-    }
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     History Commands                            */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Meta-< goes to the start of the history. */
-int
-rl_beginning_of_history (count, key)
-     int count, key;
-{
-  return (rl_get_previous_history (1 + where_history (), key));
-}
-
-/* Meta-> goes to the end of the history.  (The current line). */
-int
-rl_end_of_history (count, key)
-     int count, key;
-{
-  maybe_replace_line ();
-  using_history ();
-  maybe_unsave_line ();
-  return 0;
-}
-
-/* Move down to the next history line. */
-int
-rl_get_next_history (count, key)
-     int count, key;
-{
-  HIST_ENTRY *temp;
-  int line_len;
-
-  if (count < 0)
-    return (rl_get_previous_history (-count, key));
-
-  if (count == 0)
-    return 0;
-
-  maybe_replace_line ();
-
-  temp = (HIST_ENTRY *)NULL;
-  while (count)
-    {
-      temp = next_history ();
-      if (!temp)
-       break;
-      --count;
-    }
-
-  if (temp == 0)
-    maybe_unsave_line ();
-  else
-    {
-      line_len = strlen (temp->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, temp->line);
-      rl_undo_list = (UNDO_LIST *)temp->data;
-      rl_end = rl_point = strlen (the_line);
-#if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_point = 0;
-#endif /* VI_MODE */
-    }
-  return 0;
-}
-
-/* Get the previous item out of our interactive history, making it the current
-   line.  If there is no previous history, just ding. */
-int
-rl_get_previous_history (count, key)
-     int count, key;
-{
-  HIST_ENTRY *old_temp, *temp;
-  int line_len;
-
-  if (count < 0)
-    return (rl_get_next_history (-count, key));
-
-  if (count == 0)
-    return 0;
-
-  /* If we don't have a line saved, then save this one. */
-  maybe_save_line ();
-
-  /* If the current line has changed, save the changes. */
-  maybe_replace_line ();
-
-  temp = old_temp = (HIST_ENTRY *)NULL;
-  while (count)
-    {
-      temp = previous_history ();
-      if (temp == 0)
-       break;
-
-      old_temp = temp;
-      --count;
-    }
-
-  /* If there was a large argument, and we moved back to the start of the
-     history, that is not an error.  So use the last value found. */
-  if (!temp && old_temp)
-    temp = old_temp;
-
-  if (temp == 0)
-    ding ();
-  else
-    {
-      line_len = strlen (temp->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, temp->line);
-      rl_undo_list = (UNDO_LIST *)temp->data;
-      rl_end = rl_point = line_len;
-
-#if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_point = 0;
-#endif /* VI_MODE */
-    }
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                The Mark and the Region.                         */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Set the mark at POSITION. */
-int
-_rl_set_mark_at_pos (position)
-     int position;
-{
-  if (position > rl_end)
-    return -1;
-
-  rl_mark = position;
-  return 0;
-}
-
-/* A bindable command to set the mark. */
-int
-rl_set_mark (count, key)
-     int count, key;
-{
-  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
-}
-
-/* Exchange the position of mark and point. */
-int
-rl_exchange_point_and_mark (count, key)
-     int count, key;
-{
-  if (rl_mark > rl_end)
-    rl_mark = -1;
-
-  if (rl_mark == -1)
-    {
-      ding ();
-      return -1;
-    }
-  else
-    SWAP (rl_point, rl_mark);
-
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                         Editing Modes                           */
-/*                                                                 */
-/* **************************************************************** */
-/* How to toggle back and forth between editing modes. */
-int
-rl_vi_editing_mode (count, key)
-     int count, key;
-{
-#if defined (VI_MODE)
-  rl_editing_mode = vi_mode;
-  rl_vi_insertion_mode (1, key);
-#endif /* VI_MODE */
-  return 0;
-}
-
-int
-rl_emacs_editing_mode (count, key)
-     int count, key;
-{
-  rl_editing_mode = emacs_mode;
-  _rl_keymap = emacs_standard_keymap;
-  return 0;
-}