]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/misc.c
Imported from ../bash-3.0.16.tar.gz.
[thirdparty/bash.git] / lib / readline / misc.c
CommitLineData
7117c2d2
JA
1/* misc.c -- miscellaneous bindable readline functions. */
2
b80f6443 3/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
7117c2d2
JA
4
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
7
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.
12
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.
17
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
23
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
28#if defined (HAVE_UNISTD_H)
29# include <unistd.h>
30#endif /* HAVE_UNISTD_H */
31
32#if defined (HAVE_STDLIB_H)
33# include <stdlib.h>
34#else
35# include "ansi_stdlib.h"
36#endif /* HAVE_STDLIB_H */
37
38#if defined (HAVE_LOCALE_H)
39# include <locale.h>
40#endif
41
42#include <stdio.h>
43
44/* System-specific feature definitions and include files. */
45#include "rldefs.h"
46#include "rlmbutil.h"
47
48/* Some standard library routines. */
49#include "readline.h"
50#include "history.h"
51
52#include "rlprivate.h"
53#include "rlshell.h"
54#include "xmalloc.h"
55
56static int rl_digit_loop PARAMS((void));
57static void _rl_history_set_point PARAMS((void));
58
59/* Forward declarations used in this file */
60void _rl_free_history_entry PARAMS((HIST_ENTRY *));
61
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. */
64int _rl_history_preserve_point = 0;
65
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. */
68int _rl_history_saved_point = -1;
69
70/* **************************************************************** */
71/* */
72/* Numeric Arguments */
73/* */
74/* **************************************************************** */
75
76/* Handle C-u style numeric args, as well as M--, and M-digits. */
77static int
78rl_digit_loop ()
79{
80 int key, c, sawminus, sawdigits;
81
82 rl_save_prompt ();
83
84 RL_SETSTATE(RL_STATE_NUMERICARG);
85 sawminus = sawdigits = 0;
86 while (1)
87 {
88 if (rl_numeric_arg > 1000000)
89 {
90 sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
91 rl_ding ();
92 rl_restore_prompt ();
93 rl_clear_message ();
94 RL_UNSETSTATE(RL_STATE_NUMERICARG);
95 return 1;
96 }
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);
101
102 if (c < 0)
103 {
104 _rl_abort_internal ();
105 return -1;
106 }
107
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)
112 {
113 if (sawdigits == 0)
114 {
115 rl_numeric_arg *= 4;
116 continue;
117 }
118 else
119 {
120 RL_SETSTATE(RL_STATE_MOREINPUT);
121 key = rl_read_key ();
122 RL_UNSETSTATE(RL_STATE_MOREINPUT);
123 rl_restore_prompt ();
124 rl_clear_message ();
125 RL_UNSETSTATE(RL_STATE_NUMERICARG);
126 return (_rl_dispatch (key, _rl_keymap));
127 }
128 }
129
130 c = UNMETA (c);
131
132 if (_rl_digit_p (c))
133 {
134 rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
135 sawdigits = rl_explicit_arg = 1;
136 }
137 else if (c == '-' && rl_explicit_arg == 0)
138 {
139 rl_numeric_arg = sawminus = 1;
140 rl_arg_sign = -1;
141 }
142 else
143 {
144 /* Make M-- command equivalent to M--1 command. */
145 if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
146 rl_explicit_arg = 1;
147 rl_restore_prompt ();
148 rl_clear_message ();
149 RL_UNSETSTATE(RL_STATE_NUMERICARG);
150 return (_rl_dispatch (key, _rl_keymap));
151 }
152 }
153
154 /*NOTREACHED*/
155}
156
157/* Add the current digit to the argument in progress. */
158int
159rl_digit_argument (ignore, key)
160 int ignore, key;
161{
162 rl_execute_next (key);
163 return (rl_digit_loop ());
164}
165
166/* What to do when you abort reading an argument. */
167int
168rl_discard_argument ()
169{
170 rl_ding ();
171 rl_clear_message ();
172 _rl_init_argument ();
173 return 0;
174}
175
176/* Create a default argument. */
177int
178_rl_init_argument ()
179{
180 rl_numeric_arg = rl_arg_sign = 1;
181 rl_explicit_arg = 0;
182 return 0;
183}
184
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. */
188int
189rl_universal_argument (count, key)
190 int count, key;
191{
192 rl_numeric_arg *= 4;
193 return (rl_digit_loop ());
194}
195
196/* **************************************************************** */
197/* */
198/* History Utilities */
199/* */
200/* **************************************************************** */
201
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. */
205
206/* While we are editing the history, this is the saved
207 version of the original line. */
208HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
209
210/* Set the history pointer back to the last entry in the history. */
211void
212_rl_start_using_history ()
213{
214 using_history ();
215 if (_rl_saved_line_for_history)
216 _rl_free_history_entry (_rl_saved_line_for_history);
217
218 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
219}
220
221/* Free the contents (and containing structure) of a HIST_ENTRY. */
222void
223_rl_free_history_entry (entry)
224 HIST_ENTRY *entry;
225{
226 if (entry == 0)
227 return;
228 if (entry->line)
229 free (entry->line);
230 free (entry);
231}
232
233/* Perhaps put back the current line if it has changed. */
234int
235rl_maybe_replace_line ()
236{
237 HIST_ENTRY *temp;
238
239 temp = current_history ();
240 /* If the current line has changed, save the changes. */
241 if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
242 {
243 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
244 free (temp->line);
245 free (temp);
246 }
247 return 0;
248}
249
250/* Restore the _rl_saved_line_for_history if there is one. */
251int
252rl_maybe_unsave_line ()
253{
254 if (_rl_saved_line_for_history)
255 {
b80f6443
JA
256 /* Can't call with `1' because rl_undo_list might point to an undo
257 list from a history entry, as in rl_replace_from_history() below. */
7117c2d2
JA
258 rl_replace_line (_rl_saved_line_for_history->line, 0);
259 rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
260 _rl_free_history_entry (_rl_saved_line_for_history);
261 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
262 rl_point = rl_end; /* rl_replace_line sets rl_end */
263 }
264 else
265 rl_ding ();
266 return 0;
267}
268
269/* Save the current line in _rl_saved_line_for_history. */
270int
271rl_maybe_save_line ()
272{
273 if (_rl_saved_line_for_history == 0)
274 {
275 _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
276 _rl_saved_line_for_history->line = savestring (rl_line_buffer);
277 _rl_saved_line_for_history->data = (char *)rl_undo_list;
278 }
b80f6443 279
7117c2d2
JA
280 return 0;
281}
282
283int
284_rl_free_saved_history_line ()
285{
286 if (_rl_saved_line_for_history)
287 {
288 _rl_free_history_entry (_rl_saved_line_for_history);
289 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
290 }
291 return 0;
292}
293
294static void
295_rl_history_set_point ()
296{
297 rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
298 ? _rl_history_saved_point
299 : rl_end;
300 if (rl_point > rl_end)
301 rl_point = rl_end;
302
303#if defined (VI_MODE)
b80f6443 304 if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
7117c2d2
JA
305 rl_point = 0;
306#endif /* VI_MODE */
307
308 if (rl_editing_mode == emacs_mode)
309 rl_mark = (rl_point == rl_end ? 0 : rl_end);
310}
311
312void
313rl_replace_from_history (entry, flags)
314 HIST_ENTRY *entry;
315 int flags; /* currently unused */
316{
b80f6443
JA
317 /* Can't call with `1' because rl_undo_list might point to an undo list
318 from a history entry, just like we're setting up here. */
7117c2d2
JA
319 rl_replace_line (entry->line, 0);
320 rl_undo_list = (UNDO_LIST *)entry->data;
321 rl_point = rl_end;
322 rl_mark = 0;
323
324#if defined (VI_MODE)
325 if (rl_editing_mode == vi_mode)
326 {
327 rl_point = 0;
328 rl_mark = rl_end;
329 }
330#endif
331}
332
333/* **************************************************************** */
334/* */
335/* History Commands */
336/* */
337/* **************************************************************** */
338
339/* Meta-< goes to the start of the history. */
340int
341rl_beginning_of_history (count, key)
342 int count, key;
343{
344 return (rl_get_previous_history (1 + where_history (), key));
345}
346
347/* Meta-> goes to the end of the history. (The current line). */
348int
349rl_end_of_history (count, key)
350 int count, key;
351{
352 rl_maybe_replace_line ();
353 using_history ();
354 rl_maybe_unsave_line ();
355 return 0;
356}
357
358/* Move down to the next history line. */
359int
360rl_get_next_history (count, key)
361 int count, key;
362{
363 HIST_ENTRY *temp;
364
365 if (count < 0)
366 return (rl_get_previous_history (-count, key));
367
368 if (count == 0)
369 return 0;
370
371 rl_maybe_replace_line ();
372
373 /* either not saved by rl_newline or at end of line, so set appropriately. */
374 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
375 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
376
377 temp = (HIST_ENTRY *)NULL;
378 while (count)
379 {
380 temp = next_history ();
381 if (!temp)
382 break;
383 --count;
384 }
385
386 if (temp == 0)
387 rl_maybe_unsave_line ();
388 else
389 {
390 rl_replace_from_history (temp, 0);
391 _rl_history_set_point ();
392 }
393 return 0;
394}
395
396/* Get the previous item out of our interactive history, making it the current
397 line. If there is no previous history, just ding. */
398int
399rl_get_previous_history (count, key)
400 int count, key;
401{
402 HIST_ENTRY *old_temp, *temp;
403
404 if (count < 0)
405 return (rl_get_next_history (-count, key));
406
407 if (count == 0)
408 return 0;
409
410 /* either not saved by rl_newline or at end of line, so set appropriately. */
411 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
412 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
413
414 /* If we don't have a line saved, then save this one. */
415 rl_maybe_save_line ();
416
417 /* If the current line has changed, save the changes. */
418 rl_maybe_replace_line ();
419
420 temp = old_temp = (HIST_ENTRY *)NULL;
421 while (count)
422 {
423 temp = previous_history ();
424 if (temp == 0)
425 break;
426
427 old_temp = temp;
428 --count;
429 }
430
431 /* If there was a large argument, and we moved back to the start of the
432 history, that is not an error. So use the last value found. */
433 if (!temp && old_temp)
434 temp = old_temp;
435
436 if (temp == 0)
437 rl_ding ();
438 else
439 {
440 rl_replace_from_history (temp, 0);
441 _rl_history_set_point ();
442 }
b80f6443 443
7117c2d2
JA
444 return 0;
445}
446
447/* **************************************************************** */
448/* */
449/* Editing Modes */
450/* */
451/* **************************************************************** */
452/* How to toggle back and forth between editing modes. */
453int
454rl_vi_editing_mode (count, key)
455 int count, key;
456{
457#if defined (VI_MODE)
458 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
459 rl_editing_mode = vi_mode;
460 rl_vi_insertion_mode (1, key);
461#endif /* VI_MODE */
462
463 return 0;
464}
465
466int
467rl_emacs_editing_mode (count, key)
468 int count, key;
469{
470 rl_editing_mode = emacs_mode;
471 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
472 _rl_keymap = emacs_standard_keymap;
473 return 0;
474}
475
476/* Function for the rest of the library to use to set insert/overwrite mode. */
477void
478_rl_set_insert_mode (im, force)
479 int im, force;
480{
481#ifdef CURSOR_MODE
482 _rl_set_cursor (im, force);
483#endif
484
485 rl_insert_mode = im;
486}
487
488/* Toggle overwrite mode. A positive explicit argument selects overwrite
489 mode. A negative or zero explicit argument selects insert mode. */
490int
491rl_overwrite_mode (count, key)
492 int count, key;
493{
494 if (rl_explicit_arg == 0)
495 _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
496 else if (count > 0)
497 _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
498 else
499 _rl_set_insert_mode (RL_IM_INSERT, 0);
500
501 return 0;
502}