1/* misc.c -- miscellaneous bindable readline functions. */
2
3/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25# include "config_readline.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_rl_arg_cxt _rl_argcxt;
67
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
78int
79_rl_arg_overflow ()
80{
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}
93
94void
95_rl_arg_init ()
96{
97 rl_save_prompt ();
98 _rl_argcxt = 0;
99 RL_SETSTATE(RL_STATE_NUMERICARG);
100}
101
102int
103_rl_arg_getchar ()
104{
105 int c;
106
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);
111
112 return c;
113}
114
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
119_rl_arg_dispatch (cxt, c)
120 _rl_arg_cxt cxt;
121 int c;
122{
123 int key, r;
124
125 key = c;
126
127 /* If we see a key bound to `universal-argument' after seeing digits,
128 it ends the argument but is otherwise ignored. */
129 if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
130 {
131 if ((cxt & NUM_SAWDIGITS) == 0)
132 {
133 rl_numeric_arg *= 4;
134 return 1;
135 }
136 else if (RL_ISSTATE (RL_STATE_CALLBACK))
137 {
138 _rl_argcxt |= NUM_READONE;
139 return 0; /* XXX */
140 }
141 else
142 {
143 RL_SETSTATE(RL_STATE_MOREINPUT);
144 key = rl_read_key ();
145 RL_UNSETSTATE(RL_STATE_MOREINPUT);
146 rl_restore_prompt ();
147 rl_clear_message ();
148 RL_UNSETSTATE(RL_STATE_NUMERICARG);
149 return (_rl_dispatch (key, _rl_keymap));
150 }
151 }
152
153 c = UNMETA (c);
154
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;
190}
191
192/* Handle C-u style numeric args, as well as M--, and M-digits. */
193static int
194rl_digit_loop ()
195{
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 }
215
216 return r;
217}
218
219/* Create a default argument. */
220void
221_rl_reset_argument ()
222{
223 rl_numeric_arg = rl_arg_sign = 1;
224 rl_explicit_arg = 0;
225 _rl_argcxt = 0;
226}
227
228/* Start a numeric argument with initial value KEY */
229int
230rl_digit_argument (ignore, key)
231 int ignore __attribute__((unused)), key;
232{
233 _rl_arg_init ();
234 if (RL_ISSTATE (RL_STATE_CALLBACK))
235 {
236 _rl_arg_dispatch (_rl_argcxt, key);
237 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
238 return 0;
239 }
240 else
241 {
242 rl_execute_next (key);
243 return (rl_digit_loop ());
244 }
245}
246
247/* C-u, universal argument. Multiply the current argument by 4.
248 Read a key. If the key has nothing to do with arguments, then
249 dispatch on it. If the key is the abort character then abort. */
250int
251rl_universal_argument (count, key)
252 int count __attribute__((unused)), key __attribute__((unused));
253{
254 _rl_arg_init ();
255 rl_numeric_arg *= 4;
256
257 return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
258}
259
260int
261_rl_arg_callback (cxt)
262 _rl_arg_cxt cxt;
263{
264 int c, r;
265
266 c = _rl_arg_getchar ();
267
268 if (_rl_argcxt & NUM_READONE)
269 {
270 _rl_argcxt &= ~NUM_READONE;
271 rl_restore_prompt ();
272 rl_clear_message ();
273 RL_UNSETSTATE(RL_STATE_NUMERICARG);
274 rl_execute_next (c);
275 return 0;
276 }
277
278 r = _rl_arg_dispatch (cxt, c);
279 return (r != 1);
280}
281
282/* What to do when you abort reading an argument. */
283int
284rl_discard_argument ()
285{
286 rl_ding ();
287 rl_clear_message ();
288 _rl_reset_argument ();
289
290 return 0;
291}
292
293/* **************************************************************** */
294/* */
295/* History Utilities */
296/* */
297/* **************************************************************** */
298
299/* We already have a history library, and that is what we use to control
300 the history features of readline. This is our local interface to
301 the history mechanism. */
302
303/* While we are editing the history, this is the saved
304 version of the original line. */
305HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
306
307/* Set the history pointer back to the last entry in the history. */
308void
309_rl_start_using_history ()
310{
311 using_history ();
312 if (_rl_saved_line_for_history)
313 _rl_free_history_entry (_rl_saved_line_for_history);
314
315 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
316}
317
318/* Free the contents (and containing structure) of a HIST_ENTRY. */
319void
320_rl_free_history_entry (entry)
321 HIST_ENTRY *entry;
322{
323 if (entry == 0)
324 return;
325
326 FREE (entry->line);
327 FREE (entry->timestamp);
328
329 free (entry);
330}
331
332/* Perhaps put back the current line if it has changed. */
333int
334rl_maybe_replace_line ()
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);
343 free (temp->line);
344 FREE (temp->timestamp);
345 free (temp);
346 }
347 return 0;
348}
349
350/* Restore the _rl_saved_line_for_history if there is one. */
351int
352rl_maybe_unsave_line ()
353{
354 if (_rl_saved_line_for_history)
355 {
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. */
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
371rl_maybe_save_line ()
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);
377 _rl_saved_line_for_history->timestamp = (char *)NULL;
378 _rl_saved_line_for_history->data = (char *)rl_undo_list;
379 }
380
381 return 0;
382}
383
384int
385_rl_free_saved_history_line ()
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
396_rl_history_set_point ()
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)
405 if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
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
414rl_replace_from_history (entry, flags)
415 HIST_ENTRY *entry;
416 int flags __attribute__((unused)); /* currently unused */
417{
418 /* Can't call with `1' because rl_undo_list might point to an undo list
419 from a history entry, just like we're setting up here. */
420 rl_replace_line (entry->line, 0);
421 rl_undo_list = (UNDO_LIST *)entry->data;
422 rl_point = rl_end;
423 rl_mark = 0;
424
425#if defined (VI_MODE)
426 if (rl_editing_mode == vi_mode)
427 {
428 rl_point = 0;
429 rl_mark = rl_end;
430 }
431#endif
432}
433
434/* **************************************************************** */
435/* */
436/* History Commands */
437/* */
438/* **************************************************************** */
439
440/* Meta-< goes to the start of the history. */
441int
442rl_beginning_of_history (count, key)
443 int count __attribute__((unused)), key;
444{
445 return (rl_get_previous_history (1 + where_history (), key));
446}
447
448/* Meta-> goes to the end of the history. (The current line). */
449int
450rl_end_of_history (count, key)
451 int count __attribute__((unused)), key __attribute__((unused));
452{
453 rl_maybe_replace_line ();
454 using_history ();
455 rl_maybe_unsave_line ();
456 return 0;
457}
458
459/* Move down to the next history line. */
460int
461rl_get_next_history (count, key)
462 int count, key;
463{
464 HIST_ENTRY *temp;
465
466 if (count < 0)
467 return (rl_get_previous_history (-count, key));
468
469 if (count == 0)
470 return 0;
471
472 rl_maybe_replace_line ();
473
474 /* either not saved by rl_newline or at end of line, so set appropriately. */
475 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
476 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
477
478 temp = (HIST_ENTRY *)NULL;
479 while (count)
480 {
481 temp = next_history ();
482 if (!temp)
483 break;
484 --count;
485 }
486
487 if (temp == 0)
488 rl_maybe_unsave_line ();
489 else
490 {
491 rl_replace_from_history (temp, 0);
492 _rl_history_set_point ();
493 }
494 return 0;
495}
496
497/* Get the previous item out of our interactive history, making it the current
498 line. If there is no previous history, just ding. */
499int
500rl_get_previous_history (count, key)
501 int count, key;
502{
503 HIST_ENTRY *old_temp, *temp;
504
505 if (count < 0)
506 return (rl_get_next_history (-count, key));
507
508 if (count == 0)
509 return 0;
510
511 /* either not saved by rl_newline or at end of line, so set appropriately. */
512 if (_rl_history_saved_point == -1 && (rl_point || rl_end))
513 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
514
515 /* If we don't have a line saved, then save this one. */
516 rl_maybe_save_line ();
517
518 /* If the current line has changed, save the changes. */
519 rl_maybe_replace_line ();
520
521 temp = old_temp = (HIST_ENTRY *)NULL;
522 while (count)
523 {
524 temp = previous_history ();
525 if (temp == 0)
526 break;
527
528 old_temp = temp;
529 --count;
530 }
531
532 /* If there was a large argument, and we moved back to the start of the
533 history, that is not an error. So use the last value found. */
534 if (!temp && old_temp)
535 temp = old_temp;
536
537 if (temp == 0)
538 rl_ding ();
539 else
540 {
541 rl_replace_from_history (temp, 0);
542 _rl_history_set_point ();
543 }
544
545 return 0;
546}
547
548/* **************************************************************** */
549/* */
550/* Editing Modes */
551/* */
552/* **************************************************************** */
553/* How to toggle back and forth between editing modes. */
554int
555rl_vi_editing_mode (count, key)
556 int count __attribute__((unused)), key;
557{
558#if defined (VI_MODE)
559 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
560 rl_editing_mode = vi_mode;
561 rl_vi_insertion_mode (1, key);
562#endif /* VI_MODE */
563
564 return 0;
565}
566
567int
568rl_emacs_editing_mode (count, key)
569 int count __attribute__((unused)), key __attribute__((unused));
570{
571 rl_editing_mode = emacs_mode;
572 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
573 _rl_keymap = emacs_standard_keymap;
574 return 0;
575}
576
577/* Function for the rest of the library to use to set insert/overwrite mode. */
578void
579_rl_set_insert_mode (im, force)
580 int im, force __attribute__((unused));
581{
582#ifdef CURSOR_MODE
583 _rl_set_cursor (im, force);
584#endif
585
586 rl_insert_mode = im;
587}
588
589/* Toggle overwrite mode. A positive explicit argument selects overwrite
590 mode. A negative or zero explicit argument selects insert mode. */
591int
592rl_overwrite_mode (count, key)
593 int count, key __attribute__((unused));
594{
595 if (rl_explicit_arg == 0)
596 _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
597 else if (count > 0)
598 _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
599 else
600 _rl_set_insert_mode (RL_IM_INSERT, 0);
601
602 return 0;
603}
604