Annotation of embedaddon/readline/misc.c, revision 1.1
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 */
! 464: /* Undo all changes to this history entry */
! 465: while (rl_undo_list)
! 466: rl_do_undo ();
! 467: /* And copy the reverted line back to the history entry, preserving
! 468: the timestamp. */
! 469: FREE (entry->line);
! 470: entry->line = savestring (rl_line_buffer);
! 471: entry->data = 0;
! 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>