]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - lib/readline/readline.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / readline.c
index 6040cbb42f6e823c1f67b1a59946dd634eec8236..9d7cc5bf7df830564f916a60a925fdcf3547db66 100644 (file)
@@ -8,7 +8,7 @@
 
    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
    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
 
-#include <stdio.h>
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
 #include <sys/types.h>
+#include "posixstat.h"
 #include <fcntl.h>
-#if !defined (NO_SYS_FILE)
+#if defined (HAVE_SYS_FILE_H)
 #  include <sys/file.h>
-#endif /* !NO_SYS_FILE */
-#include <signal.h>
+#endif /* HAVE_SYS_FILE_H */
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #  include "ansi_stdlib.h"
 #endif /* HAVE_STDLIB_H */
 
-#include <errno.h>
-/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include <setjmp.h>
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
 
-#include "posixstat.h"
+#include <stdio.h>
+#include "posixjmp.h"
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
 
-#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4))
-#  include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS */
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
 
 /* Some standard library routines. */
 #include "readline.h"
 #include "history.h"
 
-/* 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. */
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
 
-/* Functions imported from other files in the library. */
-extern char *tgetstr ();
-extern void rl_prep_terminal (), rl_deprep_terminal ();
-
-extern void _rl_bind_if_unbound ();
-
-/* External redisplay functions and variables from display.c */
-extern void _rl_move_vert ();
-extern void _rl_update_final ();
-
-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 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;
+#ifndef RL_LIBRARY_VERSION
+#  define RL_LIBRARY_VERSION "4.2"
+#endif
 
-#if defined (VI_MODE)
-extern void _rl_vi_set_last ();
-extern void _rl_vi_reset_last ();
-extern void _rl_vi_done_inserting ();
-#endif /* VI_MODE */
+/* Evaluates its arguments multiple times. */
+#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
 
 /* Forward declarations used in this file. */
-void _rl_free_history_entry ();
+void _rl_free_history_entry __P((HIST_ENTRY *));
 
-int _rl_dispatch ();
-void _rl_set_screen_size ();
-int _rl_output_character_function ();
+static char *readline_internal __P((void));
+static void readline_initialize_everything __P((void));
+static void start_using_history __P((void));
+static void bind_arrow_keys __P((void));
+static int rl_change_case __P((int, int));
 
-static char *readline_internal ();
-static void readline_initialize_everything ();
-static int init_terminal_io ();
-static void start_using_history ();
-static void bind_arrow_keys ();
+static void readline_default_bindings __P((void));
 
-#if !defined (__GO32__)
-static void readline_default_bindings ();
-#endif /* !__GO32__ */
-
-#if defined (__GO32__)
-#  include <sys/pc.h>
-#  undef HANDLE_SIGNALS
-#endif /* __GO32__ */
-
-#if defined (STATIC_MALLOC)
-static char *xmalloc (), *xrealloc ();
-#else
-extern char *xmalloc (), *xrealloc ();
-#endif /* STATIC_MALLOC */
-
-\f
 /* **************************************************************** */
 /*                                                                 */
 /*                     Line editing input utility                  */
 /*                                                                 */
 /* **************************************************************** */
 
-static char *LibraryVersion = "2.0";
+const char *rl_library_version = RL_LIBRARY_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. */
@@ -141,8 +102,13 @@ Keymap _rl_keymap = emacs_standard_keymap;
 /* The current style of editing. */
 int rl_editing_mode = emacs_mode;
 
+/* 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. */
+int rl_dispatching;
+
 /* Non-zero if the previous command was a kill command. */
-static int last_command_was_kill = 0;
+int _rl_last_command_was_kill = 0;
 
 /* The current value of the numeric argument specified by the user. */
 int rl_numeric_arg = 1;
@@ -154,10 +120,15 @@ int rl_explicit_arg = 0;
 int rl_arg_sign = 1;
 
 /* Non-zero means we have been called at least once before. */
-static int rl_initialized = 0;
+static int rl_initialized;
 
+#if 0
 /* If non-zero, this program is running in an EMACS buffer. */
-static int running_in_emacs = 0;
+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;
@@ -172,13 +143,13 @@ int rl_end;
 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 (). */
-static jmp_buf readline_top_level;
+procenv_t readline_top_level;
 
 /* The streams we interact with. */
-static FILE *in_stream, *out_stream;
+FILE *_rl_in_stream, *_rl_out_stream;
 
 /* The names of the streams that we do input and output to. */
 FILE *rl_instream = (FILE *)NULL;
@@ -188,15 +159,24 @@ FILE *rl_outstream = (FILE *)NULL;
 int readline_echoing_p = 1;
 
 /* Current prompt. */
-char *rl_prompt;
+char *rl_prompt = (char *)NULL;
 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
-   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;
@@ -209,7 +189,7 @@ int _rl_eof_char = CTRL ('D');
 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;
@@ -222,16 +202,25 @@ int _rl_mark_modified_lines = 0;
    AUDIBLE_BELL, or VISIBLE_BELL. */
 int _rl_bell_preference = AUDIBLE_BELL;
      
+/* String inserted into the line by rl_insert_comment (). */
+char *_rl_comment_begin;
+
+/* 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;
-#define DEFAULT_BUFFER_SIZE 256
 
 /* Forward declarations used by the display and termcap code. */
-int term_xn;
-int screenwidth, screenheight, screenchars;
 
-\f
 /* **************************************************************** */
 /*                                                                 */
 /*                     `Forward' declarations                      */
@@ -242,9 +231,6 @@ int screenwidth, screenheight, screenchars;
    parser directives. */
 unsigned char _rl_parsing_conditionalized_out = 0;
 
-/* Non-zero means to save keys that we dispatch on in a kbd macro. */
-static int defining_kbd_macro = 0;
-
 /* Non-zero means to convert characters with the meta bit set to
    escape-prefixed characters so we can indirect through
    emacs_meta_keymap or vi_escape_keymap. */
@@ -254,10 +240,6 @@ int _rl_convert_meta_chars_to_ascii = 1;
    rather than as a meta-prefixed escape sequence. */
 int _rl_output_meta_chars = 0;
 
-/* Non-zero tells rl_delete_text and rl_insert_text to not add to
-   the undo list. */
-static int doing_an_undo = 0;
-\f
 /* **************************************************************** */
 /*                                                                 */
 /*                     Top Level Functions                         */
@@ -267,34 +249,47 @@ static int doing_an_undo = 0;
 /* Non-zero means treat 0200 bit in terminal input as Meta bit. */
 int _rl_meta_flag = 0; /* Forward declaration */
 
-/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means
+/* 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_prompt && *rl_prompt)
+                               ? rl_expand_prompt (rl_prompt)
+                               : 0;
+  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)
-     char *prompt;
+     const char *prompt;
 {
   char *value;
 
-  rl_prompt = prompt;
-
   /* 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);
     }
 
-  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+  rl_set_prompt (prompt);
 
   rl_initialize ();
-  rl_prep_terminal (_rl_meta_flag);
+  (*rl_prep_term_function) (_rl_meta_flag);
 
 #if defined (HANDLE_SIGNALS)
   rl_set_signals ();
 #endif
 
   value = readline_internal ();
-  rl_deprep_terminal ();
+  (*rl_deprep_term_function) ();
 
 #if defined (HANDLE_SIGNALS)
   rl_clear_signals ();
@@ -303,59 +298,114 @@ readline (prompt)
   return (value);
 }
 
-/* Read a line of input from the global rl_instream, doing output on
-   the global rl_outstream.
-   If rl_prompt is non-null, then that is our prompt. */
-static char *
-readline_internal ()
-{
-  int lastc, c, eof_found;
+#if defined (READLINE_CALLBACKS)
+#  define STATIC_CALLBACK
+#else
+#  define STATIC_CALLBACK static
+#endif
 
-  in_stream  = rl_instream;
-  out_stream = rl_outstream;
+STATIC_CALLBACK void
+readline_internal_setup ()
+{
+  char *nprompt;
 
-  lastc = -1;
-  eof_found = 0;
+  _rl_in_stream = rl_instream;
+  _rl_out_stream = rl_outstream;
 
   if (rl_startup_hook)
     (*rl_startup_hook) ();
 
-  if (!readline_echoing_p)
+  if (readline_echoing_p == 0)
     {
-      if (rl_prompt)
+      if (rl_prompt && rl_already_prompted == 0)
        {
-         fprintf (out_stream, "%s", rl_prompt);
-         fflush (out_stream);
+         nprompt = _rl_strip_prompt (rl_prompt);
+         fprintf (_rl_out_stream, "%s", nprompt);
+         fflush (_rl_out_stream);
+         free (nprompt);
        }
     }
   else
     {
-      rl_on_new_line ();
-      rl_redisplay ();
+      if (rl_prompt && rl_already_prompted)
+       rl_on_new_line_with_prompt ();
+      else
+       rl_on_new_line ();
+      (*rl_redisplay_function) ();
 #if defined (VI_MODE)
       if (rl_editing_mode == vi_mode)
-       rl_vi_insertion_mode ();
+       rl_vi_insertion_mode (1, 0);
 #endif /* VI_MODE */
     }
 
-  while (!rl_done)
+  if (rl_pre_input_hook)
+    (*rl_pre_input_hook) ();
+}
+
+STATIC_CALLBACK char *
+readline_internal_teardown (eof)
+     int eof;
+{
+  char *temp;
+  HIST_ENTRY *entry;
+
+  /* Restore the original of this history line, iff the line that we
+     are editing was originally in the history, AND the line has changed. */
+  entry = current_history ();
+
+  if (entry && rl_undo_list)
+    {
+      temp = savestring (the_line);
+      rl_revert_line (1, 0);
+      entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
+      _rl_free_history_entry (entry);
+
+      strcpy (the_line, temp);
+      free (temp);
+    }
+
+  /* At any rate, it is highly likely that this line has an undo list.  Get
+     rid of it now. */
+  if (rl_undo_list)
+    rl_free_undo_list ();
+
+  return (eof ? (char *)NULL : savestring (the_line));
+}
+
+STATIC_CALLBACK int
+#if defined (READLINE_CALLBACKS)
+readline_internal_char ()
+#else
+readline_internal_charloop ()
+#endif
+{
+  static int lastc, eof_found;
+  int c, code, lk;
+
+  lastc = -1;
+  eof_found = 0;
+
+#if !defined (READLINE_CALLBACKS)
+  while (rl_done == 0)
     {
-      int lk = last_command_was_kill;
-      int code;
+#endif
+      lk = _rl_last_command_was_kill;
 
       code = setjmp (readline_top_level);
 
       if (code)
-       rl_redisplay ();
+       (*rl_redisplay_function) ();
 
-      if (!rl_pending_input)
+      if (rl_pending_input == 0)
        {
          /* Then initialize the argument and number of keys read. */
-         rl_init_argument ();
+         _rl_init_argument ();
          rl_key_sequence_length = 0;
        }
 
+      RL_SETSTATE(RL_STATE_READCMD);
       c = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_READCMD);
 
       /* EOF typed to a non-blank line is a <NL>. */
       if (c == EOF && rl_end)
@@ -365,21 +415,23 @@ readline_internal ()
         previous character is interpreted as EOF. */
       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;
          break;
+#endif
        }
 
       lastc = c;
-      _rl_dispatch (c, _rl_keymap);
+      _rl_dispatch ((unsigned char)c, _rl_keymap);
 
-      /* If there was no change in last_command_was_kill, then no kill
+      /* 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
         a prefix command, so nothing has changed yet. */
-      if (!rl_pending_input)
-       {
-         if (lk == last_command_was_kill)
-           last_command_was_kill = 0;
-       }
+      if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
+       _rl_last_command_was_kill = 0;
 
 #if defined (VI_MODE)
       /* In vi mode, when you exit insert mode, the cursor moves back
@@ -388,232 +440,69 @@ readline_internal ()
        rl_vi_check ();
 #endif /* VI_MODE */
 
-      if (!rl_done)
-       rl_redisplay ();
-    }
-
-  /* Restore the original of this history line, iff the line that we
-     are editing was originally in the history, AND the line has changed. */
-  {
-    HIST_ENTRY *entry = current_history ();
-
-    if (entry && rl_undo_list)
-      {
-       char *temp = savestring (the_line);
-       rl_revert_line ();
-       entry = replace_history_entry (where_history (), the_line,
-                                      (HIST_ENTRY *)NULL);
-       _rl_free_history_entry (entry);
-
-       strcpy (the_line, temp);
-       free (temp);
-      }
-  }
-
-  /* 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 ();
-
-  if (eof_found)
-    return (char *)NULL;
-  else
-    return (savestring (the_line));
-}
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Character Input Buffering                   */
-/*                                                                 */
-/* **************************************************************** */
-
-static int pop_index = 0, push_index = 0, ibuffer_len = 511;
-static unsigned char ibuffer[512];
+      if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
+        {
+          (*rl_redisplay_function) ();
+          rl_newline (1, '\n');
+        }
 
-/* Non-null means it is a pointer to a function to run while waiting for
-   character input. */
-Function *rl_event_hook = (Function *)NULL;
+      if (rl_done == 0)
+       (*rl_redisplay_function) ();
 
-#define any_typein (push_index != pop_index)
+      /* 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 ();
 
-/* Add KEY to the buffer of characters to be read. */
-rl_stuff_char (key)
-     int key;
-{
-  if (key == EOF)
-    {
-      key = NEWLINE;
-      rl_pending_input = EOF;
+#if defined (READLINE_CALLBACKS)
+      return 0;
+#else
     }
-  ibuffer[push_index++] = key;
-  if (push_index >= ibuffer_len)
-    push_index = 0;
-  return push_index;
-}
 
-/* Return the amount of space available in the
-   buffer for stuffing characters. */
-int
-ibuffer_space ()
-{
-  if (pop_index > push_index)
-    return (pop_index - push_index);
-  else
-    return (ibuffer_len - (push_index - pop_index));
+  return (eof_found);
+#endif
 }
 
-/* Get a key from the buffer of characters to be read.
-   Return the key in KEY.
-   Result is KEY if there was a key, or 0 if there wasn't. */
-int
-rl_get_char (key)
-     int *key;
+#if defined (READLINE_CALLBACKS)
+static int
+readline_internal_charloop ()
 {
-  if (push_index == pop_index)
-    return (0);
-
-  *key = ibuffer[pop_index++];
-
-  if (pop_index >= ibuffer_len)
-    pop_index = 0;
+  int eof = 1;
 
-  return (1);
+  while (rl_done == 0)
+    eof = readline_internal_char ();
+  return (eof);
 }
+#endif /* READLINE_CALLBACKS */
 
-/* Stuff KEY into the *front* of the input buffer.
-   Returns non-zero if successful, zero if there is
-   no space left in the buffer. */
-int
-rl_unget_char (key)
-     int key;
+/* Read a line of input from the global rl_instream, doing output on
+   the global rl_outstream.
+   If rl_prompt is non-null, then that is our prompt. */
+static char *
+readline_internal ()
 {
-  if (ibuffer_space ())
-    {
-      pop_index--;
-      if (pop_index < 0)
-       pop_index = ibuffer_len - 1;
-      ibuffer[pop_index] = key;
-      return (1);
-    }
-  return (0);
+  int eof;
+
+  readline_internal_setup ();
+  eof = readline_internal_charloop ();
+  return (readline_internal_teardown (eof));
 }
 
-/* If a character is available to be read, then read it
-   and stuff it into IBUFFER.  Otherwise, just return. */
 void
-rl_gather_tyi ()
+_rl_init_line_state ()
 {
-#if defined (__GO32__)
-  char input;
-
-  if (isatty (0))
-    {
-      int i = rl_getc ();
-
-      if (i != EOF)
-       rl_stuff_char (i);
-    }
-  else if (kbhit () && ibuffer_space ())
-    rl_stuff_char (getkey ());
-#else /* !__GO32__ */
-
-  int tty = fileno (in_stream);
-  register int tem, result = -1;
-  int chars_avail;
-  char input;
-
-#if defined (FIONREAD)
-  result = ioctl (tty, FIONREAD, &chars_avail);
-#endif
-
-#if defined (O_NDELAY)
-  if (result == -1)
-    {
-      int flags;
-
-      flags = fcntl (tty, F_GETFL, 0);
-
-      fcntl (tty, F_SETFL, (flags | O_NDELAY));
-      chars_avail = read (tty, &input, 1);
-
-      fcntl (tty, F_SETFL, flags);
-      if (chars_avail == -1 && errno == EAGAIN)
-       return;
-    }
-#endif /* O_NDELAY */
-
-  /* If there's nothing available, don't waste time trying to read
-     something. */
-  if (chars_avail == 0)
-    return;
-
-  tem = ibuffer_space ();
-
-  if (chars_avail > tem)
-    chars_avail = tem;
-
-  /* One cannot read all of the available input.  I can only read a single
-     character at a time, or else programs which require input can be
-     thwarted.  If the buffer is larger than one character, I lose.
-     Damn! */
-  if (tem < ibuffer_len)
-    chars_avail = 0;
-
-  if (result != -1)
-    {
-      while (chars_avail--)
-       rl_stuff_char (rl_getc (in_stream));
-    }
-  else
-    {
-      if (chars_avail)
-       rl_stuff_char (input);
-    }
-#endif /* !__GO32__ */
+  rl_point = rl_end = 0;
+  the_line = rl_line_buffer;
+  the_line[0] = 0;
 }
 
-static int next_macro_key ();
-/* Read a key, including pending input. */
-int
-rl_read_key ()
+void
+_rl_set_the_line ()
 {
-  int c;
-
-  rl_key_sequence_length++;
-
-  if (rl_pending_input)
-    {
-      c = rl_pending_input;
-      rl_pending_input = 0;
-    }
-  else
-    {
-      /* If input is coming from a macro, then use that. */
-      if (c = next_macro_key ())
-       return (c);
-
-      /* If the user has an event function, then call it periodically. */
-      if (rl_event_hook)
-       {
-         while (rl_event_hook && !rl_get_char (&c))
-           {
-             (*rl_event_hook) ();
-             rl_gather_tyi ();
-           }
-       }
-      else
-       {
-         if (!rl_get_char (&c))
-           c = rl_getc (in_stream);
-       }
-    }
-
-  return (c);
+  the_line = rl_line_buffer;
 }
 
-/* Found later in this file. */
-static void add_macro_char (), with_macro_input ();
-
 /* Do the command associated with KEY in MAP.
    If the associated command is really a keymap, then read
    another key, and dispatch into that map. */
@@ -622,393 +511,233 @@ _rl_dispatch (key, map)
      register int key;
      Keymap map;
 {
-  int r = 0;
+  int r, newkey;
+  char *macro;
+  rl_command_func_t *func;
 
   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
     {
       if (map[ESC].type == ISKMAP)
        {
-         if (defining_kbd_macro)
-           add_macro_char (ESC);
+         if (_rl_defining_kbd_macro)
+           _rl_add_macro_char (ESC);
          map = FUNCTION_TO_KEYMAP (map, ESC);
          key = UNMETA (key);
          rl_key_sequence_length += 2;
          return (_rl_dispatch (key, map));
        }
       else
-       ding ();
+       rl_ding ();
       return 0;
     }
 
-  if (defining_kbd_macro)
-    add_macro_char (key);
+  if (_rl_defining_kbd_macro)
+    _rl_add_macro_char (key);
 
+  r = 0;
   switch (map[key].type)
     {
     case ISFUNC:
-      {
-       Function *func = map[key].function;
-
-       if (func != (Function *)NULL)
-         {
-           /* Special case rl_do_lowercase_version (). */
-           if (func == rl_do_lowercase_version)
-             return (_rl_dispatch (to_lower (key), map));
-
-           r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
-
-           /* 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)
-             rl_last_func = map[key].function;
-         }
-       else
-         {
-           rl_abort ();
-           return -1;
-         }
-      }
+      func = map[key].function;
+      if (func)
+       {
+         /* Special case rl_do_lowercase_version (). */
+         if (func == rl_do_lowercase_version)
+           return (_rl_dispatch (_rl_to_lower (key), map));
+
+         rl_executing_keymap = map;
+
+#if 0
+         _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available ();
+#endif
+
+         rl_dispatching = 1;
+         RL_SETSTATE(RL_STATE_DISPATCHING);
+         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. */
+         if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
+           rl_last_func = map[key].function;
+       }
+      else
+       {
+         _rl_abort_internal ();
+         return -1;
+       }
       break;
 
     case ISKMAP:
-      if (map[key].function != (Function *)NULL)
+      if (map[key].function != 0)
        {
-         int newkey;
-
          rl_key_sequence_length++;
+
+         if (key == ESC)
+           RL_SETSTATE(RL_STATE_METANEXT);
+         RL_SETSTATE(RL_STATE_MOREINPUT);
          newkey = rl_read_key ();
+         RL_UNSETSTATE(RL_STATE_MOREINPUT);
+         if (key == ESC)
+           RL_UNSETSTATE(RL_STATE_METANEXT);
+
          r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
        }
       else
        {
-         rl_abort ();
+         _rl_abort_internal ();
          return -1;
        }
       break;
 
     case ISMACR:
-      if (map[key].function != (Function *)NULL)
+      if (map[key].function != 0)
        {
-         char *macro;
-
          macro = savestring ((char *)map[key].function);
-         with_macro_input (macro);
+         _rl_with_macro_input (macro);
          return 0;
        }
       break;
     }
 #if defined (VI_MODE)
   if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
-      rl_vi_textmod_command (key))
+      _rl_vi_textmod_command (key))
     _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
 #endif
   return (r);
 }
 
-\f
 /* **************************************************************** */
 /*                                                                 */
-/*                     Hacking Keyboard Macros                     */
+/*                     Initializations                             */
 /*                                                                 */
 /* **************************************************************** */
 
-/* The currently executing macro string.  If this is non-zero,
-   then it is a malloc ()'ed string where input is coming from. */
-static char *executing_macro = (char *)NULL;
-
-/* The offset in the above string to the next character to be read. */
-static int executing_macro_index = 0;
+/* Initialize readline (and terminal if not already). */
+int
+rl_initialize ()
+{
+  /* If we have never been called before, initialize the
+     terminal and data structures. */
+  if (!rl_initialized)
+    {
+      RL_SETSTATE(RL_STATE_INITIALIZING);
+      readline_initialize_everything ();
+      RL_UNSETSTATE(RL_STATE_INITIALIZING);
+      rl_initialized++;
+      RL_SETSTATE(RL_STATE_INITIALIZED);
+    }
 
-/* The current macro string being built.  Characters get stuffed
-   in here by add_macro_char (). */
-static char *current_macro = (char *)NULL;
+  /* Initalize the current line information. */
+  _rl_init_line_state ();
 
-/* The size of the buffer allocated to current_macro. */
-static int current_macro_size = 0;
+  /* We aren't done yet.  We haven't even gotten started yet! */
+  rl_done = 0;
+  RL_UNSETSTATE(RL_STATE_DONE);
 
-/* The index at which characters are being added to current_macro. */
-static int current_macro_index = 0;
+  /* Tell the history routines what is going on. */
+  start_using_history ();
 
-/* A structure used to save nested macro strings.
-   It is a linked list of string/index for each saved macro. */
-struct saved_macro {
-  struct saved_macro *next;
-  char *string;
-  int sindex;
-};
+  /* Make the display buffer match the state of the line. */
+  rl_reset_line_state ();
 
-/* The list of saved macros. */
-struct saved_macro *macro_list = (struct saved_macro *)NULL;
+  /* No such function typed yet. */
+  rl_last_func = (rl_command_func_t *)NULL;
 
-/* Forward declarations of static functions.  Thank you C. */
-static void push_executing_macro (), pop_executing_macro ();
+  /* Parsing of key-bindings begins in an enabled state. */
+  _rl_parsing_conditionalized_out = 0;
 
-/* This one has to be declared earlier in the file. */
-/* static void add_macro_char (); */
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    _rl_vi_initialize_line ();
+#endif
 
-/* Set up to read subsequent input from STRING.
-   STRING is free ()'ed when we are done with it. */
-static void
-with_macro_input (string)
-     char *string;
-{
-  push_executing_macro ();
-  executing_macro = string;
-  executing_macro_index = 0;
+  return 0;
 }
 
-/* Return the next character available from a macro, or 0 if
-   there are no macro characters. */
-static int
-next_macro_key ()
+#if 0
+#if defined (__EMX__)
+static void
+_emx_build_environ ()
 {
-  if (!executing_macro)
-    return (0);
+  TIB *tibp;
+  PIB *pibp;
+  char *t, **tp;
+  int c;
 
-  if (!executing_macro[executing_macro_index])
+  DosGetInfoBlocks (&tibp, &pibp);
+  t = pibp->pib_pchenv;
+  for (c = 1; *t; c++)
+    t += strlen (t) + 1;
+  tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
+  t = pibp->pib_pchenv;
+  while (*t)
     {
-      pop_executing_macro ();
-      return (next_macro_key ());
+      *tp++ = t;
+      t += strlen (t) + 1;
     }
-
-  return (executing_macro[executing_macro_index++]);
+  *tp = 0;
 }
+#endif /* __EMX__ */
+#endif
 
-/* Save the currently executing macro on a stack of saved macros. */
+/* Initialize the entire state of the world. */
 static void
-push_executing_macro ()
+readline_initialize_everything ()
 {
-  struct saved_macro *saver;
-
-  saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
-  saver->next = macro_list;
-  saver->sindex = executing_macro_index;
-  saver->string = executing_macro;
+#if 0
+#if defined (__EMX__)
+  if (environ == 0)
+    _emx_build_environ ();
+#endif
+#endif
 
-  macro_list = saver;
-}
+#if 0
+  /* Find out if we are running in Emacs -- UNUSED. */
+  running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
+#endif
 
-/* Discard the current macro, replacing it with the one
-   on the top of the stack of saved macros. */
-static void
-pop_executing_macro ()
-{
-  if (executing_macro)
-    free (executing_macro);
+  /* Set up input and output if they are not already set up. */
+  if (!rl_instream)
+    rl_instream = stdin;
 
-  executing_macro = (char *)NULL;
-  executing_macro_index = 0;
+  if (!rl_outstream)
+    rl_outstream = stdout;
 
-  if (macro_list)
-    {
-      struct saved_macro *disposer = macro_list;
-      executing_macro = macro_list->string;
-      executing_macro_index = macro_list->sindex;
-      macro_list = macro_list->next;
-      free (disposer);
-    }
-}
+  /* Bind _rl_in_stream and _rl_out_stream immediately.  These values
+     may change, but they may also be used before readline_internal ()
+     is called. */
+  _rl_in_stream = rl_instream;
+  _rl_out_stream = rl_outstream;
 
-/* Add a character to the macro being built. */
-static void
-add_macro_char (c)
-     int c;
-{
-  if (current_macro_index + 1 >= current_macro_size)
-    {
-      if (!current_macro)
-       current_macro = xmalloc (current_macro_size = 25);
-      else
-       current_macro = xrealloc (current_macro, current_macro_size += 25);
-    }
+  /* Allocate data structures. */
+  if (rl_line_buffer == 0)
+    rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
 
-  current_macro[current_macro_index++] = c;
-  current_macro[current_macro_index] = '\0';
-}
+  /* Initialize the terminal interface. */
+  if (rl_terminal_name == 0)
+    rl_terminal_name = sh_get_env_value ("TERM");
+  _rl_init_terminal_io (rl_terminal_name);
 
-/* Begin defining a keyboard macro.
-   Keystrokes are recorded as they are executed.
-   End the definition with rl_end_kbd_macro ().
-   If a numeric argument was explicitly typed, then append this
-   definition to the end of the existing macro, and start by
-   re-executing the existing macro. */
-rl_start_kbd_macro (ignore1, ignore2)
-     int ignore1, ignore2;
-{
-  if (defining_kbd_macro)
-    {
-      rl_abort ();
-      return -1;
-    }
-
-  if (rl_explicit_arg)
-    {
-      if (current_macro)
-       with_macro_input (savestring (current_macro));
-    }
-  else
-    current_macro_index = 0;
-
-  defining_kbd_macro = 1;
-  return 0;
-}
-
-/* Stop defining a keyboard macro.
-   A numeric argument says to execute the macro right now,
-   that many times, counting the definition as the first time. */
-rl_end_kbd_macro (count, ignore)
-     int count, ignore;
-{
-  if (!defining_kbd_macro)
-    {
-      rl_abort ();
-      return -1;
-    }
-
-  current_macro_index -= (rl_key_sequence_length - 1);
-  current_macro[current_macro_index] = '\0';
-
-  defining_kbd_macro = 0;
-
-  return (rl_call_last_kbd_macro (--count, 0));
-}
-
-/* Execute the most recently defined keyboard macro.
-   COUNT says how many times to execute it. */
-rl_call_last_kbd_macro (count, ignore)
-     int count, ignore;
-{
-  if (!current_macro)
-    rl_abort ();
-
-  if (defining_kbd_macro)
-    {
-      ding ();         /* no recursive macros */
-      current_macro[--current_macro_index] = '\0';     /* erase this char */
-      return 0;
-    }
-
-  while (count--)
-    with_macro_input (savestring (current_macro));
-  return 0;
-}
-
-void
-_rl_kill_kbd_macro ()
-{
-  if (current_macro)
-    {
-      free (current_macro);
-      current_macro = (char *) NULL;
-    }
-  current_macro_size = current_macro_index = 0;
-
-  if (executing_macro)
-    {
-      free (executing_macro);
-      executing_macro = (char *) NULL;
-    }
-  executing_macro_index = 0;
-
-  defining_kbd_macro = 0;
-}
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Initializations                             */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Initliaze readline (and terminal if not already). */
-rl_initialize ()
-{
-  /* If we have never been called before, initialize the
-     terminal and data structures. */
-  if (!rl_initialized)
-    {
-      readline_initialize_everything ();
-      rl_initialized++;
-    }
-
-  /* Initalize the current line information. */
-  rl_point = rl_end = 0;
-  the_line = rl_line_buffer;
-  the_line[0] = 0;
-
-  /* We aren't done yet.  We haven't even gotten started yet! */
-  rl_done = 0;
-
-  /* Tell the history routines what is going on. */
-  start_using_history ();
-
-  /* Make the display buffer match the state of the line. */
-  rl_reset_line_state ();
-
-  /* No such function typed yet. */
-  rl_last_func = (Function *)NULL;
-
-  /* Parsing of key-bindings begins in an enabled state. */
-  _rl_parsing_conditionalized_out = 0;
-
-  return 0;
-}
-
-/* Initialize the entire state of the world. */
-static void
-readline_initialize_everything ()
-{
-  char *t;
-
-  /* Find out if we are running in Emacs. */
-  running_in_emacs = getenv ("EMACS") != (char *)0;
-
-  /* Set up input and output if they are not already set up. */
-  if (!rl_instream)
-    rl_instream = stdin;
-
-  if (!rl_outstream)
-    rl_outstream = stdout;
-
-  /* Bind in_stream and out_stream immediately.  These values may change,
-     but they may also be used before readline_internal () is called. */
-  in_stream = rl_instream;
-  out_stream = rl_outstream;
-
-  /* Allocate data structures. */
-  if (!rl_line_buffer)
-    rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
-
-  /* Initialize the terminal interface. */
-  init_terminal_io ((char *)NULL);
-
-#if !defined (__GO32__)
-  /* Bind tty characters to readline functions. */
-  readline_default_bindings ();
-#endif /* !__GO32__ */
+  /* Bind tty characters to readline functions. */
+  readline_default_bindings ();
 
   /* Initialize the function names. */
   rl_initialize_funmap ();
 
-  /* Check for LC_CTYPE and use its value to decide the defaults for
-     8-bit character input and output. */
-  t = getenv ("LC_CTYPE");
-  if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0 ||
-           strcmp (t, "ISO-8859-1") == 0))
-    {
-      _rl_meta_flag = 1;
-      _rl_convert_meta_chars_to_ascii = 0;
-      _rl_output_meta_chars = 1;
-    }
+  /* Decide whether we should automatically go into eight-bit mode. */
+  _rl_init_eightbit ();
       
   /* Read in the init file. */
   rl_read_init_file ((char *)NULL);
 
   /* XXX */
-  if (_rl_horizontal_scroll_mode && term_xn)
+  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
@@ -1018,6 +747,10 @@ readline_initialize_everything ()
   /* Try to bind a common arrow key prefix, if not already bound. */
   bind_arrow_keys ();
 
+  /* Enable the meta key, if this terminal has one. */
+  if (_rl_enable_meta)
+    _rl_enable_meta_key ();
+
   /* If the completion parser's default word break characters haven't
      been set yet, then do so now. */
   if (rl_completer_word_break_characters == (char *)NULL)
@@ -1030,14 +763,25 @@ readline_initialize_everything ()
 static void
 readline_default_bindings ()
 {
-  rltty_set_default_bindings (_rl_keymap);
+  rl_tty_set_default_bindings (_rl_keymap);
 }
 
 static void
 bind_arrow_keys_internal ()
 {
-  Function *f;
+  rl_command_func_t *f;
 
+#if defined (__MSDOS__)
+  f = rl_function_of_keyseq ("\033[0A", _rl_keymap, (int *)NULL);
+  if (!f || f == rl_do_lowercase_version)
+    {
+       _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
+       _rl_bind_if_unbound ("\033[0B", rl_backward);
+       _rl_bind_if_unbound ("\033[0C", rl_forward);
+       _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
+    }
+#endif
+       
   f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
   if (!f || f == rl_do_lowercase_version)
     {
@@ -1089,64 +833,100 @@ bind_arrow_keys ()
 static int
 rl_digit_loop ()
 {
-  int key, c;
+  int key, c, sawminus, sawdigits;
+
+  rl_save_prompt ();
 
+  RL_SETSTATE(RL_STATE_NUMERICARG);
+  sawminus = sawdigits = 0;
   while (1)
     {
+      if (rl_numeric_arg > 1000000)
+       {
+         sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
+         rl_ding ();
+         rl_restore_prompt ();
+         rl_clear_message ();
+         RL_UNSETSTATE(RL_STATE_NUMERICARG);
+         return 1;
+       }
       rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+      RL_SETSTATE(RL_STATE_MOREINPUT);
       key = c = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+      /* 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)
        {
-         rl_numeric_arg *= 4;
-         continue;
-       }
-      c = UNMETA (c);
-      if (digit_p (c))
-       {
-         if (rl_explicit_arg)
-           rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
-         else
-           rl_numeric_arg = (c - '0');
-         rl_explicit_arg = 1;
-       }
-      else
-       {
-         if (c == '-' && !rl_explicit_arg)
+         if (sawdigits == 0)
            {
-             rl_numeric_arg = 1;
-             rl_arg_sign = -1;
+             rl_numeric_arg *= 4;
+             continue;
            }
          else
            {
+             RL_SETSTATE(RL_STATE_MOREINPUT);
+             key = rl_read_key ();
+             RL_UNSETSTATE(RL_STATE_MOREINPUT);
+             rl_restore_prompt ();
              rl_clear_message ();
+             RL_UNSETSTATE(RL_STATE_NUMERICARG);
              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 ();
+         RL_UNSETSTATE(RL_STATE_NUMERICARG);
+         return (_rl_dispatch (key, _rl_keymap));
+       }
     }
+
+  RL_UNSETSTATE(RL_STATE_NUMERICARG);
   return 0;
 }
 
 /* Add the current digit to the argument in progress. */
+int
 rl_digit_argument (ignore, key)
      int ignore, key;
 {
-  rl_pending_input = key;
+  rl_execute_next (key);
   return (rl_digit_loop ());
 }
 
 /* What to do when you abort reading an argument. */
+int
 rl_discard_argument ()
 {
-  ding ();
+  rl_ding ();
   rl_clear_message ();
-  rl_init_argument ();
+  _rl_init_argument ();
   return 0;
 }
 
 /* Create a default argument. */
-rl_init_argument ()
+int
+_rl_init_argument ()
 {
   rl_numeric_arg = rl_arg_sign = 1;
   rl_explicit_arg = 0;
@@ -1156,2384 +936,1224 @@ rl_init_argument ()
 /* 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. */
-rl_universal_argument ()
+int
+rl_universal_argument (count, key)
+     int count, key;
 {
   rl_numeric_arg *= 4;
   return (rl_digit_loop ());
 }
-\f
+
 /* **************************************************************** */
 /*                                                                 */
-/*                     Terminal and Termcap                        */
+/*                     Insert and Delete                           */
 /*                                                                 */
 /* **************************************************************** */
 
-static char *term_buffer = (char *)NULL;
-static char *term_string_buffer = (char *)NULL;
-
-static int tcap_initialized = 0;
-
-/* Non-zero means this terminal can't really do anything. */
-int dumb_term = 0;
-/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
-   Unfortunately, PC is a global variable used by the termcap library. */
-#undef PC
-
-#if !defined (__linux__)
-/* If this causes problems, add back the `extern'. */
-/*extern*/ char PC, *BC, *UP;
-#endif /* __linux__ */
+/* 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)
+     const char *string;
+{
+  register int i, l = strlen (string);
 
-/* Some strings to control terminal actions.  These are output by tputs (). */
-char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
-char *term_pc;
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
 
-/* Non-zero if we determine that the terminal can do character insertion. */
-int terminal_can_insert = 0;
+  for (i = rl_end; i >= rl_point; i--)
+    the_line[i + l] = the_line[i];
+  strncpy (the_line + rl_point, string, l);
 
-/* How to insert characters. */
-char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
+  /* 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;
+}
 
-/* How to delete characters. */
-char *term_dc, *term_DC;
+/* 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;
 
-#if defined (HACK_TERMCAP_MOTION)
-char *term_forward_char;
-#endif  /* HACK_TERMCAP_MOTION */
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
 
-/* How to go up a line. */
-char *term_up;
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+        from = to;
+    }
 
-/* A visible bell, if the terminal can be made to flash the screen. */
-char *visible_bell;
+  text = rl_copy_text (from, to);
 
-/* Non-zero means that this terminal has a meta key. */
-int term_has_meta;
+  /* 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];
 
-/* The string to write to turn on the meta key, if this term has one. */
-char *term_mm;
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
 
-/* The string to write to turn off the meta key, if this term has one. */
-char *term_mo;
+  rl_end -= diff;
+  the_line[rl_end] = '\0';
+  return (diff);
+}
 
-/* The key sequences output by the arrow keys, if this terminal has any. */
-char *term_ku, *term_kd, *term_kr, *term_kl;
+/* 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. */
 
-/* How to initialize and reset the arrow keys, if this terminal has any. */
-char *term_ks, *term_ke;
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
 
-/* Re-initialize the terminal considering that the TERM/TERMCAP variable
-   has changed. */
-rl_reset_terminal (terminal_name)
-     char *terminal_name;
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
 {
-  init_terminal_io (terminal_name);
-  return 0;
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
 }
+#undef _RL_FIX_POINT
 
-/* Set readline's idea of the screen size.  TTY is a file descriptor open
-   to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
-   values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
-   non-null serve to check whether or not we have initialized termcap. */
 void
-_rl_set_screen_size (tty, ignore_env)
-     int tty, ignore_env;
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
 {
-#if defined (TIOCGWINSZ)
-  struct winsize window_size;
-#endif /* TIOCGWINSZ */
-
-#if defined (TIOCGWINSZ)
-  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
-    {
-      screenwidth = (int) window_size.ws_col;
-      screenheight = (int) window_size.ws_row;
-    }
-#endif /* TIOCGWINSZ */
-
-  /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
-     is unset. */
-  if (screenwidth <= 0)
-    {
-      char *sw;
+  rl_begin_undo_group ();
+  rl_delete_text (start, end + 1);
+  rl_point = start;
+  rl_insert_text (text);
+  rl_end_undo_group ();
+}
 
-      if (!ignore_env && (sw = getenv ("COLUMNS")))
-       screenwidth = atoi (sw);
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
 
-      if (screenwidth <= 0 && term_string_buffer)
-       screenwidth = tgetnum ("co");
-    }
+/* 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. */
 
-  /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
-     is unset. */
-  if (screenheight <= 0)
-    {
-      char *sh;
+/* Note that:
 
-      if (!ignore_env && (sh = getenv ("LINES")))
-       screenheight = atoi (sh);
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
 
-      if (screenheight <= 0 && term_string_buffer)
-       screenheight = tgetnum ("li");
-    }
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
 
-  /* If all else fails, default to 80x24 terminal. */
-  if (screenwidth <= 1)
-    screenwidth = 80;
+   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.
+*/
 
-  if (screenheight <= 0)
-    screenheight = 24;
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
 
-#if defined (SHELL)
-  /* If we're being compiled as part of bash, set the environment
-     variables $LINES and $COLUMNS to new values. */
-  set_lines_and_columns (screenheight, screenwidth);
-#endif
+/* 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. */
 
-  if (!term_xn)
-    screenwidth--;
-
-  screenchars = screenwidth * screenheight;
-}
-
-struct _tc_string {
-     char *tc_var;
-     char **tc_value;
-};
-
-/* This should be kept sorted, just in case we decide to change the
-   search algorithm to something smarter. */
-static struct _tc_string tc_strings[] =
-{
-  "DC", &term_DC,
-  "IC", &term_IC,
-  "ce", &term_clreol,
-  "cl", &term_clrpag,
-  "cr", &term_cr,
-  "dc", &term_dc,
-  "ei", &term_ei,
-  "ic", &term_ic,
-  "im", &term_im,
-  "kd", &term_kd,
-  "kl", &term_kl,
-  "kr", &term_kr,
-  "ku", &term_ku,
-  "ks", &term_ks,
-  "ke", &term_ke,
-  "le", &term_backspace,
-  "mm", &term_mm,
-  "mo", &term_mo,
-#if defined (HACK_TERMCAP_MOTION)
-  "nd", &term_forward_char,
+/* 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 > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+      int lend = rl_end;
 #endif
-  "pc", &term_pc,
-  "up", &term_up,
-  "vb", &visible_bell,
-};
 
-#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
 
-/* Read the desired terminal capability strings into BP.  The capabilities
-   are described in the TC_STRINGS table. */
-static void
-get_term_capabilities (bp)
-     char **bp;
-{
-  register int i;
+  if (rl_end < 0)
+    rl_end = 0;
 
-  for (i = 0; i < NUM_TC_STRINGS; i++)
-    *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
-  tcap_initialized = 1;
+  return 0;
 }
 
-static int
-init_terminal_io (terminal_name)
-     char *terminal_name;
-{
-#if defined (__GO32__)
-  screenwidth = ScreenCols ();
-  screenheight = ScreenRows ();
-  screenchars = screenwidth * screenheight;
-  term_cr = "\r";
-  term_im = term_ei = term_ic = term_IC = (char *)NULL;
-  term_up = term_dc = term_DC = visible_bell = (char *)NULL;
-
-  /* Does the __GO32__ have a meta key?  I don't know. */
-  term_has_meta = 0;
-  term_mm = term_mo = (char *)NULL;
-
-  /* It probably has arrow keys, but I don't know what they are. */
-  term_ku = term_kd = term_kr = term_kl = (char *)NULL;
-
-#if defined (HACK_TERMCAP_MOTION)
-  term_forward_char = (char *)NULL;
-#endif /* HACK_TERMCAP_MOTION */
-  terminal_can_insert = term_xn = 0;
-  return;
-#else /* !__GO32__ */
-
-  char *term, *buffer;
-  int tty;
-  Keymap xkeymap;
-
-  term = terminal_name ? terminal_name : getenv ("TERM");
-
-  if (!term_string_buffer)
-    term_string_buffer = xmalloc (2048);
-
-  if (!term_buffer)
-    term_buffer = xmalloc (2048);
-
-  buffer = term_string_buffer;
-
-  term_clrpag = term_cr = term_clreol = (char *)NULL;
-
-  if (!term)
-    term = "dumb";
-
-  if (tgetent (term_buffer, term) <= 0)
-    {
-      dumb_term = 1;
-      screenwidth = 79;
-      screenheight = 24;
-      screenchars = 79 * 24;
-      term_cr = "\r";
-      term_im = term_ei = term_ic = term_IC = (char *)NULL;
-      term_up = term_dc = term_DC = visible_bell = (char *)NULL;
-      term_ku = term_kd = term_kl = term_kr = (char *)NULL;
-#if defined (HACK_TERMCAP_MOTION)
-      term_forward_char = (char *)NULL;
-#endif
-      terminal_can_insert = 0;
-      return 0;
-    }
-
-  get_term_capabilities (&buffer);
-
-  /* Set up the variables that the termcap library expects the application
-     to provide. */
-  PC = term_pc ? *term_pc : 0;
-  BC = term_backspace;
-  UP = term_up;
-
-  if (!term_cr)
-    term_cr =  "\r";
-
-  if (rl_instream)
-    tty = fileno (rl_instream);
-  else
-    tty = 0;
-
-  screenwidth = screenheight = 0;
-
-  term_xn = tgetflag ("am") && tgetflag ("xn");
-
-  _rl_set_screen_size (tty, 0);
-
-  /* "An application program can assume that the terminal can do
-      character insertion if *any one of* the capabilities `IC',
-      `im', `ic' or `ip' is provided."  But we can't do anything if
-      only `ip' is provided, so... */
-  terminal_can_insert = (term_IC || term_im || term_ic);
-
-  /* Check to see if this terminal has a meta key and clear the capability
-     variables if there is none. */
-  term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
-  if (!term_has_meta)
-    {
-      term_mm = (char *)NULL;
-      term_mo = (char *)NULL;
-    }
-
-  /* Attempt to find and bind the arrow keys.  Do not override already
-     bound keys in an overzealous attempt, however. */
-  xkeymap = _rl_keymap;
-
-  _rl_keymap = emacs_standard_keymap;
-  _rl_bind_if_unbound (term_ku, rl_get_previous_history);
-  _rl_bind_if_unbound (term_kd, rl_get_next_history);
-  _rl_bind_if_unbound (term_kr, rl_forward);
-  _rl_bind_if_unbound (term_kl, rl_backward);
-
-#if defined (VI_MODE)
-  _rl_keymap = vi_movement_keymap;
-  _rl_bind_if_unbound (term_ku, rl_get_previous_history);
-  _rl_bind_if_unbound (term_kd, rl_get_next_history);
-  _rl_bind_if_unbound (term_kr, rl_forward);
-  _rl_bind_if_unbound (term_kl, rl_backward);
-#endif /* VI_MODE */
-
-  _rl_keymap = xkeymap;
-
-#endif /* !__GO32__ */
-  return 0;
-}
-
-char *
-rl_get_termcap (cap)
-     char *cap;
-{
-  register int i;
-
-  if (tcap_initialized == 0)
-    return ((char *)NULL);
-  for (i = 0; i < NUM_TC_STRINGS; i++)
-    {
-      if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
-        return *(tc_strings[i].tc_value);
-    }
-  return ((char *)NULL);
-}
-
-/* A function for the use of tputs () */
-int
-_rl_output_character_function (c)
-     int c;
-{
-  return putc (c, out_stream);
-}
-
-/* Write COUNT characters from STRING to the output stream. */
-void
-_rl_output_some_chars (string, count)
-     char *string;
-     int count;
-{
-  fwrite (string, 1, count, out_stream);
-}
-
-/* Move the cursor back. */
-backspace (count)
-     int count;
-{
-  register int i;
-
-#if !defined (__GO32__)
-  if (term_backspace)
-    for (i = 0; i < count; i++)
-      tputs (term_backspace, 1, _rl_output_character_function);
-  else
-#endif /* !__GO32__ */
-    for (i = 0; i < count; i++)
-      putc ('\b', out_stream);
-  return 0;
-}
-
-/* Move to the start of the next line. */
-crlf ()
-{
-#if defined (NEW_TTY_DRIVER)
-  tputs (term_cr, 1, _rl_output_character_function);
-#endif /* NEW_TTY_DRIVER */
-  putc ('\n', out_stream);
-  return 0;
-}
-
-rl_tty_status (count, key)
-     int count, key;
-{
-#if defined (TIOCSTAT)
-  ioctl (1, TIOCSTAT, (char *)0);
-  rl_refresh_line ();
-#else
-  ding ();
-#endif
-  return 0;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Utility Functions                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Return 0 if C is not a member of the class of characters that belong
-   in words, or 1 if it is. */
-
-int allow_pathname_alphabetic_chars = 0;
-char *pathname_alphabetic_chars = "/-_=~.#$";
-
-int
-alphabetic (c)
-     int c;
-{
-  if (pure_alphabetic (c) || (digit_p (c)))
-    return (1);
-
-  if (allow_pathname_alphabetic_chars)
-    return (strchr (pathname_alphabetic_chars, c) != NULL);
-  else
-    return (0);
-}
-
-/* Ring the terminal bell. */
+/* Move backward COUNT characters. */
 int
-ding ()
-{
-  if (readline_echoing_p)
-    {
-#if !defined (__GO32__)
-      switch (_rl_bell_preference)
-        {
-       case NO_BELL:
-       default:
-         break;
-       case VISIBLE_BELL:
-         if (visible_bell)
-           {
-             tputs (visible_bell, 1, _rl_output_character_function);
-             break;
-           }
-         /* FALLTHROUGH */
-       case AUDIBLE_BELL:
-         fprintf (stderr, "\007");
-         fflush (stderr);
-         break;
-        }
-#else /* __GO32__ */
-      fprintf (stderr, "\007");
-      fflush (stderr);
-#endif /* __GO32__ */
-      return (0);
-    }
-  return (-1);
-}
-
-/* How to abort things. */
-rl_abort (count, key)
-     int count, key;
-{
-  ding ();
-  rl_clear_message ();
-  rl_init_argument ();
-  rl_pending_input = 0;
-
-  defining_kbd_macro = 0;
-  while (executing_macro)
-    pop_executing_macro ();
-
-  rl_last_func = (Function *)NULL;
-  longjmp (readline_top_level, 1);
-}
-
-/* Return a copy of the string between FROM and TO.
-   FROM is inclusive, TO is not. */
-char *
-rl_copy_text (from, to)
-     int from, to;
-{
-  register int length;
-  char *copy;
-
-  /* Fix it if the caller is confused. */
-  if (from > to)
-    {
-      int t = from;
-      from = to;
-      to = t;
-    }
-
-  length = to - from;
-  copy = xmalloc (1 + length);
-  strncpy (copy, the_line + from, length);
-  copy[length] = '\0';
-  return (copy);
-}
-
-/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
-   LEN characters. */
-void
-rl_extend_line_buffer (len)
-     int len;
-{
-  while (len >= rl_line_buffer_len)
-    {
-      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
-      rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len);
-    }
-
-  the_line = rl_line_buffer;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     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. */
-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 (!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. */
-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)
-    {
-      int t = from;
-      from = to;
-      to = t;
-    }
-
-  if (to > rl_end)
-    to = rl_end;
-
-  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];
-
-  /* Remember how to undo this delete. */
-  if (!doing_an_undo)
-    rl_add_undo (UNDO_DELETE, from, to, text);
-  else
-    free (text);
-
-  rl_end -= diff;
-  the_line[rl_end] = '\0';
-  return (diff);
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Readline character functions                */
-/*                                                                 */
-/* **************************************************************** */
-
-/* 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.
-*/
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     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. */
-rl_forward (count, key)
+rl_backward (count, key)
      int count, key;
 {
-  if (count < 0)
-    rl_backward (-count);
-  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. */
-rl_backward (count, key)
-     int count, key;
-{
-  if (count < 0)
-    rl_forward (-count);
-  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. */
-rl_beg_of_line (count, key)
-     int count, key;
-{
-  rl_point = 0;
-  return 0;
-}
-
-/* Move to the end of the line. */
-rl_end_of_line (count, key)
-     int count, key;
-{
-  rl_point = rl_end;
-  return 0;
-}
-
-/* Move forward a word.  We do what Emacs does. */
-rl_forward_word (count, key)
-     int count, key;
-{
-  int c;
-
-  if (count < 0)
-    {
-      rl_backward_word (-count);
-      return 0;
-    }
-
-  while (count)
-    {
-      if (rl_point == rl_end)
-       return 0;
-
-      /* 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))
-       {
-         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))
-           break;
-       }
-      --count;
-    }
-  return 0;
-}
-
-/* Move backward a word.  We do what Emacs does. */
-rl_backward_word (count, key)
-     int count, key;
-{
-  int c;
-
-  if (count < 0)
-    {
-      rl_forward_word (-count);
-      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))
-       {
-         while (--rl_point)
-           {
-             c = the_line[rl_point - 1];
-             if (alphabetic (c))
-               break;
-           }
-       }
-
-      while (rl_point)
-       {
-         c = the_line[rl_point - 1];
-         if (!alphabetic (c))
-           break;
-         else
-           --rl_point;
-       }
-      --count;
-    }
-  return 0;
-}
-
-/* Clear the current line.  Numeric argument to C-l does this. */
-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__ */
-  if (term_clreol)
-    tputs (term_clreol, 1, _rl_output_character_function);
-#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. */
-rl_clear_screen (count, key)
-     int count, key;
-{
-  if (rl_explicit_arg)
-    {
-      rl_refresh_line ();
-      return 0;
-    }
-
-#if !defined (__GO32__)
-  if (term_clrpag)
-    tputs (term_clrpag, 1, _rl_output_character_function);
-  else
-#endif /* !__GO32__ */
-    crlf ();
-
-  rl_forced_update_display ();
-  rl_display_fixed = 1;
-
-  return 0;
-}
-
-rl_arrow_keys (count, c)
-     int count, c;
-{
-  int ch;
-
-  ch = rl_read_key ();
-
-  switch (to_upper (ch))
-    {
-    case 'A':
-      rl_get_previous_history (count);
-      break;
-
-    case 'B':
-      rl_get_next_history (count);
-      break;
-
-    case 'C':
-      rl_forward (count);
-      break;
-
-    case 'D':
-      rl_backward (count);
-      break;
-
-    default:
-      ding ();
-    }
-  return 0;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Text commands                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Insert the character C at the current location, moving point forward. */
-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 (any_typein)
-    {
-      int key = 0, t;
-
-      i = 0;
-      string = xmalloc (ibuffer_len + 1);
-      string[i++] = c;
-
-      while ((t = rl_get_char (&key)) &&
-            (_rl_keymap[key].type == ISFUNC &&
-             _rl_keymap[key].function == rl_insert))
-       string[i++] = key;
-
-      if (t)
-       rl_unget_char (key);
-
-      string[i] = '\0';
-      rl_insert_text (string);
-      free (string);
-    }
-  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. */
-rl_quoted_insert (count, key)
-     int count, key;
-{
-  int c;
-
-  c = rl_read_key ();
-  return (rl_insert (count, c));  
-}
-
-/* Insert a tab character. */
-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. */
-rl_newline (count, key)
-     int count, key;
-{
-  rl_done = 1;
-
-#if defined (VI_MODE)
-  _rl_vi_done_inserting ();
-  _rl_vi_reset_last ();
-
-#endif /* VI_MODE */
-
-  if (readline_echoing_p)
-    _rl_update_final ();
-  return 0;
-}
-
-rl_clean_up_for_exit ()
-{
-  if (readline_echoing_p)
-    {
-      _rl_move_vert (_rl_vis_botlin);
-      _rl_vis_botlin = 0;
-      fflush (out_stream);
-      rl_restart_output ();
-    }
-  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. */
-rl_do_lowercase_version (ignore1, ignore2)
-     int ignore1, ignore2;
-{
-  return 0;
-}
-
-/* Rubout the character behind point. */
-rl_rubout (count, key)
-     int count, key;
-{
-  if (count < 0)
-    {
-      rl_delete (-count);
-      return 0;
-    }
-
-  if (!rl_point)
-    {
-      ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_backward (count);
-      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. */
-rl_delete (count, invoking_key)
-     int count, invoking_key;
-{
-  if (count < 0)
-    {
-      return (rl_rubout (-count));
-    }
-
-  if (rl_point == rl_end)
-    {
-      ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_forward (count);
-      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. */
-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;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Kill commands                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* The next two functions mimic unix line editing behaviour, except they
-   save the deleted text on the kill ring.  This is safer than not saving
-   it, and since we have a ring, nobody should get screwed. */
-
-/* This does what C-w does in Unix.  We can't prevent people from
-   using behaviour that they expect. */
-rl_unix_word_rubout (count, key)
-     int count, key;
-{
-  if (!rl_point)
-    ding ();
-  else
-    {
-      int orig_point = rl_point;
-      if (count <= 0)
-       count = 1;
-
-      while (count--)
-       {
-         while (rl_point && whitespace (the_line[rl_point - 1]))
-           rl_point--;
-
-         while (rl_point && !whitespace (the_line[rl_point - 1]))
-           rl_point--;
-       }
-
-      rl_kill_text (orig_point, rl_point);
-    }
-  return 0;
-}
-
-/* Here is C-u doing what Unix does.  You don't *have* to use these
-   key-bindings.  We have a choice of killing the entire line, or
-   killing from where we are to the start of the line.  We choose the
-   latter, because if you are a Unix weenie, then you haven't backspaced
-   into the line at all, and if you aren't, then you know what you are
-   doing. */
-rl_unix_line_discard (count, key)
-     int count, key;
-{
-  if (!rl_point)
-    ding ();
-  else
-    {
-      rl_kill_text (rl_point, 0);
-      rl_point = 0;
-    }
-  return 0;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Commands For Typos                          */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Random and interesting things in here.  */
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     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. */
-rl_upcase_word (count, key)
-     int count, key;
-{
-  return (rl_change_case (count, UpCase));
+  if (count < 0)
+    rl_forward (-count, key);
+  else if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point -= count;
+    }
+  return 0;
 }
 
-/* Lowercase the word at point. */
-rl_downcase_word (count, key)
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
      int count, key;
 {
-  return (rl_change_case (count, DownCase));
+  rl_point = 0;
+  return 0;
 }
 
-/* Upcase the first letter, downcase the rest. */
-rl_capitalize_word (count, key)
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
      int count, key;
 {
- return (rl_change_case (count, CapCase));
+  rl_point = rl_end;
+  return 0;
 }
 
-/* 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;
+/* Move forward a word.  We do what Emacs does. */
+int
+rl_forward_word (count, key)
+     int count, key;
 {
-  register int start = rl_point, end;
-  int state = 0;
-
-  rl_forward_word (count);
-  end = rl_point;
+  int c;
 
   if (count < 0)
     {
-      int temp = start;
-      start = end;
-      end = temp;
+      rl_backward_word (-count, key);
+      return 0;
     }
 
-  /* We are going to modify some text, so let's prepare to undo it. */
-  rl_modifying (start, end);
-
-  for (; start < end; start++)
+  while (count)
     {
-      switch (op)
-       {
-       case UpCase:
-         the_line[start] = to_upper (the_line[start]);
-         break;
-
-       case DownCase:
-         the_line[start] = to_lower (the_line[start]);
-         break;
+      if (rl_point == rl_end)
+       return 0;
 
-       case CapCase:
-         if (state == 0)
-           {
-             the_line[start] = to_upper (the_line[start]);
-             state = 1;
-           }
-         else
+      /* 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 (rl_alphabetic (c) == 0)
+       {
+         while (++rl_point < rl_end)
            {
-             the_line[start] = to_lower (the_line[start]);
+             c = the_line[rl_point];
+             if (rl_alphabetic (c))
+               break;
            }
-         if (!pure_alphabetic (the_line[start]))
-           state = 0;
-         break;
-
-       default:
-         ding ();
-         return -1;
        }
+      if (rl_point == rl_end)
+       return 0;
+      while (++rl_point < rl_end)
+       {
+         c = the_line[rl_point];
+         if (rl_alphabetic (c) == 0)
+           break;
+       }
+      --count;
     }
-  rl_point = end;
   return 0;
 }
 
-/* **************************************************************** */
-/*                                                                 */
-/*                     Transposition                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Transpose the words at point. */
-rl_transpose_words (count, key)
+/* Move backward a word.  We do what Emacs does. */
+int
+rl_backward_word (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);
-  w2_end = rl_point;
-  rl_backward_word (1);
-  w2_beg = rl_point;
-  rl_backward_word (count);
-  w1_beg = rl_point;
-  rl_forward_word (1);
-  w1_end = rl_point;
+  int c;
 
-  /* Do some check to make sure that there really are two words. */
-  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+  if (count < 0)
     {
-      ding ();
-      rl_point = orig_point;
-      return -1;
+      rl_forward_word (-count, key);
+      return 0;
     }
 
-  /* 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);
+  while (count)
+    {
+      if (!rl_point)
+       return 0;
 
-  /* This is exactly correct since the text before this point has not
-     changed in length. */
-  rl_point = w2_end;
+      /* Like rl_forward_word (), except that we look at the characters
+        just before point. */
 
-  /* I think that does it. */
-  rl_end_undo_group ();
-  free (word1);
-  free (word2);
+      c = the_line[rl_point - 1];
+      if (rl_alphabetic (c) == 0)
+       {
+         while (--rl_point)
+           {
+             c = the_line[rl_point - 1];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
 
+      while (rl_point)
+       {
+         c = the_line[rl_point - 1];
+         if (rl_alphabetic (c) == 0)
+           break;
+         else
+           --rl_point;
+       }
+      --count;
+    }
   return 0;
 }
 
-/* Transpose the characters at point.  If point is at the end of the line,
-   then transpose the characters before point. */
-rl_transpose_chars (count, key)
-     int count, key;
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
 {
-  char dummy[2];
-
-  if (!count)
-    return 0;
+  int curr_line;
 
-  if (!rl_point || rl_end < 2)
-    {
-      ding ();
-      return -1;
-    }
-
-  rl_begin_undo_group ();
-
-  if (rl_point == rl_end)
-    {
-      --rl_point;
-      count = 1;
-    }
-  rl_point--;
+  curr_line = _rl_current_display_line ();
 
-  dummy[0] = the_line[rl_point];
-  dummy[1] = '\0';
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, the_line);   /* XXX is this right */
 
-  rl_delete_text (rl_point, rl_point + 1);
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
 
-  rl_point += count;
-  if (rl_point > rl_end)
-    rl_point = rl_end;
-  else if (rl_point < 0)
-    rl_point = 0;
-  rl_insert_text (dummy);
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
 
-  rl_end_undo_group ();
   return 0;
 }
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Undo, and Undoing                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* The current undo list for THE_LINE. */
-UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
-
-/* Remember how to undo something.  Concatenate some undos if that
-   seems right. */
-void
-rl_add_undo (what, start, end, text)
-     enum undo_code what;
-     int start, end;
-     char *text;
-{
-  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
-  temp->what = what;
-  temp->start = start;
-  temp->end = end;
-  temp->text = text;
-  temp->next = rl_undo_list;
-  rl_undo_list = temp;
-}
 
-/* Free the existing undo list. */
-void
-free_undo_list ()
+/* 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;
 {
-  while (rl_undo_list)
+  if (rl_explicit_arg)
     {
-      UNDO_LIST *release = rl_undo_list;
-      rl_undo_list = rl_undo_list->next;
-
-      if (release->what == UNDO_DELETE)
-       free (release->text);
-
-      free (release);
+      rl_refresh_line (count, key);
+      return 0;
     }
-  rl_undo_list = (UNDO_LIST *)NULL;
-}
-
-/* Undo the next thing in the list.  Return 0 if there
-   is nothing to undo, or non-zero if there was. */
-int
-rl_do_undo ()
-{
-  UNDO_LIST *release;
-  int waiting_for_begin = 0;
-
-undo_thing:
-  if (!rl_undo_list)
-    return (0);
-
-  doing_an_undo = 1;
-
-  switch (rl_undo_list->what) {
-
-    /* Undoing deletes means inserting some text. */
-  case UNDO_DELETE:
-    rl_point = rl_undo_list->start;
-    rl_insert_text (rl_undo_list->text);
-    free (rl_undo_list->text);
-    break;
-
-    /* Undoing inserts means deleting some text. */
-  case UNDO_INSERT:
-    rl_delete_text (rl_undo_list->start, rl_undo_list->end);
-    rl_point = rl_undo_list->start;
-    break;
-
-    /* Undoing an END means undoing everything 'til we get to
-       a BEGIN. */
-  case UNDO_END:
-    waiting_for_begin++;
-    break;
-
-    /* Undoing a BEGIN means that we are done with this group. */
-  case UNDO_BEGIN:
-    if (waiting_for_begin)
-      waiting_for_begin--;
-    else
-      ding ();
-    break;
-  }
 
-  doing_an_undo = 0;
-
-  release = rl_undo_list;
-  rl_undo_list = rl_undo_list->next;
-  free (release);
-
-  if (waiting_for_begin)
-    goto undo_thing;
-
-  return (1);
-}
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
 
-/* Begin a group.  Subsequent undos are undone as an atomic operation. */
-int
-rl_begin_undo_group ()
-{
-  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
   return 0;
 }
 
-/* End an undo group started with rl_begin_undo_group (). */
 int
-rl_end_undo_group ()
+rl_arrow_keys (count, c)
+     int count, c;
 {
-  rl_add_undo (UNDO_END, 0, 0, 0);
-  return 0;
-}
+  int ch;
 
-/* Save an undo entry for the text from START to END. */
-rl_modifying (start, end)
-     int start, end;
-{
-  if (start > end)
-    {
-      int t = start;
-      start = end;
-      end = t;
-    }
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
-  if (start != end)
+  switch (_rl_to_upper (ch))
     {
-      char *temp = rl_copy_text (start, end);
-      rl_begin_undo_group ();
-      rl_add_undo (UNDO_DELETE, start, end, temp);
-      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
-      rl_end_undo_group ();
-    }
-  return 0;
-}
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
 
-/* Revert the current line to its previous state. */
-int
-rl_revert_line (count, key)
-     int count, key;
-{
-  if (!rl_undo_list)
-    ding ();
-  else
-    {
-      while (rl_undo_list)
-       rl_do_undo ();
-    }
-  return 0;
-}
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
 
-/* Do some undoing of things that were done. */
-int
-rl_undo_command (count, key)
-     int count, key;
-{
-  if (count < 0)
-    return 0;  /* Nothing to do. */
+    case 'C':
+      rl_forward (count, ch);
+      break;
 
-  while (count)
-    {
-      if (rl_do_undo ())
-       count--;
-      else
-       {
-         ding ();
-         break;
-       }
+    case 'D':
+      rl_backward (count, ch);
+      break;
+
+    default:
+      rl_ding ();
     }
   return 0;
 }
+
 \f
 /* **************************************************************** */
 /*                                                                 */
-/*                     History Utilities                           */
+/*                     Text commands                               */
 /*                                                                 */
 /* **************************************************************** */
 
-/* We already have a history library, and that is what we use to control
-   the history features of readline.  However, 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 ()
+/* Insert the character C at the current location, moving point forward. */
+int
+rl_insert (count, c)
+     int count, c;
 {
-  using_history ();
-  if (saved_line_for_history)
-    _rl_free_history_entry (saved_line_for_history);
+  register int i;
+  char *string;
 
-  saved_line_for_history = (HIST_ENTRY *)NULL;
-}
+  if (count <= 0)
+    return 0;
 
-/* Free the contents (and containing structure) of a HIST_ENTRY. */
-void
-_rl_free_history_entry (entry)
-     HIST_ENTRY *entry;
-{
-  if (!entry)
-    return;
-  if (entry->line)
-    free (entry->line);
-  free (entry);
-}
+  /* 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);
 
-/* Perhaps put back the current line if it has changed. */
-maybe_replace_line ()
-{
-  HIST_ENTRY *temp = current_history ();
+      for (i = 0; i < count; i++)
+       string[i] = c;
 
-  /* 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);
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+
+      return 0;
     }
-  return 0;
-}
 
-/* Put back the saved_line_for_history if there is one. */
-maybe_unsave_line ()
-{
-  if (saved_line_for_history)
+  if (count > 1024)
     {
-      int line_len;
+      int decreaser;
+      char str[1024+1];
 
-      line_len = strlen (saved_line_for_history->line);
+      for (i = 0; i < 1024; i++)
+       str[i] = c;
 
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
 
-      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);
+      return 0;
     }
-  else
-    ding ();
-  return 0;
-}
 
-/* Save the current line in saved_line_for_history. */
-maybe_save_line ()
-{
-  if (!saved_line_for_history)
+  /* 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
     {
-      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;
+      /* Inserting a single character. */
+      char str[2];
+
+      str[1] = '\0';
+      str[0] = c;
+      rl_insert_text (str);
     }
   return 0;
 }
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     History Commands                            */
-/*                                                                 */
-/* **************************************************************** */
 
-/* Meta-< goes to the start of the history. */
-rl_beginning_of_history (count, key)
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
      int count, key;
 {
-  return (rl_get_previous_history (1 + where_history ()));
+  int c;
+
+#if defined (HANDLE_SIGNALS)
+  _rl_disable_tty_signals ();
+#endif
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_SIGNALS)
+  _rl_restore_tty_signals ();
+#endif
+
+  return (rl_insert (count, c));  
 }
 
-/* Meta-> goes to the end of the history.  (The current line). */
-rl_end_of_history (count, key)
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
      int count, key;
 {
-  maybe_replace_line ();
-  using_history ();
-  maybe_unsave_line ();
-  return 0;
+  return (rl_insert (count, '\t'));
 }
 
-/* Move down to the next history line. */
-rl_get_next_history (count, key)
+/* 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;
 {
-  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+  rl_done = 1;
+  RL_SETSTATE(RL_STATE_DONE);
 
-  if (count < 0)
-    return (rl_get_previous_history (-count));
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
 
-  if (!count)
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
     return 0;
 
-  maybe_replace_line ();
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
 
-  while (count)
+/* 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)
     {
-      temp = next_history ();
-      if (!temp)
-       break;
-      --count;
+      rl_delete (-count, key);
+      return 0;
     }
 
-  if (!temp)
-    maybe_unsave_line ();
-  else
+  if (!rl_point)
     {
-      int line_len;
-
-      line_len = strlen (temp->line);
+      rl_ding ();
+      return -1;
+    }
 
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
+  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);
 
-      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 */
+      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;
 }
 
-/* Get the previous item out of our interactive history, making it the current
-   line.  If there is no previous history, just ding. */
-rl_get_previous_history (count, key)
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
      int count, key;
 {
-  HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
-  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
-
   if (count < 0)
-    return (rl_get_next_history (-count));
-
-  if (!count)
-    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 ();
+    return (rl_rubout (-count, key));
 
-  while (count)
+  if (rl_point == rl_end)
     {
-      temp = previous_history ();
-      if (!temp)
-       break;
-      else
-       old_temp = temp;
-      --count;
+      rl_ding ();
+      return -1;
     }
 
-  /* 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)
-    ding ();
-  else
+  if (count > 1 || rl_explicit_arg)
     {
-      int line_len;
-
-      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 */
+      int orig_point = rl_point;
+      rl_forward (count, key);
+      rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+      return 0;
     }
-  return 0;
+  else
+    return (rl_delete_text (rl_point, rl_point + 1));
 }
 
-/* Make C be the next command to be executed. */
-rl_execute_next (c)
-     int c;
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_rubout (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
 {
-  rl_pending_input = c;
-  return 0;
-}
+  int start = rl_point;
 
-/* **************************************************************** */
-/*                                                                 */
-/*                The Mark and the Region.                         */
-/*                                                                 */
-/* **************************************************************** */
+  while (rl_point && whitespace (the_line[rl_point - 1]))
+    rl_point--;
 
-/* Set the mark at POSITION. */
-rl_set_mark (position)
-     int position;
-{
-  if (position > rl_end)
-    return -1;
+  start = rl_point;
 
-  rl_mark = position;
+  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;
 }
 
-/* Exchange the position of mark and point. */
-rl_exchange_mark_and_point (count, key)
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
      int count, key;
 {
-  if (rl_mark > rl_end)
-    rl_mark = -1;
-
-  if (rl_mark == -1)
-    {
-      ding ();
-      return -1;
-    }
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
   else
-    {
-      int temp = rl_point;
+    return (rl_delete (count, key));
+}
 
-      rl_point = rl_mark;
-      rl_mark = temp;
-    }
-  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);
 }
 
-\f
 /* **************************************************************** */
 /*                                                                 */
-/*                     Killing Mechanism                           */
+/*                     Changing Case                               */
 /*                                                                 */
 /* **************************************************************** */
 
-/* What we assume for a max number of kills. */
-#define DEFAULT_MAX_KILLS 10
-
-/* The real variable to look at to find out when to flush kills. */
-int rl_max_kills =  DEFAULT_MAX_KILLS;
-
-/* Where to store killed text. */
-char **rl_kill_ring = (char **)NULL;
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
 
-/* Where we are in the kill ring. */
-int rl_kill_index = 0;
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
 
-/* How many slots we have in the kill ring. */
-int rl_kill_ring_length = 0;
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
 
-/* How to say that you only want to save a certain amount
-   of kill material. */
-rl_set_retained_kills (num)
-     int num;
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
 {
 return 0;
return (rl_change_case (count, CapCase));
 }
 
-/* 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 text is appended, otherwise prepended.  If the
-   last command was not a kill command, then a new slot is made for
-   this kill. */
-rl_kill_text (from, to)
-     int from, to;
+/* 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;
 {
-  int slot;
-  char *text;
+  register int start, end;
+  int inword, c;
 
-  /* Is there anything to kill? */
-  if (from == to)
-    {
-      last_command_was_kill++;
-      return 0;
-    }
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
 
-  text = rl_copy_text (from, to);
+  if (count < 0)
+    SWAP (start, end);
 
-  /* Delete the copied text from the line. */
-  rl_delete_text (from, to);
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
 
-  /* First, find the slot to work with. */
-  if (!last_command_was_kill)
+  for (inword = 0; start < end; start++)
     {
-      /* Get a new slot.  */
-      if (!rl_kill_ring)
-       {
-         /* If we don't have any defined, then make one. */
-         rl_kill_ring = (char **)
-           xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
-         rl_kill_ring[slot = 0] = (char *)NULL;
-       }
-      else
+      c = the_line[start];
+      switch (op)
        {
-         /* We have to add a new slot on the end, unless we have
-            exceeded the max limit for remembering kills. */
-         slot = rl_kill_ring_length;
-         if (slot == rl_max_kills)
-           {
-             register int i;
-             free (rl_kill_ring[0]);
-             for (i = 0; i < slot; i++)
-               rl_kill_ring[i] = rl_kill_ring[i + 1];
-           }
-         else
-           {
-             slot = rl_kill_ring_length += 1;
-             rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
-           }
-         rl_kill_ring[--slot] = (char *)NULL;
-       }
-    }
-  else
-    slot = rl_kill_ring_length - 1;
+       case UpCase:
+         the_line[start] = _rl_to_upper (c);
+         break;
 
-  /* If the last command was a kill, prepend or append. */
-  if (last_command_was_kill && rl_editing_mode != vi_mode)
-    {
-      char *old = rl_kill_ring[slot];
-      char *new = xmalloc (1 + strlen (old) + strlen (text));
+       case DownCase:
+         the_line[start] = _rl_to_lower (c);
+         break;
 
-      if (from < to)
-       {
-         strcpy (new, old);
-         strcat (new, text);
-       }
-      else
-       {
-         strcpy (new, text);
-         strcat (new, old);
+       case CapCase:
+         the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
+         inword = rl_alphabetic (the_line[start]);
+         break;
+
+       default:
+         rl_ding ();
+         return -1;
        }
-      free (old);
-      free (text);
-      rl_kill_ring[slot] = new;
-    }
-  else
-    {
-      rl_kill_ring[slot] = text;
     }
-  rl_kill_index = slot;
-  last_command_was_kill++;
+  rl_point = end;
   return 0;
 }
 
-/* Now REMEMBER!  In order to do prepending or appending correctly, kill
-   commands always make rl_point's original position be the FROM argument,
-   and rl_point's extent be the TO argument. */
-
 /* **************************************************************** */
 /*                                                                 */
-/*                     Killing Commands                            */
+/*                     Transposition                               */
 /*                                                                 */
 /* **************************************************************** */
 
-/* Delete the word at point, saving the text in the kill ring. */
-rl_kill_word (count, key)
+/* 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 < 0)
-    return (rl_backward_kill_word (-count));
-  else
-    {
-      rl_forward_word (count);
+  if (!count)
+    return 0;
 
-      if (rl_point != orig_point)
-       rl_kill_text (orig_point, rl_point);
+  /* 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))
+    {
+      rl_ding ();
       rl_point = orig_point;
+      return -1;
     }
-  return 0;
-}
-
-/* Rubout the word before point, placing it on the kill ring. */
-rl_backward_kill_word (count, ignore)
-     int count, ignore;
-{
-  int orig_point = rl_point;
 
-  if (count < 0)
-    return (rl_kill_word (-count));
-  else
-    {
-      rl_backward_word (count);
-
-      if (rl_point != orig_point)
-       rl_kill_text (orig_point, rl_point);
-    }
-  return 0;
-}
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
 
-/* Kill from here to the end of the line.  If DIRECTION is negative, kill
-   back to the line start instead. */
-rl_kill_line (direction, ignore)
-     int direction, ignore;
-{
-  int orig_point = rl_point;
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
 
-  if (direction < 0)
-    return (rl_backward_kill_line (1));
-  else
-    {
-      rl_end_of_line (1, ignore);
-      if (orig_point != rl_point)
-       rl_kill_text (orig_point, rl_point);
-      rl_point = orig_point;
-    }
-  return 0;
-}
+  /* 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);
 
-/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
-   forwards to the line end instead. */
-rl_backward_kill_line (direction, ignore)
-     int direction, ignore;
-{
-  int orig_point = rl_point;
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
 
-  if (direction < 0)
-    return (rl_kill_line (1));
-  else
-    {
-      if (!rl_point)
-       ding ();
-      else
-       {
-         rl_beg_of_line (1, ignore);
-         rl_kill_text (orig_point, rl_point);
-       }
-    }
-  return 0;
-}
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
 
-/* Kill the whole line, no matter where point is. */
-rl_kill_full_line (count, ignore)
-     int count, ignore;
-{
-  rl_begin_undo_group ();
-  rl_point = 0;
-  rl_kill_text (rl_point, rl_end);
+  /* I think that does it. */
   rl_end_undo_group ();
-  return 0;
-}
-
-/* Yank back the last killed text.  This ignores arguments. */
-rl_yank (count, ignore)
-     int count, ignore;
-{
-  if (!rl_kill_ring)
-    {
-      rl_abort (count, ignore);
-      return -1;
-    }
+  free (word1);
+  free (word2);
 
-  rl_set_mark (rl_point);
-  rl_insert_text (rl_kill_ring[rl_kill_index]);
   return 0;
 }
 
-/* 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. */
-rl_yank_pop (count, key)
+/* 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;
 {
-  int l;
-
-  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
-      !rl_kill_ring)
-    {
-      rl_abort (1, key);
-      return -1;
-    }
-
-  l = strlen (rl_kill_ring[rl_kill_index]);
-  if (((rl_point - l) >= 0) &&
-      (strncmp (the_line + (rl_point - l),
-               rl_kill_ring[rl_kill_index], l) == 0))
-    {
-      rl_delete_text ((rl_point - l), rl_point);
-      rl_point -= l;
-      rl_kill_index--;
-      if (rl_kill_index < 0)
-       rl_kill_index = rl_kill_ring_length - 1;
-      rl_yank (1, 0);
-      return 0;
-    }
-  else
-    {
-      rl_abort (1, key);
-      return -1;
-    }
-}
-
-/* Yank the COUNTth argument from the previous history line. */
-rl_yank_nth_arg (count, ignore)
-     int count, ignore;
-{
-  register HIST_ENTRY *entry = previous_history ();
-  char *arg;
+  char dummy[2];
 
-  if (entry)
-    next_history ();
-  else
-    {
-      ding ();
-      return -1;
-    }
+  if (!count)
+    return 0;
 
-  arg = history_arg_extract (count, count, entry->line);
-  if (!arg || !*arg)
+  if (!rl_point || rl_end < 2)
     {
-      ding ();
+      rl_ding ();
       return -1;
     }
 
   rl_begin_undo_group ();
 
-#if defined (VI_MODE)
-  /* Vi mode always inserts a space before yanking the argument, and it
-     inserts it right *after* rl_point. */
-  if (rl_editing_mode == vi_mode)
+  if (rl_point == rl_end)
     {
-      rl_vi_append_mode ();
-      rl_insert_text (" ");
+      --rl_point;
+      count = 1;
     }
-#endif /* VI_MODE */
-
-  rl_insert_text (arg);
-  free (arg);
-
-  rl_end_undo_group ();
-  return 0;
-}
+  rl_point--;
 
-/* Yank the last argument from the previous history line.  This `knows'
-   how rl_yank_nth_arg treats a count of `$'.  With an argument, this
-   behaves the same as rl_yank_nth_arg. */
-int
-rl_yank_last_arg (count, key)
-     int count, key;
-{
-  if (rl_explicit_arg)
-    return (rl_yank_nth_arg (count, key));
-  else
-    return (rl_yank_nth_arg ('$', key));
-}
+  dummy[0] = the_line[rl_point];
+  dummy[1] = '\0';
 
-/* How to toggle back and forth between editing modes. */
-rl_vi_editing_mode (count, key)
-     int count, key;
-{
-#if defined (VI_MODE)
-  rl_editing_mode = vi_mode;
-  rl_vi_insertion_mode ();
-  return 0;
-#endif /* VI_MODE */
-}
+  rl_delete_text (rl_point, rl_point + 1);
 
-rl_emacs_editing_mode (count, key)
-     int count, key;
-{
-  rl_editing_mode = emacs_mode;
-  _rl_keymap = emacs_standard_keymap;
+  rl_point += count;
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+
+  rl_end_undo_group ();
   return 0;
 }
 
-\f
 /* **************************************************************** */
 /*                                                                 */
-/*                     USG (System V) Support                      */
+/*                     Character Searching                         */
 /*                                                                 */
 /* **************************************************************** */
 
 int
-rl_getc (stream)
-     FILE *stream;
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
 {
-  int result;
-  unsigned char c;
+  int pos, inc;
 
-#if defined (__GO32__)
-  if (isatty (0))
-    return (getkey () & 0x7F);
-#endif /* __GO32__ */
-
-  while (1)
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
     {
-      result = read (fileno (stream), &c, sizeof (unsigned char));
-
-      if (result == sizeof (unsigned char))
-       return (c);
-
-      /* If zero characters are returned, then the file that we are
-        reading from is empty!  Return EOF in that case. */
-      if (result == 0)
-       return (EOF);
-
-#if defined (EWOULDBLOCK)
-      if (errno == EWOULDBLOCK)
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
        {
-         int flags;
-
-         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
-           return (EOF);
-         if (flags & O_NDELAY)
-           {
-             flags &= ~O_NDELAY;
-             fcntl (fileno (stream), F_SETFL, flags);
-             continue;
-           }
-         continue;
+         rl_ding ();
+         return -1;
        }
-#endif /* EWOULDBLOCK */
 
-#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK)
-      if (errno == EAGAIN)
+      pos += inc;
+      do
        {
-         int flags;
-
-         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
-           return (EOF);
-         if (flags & O_NONBLOCK)
+         if (rl_line_buffer[pos] == schar)
            {
-             flags &= ~O_NONBLOCK;
-             fcntl (fileno (stream), F_SETFL, flags);
-             continue;
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? pos + 1 : pos;
+             else
+               rl_point = (dir == FTO) ? pos - 1 : pos;
+             break;
            }
        }
-#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
-
-#if !defined (__GO32__)
-      /* If the error that we received was SIGINT, then try again,
-        this is simply an interrupted system call to read ().
-        Otherwise, some error ocurred, also signifying EOF. */
-      if (errno != EINTR)
-       return (EOF);
-#endif /* !__GO32__ */
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
     }
+  return (0);
 }
 
-#if !defined (SHELL)
-#ifdef savestring
-#undef savestring
-#endif
-/* Backwards compatibilty, now that savestring has been removed from
-   all `public' readline header files. */
-char *
-savestring (s)
-     char *s;
+/* 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;
 {
-  return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
 }
-#endif
 
-/* Function equivalents for the macros defined in chartypes.h. */
-#undef uppercase_p
 int
-uppercase_p (c)
-     int c;
+rl_char_search (count, key)
+     int count, key;
 {
-  return (isupper (c));
+  return (_rl_char_search (count, FFIND, BFIND));
 }
 
-#undef lowercase_p
 int
-lowercase_p (c)
-     int c;
+rl_backward_char_search (count, key)
+     int count, key;
 {
-  return (islower (c));
+  return (_rl_char_search (count, BFIND, FFIND));
 }
 
-#undef pure_alphabetic
-int
-pure_alphabetic (c)
-     int c;
+/* **************************************************************** */
+/*                                                                 */
+/*                     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 *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+static void
+start_using_history ()
 {
-  return (isupper (c) || islower (c));
+  using_history ();
+  if (_rl_saved_line_for_history)
+    _rl_free_history_entry (_rl_saved_line_for_history);
+
+  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
 }
 
-#undef digit_p
-int
-digit_p (c)
-     int c;
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+void
+_rl_free_history_entry (entry)
+     HIST_ENTRY *entry;
 {
-  return (isdigit (c));
+  if (entry == 0)
+    return;
+  if (entry->line)
+    free (entry->line);
+  free (entry);
 }
 
-#undef to_lower
+/* Perhaps put back the current line if it has changed. */
 int
-to_lower (c)
-     int c;
+rl_maybe_replace_line ()
 {
-  return (isupper (c) ? tolower (c) : c);
+  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, (histdata_t)rl_undo_list);
+      free (temp->line);
+      free (temp);
+    }
+  return 0;
 }
 
-#undef to_upper
+/* Restore the _rl_saved_line_for_history if there is one. */
 int
-to_upper (c)
-     int c;
+rl_maybe_unsave_line ()
 {
-  return (islower (c) ? toupper (c) : c);
+  int line_len;
+
+  if (_rl_saved_line_for_history)
+    {
+      line_len = strlen (_rl_saved_line_for_history->line);
+
+      if (line_len >= rl_line_buffer_len)
+       rl_extend_line_buffer (line_len);
+
+      strcpy (the_line, _rl_saved_line_for_history->line);
+      rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
+      _rl_free_history_entry (_rl_saved_line_for_history);
+      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+      rl_end = rl_point = strlen (the_line);
+    }
+  else
+    rl_ding ();
+  return 0;
 }
 
-#undef digit_value
+/* Save the current line in _rl_saved_line_for_history. */
 int
-digit_value (c)
-     int c;
+rl_maybe_save_line ()
 {
-  return (isdigit (c) ? c - '0' : c);
+  if (_rl_saved_line_for_history == 0)
+    {
+      _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+      _rl_saved_line_for_history->line = savestring (the_line);
+      _rl_saved_line_for_history->data = (char *)rl_undo_list;
+    }
+  return 0;
 }
 
-#if defined (STATIC_MALLOC)
-\f
+int
+_rl_free_saved_history_line ()
+{
+  if (_rl_saved_line_for_history)
+    {
+      _rl_free_history_entry (_rl_saved_line_for_history);
+      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+    }
+  return 0;
+}      
+
 /* **************************************************************** */
 /*                                                                 */
-/*                     xmalloc and xrealloc ()                     */
+/*                     History Commands                            */
 /*                                                                 */
 /* **************************************************************** */
 
-static void memory_error_and_abort ();
-
-static char *
-xmalloc (bytes)
-     int bytes;
+/* Meta-< goes to the start of the history. */
+int
+rl_beginning_of_history (count, key)
+     int count, key;
 {
-  char *temp = (char *)malloc (bytes);
+  return (rl_get_previous_history (1 + where_history (), key));
+}
 
-  if (!temp)
-    memory_error_and_abort ();
-  return (temp);
+/* Meta-> goes to the end of the history.  (The current line). */
+int
+rl_end_of_history (count, key)
+     int count, key;
+{
+  rl_maybe_replace_line ();
+  using_history ();
+  rl_maybe_unsave_line ();
+  return 0;
 }
 
-static char *
-xrealloc (pointer, bytes)
-     char *pointer;
-     int bytes;
+/* Move down to the next history line. */
+int
+rl_get_next_history (count, key)
+     int count, key;
 {
-  char *temp;
+  HIST_ENTRY *temp;
+  int line_len;
+
+  if (count < 0)
+    return (rl_get_previous_history (-count, key));
+
+  if (count == 0)
+    return 0;
+
+  rl_maybe_replace_line ();
+
+  temp = (HIST_ENTRY *)NULL;
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+       break;
+      --count;
+    }
 
-  if (!pointer)
-    temp = (char *)malloc (bytes);
+  if (temp == 0)
+    rl_maybe_unsave_line ();
   else
-    temp = (char *)realloc (pointer, bytes);
+    {
+      line_len = strlen (temp->line);
 
-  if (!temp)
-    memory_error_and_abort ();
+      if (line_len >= rl_line_buffer_len)
+       rl_extend_line_buffer (line_len);
 
-  return (temp);
+      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;
 }
 
-static void
-memory_error_and_abort ()
+/* 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;
 {
-  fprintf (stderr, "readline: Out of virtual memory!\n");
-  abort ();
+  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. */
+  rl_maybe_save_line ();
+
+  /* If the current line has changed, save the changes. */
+  rl_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)
+    rl_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;
 }
-#endif /* STATIC_MALLOC */
 
-\f
 /* **************************************************************** */
 /*                                                                 */
-/*                     Testing Readline                            */
+/*                The Mark and the Region.                         */
 /*                                                                 */
 /* **************************************************************** */
 
-#if defined (TEST)
-
-main ()
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
 {
-  HIST_ENTRY **history_list ();
-  char *temp = (char *)NULL;
-  char *prompt = "readline% ";
-  int done = 0;
-
-  while (!done)
-    {
-      temp = readline (prompt);
+  if (position > rl_end)
+    return -1;
 
-      /* Test for EOF. */
-      if (!temp)
-       exit (1);
+  rl_mark = position;
+  return 0;
+}
 
-      /* If there is anything on the line, print it and remember it. */
-      if (*temp)
-       {
-         fprintf (stderr, "%s\r\n", temp);
-         add_history (temp);
-       }
+/* 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));
+}
 
-      /* Check for `command' that we handle. */
-      if (strcmp (temp, "quit") == 0)
-       done = 1;
+/* 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 (strcmp (temp, "list") == 0)
-       {
-         HIST_ENTRY **list = history_list ();
-         register int i;
-         if (list)
-           {
-             for (i = 0; list[i]; i++)
-               {
-                 fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
-                 free (list[i]->line);
-               }
-             free (list);
-           }
-       }
-      free (temp);
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return -1;
     }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
 }
 
-#endif /* TEST */
+/* **************************************************************** */
+/*                                                                 */
+/*                         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;
+}
 
-\f
-/*
- * Local variables:
- * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
- * end:
- */
+int
+rl_emacs_editing_mode (count, key)
+     int count, key;
+{
+  rl_editing_mode = emacs_mode;
+  _rl_keymap = emacs_standard_keymap;
+  return 0;
+}