1 /* misc.c -- miscellaneous bindable readline functions. */
3 /* Copyright (C) 1987-2002 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
8 The GNU Readline Library is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2, or
11 (at your option) any later version.
13 The GNU Readline Library is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 The GNU General Public License is often shipped with GNU software, and
19 is generally kept in a file called COPYING or LICENSE. If you do not
20 have a copy of the license, write to the Free Software Foundation,
21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22 #define READLINE_LIBRARY
24 #if defined (HAVE_CONFIG_H)
28 #if defined (HAVE_UNISTD_H)
30 #endif /* HAVE_UNISTD_H */
32 #if defined (HAVE_STDLIB_H)
35 # include "ansi_stdlib.h"
36 #endif /* HAVE_STDLIB_H */
38 #if defined (HAVE_LOCALE_H)
44 /* System-specific feature definitions and include files. */
48 /* Some standard library routines. */
52 #include "rlprivate.h"
56 static int rl_digit_loop PARAMS((void));
57 static void _rl_history_set_point PARAMS((void));
59 /* Forward declarations used in this file */
60 void _rl_free_history_entry PARAMS((HIST_ENTRY *));
62 /* If non-zero, rl_get_previous_history and rl_get_next_history attempt
63 to preserve the value of rl_point from line to line. */
64 int _rl_history_preserve_point = 0;
66 /* Saved target point for when _rl_history_preserve_point is set. Special
67 value of -1 means that point is at the end of the line. */
68 int _rl_history_saved_point = -1;
70 /* **************************************************************** */
72 /* Numeric Arguments */
74 /* **************************************************************** */
76 /* Handle C-u style numeric args, as well as M--, and M-digits. */
80 int key, c, sawminus, sawdigits;
84 RL_SETSTATE(RL_STATE_NUMERICARG);
85 sawminus = sawdigits = 0;
88 if (rl_numeric_arg > 1000000)
90 sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
94 RL_UNSETSTATE(RL_STATE_NUMERICARG);
97 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
98 RL_SETSTATE(RL_STATE_MOREINPUT);
99 key = c = rl_read_key ();
100 RL_UNSETSTATE(RL_STATE_MOREINPUT);
104 _rl_abort_internal ();
108 /* If we see a key bound to `universal-argument' after seeing digits,
109 it ends the argument but is otherwise ignored. */
110 if (_rl_keymap[c].type == ISFUNC &&
111 _rl_keymap[c].function == rl_universal_argument)
120 RL_SETSTATE(RL_STATE_MOREINPUT);
121 key = rl_read_key ();
122 RL_UNSETSTATE(RL_STATE_MOREINPUT);
123 rl_restore_prompt ();
125 RL_UNSETSTATE(RL_STATE_NUMERICARG);
126 return (_rl_dispatch (key, _rl_keymap));
134 rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
135 sawdigits = rl_explicit_arg = 1;
137 else if (c == '-' && rl_explicit_arg == 0)
139 rl_numeric_arg = sawminus = 1;
144 /* Make M-- command equivalent to M--1 command. */
145 if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
147 rl_restore_prompt ();
149 RL_UNSETSTATE(RL_STATE_NUMERICARG);
150 return (_rl_dispatch (key, _rl_keymap));
157 /* Add the current digit to the argument in progress. */
159 rl_digit_argument (ignore, key)
162 rl_execute_next (key);
163 return (rl_digit_loop ());
166 /* What to do when you abort reading an argument. */
168 rl_discard_argument ()
172 _rl_init_argument ();
176 /* Create a default argument. */
180 rl_numeric_arg = rl_arg_sign = 1;
185 /* C-u, universal argument. Multiply the current argument by 4.
186 Read a key. If the key has nothing to do with arguments, then
187 dispatch on it. If the key is the abort character then abort. */
189 rl_universal_argument (count, key)
193 return (rl_digit_loop ());
196 /* **************************************************************** */
198 /* History Utilities */
200 /* **************************************************************** */
202 /* We already have a history library, and that is what we use to control
203 the history features of readline. This is our local interface to
204 the history mechanism. */
206 /* While we are editing the history, this is the saved
207 version of the original line. */
208 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
210 /* Set the history pointer back to the last entry in the history. */
212 _rl_start_using_history ()
215 if (_rl_saved_line_for_history)
216 _rl_free_history_entry (_rl_saved_line_for_history);
218 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
221 /* Free the contents (and containing structure) of a HIST_ENTRY. */
223 _rl_free_history_entry (entry)
233 /* Perhaps put back the current line if it has changed. */
235 rl_maybe_replace_line ()
239 temp = current_history ();
240 /* If the current line has changed, save the changes. */
241 if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
243 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
250 /* Restore the _rl_saved_line_for_history if there is one. */
252 rl_maybe_unsave_line ()
254 if (_rl_saved_line_for_history)
256 rl_replace_line (_rl_saved_line_for_history->line, 0);
257 rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
258 _rl_free_history_entry (_rl_saved_line_for_history);
259 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
260 rl_point = rl_end; /* rl_replace_line sets rl_end */
267 /* Save the current line in _rl_saved_line_for_history. */
269 rl_maybe_save_line ()
271 if (_rl_saved_line_for_history == 0)
273 _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
274 _rl_saved_line_for_history->line = savestring (rl_line_buffer);
275 _rl_saved_line_for_history->data = (char *)rl_undo_list;
281 _rl_free_saved_history_line ()
283 if (_rl_saved_line_for_history)
285 _rl_free_history_entry (_rl_saved_line_for_history);
286 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
292 _rl_history_set_point ()
294 rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
295 ? _rl_history_saved_point
297 if (rl_point > rl_end)
300 #if defined (VI_MODE)
301 if (rl_editing_mode == vi_mode)
305 if (rl_editing_mode == emacs_mode)
306 rl_mark = (rl_point == rl_end ? 0 : rl_end);
310 rl_replace_from_history (entry, flags)
312 int flags; /* currently unused */
314 rl_replace_line (entry->line, 0);
315 rl_undo_list = (UNDO_LIST *)entry->data;
319 #if defined (VI_MODE)
320 if (rl_editing_mode == vi_mode)
328 /* **************************************************************** */
330 /* History Commands */
332 /* **************************************************************** */
334 /* Meta-< goes to the start of the history. */
336 rl_beginning_of_history (count, key)
339 return (rl_get_previous_history (1 + where_history (), key));
342 /* Meta-> goes to the end of the history. (The current line). */
344 rl_end_of_history (count, key)
347 rl_maybe_replace_line ();
349 rl_maybe_unsave_line ();
353 /* Move down to the next history line. */
355 rl_get_next_history (count, key)
361 return (rl_get_previous_history (-count, key));
366 rl_maybe_replace_line ();
368 /* either not saved by rl_newline or at end of line, so set appropriately. */
369 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
370 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
372 temp = (HIST_ENTRY *)NULL;
375 temp = next_history ();
382 rl_maybe_unsave_line ();
385 rl_replace_from_history (temp, 0);
386 _rl_history_set_point ();
391 /* Get the previous item out of our interactive history, making it the current
392 line. If there is no previous history, just ding. */
394 rl_get_previous_history (count, key)
397 HIST_ENTRY *old_temp, *temp;
400 return (rl_get_next_history (-count, key));
405 /* either not saved by rl_newline or at end of line, so set appropriately. */
406 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
407 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
409 /* If we don't have a line saved, then save this one. */
410 rl_maybe_save_line ();
412 /* If the current line has changed, save the changes. */
413 rl_maybe_replace_line ();
415 temp = old_temp = (HIST_ENTRY *)NULL;
418 temp = previous_history ();
426 /* If there was a large argument, and we moved back to the start of the
427 history, that is not an error. So use the last value found. */
428 if (!temp && old_temp)
435 rl_replace_from_history (temp, 0);
436 _rl_history_set_point ();
441 /* **************************************************************** */
445 /* **************************************************************** */
446 /* How to toggle back and forth between editing modes. */
448 rl_vi_editing_mode (count, key)
451 #if defined (VI_MODE)
452 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
453 rl_editing_mode = vi_mode;
454 rl_vi_insertion_mode (1, key);
461 rl_emacs_editing_mode (count, key)
464 rl_editing_mode = emacs_mode;
465 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
466 _rl_keymap = emacs_standard_keymap;
470 /* Function for the rest of the library to use to set insert/overwrite mode. */
472 _rl_set_insert_mode (im, force)
476 _rl_set_cursor (im, force);
482 /* Toggle overwrite mode. A positive explicit argument selects overwrite
483 mode. A negative or zero explicit argument selects insert mode. */
485 rl_overwrite_mode (count, key)
488 if (rl_explicit_arg == 0)
489 _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
491 _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
493 _rl_set_insert_mode (RL_IM_INSERT, 0);