]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/libreadline/misc.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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           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. */
193 static int
194 rl_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. */
220 void
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 */
229 int
230 rl_digit_argument (ignore, key)
231      int ignore, 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. */
250 int
251 rl_universal_argument (count, key)
252      int count, key;
253 {
254   _rl_arg_init ();
255   rl_numeric_arg *= 4;
256
257   return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
258 }
259
260 int
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. */
283 int
284 rl_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. */
305 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
306
307 /* Set the history pointer back to the last entry in the history. */
308 void
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. */
319 void
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. */
333 int
334 rl_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. */
351 int
352 rl_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. */
370 int
371 rl_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
384 int
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
395 static 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
413 void
414 rl_replace_from_history (entry, flags)
415      HIST_ENTRY *entry;
416      int flags;                 /* 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. */
441 int
442 rl_beginning_of_history (count, key)
443      int count, 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). */
449 int
450 rl_end_of_history (count, key)
451      int count, key;
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. */
460 int
461 rl_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. */
499 int
500 rl_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. */
554 int
555 rl_vi_editing_mode (count, key)
556      int count, 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
567 int
568 rl_emacs_editing_mode (count, key)
569      int count, key;
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. */
578 void
579 _rl_set_insert_mode (im, force)
580      int im, force;
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. */
591 int
592 rl_overwrite_mode (count, key)
593      int count, key;
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 }