]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libreadline/misc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libreadline / misc.c
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    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
56 static int rl_digit_loop PARAMS((void));
57 static void _rl_history_set_point PARAMS((void));
58
59 /* Forward declarations used in this file */
60 void _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. */
64 int _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. */
70 int _rl_history_saved_point = -1;
71
72 /* **************************************************************** */
73 /*                                                                  */
74 /*                      Numeric Arguments                           */
75 /*                                                                  */
76 /* **************************************************************** */
77
78 int
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
94 void
95 _rl_arg_init ()
96 {
97   rl_save_prompt ();
98   _rl_argcxt = 0;
99   RL_SETSTATE(RL_STATE_NUMERICARG);
100 }
101
102 int
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. */
118 int
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. */
195 static int
196 rl_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. */
222 void
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 */
231 int
232 rl_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. */
252 int
253 rl_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
262 int
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. */
285 int
286 rl_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. */
307 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
308
309 /* Set the history pointer back to the last entry in the history. */
310 void
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. */
321 void
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. */
335 int
336 rl_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. */
353 int
354 rl_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. */
372 int
373 rl_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
386 int
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
397 static 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
415 void
416 rl_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 /* **************************************************************** */
437 /*                                                                  */
438 /*                      History Commands                            */
439 /*                                                                  */
440 /* **************************************************************** */
441
442 /* Meta-< goes to the start of the history. */
443 int
444 rl_beginning_of_history (count, key)
445      int count, key;
446 {
447   return (rl_get_previous_history (1 + where_history (), key));
448 }
449
450 /* Meta-> goes to the end of the history.  (The current line). */
451 int
452 rl_end_of_history (count, key)
453      int count, key;
454 {
455   rl_maybe_replace_line ();
456   using_history ();
457   rl_maybe_unsave_line ();
458   return 0;
459 }
460
461 /* Move down to the next history line. */
462 int
463 rl_get_next_history (count, key)
464      int count, key;
465 {
466   HIST_ENTRY *temp;
467
468   if (count < 0)
469     return (rl_get_previous_history (-count, key));
470
471   if (count == 0)
472     return 0;
473
474   rl_maybe_replace_line ();
475
476   /* either not saved by rl_newline or at end of line, so set appropriately. */
477   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
478     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
479
480   temp = (HIST_ENTRY *)NULL;
481   while (count)
482     {
483       temp = next_history ();
484       if (!temp)
485         break;
486       --count;
487     }
488
489   if (temp == 0)
490     rl_maybe_unsave_line ();
491   else
492     {
493       rl_replace_from_history (temp, 0);
494       _rl_history_set_point ();
495     }
496   return 0;
497 }
498
499 /* Get the previous item out of our interactive history, making it the current
500    line.  If there is no previous history, just ding. */
501 int
502 rl_get_previous_history (count, key)
503      int count, key;
504 {
505   HIST_ENTRY *old_temp, *temp;
506
507   if (count < 0)
508     return (rl_get_next_history (-count, key));
509
510   if (count == 0)
511     return 0;
512
513   /* either not saved by rl_newline or at end of line, so set appropriately. */
514   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
515     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
516
517   /* If we don't have a line saved, then save this one. */
518   rl_maybe_save_line ();
519
520   /* If the current line has changed, save the changes. */
521   rl_maybe_replace_line ();
522
523   temp = old_temp = (HIST_ENTRY *)NULL;
524   while (count)
525     {
526       temp = previous_history ();
527       if (temp == 0)
528         break;
529
530       old_temp = temp;
531       --count;
532     }
533
534   /* If there was a large argument, and we moved back to the start of the
535      history, that is not an error.  So use the last value found. */
536   if (!temp && old_temp)
537     temp = old_temp;
538
539   if (temp == 0)
540     rl_ding ();
541   else
542     {
543       rl_replace_from_history (temp, 0);
544       _rl_history_set_point ();
545     }
546
547   return 0;
548 }
549
550 /* **************************************************************** */
551 /*                                                                  */
552 /*                          Editing Modes                           */
553 /*                                                                  */
554 /* **************************************************************** */
555 /* How to toggle back and forth between editing modes. */
556 int
557 rl_vi_editing_mode (count, key)
558      int count, key;
559 {
560 #if defined (VI_MODE)
561   _rl_set_insert_mode (RL_IM_INSERT, 1);        /* vi mode ignores insert mode */
562   rl_editing_mode = vi_mode;
563   rl_vi_insertion_mode (1, key);
564 #endif /* VI_MODE */
565
566   return 0;
567 }
568
569 int
570 rl_emacs_editing_mode (count, key)
571      int count, key;
572 {
573   rl_editing_mode = emacs_mode;
574   _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
575   _rl_keymap = emacs_standard_keymap;
576   return 0;
577 }
578
579 /* Function for the rest of the library to use to set insert/overwrite mode. */
580 void
581 _rl_set_insert_mode (im, force)
582      int im, force;
583 {
584 #ifdef CURSOR_MODE
585   _rl_set_cursor (im, force);
586 #endif
587
588   rl_insert_mode = im;
589 }
590
591 /* Toggle overwrite mode.  A positive explicit argument selects overwrite
592    mode.  A negative or zero explicit argument selects insert mode. */
593 int
594 rl_overwrite_mode (count, key)
595      int count, key;
596 {
597   if (rl_explicit_arg == 0)
598     _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
599   else if (count > 0)
600     _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
601   else
602     _rl_set_insert_mode (RL_IM_INSERT, 0);
603
604   return 0;
605 }