Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / lib / readline / misc.c
1 /* misc.c -- miscellaneous bindable readline functions. */
2
3 /* Copyright (C) 1987-2002 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 /* Saved target point for when _rl_history_preserve_point is set.  Special
67    value of -1 means that point is at the end of the line. */
68 int _rl_history_saved_point = -1;
69
70 /* **************************************************************** */
71 /*                                                                  */
72 /*                      Numeric Arguments                           */
73 /*                                                                  */
74 /* **************************************************************** */
75
76 /* Handle C-u style numeric args, as well as M--, and M-digits. */
77 static int
78 rl_digit_loop ()
79 {
80   int key, c, sawminus, sawdigits;
81
82   rl_save_prompt ();
83
84   RL_SETSTATE(RL_STATE_NUMERICARG);
85   sawminus = sawdigits = 0;
86   while (1)
87     {
88       if (rl_numeric_arg > 1000000)
89         {
90           sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
91           rl_ding ();
92           rl_restore_prompt ();
93           rl_clear_message ();
94           RL_UNSETSTATE(RL_STATE_NUMERICARG);
95           return 1;
96         }
97       rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
98       RL_SETSTATE(RL_STATE_MOREINPUT);
99       key = c = rl_read_key ();
100       RL_UNSETSTATE(RL_STATE_MOREINPUT);
101
102       if (c < 0)
103         {
104           _rl_abort_internal ();
105           return -1;
106         }
107
108       /* If we see a key bound to `universal-argument' after seeing digits,
109          it ends the argument but is otherwise ignored. */
110       if (_rl_keymap[c].type == ISFUNC &&
111           _rl_keymap[c].function == rl_universal_argument)
112         {
113           if (sawdigits == 0)
114             {
115               rl_numeric_arg *= 4;
116               continue;
117             }
118           else
119             {
120               RL_SETSTATE(RL_STATE_MOREINPUT);
121               key = rl_read_key ();
122               RL_UNSETSTATE(RL_STATE_MOREINPUT);
123               rl_restore_prompt ();
124               rl_clear_message ();
125               RL_UNSETSTATE(RL_STATE_NUMERICARG);
126               return (_rl_dispatch (key, _rl_keymap));
127             }
128         }
129
130       c = UNMETA (c);
131
132       if (_rl_digit_p (c))
133         {
134           rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
135           sawdigits = rl_explicit_arg = 1;
136         }
137       else if (c == '-' && rl_explicit_arg == 0)
138         {
139           rl_numeric_arg = sawminus = 1;
140           rl_arg_sign = -1;
141         }
142       else
143         {
144           /* Make M-- command equivalent to M--1 command. */
145           if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
146             rl_explicit_arg = 1;
147           rl_restore_prompt ();
148           rl_clear_message ();
149           RL_UNSETSTATE(RL_STATE_NUMERICARG);
150           return (_rl_dispatch (key, _rl_keymap));
151         }
152     }
153
154   /*NOTREACHED*/
155 }
156
157 /* Add the current digit to the argument in progress. */
158 int
159 rl_digit_argument (ignore, key)
160      int ignore, key;
161 {
162   rl_execute_next (key);
163   return (rl_digit_loop ());
164 }
165
166 /* What to do when you abort reading an argument. */
167 int
168 rl_discard_argument ()
169 {
170   rl_ding ();
171   rl_clear_message ();
172   _rl_init_argument ();
173   return 0;
174 }
175
176 /* Create a default argument. */
177 int
178 _rl_init_argument ()
179 {
180   rl_numeric_arg = rl_arg_sign = 1;
181   rl_explicit_arg = 0;
182   return 0;
183 }
184
185 /* C-u, universal argument.  Multiply the current argument by 4.
186    Read a key.  If the key has nothing to do with arguments, then
187    dispatch on it.  If the key is the abort character then abort. */
188 int
189 rl_universal_argument (count, key)
190      int count, key;
191 {
192   rl_numeric_arg *= 4;
193   return (rl_digit_loop ());
194 }
195
196 /* **************************************************************** */
197 /*                                                                  */
198 /*                      History Utilities                           */
199 /*                                                                  */
200 /* **************************************************************** */
201
202 /* We already have a history library, and that is what we use to control
203    the history features of readline.  This is our local interface to
204    the history mechanism. */
205
206 /* While we are editing the history, this is the saved
207    version of the original line. */
208 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
209
210 /* Set the history pointer back to the last entry in the history. */
211 void
212 _rl_start_using_history ()
213 {
214   using_history ();
215   if (_rl_saved_line_for_history)
216     _rl_free_history_entry (_rl_saved_line_for_history);
217
218   _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
219 }
220
221 /* Free the contents (and containing structure) of a HIST_ENTRY. */
222 void
223 _rl_free_history_entry (entry)
224      HIST_ENTRY *entry;
225 {
226   if (entry == 0)
227     return;
228   if (entry->line)
229     free (entry->line);
230   free (entry);
231 }
232
233 /* Perhaps put back the current line if it has changed. */
234 int
235 rl_maybe_replace_line ()
236 {
237   HIST_ENTRY *temp;
238
239   temp = current_history ();
240   /* If the current line has changed, save the changes. */
241   if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
242     {
243       temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
244       free (temp->line);
245       free (temp);
246     }
247   return 0;
248 }
249
250 /* Restore the _rl_saved_line_for_history if there is one. */
251 int
252 rl_maybe_unsave_line ()
253 {
254   if (_rl_saved_line_for_history)
255     {
256       rl_replace_line (_rl_saved_line_for_history->line, 0);
257       rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
258       _rl_free_history_entry (_rl_saved_line_for_history);
259       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
260       rl_point = rl_end;        /* rl_replace_line sets rl_end */
261     }
262   else
263     rl_ding ();
264   return 0;
265 }
266
267 /* Save the current line in _rl_saved_line_for_history. */
268 int
269 rl_maybe_save_line ()
270 {
271   if (_rl_saved_line_for_history == 0)
272     {
273       _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
274       _rl_saved_line_for_history->line = savestring (rl_line_buffer);
275       _rl_saved_line_for_history->data = (char *)rl_undo_list;
276     }
277   return 0;
278 }
279
280 int
281 _rl_free_saved_history_line ()
282 {
283   if (_rl_saved_line_for_history)
284     {
285       _rl_free_history_entry (_rl_saved_line_for_history);
286       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
287     }
288   return 0;
289 }
290
291 static void
292 _rl_history_set_point ()
293 {
294   rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
295                 ? _rl_history_saved_point
296                 : rl_end;
297   if (rl_point > rl_end)
298     rl_point = rl_end;
299
300 #if defined (VI_MODE)
301   if (rl_editing_mode == vi_mode)
302     rl_point = 0;
303 #endif /* VI_MODE */
304
305   if (rl_editing_mode == emacs_mode)
306     rl_mark = (rl_point == rl_end ? 0 : rl_end);
307 }
308
309 void
310 rl_replace_from_history (entry, flags)
311      HIST_ENTRY *entry;
312      int flags;                 /* currently unused */
313 {
314   rl_replace_line (entry->line, 0);
315   rl_undo_list = (UNDO_LIST *)entry->data;
316   rl_point = rl_end;
317   rl_mark = 0;
318
319 #if defined (VI_MODE)
320   if (rl_editing_mode == vi_mode)
321     {
322       rl_point = 0;
323       rl_mark = rl_end;
324     }
325 #endif
326 }  
327
328 /* **************************************************************** */
329 /*                                                                  */
330 /*                      History Commands                            */
331 /*                                                                  */
332 /* **************************************************************** */
333
334 /* Meta-< goes to the start of the history. */
335 int
336 rl_beginning_of_history (count, key)
337      int count, key;
338 {
339   return (rl_get_previous_history (1 + where_history (), key));
340 }
341
342 /* Meta-> goes to the end of the history.  (The current line). */
343 int
344 rl_end_of_history (count, key)
345      int count, key;
346 {
347   rl_maybe_replace_line ();
348   using_history ();
349   rl_maybe_unsave_line ();
350   return 0;
351 }
352
353 /* Move down to the next history line. */
354 int
355 rl_get_next_history (count, key)
356      int count, key;
357 {
358   HIST_ENTRY *temp;
359
360   if (count < 0)
361     return (rl_get_previous_history (-count, key));
362
363   if (count == 0)
364     return 0;
365
366   rl_maybe_replace_line ();
367
368   /* either not saved by rl_newline or at end of line, so set appropriately. */
369   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
370     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
371
372   temp = (HIST_ENTRY *)NULL;
373   while (count)
374     {
375       temp = next_history ();
376       if (!temp)
377         break;
378       --count;
379     }
380
381   if (temp == 0)
382     rl_maybe_unsave_line ();
383   else
384     {
385       rl_replace_from_history (temp, 0);
386       _rl_history_set_point ();
387     }
388   return 0;
389 }
390
391 /* Get the previous item out of our interactive history, making it the current
392    line.  If there is no previous history, just ding. */
393 int
394 rl_get_previous_history (count, key)
395      int count, key;
396 {
397   HIST_ENTRY *old_temp, *temp;
398
399   if (count < 0)
400     return (rl_get_next_history (-count, key));
401
402   if (count == 0)
403     return 0;
404
405   /* either not saved by rl_newline or at end of line, so set appropriately. */
406   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
407     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
408
409   /* If we don't have a line saved, then save this one. */
410   rl_maybe_save_line ();
411
412   /* If the current line has changed, save the changes. */
413   rl_maybe_replace_line ();
414
415   temp = old_temp = (HIST_ENTRY *)NULL;
416   while (count)
417     {
418       temp = previous_history ();
419       if (temp == 0)
420         break;
421
422       old_temp = temp;
423       --count;
424     }
425
426   /* If there was a large argument, and we moved back to the start of the
427      history, that is not an error.  So use the last value found. */
428   if (!temp && old_temp)
429     temp = old_temp;
430
431   if (temp == 0)
432     rl_ding ();
433   else
434     {
435       rl_replace_from_history (temp, 0);
436       _rl_history_set_point ();
437     }
438   return 0;
439 }
440
441 /* **************************************************************** */
442 /*                                                                  */
443 /*                          Editing Modes                           */
444 /*                                                                  */
445 /* **************************************************************** */
446 /* How to toggle back and forth between editing modes. */
447 int
448 rl_vi_editing_mode (count, key)
449      int count, key;
450 {
451 #if defined (VI_MODE)
452   _rl_set_insert_mode (RL_IM_INSERT, 1);        /* vi mode ignores insert mode */
453   rl_editing_mode = vi_mode;
454   rl_vi_insertion_mode (1, key);
455 #endif /* VI_MODE */
456
457   return 0;
458 }
459
460 int
461 rl_emacs_editing_mode (count, key)
462      int count, key;
463 {
464   rl_editing_mode = emacs_mode;
465   _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
466   _rl_keymap = emacs_standard_keymap;
467   return 0;
468 }
469
470 /* Function for the rest of the library to use to set insert/overwrite mode. */
471 void
472 _rl_set_insert_mode (im, force)
473      int im, force;
474 {
475 #ifdef CURSOR_MODE
476   _rl_set_cursor (im, force);
477 #endif
478
479   rl_insert_mode = im;
480 }
481
482 /* Toggle overwrite mode.  A positive explicit argument selects overwrite
483    mode.  A negative or zero explicit argument selects insert mode. */
484 int
485 rl_overwrite_mode (count, key)
486      int count, key;
487 {
488   if (rl_explicit_arg == 0)
489     _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
490   else if (count > 0)
491     _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
492   else
493     _rl_set_insert_mode (RL_IM_INSERT, 0);
494
495   return 0;
496 }