Merge from vendor branch NTPD:
[dragonfly.git] / contrib / readline-5.0 / misc.c
1 /* misc.c -- miscellaneous bindable readline functions. */
2
3 /* Copyright (C) 1987-2004 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       /* Can't call with `1' because rl_undo_list might point to an undo
257          list from a history entry, as in rl_replace_from_history() below. */
258       rl_replace_line (_rl_saved_line_for_history->line, 0);
259       rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
260       _rl_free_history_entry (_rl_saved_line_for_history);
261       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
262       rl_point = rl_end;        /* rl_replace_line sets rl_end */
263     }
264   else
265     rl_ding ();
266   return 0;
267 }
268
269 /* Save the current line in _rl_saved_line_for_history. */
270 int
271 rl_maybe_save_line ()
272 {
273   if (_rl_saved_line_for_history == 0)
274     {
275       _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
276       _rl_saved_line_for_history->line = savestring (rl_line_buffer);
277       _rl_saved_line_for_history->data = (char *)rl_undo_list;
278     }
279   else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0)
280     {
281       free (_rl_saved_line_for_history->line);
282       _rl_saved_line_for_history->line = savestring (rl_line_buffer);
283       _rl_saved_line_for_history->data = (char *)rl_undo_list;  /* XXX possible memleak */
284     }
285
286   return 0;
287 }
288
289 int
290 _rl_free_saved_history_line ()
291 {
292   if (_rl_saved_line_for_history)
293     {
294       _rl_free_history_entry (_rl_saved_line_for_history);
295       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
296     }
297   return 0;
298 }
299
300 static void
301 _rl_history_set_point ()
302 {
303   rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
304                 ? _rl_history_saved_point
305                 : rl_end;
306   if (rl_point > rl_end)
307     rl_point = rl_end;
308
309 #if defined (VI_MODE)
310   if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
311     rl_point = 0;
312 #endif /* VI_MODE */
313
314   if (rl_editing_mode == emacs_mode)
315     rl_mark = (rl_point == rl_end ? 0 : rl_end);
316 }
317
318 void
319 rl_replace_from_history (entry, flags)
320      HIST_ENTRY *entry;
321      int flags;                 /* currently unused */
322 {
323   /* Can't call with `1' because rl_undo_list might point to an undo list
324      from a history entry, just like we're setting up here. */
325   rl_replace_line (entry->line, 0);
326   rl_undo_list = (UNDO_LIST *)entry->data;
327   rl_point = rl_end;
328   rl_mark = 0;
329
330 #if defined (VI_MODE)
331   if (rl_editing_mode == vi_mode)
332     {
333       rl_point = 0;
334       rl_mark = rl_end;
335     }
336 #endif
337 }  
338
339 /* **************************************************************** */
340 /*                                                                  */
341 /*                      History Commands                            */
342 /*                                                                  */
343 /* **************************************************************** */
344
345 /* Meta-< goes to the start of the history. */
346 int
347 rl_beginning_of_history (count, key)
348      int count, key;
349 {
350   return (rl_get_previous_history (1 + where_history (), key));
351 }
352
353 /* Meta-> goes to the end of the history.  (The current line). */
354 int
355 rl_end_of_history (count, key)
356      int count, key;
357 {
358   rl_maybe_replace_line ();
359   using_history ();
360   rl_maybe_unsave_line ();
361   return 0;
362 }
363
364 /* Move down to the next history line. */
365 int
366 rl_get_next_history (count, key)
367      int count, key;
368 {
369   HIST_ENTRY *temp;
370
371   if (count < 0)
372     return (rl_get_previous_history (-count, key));
373
374   if (count == 0)
375     return 0;
376
377   rl_maybe_replace_line ();
378
379   /* either not saved by rl_newline or at end of line, so set appropriately. */
380   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
381     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
382
383   temp = (HIST_ENTRY *)NULL;
384   while (count)
385     {
386       temp = next_history ();
387       if (!temp)
388         break;
389       --count;
390     }
391
392   if (temp == 0)
393     rl_maybe_unsave_line ();
394   else
395     {
396       rl_replace_from_history (temp, 0);
397       _rl_history_set_point ();
398     }
399   return 0;
400 }
401
402 /* Get the previous item out of our interactive history, making it the current
403    line.  If there is no previous history, just ding. */
404 int
405 rl_get_previous_history (count, key)
406      int count, key;
407 {
408   HIST_ENTRY *old_temp, *temp;
409
410   if (count < 0)
411     return (rl_get_next_history (-count, key));
412
413   if (count == 0)
414     return 0;
415
416   /* either not saved by rl_newline or at end of line, so set appropriately. */
417   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
418     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
419
420   /* If we don't have a line saved, then save this one. */
421   rl_maybe_save_line ();
422
423   /* If the current line has changed, save the changes. */
424   rl_maybe_replace_line ();
425
426   temp = old_temp = (HIST_ENTRY *)NULL;
427   while (count)
428     {
429       temp = previous_history ();
430       if (temp == 0)
431         break;
432
433       old_temp = temp;
434       --count;
435     }
436
437   /* If there was a large argument, and we moved back to the start of the
438      history, that is not an error.  So use the last value found. */
439   if (!temp && old_temp)
440     temp = old_temp;
441
442   if (temp == 0)
443     rl_ding ();
444   else
445     {
446       rl_replace_from_history (temp, 0);
447       _rl_history_set_point ();
448     }
449
450   return 0;
451 }
452
453 /* **************************************************************** */
454 /*                                                                  */
455 /*                          Editing Modes                           */
456 /*                                                                  */
457 /* **************************************************************** */
458 /* How to toggle back and forth between editing modes. */
459 int
460 rl_vi_editing_mode (count, key)
461      int count, key;
462 {
463 #if defined (VI_MODE)
464   _rl_set_insert_mode (RL_IM_INSERT, 1);        /* vi mode ignores insert mode */
465   rl_editing_mode = vi_mode;
466   rl_vi_insertion_mode (1, key);
467 #endif /* VI_MODE */
468
469   return 0;
470 }
471
472 int
473 rl_emacs_editing_mode (count, key)
474      int count, key;
475 {
476   rl_editing_mode = emacs_mode;
477   _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
478   _rl_keymap = emacs_standard_keymap;
479   return 0;
480 }
481
482 /* Function for the rest of the library to use to set insert/overwrite mode. */
483 void
484 _rl_set_insert_mode (im, force)
485      int im, force;
486 {
487 #ifdef CURSOR_MODE
488   _rl_set_cursor (im, force);
489 #endif
490
491   rl_insert_mode = im;
492 }
493
494 /* Toggle overwrite mode.  A positive explicit argument selects overwrite
495    mode.  A negative or zero explicit argument selects insert mode. */
496 int
497 rl_overwrite_mode (count, key)
498      int count, key;
499 {
500   if (rl_explicit_arg == 0)
501     _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
502   else if (count > 0)
503     _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
504   else
505     _rl_set_insert_mode (RL_IM_INSERT, 0);
506
507   return 0;
508 }