1/* misc.c -- miscellaneous bindable readline functions. */
2
3/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
4
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.
7
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
11   (at your option) any later version.
12
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
16   GNU General Public License for more details.
17
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
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_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	  if (key < 0)
150	    return -1;
151	  return (_rl_dispatch (key, _rl_keymap));
152	}
153    }
154
155  c = UNMETA (c);
156
157  if (_rl_digit_p (c))
158    {
159      r = _rl_digit_value (c);
160      rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) +  r : r;
161      rl_explicit_arg = 1;
162      _rl_argcxt |= NUM_SAWDIGITS;
163    }
164  else if (c == '-' && rl_explicit_arg == 0)
165    {
166      rl_numeric_arg = 1;
167      _rl_argcxt |= NUM_SAWMINUS;
168      rl_arg_sign = -1;
169    }
170  else
171    {
172      /* Make M-- command equivalent to M--1 command. */
173      if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
174	rl_explicit_arg = 1;
175      rl_restore_prompt ();
176      rl_clear_message ();
177      RL_UNSETSTATE(RL_STATE_NUMERICARG);
178
179      r = _rl_dispatch (key, _rl_keymap);
180      if (RL_ISSTATE (RL_STATE_CALLBACK))
181	{
182	  /* At worst, this will cause an extra redisplay.  Otherwise,
183	     we have to wait until the next character comes in. */
184	  if (rl_done == 0)
185	    (*rl_redisplay_function) ();
186	  r = 0;
187	}
188      return r;
189    }
190
191  return 1;
192}
193
194/* Handle C-u style numeric args, as well as M--, and M-digits. */
195static int
196rl_digit_loop ()
197{
198  int c, r;
199
200  while (1)
201    {
202      if (_rl_arg_overflow ())
203	return 1;
204
205      c = _rl_arg_getchar ();
206
207      if (c < 0)
208	{
209	  _rl_abort_internal ();
210	  return -1;
211	}
212
213      r = _rl_arg_dispatch (_rl_argcxt, c);
214      if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
215        break;
216    }
217
218  return r;
219}
220
221/* Create a default argument. */
222void
223_rl_reset_argument ()
224{
225  rl_numeric_arg = rl_arg_sign = 1;
226  rl_explicit_arg = 0;
227  _rl_argcxt = 0;
228}
229
230/* Start a numeric argument with initial value KEY */
231int
232rl_digit_argument (ignore, key)
233     int ignore, key;
234{
235  _rl_arg_init ();
236  if (RL_ISSTATE (RL_STATE_CALLBACK))
237    {
238      _rl_arg_dispatch (_rl_argcxt, key);
239      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
240      return 0;
241    }
242  else
243    {
244      rl_execute_next (key);
245      return (rl_digit_loop ());
246    }
247}
248
249/* C-u, universal argument.  Multiply the current argument by 4.
250   Read a key.  If the key has nothing to do with arguments, then
251   dispatch on it.  If the key is the abort character then abort. */
252int
253rl_universal_argument (count, key)
254     int count, key;
255{
256  _rl_arg_init ();
257  rl_numeric_arg *= 4;
258
259  return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
260}
261
262int
263_rl_arg_callback (cxt)
264     _rl_arg_cxt cxt;
265{
266  int c, r;
267
268  c = _rl_arg_getchar ();
269
270  if (_rl_argcxt & NUM_READONE)
271    {
272      _rl_argcxt &= ~NUM_READONE;
273      rl_restore_prompt ();
274      rl_clear_message ();
275      RL_UNSETSTATE(RL_STATE_NUMERICARG);
276      rl_execute_next (c);
277      return 0;
278    }
279
280  r = _rl_arg_dispatch (cxt, c);
281  return (r != 1);
282}
283
284/* What to do when you abort reading an argument. */
285int
286rl_discard_argument ()
287{
288  rl_ding ();
289  rl_clear_message ();
290  _rl_reset_argument ();
291
292  return 0;
293}
294
295/* **************************************************************** */
296/*								    */
297/*			History Utilities			    */
298/*								    */
299/* **************************************************************** */
300
301/* We already have a history library, and that is what we use to control
302   the history features of readline.  This is our local interface to
303   the history mechanism. */
304
305/* While we are editing the history, this is the saved
306   version of the original line. */
307HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
308
309/* Set the history pointer back to the last entry in the history. */
310void
311_rl_start_using_history ()
312{
313  using_history ();
314  if (_rl_saved_line_for_history)
315    _rl_free_history_entry (_rl_saved_line_for_history);
316
317  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
318}
319
320/* Free the contents (and containing structure) of a HIST_ENTRY. */
321void
322_rl_free_history_entry (entry)
323     HIST_ENTRY *entry;
324{
325  if (entry == 0)
326    return;
327
328  FREE (entry->line);
329  FREE (entry->timestamp);
330
331  free (entry);
332}
333
334/* Perhaps put back the current line if it has changed. */
335int
336rl_maybe_replace_line ()
337{
338  HIST_ENTRY *temp;
339
340  temp = current_history ();
341  /* If the current line has changed, save the changes. */
342  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
343    {
344      temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
345      free (temp->line);
346      FREE (temp->timestamp);
347      free (temp);
348    }
349  return 0;
350}
351
352/* Restore the _rl_saved_line_for_history if there is one. */
353int
354rl_maybe_unsave_line ()
355{
356  if (_rl_saved_line_for_history)
357    {
358      /* Can't call with `1' because rl_undo_list might point to an undo
359	 list from a history entry, as in rl_replace_from_history() below. */
360      rl_replace_line (_rl_saved_line_for_history->line, 0);
361      rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
362      _rl_free_history_entry (_rl_saved_line_for_history);
363      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
364      rl_point = rl_end;	/* rl_replace_line sets rl_end */
365    }
366  else
367    rl_ding ();
368  return 0;
369}
370
371/* Save the current line in _rl_saved_line_for_history. */
372int
373rl_maybe_save_line ()
374{
375  if (_rl_saved_line_for_history == 0)
376    {
377      _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
378      _rl_saved_line_for_history->line = savestring (rl_line_buffer);
379      _rl_saved_line_for_history->timestamp = (char *)NULL;
380      _rl_saved_line_for_history->data = (char *)rl_undo_list;
381    }
382
383  return 0;
384}
385
386int
387_rl_free_saved_history_line ()
388{
389  if (_rl_saved_line_for_history)
390    {
391      _rl_free_history_entry (_rl_saved_line_for_history);
392      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
393    }
394  return 0;
395}
396
397static void
398_rl_history_set_point ()
399{
400  rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
401		? _rl_history_saved_point
402		: rl_end;
403  if (rl_point > rl_end)
404    rl_point = rl_end;
405
406#if defined (VI_MODE)
407  if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
408    rl_point = 0;
409#endif /* VI_MODE */
410
411  if (rl_editing_mode == emacs_mode)
412    rl_mark = (rl_point == rl_end ? 0 : rl_end);
413}
414
415void
416rl_replace_from_history (entry, flags)
417     HIST_ENTRY *entry;
418     int flags;			/* currently unused */
419{
420  /* Can't call with `1' because rl_undo_list might point to an undo list
421     from a history entry, just like we're setting up here. */
422  rl_replace_line (entry->line, 0);
423  rl_undo_list = (UNDO_LIST *)entry->data;
424  rl_point = rl_end;
425  rl_mark = 0;
426
427#if defined (VI_MODE)
428  if (rl_editing_mode == vi_mode)
429    {
430      rl_point = 0;
431      rl_mark = rl_end;
432    }
433#endif
434}
435
436/* Process and free undo lists attached to each history entry prior to the
437   current entry, inclusive, reverting each line to its saved state.  This
438   is destructive, and state about the current line is lost.  This is not
439   intended to be called while actively editing, and the current line is
440   not assumed to have been added to the history list. */
441void
442_rl_revert_all_lines ()
443{
444  int hpos;
445  HIST_ENTRY *entry;
446  UNDO_LIST *ul, *saved_undo_list;
447  char *lbuf;
448
449  lbuf = savestring (rl_line_buffer);
450  saved_undo_list = rl_undo_list;
451  hpos = where_history ();
452
453  entry = (hpos == history_length) ? previous_history () : current_history ();
454  while (entry)
455    {
456      if (ul = (UNDO_LIST *)entry->data)
457	{
458	  if (ul == saved_undo_list)
459	    saved_undo_list = 0;
460	  /* Set up rl_line_buffer and other variables from history entry */
461	  rl_replace_from_history (entry, 0);	/* entry->line is now current */
462	  /* Undo all changes to this history entry */
463	  while (rl_undo_list)
464	    rl_do_undo ();
465	  /* And copy the reverted line back to the history entry, preserving
466	     the timestamp. */
467	  FREE (entry->line);
468	  entry->line = savestring (rl_line_buffer);
469	  entry->data = 0;
470	}
471      entry = previous_history ();
472    }
473
474  /* Restore history state */
475  rl_undo_list = saved_undo_list;	/* may have been set to null */
476  history_set_pos (hpos);
477
478  /* reset the line buffer */
479  rl_replace_line (lbuf, 0);
480  _rl_set_the_line ();
481
482  /* and clean up */
483  free (lbuf);
484}
485
486/* **************************************************************** */
487/*								    */
488/*			History Commands			    */
489/*								    */
490/* **************************************************************** */
491
492/* Meta-< goes to the start of the history. */
493int
494rl_beginning_of_history (count, key)
495     int count, key;
496{
497  return (rl_get_previous_history (1 + where_history (), key));
498}
499
500/* Meta-> goes to the end of the history.  (The current line). */
501int
502rl_end_of_history (count, key)
503     int count, key;
504{
505  rl_maybe_replace_line ();
506  using_history ();
507  rl_maybe_unsave_line ();
508  return 0;
509}
510
511/* Move down to the next history line. */
512int
513rl_get_next_history (count, key)
514     int count, key;
515{
516  HIST_ENTRY *temp;
517
518  if (count < 0)
519    return (rl_get_previous_history (-count, key));
520
521  if (count == 0)
522    return 0;
523
524  rl_maybe_replace_line ();
525
526  /* either not saved by rl_newline or at end of line, so set appropriately. */
527  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
528    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
529
530  temp = (HIST_ENTRY *)NULL;
531  while (count)
532    {
533      temp = next_history ();
534      if (!temp)
535	break;
536      --count;
537    }
538
539  if (temp == 0)
540    rl_maybe_unsave_line ();
541  else
542    {
543      rl_replace_from_history (temp, 0);
544      _rl_history_set_point ();
545    }
546  return 0;
547}
548
549/* Get the previous item out of our interactive history, making it the current
550   line.  If there is no previous history, just ding. */
551int
552rl_get_previous_history (count, key)
553     int count, key;
554{
555  HIST_ENTRY *old_temp, *temp;
556
557  if (count < 0)
558    return (rl_get_next_history (-count, key));
559
560  if (count == 0)
561    return 0;
562
563  /* either not saved by rl_newline or at end of line, so set appropriately. */
564  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
565    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
566
567  /* If we don't have a line saved, then save this one. */
568  rl_maybe_save_line ();
569
570  /* If the current line has changed, save the changes. */
571  rl_maybe_replace_line ();
572
573  temp = old_temp = (HIST_ENTRY *)NULL;
574  while (count)
575    {
576      temp = previous_history ();
577      if (temp == 0)
578	break;
579
580      old_temp = temp;
581      --count;
582    }
583
584  /* If there was a large argument, and we moved back to the start of the
585     history, that is not an error.  So use the last value found. */
586  if (!temp && old_temp)
587    temp = old_temp;
588
589  if (temp == 0)
590    rl_ding ();
591  else
592    {
593      rl_replace_from_history (temp, 0);
594      _rl_history_set_point ();
595    }
596
597  return 0;
598}
599
600/* **************************************************************** */
601/*								    */
602/*			    Editing Modes			    */
603/*								    */
604/* **************************************************************** */
605/* How to toggle back and forth between editing modes. */
606int
607rl_vi_editing_mode (count, key)
608     int count, key;
609{
610#if defined (VI_MODE)
611  _rl_set_insert_mode (RL_IM_INSERT, 1);	/* vi mode ignores insert mode */
612  rl_editing_mode = vi_mode;
613  rl_vi_insert_mode (1, key);
614#endif /* VI_MODE */
615
616  return 0;
617}
618
619int
620rl_emacs_editing_mode (count, key)
621     int count, key;
622{
623  rl_editing_mode = emacs_mode;
624  _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
625  _rl_keymap = emacs_standard_keymap;
626  return 0;
627}
628
629/* Function for the rest of the library to use to set insert/overwrite mode. */
630void
631_rl_set_insert_mode (im, force)
632     int im, force;
633{
634#ifdef CURSOR_MODE
635  _rl_set_cursor (im, force);
636#endif
637
638  rl_insert_mode = im;
639}
640
641/* Toggle overwrite mode.  A positive explicit argument selects overwrite
642   mode.  A negative or zero explicit argument selects insert mode. */
643int
644rl_overwrite_mode (count, key)
645     int count, key;
646{
647  if (rl_explicit_arg == 0)
648    _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
649  else if (count > 0)
650    _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
651  else
652    _rl_set_insert_mode (RL_IM_INSERT, 0);
653
654  return 0;
655}
656