/* readline.c -- a general facility for reading lines of input
with emacs style editing and completion. */
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
/* System-specific feature definitions and include files. */
#include "rldefs.h"
-#include "rlmbutil.h"
#if defined (__EMX__)
# define INCL_DOSPROCESS
#include "xmalloc.h"
#ifndef RL_LIBRARY_VERSION
-# define RL_LIBRARY_VERSION "4.3"
+# define RL_LIBRARY_VERSION "4.1"
#endif
-#ifndef RL_READLINE_VERSION
-# define RL_READLINE_VERSION 0x0403
-#endif
-
-extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
+/* 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. */
-static char *readline_internal PARAMS((void));
-static void readline_initialize_everything PARAMS((void));
+void _rl_free_history_entry __P((HIST_ENTRY *));
-static void bind_arrow_keys_internal PARAMS((Keymap));
-static void bind_arrow_keys PARAMS((void));
+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 void readline_default_bindings PARAMS((void));
+static void readline_default_bindings __P((void));
/* **************************************************************** */
/* */
/* */
/* **************************************************************** */
-const char *rl_library_version = RL_LIBRARY_VERSION;
+char *rl_library_version = RL_LIBRARY_VERSION;
-int rl_readline_version = RL_READLINE_VERSION;
-
-/* True if this is `real' readline as opposed to some stub substitute. */
int rl_gnu_readline_p = 1;
/* A pointer to the keymap that is currently in use.
/* The current style of editing. */
int rl_editing_mode = emacs_mode;
-/* The current insert mode: input (the default) or overwrite */
-int rl_insert_mode = RL_IM_DEFAULT;
-
/* Non-zero if we called this function from _rl_dispatch(). It's present
so functions can find out whether they were called from a key binding
or directly from an application. */
/* Non-zero means we have been called at least once before. */
static int rl_initialized;
-#if 0
/* If non-zero, this program is running in an EMACS buffer. */
static int running_in_emacs;
-#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;
int rl_done;
/* The last function executed by readline. */
-rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL;
+Function *rl_last_func = (Function *)NULL;
/* Top level environment for readline_internal (). */
procenv_t readline_top_level;
FILE *rl_instream = (FILE *)NULL;
FILE *rl_outstream = (FILE *)NULL;
-/* Non-zero means echo characters as they are read. Defaults to no echo;
- set to 1 if there is a controlling terminal, we can get its attributes,
- and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings
- for the code that sets it. */
-int readline_echoing_p = 0;
+/* Non-zero means echo characters as they are read. */
+int readline_echoing_p = 1;
/* Current prompt. */
-char *rl_prompt = (char *)NULL;
+char *rl_prompt;
int rl_visible_prompt_length = 0;
/* Set to non-zero by calling application if it has already printed rl_prompt
/* If non-zero, then this is the address of a function to call just
before readline_internal_setup () prints the first prompt. */
-rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
+Function *rl_startup_hook = (Function *)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;
+Function *rl_pre_input_hook = (Function *)NULL;
/* What we use internally. You should always refer to RL_LINE_BUFFER. */
static char *the_line;
int rl_pending_input = 0;
/* Pointer to a useful terminal name. */
-const char *rl_terminal_name = (const char *)NULL;
+char *rl_terminal_name = (char *)NULL;
/* Non-zero means to always use horizontal scrolling in line display. */
int _rl_horizontal_scroll_mode = 0;
char *rl_line_buffer = (char *)NULL;
int rl_line_buffer_len = 0;
-/* Forward declarations used by the display, termcap, and history code. */
+/* Forward declarations used by the display and termcap code. */
/* **************************************************************** */
/* */
/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
int _rl_meta_flag = 0; /* Forward declaration */
-/* Set up the prompt and expand it. Called from readline() and
- rl_callback_handler_install (). */
-int
-rl_set_prompt (prompt)
- const char *prompt;
-{
- FREE (rl_prompt);
- rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
-
- rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
- return 0;
-}
-
/* Read a line of input. Prompt with PROMPT. An empty PROMPT means
none. A return value of NULL means that EOF was encountered. */
char *
readline (prompt)
- const char *prompt;
+ char *prompt;
{
char *value;
+ rl_prompt = prompt;
+
/* If we are at EOF return a NULL string. */
if (rl_pending_input == EOF)
{
- rl_clear_pending_input ();
+ rl_pending_input = 0;
return ((char *)NULL);
}
- rl_set_prompt (prompt);
+ rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
rl_initialize ();
(*rl_prep_term_function) (_rl_meta_flag);
if (rl_startup_hook)
(*rl_startup_hook) ();
- /* If we're not echoing, we still want to at least print a prompt, because
- rl_redisplay will not do it for us. If the calling application has a
- custom redisplay function, though, let that function handle it. */
- if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
+ if (readline_echoing_p == 0)
{
if (rl_prompt && rl_already_prompted == 0)
{
else
rl_on_new_line ();
(*rl_redisplay_function) ();
- }
-
#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode (1, 0);
+ if (rl_editing_mode == vi_mode)
+ rl_vi_insertion_mode (1, 0);
#endif /* VI_MODE */
+ }
if (rl_pre_input_hook)
(*rl_pre_input_hook) ();
/* 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 ();
-
- /* Restore normal cursor, if available. */
- _rl_set_insert_mode (RL_IM_INSERT, 0);
+ free_undo_list ();
return (eof ? (char *)NULL : savestring (the_line));
}
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)
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;
void
_rl_init_line_state ()
{
- rl_point = rl_end = rl_mark = 0;
+ rl_point = rl_end = 0;
the_line = rl_line_buffer;
the_line[0] = 0;
}
_rl_dispatch (key, map)
register int key;
Keymap map;
-{
- return _rl_dispatch_subseq (key, map, 0);
-}
-
-int
-_rl_dispatch_subseq (key, map, got_subseq)
- register int key;
- Keymap map;
- int got_subseq;
{
int r, newkey;
char *macro;
- rl_command_func_t *func;
+ Function *func;
if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
{
if (map[ESC].type == ISKMAP)
{
- if (RL_ISSTATE (RL_STATE_MACRODEF))
+ if (_rl_defining_kbd_macro)
_rl_add_macro_char (ESC);
map = FUNCTION_TO_KEYMAP (map, ESC);
key = UNMETA (key);
return (_rl_dispatch (key, map));
}
else
- rl_ding ();
+ ding ();
return 0;
}
- if (RL_ISSTATE (RL_STATE_MACRODEF))
+ if (_rl_defining_kbd_macro)
_rl_add_macro_char (key);
r = 0;
{
case ISFUNC:
func = map[key].function;
- if (func)
+ if (func != (Function *)NULL)
{
/* Special case rl_do_lowercase_version (). */
if (func == rl_do_lowercase_version)
#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)
+ if (!rl_pending_input && map[key].function != rl_digit_argument)
rl_last_func = map[key].function;
}
- else if (map[ANYOTHERKEY].function)
- {
- /* OK, there's no function bound in this map, but there is a
- shadow function that was overridden when the current keymap
- was created. Return -2 to note that. */
- _rl_unget_char (key);
- return -2;
- }
- else if (got_subseq)
- {
- /* Return -1 to note that we're in a subsequence, but we don't
- have a matching key, nor was one overridden. This means
- we need to back up the recursion chain and find the last
- subsequence that is bound to a function. */
- _rl_unget_char (key);
- return -1;
- }
else
{
_rl_abort_internal ();
break;
case ISKMAP:
- if (map[key].function != 0)
+ if (map[key].function != (Function *)NULL)
{
-#if defined (VI_MODE)
- /* The only way this test will be true is if a subsequence has been
- bound starting with ESC, generally the arrow keys. What we do is
- check whether there's input in the queue, which there generally
- will be if an arrow key has been pressed, and, if there's not,
- just dispatch to (what we assume is) rl_vi_movement_mode right
- away. This is essentially an input test with a zero timeout. */
- if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
- && _rl_input_queued (0) == 0)
- return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
-#endif
-
rl_key_sequence_length++;
-
- 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);
-
- if (newkey < 0)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function);
-
- if (r == -2)
- /* We didn't match anything, and the keymap we're indexed into
- shadowed a function previously bound to that prefix. Call
- the function. The recursive call to _rl_dispatch_subseq has
- already taken care of pushing any necessary input back onto
- the input queue with _rl_unget_char. */
- r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
- else if (r && map[ANYOTHERKEY].function)
- {
- /* We didn't match (r is probably -1), so return something to
- tell the caller that it should try ANYOTHERKEY for an
- overridden function. */
- _rl_unget_char (key);
- return -2;
- }
- else if (r && got_subseq)
- {
- /* OK, back up the chain. */
- _rl_unget_char (key);
- return -1;
- }
+ r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
}
else
{
break;
case ISMACR:
- if (map[key].function != 0)
+ if (map[key].function != (Function *)NULL)
{
macro = savestring ((char *)map[key].function);
_rl_with_macro_input (macro);
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);
}
/* Initalize the current line information. */
/* We aren't done yet. We haven't even gotten started yet! */
rl_done = 0;
- RL_UNSETSTATE(RL_STATE_DONE);
/* Tell the history routines what is going on. */
- _rl_start_using_history ();
+ 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 = (rl_command_func_t *)NULL;
+ rl_last_func = (Function *)NULL;
/* Parsing of key-bindings begins in an enabled state. */
_rl_parsing_conditionalized_out = 0;
_rl_vi_initialize_line ();
#endif
- /* Each line starts in insert mode (the default). */
- _rl_set_insert_mode (RL_IM_DEFAULT, 1);
-
return 0;
}
#endif
#endif
-#if 0
- /* Find out if we are running in Emacs -- UNUSED. */
- running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
-#endif
+ /* Find out if we are running in Emacs. */
+ running_in_emacs = get_env_value ("EMACS") != (char *)0;
/* Set up input and output if they are not already set up. */
if (!rl_instream)
/* Allocate data structures. */
if (rl_line_buffer == 0)
- rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+ rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
/* Initialize the terminal interface. */
- if (rl_terminal_name == 0)
- rl_terminal_name = sh_get_env_value ("TERM");
- _rl_init_terminal_io (rl_terminal_name);
+ _rl_init_terminal_io ((char *)NULL);
/* Bind tty characters to readline functions. */
readline_default_bindings ();
/* XXX */
if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
{
- _rl_screenwidth--;
- _rl_screenchars -= _rl_screenheight;
+ screenwidth--;
+ screenchars -= screenheight;
}
/* Override the effect of any `set keymap' assignments in the
static void
readline_default_bindings ()
{
- rl_tty_set_default_bindings (_rl_keymap);
+ rltty_set_default_bindings (_rl_keymap);
}
-/* Bind some common arrow key sequences in MAP. */
static void
-bind_arrow_keys_internal (map)
- Keymap map;
+bind_arrow_keys_internal ()
{
- Keymap xkeymap;
-
- xkeymap = _rl_keymap;
- _rl_keymap = map;
+ Function *f;
#if defined (__MSDOS__)
- _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
- _rl_bind_if_unbound ("\033[0B", rl_backward_char);
- _rl_bind_if_unbound ("\033[0C", rl_forward_char);
- _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
+ 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)
+ {
+ _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
+ _rl_bind_if_unbound ("\033[B", rl_get_next_history);
+ _rl_bind_if_unbound ("\033[C", rl_forward);
+ _rl_bind_if_unbound ("\033[D", rl_backward);
+ }
- _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
- _rl_bind_if_unbound ("\033[B", rl_get_next_history);
- _rl_bind_if_unbound ("\033[C", rl_forward_char);
- _rl_bind_if_unbound ("\033[D", rl_backward_char);
- _rl_bind_if_unbound ("\033[H", rl_beg_of_line);
- _rl_bind_if_unbound ("\033[F", rl_end_of_line);
-
- _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
- _rl_bind_if_unbound ("\033OB", rl_get_next_history);
- _rl_bind_if_unbound ("\033OC", rl_forward_char);
- _rl_bind_if_unbound ("\033OD", rl_backward_char);
- _rl_bind_if_unbound ("\033OH", rl_beg_of_line);
- _rl_bind_if_unbound ("\033OF", rl_end_of_line);
-
- _rl_keymap = xkeymap;
+ f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
+ if (!f || f == rl_do_lowercase_version)
+ {
+ _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
+ _rl_bind_if_unbound ("\033OB", rl_get_next_history);
+ _rl_bind_if_unbound ("\033OC", rl_forward);
+ _rl_bind_if_unbound ("\033OD", rl_backward);
+ }
}
-/* Try and bind the common arrow key prefixes after giving termcap and
+/* Try and bind the common arrow key prefix after giving termcap and
the inputrc file a chance to bind them and create `real' keymaps
for the arrow key prefix. */
static void
bind_arrow_keys ()
{
- bind_arrow_keys_internal (emacs_standard_keymap);
+ Keymap xkeymap;
+
+ xkeymap = _rl_keymap;
+
+ _rl_keymap = emacs_standard_keymap;
+ bind_arrow_keys_internal ();
#if defined (VI_MODE)
- bind_arrow_keys_internal (vi_movement_keymap);
- bind_arrow_keys_internal (vi_insertion_keymap);
+ _rl_keymap = vi_movement_keymap;
+ bind_arrow_keys_internal ();
#endif
+
+ _rl_keymap = xkeymap;
}
+\f
/* **************************************************************** */
/* */
-/* Saving and Restoring Readline's state */
+/* Numeric Arguments */
/* */
/* **************************************************************** */
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+static int
+rl_digit_loop ()
+{
+ int key, c, sawminus, sawdigits;
+
+ rl_save_prompt ();
+
+ sawminus = sawdigits = 0;
+ while (1)
+ {
+ if (rl_numeric_arg > 1000000)
+ {
+ sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
+ ding ();
+ rl_restore_prompt ();
+ rl_clear_message ();
+ return 1;
+ }
+ rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+ key = c = rl_read_key ();
+
+ /* If we see a key bound to `universal-argument' after seeing digits,
+ it ends the argument but is otherwise ignored. */
+ if (_rl_keymap[c].type == ISFUNC &&
+ _rl_keymap[c].function == rl_universal_argument)
+ {
+ if (sawdigits == 0)
+ {
+ rl_numeric_arg *= 4;
+ continue;
+ }
+ else
+ {
+ key = rl_read_key ();
+ rl_restore_prompt ();
+ rl_clear_message ();
+ return (_rl_dispatch (key, _rl_keymap));
+ }
+ }
+
+ c = UNMETA (c);
+
+ if (_rl_digit_p (c))
+ {
+ rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
+ sawdigits = rl_explicit_arg = 1;
+ }
+ else if (c == '-' && rl_explicit_arg == 0)
+ {
+ rl_numeric_arg = sawminus = 1;
+ rl_arg_sign = -1;
+ }
+ else
+ {
+ /* Make M-- command equivalent to M--1 command. */
+ if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
+ rl_explicit_arg = 1;
+ rl_restore_prompt ();
+ rl_clear_message ();
+ return (_rl_dispatch (key, _rl_keymap));
+ }
+ }
+
+ return 0;
+}
+
+/* Add the current digit to the argument in progress. */
int
-rl_save_state (sp)
- struct readline_state *sp;
+rl_digit_argument (ignore, key)
+ int ignore, key;
{
- if (sp == 0)
- return -1;
+ rl_pending_input = key;
+ return (rl_digit_loop ());
+}
- sp->point = rl_point;
- sp->end = rl_end;
- sp->mark = rl_mark;
- sp->buffer = rl_line_buffer;
- sp->buflen = rl_line_buffer_len;
- sp->ul = rl_undo_list;
- sp->prompt = rl_prompt;
-
- sp->rlstate = rl_readline_state;
- sp->done = rl_done;
- sp->kmap = _rl_keymap;
-
- sp->lastfunc = rl_last_func;
- sp->insmode = rl_insert_mode;
- sp->edmode = rl_editing_mode;
- sp->kseqlen = rl_key_sequence_length;
- sp->inf = rl_instream;
- sp->outf = rl_outstream;
- sp->pendingin = rl_pending_input;
- sp->macro = rl_executing_macro;
-
- sp->catchsigs = rl_catch_signals;
- sp->catchsigwinch = rl_catch_sigwinch;
+/* What to do when you abort reading an argument. */
+int
+rl_discard_argument ()
+{
+ ding ();
+ rl_clear_message ();
+ _rl_init_argument ();
+ return 0;
+}
- return (0);
+/* Create a default argument. */
+int
+_rl_init_argument ()
+{
+ rl_numeric_arg = rl_arg_sign = 1;
+ rl_explicit_arg = 0;
+ return 0;
}
+/* C-u, universal argument. Multiply the current argument by 4.
+ Read a key. If the key has nothing to do with arguments, then
+ dispatch on it. If the key is the abort character then abort. */
int
-rl_restore_state (sp)
- struct readline_state *sp;
+rl_universal_argument (count, key)
+ int count, key;
{
- if (sp == 0)
- return -1;
+ rl_numeric_arg *= 4;
+ return (rl_digit_loop ());
+}
- rl_point = sp->point;
- rl_end = sp->end;
- rl_mark = sp->mark;
- the_line = rl_line_buffer = sp->buffer;
- rl_line_buffer_len = sp->buflen;
- rl_undo_list = sp->ul;
- rl_prompt = sp->prompt;
-
- rl_readline_state = sp->rlstate;
- rl_done = sp->done;
- _rl_keymap = sp->kmap;
-
- rl_last_func = sp->lastfunc;
- rl_insert_mode = sp->insmode;
- rl_editing_mode = sp->edmode;
- rl_key_sequence_length = sp->kseqlen;
- rl_instream = sp->inf;
- rl_outstream = sp->outf;
- rl_pending_input = sp->pendingin;
- rl_executing_macro = sp->macro;
-
- rl_catch_signals = sp->catchsigs;
- rl_catch_sigwinch = sp->catchsigwinch;
+/* **************************************************************** */
+/* */
+/* Insert and Delete */
+/* */
+/* **************************************************************** */
- return (0);
+/* Insert a string of text into the line at point. This is the only
+ way that you should do insertion. rl_insert () calls this
+ function. */
+int
+rl_insert_text (string)
+ char *string;
+{
+ register int i, l = strlen (string);
+
+ if (rl_end + l >= rl_line_buffer_len)
+ rl_extend_line_buffer (rl_end + l);
+
+ for (i = rl_end; i >= rl_point; i--)
+ the_line[i + l] = the_line[i];
+ strncpy (the_line + rl_point, string, l);
+
+ /* Remember how to undo this if we aren't undoing something. */
+ if (!_rl_doing_an_undo)
+ {
+ /* If possible and desirable, concatenate the undos. */
+ if ((l == 1) &&
+ rl_undo_list &&
+ (rl_undo_list->what == UNDO_INSERT) &&
+ (rl_undo_list->end == rl_point) &&
+ (rl_undo_list->end - rl_undo_list->start < 20))
+ rl_undo_list->end++;
+ else
+ rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+ }
+ rl_point += l;
+ rl_end += l;
+ the_line[rl_end] = '\0';
+ return l;
+}
+
+/* Delete the string between FROM and TO. FROM is
+ inclusive, TO is not. */
+int
+rl_delete_text (from, to)
+ int from, to;
+{
+ register char *text;
+ register int diff, i;
+
+ /* Fix it if the caller is confused. */
+ if (from > to)
+ SWAP (from, to);
+
+ /* fix boundaries */
+ if (to > rl_end)
+ {
+ to = rl_end;
+ if (from > to)
+ from = to;
+ }
+
+ text = rl_copy_text (from, to);
+
+ /* Some versions of strncpy() can't handle overlapping arguments. */
+ diff = to - from;
+ for (i = from; i < rl_end - diff; i++)
+ the_line[i] = the_line[i + diff];
+
+ /* Remember how to undo this delete. */
+ if (_rl_doing_an_undo == 0)
+ rl_add_undo (UNDO_DELETE, from, to, text);
+ else
+ free (text);
+
+ rl_end -= diff;
+ the_line[rl_end] = '\0';
+ return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+ text. If FIX_MARK_TOO is non-zero, the mark is forced within line
+ boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+ do { \
+ if (x > rl_end) \
+ x = rl_end; \
+ else if (x < 0) \
+ x = 0; \
+ } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+ int fix_mark_too;
+{
+ _RL_FIX_POINT (rl_point);
+ if (fix_mark_too)
+ _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+void
+_rl_replace_text (text, start, end)
+ char *text;
+ int start, end;
+{
+ rl_begin_undo_group ();
+ rl_delete_text (start, end + 1);
+ rl_point = start;
+ rl_insert_text (text);
+ rl_end_undo_group ();
+}
+
+/* **************************************************************** */
+/* */
+/* 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.
+*/
+
+/* **************************************************************** */
+/* */
+/* Movement Commands */
+/* */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+ use said functions in other functions which do not do optimizing display.
+ I.e., you will have to update the data base for rl_redisplay, and you
+ might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT characters. */
+int
+rl_forward (count, key)
+ int count, key;
+{
+ if (count < 0)
+ rl_backward (-count, key);
+ else if (count > 0)
+ {
+ int end = rl_point + count;
+#if defined (VI_MODE)
+ int lend = rl_end - (rl_editing_mode == vi_mode);
+#else
+ int lend = rl_end;
+#endif
+
+ if (end > lend)
+ {
+ rl_point = lend;
+ ding ();
+ }
+ else
+ rl_point = end;
+ }
+
+ if (rl_end < 0)
+ rl_end = 0;
+
+ return 0;
+}
+
+/* Move backward COUNT characters. */
+int
+rl_backward (count, key)
+ int count, key;
+{
+ if (count < 0)
+ rl_forward (-count, key);
+ else if (count > 0)
+ {
+ if (rl_point < count)
+ {
+ rl_point = 0;
+ ding ();
+ }
+ else
+ rl_point -= count;
+ }
+ return 0;
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+ int count, key;
+{
+ rl_point = 0;
+ return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+ int count, key;
+{
+ rl_point = rl_end;
+ return 0;
+}
+
+/* Move forward a word. We do what Emacs does. */
+int
+rl_forward_word (count, key)
+ int count, key;
+{
+ int c;
+
+ if (count < 0)
+ {
+ rl_backward_word (-count, key);
+ return 0;
+ }
+
+ 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) == 0)
+ {
+ while (++rl_point < rl_end)
+ {
+ c = the_line[rl_point];
+ if (alphabetic (c))
+ break;
+ }
+ }
+ if (rl_point == rl_end)
+ return 0;
+ while (++rl_point < rl_end)
+ {
+ c = the_line[rl_point];
+ if (alphabetic (c) == 0)
+ break;
+ }
+ --count;
+ }
+ return 0;
+}
+
+/* Move backward a word. We do what Emacs does. */
+int
+rl_backward_word (count, key)
+ int count, key;
+{
+ int c;
+
+ if (count < 0)
+ {
+ rl_forward_word (-count, key);
+ return 0;
+ }
+
+ while (count)
+ {
+ if (!rl_point)
+ return 0;
+
+ /* Like rl_forward_word (), except that we look at the characters
+ just before point. */
+
+ c = the_line[rl_point - 1];
+ if (alphabetic (c) == 0)
+ {
+ while (--rl_point)
+ {
+ c = the_line[rl_point - 1];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ while (rl_point)
+ {
+ c = the_line[rl_point - 1];
+ if (alphabetic (c) == 0)
+ break;
+ else
+ --rl_point;
+ }
+ --count;
+ }
+ return 0;
+}
+
+/* Clear the current line. Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+ int ignore1, ignore2;
+{
+ int curr_line;
+
+ curr_line = _rl_current_display_line ();
+
+ _rl_move_vert (curr_line);
+ _rl_move_cursor_relative (0, the_line); /* XXX is this right */
+
+ _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+ the prompt and the current input line. Given a numeric arg, redraw only
+ the current line. */
+int
+rl_clear_screen (count, key)
+ int count, key;
+{
+ if (rl_explicit_arg)
+ {
+ rl_refresh_line (count, key);
+ return 0;
+ }
+
+ _rl_clear_screen (); /* calls termcap function to clear screen */
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+ int count, c;
+{
+ int ch;
+
+ ch = rl_read_key ();
+
+ switch (_rl_to_upper (ch))
+ {
+ case 'A':
+ rl_get_previous_history (count, ch);
+ break;
+
+ case 'B':
+ rl_get_next_history (count, ch);
+ break;
+
+ case 'C':
+ rl_forward (count, ch);
+ break;
+
+ case 'D':
+ rl_backward (count, ch);
+ break;
+
+ default:
+ ding ();
+ }
+ return 0;
+}
+
+\f
+/* **************************************************************** */
+/* */
+/* Text commands */
+/* */
+/* **************************************************************** */
+
+/* Insert the character C at the current location, moving point forward. */
+int
+rl_insert (count, c)
+ int count, c;
+{
+ register int i;
+ char *string;
+
+ if (count <= 0)
+ return 0;
+
+ /* If we can optimize, then do it. But don't let people crash
+ readline because of extra large arguments. */
+ if (count > 1 && count <= 1024)
+ {
+ string = xmalloc (1 + count);
+
+ for (i = 0; i < count; i++)
+ string[i] = c;
+
+ string[i] = '\0';
+ rl_insert_text (string);
+ free (string);
+
+ return 0;
+ }
+
+ if (count > 1024)
+ {
+ int decreaser;
+ char str[1024+1];
+
+ for (i = 0; i < 1024; i++)
+ str[i] = c;
+
+ while (count)
+ {
+ decreaser = (count > 1024 ? 1024 : count);
+ str[decreaser] = '\0';
+ rl_insert_text (str);
+ count -= decreaser;
+ }
+
+ return 0;
+ }
+
+ /* We are inserting a single character.
+ If there is pending input, then make a string of all of the
+ pending characters that are bound to rl_insert, and insert
+ them all. */
+ if (_rl_any_typein ())
+ _rl_insert_typein (c);
+ else
+ {
+ /* Inserting a single character. */
+ char str[2];
+
+ str[1] = '\0';
+ str[0] = c;
+ rl_insert_text (str);
+ }
+ return 0;
+}
+
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
+ int count, key;
+{
+ int c;
+
+#if defined (HANDLE_SIGNALS)
+ _rl_disable_tty_signals ();
+#endif
+ c = rl_read_key ();
+#if defined (HANDLE_SIGNALS)
+ _rl_restore_tty_signals ();
+#endif
+
+ return (rl_insert (count, c));
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+ int count, key;
+{
+ return (rl_insert (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed. We accept the whole line.
+ KEY is the key that invoked this command. I guess it could have
+ meaning in the future. */
+int
+rl_newline (count, key)
+ int count, key;
+{
+ rl_done = 1;
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ {
+ _rl_vi_done_inserting ();
+ _rl_vi_reset_last ();
+ }
+#endif /* VI_MODE */
+
+ /* If we've been asked to erase empty lines, suppress the final update,
+ since _rl_update_final calls crlf(). */
+ if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+ return 0;
+
+ if (readline_echoing_p)
+ _rl_update_final ();
+ return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+ and some characters appearing in emacs_ctlx_keymap. This function
+ is just a stub, you bind keys to it and the code in _rl_dispatch ()
+ is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+ int ignore1, ignore2;
+{
+ return 0;
+}
+
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+ int count, key;
+{
+ if (count < 0)
+ {
+ rl_delete (-count, key);
+ return 0;
+ }
+
+ if (!rl_point)
+ {
+ ding ();
+ return -1;
+ }
+
+ if (count > 1 || rl_explicit_arg)
+ {
+ int orig_point = rl_point;
+ rl_backward (count, key);
+ rl_kill_text (orig_point, rl_point);
+ }
+ else
+ {
+ int c = the_line[--rl_point];
+ rl_delete_text (rl_point, rl_point + 1);
+
+ if (rl_point == rl_end && isprint (c) && _rl_last_c_pos)
+ {
+ int l;
+ l = rl_character_len (c, rl_point);
+ _rl_erase_at_end_of_line (l);
+ }
+ }
+ return 0;
+}
+
+/* Delete the character under the cursor. Given a numeric argument,
+ kill that many characters instead. */
+int
+rl_delete (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_rubout (-count, key));
+
+ if (rl_point == rl_end)
+ {
+ ding ();
+ return -1;
+ }
+
+ if (count > 1 || rl_explicit_arg)
+ {
+ int orig_point = rl_point;
+ rl_forward (count, key);
+ rl_kill_text (orig_point, rl_point);
+ rl_point = orig_point;
+ return 0;
+ }
+ else
+ return (rl_delete_text (rl_point, rl_point + 1));
+}
+
+/* Delete 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;
+{
+ 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;
+}
+
+/* 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_end != 0 && rl_point == rl_end)
+ return (rl_possible_completions (count, key));
+ else
+ return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+ A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+ int count, key;
+{
+ rl_beg_of_line (1, key);
+ rl_insert_text (_rl_comment_begin ? _rl_comment_begin
+ : RL_COMMENT_BEGIN_DEFAULT);
+ (*rl_redisplay_function) ();
+ rl_newline (1, '\n');
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Changing Case */
+/* */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+ Change the case of COUNT words, performing OP on them.
+ OP is one of UpCase, DownCase, or CapCase.
+ If a negative argument is given, leave point where it started,
+ otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+ int count, op;
+{
+ register int start, end;
+ int inword, c;
+
+ start = rl_point;
+ rl_forward_word (count, 0);
+ end = rl_point;
+
+ if (count < 0)
+ SWAP (start, end);
+
+ /* We are going to modify some text, so let's prepare to undo it. */
+ rl_modifying (start, end);
+
+ for (inword = 0; start < end; start++)
+ {
+ c = the_line[start];
+ switch (op)
+ {
+ case UpCase:
+ the_line[start] = _rl_to_upper (c);
+ break;
+
+ case DownCase:
+ the_line[start] = _rl_to_lower (c);
+ break;
+
+ case CapCase:
+ the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
+ inword = alphabetic (the_line[start]);
+ break;
+
+ default:
+ ding ();
+ return -1;
+ }
+ }
+ rl_point = end;
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Transposition */
+/* */
+/* **************************************************************** */
+
+/* Transpose the words at point. */
+int
+rl_transpose_words (count, key)
+ int count, key;
+{
+ char *word1, *word2;
+ int w1_beg, w1_end, w2_beg, w2_end;
+ int orig_point = rl_point;
+
+ if (!count)
+ return 0;
+
+ /* Find the two words. */
+ rl_forward_word (count, key);
+ w2_end = rl_point;
+ rl_backward_word (1, key);
+ w2_beg = rl_point;
+ rl_backward_word (count, key);
+ w1_beg = rl_point;
+ rl_forward_word (1, key);
+ w1_end = rl_point;
+
+ /* Do some check to make sure that there really are two words. */
+ if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+ {
+ ding ();
+ rl_point = orig_point;
+ return -1;
+ }
+
+ /* Get the text of the words. */
+ word1 = rl_copy_text (w1_beg, w1_end);
+ word2 = rl_copy_text (w2_beg, w2_end);
+
+ /* We are about to do many insertions and deletions. Remember them
+ as one operation. */
+ rl_begin_undo_group ();
+
+ /* Do the stuff at word2 first, so that we don't have to worry
+ about word1 moving. */
+ rl_point = w2_beg;
+ rl_delete_text (w2_beg, w2_end);
+ rl_insert_text (word1);
+
+ rl_point = w1_beg;
+ rl_delete_text (w1_beg, w1_end);
+ rl_insert_text (word2);
+
+ /* This is exactly correct since the text before this point has not
+ changed in length. */
+ rl_point = w2_end;
+
+ /* I think that does it. */
+ rl_end_undo_group ();
+ free (word1);
+ free (word2);
+
+ return 0;
+}
+
+/* Transpose the characters at point. If point is at the end of the line,
+ then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+ int count, key;
+{
+ char dummy[2];
+
+ if (!count)
+ return 0;
+
+ if (!rl_point || rl_end < 2)
+ {
+ ding ();
+ return -1;
+ }
+
+ rl_begin_undo_group ();
+
+ if (rl_point == rl_end)
+ {
+ --rl_point;
+ count = 1;
+ }
+ rl_point--;
+
+ dummy[0] = the_line[rl_point];
+ dummy[1] = '\0';
+
+ rl_delete_text (rl_point, rl_point + 1);
+
+ rl_point += count;
+ _rl_fix_point (0);
+ rl_insert_text (dummy);
+
+ rl_end_undo_group ();
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Character Searching */
+/* */
+/* **************************************************************** */
+
+int
+_rl_char_search_internal (count, dir, schar)
+ int count, dir, schar;
+{
+ int pos, inc;
+
+ pos = rl_point;
+ inc = (dir < 0) ? -1 : 1;
+ while (count)
+ {
+ if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+ {
+ ding ();
+ return -1;
+ }
+
+ pos += inc;
+ do
+ {
+ if (rl_line_buffer[pos] == schar)
+ {
+ count--;
+ if (dir < 0)
+ rl_point = (dir == BTO) ? pos + 1 : pos;
+ else
+ rl_point = (dir == FTO) ? pos - 1 : pos;
+ break;
+ }
+ }
+ while ((dir < 0) ? pos-- : ++pos < rl_end);
+ }
+ return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+ FDIR is the direction to search if COUNT is non-negative; otherwise
+ the search goes in BDIR. */
+static int
+_rl_char_search (count, fdir, bdir)
+ int count, fdir, bdir;
+{
+ int c;
+
+ c = rl_read_key ();
+ if (count < 0)
+ return (_rl_char_search_internal (-count, bdir, c));
+ else
+ return (_rl_char_search_internal (count, fdir, c));
+}
+
+int
+rl_char_search (count, key)
+ int count, key;
+{
+ return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+ int count, key;
+{
+ return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/* */
+/* History Utilities */
+/* */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+ the history features of readline. This is our local interface to
+ the history mechanism. */
+
+/* While we are editing the history, this is the saved
+ version of the original line. */
+HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+static void
+start_using_history ()
+{
+ using_history ();
+ if (saved_line_for_history)
+ _rl_free_history_entry (saved_line_for_history);
+
+ saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+void
+_rl_free_history_entry (entry)
+ HIST_ENTRY *entry;
+{
+ if (entry == 0)
+ return;
+ if (entry->line)
+ free (entry->line);
+ free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+int
+maybe_replace_line ()
+{
+ HIST_ENTRY *temp;
+
+ temp = current_history ();
+ /* If the current line has changed, save the changes. */
+ if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
+ {
+ temp = replace_history_entry (where_history (), the_line, (histdata_t)rl_undo_list);
+ free (temp->line);
+ free (temp);
+ }
+ return 0;
+}
+
+/* Put back the saved_line_for_history if there is one. */
+int
+maybe_unsave_line ()
+{
+ int line_len;
+
+ if (saved_line_for_history)
+ {
+ line_len = strlen (saved_line_for_history->line);
+
+ if (line_len >= rl_line_buffer_len)
+ rl_extend_line_buffer (line_len);
+
+ strcpy (the_line, saved_line_for_history->line);
+ rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
+ _rl_free_history_entry (saved_line_for_history);
+ saved_line_for_history = (HIST_ENTRY *)NULL;
+ rl_end = rl_point = strlen (the_line);
+ }
+ else
+ ding ();
+ return 0;
+}
+
+/* Save the current line in saved_line_for_history. */
+int
+maybe_save_line ()
+{
+ if (saved_line_for_history == 0)
+ {
+ saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+ saved_line_for_history->line = savestring (the_line);
+ saved_line_for_history->data = (char *)rl_undo_list;
+ }
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* History Commands */
+/* */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+int
+rl_beginning_of_history (count, key)
+ int count, key;
+{
+ return (rl_get_previous_history (1 + where_history (), key));
+}
+
+/* Meta-> goes to the end of the history. (The current line). */
+int
+rl_end_of_history (count, key)
+ int count, key;
+{
+ maybe_replace_line ();
+ using_history ();
+ maybe_unsave_line ();
+ return 0;
+}
+
+/* Move down to the next history line. */
+int
+rl_get_next_history (count, key)
+ int count, key;
+{
+ HIST_ENTRY *temp;
+ int line_len;
+
+ if (count < 0)
+ return (rl_get_previous_history (-count, key));
+
+ if (count == 0)
+ return 0;
+
+ maybe_replace_line ();
+
+ temp = (HIST_ENTRY *)NULL;
+ while (count)
+ {
+ temp = next_history ();
+ if (!temp)
+ break;
+ --count;
+ }
+
+ if (temp == 0)
+ maybe_unsave_line ();
+ else
+ {
+ line_len = strlen (temp->line);
+
+ if (line_len >= rl_line_buffer_len)
+ rl_extend_line_buffer (line_len);
+
+ strcpy (the_line, temp->line);
+ rl_undo_list = (UNDO_LIST *)temp->data;
+ rl_end = rl_point = strlen (the_line);
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ rl_point = 0;
+#endif /* VI_MODE */
+ }
+ return 0;
+}
+
+/* Get the previous item out of our interactive history, making it the current
+ line. If there is no previous history, just ding. */
+int
+rl_get_previous_history (count, key)
+ int count, key;
+{
+ HIST_ENTRY *old_temp, *temp;
+ int line_len;
+
+ if (count < 0)
+ return (rl_get_next_history (-count, key));
+
+ if (count == 0)
+ return 0;
+
+ /* If we don't have a line saved, then save this one. */
+ maybe_save_line ();
+
+ /* If the current line has changed, save the changes. */
+ maybe_replace_line ();
+
+ temp = old_temp = (HIST_ENTRY *)NULL;
+ while (count)
+ {
+ temp = previous_history ();
+ if (temp == 0)
+ break;
+
+ old_temp = temp;
+ --count;
+ }
+
+ /* If there was a large argument, and we moved back to the start of the
+ history, that is not an error. So use the last value found. */
+ if (!temp && old_temp)
+ temp = old_temp;
+
+ if (temp == 0)
+ ding ();
+ else
+ {
+ line_len = strlen (temp->line);
+
+ if (line_len >= rl_line_buffer_len)
+ rl_extend_line_buffer (line_len);
+
+ strcpy (the_line, temp->line);
+ rl_undo_list = (UNDO_LIST *)temp->data;
+ rl_end = rl_point = line_len;
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ rl_point = 0;
+#endif /* VI_MODE */
+ }
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* The Mark and the Region. */
+/* */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+ int position;
+{
+ if (position > rl_end)
+ return -1;
+
+ rl_mark = position;
+ return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+ int count, key;
+{
+ return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+ int count, key;
+{
+ if (rl_mark > rl_end)
+ rl_mark = -1;
+
+ if (rl_mark == -1)
+ {
+ ding ();
+ return -1;
+ }
+ else
+ SWAP (rl_point, rl_mark);
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Editing Modes */
+/* */
+/* **************************************************************** */
+/* How to toggle back and forth between editing modes. */
+int
+rl_vi_editing_mode (count, key)
+ int count, key;
+{
+#if defined (VI_MODE)
+ rl_editing_mode = vi_mode;
+ rl_vi_insertion_mode (1, key);
+#endif /* VI_MODE */
+ return 0;
+}
+
+int
+rl_emacs_editing_mode (count, key)
+ int count, key;
+{
+ rl_editing_mode = emacs_mode;
+ _rl_keymap = emacs_standard_keymap;
+ return 0;
}