]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/misc.c
Bash-5.0 patch 12: fix problems moving back beyond start of history
[thirdparty/bash.git] / lib / readline / misc.c
CommitLineData
7117c2d2
JA
1/* misc.c -- miscellaneous bindable readline functions. */
2
d233b485 3/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
7117c2d2 4
3185942a
JA
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
7117c2d2 7
3185942a
JA
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
7117c2d2
JA
11 (at your option) any later version.
12
3185942a
JA
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7117c2d2
JA
16 GNU General Public License for more details.
17
3185942a
JA
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
20*/
21
7117c2d2
JA
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
95732b49
JA
66_rl_arg_cxt _rl_argcxt;
67
7117c2d2
JA
68/* Saved target point for when _rl_history_preserve_point is set. Special
69 value of -1 means that point is at the end of the line. */
70int _rl_history_saved_point = -1;
71
72/* **************************************************************** */
73/* */
74/* Numeric Arguments */
75/* */
76/* **************************************************************** */
77
95732b49 78int
d233b485 79_rl_arg_overflow (void)
7117c2d2 80{
95732b49
JA
81 if (rl_numeric_arg > 1000000)
82 {
83 _rl_argcxt = 0;
84 rl_explicit_arg = rl_numeric_arg = 0;
85 rl_ding ();
86 rl_restore_prompt ();
87 rl_clear_message ();
88 RL_UNSETSTATE(RL_STATE_NUMERICARG);
89 return 1;
90 }
91 return 0;
92}
7117c2d2 93
95732b49 94void
d233b485 95_rl_arg_init (void)
95732b49 96{
7117c2d2 97 rl_save_prompt ();
95732b49 98 _rl_argcxt = 0;
7117c2d2 99 RL_SETSTATE(RL_STATE_NUMERICARG);
95732b49 100}
7117c2d2 101
95732b49 102int
d233b485 103_rl_arg_getchar (void)
95732b49
JA
104{
105 int c;
7117c2d2 106
95732b49
JA
107 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
108 RL_SETSTATE(RL_STATE_MOREINPUT);
109 c = rl_read_key ();
110 RL_UNSETSTATE(RL_STATE_MOREINPUT);
7117c2d2 111
95732b49
JA
112 return c;
113}
7117c2d2 114
95732b49
JA
115/* Process C as part of the current numeric argument. Return -1 if the
116 argument should be aborted, 0 if we should not read any more chars, and
117 1 if we should continue to read chars. */
118int
d233b485 119_rl_arg_dispatch (_rl_arg_cxt cxt, int c)
95732b49
JA
120{
121 int key, r;
122
123 key = c;
124
125 /* If we see a key bound to `universal-argument' after seeing digits,
126 it ends the argument but is otherwise ignored. */
a0c0a00f 127 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
95732b49
JA
128 {
129 if ((cxt & NUM_SAWDIGITS) == 0)
7117c2d2 130 {
95732b49
JA
131 rl_numeric_arg *= 4;
132 return 1;
7117c2d2 133 }
95732b49
JA
134 else if (RL_ISSTATE (RL_STATE_CALLBACK))
135 {
136 _rl_argcxt |= NUM_READONE;
137 return 0; /* XXX */
138 }
7117c2d2
JA
139 else
140 {
95732b49
JA
141 RL_SETSTATE(RL_STATE_MOREINPUT);
142 key = rl_read_key ();
143 RL_UNSETSTATE(RL_STATE_MOREINPUT);
7117c2d2
JA
144 rl_restore_prompt ();
145 rl_clear_message ();
146 RL_UNSETSTATE(RL_STATE_NUMERICARG);
f1be666c
JA
147 if (key < 0)
148 return -1;
7117c2d2
JA
149 return (_rl_dispatch (key, _rl_keymap));
150 }
151 }
152
95732b49 153 c = UNMETA (c);
7117c2d2 154
95732b49
JA
155 if (_rl_digit_p (c))
156 {
157 r = _rl_digit_value (c);
158 rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
159 rl_explicit_arg = 1;
160 _rl_argcxt |= NUM_SAWDIGITS;
161 }
162 else if (c == '-' && rl_explicit_arg == 0)
163 {
164 rl_numeric_arg = 1;
165 _rl_argcxt |= NUM_SAWMINUS;
166 rl_arg_sign = -1;
167 }
168 else
169 {
170 /* Make M-- command equivalent to M--1 command. */
171 if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
172 rl_explicit_arg = 1;
173 rl_restore_prompt ();
174 rl_clear_message ();
175 RL_UNSETSTATE(RL_STATE_NUMERICARG);
176
177 r = _rl_dispatch (key, _rl_keymap);
178 if (RL_ISSTATE (RL_STATE_CALLBACK))
179 {
180 /* At worst, this will cause an extra redisplay. Otherwise,
181 we have to wait until the next character comes in. */
182 if (rl_done == 0)
183 (*rl_redisplay_function) ();
184 r = 0;
185 }
186 return r;
187 }
188
189 return 1;
7117c2d2
JA
190}
191
95732b49
JA
192/* Handle C-u style numeric args, as well as M--, and M-digits. */
193static int
d233b485 194rl_digit_loop (void)
7117c2d2 195{
95732b49
JA
196 int c, r;
197
198 while (1)
199 {
200 if (_rl_arg_overflow ())
201 return 1;
202
203 c = _rl_arg_getchar ();
204
205 if (c < 0)
206 {
207 _rl_abort_internal ();
208 return -1;
209 }
210
211 r = _rl_arg_dispatch (_rl_argcxt, c);
212 if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
213 break;
214 }
0628567a
JA
215
216 return r;
7117c2d2
JA
217}
218
219/* Create a default argument. */
95732b49 220void
d233b485 221_rl_reset_argument (void)
7117c2d2
JA
222{
223 rl_numeric_arg = rl_arg_sign = 1;
224 rl_explicit_arg = 0;
95732b49
JA
225 _rl_argcxt = 0;
226}
227
228/* Start a numeric argument with initial value KEY */
229int
d233b485 230rl_digit_argument (int ignore, int key)
95732b49
JA
231{
232 _rl_arg_init ();
233 if (RL_ISSTATE (RL_STATE_CALLBACK))
234 {
235 _rl_arg_dispatch (_rl_argcxt, key);
236 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
237 return 0;
238 }
239 else
240 {
241 rl_execute_next (key);
242 return (rl_digit_loop ());
243 }
7117c2d2
JA
244}
245
246/* C-u, universal argument. Multiply the current argument by 4.
247 Read a key. If the key has nothing to do with arguments, then
248 dispatch on it. If the key is the abort character then abort. */
249int
d233b485 250rl_universal_argument (int count, int key)
7117c2d2 251{
95732b49 252 _rl_arg_init ();
7117c2d2 253 rl_numeric_arg *= 4;
95732b49
JA
254
255 return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
256}
257
258int
d233b485 259_rl_arg_callback (_rl_arg_cxt cxt)
95732b49
JA
260{
261 int c, r;
262
263 c = _rl_arg_getchar ();
a0c0a00f
CR
264 if (c < 0)
265 return (1); /* EOF */
95732b49
JA
266
267 if (_rl_argcxt & NUM_READONE)
268 {
269 _rl_argcxt &= ~NUM_READONE;
270 rl_restore_prompt ();
271 rl_clear_message ();
272 RL_UNSETSTATE(RL_STATE_NUMERICARG);
273 rl_execute_next (c);
274 return 0;
275 }
276
277 r = _rl_arg_dispatch (cxt, c);
d233b485
CR
278 if (r > 0)
279 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
95732b49
JA
280 return (r != 1);
281}
282
283/* What to do when you abort reading an argument. */
284int
d233b485 285rl_discard_argument (void)
95732b49
JA
286{
287 rl_ding ();
288 rl_clear_message ();
289 _rl_reset_argument ();
290
291 return 0;
7117c2d2
JA
292}
293
294/* **************************************************************** */
295/* */
296/* History Utilities */
297/* */
298/* **************************************************************** */
299
300/* We already have a history library, and that is what we use to control
301 the history features of readline. This is our local interface to
302 the history mechanism. */
303
304/* While we are editing the history, this is the saved
305 version of the original line. */
306HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
307
308/* Set the history pointer back to the last entry in the history. */
309void
d233b485 310_rl_start_using_history (void)
7117c2d2
JA
311{
312 using_history ();
313 if (_rl_saved_line_for_history)
314 _rl_free_history_entry (_rl_saved_line_for_history);
315
316 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
317}
318
319/* Free the contents (and containing structure) of a HIST_ENTRY. */
320void
d233b485 321_rl_free_history_entry (HIST_ENTRY *entry)
7117c2d2
JA
322{
323 if (entry == 0)
324 return;
95732b49
JA
325
326 FREE (entry->line);
327 FREE (entry->timestamp);
328
495aee44 329 xfree (entry);
7117c2d2
JA
330}
331
332/* Perhaps put back the current line if it has changed. */
333int
d233b485 334rl_maybe_replace_line (void)
7117c2d2
JA
335{
336 HIST_ENTRY *temp;
337
338 temp = current_history ();
339 /* If the current line has changed, save the changes. */
340 if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
341 {
342 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
495aee44 343 xfree (temp->line);
95732b49 344 FREE (temp->timestamp);
495aee44 345 xfree (temp);
7117c2d2
JA
346 }
347 return 0;
348}
349
350/* Restore the _rl_saved_line_for_history if there is one. */
351int
d233b485 352rl_maybe_unsave_line (void)
7117c2d2
JA
353{
354 if (_rl_saved_line_for_history)
355 {
b80f6443
JA
356 /* Can't call with `1' because rl_undo_list might point to an undo
357 list from a history entry, as in rl_replace_from_history() below. */
7117c2d2
JA
358 rl_replace_line (_rl_saved_line_for_history->line, 0);
359 rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
360 _rl_free_history_entry (_rl_saved_line_for_history);
361 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
362 rl_point = rl_end; /* rl_replace_line sets rl_end */
363 }
364 else
365 rl_ding ();
366 return 0;
367}
368
369/* Save the current line in _rl_saved_line_for_history. */
370int
d233b485 371rl_maybe_save_line (void)
7117c2d2
JA
372{
373 if (_rl_saved_line_for_history == 0)
374 {
375 _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
376 _rl_saved_line_for_history->line = savestring (rl_line_buffer);
95732b49 377 _rl_saved_line_for_history->timestamp = (char *)NULL;
7117c2d2
JA
378 _rl_saved_line_for_history->data = (char *)rl_undo_list;
379 }
b80f6443 380
7117c2d2
JA
381 return 0;
382}
383
384int
d233b485 385_rl_free_saved_history_line (void)
7117c2d2
JA
386{
387 if (_rl_saved_line_for_history)
388 {
389 _rl_free_history_entry (_rl_saved_line_for_history);
390 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
391 }
392 return 0;
393}
394
395static void
d233b485 396_rl_history_set_point (void)
7117c2d2
JA
397{
398 rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
399 ? _rl_history_saved_point
400 : rl_end;
401 if (rl_point > rl_end)
402 rl_point = rl_end;
403
404#if defined (VI_MODE)
b80f6443 405 if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
7117c2d2
JA
406 rl_point = 0;
407#endif /* VI_MODE */
408
409 if (rl_editing_mode == emacs_mode)
410 rl_mark = (rl_point == rl_end ? 0 : rl_end);
411}
412
413void
d233b485 414rl_replace_from_history (HIST_ENTRY *entry, int flags)
7117c2d2 415{
b80f6443
JA
416 /* Can't call with `1' because rl_undo_list might point to an undo list
417 from a history entry, just like we're setting up here. */
7117c2d2
JA
418 rl_replace_line (entry->line, 0);
419 rl_undo_list = (UNDO_LIST *)entry->data;
420 rl_point = rl_end;
421 rl_mark = 0;
422
423#if defined (VI_MODE)
424 if (rl_editing_mode == vi_mode)
425 {
426 rl_point = 0;
427 rl_mark = rl_end;
428 }
429#endif
3185942a
JA
430}
431
432/* Process and free undo lists attached to each history entry prior to the
433 current entry, inclusive, reverting each line to its saved state. This
434 is destructive, and state about the current line is lost. This is not
435 intended to be called while actively editing, and the current line is
436 not assumed to have been added to the history list. */
437void
d233b485 438_rl_revert_all_lines (void)
3185942a
JA
439{
440 int hpos;
441 HIST_ENTRY *entry;
442 UNDO_LIST *ul, *saved_undo_list;
443 char *lbuf;
444
445 lbuf = savestring (rl_line_buffer);
446 saved_undo_list = rl_undo_list;
447 hpos = where_history ();
448
449 entry = (hpos == history_length) ? previous_history () : current_history ();
450 while (entry)
451 {
452 if (ul = (UNDO_LIST *)entry->data)
453 {
454 if (ul == saved_undo_list)
455 saved_undo_list = 0;
456 /* Set up rl_line_buffer and other variables from history entry */
457 rl_replace_from_history (entry, 0); /* entry->line is now current */
00062383 458 entry->data = 0; /* entry->data is now current undo list */
3185942a
JA
459 /* Undo all changes to this history entry */
460 while (rl_undo_list)
461 rl_do_undo ();
462 /* And copy the reverted line back to the history entry, preserving
463 the timestamp. */
464 FREE (entry->line);
465 entry->line = savestring (rl_line_buffer);
3185942a
JA
466 }
467 entry = previous_history ();
468 }
469
470 /* Restore history state */
471 rl_undo_list = saved_undo_list; /* may have been set to null */
472 history_set_pos (hpos);
473
474 /* reset the line buffer */
475 rl_replace_line (lbuf, 0);
476 _rl_set_the_line ();
477
478 /* and clean up */
495aee44 479 xfree (lbuf);
7117c2d2
JA
480}
481
ac50fbac
CR
482/* Free the history list, including private readline data and take care
483 of pointer aliases to history data. Resets rl_undo_list if it points
484 to an UNDO_LIST * saved as some history entry's data member. This
485 should not be called while editing is active. */
486void
d233b485 487rl_clear_history (void)
ac50fbac
CR
488{
489 HIST_ENTRY **hlist, *hent;
490 register int i;
491 UNDO_LIST *ul, *saved_undo_list;
492
493 saved_undo_list = rl_undo_list;
494 hlist = history_list (); /* direct pointer, not copy */
495
496 for (i = 0; i < history_length; i++)
497 {
498 hent = hlist[i];
499 if (ul = (UNDO_LIST *)hent->data)
500 {
501 if (ul == saved_undo_list)
502 saved_undo_list = 0;
503 _rl_free_undo_list (ul);
504 hent->data = 0;
505 }
506 _rl_free_history_entry (hent);
507 }
508
509 history_offset = history_length = 0;
510 rl_undo_list = saved_undo_list; /* should be NULL */
511}
512
7117c2d2
JA
513/* **************************************************************** */
514/* */
515/* History Commands */
516/* */
517/* **************************************************************** */
518
519/* Meta-< goes to the start of the history. */
520int
d233b485 521rl_beginning_of_history (int count, int key)
7117c2d2
JA
522{
523 return (rl_get_previous_history (1 + where_history (), key));
524}
525
526/* Meta-> goes to the end of the history. (The current line). */
527int
d233b485 528rl_end_of_history (int count, int key)
7117c2d2
JA
529{
530 rl_maybe_replace_line ();
531 using_history ();
532 rl_maybe_unsave_line ();
533 return 0;
534}
535
536/* Move down to the next history line. */
537int
d233b485 538rl_get_next_history (int count, int key)
7117c2d2
JA
539{
540 HIST_ENTRY *temp;
541
542 if (count < 0)
543 return (rl_get_previous_history (-count, key));
544
545 if (count == 0)
546 return 0;
547
548 rl_maybe_replace_line ();
549
550 /* either not saved by rl_newline or at end of line, so set appropriately. */
551 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
552 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
553
554 temp = (HIST_ENTRY *)NULL;
555 while (count)
556 {
557 temp = next_history ();
558 if (!temp)
559 break;
560 --count;
561 }
562
563 if (temp == 0)
564 rl_maybe_unsave_line ();
565 else
566 {
567 rl_replace_from_history (temp, 0);
568 _rl_history_set_point ();
569 }
570 return 0;
571}
572
573/* Get the previous item out of our interactive history, making it the current
574 line. If there is no previous history, just ding. */
575int
d233b485 576rl_get_previous_history (int count, int key)
7117c2d2
JA
577{
578 HIST_ENTRY *old_temp, *temp;
b0852fb5 579 int had_saved_line;
7117c2d2
JA
580
581 if (count < 0)
582 return (rl_get_next_history (-count, key));
583
d233b485 584 if (count == 0 || history_list () == 0)
7117c2d2
JA
585 return 0;
586
587 /* either not saved by rl_newline or at end of line, so set appropriately. */
588 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
589 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
590
591 /* If we don't have a line saved, then save this one. */
b0852fb5 592 had_saved_line = _rl_saved_line_for_history != 0;
7117c2d2
JA
593 rl_maybe_save_line ();
594
595 /* If the current line has changed, save the changes. */
596 rl_maybe_replace_line ();
597
598 temp = old_temp = (HIST_ENTRY *)NULL;
599 while (count)
600 {
601 temp = previous_history ();
602 if (temp == 0)
603 break;
604
605 old_temp = temp;
606 --count;
607 }
608
609 /* If there was a large argument, and we moved back to the start of the
610 history, that is not an error. So use the last value found. */
611 if (!temp && old_temp)
612 temp = old_temp;
613
614 if (temp == 0)
d233b485 615 {
b0852fb5
CR
616 if (had_saved_line == 0)
617 _rl_free_saved_history_line ();
d233b485
CR
618 rl_ding ();
619 }
7117c2d2
JA
620 else
621 {
622 rl_replace_from_history (temp, 0);
623 _rl_history_set_point ();
624 }
b80f6443 625
7117c2d2
JA
626 return 0;
627}
628
629/* **************************************************************** */
630/* */
631/* Editing Modes */
632/* */
633/* **************************************************************** */
634/* How to toggle back and forth between editing modes. */
635int
d233b485 636rl_vi_editing_mode (int count, int key)
7117c2d2
JA
637{
638#if defined (VI_MODE)
639 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
640 rl_editing_mode = vi_mode;
3185942a 641 rl_vi_insert_mode (1, key);
7117c2d2
JA
642#endif /* VI_MODE */
643
644 return 0;
645}
646
647int
d233b485 648rl_emacs_editing_mode (int count, int key)
7117c2d2
JA
649{
650 rl_editing_mode = emacs_mode;
651 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
652 _rl_keymap = emacs_standard_keymap;
ac50fbac
CR
653
654 if (_rl_show_mode_in_prompt)
655 _rl_reset_prompt ();
656
7117c2d2
JA
657 return 0;
658}
659
660/* Function for the rest of the library to use to set insert/overwrite mode. */
661void
d233b485 662_rl_set_insert_mode (int im, int force)
7117c2d2
JA
663{
664#ifdef CURSOR_MODE
665 _rl_set_cursor (im, force);
666#endif
667
668 rl_insert_mode = im;
669}
670
671/* Toggle overwrite mode. A positive explicit argument selects overwrite
672 mode. A negative or zero explicit argument selects insert mode. */
673int
d233b485 674rl_overwrite_mode (int count, int key)
7117c2d2
JA
675{
676 if (rl_explicit_arg == 0)
677 _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
678 else if (count > 0)
679 _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
680 else
681 _rl_set_insert_mode (RL_IM_INSERT, 0);
682
683 return 0;
684}