Annotation of embedaddon/readline/misc.c, revision 1.1.1.2
1.1 misho 1: /* misc.c -- miscellaneous bindable readline functions. */
2:
3: /* Copyright (C) 1987-2012 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:
56: static int rl_digit_loop PARAMS((void));
57: static void _rl_history_set_point PARAMS((void));
58:
59: extern int history_offset;
60:
61: /* Forward declarations used in this file */
62: void _rl_free_history_entry PARAMS((HIST_ENTRY *));
63:
64: /* If non-zero, rl_get_previous_history and rl_get_next_history attempt
65: to preserve the value of rl_point from line to line. */
66: int _rl_history_preserve_point = 0;
67:
68: _rl_arg_cxt _rl_argcxt;
69:
70: /* Saved target point for when _rl_history_preserve_point is set. Special
71: value of -1 means that point is at the end of the line. */
72: int _rl_history_saved_point = -1;
73:
74: /* **************************************************************** */
75: /* */
76: /* Numeric Arguments */
77: /* */
78: /* **************************************************************** */
79:
80: int
81: _rl_arg_overflow ()
82: {
83: if (rl_numeric_arg > 1000000)
84: {
85: _rl_argcxt = 0;
86: rl_explicit_arg = rl_numeric_arg = 0;
87: rl_ding ();
88: rl_restore_prompt ();
89: rl_clear_message ();
90: RL_UNSETSTATE(RL_STATE_NUMERICARG);
91: return 1;
92: }
93: return 0;
94: }
95:
96: void
97: _rl_arg_init ()
98: {
99: rl_save_prompt ();
100: _rl_argcxt = 0;
101: RL_SETSTATE(RL_STATE_NUMERICARG);
102: }
103:
104: int
105: _rl_arg_getchar ()
106: {
107: int c;
108:
109: rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
110: RL_SETSTATE(RL_STATE_MOREINPUT);
111: c = rl_read_key ();
112: RL_UNSETSTATE(RL_STATE_MOREINPUT);
113:
114: return c;
115: }
116:
117: /* Process C as part of the current numeric argument. Return -1 if the
118: argument should be aborted, 0 if we should not read any more chars, and
119: 1 if we should continue to read chars. */
120: int
121: _rl_arg_dispatch (cxt, c)
122: _rl_arg_cxt cxt;
123: int c;
124: {
125: int key, r;
126:
127: key = c;
128:
129: /* If we see a key bound to `universal-argument' after seeing digits,
130: it ends the argument but is otherwise ignored. */
131: if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
132: {
133: if ((cxt & NUM_SAWDIGITS) == 0)
134: {
135: rl_numeric_arg *= 4;
136: return 1;
137: }
138: else if (RL_ISSTATE (RL_STATE_CALLBACK))
139: {
140: _rl_argcxt |= NUM_READONE;
141: return 0; /* XXX */
142: }
143: else
144: {
145: RL_SETSTATE(RL_STATE_MOREINPUT);
146: key = rl_read_key ();
147: RL_UNSETSTATE(RL_STATE_MOREINPUT);
148: rl_restore_prompt ();
149: rl_clear_message ();
150: RL_UNSETSTATE(RL_STATE_NUMERICARG);
151: if (key < 0)
152: return -1;
153: return (_rl_dispatch (key, _rl_keymap));
154: }
155: }
156:
157: c = UNMETA (c);
158:
159: if (_rl_digit_p (c))
160: {
161: r = _rl_digit_value (c);
162: rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
163: rl_explicit_arg = 1;
164: _rl_argcxt |= NUM_SAWDIGITS;
165: }
166: else if (c == '-' && rl_explicit_arg == 0)
167: {
168: rl_numeric_arg = 1;
169: _rl_argcxt |= NUM_SAWMINUS;
170: rl_arg_sign = -1;
171: }
172: else
173: {
174: /* Make M-- command equivalent to M--1 command. */
175: if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
176: rl_explicit_arg = 1;
177: rl_restore_prompt ();
178: rl_clear_message ();
179: RL_UNSETSTATE(RL_STATE_NUMERICARG);
180:
181: r = _rl_dispatch (key, _rl_keymap);
182: if (RL_ISSTATE (RL_STATE_CALLBACK))
183: {
184: /* At worst, this will cause an extra redisplay. Otherwise,
185: we have to wait until the next character comes in. */
186: if (rl_done == 0)
187: (*rl_redisplay_function) ();
188: r = 0;
189: }
190: return r;
191: }
192:
193: return 1;
194: }
195:
196: /* Handle C-u style numeric args, as well as M--, and M-digits. */
197: static int
198: rl_digit_loop ()
199: {
200: int c, r;
201:
202: while (1)
203: {
204: if (_rl_arg_overflow ())
205: return 1;
206:
207: c = _rl_arg_getchar ();
208:
209: if (c < 0)
210: {
211: _rl_abort_internal ();
212: return -1;
213: }
214:
215: r = _rl_arg_dispatch (_rl_argcxt, c);
216: if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
217: break;
218: }
219:
220: return r;
221: }
222:
223: /* Create a default argument. */
224: void
225: _rl_reset_argument ()
226: {
227: rl_numeric_arg = rl_arg_sign = 1;
228: rl_explicit_arg = 0;
229: _rl_argcxt = 0;
230: }
231:
232: /* Start a numeric argument with initial value KEY */
233: int
234: rl_digit_argument (ignore, key)
235: int ignore, key;
236: {
237: _rl_arg_init ();
238: if (RL_ISSTATE (RL_STATE_CALLBACK))
239: {
240: _rl_arg_dispatch (_rl_argcxt, key);
241: rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
242: return 0;
243: }
244: else
245: {
246: rl_execute_next (key);
247: return (rl_digit_loop ());
248: }
249: }
250:
251: /* C-u, universal argument. Multiply the current argument by 4.
252: Read a key. If the key has nothing to do with arguments, then
253: dispatch on it. If the key is the abort character then abort. */
254: int
255: rl_universal_argument (count, key)
256: int count, key;
257: {
258: _rl_arg_init ();
259: rl_numeric_arg *= 4;
260:
261: return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
262: }
263:
264: int
265: _rl_arg_callback (cxt)
266: _rl_arg_cxt cxt;
267: {
268: int c, r;
269:
270: c = _rl_arg_getchar ();
271:
272: if (_rl_argcxt & NUM_READONE)
273: {
274: _rl_argcxt &= ~NUM_READONE;
275: rl_restore_prompt ();
276: rl_clear_message ();
277: RL_UNSETSTATE(RL_STATE_NUMERICARG);
278: rl_execute_next (c);
279: return 0;
280: }
281:
282: r = _rl_arg_dispatch (cxt, c);
283: return (r != 1);
284: }
285:
286: /* What to do when you abort reading an argument. */
287: int
288: rl_discard_argument ()
289: {
290: rl_ding ();
291: rl_clear_message ();
292: _rl_reset_argument ();
293:
294: return 0;
295: }
296:
297: /* **************************************************************** */
298: /* */
299: /* History Utilities */
300: /* */
301: /* **************************************************************** */
302:
303: /* We already have a history library, and that is what we use to control
304: the history features of readline. This is our local interface to
305: the history mechanism. */
306:
307: /* While we are editing the history, this is the saved
308: version of the original line. */
309: HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
310:
311: /* Set the history pointer back to the last entry in the history. */
312: void
313: _rl_start_using_history ()
314: {
315: using_history ();
316: if (_rl_saved_line_for_history)
317: _rl_free_history_entry (_rl_saved_line_for_history);
318:
319: _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
320: }
321:
322: /* Free the contents (and containing structure) of a HIST_ENTRY. */
323: void
324: _rl_free_history_entry (entry)
325: HIST_ENTRY *entry;
326: {
327: if (entry == 0)
328: return;
329:
330: FREE (entry->line);
331: FREE (entry->timestamp);
332:
333: xfree (entry);
334: }
335:
336: /* Perhaps put back the current line if it has changed. */
337: int
338: rl_maybe_replace_line ()
339: {
340: HIST_ENTRY *temp;
341:
342: temp = current_history ();
343: /* If the current line has changed, save the changes. */
344: if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
345: {
346: temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
347: xfree (temp->line);
348: FREE (temp->timestamp);
349: xfree (temp);
350: }
351: return 0;
352: }
353:
354: /* Restore the _rl_saved_line_for_history if there is one. */
355: int
356: rl_maybe_unsave_line ()
357: {
358: if (_rl_saved_line_for_history)
359: {
360: /* Can't call with `1' because rl_undo_list might point to an undo
361: list from a history entry, as in rl_replace_from_history() below. */
362: rl_replace_line (_rl_saved_line_for_history->line, 0);
363: rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
364: _rl_free_history_entry (_rl_saved_line_for_history);
365: _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
366: rl_point = rl_end; /* rl_replace_line sets rl_end */
367: }
368: else
369: rl_ding ();
370: return 0;
371: }
372:
373: /* Save the current line in _rl_saved_line_for_history. */
374: int
375: rl_maybe_save_line ()
376: {
377: if (_rl_saved_line_for_history == 0)
378: {
379: _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
380: _rl_saved_line_for_history->line = savestring (rl_line_buffer);
381: _rl_saved_line_for_history->timestamp = (char *)NULL;
382: _rl_saved_line_for_history->data = (char *)rl_undo_list;
383: }
384:
385: return 0;
386: }
387:
388: int
389: _rl_free_saved_history_line ()
390: {
391: if (_rl_saved_line_for_history)
392: {
393: _rl_free_history_entry (_rl_saved_line_for_history);
394: _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
395: }
396: return 0;
397: }
398:
399: static void
400: _rl_history_set_point ()
401: {
402: rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
403: ? _rl_history_saved_point
404: : rl_end;
405: if (rl_point > rl_end)
406: rl_point = rl_end;
407:
408: #if defined (VI_MODE)
409: if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
410: rl_point = 0;
411: #endif /* VI_MODE */
412:
413: if (rl_editing_mode == emacs_mode)
414: rl_mark = (rl_point == rl_end ? 0 : rl_end);
415: }
416:
417: void
418: rl_replace_from_history (entry, flags)
419: HIST_ENTRY *entry;
420: int flags; /* currently unused */
421: {
422: /* Can't call with `1' because rl_undo_list might point to an undo list
423: from a history entry, just like we're setting up here. */
424: rl_replace_line (entry->line, 0);
425: rl_undo_list = (UNDO_LIST *)entry->data;
426: rl_point = rl_end;
427: rl_mark = 0;
428:
429: #if defined (VI_MODE)
430: if (rl_editing_mode == vi_mode)
431: {
432: rl_point = 0;
433: rl_mark = rl_end;
434: }
435: #endif
436: }
437:
438: /* Process and free undo lists attached to each history entry prior to the
439: current entry, inclusive, reverting each line to its saved state. This
440: is destructive, and state about the current line is lost. This is not
441: intended to be called while actively editing, and the current line is
442: not assumed to have been added to the history list. */
443: void
444: _rl_revert_all_lines ()
445: {
446: int hpos;
447: HIST_ENTRY *entry;
448: UNDO_LIST *ul, *saved_undo_list;
449: char *lbuf;
450:
451: lbuf = savestring (rl_line_buffer);
452: saved_undo_list = rl_undo_list;
453: hpos = where_history ();
454:
455: entry = (hpos == history_length) ? previous_history () : current_history ();
456: while (entry)
457: {
458: if (ul = (UNDO_LIST *)entry->data)
459: {
460: if (ul == saved_undo_list)
461: saved_undo_list = 0;
462: /* Set up rl_line_buffer and other variables from history entry */
463: rl_replace_from_history (entry, 0); /* entry->line is now current */
1.1.1.2 ! misho 464: entry->data = 0; /* entry->data is now current undo list */
1.1 misho 465: /* Undo all changes to this history entry */
466: while (rl_undo_list)
467: rl_do_undo ();
468: /* And copy the reverted line back to the history entry, preserving
469: the timestamp. */
470: FREE (entry->line);
471: entry->line = savestring (rl_line_buffer);
472: }
473: entry = previous_history ();
474: }
475:
476: /* Restore history state */
477: rl_undo_list = saved_undo_list; /* may have been set to null */
478: history_set_pos (hpos);
479:
480: /* reset the line buffer */
481: rl_replace_line (lbuf, 0);
482: _rl_set_the_line ();
483:
484: /* and clean up */
485: xfree (lbuf);
486: }
487:
488: /* Free the history list, including private readline data and take care
489: of pointer aliases to history data. Resets rl_undo_list if it points
490: to an UNDO_LIST * saved as some history entry's data member. This
491: should not be called while editing is active. */
492: void
493: rl_clear_history ()
494: {
495: HIST_ENTRY **hlist, *hent;
496: register int i;
497: UNDO_LIST *ul, *saved_undo_list;
498:
499: saved_undo_list = rl_undo_list;
500: hlist = history_list (); /* direct pointer, not copy */
501:
502: for (i = 0; i < history_length; i++)
503: {
504: hent = hlist[i];
505: if (ul = (UNDO_LIST *)hent->data)
506: {
507: if (ul == saved_undo_list)
508: saved_undo_list = 0;
509: _rl_free_undo_list (ul);
510: hent->data = 0;
511: }
512: _rl_free_history_entry (hent);
513: }
514:
515: history_offset = history_length = 0;
516: rl_undo_list = saved_undo_list; /* should be NULL */
517: }
518:
519: /* **************************************************************** */
520: /* */
521: /* History Commands */
522: /* */
523: /* **************************************************************** */
524:
525: /* Meta-< goes to the start of the history. */
526: int
527: rl_beginning_of_history (count, key)
528: int count, key;
529: {
530: return (rl_get_previous_history (1 + where_history (), key));
531: }
532:
533: /* Meta-> goes to the end of the history. (The current line). */
534: int
535: rl_end_of_history (count, key)
536: int count, key;
537: {
538: rl_maybe_replace_line ();
539: using_history ();
540: rl_maybe_unsave_line ();
541: return 0;
542: }
543:
544: /* Move down to the next history line. */
545: int
546: rl_get_next_history (count, key)
547: int count, key;
548: {
549: HIST_ENTRY *temp;
550:
551: if (count < 0)
552: return (rl_get_previous_history (-count, key));
553:
554: if (count == 0)
555: return 0;
556:
557: rl_maybe_replace_line ();
558:
559: /* either not saved by rl_newline or at end of line, so set appropriately. */
560: if (_rl_history_saved_point == -1 && (rl_point || rl_end))
561: _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
562:
563: temp = (HIST_ENTRY *)NULL;
564: while (count)
565: {
566: temp = next_history ();
567: if (!temp)
568: break;
569: --count;
570: }
571:
572: if (temp == 0)
573: rl_maybe_unsave_line ();
574: else
575: {
576: rl_replace_from_history (temp, 0);
577: _rl_history_set_point ();
578: }
579: return 0;
580: }
581:
582: /* Get the previous item out of our interactive history, making it the current
583: line. If there is no previous history, just ding. */
584: int
585: rl_get_previous_history (count, key)
586: int count, key;
587: {
588: HIST_ENTRY *old_temp, *temp;
589:
590: if (count < 0)
591: return (rl_get_next_history (-count, key));
592:
593: if (count == 0)
594: return 0;
595:
596: /* either not saved by rl_newline or at end of line, so set appropriately. */
597: if (_rl_history_saved_point == -1 && (rl_point || rl_end))
598: _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
599:
600: /* If we don't have a line saved, then save this one. */
601: rl_maybe_save_line ();
602:
603: /* If the current line has changed, save the changes. */
604: rl_maybe_replace_line ();
605:
606: temp = old_temp = (HIST_ENTRY *)NULL;
607: while (count)
608: {
609: temp = previous_history ();
610: if (temp == 0)
611: break;
612:
613: old_temp = temp;
614: --count;
615: }
616:
617: /* If there was a large argument, and we moved back to the start of the
618: history, that is not an error. So use the last value found. */
619: if (!temp && old_temp)
620: temp = old_temp;
621:
622: if (temp == 0)
623: rl_ding ();
624: else
625: {
626: rl_replace_from_history (temp, 0);
627: _rl_history_set_point ();
628: }
629:
630: return 0;
631: }
632:
633: /* **************************************************************** */
634: /* */
635: /* Editing Modes */
636: /* */
637: /* **************************************************************** */
638: /* How to toggle back and forth between editing modes. */
639: int
640: rl_vi_editing_mode (count, key)
641: int count, key;
642: {
643: #if defined (VI_MODE)
644: _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
645: rl_editing_mode = vi_mode;
646: rl_vi_insert_mode (1, key);
647: #endif /* VI_MODE */
648:
649: return 0;
650: }
651:
652: int
653: rl_emacs_editing_mode (count, key)
654: int count, key;
655: {
656: rl_editing_mode = emacs_mode;
657: _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
658: _rl_keymap = emacs_standard_keymap;
659:
660: if (_rl_show_mode_in_prompt)
661: _rl_reset_prompt ();
662:
663: return 0;
664: }
665:
666: /* Function for the rest of the library to use to set insert/overwrite mode. */
667: void
668: _rl_set_insert_mode (im, force)
669: int im, force;
670: {
671: #ifdef CURSOR_MODE
672: _rl_set_cursor (im, force);
673: #endif
674:
675: rl_insert_mode = im;
676: }
677:
678: /* Toggle overwrite mode. A positive explicit argument selects overwrite
679: mode. A negative or zero explicit argument selects insert mode. */
680: int
681: rl_overwrite_mode (count, key)
682: int count, key;
683: {
684: if (rl_explicit_arg == 0)
685: _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
686: else if (count > 0)
687: _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
688: else
689: _rl_set_insert_mode (RL_IM_INSERT, 0);
690:
691: return 0;
692: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>