|
|
1.1 ! root 1: /* readline.c -- a general facility for reading lines of input ! 2: with emacs style editing and completion. */ ! 3: ! 4: /* Copyright 1987, 1989, 1991, 1992 Free Software Foundation, Inc. ! 5: ! 6: This file contains the Readline Library (the Library), a set of ! 7: routines for providing Emacs style line input to programs that ask ! 8: for it. ! 9: ! 10: The Library is free software; you can redistribute it and/or modify ! 11: it under the terms of the GNU General Public License as published by ! 12: the Free Software Foundation; either version 2 of the License, or ! 13: (at your option) any later version. ! 14: ! 15: The Library is distributed in the hope that it will be useful, ! 16: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 17: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 18: GNU General Public License for more details. ! 19: ! 20: You should have received a copy of the GNU General Public License ! 21: along with this program; if not, write to the Free Software ! 22: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 23: ! 24: /* Remove these declarations when we have a complete libgnu.a. */ ! 25: /* #define STATIC_MALLOC */ ! 26: #if !defined (STATIC_MALLOC) ! 27: extern char *xmalloc (), *xrealloc (); ! 28: #else ! 29: static char *xmalloc (), *xrealloc (); ! 30: #endif /* STATIC_MALLOC */ ! 31: ! 32: #include "sysdep.h" ! 33: #include <sys/types.h> ! 34: #include <stdio.h> ! 35: #include <fcntl.h> ! 36: #ifndef NO_SYS_FILE ! 37: #include <sys/file.h> ! 38: #endif ! 39: #include <signal.h> ! 40: ! 41: #if defined (HAVE_UNISTD_H) ! 42: # include <unistd.h> ! 43: #endif ! 44: ! 45: #define NEW_TTY_DRIVER ! 46: #define HAVE_BSD_SIGNALS ! 47: /* #define USE_XON_XOFF */ ! 48: ! 49: #ifdef __MSDOS__ ! 50: #undef NEW_TTY_DRIVER ! 51: #undef HAVE_BSD_SIGNALS ! 52: #endif ! 53: ! 54: /* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */ ! 55: #if defined (USG) && !defined (hpux) ! 56: #undef HAVE_BSD_SIGNALS ! 57: #endif ! 58: ! 59: /* System V machines use termio. */ ! 60: #if !defined (_POSIX_VERSION) ! 61: # if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) ! 62: # undef NEW_TTY_DRIVER ! 63: # define TERMIO_TTY_DRIVER ! 64: # include <termio.h> ! 65: # if !defined (TCOON) ! 66: # define TCOON 1 ! 67: # endif ! 68: # endif /* USG || hpux || Xenix || sgi || DUGX */ ! 69: #endif /* !_POSIX_VERSION */ ! 70: ! 71: /* Posix systems use termios and the Posix signal functions. */ ! 72: #if defined (_POSIX_VERSION) ! 73: # if !defined (TERMIOS_MISSING) ! 74: # undef NEW_TTY_DRIVER ! 75: # define TERMIOS_TTY_DRIVER ! 76: # include <termios.h> ! 77: # endif /* !TERMIOS_MISSING */ ! 78: # define HAVE_POSIX_SIGNALS ! 79: # if !defined (O_NDELAY) ! 80: # define O_NDELAY O_NONBLOCK /* Posix-style non-blocking i/o */ ! 81: # endif /* O_NDELAY */ ! 82: #endif /* _POSIX_VERSION */ ! 83: ! 84: /* Other (BSD) machines use sgtty. */ ! 85: #if defined (NEW_TTY_DRIVER) ! 86: #include <sgtty.h> ! 87: #endif ! 88: ! 89: /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and ! 90: it is not already defined. It is used both to determine if a ! 91: special character is disabled and to disable certain special ! 92: characters. Posix systems should set to 0, USG systems to -1. */ ! 93: #if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE) ! 94: # if defined (_POSIX_VERSION) ! 95: # define _POSIX_VDISABLE 0 ! 96: # else /* !_POSIX_VERSION */ ! 97: # define _POSIX_VDISABLE -1 ! 98: # endif /* !_POSIX_VERSION */ ! 99: #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ ! 100: ! 101: /* Define some macros for dealing with assorted signalling disciplines. ! 102: ! 103: These macros provide a way to use signal blocking and disabling ! 104: without smothering your code in a pile of #ifdef's. ! 105: ! 106: SIGNALS_UNBLOCK; Stop blocking all signals. ! 107: ! 108: { ! 109: SIGNALS_DECLARE_SAVED (name); Declare a variable to save the ! 110: signal blocking state. ! 111: ... ! 112: SIGNALS_BLOCK (SIGSTOP, name); Block a signal, and save the previous ! 113: state for restoration later. ! 114: ... ! 115: SIGNALS_RESTORE (name); Restore previous signals. ! 116: } ! 117: ! 118: */ ! 119: ! 120: #ifdef HAVE_POSIX_SIGNALS ! 121: /* POSIX signals */ ! 122: ! 123: #define SIGNALS_UNBLOCK \ ! 124: do { sigset_t set; \ ! 125: sigemptyset (&set); \ ! 126: sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); \ ! 127: } while (0) ! 128: ! 129: #define SIGNALS_DECLARE_SAVED(name) sigset_t name ! 130: ! 131: #define SIGNALS_BLOCK(SIG, saved) \ ! 132: do { sigset_t set; \ ! 133: sigemptyset (&set); \ ! 134: sigaddset (&set, SIG); \ ! 135: sigprocmask (SIG_BLOCK, &set, &saved); \ ! 136: } while (0) ! 137: ! 138: #define SIGNALS_RESTORE(saved) \ ! 139: sigprocmask (SIG_SETMASK, &saved, (sigset_t *)NULL) ! 140: ! 141: ! 142: #else /* HAVE_POSIX_SIGNALS */ ! 143: #ifdef HAVE_BSD_SIGNALS ! 144: /* BSD signals */ ! 145: ! 146: #define SIGNALS_UNBLOCK sigsetmask (0) ! 147: #define SIGNALS_DECLARE_SAVED(name) int name ! 148: #define SIGNALS_BLOCK(SIG, saved) saved = sigblock (sigmask (SIG)) ! 149: #define SIGNALS_RESTORE(saved) sigsetmask (saved) ! 150: ! 151: ! 152: #else /* HAVE_BSD_SIGNALS */ ! 153: /* None of the Above */ ! 154: ! 155: #define SIGNALS_UNBLOCK /* nothing */ ! 156: #define SIGNALS_DECLARE_SAVED(name) /* nothing */ ! 157: #define SIGNALS_BLOCK(SIG, saved) /* nothing */ ! 158: #define SIGNALS_RESTORE(saved) /* nothing */ ! 159: ! 160: ! 161: #endif /* HAVE_BSD_SIGNALS */ ! 162: #endif /* HAVE_POSIX_SIGNALS */ ! 163: ! 164: /* End of signal handling definitions. */ ! 165: ! 166: ! 167: #include <errno.h> ! 168: extern int errno; ! 169: ! 170: #include <setjmp.h> ! 171: #include <sys/stat.h> ! 172: ! 173: /* Posix macro to check file in statbuf for directory-ness. */ ! 174: #if defined (S_IFDIR) && !defined (S_ISDIR) ! 175: #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) ! 176: #endif ! 177: ! 178: #ifndef __MSDOS__ ! 179: /* These next are for filename completion. Perhaps this belongs ! 180: in a different place. */ ! 181: #include <pwd.h> ! 182: #endif /* __MSDOS__ */ ! 183: ! 184: #if defined (USG) && !defined (isc386) && !defined (sgi) ! 185: struct passwd *getpwuid (), *getpwent (); ! 186: #endif ! 187: ! 188: /* #define HACK_TERMCAP_MOTION */ ! 189: ! 190: /* Some standard library routines. */ ! 191: #include "readline.h" ! 192: #include "history.h" ! 193: ! 194: #ifndef digit ! 195: #define digit(c) ((c) >= '0' && (c) <= '9') ! 196: #endif ! 197: ! 198: #ifndef isletter ! 199: #define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) ! 200: #endif ! 201: ! 202: #ifndef digit_value ! 203: #define digit_value(c) ((c) - '0') ! 204: #endif ! 205: ! 206: #ifndef member ! 207: #define member(c, s) ((c) ? index ((s), (c)) : 0) ! 208: #endif ! 209: ! 210: #ifndef isident ! 211: #define isident(c) ((isletter(c) || digit(c) || c == '_')) ! 212: #endif ! 213: ! 214: #ifndef exchange ! 215: #define exchange(x, y) {int temp = x; x = y; y = temp;} ! 216: #endif ! 217: ! 218: #if !defined (rindex) ! 219: extern char *rindex (); ! 220: #endif /* rindex */ ! 221: ! 222: #if !defined (index) ! 223: extern char *index (); ! 224: #endif /* index */ ! 225: ! 226: extern char *getenv (); ! 227: extern char *tilde_expand (); ! 228: ! 229: static update_line (); ! 230: static void output_character_function (); ! 231: static delete_chars (); ! 232: static void insert_some_chars (); ! 233: ! 234: #if defined (VOID_SIGHANDLER) ! 235: # define sighandler void ! 236: #else ! 237: # define sighandler int ! 238: #endif /* VOID_SIGHANDLER */ ! 239: ! 240: /* This typedef is equivalant to the one for Function; it allows us ! 241: to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ ! 242: typedef sighandler SigHandler (); ! 243: ! 244: /* If on, then readline handles signals in a way that doesn't screw. */ ! 245: #define HANDLE_SIGNALS ! 246: ! 247: #ifdef __GO32__ ! 248: #include <sys/pc.h> ! 249: #undef HANDLE_SIGNALS ! 250: #endif ! 251: ! 252: ! 253: /* **************************************************************** */ ! 254: /* */ ! 255: /* Line editing input utility */ ! 256: /* */ ! 257: /* **************************************************************** */ ! 258: ! 259: /* A pointer to the keymap that is currently in use. ! 260: By default, it is the standard emacs keymap. */ ! 261: Keymap keymap = emacs_standard_keymap; ! 262: ! 263: #define no_mode -1 ! 264: #define vi_mode 0 ! 265: #define emacs_mode 1 ! 266: ! 267: /* The current style of editing. */ ! 268: int rl_editing_mode = emacs_mode; ! 269: ! 270: /* Non-zero if the previous command was a kill command. */ ! 271: static int last_command_was_kill = 0; ! 272: ! 273: /* The current value of the numeric argument specified by the user. */ ! 274: int rl_numeric_arg = 1; ! 275: ! 276: /* Non-zero if an argument was typed. */ ! 277: int rl_explicit_arg = 0; ! 278: ! 279: /* Temporary value used while generating the argument. */ ! 280: int rl_arg_sign = 1; ! 281: ! 282: /* Non-zero means we have been called at least once before. */ ! 283: static int rl_initialized = 0; ! 284: ! 285: /* If non-zero, this program is running in an EMACS buffer. */ ! 286: static char *running_in_emacs = (char *)NULL; ! 287: ! 288: /* The current offset in the current input line. */ ! 289: int rl_point; ! 290: ! 291: /* Mark in the current input line. */ ! 292: int rl_mark; ! 293: ! 294: /* Length of the current input line. */ ! 295: int rl_end; ! 296: ! 297: /* Make this non-zero to return the current input_line. */ ! 298: int rl_done; ! 299: ! 300: /* The last function executed by readline. */ ! 301: Function *rl_last_func = (Function *)NULL; ! 302: ! 303: /* Top level environment for readline_internal (). */ ! 304: static jmp_buf readline_top_level; ! 305: ! 306: /* The streams we interact with. */ ! 307: static FILE *in_stream, *out_stream; ! 308: ! 309: /* The names of the streams that we do input and output to. */ ! 310: FILE *rl_instream, *rl_outstream; ! 311: ! 312: /* Non-zero means echo characters as they are read. */ ! 313: int readline_echoing_p = 1; ! 314: ! 315: /* Current prompt. */ ! 316: char *rl_prompt; ! 317: ! 318: /* The number of characters read in order to type this complete command. */ ! 319: int rl_key_sequence_length = 0; ! 320: ! 321: /* If non-zero, then this is the address of a function to call just ! 322: before readline_internal () prints the first prompt. */ ! 323: Function *rl_startup_hook = (Function *)NULL; ! 324: ! 325: /* If non-zero, then this is the address of a function to call when ! 326: completing on a directory name. The function is called with ! 327: the address of a string (the current directory name) as an arg. */ ! 328: Function *rl_symbolic_link_hook = (Function *)NULL; ! 329: ! 330: /* What we use internally. You should always refer to RL_LINE_BUFFER. */ ! 331: static char *the_line; ! 332: ! 333: /* The character that can generate an EOF. Really read from ! 334: the terminal driver... just defaulted here. */ ! 335: static int eof_char = CTRL ('D'); ! 336: ! 337: /* Non-zero makes this the next keystroke to read. */ ! 338: int rl_pending_input = 0; ! 339: ! 340: /* Pointer to a useful terminal name. */ ! 341: char *rl_terminal_name = (char *)NULL; ! 342: ! 343: /* Line buffer and maintenence. */ ! 344: char *rl_line_buffer = (char *)NULL; ! 345: int rl_line_buffer_len = 0; ! 346: #define DEFAULT_BUFFER_SIZE 256 ! 347: ! 348: ! 349: /* **************************************************************** */ ! 350: /* */ ! 351: /* `Forward' declarations */ ! 352: /* */ ! 353: /* **************************************************************** */ ! 354: ! 355: /* Non-zero means do not parse any lines other than comments and ! 356: parser directives. */ ! 357: static unsigned char parsing_conditionalized_out = 0; ! 358: ! 359: /* Caseless strcmp (). */ ! 360: static int stricmp (), strnicmp (); ! 361: static char *strpbrk (); ! 362: ! 363: /* Non-zero means to save keys that we dispatch on in a kbd macro. */ ! 364: static int defining_kbd_macro = 0; ! 365: ! 366: ! 367: /* **************************************************************** */ ! 368: /* */ ! 369: /* Top Level Functions */ ! 370: /* */ ! 371: /* **************************************************************** */ ! 372: ! 373: static void rl_prep_terminal (), rl_deprep_terminal (); ! 374: static void clear_to_eol (), rl_generic_bind (); ! 375: ! 376: /* Read a line of input. Prompt with PROMPT. A NULL PROMPT means ! 377: none. A return value of NULL means that EOF was encountered. */ ! 378: char * ! 379: readline (prompt) ! 380: char *prompt; ! 381: { ! 382: char *readline_internal (); ! 383: char *value; ! 384: ! 385: rl_prompt = prompt; ! 386: ! 387: /* If we are at EOF return a NULL string. */ ! 388: if (rl_pending_input == EOF) ! 389: { ! 390: rl_pending_input = 0; ! 391: return ((char *)NULL); ! 392: } ! 393: ! 394: rl_initialize (); ! 395: rl_prep_terminal (); ! 396: ! 397: #if defined (HANDLE_SIGNALS) ! 398: rl_set_signals (); ! 399: #endif ! 400: ! 401: value = readline_internal (); ! 402: rl_deprep_terminal (); ! 403: ! 404: #if defined (HANDLE_SIGNALS) ! 405: rl_clear_signals (); ! 406: #endif ! 407: ! 408: return (value); ! 409: } ! 410: ! 411: /* Read a line of input from the global rl_instream, doing output on ! 412: the global rl_outstream. ! 413: If rl_prompt is non-null, then that is our prompt. */ ! 414: char * ! 415: readline_internal () ! 416: { ! 417: int lastc, c, eof_found; ! 418: ! 419: in_stream = rl_instream; ! 420: out_stream = rl_outstream; ! 421: ! 422: lastc = -1; ! 423: eof_found = 0; ! 424: ! 425: if (rl_startup_hook) ! 426: (*rl_startup_hook) (); ! 427: ! 428: if (!readline_echoing_p) ! 429: { ! 430: if (rl_prompt) ! 431: { ! 432: fprintf (out_stream, "%s", rl_prompt); ! 433: fflush (out_stream); ! 434: } ! 435: } ! 436: else ! 437: { ! 438: rl_on_new_line (); ! 439: rl_redisplay (); ! 440: #if defined (VI_MODE) ! 441: if (rl_editing_mode == vi_mode) ! 442: rl_vi_insertion_mode (); ! 443: #endif /* VI_MODE */ ! 444: } ! 445: ! 446: while (!rl_done) ! 447: { ! 448: int lk = last_command_was_kill; ! 449: int code = setjmp (readline_top_level); ! 450: ! 451: if (code) ! 452: rl_redisplay (); ! 453: ! 454: if (!rl_pending_input) ! 455: { ! 456: /* Then initialize the argument and number of keys read. */ ! 457: rl_init_argument (); ! 458: rl_key_sequence_length = 0; ! 459: } ! 460: ! 461: c = rl_read_key (); ! 462: ! 463: /* EOF typed to a non-blank line is a <NL>. */ ! 464: if (c == EOF && rl_end) ! 465: c = NEWLINE; ! 466: ! 467: /* The character eof_char typed to blank line, and not as the ! 468: previous character is interpreted as EOF. */ ! 469: if (((c == eof_char && lastc != c) || c == EOF) && !rl_end) ! 470: { ! 471: eof_found = 1; ! 472: break; ! 473: } ! 474: ! 475: lastc = c; ! 476: rl_dispatch (c, keymap); ! 477: ! 478: /* If there was no change in last_command_was_kill, then no kill ! 479: has taken place. Note that if input is pending we are reading ! 480: a prefix command, so nothing has changed yet. */ ! 481: if (!rl_pending_input) ! 482: { ! 483: if (lk == last_command_was_kill) ! 484: last_command_was_kill = 0; ! 485: } ! 486: ! 487: #if defined (VI_MODE) ! 488: /* In vi mode, when you exit insert mode, the cursor moves back ! 489: over the previous character. We explicitly check for that here. */ ! 490: if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap) ! 491: rl_vi_check (); ! 492: #endif /* VI_MODE */ ! 493: ! 494: if (!rl_done) ! 495: rl_redisplay (); ! 496: } ! 497: ! 498: /* Restore the original of this history line, iff the line that we ! 499: are editing was originally in the history, AND the line has changed. */ ! 500: { ! 501: HIST_ENTRY *entry = current_history (); ! 502: ! 503: if (entry && rl_undo_list) ! 504: { ! 505: char *temp = savestring (the_line); ! 506: rl_revert_line (); ! 507: entry = replace_history_entry (where_history (), the_line, ! 508: (HIST_ENTRY *)NULL); ! 509: free_history_entry (entry); ! 510: ! 511: strcpy (the_line, temp); ! 512: free (temp); ! 513: } ! 514: } ! 515: ! 516: /* At any rate, it is highly likely that this line has an undo list. Get ! 517: rid of it now. */ ! 518: if (rl_undo_list) ! 519: free_undo_list (); ! 520: ! 521: if (eof_found) ! 522: return (char *)NULL; ! 523: else ! 524: return (savestring (the_line)); ! 525: } ! 526: ! 527: ! 528: /* **************************************************************** */ ! 529: /* */ ! 530: /* Signal Handling */ ! 531: /* */ ! 532: /* **************************************************************** */ ! 533: ! 534: #if defined (SIGWINCH) ! 535: static SigHandler *old_sigwinch = (SigHandler *)NULL; ! 536: ! 537: static sighandler ! 538: rl_handle_sigwinch (sig) ! 539: int sig; ! 540: { ! 541: char *term; ! 542: ! 543: term = rl_terminal_name; ! 544: ! 545: if (readline_echoing_p) ! 546: { ! 547: if (!term) ! 548: term = getenv ("TERM"); ! 549: if (!term) ! 550: term = "dumb"; ! 551: rl_reset_terminal (term); ! 552: #if defined (NOTDEF) ! 553: crlf (); ! 554: rl_forced_update_display (); ! 555: #endif /* NOTDEF */ ! 556: } ! 557: ! 558: if (old_sigwinch && ! 559: old_sigwinch != (SigHandler *)SIG_IGN && ! 560: old_sigwinch != (SigHandler *)SIG_DFL) ! 561: (*old_sigwinch) (sig); ! 562: #if !defined (VOID_SIGHANDLER) ! 563: return (0); ! 564: #endif /* VOID_SIGHANDLER */ ! 565: } ! 566: #endif /* SIGWINCH */ ! 567: ! 568: #if defined (HANDLE_SIGNALS) ! 569: /* Interrupt handling. */ ! 570: static SigHandler ! 571: *old_int = (SigHandler *)NULL, ! 572: *old_tstp = (SigHandler *)NULL, ! 573: *old_ttou = (SigHandler *)NULL, ! 574: *old_ttin = (SigHandler *)NULL, ! 575: *old_cont = (SigHandler *)NULL, ! 576: *old_alrm = (SigHandler *)NULL; ! 577: ! 578: /* Handle an interrupt character. */ ! 579: static sighandler ! 580: rl_signal_handler (sig) ! 581: int sig; ! 582: { ! 583: #if !defined (HAVE_BSD_SIGNALS) ! 584: /* Since the signal will not be blocked while we are in the signal ! 585: handler, ignore it until rl_clear_signals resets the catcher. */ ! 586: if (sig == SIGINT) ! 587: signal (sig, SIG_IGN); ! 588: #endif /* !HAVE_BSD_SIGNALS */ ! 589: ! 590: switch (sig) ! 591: { ! 592: case SIGINT: ! 593: free_undo_list (); ! 594: rl_clear_message (); ! 595: rl_init_argument (); ! 596: ! 597: #if defined (SIGTSTP) ! 598: case SIGTSTP: ! 599: case SIGTTOU: ! 600: case SIGTTIN: ! 601: #endif /* SIGTSTP */ ! 602: case SIGALRM: ! 603: rl_clean_up_for_exit (); ! 604: rl_deprep_terminal (); ! 605: rl_clear_signals (); ! 606: rl_pending_input = 0; ! 607: ! 608: kill (getpid (), sig); ! 609: ! 610: SIGNALS_UNBLOCK; ! 611: ! 612: rl_prep_terminal (); ! 613: rl_set_signals (); ! 614: } ! 615: ! 616: #if !defined (VOID_SIGHANDLER) ! 617: return (0); ! 618: #endif /* !VOID_SIGHANDLER */ ! 619: } ! 620: ! 621: rl_set_signals () ! 622: { ! 623: old_int = (SigHandler *)signal (SIGINT, rl_signal_handler); ! 624: if (old_int == (SigHandler *)SIG_IGN) ! 625: signal (SIGINT, SIG_IGN); ! 626: ! 627: old_alrm = (SigHandler *)signal (SIGALRM, rl_signal_handler); ! 628: if (old_alrm == (SigHandler *)SIG_IGN) ! 629: signal (SIGALRM, SIG_IGN); ! 630: ! 631: #if defined (SIGTSTP) ! 632: old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler); ! 633: if (old_tstp == (SigHandler *)SIG_IGN) ! 634: signal (SIGTSTP, SIG_IGN); ! 635: #endif ! 636: #if defined (SIGTTOU) ! 637: old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler); ! 638: old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler); ! 639: ! 640: if (old_tstp == (SigHandler *)SIG_IGN) ! 641: { ! 642: signal (SIGTTOU, SIG_IGN); ! 643: signal (SIGTTIN, SIG_IGN); ! 644: } ! 645: #endif ! 646: ! 647: #if defined (SIGWINCH) ! 648: old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch); ! 649: #endif ! 650: } ! 651: ! 652: rl_clear_signals () ! 653: { ! 654: signal (SIGINT, old_int); ! 655: signal (SIGALRM, old_alrm); ! 656: ! 657: #if defined (SIGTSTP) ! 658: signal (SIGTSTP, old_tstp); ! 659: #endif ! 660: ! 661: #if defined (SIGTTOU) ! 662: signal (SIGTTOU, old_ttou); ! 663: signal (SIGTTIN, old_ttin); ! 664: #endif ! 665: ! 666: #if defined (SIGWINCH) ! 667: signal (SIGWINCH, old_sigwinch); ! 668: #endif ! 669: } ! 670: #endif /* HANDLE_SIGNALS */ ! 671: ! 672: ! 673: /* **************************************************************** */ ! 674: /* */ ! 675: /* Character Input Buffering */ ! 676: /* */ ! 677: /* **************************************************************** */ ! 678: ! 679: #if defined (USE_XON_XOFF) ! 680: /* If the terminal was in xoff state when we got to it, then xon_char ! 681: contains the character that is supposed to start it again. */ ! 682: static int xon_char, xoff_state; ! 683: #endif /* USE_XON_XOFF */ ! 684: ! 685: static int pop_index = 0, push_index = 0, ibuffer_len = 511; ! 686: static unsigned char ibuffer[512]; ! 687: ! 688: /* Non-null means it is a pointer to a function to run while waiting for ! 689: character input. */ ! 690: Function *rl_event_hook = (Function *)NULL; ! 691: ! 692: #define any_typein (push_index != pop_index) ! 693: ! 694: /* Add KEY to the buffer of characters to be read. */ ! 695: rl_stuff_char (key) ! 696: int key; ! 697: { ! 698: if (key == EOF) ! 699: { ! 700: key = NEWLINE; ! 701: rl_pending_input = EOF; ! 702: } ! 703: ibuffer[push_index++] = key; ! 704: if (push_index >= ibuffer_len) ! 705: push_index = 0; ! 706: } ! 707: ! 708: /* Return the amount of space available in the ! 709: buffer for stuffing characters. */ ! 710: int ! 711: ibuffer_space () ! 712: { ! 713: if (pop_index > push_index) ! 714: return (pop_index - push_index); ! 715: else ! 716: return (ibuffer_len - (push_index - pop_index)); ! 717: } ! 718: ! 719: /* Get a key from the buffer of characters to be read. ! 720: Return the key in KEY. ! 721: Result is KEY if there was a key, or 0 if there wasn't. */ ! 722: int ! 723: rl_get_char (key) ! 724: int *key; ! 725: { ! 726: if (push_index == pop_index) ! 727: return (0); ! 728: ! 729: *key = ibuffer[pop_index++]; ! 730: ! 731: if (pop_index >= ibuffer_len) ! 732: pop_index = 0; ! 733: ! 734: return (1); ! 735: } ! 736: ! 737: /* Stuff KEY into the *front* of the input buffer. ! 738: Returns non-zero if successful, zero if there is ! 739: no space left in the buffer. */ ! 740: int ! 741: rl_unget_char (key) ! 742: int key; ! 743: { ! 744: if (ibuffer_space ()) ! 745: { ! 746: pop_index--; ! 747: if (pop_index < 0) ! 748: pop_index = ibuffer_len - 1; ! 749: ibuffer[pop_index] = key; ! 750: return (1); ! 751: } ! 752: return (0); ! 753: } ! 754: ! 755: /* If a character is available to be read, then read it ! 756: and stuff it into IBUFFER. Otherwise, just return. */ ! 757: rl_gather_tyi () ! 758: { ! 759: #ifdef __GO32__ ! 760: char input; ! 761: if (isatty(0)) ! 762: { ! 763: int i = rl_getc(); ! 764: if (i != EOF) ! 765: rl_stuff_char(i); ! 766: } ! 767: else ! 768: if (kbhit() && ibuffer_space()) ! 769: rl_stuff_char(getkey()); ! 770: #else ! 771: int tty = fileno (in_stream); ! 772: register int tem, result = -1; ! 773: long chars_avail; ! 774: char input; ! 775: ! 776: #if defined (FIONREAD) ! 777: result = ioctl (tty, FIONREAD, &chars_avail); ! 778: #endif ! 779: ! 780: if (result == -1) ! 781: { ! 782: int flags; ! 783: ! 784: flags = fcntl (tty, F_GETFL, 0); ! 785: ! 786: fcntl (tty, F_SETFL, (flags | O_NDELAY)); ! 787: chars_avail = read (tty, &input, 1); ! 788: ! 789: fcntl (tty, F_SETFL, flags); ! 790: if (chars_avail == -1 && errno == EAGAIN) ! 791: return; ! 792: } ! 793: ! 794: /* If there's nothing available, don't waste time trying to read ! 795: something. */ ! 796: if (chars_avail == 0) ! 797: return; ! 798: ! 799: tem = ibuffer_space (); ! 800: ! 801: if (chars_avail > tem) ! 802: chars_avail = tem; ! 803: ! 804: /* One cannot read all of the available input. I can only read a single ! 805: character at a time, or else programs which require input can be ! 806: thwarted. If the buffer is larger than one character, I lose. ! 807: Damn! */ ! 808: if (tem < ibuffer_len) ! 809: chars_avail = 0; ! 810: ! 811: if (result != -1) ! 812: { ! 813: while (chars_avail--) ! 814: rl_stuff_char (rl_getc (in_stream)); ! 815: } ! 816: else ! 817: { ! 818: if (chars_avail) ! 819: rl_stuff_char (input); ! 820: } ! 821: #endif /* def __GO32__/else */ ! 822: } ! 823: ! 824: static int next_macro_key (); ! 825: /* Read a key, including pending input. */ ! 826: int ! 827: rl_read_key () ! 828: { ! 829: int c; ! 830: ! 831: rl_key_sequence_length++; ! 832: ! 833: if (rl_pending_input) ! 834: { ! 835: c = rl_pending_input; ! 836: rl_pending_input = 0; ! 837: } ! 838: else ! 839: { ! 840: /* If input is coming from a macro, then use that. */ ! 841: if (c = next_macro_key ()) ! 842: return (c); ! 843: ! 844: /* If the user has an event function, then call it periodically. */ ! 845: if (rl_event_hook) ! 846: { ! 847: while (rl_event_hook && !rl_get_char (&c)) ! 848: { ! 849: (*rl_event_hook) (); ! 850: rl_gather_tyi (); ! 851: } ! 852: } ! 853: else ! 854: { ! 855: if (!rl_get_char (&c)) ! 856: c = rl_getc (in_stream); ! 857: } ! 858: } ! 859: ! 860: return (c); ! 861: } ! 862: ! 863: /* I'm beginning to hate the declaration rules for various compilers. */ ! 864: static void add_macro_char (), with_macro_input (); ! 865: ! 866: /* Do the command associated with KEY in MAP. ! 867: If the associated command is really a keymap, then read ! 868: another key, and dispatch into that map. */ ! 869: rl_dispatch (key, map) ! 870: register int key; ! 871: Keymap map; ! 872: { ! 873: ! 874: if (defining_kbd_macro) ! 875: add_macro_char (key); ! 876: ! 877: if (key > 127 && key < 256) ! 878: { ! 879: if (map[ESC].type == ISKMAP) ! 880: { ! 881: map = (Keymap)map[ESC].function; ! 882: key -= 128; ! 883: rl_dispatch (key, map); ! 884: } ! 885: else ! 886: ding (); ! 887: return; ! 888: } ! 889: ! 890: switch (map[key].type) ! 891: { ! 892: case ISFUNC: ! 893: { ! 894: Function *func = map[key].function; ! 895: ! 896: if (func != (Function *)NULL) ! 897: { ! 898: /* Special case rl_do_lowercase_version (). */ ! 899: if (func == rl_do_lowercase_version) ! 900: { ! 901: rl_dispatch (to_lower (key), map); ! 902: return; ! 903: } ! 904: ! 905: (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); ! 906: ! 907: /* If we have input pending, then the last command was a prefix ! 908: command. Don't change the state of rl_last_func. Otherwise, ! 909: remember the last command executed in this variable. */ ! 910: if (!rl_pending_input) ! 911: rl_last_func = map[key].function; ! 912: } ! 913: else ! 914: { ! 915: rl_abort (); ! 916: return; ! 917: } ! 918: } ! 919: break; ! 920: ! 921: case ISKMAP: ! 922: if (map[key].function != (Function *)NULL) ! 923: { ! 924: int newkey; ! 925: ! 926: rl_key_sequence_length++; ! 927: newkey = rl_read_key (); ! 928: rl_dispatch (newkey, (Keymap)map[key].function); ! 929: } ! 930: else ! 931: { ! 932: rl_abort (); ! 933: return; ! 934: } ! 935: break; ! 936: ! 937: case ISMACR: ! 938: if (map[key].function != (Function *)NULL) ! 939: { ! 940: char *macro; ! 941: ! 942: macro = savestring ((char *)map[key].function); ! 943: with_macro_input (macro); ! 944: return; ! 945: } ! 946: break; ! 947: } ! 948: } ! 949: ! 950: ! 951: /* **************************************************************** */ ! 952: /* */ ! 953: /* Hacking Keyboard Macros */ ! 954: /* */ ! 955: /* **************************************************************** */ ! 956: ! 957: /* The currently executing macro string. If this is non-zero, ! 958: then it is a malloc ()'ed string where input is coming from. */ ! 959: static char *executing_macro = (char *)NULL; ! 960: ! 961: /* The offset in the above string to the next character to be read. */ ! 962: static int executing_macro_index = 0; ! 963: ! 964: /* The current macro string being built. Characters get stuffed ! 965: in here by add_macro_char (). */ ! 966: static char *current_macro = (char *)NULL; ! 967: ! 968: /* The size of the buffer allocated to current_macro. */ ! 969: static int current_macro_size = 0; ! 970: ! 971: /* The index at which characters are being added to current_macro. */ ! 972: static int current_macro_index = 0; ! 973: ! 974: /* A structure used to save nested macro strings. ! 975: It is a linked list of string/index for each saved macro. */ ! 976: struct saved_macro { ! 977: struct saved_macro *next; ! 978: char *string; ! 979: int index; ! 980: }; ! 981: ! 982: /* The list of saved macros. */ ! 983: struct saved_macro *macro_list = (struct saved_macro *)NULL; ! 984: ! 985: /* Forward declarations of static functions. Thank you C. */ ! 986: static void push_executing_macro (), pop_executing_macro (); ! 987: ! 988: /* This one has to be declared earlier in the file. */ ! 989: /* static void add_macro_char (); */ ! 990: ! 991: /* Set up to read subsequent input from STRING. ! 992: STRING is free ()'ed when we are done with it. */ ! 993: static void ! 994: with_macro_input (string) ! 995: char *string; ! 996: { ! 997: push_executing_macro (); ! 998: executing_macro = string; ! 999: executing_macro_index = 0; ! 1000: } ! 1001: ! 1002: /* Return the next character available from a macro, or 0 if ! 1003: there are no macro characters. */ ! 1004: static int ! 1005: next_macro_key () ! 1006: { ! 1007: if (!executing_macro) ! 1008: return (0); ! 1009: ! 1010: if (!executing_macro[executing_macro_index]) ! 1011: { ! 1012: pop_executing_macro (); ! 1013: return (next_macro_key ()); ! 1014: } ! 1015: ! 1016: return (executing_macro[executing_macro_index++]); ! 1017: } ! 1018: ! 1019: /* Save the currently executing macro on a stack of saved macros. */ ! 1020: static void ! 1021: push_executing_macro () ! 1022: { ! 1023: struct saved_macro *saver; ! 1024: ! 1025: saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); ! 1026: saver->next = macro_list; ! 1027: saver->index = executing_macro_index; ! 1028: saver->string = executing_macro; ! 1029: ! 1030: macro_list = saver; ! 1031: } ! 1032: ! 1033: /* Discard the current macro, replacing it with the one ! 1034: on the top of the stack of saved macros. */ ! 1035: static void ! 1036: pop_executing_macro () ! 1037: { ! 1038: if (executing_macro) ! 1039: free (executing_macro); ! 1040: ! 1041: executing_macro = (char *)NULL; ! 1042: executing_macro_index = 0; ! 1043: ! 1044: if (macro_list) ! 1045: { ! 1046: struct saved_macro *disposer = macro_list; ! 1047: executing_macro = macro_list->string; ! 1048: executing_macro_index = macro_list->index; ! 1049: macro_list = macro_list->next; ! 1050: free (disposer); ! 1051: } ! 1052: } ! 1053: ! 1054: /* Add a character to the macro being built. */ ! 1055: static void ! 1056: add_macro_char (c) ! 1057: int c; ! 1058: { ! 1059: if (current_macro_index + 1 >= current_macro_size) ! 1060: { ! 1061: if (!current_macro) ! 1062: current_macro = (char *)xmalloc (current_macro_size = 25); ! 1063: else ! 1064: current_macro = ! 1065: (char *)xrealloc (current_macro, current_macro_size += 25); ! 1066: } ! 1067: ! 1068: current_macro[current_macro_index++] = c; ! 1069: current_macro[current_macro_index] = '\0'; ! 1070: } ! 1071: ! 1072: /* Begin defining a keyboard macro. ! 1073: Keystrokes are recorded as they are executed. ! 1074: End the definition with rl_end_kbd_macro (). ! 1075: If a numeric argument was explicitly typed, then append this ! 1076: definition to the end of the existing macro, and start by ! 1077: re-executing the existing macro. */ ! 1078: rl_start_kbd_macro (ignore1, ignore2) ! 1079: int ignore1, ignore2; ! 1080: { ! 1081: if (defining_kbd_macro) ! 1082: rl_abort (); ! 1083: ! 1084: if (rl_explicit_arg) ! 1085: { ! 1086: if (current_macro) ! 1087: with_macro_input (savestring (current_macro)); ! 1088: } ! 1089: else ! 1090: current_macro_index = 0; ! 1091: ! 1092: defining_kbd_macro = 1; ! 1093: } ! 1094: ! 1095: /* Stop defining a keyboard macro. ! 1096: A numeric argument says to execute the macro right now, ! 1097: that many times, counting the definition as the first time. */ ! 1098: rl_end_kbd_macro (count, ignore) ! 1099: int count, ignore; ! 1100: { ! 1101: if (!defining_kbd_macro) ! 1102: rl_abort (); ! 1103: ! 1104: current_macro_index -= (rl_key_sequence_length - 1); ! 1105: current_macro[current_macro_index] = '\0'; ! 1106: ! 1107: defining_kbd_macro = 0; ! 1108: ! 1109: rl_call_last_kbd_macro (--count, 0); ! 1110: } ! 1111: ! 1112: /* Execute the most recently defined keyboard macro. ! 1113: COUNT says how many times to execute it. */ ! 1114: rl_call_last_kbd_macro (count, ignore) ! 1115: int count, ignore; ! 1116: { ! 1117: if (!current_macro) ! 1118: rl_abort (); ! 1119: ! 1120: while (count--) ! 1121: with_macro_input (savestring (current_macro)); ! 1122: } ! 1123: ! 1124: ! 1125: /* **************************************************************** */ ! 1126: /* */ ! 1127: /* Initializations */ ! 1128: /* */ ! 1129: /* **************************************************************** */ ! 1130: ! 1131: /* Initliaze readline (and terminal if not already). */ ! 1132: rl_initialize () ! 1133: { ! 1134: extern char *rl_display_prompt; ! 1135: ! 1136: /* If we have never been called before, initialize the ! 1137: terminal and data structures. */ ! 1138: if (!rl_initialized) ! 1139: { ! 1140: readline_initialize_everything (); ! 1141: rl_initialized++; ! 1142: } ! 1143: ! 1144: /* Initalize the current line information. */ ! 1145: rl_point = rl_end = 0; ! 1146: the_line = rl_line_buffer; ! 1147: the_line[0] = 0; ! 1148: ! 1149: /* We aren't done yet. We haven't even gotten started yet! */ ! 1150: rl_done = 0; ! 1151: ! 1152: /* Tell the history routines what is going on. */ ! 1153: start_using_history (); ! 1154: ! 1155: /* Make the display buffer match the state of the line. */ ! 1156: { ! 1157: extern char *rl_display_prompt; ! 1158: extern int forced_display; ! 1159: ! 1160: rl_on_new_line (); ! 1161: ! 1162: rl_display_prompt = rl_prompt ? rl_prompt : ""; ! 1163: forced_display = 1; ! 1164: } ! 1165: ! 1166: /* No such function typed yet. */ ! 1167: rl_last_func = (Function *)NULL; ! 1168: ! 1169: /* Parsing of key-bindings begins in an enabled state. */ ! 1170: parsing_conditionalized_out = 0; ! 1171: } ! 1172: ! 1173: /* Initialize the entire state of the world. */ ! 1174: readline_initialize_everything () ! 1175: { ! 1176: /* Find out if we are running in Emacs. */ ! 1177: running_in_emacs = getenv ("EMACS"); ! 1178: ! 1179: /* Set up input and output if they aren't already. */ ! 1180: if (!rl_instream) ! 1181: rl_instream = stdin; ! 1182: if (!rl_outstream) ! 1183: rl_outstream = stdout; ! 1184: ! 1185: /* Allocate data structures. */ ! 1186: if (!rl_line_buffer) ! 1187: rl_line_buffer = ! 1188: (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); ! 1189: ! 1190: /* Initialize the terminal interface. */ ! 1191: init_terminal_io ((char *)NULL); ! 1192: ! 1193: /* Bind tty characters to readline functions. */ ! 1194: readline_default_bindings (); ! 1195: ! 1196: /* Initialize the function names. */ ! 1197: rl_initialize_funmap (); ! 1198: ! 1199: /* Read in the init file. */ ! 1200: rl_read_init_file ((char *)NULL); ! 1201: ! 1202: /* If the completion parser's default word break characters haven't ! 1203: been set yet, then do so now. */ ! 1204: { ! 1205: extern char *rl_completer_word_break_characters; ! 1206: extern char *rl_basic_word_break_characters; ! 1207: ! 1208: if (rl_completer_word_break_characters == (char *)NULL) ! 1209: rl_completer_word_break_characters = rl_basic_word_break_characters; ! 1210: } ! 1211: } ! 1212: ! 1213: /* If this system allows us to look at the values of the regular ! 1214: input editing characters, then bind them to their readline ! 1215: equivalents, iff the characters are not bound to keymaps. */ ! 1216: readline_default_bindings () ! 1217: { ! 1218: #ifndef __GO32__ ! 1219: ! 1220: #if defined (NEW_TTY_DRIVER) ! 1221: struct sgttyb ttybuff; ! 1222: int tty = fileno (rl_instream); ! 1223: ! 1224: if (ioctl (tty, TIOCGETP, &ttybuff) != -1) ! 1225: { ! 1226: int erase, kill; ! 1227: ! 1228: erase = ttybuff.sg_erase; ! 1229: kill = ttybuff.sg_kill; ! 1230: ! 1231: if (erase != -1 && keymap[erase].type == ISFUNC) ! 1232: keymap[erase].function = rl_rubout; ! 1233: ! 1234: if (kill != -1 && keymap[kill].type == ISFUNC) ! 1235: keymap[kill].function = rl_unix_line_discard; ! 1236: } ! 1237: ! 1238: #if defined (TIOCGLTC) ! 1239: { ! 1240: struct ltchars lt; ! 1241: ! 1242: if (ioctl (tty, TIOCGLTC, <) != -1) ! 1243: { ! 1244: int erase, nextc; ! 1245: ! 1246: erase = lt.t_werasc; ! 1247: nextc = lt.t_lnextc; ! 1248: ! 1249: if (erase != -1 && keymap[erase].type == ISFUNC) ! 1250: keymap[erase].function = rl_unix_word_rubout; ! 1251: ! 1252: if (nextc != -1 && keymap[nextc].type == ISFUNC) ! 1253: keymap[nextc].function = rl_quoted_insert; ! 1254: } ! 1255: } ! 1256: #endif /* TIOCGLTC */ ! 1257: #else /* not NEW_TTY_DRIVER */ ! 1258: ! 1259: #if defined (TERMIOS_TTY_DRIVER) ! 1260: struct termios ttybuff; ! 1261: #else ! 1262: struct termio ttybuff; ! 1263: #endif /* TERMIOS_TTY_DRIVER */ ! 1264: int tty = fileno (rl_instream); ! 1265: ! 1266: #if defined (TERMIOS_TTY_DRIVER) ! 1267: if (tcgetattr (tty, &ttybuff) != -1) ! 1268: #else ! 1269: if (ioctl (tty, TCGETA, &ttybuff) != -1) ! 1270: #endif /* !TERMIOS_TTY_DRIVER */ ! 1271: { ! 1272: int erase, kill; ! 1273: ! 1274: erase = ttybuff.c_cc[VERASE]; ! 1275: kill = ttybuff.c_cc[VKILL]; ! 1276: ! 1277: if (erase != _POSIX_VDISABLE && ! 1278: keymap[(unsigned char)erase].type == ISFUNC) ! 1279: keymap[(unsigned char)erase].function = rl_rubout; ! 1280: ! 1281: if (kill != _POSIX_VDISABLE && ! 1282: keymap[(unsigned char)kill].type == ISFUNC) ! 1283: keymap[(unsigned char)kill].function = rl_unix_line_discard; ! 1284: ! 1285: #if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) ! 1286: { ! 1287: int nextc; ! 1288: ! 1289: nextc = ttybuff.c_cc[VLNEXT]; ! 1290: ! 1291: if (nextc != _POSIX_VDISABLE && ! 1292: keymap[(unsigned char)nextc].type == ISFUNC) ! 1293: keymap[(unsigned char)nextc].function = rl_quoted_insert; ! 1294: } ! 1295: #endif /* VLNEXT && TERMIOS_TTY_DRIVER */ ! 1296: ! 1297: #if defined (VWERASE) ! 1298: { ! 1299: int werase; ! 1300: ! 1301: werase = ttybuff.c_cc[VWERASE]; ! 1302: ! 1303: if (werase != _POSIX_VDISABLE && ! 1304: keymap[(unsigned char)werase].type == ISFUNC) ! 1305: keymap[(unsigned char)werase].function = rl_unix_word_rubout; ! 1306: } ! 1307: #endif /* VWERASE */ ! 1308: } ! 1309: #endif /* !NEW_TTY_DRIVER */ ! 1310: #endif /* def __GO32__ */ ! 1311: } ! 1312: ! 1313: ! 1314: /* **************************************************************** */ ! 1315: /* */ ! 1316: /* Numeric Arguments */ ! 1317: /* */ ! 1318: /* **************************************************************** */ ! 1319: ! 1320: /* Handle C-u style numeric args, as well as M--, and M-digits. */ ! 1321: ! 1322: /* Add the current digit to the argument in progress. */ ! 1323: rl_digit_argument (ignore, key) ! 1324: int ignore, key; ! 1325: { ! 1326: rl_pending_input = key; ! 1327: rl_digit_loop (); ! 1328: } ! 1329: ! 1330: /* What to do when you abort reading an argument. */ ! 1331: rl_discard_argument () ! 1332: { ! 1333: ding (); ! 1334: rl_clear_message (); ! 1335: rl_init_argument (); ! 1336: } ! 1337: ! 1338: /* Create a default argument. */ ! 1339: rl_init_argument () ! 1340: { ! 1341: rl_numeric_arg = rl_arg_sign = 1; ! 1342: rl_explicit_arg = 0; ! 1343: } ! 1344: ! 1345: /* C-u, universal argument. Multiply the current argument by 4. ! 1346: Read a key. If the key has nothing to do with arguments, then ! 1347: dispatch on it. If the key is the abort character then abort. */ ! 1348: rl_universal_argument () ! 1349: { ! 1350: rl_numeric_arg *= 4; ! 1351: rl_digit_loop (); ! 1352: } ! 1353: ! 1354: rl_digit_loop () ! 1355: { ! 1356: int key, c; ! 1357: while (1) ! 1358: { ! 1359: rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); ! 1360: key = c = rl_read_key (); ! 1361: ! 1362: if (keymap[c].type == ISFUNC && ! 1363: keymap[c].function == rl_universal_argument) ! 1364: { ! 1365: rl_numeric_arg *= 4; ! 1366: continue; ! 1367: } ! 1368: c = UNMETA (c); ! 1369: if (numeric (c)) ! 1370: { ! 1371: if (rl_explicit_arg) ! 1372: rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0'); ! 1373: else ! 1374: rl_numeric_arg = (c - '0'); ! 1375: rl_explicit_arg = 1; ! 1376: } ! 1377: else ! 1378: { ! 1379: if (c == '-' && !rl_explicit_arg) ! 1380: { ! 1381: rl_numeric_arg = 1; ! 1382: rl_arg_sign = -1; ! 1383: } ! 1384: else ! 1385: { ! 1386: rl_clear_message (); ! 1387: rl_dispatch (key, keymap); ! 1388: return; ! 1389: } ! 1390: } ! 1391: } ! 1392: } ! 1393: ! 1394: ! 1395: /* **************************************************************** */ ! 1396: /* */ ! 1397: /* Display stuff */ ! 1398: /* */ ! 1399: /* **************************************************************** */ ! 1400: ! 1401: /* This is the stuff that is hard for me. I never seem to write good ! 1402: display routines in C. Let's see how I do this time. */ ! 1403: ! 1404: /* (PWP) Well... Good for a simple line updater, but totally ignores ! 1405: the problems of input lines longer than the screen width. ! 1406: ! 1407: update_line and the code that calls it makes a multiple line, ! 1408: automatically wrapping line update. Carefull attention needs ! 1409: to be paid to the vertical position variables. ! 1410: ! 1411: handling of terminals with autowrap on (incl. DEC braindamage) ! 1412: could be improved a bit. Right now I just cheat and decrement ! 1413: screenwidth by one. */ ! 1414: ! 1415: /* Keep two buffers; one which reflects the current contents of the ! 1416: screen, and the other to draw what we think the new contents should ! 1417: be. Then compare the buffers, and make whatever changes to the ! 1418: screen itself that we should. Finally, make the buffer that we ! 1419: just drew into be the one which reflects the current contents of the ! 1420: screen, and place the cursor where it belongs. ! 1421: ! 1422: Commands that want to can fix the display themselves, and then let ! 1423: this function know that the display has been fixed by setting the ! 1424: RL_DISPLAY_FIXED variable. This is good for efficiency. */ ! 1425: ! 1426: /* Termcap variables: */ ! 1427: extern char *term_up, *term_dc, *term_cr; ! 1428: extern int screenheight, screenwidth, terminal_can_insert; ! 1429: ! 1430: /* What YOU turn on when you have handled all redisplay yourself. */ ! 1431: int rl_display_fixed = 0; ! 1432: ! 1433: /* The visible cursor position. If you print some text, adjust this. */ ! 1434: int last_c_pos = 0; ! 1435: int last_v_pos = 0; ! 1436: ! 1437: /* The last left edge of text that was displayed. This is used when ! 1438: doing horizontal scrolling. It shifts in thirds of a screenwidth. */ ! 1439: static int last_lmargin = 0; ! 1440: ! 1441: /* The line display buffers. One is the line currently displayed on ! 1442: the screen. The other is the line about to be displayed. */ ! 1443: static char *visible_line = (char *)NULL; ! 1444: static char *invisible_line = (char *)NULL; ! 1445: ! 1446: /* Number of lines currently on screen minus 1. */ ! 1447: int vis_botlin = 0; ! 1448: ! 1449: /* A buffer for `modeline' messages. */ ! 1450: char msg_buf[128]; ! 1451: ! 1452: /* Non-zero forces the redisplay even if we thought it was unnecessary. */ ! 1453: int forced_display = 0; ! 1454: ! 1455: /* The stuff that gets printed out before the actual text of the line. ! 1456: This is usually pointing to rl_prompt. */ ! 1457: char *rl_display_prompt = (char *)NULL; ! 1458: ! 1459: /* Default and initial buffer size. Can grow. */ ! 1460: static int line_size = 1024; ! 1461: ! 1462: /* Non-zero means to always use horizontal scrolling in line display. */ ! 1463: static int horizontal_scroll_mode = 0; ! 1464: ! 1465: /* Non-zero means to display an asterisk at the starts of history lines ! 1466: which have been modified. */ ! 1467: static int mark_modified_lines = 0; ! 1468: ! 1469: /* Non-zero means to use a visible bell if one is available rather than ! 1470: simply ringing the terminal bell. */ ! 1471: static int prefer_visible_bell = 0; ! 1472: ! 1473: /* I really disagree with this, but my boss (among others) insists that we ! 1474: support compilers that don't work. I don't think we are gaining by doing ! 1475: so; what is the advantage in producing better code if we can't use it? */ ! 1476: /* The following two declarations belong inside the ! 1477: function block, not here. */ ! 1478: static void move_cursor_relative (); ! 1479: static void output_some_chars (); ! 1480: static void output_character_function (); ! 1481: static int compare_strings (); ! 1482: ! 1483: /* Basic redisplay algorithm. */ ! 1484: rl_redisplay () ! 1485: { ! 1486: register int in, out, c, linenum; ! 1487: register char *line = invisible_line; ! 1488: char *prompt_this_line; ! 1489: int c_pos = 0; ! 1490: int inv_botlin = 0; /* Number of lines in newly drawn buffer. */ ! 1491: ! 1492: extern int readline_echoing_p; ! 1493: ! 1494: if (!readline_echoing_p) ! 1495: return; ! 1496: ! 1497: if (!rl_display_prompt) ! 1498: rl_display_prompt = ""; ! 1499: ! 1500: if (!invisible_line) ! 1501: { ! 1502: visible_line = (char *)xmalloc (line_size); ! 1503: invisible_line = (char *)xmalloc (line_size); ! 1504: line = invisible_line; ! 1505: for (in = 0; in < line_size; in++) ! 1506: { ! 1507: visible_line[in] = 0; ! 1508: invisible_line[in] = 1; ! 1509: } ! 1510: rl_on_new_line (); ! 1511: } ! 1512: ! 1513: /* Draw the line into the buffer. */ ! 1514: c_pos = -1; ! 1515: ! 1516: /* Mark the line as modified or not. We only do this for history ! 1517: lines. */ ! 1518: out = 0; ! 1519: if (mark_modified_lines && current_history () && rl_undo_list) ! 1520: { ! 1521: line[out++] = '*'; ! 1522: line[out] = '\0'; ! 1523: } ! 1524: ! 1525: /* If someone thought that the redisplay was handled, but the currently ! 1526: visible line has a different modification state than the one about ! 1527: to become visible, then correct the callers misconception. */ ! 1528: if (visible_line[0] != invisible_line[0]) ! 1529: rl_display_fixed = 0; ! 1530: ! 1531: prompt_this_line = rindex (rl_display_prompt, '\n'); ! 1532: if (!prompt_this_line) ! 1533: prompt_this_line = rl_display_prompt; ! 1534: else ! 1535: { ! 1536: prompt_this_line++; ! 1537: if (forced_display) ! 1538: output_some_chars (rl_display_prompt, ! 1539: prompt_this_line - rl_display_prompt); ! 1540: } ! 1541: ! 1542: strncpy (line + out, prompt_this_line, strlen (prompt_this_line)); ! 1543: out += strlen (prompt_this_line); ! 1544: line[out] = '\0'; ! 1545: ! 1546: for (in = 0; in < rl_end; in++) ! 1547: { ! 1548: c = (unsigned char)the_line[in]; ! 1549: ! 1550: if (out + 1 >= line_size) ! 1551: { ! 1552: line_size *= 2; ! 1553: visible_line = (char *)xrealloc (visible_line, line_size); ! 1554: invisible_line = (char *)xrealloc (invisible_line, line_size); ! 1555: line = invisible_line; ! 1556: } ! 1557: ! 1558: if (in == rl_point) ! 1559: c_pos = out; ! 1560: ! 1561: if (c > 127) ! 1562: { ! 1563: line[out++] = 'M'; ! 1564: line[out++] = '-'; ! 1565: line[out++] = c - 128; ! 1566: } ! 1567: #define DISPLAY_TABS ! 1568: #if defined (DISPLAY_TABS) ! 1569: else if (c == '\t') ! 1570: { ! 1571: register int newout = (out | (int)7) + 1; ! 1572: while (out < newout) ! 1573: line[out++] = ' '; ! 1574: } ! 1575: #endif ! 1576: else if (c < 32) ! 1577: { ! 1578: line[out++] = 'C'; ! 1579: line[out++] = '-'; ! 1580: line[out++] = c + 64; ! 1581: } ! 1582: else if (c == 127) ! 1583: { ! 1584: line[out++] = 'C'; ! 1585: line[out++] = '-'; ! 1586: line[out++] = '?'; ! 1587: } ! 1588: else ! 1589: line[out++] = c; ! 1590: } ! 1591: line[out] = '\0'; ! 1592: if (c_pos < 0) ! 1593: c_pos = out; ! 1594: ! 1595: /* PWP: now is when things get a bit hairy. The visible and invisible ! 1596: line buffers are really multiple lines, which would wrap every ! 1597: (screenwidth - 1) characters. Go through each in turn, finding ! 1598: the changed region and updating it. The line order is top to bottom. */ ! 1599: ! 1600: /* If we can move the cursor up and down, then use multiple lines, ! 1601: otherwise, let long lines display in a single terminal line, and ! 1602: horizontally scroll it. */ ! 1603: ! 1604: if (!horizontal_scroll_mode && term_up && *term_up) ! 1605: { ! 1606: int total_screen_chars = (screenwidth * screenheight); ! 1607: ! 1608: if (!rl_display_fixed || forced_display) ! 1609: { ! 1610: forced_display = 0; ! 1611: ! 1612: /* If we have more than a screenful of material to display, then ! 1613: only display a screenful. We should display the last screen, ! 1614: not the first. I'll fix this in a minute. */ ! 1615: if (out >= total_screen_chars) ! 1616: out = total_screen_chars - 1; ! 1617: ! 1618: /* Number of screen lines to display. */ ! 1619: inv_botlin = out / screenwidth; ! 1620: ! 1621: /* For each line in the buffer, do the updating display. */ ! 1622: for (linenum = 0; linenum <= inv_botlin; linenum++) ! 1623: update_line (linenum > vis_botlin ? "" ! 1624: : &visible_line[linenum * screenwidth], ! 1625: &invisible_line[linenum * screenwidth], ! 1626: linenum); ! 1627: ! 1628: /* We may have deleted some lines. If so, clear the left over ! 1629: blank ones at the bottom out. */ ! 1630: if (vis_botlin > inv_botlin) ! 1631: { ! 1632: char *tt; ! 1633: for (; linenum <= vis_botlin; linenum++) ! 1634: { ! 1635: tt = &visible_line[linenum * screenwidth]; ! 1636: move_vert (linenum); ! 1637: move_cursor_relative (0, tt); ! 1638: clear_to_eol ((linenum == vis_botlin)? ! 1639: strlen (tt) : screenwidth); ! 1640: } ! 1641: } ! 1642: vis_botlin = inv_botlin; ! 1643: ! 1644: /* Move the cursor where it should be. */ ! 1645: move_vert (c_pos / screenwidth); ! 1646: move_cursor_relative (c_pos % screenwidth, ! 1647: &invisible_line[(c_pos / screenwidth) * screenwidth]); ! 1648: } ! 1649: } ! 1650: else /* Do horizontal scrolling. */ ! 1651: { ! 1652: int lmargin; ! 1653: ! 1654: /* Always at top line. */ ! 1655: last_v_pos = 0; ! 1656: ! 1657: /* If the display position of the cursor would be off the edge ! 1658: of the screen, start the display of this line at an offset that ! 1659: leaves the cursor on the screen. */ ! 1660: if (c_pos - last_lmargin > screenwidth - 2) ! 1661: lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3); ! 1662: else if (c_pos - last_lmargin < 1) ! 1663: lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3); ! 1664: else ! 1665: lmargin = last_lmargin; ! 1666: ! 1667: /* If the first character on the screen isn't the first character ! 1668: in the display line, indicate this with a special character. */ ! 1669: if (lmargin > 0) ! 1670: line[lmargin] = '<'; ! 1671: ! 1672: if (lmargin + screenwidth < out) ! 1673: line[lmargin + screenwidth - 1] = '>'; ! 1674: ! 1675: if (!rl_display_fixed || forced_display || lmargin != last_lmargin) ! 1676: { ! 1677: forced_display = 0; ! 1678: update_line (&visible_line[last_lmargin], ! 1679: &invisible_line[lmargin], 0); ! 1680: ! 1681: move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); ! 1682: last_lmargin = lmargin; ! 1683: } ! 1684: } ! 1685: fflush (out_stream); ! 1686: ! 1687: /* Swap visible and non-visible lines. */ ! 1688: { ! 1689: char *temp = visible_line; ! 1690: visible_line = invisible_line; ! 1691: invisible_line = temp; ! 1692: rl_display_fixed = 0; ! 1693: } ! 1694: } ! 1695: ! 1696: /* PWP: update_line() is based on finding the middle difference of each ! 1697: line on the screen; vis: ! 1698: ! 1699: /old first difference ! 1700: /beginning of line | /old last same /old EOL ! 1701: v v v v ! 1702: old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as ! 1703: new: eddie> Oh, my little buggy says to me, as lurgid as ! 1704: ^ ^ ^ ^ ! 1705: \beginning of line | \new last same \new end of line ! 1706: \new first difference ! 1707: ! 1708: All are character pointers for the sake of speed. Special cases for ! 1709: no differences, as well as for end of line additions must be handeled. ! 1710: ! 1711: Could be made even smarter, but this works well enough */ ! 1712: static ! 1713: update_line (old, new, current_line) ! 1714: register char *old, *new; ! 1715: int current_line; ! 1716: { ! 1717: register char *ofd, *ols, *oe, *nfd, *nls, *ne; ! 1718: int lendiff, wsatend; ! 1719: ! 1720: /* Find first difference. */ ! 1721: for (ofd = old, nfd = new; ! 1722: (ofd - old < screenwidth) && *ofd && (*ofd == *nfd); ! 1723: ofd++, nfd++) ! 1724: ; ! 1725: ! 1726: /* Move to the end of the screen line. */ ! 1727: for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++); ! 1728: for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++); ! 1729: ! 1730: /* If no difference, continue to next line. */ ! 1731: if (ofd == oe && nfd == ne) ! 1732: return; ! 1733: ! 1734: wsatend = 1; /* flag for trailing whitespace */ ! 1735: ols = oe - 1; /* find last same */ ! 1736: nls = ne - 1; ! 1737: while ((*ols == *nls) && (ols > ofd) && (nls > nfd)) ! 1738: { ! 1739: if (*ols != ' ') ! 1740: wsatend = 0; ! 1741: ols--; ! 1742: nls--; ! 1743: } ! 1744: ! 1745: if (wsatend) ! 1746: { ! 1747: ols = oe; ! 1748: nls = ne; ! 1749: } ! 1750: else if (*ols != *nls) ! 1751: { ! 1752: if (*ols) /* don't step past the NUL */ ! 1753: ols++; ! 1754: if (*nls) ! 1755: nls++; ! 1756: } ! 1757: ! 1758: move_vert (current_line); ! 1759: move_cursor_relative (ofd - old, old); ! 1760: ! 1761: /* if (len (new) > len (old)) */ ! 1762: lendiff = (nls - nfd) - (ols - ofd); ! 1763: ! 1764: /* Insert (diff(len(old),len(new)) ch */ ! 1765: if (lendiff > 0) ! 1766: { ! 1767: if (terminal_can_insert) ! 1768: { ! 1769: extern char *term_IC; ! 1770: ! 1771: /* Sometimes it is cheaper to print the characters rather than ! 1772: use the terminal's capabilities. */ ! 1773: if ((2 * (ne - nfd)) < lendiff && !term_IC) ! 1774: { ! 1775: output_some_chars (nfd, (ne - nfd)); ! 1776: last_c_pos += (ne - nfd); ! 1777: } ! 1778: else ! 1779: { ! 1780: if (*ols) ! 1781: { ! 1782: insert_some_chars (nfd, lendiff); ! 1783: last_c_pos += lendiff; ! 1784: } ! 1785: else ! 1786: { ! 1787: /* At the end of a line the characters do not have to ! 1788: be "inserted". They can just be placed on the screen. */ ! 1789: output_some_chars (nfd, lendiff); ! 1790: last_c_pos += lendiff; ! 1791: } ! 1792: /* Copy (new) chars to screen from first diff to last match. */ ! 1793: if (((nls - nfd) - lendiff) > 0) ! 1794: { ! 1795: output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff)); ! 1796: last_c_pos += ((nls - nfd) - lendiff); ! 1797: } ! 1798: } ! 1799: } ! 1800: else ! 1801: { /* cannot insert chars, write to EOL */ ! 1802: output_some_chars (nfd, (ne - nfd)); ! 1803: last_c_pos += (ne - nfd); ! 1804: } ! 1805: } ! 1806: else /* Delete characters from line. */ ! 1807: { ! 1808: /* If possible and inexpensive to use terminal deletion, then do so. */ ! 1809: if (term_dc && (2 * (ne - nfd)) >= (-lendiff)) ! 1810: { ! 1811: if (lendiff) ! 1812: delete_chars (-lendiff); /* delete (diff) characters */ ! 1813: ! 1814: /* Copy (new) chars to screen from first diff to last match */ ! 1815: if ((nls - nfd) > 0) ! 1816: { ! 1817: output_some_chars (nfd, (nls - nfd)); ! 1818: last_c_pos += (nls - nfd); ! 1819: } ! 1820: } ! 1821: /* Otherwise, print over the existing material. */ ! 1822: else ! 1823: { ! 1824: output_some_chars (nfd, (ne - nfd)); ! 1825: last_c_pos += (ne - nfd); ! 1826: clear_to_eol ((oe - old) - (ne - new)); ! 1827: } ! 1828: } ! 1829: } ! 1830: ! 1831: /* (PWP) tell the update routines that we have moved onto a ! 1832: new (empty) line. */ ! 1833: rl_on_new_line () ! 1834: { ! 1835: if (visible_line) ! 1836: visible_line[0] = '\0'; ! 1837: ! 1838: last_c_pos = last_v_pos = 0; ! 1839: vis_botlin = last_lmargin = 0; ! 1840: } ! 1841: ! 1842: /* Actually update the display, period. */ ! 1843: rl_forced_update_display () ! 1844: { ! 1845: if (visible_line) ! 1846: { ! 1847: register char *temp = visible_line; ! 1848: ! 1849: while (*temp) *temp++ = '\0'; ! 1850: } ! 1851: rl_on_new_line (); ! 1852: forced_display++; ! 1853: rl_redisplay (); ! 1854: } ! 1855: ! 1856: /* Move the cursor from last_c_pos to NEW, which are buffer indices. ! 1857: DATA is the contents of the screen line of interest; i.e., where ! 1858: the movement is being done. */ ! 1859: static void ! 1860: move_cursor_relative (new, data) ! 1861: int new; ! 1862: char *data; ! 1863: { ! 1864: register int i; ! 1865: ! 1866: /* It may be faster to output a CR, and then move forwards instead ! 1867: of moving backwards. */ ! 1868: if (new + 1 < last_c_pos - new) ! 1869: { ! 1870: #ifdef __MSDOS__ ! 1871: putc('\r', out_stream); ! 1872: #else ! 1873: tputs (term_cr, 1, output_character_function); ! 1874: #endif ! 1875: last_c_pos = 0; ! 1876: } ! 1877: ! 1878: if (last_c_pos == new) return; ! 1879: ! 1880: if (last_c_pos < new) ! 1881: { ! 1882: /* Move the cursor forward. We do it by printing the command ! 1883: to move the cursor forward if there is one, else print that ! 1884: portion of the output buffer again. Which is cheaper? */ ! 1885: ! 1886: /* The above comment is left here for posterity. It is faster ! 1887: to print one character (non-control) than to print a control ! 1888: sequence telling the terminal to move forward one character. ! 1889: That kind of control is for people who don't know what the ! 1890: data is underneath the cursor. */ ! 1891: #if defined (HACK_TERMCAP_MOTION) ! 1892: extern char *term_forward_char; ! 1893: ! 1894: if (term_forward_char) ! 1895: for (i = last_c_pos; i < new; i++) ! 1896: tputs (term_forward_char, 1, output_character_function); ! 1897: else ! 1898: for (i = last_c_pos; i < new; i++) ! 1899: putc (data[i], out_stream); ! 1900: #else ! 1901: for (i = last_c_pos; i < new; i++) ! 1902: putc (data[i], out_stream); ! 1903: #endif /* HACK_TERMCAP_MOTION */ ! 1904: } ! 1905: else ! 1906: backspace (last_c_pos - new); ! 1907: last_c_pos = new; ! 1908: } ! 1909: ! 1910: /* PWP: move the cursor up or down. */ ! 1911: move_vert (to) ! 1912: int to; ! 1913: { ! 1914: void output_character_function (); ! 1915: register int delta, i; ! 1916: ! 1917: if (last_v_pos == to) return; ! 1918: ! 1919: if (to > screenheight) ! 1920: return; ! 1921: ! 1922: #ifdef __GO32__ ! 1923: { ! 1924: int cur_r, cur_c; ! 1925: ScreenGetCursor(&cur_r, &cur_c); ! 1926: ScreenSetCursor(cur_r+to-last_v_pos, cur_c); ! 1927: } ! 1928: #else /* __GO32__ */ ! 1929: if ((delta = to - last_v_pos) > 0) ! 1930: { ! 1931: for (i = 0; i < delta; i++) ! 1932: putc ('\n', out_stream); ! 1933: tputs (term_cr, 1, output_character_function); ! 1934: last_c_pos = 0; ! 1935: } ! 1936: else ! 1937: { /* delta < 0 */ ! 1938: if (term_up && *term_up) ! 1939: for (i = 0; i < -delta; i++) ! 1940: tputs (term_up, 1, output_character_function); ! 1941: } ! 1942: #endif /* __GO32__ */ ! 1943: last_v_pos = to; /* now to is here */ ! 1944: } ! 1945: ! 1946: /* Physically print C on out_stream. This is for functions which know ! 1947: how to optimize the display. */ ! 1948: rl_show_char (c) ! 1949: int c; ! 1950: { ! 1951: if (c > 127) ! 1952: { ! 1953: fprintf (out_stream, "M-"); ! 1954: c -= 128; ! 1955: } ! 1956: ! 1957: #if defined (DISPLAY_TABS) ! 1958: if (c < 32 && c != '\t') ! 1959: #else ! 1960: if (c < 32) ! 1961: #endif ! 1962: { ! 1963: ! 1964: c += 64; ! 1965: } ! 1966: ! 1967: putc (c, out_stream); ! 1968: fflush (out_stream); ! 1969: } ! 1970: ! 1971: #if defined (DISPLAY_TABS) ! 1972: int ! 1973: rl_character_len (c, pos) ! 1974: register int c, pos; ! 1975: { ! 1976: if (c < ' ' || c > 126) ! 1977: { ! 1978: if (c == '\t') ! 1979: return (((pos | (int)7) + 1) - pos); ! 1980: else ! 1981: return (3); ! 1982: } ! 1983: else ! 1984: return (1); ! 1985: } ! 1986: #else ! 1987: int ! 1988: rl_character_len (c) ! 1989: int c; ! 1990: { ! 1991: if (c < ' ' || c > 126) ! 1992: return (3); ! 1993: else ! 1994: return (1); ! 1995: } ! 1996: #endif /* DISPLAY_TAB */ ! 1997: ! 1998: /* How to print things in the "echo-area". The prompt is treated as a ! 1999: mini-modeline. */ ! 2000: rl_message (string, arg1, arg2) ! 2001: char *string; ! 2002: { ! 2003: sprintf (msg_buf, string, arg1, arg2); ! 2004: rl_display_prompt = msg_buf; ! 2005: rl_redisplay (); ! 2006: } ! 2007: ! 2008: /* How to clear things from the "echo-area". */ ! 2009: rl_clear_message () ! 2010: { ! 2011: rl_display_prompt = rl_prompt; ! 2012: rl_redisplay (); ! 2013: } ! 2014: ! 2015: /* **************************************************************** */ ! 2016: /* */ ! 2017: /* Terminal and Termcap */ ! 2018: /* */ ! 2019: /* **************************************************************** */ ! 2020: ! 2021: static char *term_buffer = (char *)NULL; ! 2022: static char *term_string_buffer = (char *)NULL; ! 2023: ! 2024: /* Non-zero means this terminal can't really do anything. */ ! 2025: int dumb_term = 0; ! 2026: ! 2027: /* On Solaris2, sys/types.h brings in sys/reg.h, ! 2028: which screws up the Termcap variable PC, used below. */ ! 2029: ! 2030: #undef PC ! 2031: ! 2032: char PC; ! 2033: char *BC, *UP; ! 2034: ! 2035: /* Some strings to control terminal actions. These are output by tputs (). */ ! 2036: char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace; ! 2037: ! 2038: int screenwidth, screenheight; ! 2039: ! 2040: /* Non-zero if we determine that the terminal can do character insertion. */ ! 2041: int terminal_can_insert = 0; ! 2042: ! 2043: /* How to insert characters. */ ! 2044: char *term_im, *term_ei, *term_ic, *term_ip, *term_IC; ! 2045: ! 2046: /* How to delete characters. */ ! 2047: char *term_dc, *term_DC; ! 2048: ! 2049: #if defined (HACK_TERMCAP_MOTION) ! 2050: char *term_forward_char; ! 2051: #endif /* HACK_TERMCAP_MOTION */ ! 2052: ! 2053: /* How to go up a line. */ ! 2054: char *term_up; ! 2055: ! 2056: /* A visible bell, if the terminal can be made to flash the screen. */ ! 2057: char *visible_bell; ! 2058: ! 2059: /* Re-initialize the terminal considering that the TERM/TERMCAP variable ! 2060: has changed. */ ! 2061: rl_reset_terminal (terminal_name) ! 2062: char *terminal_name; ! 2063: { ! 2064: init_terminal_io (terminal_name); ! 2065: } ! 2066: ! 2067: init_terminal_io (terminal_name) ! 2068: char *terminal_name; ! 2069: { ! 2070: #ifdef __GO32__ ! 2071: screenwidth = ScreenCols(); ! 2072: screenheight = ScreenRows(); ! 2073: term_cr = "\r"; ! 2074: term_im = term_ei = term_ic = term_IC = (char *)NULL; ! 2075: term_up = term_dc = term_DC = visible_bell = (char *)NULL; ! 2076: #if defined (HACK_TERMCAP_MOTION) ! 2077: term_forward_char = (char *)NULL; ! 2078: #endif ! 2079: terminal_can_insert = 0; ! 2080: return; ! 2081: #else ! 2082: extern char *tgetstr (); ! 2083: char *term, *buffer; ! 2084: #if defined (TIOCGWINSZ) ! 2085: struct winsize window_size; ! 2086: #endif ! 2087: int tty; ! 2088: ! 2089: term = terminal_name ? terminal_name : getenv ("TERM"); ! 2090: ! 2091: if (!term_string_buffer) ! 2092: term_string_buffer = (char *)xmalloc (2048); ! 2093: ! 2094: if (!term_buffer) ! 2095: term_buffer = (char *)xmalloc (2048); ! 2096: ! 2097: buffer = term_string_buffer; ! 2098: ! 2099: term_clrpag = term_cr = term_clreol = (char *)NULL; ! 2100: ! 2101: if (!term) ! 2102: term = "dumb"; ! 2103: ! 2104: if (tgetent (term_buffer, term) <= 0) ! 2105: { ! 2106: dumb_term = 1; ! 2107: screenwidth = 79; ! 2108: screenheight = 24; ! 2109: term_cr = "\r"; ! 2110: term_im = term_ei = term_ic = term_IC = (char *)NULL; ! 2111: term_up = term_dc = term_DC = visible_bell = (char *)NULL; ! 2112: #if defined (HACK_TERMCAP_MOTION) ! 2113: term_forward_char = (char *)NULL; ! 2114: #endif ! 2115: terminal_can_insert = 0; ! 2116: return; ! 2117: } ! 2118: ! 2119: BC = tgetstr ("pc", &buffer); ! 2120: PC = buffer ? *buffer : 0; ! 2121: ! 2122: term_backspace = tgetstr ("le", &buffer); ! 2123: ! 2124: term_cr = tgetstr ("cr", &buffer); ! 2125: term_clreol = tgetstr ("ce", &buffer); ! 2126: term_clrpag = tgetstr ("cl", &buffer); ! 2127: ! 2128: if (!term_cr) ! 2129: term_cr = "\r"; ! 2130: ! 2131: #if defined (HACK_TERMCAP_MOTION) ! 2132: term_forward_char = tgetstr ("nd", &buffer); ! 2133: #endif /* HACK_TERMCAP_MOTION */ ! 2134: ! 2135: if (rl_instream) ! 2136: tty = fileno (rl_instream); ! 2137: else ! 2138: tty = 0; ! 2139: ! 2140: screenwidth = screenheight = 0; ! 2141: #if defined (TIOCGWINSZ) ! 2142: if (ioctl (tty, TIOCGWINSZ, &window_size) == 0) ! 2143: { ! 2144: screenwidth = (int) window_size.ws_col; ! 2145: screenheight = (int) window_size.ws_row; ! 2146: } ! 2147: #endif ! 2148: ! 2149: if (screenwidth <= 0 || screenheight <= 0) ! 2150: { ! 2151: screenwidth = tgetnum ("co"); ! 2152: screenheight = tgetnum ("li"); ! 2153: } ! 2154: ! 2155: screenwidth--; ! 2156: ! 2157: if (screenwidth <= 0) ! 2158: screenwidth = 79; ! 2159: ! 2160: if (screenheight <= 0) ! 2161: screenheight = 24; ! 2162: ! 2163: term_im = tgetstr ("im", &buffer); ! 2164: term_ei = tgetstr ("ei", &buffer); ! 2165: term_IC = tgetstr ("IC", &buffer); ! 2166: term_ic = tgetstr ("ic", &buffer); ! 2167: ! 2168: /* "An application program can assume that the terminal can do ! 2169: character insertion if *any one of* the capabilities `IC', ! 2170: `im', `ic' or `ip' is provided." But we can't do anything if ! 2171: only `ip' is provided, so... */ ! 2172: terminal_can_insert = (term_IC || term_im || term_ic); ! 2173: ! 2174: term_up = tgetstr ("up", &buffer); ! 2175: term_dc = tgetstr ("dc", &buffer); ! 2176: term_DC = tgetstr ("DC", &buffer); ! 2177: ! 2178: visible_bell = tgetstr ("vb", &buffer); ! 2179: #endif /* !__GO32__ */ ! 2180: } ! 2181: ! 2182: /* A function for the use of tputs () */ ! 2183: static void ! 2184: output_character_function (c) ! 2185: int c; ! 2186: { ! 2187: putc (c, out_stream); ! 2188: } ! 2189: ! 2190: /* Write COUNT characters from STRING to the output stream. */ ! 2191: static void ! 2192: output_some_chars (string, count) ! 2193: char *string; ! 2194: int count; ! 2195: { ! 2196: fwrite (string, 1, count, out_stream); ! 2197: } ! 2198: ! 2199: /* Delete COUNT characters from the display line. */ ! 2200: static ! 2201: delete_chars (count) ! 2202: int count; ! 2203: { ! 2204: #ifdef __GO32__ ! 2205: int r, c, w; ! 2206: ScreenGetCursor(&r, &c); ! 2207: w = ScreenCols(); ! 2208: memcpy(ScreenPrimary+r*w+c, ScreenPrimary+r*w+c+count, w-c-count); ! 2209: memset(ScreenPrimary+r*w+w-count, 0, count*2); ! 2210: #else /* __GO32__ */ ! 2211: if (count > screenwidth) ! 2212: return; ! 2213: ! 2214: if (term_DC && *term_DC) ! 2215: { ! 2216: char *tgoto (), *buffer; ! 2217: buffer = tgoto (term_DC, 0, count); ! 2218: tputs (buffer, 1, output_character_function); ! 2219: } ! 2220: else ! 2221: { ! 2222: if (term_dc && *term_dc) ! 2223: while (count--) ! 2224: tputs (term_dc, 1, output_character_function); ! 2225: } ! 2226: #endif /* __GO32__ */ ! 2227: } ! 2228: ! 2229: /* Insert COUNT characters from STRING to the output stream. */ ! 2230: static void ! 2231: insert_some_chars (string, count) ! 2232: char *string; ! 2233: int count; ! 2234: { ! 2235: #ifdef __GO32__ ! 2236: int r, c, w; ! 2237: ScreenGetCursor(&r, &c); ! 2238: w = ScreenCols(); ! 2239: memcpy(ScreenPrimary+r*w+c+count, ScreenPrimary+r*w+c, w-c-count); ! 2240: /* Print the text. */ ! 2241: output_some_chars (string, count); ! 2242: #else /* __GO32__ */ ! 2243: /* If IC is defined, then we do not have to "enter" insert mode. */ ! 2244: if (term_IC) ! 2245: { ! 2246: char *tgoto (), *buffer; ! 2247: buffer = tgoto (term_IC, 0, count); ! 2248: tputs (buffer, 1, output_character_function); ! 2249: output_some_chars (string, count); ! 2250: } ! 2251: else ! 2252: { ! 2253: register int i; ! 2254: ! 2255: /* If we have to turn on insert-mode, then do so. */ ! 2256: if (term_im && *term_im) ! 2257: tputs (term_im, 1, output_character_function); ! 2258: ! 2259: /* If there is a special command for inserting characters, then ! 2260: use that first to open up the space. */ ! 2261: if (term_ic && *term_ic) ! 2262: { ! 2263: for (i = count; i--; ) ! 2264: tputs (term_ic, 1, output_character_function); ! 2265: } ! 2266: ! 2267: /* Print the text. */ ! 2268: output_some_chars (string, count); ! 2269: ! 2270: /* If there is a string to turn off insert mode, we had best use ! 2271: it now. */ ! 2272: if (term_ei && *term_ei) ! 2273: tputs (term_ei, 1, output_character_function); ! 2274: } ! 2275: #endif /* __GO32__ */ ! 2276: } ! 2277: ! 2278: /* Move the cursor back. */ ! 2279: backspace (count) ! 2280: int count; ! 2281: { ! 2282: register int i; ! 2283: ! 2284: #ifndef __GO32__ ! 2285: if (term_backspace) ! 2286: for (i = 0; i < count; i++) ! 2287: tputs (term_backspace, 1, output_character_function); ! 2288: else ! 2289: #endif /* !__GO32__ */ ! 2290: for (i = 0; i < count; i++) ! 2291: putc ('\b', out_stream); ! 2292: } ! 2293: ! 2294: /* Move to the start of the next line. */ ! 2295: crlf () ! 2296: { ! 2297: #if defined (NEW_TTY_DRIVER) ! 2298: tputs (term_cr, 1, output_character_function); ! 2299: #endif /* NEW_TTY_DRIVER */ ! 2300: putc ('\n', out_stream); ! 2301: } ! 2302: ! 2303: /* Clear to the end of the line. COUNT is the minimum ! 2304: number of character spaces to clear, */ ! 2305: static void ! 2306: clear_to_eol (count) ! 2307: int count; ! 2308: { ! 2309: #ifndef __GO32__ ! 2310: if (term_clreol) ! 2311: { ! 2312: tputs (term_clreol, 1, output_character_function); ! 2313: } ! 2314: else ! 2315: #endif /* !__GO32__ */ ! 2316: { ! 2317: register int i; ! 2318: ! 2319: /* Do one more character space. */ ! 2320: count++; ! 2321: ! 2322: for (i = 0; i < count; i++) ! 2323: putc (' ', out_stream); ! 2324: ! 2325: backspace (count); ! 2326: } ! 2327: } ! 2328: ! 2329: ! 2330: /* **************************************************************** */ ! 2331: /* */ ! 2332: /* Saving and Restoring the TTY */ ! 2333: /* */ ! 2334: /* **************************************************************** */ ! 2335: ! 2336: /* Non-zero means that the terminal is in a prepped state. */ ! 2337: static int terminal_prepped = 0; ! 2338: ! 2339: #if defined (NEW_TTY_DRIVER) ! 2340: ! 2341: /* Standard flags, including ECHO. */ ! 2342: static int original_tty_flags = 0; ! 2343: ! 2344: /* Local mode flags, like LPASS8. */ ! 2345: static int local_mode_flags = 0; ! 2346: ! 2347: /* Terminal characters. This has C-s and C-q in it. */ ! 2348: static struct tchars original_tchars; ! 2349: ! 2350: /* Local special characters. This has the interrupt characters in it. */ ! 2351: #if defined (TIOCGLTC) ! 2352: static struct ltchars original_ltchars; ! 2353: #endif ! 2354: ! 2355: /* We use this to get and set the tty_flags. */ ! 2356: static struct sgttyb the_ttybuff; ! 2357: ! 2358: /* Put the terminal in CBREAK mode so that we can detect key presses. */ ! 2359: static void ! 2360: rl_prep_terminal () ! 2361: { ! 2362: #ifndef __GO32__ ! 2363: int tty = fileno (rl_instream); ! 2364: SIGNALS_DECLARE_SAVED (saved_signals); ! 2365: ! 2366: if (terminal_prepped) ! 2367: return; ! 2368: ! 2369: SIGNALS_BLOCK (SIGINT, saved_signals); ! 2370: ! 2371: /* We always get the latest tty values. Maybe stty changed them. */ ! 2372: ioctl (tty, TIOCGETP, &the_ttybuff); ! 2373: original_tty_flags = the_ttybuff.sg_flags; ! 2374: ! 2375: readline_echoing_p = (original_tty_flags & ECHO); ! 2376: ! 2377: #if defined (TIOCLGET) ! 2378: ioctl (tty, TIOCLGET, &local_mode_flags); ! 2379: #endif ! 2380: ! 2381: #if !defined (ANYP) ! 2382: # define ANYP (EVENP | ODDP) ! 2383: #endif ! 2384: ! 2385: /* If this terminal doesn't care how the 8th bit is used, ! 2386: then we can use it for the meta-key. We check by seeing ! 2387: if BOTH odd and even parity are allowed. */ ! 2388: if (the_ttybuff.sg_flags & ANYP) ! 2389: { ! 2390: #if defined (PASS8) ! 2391: the_ttybuff.sg_flags |= PASS8; ! 2392: #endif ! 2393: ! 2394: /* Hack on local mode flags if we can. */ ! 2395: #if defined (TIOCLGET) && defined (LPASS8) ! 2396: { ! 2397: int flags; ! 2398: flags = local_mode_flags | LPASS8; ! 2399: ioctl (tty, TIOCLSET, &flags); ! 2400: } ! 2401: #endif /* TIOCLGET && LPASS8 */ ! 2402: } ! 2403: ! 2404: #if defined (TIOCGETC) ! 2405: { ! 2406: struct tchars temp; ! 2407: ! 2408: ioctl (tty, TIOCGETC, &original_tchars); ! 2409: temp = original_tchars; ! 2410: ! 2411: #if defined (USE_XON_XOFF) ! 2412: /* Get rid of C-s and C-q. ! 2413: We remember the value of startc (C-q) so that if the terminal is in ! 2414: xoff state, the user can xon it by pressing that character. */ ! 2415: xon_char = temp.t_startc; ! 2416: temp.t_stopc = -1; ! 2417: temp.t_startc = -1; ! 2418: ! 2419: /* If there is an XON character, bind it to restart the output. */ ! 2420: if (xon_char != -1) ! 2421: rl_bind_key (xon_char, rl_restart_output); ! 2422: #endif /* USE_XON_XOFF */ ! 2423: ! 2424: /* If there is an EOF char, bind eof_char to it. */ ! 2425: if (temp.t_eofc != -1) ! 2426: eof_char = temp.t_eofc; ! 2427: ! 2428: #if defined (NO_KILL_INTR) ! 2429: /* Get rid of C-\ and C-c. */ ! 2430: temp.t_intrc = temp.t_quitc = -1; ! 2431: #endif /* NO_KILL_INTR */ ! 2432: ! 2433: ioctl (tty, TIOCSETC, &temp); ! 2434: } ! 2435: #endif /* TIOCGETC */ ! 2436: ! 2437: #if defined (TIOCGLTC) ! 2438: { ! 2439: struct ltchars temp; ! 2440: ! 2441: ioctl (tty, TIOCGLTC, &original_ltchars); ! 2442: temp = original_ltchars; ! 2443: ! 2444: /* Make the interrupt keys go away. Just enough to make people ! 2445: happy. */ ! 2446: temp.t_dsuspc = -1; /* C-y */ ! 2447: temp.t_lnextc = -1; /* C-v */ ! 2448: ! 2449: ioctl (tty, TIOCSLTC, &temp); ! 2450: } ! 2451: #endif /* TIOCGLTC */ ! 2452: ! 2453: the_ttybuff.sg_flags &= ~(ECHO | CRMOD); ! 2454: the_ttybuff.sg_flags |= CBREAK; ! 2455: ioctl (tty, TIOCSETN, &the_ttybuff); ! 2456: ! 2457: terminal_prepped = 1; ! 2458: ! 2459: SIGNALS_RESTORE (saved_signals); ! 2460: #endif /* !__GO32__ */ ! 2461: } ! 2462: ! 2463: /* Restore the terminal to its original state. */ ! 2464: static void ! 2465: rl_deprep_terminal () ! 2466: { ! 2467: #ifndef __GO32__ ! 2468: int tty = fileno (rl_instream); ! 2469: SIGNALS_DECLARE_SAVED (saved_signals); ! 2470: ! 2471: if (!terminal_prepped) ! 2472: return; ! 2473: ! 2474: SIGNALS_BLOCK (SIGINT, saved_signals); ! 2475: ! 2476: the_ttybuff.sg_flags = original_tty_flags; ! 2477: ioctl (tty, TIOCSETN, &the_ttybuff); ! 2478: readline_echoing_p = 1; ! 2479: ! 2480: #if defined (TIOCLGET) ! 2481: ioctl (tty, TIOCLSET, &local_mode_flags); ! 2482: #endif ! 2483: ! 2484: #if defined (TIOCSLTC) ! 2485: ioctl (tty, TIOCSLTC, &original_ltchars); ! 2486: #endif ! 2487: ! 2488: #if defined (TIOCSETC) ! 2489: ioctl (tty, TIOCSETC, &original_tchars); ! 2490: #endif ! 2491: terminal_prepped = 0; ! 2492: ! 2493: SIGNALS_RESTORE (saved_signals); ! 2494: #endif /* !__GO32 */ ! 2495: } ! 2496: ! 2497: #else /* !defined (NEW_TTY_DRIVER) */ ! 2498: ! 2499: #if !defined (VMIN) ! 2500: #define VMIN VEOF ! 2501: #endif ! 2502: ! 2503: #if !defined (VTIME) ! 2504: #define VTIME VEOL ! 2505: #endif ! 2506: ! 2507: #ifndef __GO32__ ! 2508: #if defined (TERMIOS_TTY_DRIVER) ! 2509: static struct termios otio; ! 2510: #else ! 2511: static struct termio otio; ! 2512: #endif /* !TERMIOS_TTY_DRIVER */ ! 2513: #endif /* __GO32__ */ ! 2514: ! 2515: static void ! 2516: rl_prep_terminal () ! 2517: { ! 2518: #ifndef __GO32__ ! 2519: int tty = fileno (rl_instream); ! 2520: #if defined (TERMIOS_TTY_DRIVER) ! 2521: struct termios tio; ! 2522: #else ! 2523: struct termio tio; ! 2524: #endif /* !TERMIOS_TTY_DRIVER */ ! 2525: ! 2526: SIGNALS_DECLARE_SAVED (saved_signals); ! 2527: ! 2528: if (terminal_prepped) ! 2529: return; ! 2530: ! 2531: /* Try to keep this function from being INTerrupted. We can do it ! 2532: on POSIX and systems with BSD-like signal handling. */ ! 2533: SIGNALS_BLOCK (SIGINT, saved_signals); ! 2534: ! 2535: #if defined (TERMIOS_TTY_DRIVER) ! 2536: tcgetattr (tty, &tio); ! 2537: #else ! 2538: ioctl (tty, TCGETA, &tio); ! 2539: #endif /* !TERMIOS_TTY_DRIVER */ ! 2540: ! 2541: otio = tio; ! 2542: ! 2543: readline_echoing_p = (tio.c_lflag & ECHO); ! 2544: ! 2545: tio.c_lflag &= ~(ICANON|ECHO); ! 2546: ! 2547: if (otio.c_cc[VEOF] != _POSIX_VDISABLE) ! 2548: eof_char = otio.c_cc[VEOF]; ! 2549: ! 2550: #if defined (USE_XON_XOFF) ! 2551: #if defined (IXANY) ! 2552: tio.c_iflag &= ~(IXON|IXOFF|IXANY); ! 2553: #else ! 2554: /* `strict' Posix systems do not define IXANY. */ ! 2555: tio.c_iflag &= ~(IXON|IXOFF); ! 2556: #endif /* IXANY */ ! 2557: #endif /* USE_XON_XOFF */ ! 2558: ! 2559: /* Only turn this off if we are using all 8 bits. */ ! 2560: /* |ISTRIP|INPCK */ ! 2561: tio.c_iflag &= ~(ISTRIP | INPCK); ! 2562: ! 2563: /* Make sure we differentiate between CR and NL on input. */ ! 2564: tio.c_iflag &= ~(ICRNL | INLCR); ! 2565: ! 2566: #if !defined (HANDLE_SIGNALS) ! 2567: tio.c_lflag &= ~ISIG; ! 2568: #else ! 2569: tio.c_lflag |= ISIG; ! 2570: #endif ! 2571: ! 2572: tio.c_cc[VMIN] = 1; ! 2573: tio.c_cc[VTIME] = 0; ! 2574: ! 2575: /* Turn off characters that we need on Posix systems with job control, ! 2576: just to be sure. This includes ^Y and ^V. This should not really ! 2577: be necessary. */ ! 2578: #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_JOB_CONTROL) ! 2579: ! 2580: #if defined (VLNEXT) ! 2581: tio.c_cc[VLNEXT] = _POSIX_VDISABLE; ! 2582: #endif ! 2583: ! 2584: #if defined (VDSUSP) ! 2585: tio.c_cc[VDSUSP] = _POSIX_VDISABLE; ! 2586: #endif ! 2587: ! 2588: #endif /* POSIX && JOB_CONTROL */ ! 2589: ! 2590: #if defined (TERMIOS_TTY_DRIVER) ! 2591: tcsetattr (tty, TCSADRAIN, &tio); ! 2592: tcflow (tty, TCOON); /* Simulate a ^Q. */ ! 2593: #else ! 2594: ioctl (tty, TCSETAW, &tio); ! 2595: ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ ! 2596: #endif /* !TERMIOS_TTY_DRIVER */ ! 2597: ! 2598: terminal_prepped = 1; ! 2599: ! 2600: SIGNALS_RESTORE (saved_signals); ! 2601: #endif /* !__GO32__ */ ! 2602: } ! 2603: ! 2604: static void ! 2605: rl_deprep_terminal () ! 2606: { ! 2607: #ifndef __GO32__ ! 2608: int tty = fileno (rl_instream); ! 2609: ! 2610: /* Try to keep this function from being INTerrupted. We can do it ! 2611: on POSIX and systems with BSD-like signal handling. */ ! 2612: SIGNALS_DECLARE_SAVED (saved_signals); ! 2613: ! 2614: if (!terminal_prepped) ! 2615: return; ! 2616: ! 2617: SIGNALS_BLOCK (SIGINT, saved_signals); ! 2618: ! 2619: #if defined (TERMIOS_TTY_DRIVER) ! 2620: tcsetattr (tty, TCSADRAIN, &otio); ! 2621: tcflow (tty, TCOON); /* Simulate a ^Q. */ ! 2622: #else /* TERMIOS_TTY_DRIVER */ ! 2623: ioctl (tty, TCSETAW, &otio); ! 2624: ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ ! 2625: #endif /* !TERMIOS_TTY_DRIVER */ ! 2626: ! 2627: terminal_prepped = 0; ! 2628: ! 2629: SIGNALS_RESTORE (saved_signals); ! 2630: #endif /* !__GO32__ */ ! 2631: } ! 2632: #endif /* NEW_TTY_DRIVER */ ! 2633: ! 2634: void ! 2635: rl_deprepare_terminal() ! 2636: { ! 2637: rl_clear_signals(); ! 2638: rl_deprep_terminal(); ! 2639: } ! 2640: ! 2641: void ! 2642: rl_prepare_terminal() ! 2643: { ! 2644: rl_set_signals(); ! 2645: rl_prep_terminal(); ! 2646: } ! 2647: ! 2648: ! 2649: /* **************************************************************** */ ! 2650: /* */ ! 2651: /* Utility Functions */ ! 2652: /* */ ! 2653: /* **************************************************************** */ ! 2654: ! 2655: /* Return 0 if C is not a member of the class of characters that belong ! 2656: in words, or 1 if it is. */ ! 2657: ! 2658: int allow_pathname_alphabetic_chars = 0; ! 2659: char *pathname_alphabetic_chars = "/-_=~.#$"; ! 2660: ! 2661: int ! 2662: alphabetic (c) ! 2663: int c; ! 2664: { ! 2665: if (pure_alphabetic (c) || (numeric (c))) ! 2666: return (1); ! 2667: ! 2668: if (allow_pathname_alphabetic_chars) ! 2669: return ((int)rindex (pathname_alphabetic_chars, c)); ! 2670: else ! 2671: return (0); ! 2672: } ! 2673: ! 2674: /* Return non-zero if C is a numeric character. */ ! 2675: int ! 2676: numeric (c) ! 2677: int c; ! 2678: { ! 2679: return (c >= '0' && c <= '9'); ! 2680: } ! 2681: ! 2682: /* Ring the terminal bell. */ ! 2683: int ! 2684: ding () ! 2685: { ! 2686: if (readline_echoing_p) ! 2687: { ! 2688: #ifndef __GO32__ ! 2689: if (prefer_visible_bell && visible_bell) ! 2690: tputs (visible_bell, 1, output_character_function); ! 2691: else ! 2692: #endif /* !__GO32__ */ ! 2693: { ! 2694: fprintf (stderr, "\007"); ! 2695: fflush (stderr); ! 2696: } ! 2697: } ! 2698: return (-1); ! 2699: } ! 2700: ! 2701: /* How to abort things. */ ! 2702: rl_abort () ! 2703: { ! 2704: ding (); ! 2705: rl_clear_message (); ! 2706: rl_init_argument (); ! 2707: rl_pending_input = 0; ! 2708: ! 2709: defining_kbd_macro = 0; ! 2710: while (executing_macro) ! 2711: pop_executing_macro (); ! 2712: ! 2713: rl_last_func = (Function *)NULL; ! 2714: longjmp (readline_top_level, 1); ! 2715: } ! 2716: ! 2717: /* Return a copy of the string between FROM and TO. ! 2718: FROM is inclusive, TO is not. */ ! 2719: #if defined (sun) /* Yes, that's right, some crufty function in sunview is ! 2720: called rl_copy (). */ ! 2721: static ! 2722: #endif ! 2723: char * ! 2724: rl_copy (from, to) ! 2725: int from, to; ! 2726: { ! 2727: register int length; ! 2728: char *copy; ! 2729: ! 2730: /* Fix it if the caller is confused. */ ! 2731: if (from > to) ! 2732: { ! 2733: int t = from; ! 2734: from = to; ! 2735: to = t; ! 2736: } ! 2737: ! 2738: length = to - from; ! 2739: copy = (char *)xmalloc (1 + length); ! 2740: strncpy (copy, the_line + from, length); ! 2741: copy[length] = '\0'; ! 2742: return (copy); ! 2743: } ! 2744: ! 2745: /* Increase the size of RL_LINE_BUFFER until it has enough space to hold ! 2746: LEN characters. */ ! 2747: void ! 2748: rl_extend_line_buffer (len) ! 2749: int len; ! 2750: { ! 2751: while (len >= rl_line_buffer_len) ! 2752: rl_line_buffer = ! 2753: (char *)xrealloc ! 2754: (rl_line_buffer, rl_line_buffer_len += DEFAULT_BUFFER_SIZE); ! 2755: ! 2756: the_line = rl_line_buffer; ! 2757: } ! 2758: ! 2759: ! 2760: /* **************************************************************** */ ! 2761: /* */ ! 2762: /* Insert and Delete */ ! 2763: /* */ ! 2764: /* **************************************************************** */ ! 2765: ! 2766: /* Insert a string of text into the line at point. This is the only ! 2767: way that you should do insertion. rl_insert () calls this ! 2768: function. */ ! 2769: rl_insert_text (string) ! 2770: char *string; ! 2771: { ! 2772: extern int doing_an_undo; ! 2773: register int i, l = strlen (string); ! 2774: ! 2775: if (rl_end + l >= rl_line_buffer_len) ! 2776: rl_extend_line_buffer (rl_end + l); ! 2777: ! 2778: for (i = rl_end; i >= rl_point; i--) ! 2779: the_line[i + l] = the_line[i]; ! 2780: strncpy (the_line + rl_point, string, l); ! 2781: ! 2782: /* Remember how to undo this if we aren't undoing something. */ ! 2783: if (!doing_an_undo) ! 2784: { ! 2785: /* If possible and desirable, concatenate the undos. */ ! 2786: if ((strlen (string) == 1) && ! 2787: rl_undo_list && ! 2788: (rl_undo_list->what == UNDO_INSERT) && ! 2789: (rl_undo_list->end == rl_point) && ! 2790: (rl_undo_list->end - rl_undo_list->start < 20)) ! 2791: rl_undo_list->end++; ! 2792: else ! 2793: rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); ! 2794: } ! 2795: rl_point += l; ! 2796: rl_end += l; ! 2797: the_line[rl_end] = '\0'; ! 2798: } ! 2799: ! 2800: /* Delete the string between FROM and TO. FROM is ! 2801: inclusive, TO is not. */ ! 2802: rl_delete_text (from, to) ! 2803: int from, to; ! 2804: { ! 2805: extern int doing_an_undo; ! 2806: register char *text; ! 2807: ! 2808: /* Fix it if the caller is confused. */ ! 2809: if (from > to) ! 2810: { ! 2811: int t = from; ! 2812: from = to; ! 2813: to = t; ! 2814: } ! 2815: text = rl_copy (from, to); ! 2816: strncpy (the_line + from, the_line + to, rl_end - to); ! 2817: ! 2818: /* Remember how to undo this delete. */ ! 2819: if (!doing_an_undo) ! 2820: rl_add_undo (UNDO_DELETE, from, to, text); ! 2821: else ! 2822: free (text); ! 2823: ! 2824: rl_end -= (to - from); ! 2825: the_line[rl_end] = '\0'; ! 2826: } ! 2827: ! 2828: ! 2829: /* **************************************************************** */ ! 2830: /* */ ! 2831: /* Readline character functions */ ! 2832: /* */ ! 2833: /* **************************************************************** */ ! 2834: ! 2835: /* This is not a gap editor, just a stupid line input routine. No hair ! 2836: is involved in writing any of the functions, and none should be. */ ! 2837: ! 2838: /* Note that: ! 2839: ! 2840: rl_end is the place in the string that we would place '\0'; ! 2841: i.e., it is always safe to place '\0' there. ! 2842: ! 2843: rl_point is the place in the string where the cursor is. Sometimes ! 2844: this is the same as rl_end. ! 2845: ! 2846: Any command that is called interactively receives two arguments. ! 2847: The first is a count: the numeric arg pased to this command. ! 2848: The second is the key which invoked this command. ! 2849: */ ! 2850: ! 2851: ! 2852: /* **************************************************************** */ ! 2853: /* */ ! 2854: /* Movement Commands */ ! 2855: /* */ ! 2856: /* **************************************************************** */ ! 2857: ! 2858: /* Note that if you `optimize' the display for these functions, you cannot ! 2859: use said functions in other functions which do not do optimizing display. ! 2860: I.e., you will have to update the data base for rl_redisplay, and you ! 2861: might as well let rl_redisplay do that job. */ ! 2862: ! 2863: /* Move forward COUNT characters. */ ! 2864: rl_forward (count) ! 2865: int count; ! 2866: { ! 2867: if (count < 0) ! 2868: rl_backward (-count); ! 2869: else ! 2870: while (count) ! 2871: { ! 2872: #if defined (VI_MODE) ! 2873: if (rl_point == (rl_end - (rl_editing_mode == vi_mode))) ! 2874: #else ! 2875: if (rl_point == rl_end) ! 2876: #endif /* VI_MODE */ ! 2877: { ! 2878: ding (); ! 2879: return; ! 2880: } ! 2881: else ! 2882: rl_point++; ! 2883: --count; ! 2884: } ! 2885: } ! 2886: ! 2887: /* Move backward COUNT characters. */ ! 2888: rl_backward (count) ! 2889: int count; ! 2890: { ! 2891: if (count < 0) ! 2892: rl_forward (-count); ! 2893: else ! 2894: while (count) ! 2895: { ! 2896: if (!rl_point) ! 2897: { ! 2898: ding (); ! 2899: return; ! 2900: } ! 2901: else ! 2902: --rl_point; ! 2903: --count; ! 2904: } ! 2905: } ! 2906: ! 2907: /* Move to the beginning of the line. */ ! 2908: rl_beg_of_line () ! 2909: { ! 2910: rl_point = 0; ! 2911: } ! 2912: ! 2913: /* Move to the end of the line. */ ! 2914: rl_end_of_line () ! 2915: { ! 2916: rl_point = rl_end; ! 2917: } ! 2918: ! 2919: /* Move forward a word. We do what Emacs does. */ ! 2920: rl_forward_word (count) ! 2921: int count; ! 2922: { ! 2923: int c; ! 2924: ! 2925: if (count < 0) ! 2926: { ! 2927: rl_backward_word (-count); ! 2928: return; ! 2929: } ! 2930: ! 2931: while (count) ! 2932: { ! 2933: if (rl_point == rl_end) ! 2934: return; ! 2935: ! 2936: /* If we are not in a word, move forward until we are in one. ! 2937: Then, move forward until we hit a non-alphabetic character. */ ! 2938: c = the_line[rl_point]; ! 2939: if (!alphabetic (c)) ! 2940: { ! 2941: while (++rl_point < rl_end) ! 2942: { ! 2943: c = the_line[rl_point]; ! 2944: if (alphabetic (c)) break; ! 2945: } ! 2946: } ! 2947: if (rl_point == rl_end) return; ! 2948: while (++rl_point < rl_end) ! 2949: { ! 2950: c = the_line[rl_point]; ! 2951: if (!alphabetic (c)) break; ! 2952: } ! 2953: --count; ! 2954: } ! 2955: } ! 2956: ! 2957: /* Move backward a word. We do what Emacs does. */ ! 2958: rl_backward_word (count) ! 2959: int count; ! 2960: { ! 2961: int c; ! 2962: ! 2963: if (count < 0) ! 2964: { ! 2965: rl_forward_word (-count); ! 2966: return; ! 2967: } ! 2968: ! 2969: while (count) ! 2970: { ! 2971: if (!rl_point) ! 2972: return; ! 2973: ! 2974: /* Like rl_forward_word (), except that we look at the characters ! 2975: just before point. */ ! 2976: ! 2977: c = the_line[rl_point - 1]; ! 2978: if (!alphabetic (c)) ! 2979: { ! 2980: while (--rl_point) ! 2981: { ! 2982: c = the_line[rl_point - 1]; ! 2983: if (alphabetic (c)) break; ! 2984: } ! 2985: } ! 2986: ! 2987: while (rl_point) ! 2988: { ! 2989: c = the_line[rl_point - 1]; ! 2990: if (!alphabetic (c)) ! 2991: break; ! 2992: else --rl_point; ! 2993: } ! 2994: --count; ! 2995: } ! 2996: } ! 2997: ! 2998: /* Clear the current line. Numeric argument to C-l does this. */ ! 2999: rl_refresh_line () ! 3000: { ! 3001: int curr_line = last_c_pos / screenwidth; ! 3002: extern char *term_clreol; ! 3003: ! 3004: move_vert(curr_line); ! 3005: move_cursor_relative (0, the_line); /* XXX is this right */ ! 3006: ! 3007: #ifdef __GO32__ ! 3008: { ! 3009: int r, c, w; ! 3010: ScreenGetCursor(&r, &c); ! 3011: w = ScreenCols(); ! 3012: memset(ScreenPrimary+r*w+c, 0, (w-c)*2); ! 3013: } ! 3014: #else /* __GO32__ */ ! 3015: if (term_clreol) ! 3016: tputs (term_clreol, 1, output_character_function); ! 3017: #endif /* __GO32__/else */ ! 3018: ! 3019: rl_forced_update_display (); ! 3020: rl_display_fixed = 1; ! 3021: } ! 3022: ! 3023: /* C-l typed to a line without quoting clears the screen, and then reprints ! 3024: the prompt and the current input line. Given a numeric arg, redraw only ! 3025: the current line. */ ! 3026: rl_clear_screen () ! 3027: { ! 3028: extern char *term_clrpag; ! 3029: ! 3030: if (rl_explicit_arg) ! 3031: { ! 3032: rl_refresh_line (); ! 3033: return; ! 3034: } ! 3035: ! 3036: #ifndef __GO32__ ! 3037: if (term_clrpag) ! 3038: tputs (term_clrpag, 1, output_character_function); ! 3039: else ! 3040: #endif /* !__GO32__ */ ! 3041: crlf (); ! 3042: ! 3043: rl_forced_update_display (); ! 3044: rl_display_fixed = 1; ! 3045: } ! 3046: ! 3047: rl_arrow_keys (count, c) ! 3048: int count, c; ! 3049: { ! 3050: int ch; ! 3051: ! 3052: ch = rl_read_key (); ! 3053: ! 3054: switch (to_upper (ch)) ! 3055: { ! 3056: case 'A': ! 3057: rl_get_previous_history (count); ! 3058: break; ! 3059: ! 3060: case 'B': ! 3061: rl_get_next_history (count); ! 3062: break; ! 3063: ! 3064: case 'C': ! 3065: rl_forward (count); ! 3066: break; ! 3067: ! 3068: case 'D': ! 3069: rl_backward (count); ! 3070: break; ! 3071: ! 3072: default: ! 3073: ding (); ! 3074: } ! 3075: } ! 3076: ! 3077: ! 3078: /* **************************************************************** */ ! 3079: /* */ ! 3080: /* Text commands */ ! 3081: /* */ ! 3082: /* **************************************************************** */ ! 3083: ! 3084: /* Insert the character C at the current location, moving point forward. */ ! 3085: rl_insert (count, c) ! 3086: int count, c; ! 3087: { ! 3088: register int i; ! 3089: char *string; ! 3090: ! 3091: if (count <= 0) ! 3092: return; ! 3093: ! 3094: /* If we can optimize, then do it. But don't let people crash ! 3095: readline because of extra large arguments. */ ! 3096: if (count > 1 && count < 1024) ! 3097: { ! 3098: string = (char *)alloca (1 + count); ! 3099: ! 3100: for (i = 0; i < count; i++) ! 3101: string[i] = c; ! 3102: ! 3103: string[i] = '\0'; ! 3104: rl_insert_text (string); ! 3105: return; ! 3106: } ! 3107: ! 3108: if (count > 1024) ! 3109: { ! 3110: int decreaser; ! 3111: ! 3112: string = (char *)alloca (1024 + 1); ! 3113: ! 3114: for (i = 0; i < 1024; i++) ! 3115: string[i] = c; ! 3116: ! 3117: while (count) ! 3118: { ! 3119: decreaser = (count > 1024 ? 1024 : count); ! 3120: string[decreaser] = '\0'; ! 3121: rl_insert_text (string); ! 3122: count -= decreaser; ! 3123: } ! 3124: return; ! 3125: } ! 3126: ! 3127: /* We are inserting a single character. ! 3128: If there is pending input, then make a string of all of the ! 3129: pending characters that are bound to rl_insert, and insert ! 3130: them all. */ ! 3131: if (any_typein) ! 3132: { ! 3133: int key = 0, t; ! 3134: ! 3135: i = 0; ! 3136: string = (char *)alloca (ibuffer_len + 1); ! 3137: string[i++] = c; ! 3138: ! 3139: while ((t = rl_get_char (&key)) && ! 3140: (keymap[key].type == ISFUNC && ! 3141: keymap[key].function == rl_insert)) ! 3142: string[i++] = key; ! 3143: ! 3144: if (t) ! 3145: rl_unget_char (key); ! 3146: ! 3147: string[i] = '\0'; ! 3148: rl_insert_text (string); ! 3149: return; ! 3150: } ! 3151: else ! 3152: { ! 3153: /* Inserting a single character. */ ! 3154: string = (char *)alloca (2); ! 3155: ! 3156: string[1] = '\0'; ! 3157: string[0] = c; ! 3158: rl_insert_text (string); ! 3159: } ! 3160: } ! 3161: ! 3162: /* Insert the next typed character verbatim. */ ! 3163: rl_quoted_insert (count) ! 3164: int count; ! 3165: { ! 3166: int c = rl_read_key (); ! 3167: rl_insert (count, c); ! 3168: } ! 3169: ! 3170: /* Insert a tab character. */ ! 3171: rl_tab_insert (count) ! 3172: int count; ! 3173: { ! 3174: rl_insert (count, '\t'); ! 3175: } ! 3176: ! 3177: /* What to do when a NEWLINE is pressed. We accept the whole line. ! 3178: KEY is the key that invoked this command. I guess it could have ! 3179: meaning in the future. */ ! 3180: rl_newline (count, key) ! 3181: int count, key; ! 3182: { ! 3183: ! 3184: rl_done = 1; ! 3185: ! 3186: #if defined (VI_MODE) ! 3187: { ! 3188: extern int vi_doing_insert; ! 3189: if (vi_doing_insert) ! 3190: { ! 3191: rl_end_undo_group (); ! 3192: vi_doing_insert = 0; ! 3193: } ! 3194: } ! 3195: #endif /* VI_MODE */ ! 3196: ! 3197: if (readline_echoing_p) ! 3198: { ! 3199: move_vert (vis_botlin); ! 3200: vis_botlin = 0; ! 3201: crlf (); ! 3202: fflush (out_stream); ! 3203: rl_display_fixed++; ! 3204: } ! 3205: } ! 3206: ! 3207: rl_clean_up_for_exit () ! 3208: { ! 3209: if (readline_echoing_p) ! 3210: { ! 3211: move_vert (vis_botlin); ! 3212: vis_botlin = 0; ! 3213: fflush (out_stream); ! 3214: rl_restart_output (); ! 3215: } ! 3216: } ! 3217: ! 3218: /* What to do for some uppercase characters, like meta characters, ! 3219: and some characters appearing in emacs_ctlx_keymap. This function ! 3220: is just a stub, you bind keys to it and the code in rl_dispatch () ! 3221: is special cased. */ ! 3222: rl_do_lowercase_version (ignore1, ignore2) ! 3223: int ignore1, ignore2; ! 3224: { ! 3225: } ! 3226: ! 3227: /* Rubout the character behind point. */ ! 3228: rl_rubout (count) ! 3229: int count; ! 3230: { ! 3231: if (count < 0) ! 3232: { ! 3233: rl_delete (-count); ! 3234: return; ! 3235: } ! 3236: ! 3237: if (!rl_point) ! 3238: { ! 3239: ding (); ! 3240: return; ! 3241: } ! 3242: ! 3243: if (count > 1) ! 3244: { ! 3245: int orig_point = rl_point; ! 3246: rl_backward (count); ! 3247: rl_kill_text (orig_point, rl_point); ! 3248: } ! 3249: else ! 3250: { ! 3251: int c = the_line[--rl_point]; ! 3252: rl_delete_text (rl_point, rl_point + 1); ! 3253: ! 3254: if (rl_point == rl_end && alphabetic (c) && last_c_pos) ! 3255: { ! 3256: backspace (1); ! 3257: putc (' ', out_stream); ! 3258: backspace (1); ! 3259: last_c_pos--; ! 3260: visible_line[last_c_pos] = '\0'; ! 3261: rl_display_fixed++; ! 3262: } ! 3263: } ! 3264: } ! 3265: ! 3266: /* Delete the character under the cursor. Given a numeric argument, ! 3267: kill that many characters instead. */ ! 3268: rl_delete (count, invoking_key) ! 3269: int count, invoking_key; ! 3270: { ! 3271: if (count < 0) ! 3272: { ! 3273: rl_rubout (-count); ! 3274: return; ! 3275: } ! 3276: ! 3277: if (rl_point == rl_end) ! 3278: { ! 3279: ding (); ! 3280: return; ! 3281: } ! 3282: ! 3283: if (count > 1) ! 3284: { ! 3285: int orig_point = rl_point; ! 3286: rl_forward (count); ! 3287: rl_kill_text (orig_point, rl_point); ! 3288: rl_point = orig_point; ! 3289: } ! 3290: else ! 3291: rl_delete_text (rl_point, rl_point + 1); ! 3292: } ! 3293: ! 3294: ! 3295: /* **************************************************************** */ ! 3296: /* */ ! 3297: /* Kill commands */ ! 3298: /* */ ! 3299: /* **************************************************************** */ ! 3300: ! 3301: /* The next two functions mimic unix line editing behaviour, except they ! 3302: save the deleted text on the kill ring. This is safer than not saving ! 3303: it, and since we have a ring, nobody should get screwed. */ ! 3304: ! 3305: /* This does what C-w does in Unix. We can't prevent people from ! 3306: using behaviour that they expect. */ ! 3307: rl_unix_word_rubout () ! 3308: { ! 3309: if (!rl_point) ding (); ! 3310: else { ! 3311: int orig_point = rl_point; ! 3312: while (rl_point && whitespace (the_line[rl_point - 1])) ! 3313: rl_point--; ! 3314: while (rl_point && !whitespace (the_line[rl_point - 1])) ! 3315: rl_point--; ! 3316: rl_kill_text (rl_point, orig_point); ! 3317: } ! 3318: } ! 3319: ! 3320: /* Here is C-u doing what Unix does. You don't *have* to use these ! 3321: key-bindings. We have a choice of killing the entire line, or ! 3322: killing from where we are to the start of the line. We choose the ! 3323: latter, because if you are a Unix weenie, then you haven't backspaced ! 3324: into the line at all, and if you aren't, then you know what you are ! 3325: doing. */ ! 3326: rl_unix_line_discard () ! 3327: { ! 3328: if (!rl_point) ding (); ! 3329: else { ! 3330: rl_kill_text (rl_point, 0); ! 3331: rl_point = 0; ! 3332: } ! 3333: } ! 3334: ! 3335: ! 3336: ! 3337: /* **************************************************************** */ ! 3338: /* */ ! 3339: /* Commands For Typos */ ! 3340: /* */ ! 3341: /* **************************************************************** */ ! 3342: ! 3343: /* Random and interesting things in here. */ ! 3344: ! 3345: /* **************************************************************** */ ! 3346: /* */ ! 3347: /* Changing Case */ ! 3348: /* */ ! 3349: /* **************************************************************** */ ! 3350: ! 3351: /* The three kinds of things that we know how to do. */ ! 3352: #define UpCase 1 ! 3353: #define DownCase 2 ! 3354: #define CapCase 3 ! 3355: ! 3356: /* Uppercase the word at point. */ ! 3357: rl_upcase_word (count) ! 3358: int count; ! 3359: { ! 3360: rl_change_case (count, UpCase); ! 3361: } ! 3362: ! 3363: /* Lowercase the word at point. */ ! 3364: rl_downcase_word (count) ! 3365: int count; ! 3366: { ! 3367: rl_change_case (count, DownCase); ! 3368: } ! 3369: ! 3370: /* Upcase the first letter, downcase the rest. */ ! 3371: rl_capitalize_word (count) ! 3372: int count; ! 3373: { ! 3374: rl_change_case (count, CapCase); ! 3375: } ! 3376: ! 3377: /* The meaty function. ! 3378: Change the case of COUNT words, performing OP on them. ! 3379: OP is one of UpCase, DownCase, or CapCase. ! 3380: If a negative argument is given, leave point where it started, ! 3381: otherwise, leave it where it moves to. */ ! 3382: rl_change_case (count, op) ! 3383: int count, op; ! 3384: { ! 3385: register int start = rl_point, end; ! 3386: int state = 0; ! 3387: ! 3388: rl_forward_word (count); ! 3389: end = rl_point; ! 3390: ! 3391: if (count < 0) ! 3392: { ! 3393: int temp = start; ! 3394: start = end; ! 3395: end = temp; ! 3396: } ! 3397: ! 3398: /* We are going to modify some text, so let's prepare to undo it. */ ! 3399: rl_modifying (start, end); ! 3400: ! 3401: for (; start < end; start++) ! 3402: { ! 3403: switch (op) ! 3404: { ! 3405: case UpCase: ! 3406: the_line[start] = to_upper (the_line[start]); ! 3407: break; ! 3408: ! 3409: case DownCase: ! 3410: the_line[start] = to_lower (the_line[start]); ! 3411: break; ! 3412: ! 3413: case CapCase: ! 3414: if (state == 0) ! 3415: { ! 3416: the_line[start] = to_upper (the_line[start]); ! 3417: state = 1; ! 3418: } ! 3419: else ! 3420: { ! 3421: the_line[start] = to_lower (the_line[start]); ! 3422: } ! 3423: if (!pure_alphabetic (the_line[start])) ! 3424: state = 0; ! 3425: break; ! 3426: ! 3427: default: ! 3428: abort (); ! 3429: } ! 3430: } ! 3431: rl_point = end; ! 3432: } ! 3433: ! 3434: /* **************************************************************** */ ! 3435: /* */ ! 3436: /* Transposition */ ! 3437: /* */ ! 3438: /* **************************************************************** */ ! 3439: ! 3440: /* Transpose the words at point. */ ! 3441: rl_transpose_words (count) ! 3442: int count; ! 3443: { ! 3444: char *word1, *word2; ! 3445: int w1_beg, w1_end, w2_beg, w2_end; ! 3446: int orig_point = rl_point; ! 3447: ! 3448: if (!count) return; ! 3449: ! 3450: /* Find the two words. */ ! 3451: rl_forward_word (count); ! 3452: w2_end = rl_point; ! 3453: rl_backward_word (1); ! 3454: w2_beg = rl_point; ! 3455: rl_backward_word (count); ! 3456: w1_beg = rl_point; ! 3457: rl_forward_word (1); ! 3458: w1_end = rl_point; ! 3459: ! 3460: /* Do some check to make sure that there really are two words. */ ! 3461: if ((w1_beg == w2_beg) || (w2_beg < w1_end)) ! 3462: { ! 3463: ding (); ! 3464: rl_point = orig_point; ! 3465: return; ! 3466: } ! 3467: ! 3468: /* Get the text of the words. */ ! 3469: word1 = rl_copy (w1_beg, w1_end); ! 3470: word2 = rl_copy (w2_beg, w2_end); ! 3471: ! 3472: /* We are about to do many insertions and deletions. Remember them ! 3473: as one operation. */ ! 3474: rl_begin_undo_group (); ! 3475: ! 3476: /* Do the stuff at word2 first, so that we don't have to worry ! 3477: about word1 moving. */ ! 3478: rl_point = w2_beg; ! 3479: rl_delete_text (w2_beg, w2_end); ! 3480: rl_insert_text (word1); ! 3481: ! 3482: rl_point = w1_beg; ! 3483: rl_delete_text (w1_beg, w1_end); ! 3484: rl_insert_text (word2); ! 3485: ! 3486: /* This is exactly correct since the text before this point has not ! 3487: changed in length. */ ! 3488: rl_point = w2_end; ! 3489: ! 3490: /* I think that does it. */ ! 3491: rl_end_undo_group (); ! 3492: free (word1); free (word2); ! 3493: } ! 3494: ! 3495: /* Transpose the characters at point. If point is at the end of the line, ! 3496: then transpose the characters before point. */ ! 3497: rl_transpose_chars (count) ! 3498: int count; ! 3499: { ! 3500: if (!count) ! 3501: return; ! 3502: ! 3503: if (!rl_point || rl_end < 2) { ! 3504: ding (); ! 3505: return; ! 3506: } ! 3507: ! 3508: while (count) ! 3509: { ! 3510: if (rl_point == rl_end) ! 3511: { ! 3512: int t = the_line[rl_point - 1]; ! 3513: ! 3514: the_line[rl_point - 1] = the_line[rl_point - 2]; ! 3515: the_line[rl_point - 2] = t; ! 3516: } ! 3517: else ! 3518: { ! 3519: int t = the_line[rl_point]; ! 3520: ! 3521: the_line[rl_point] = the_line[rl_point - 1]; ! 3522: the_line[rl_point - 1] = t; ! 3523: ! 3524: if (count < 0 && rl_point) ! 3525: rl_point--; ! 3526: else ! 3527: rl_point++; ! 3528: } ! 3529: ! 3530: if (count < 0) ! 3531: count++; ! 3532: else ! 3533: count--; ! 3534: } ! 3535: } ! 3536: ! 3537: ! 3538: /* **************************************************************** */ ! 3539: /* */ ! 3540: /* Bogus Flow Control */ ! 3541: /* */ ! 3542: /* **************************************************************** */ ! 3543: ! 3544: rl_restart_output (count, key) ! 3545: int count, key; ! 3546: { ! 3547: int fildes = fileno (rl_outstream); ! 3548: #if defined (TIOCSTART) ! 3549: #if defined (apollo) ! 3550: ioctl (&fildes, TIOCSTART, 0); ! 3551: #else ! 3552: ioctl (fildes, TIOCSTART, 0); ! 3553: #endif /* apollo */ ! 3554: ! 3555: #else ! 3556: # if defined (TERMIOS_TTY_DRIVER) ! 3557: tcflow (fildes, TCOON); ! 3558: # else ! 3559: # if defined (TCXONC) ! 3560: ioctl (fildes, TCXONC, TCOON); ! 3561: # endif /* TCXONC */ ! 3562: # endif /* !TERMIOS_TTY_DRIVER */ ! 3563: #endif /* TIOCSTART */ ! 3564: } ! 3565: ! 3566: rl_stop_output (count, key) ! 3567: int count, key; ! 3568: { ! 3569: int fildes = fileno (rl_instream); ! 3570: ! 3571: #if defined (TIOCSTOP) ! 3572: # if defined (apollo) ! 3573: ioctl (&fildes, TIOCSTOP, 0); ! 3574: # else ! 3575: ioctl (fildes, TIOCSTOP, 0); ! 3576: # endif /* apollo */ ! 3577: #else ! 3578: # if defined (TERMIOS_TTY_DRIVER) ! 3579: tcflow (fildes, TCOOFF); ! 3580: # else ! 3581: # if defined (TCXONC) ! 3582: ioctl (fildes, TCXONC, TCOON); ! 3583: # endif /* TCXONC */ ! 3584: # endif /* !TERMIOS_TTY_DRIVER */ ! 3585: #endif /* TIOCSTOP */ ! 3586: } ! 3587: ! 3588: /* **************************************************************** */ ! 3589: /* */ ! 3590: /* Completion matching, from readline's point of view. */ ! 3591: /* */ ! 3592: /* **************************************************************** */ ! 3593: ! 3594: /* Pointer to the generator function for completion_matches (). ! 3595: NULL means to use filename_entry_function (), the default filename ! 3596: completer. */ ! 3597: Function *rl_completion_entry_function = (Function *)NULL; ! 3598: ! 3599: /* Pointer to alternative function to create matches. ! 3600: Function is called with TEXT, START, and END. ! 3601: START and END are indices in RL_LINE_BUFFER saying what the boundaries ! 3602: of TEXT are. ! 3603: If this function exists and returns NULL then call the value of ! 3604: rl_completion_entry_function to try to match, otherwise use the ! 3605: array of strings returned. */ ! 3606: Function *rl_attempted_completion_function = (Function *)NULL; ! 3607: ! 3608: /* Local variable states what happened during the last completion attempt. */ ! 3609: static int completion_changed_buffer = 0; ! 3610: ! 3611: /* Complete the word at or before point. You have supplied the function ! 3612: that does the initial simple matching selection algorithm (see ! 3613: completion_matches ()). The default is to do filename completion. */ ! 3614: ! 3615: rl_complete (ignore, invoking_key) ! 3616: int ignore, invoking_key; ! 3617: { ! 3618: if (rl_last_func == rl_complete && !completion_changed_buffer) ! 3619: rl_complete_internal ('?'); ! 3620: else ! 3621: rl_complete_internal (TAB); ! 3622: } ! 3623: ! 3624: /* List the possible completions. See description of rl_complete (). */ ! 3625: rl_possible_completions () ! 3626: { ! 3627: rl_complete_internal ('?'); ! 3628: } ! 3629: ! 3630: /* The user must press "y" or "n". Non-zero return means "y" pressed. */ ! 3631: get_y_or_n () ! 3632: { ! 3633: int c; ! 3634: loop: ! 3635: c = rl_read_key (); ! 3636: if (c == 'y' || c == 'Y') return (1); ! 3637: if (c == 'n' || c == 'N') return (0); ! 3638: if (c == ABORT_CHAR) rl_abort (); ! 3639: ding (); goto loop; ! 3640: } ! 3641: ! 3642: /* Up to this many items will be displayed in response to a ! 3643: possible-completions call. After that, we ask the user if ! 3644: she is sure she wants to see them all. */ ! 3645: int rl_completion_query_items = 100; ! 3646: ! 3647: /* The basic list of characters that signal a break between words for the ! 3648: completer routine. The contents of this variable is what breaks words ! 3649: in the shell, i.e. " \t\n\"\\'`@$><=" */ ! 3650: char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; ! 3651: ! 3652: /* The list of characters that signal a break between words for ! 3653: rl_complete_internal. The default list is the contents of ! 3654: rl_basic_word_break_characters. */ ! 3655: char *rl_completer_word_break_characters = (char *)NULL; ! 3656: ! 3657: /* The list of characters which are used to quote a substring of the command ! 3658: line. Command completion occurs on the entire substring, and within the ! 3659: substring rl_completer_word_break_characters are treated as any other ! 3660: character, unless they also appear within this list. */ ! 3661: char *rl_completer_quote_characters = (char *)NULL; ! 3662: ! 3663: /* List of characters that are word break characters, but should be left ! 3664: in TEXT when it is passed to the completion function. The shell uses ! 3665: this to help determine what kind of completing to do. */ ! 3666: char *rl_special_prefixes = (char *)NULL; ! 3667: ! 3668: /* If non-zero, then disallow duplicates in the matches. */ ! 3669: int rl_ignore_completion_duplicates = 1; ! 3670: ! 3671: /* Non-zero means that the results of the matches are to be treated ! 3672: as filenames. This is ALWAYS zero on entry, and can only be changed ! 3673: within a completion entry finder function. */ ! 3674: int rl_filename_completion_desired = 0; ! 3675: ! 3676: /* This function, if defined, is called by the completer when real ! 3677: filename completion is done, after all the matching names have been ! 3678: generated. It is passed a (char**) known as matches in the code below. ! 3679: It consists of a NULL-terminated array of pointers to potential ! 3680: matching strings. The 1st element (matches[0]) is the maximal ! 3681: substring that is common to all matches. This function can re-arrange ! 3682: the list of matches as required, but all elements of the array must be ! 3683: free()'d if they are deleted. The main intent of this function is ! 3684: to implement FIGNORE a la SunOS csh. */ ! 3685: Function *rl_ignore_some_completions_function = (Function *)NULL; ! 3686: ! 3687: /* Complete the word at or before point. ! 3688: WHAT_TO_DO says what to do with the completion. ! 3689: `?' means list the possible completions. ! 3690: TAB means do standard completion. ! 3691: `*' means insert all of the possible completions. */ ! 3692: rl_complete_internal (what_to_do) ! 3693: int what_to_do; ! 3694: { ! 3695: char *filename_completion_function (); ! 3696: char **completion_matches (), **matches; ! 3697: Function *our_func; ! 3698: int start, scan, end, delimiter = 0; ! 3699: char *text, *saved_line_buffer; ! 3700: char quote_char = '\0'; ! 3701: char *replacement; ! 3702: ! 3703: if (the_line) ! 3704: saved_line_buffer = savestring (the_line); ! 3705: else ! 3706: saved_line_buffer = (char *)NULL; ! 3707: ! 3708: if (rl_completion_entry_function) ! 3709: our_func = rl_completion_entry_function; ! 3710: else ! 3711: our_func = (int (*)())filename_completion_function; ! 3712: ! 3713: /* Only the completion entry function can change this. */ ! 3714: rl_filename_completion_desired = 0; ! 3715: ! 3716: /* We now look backwards for the start of a filename/variable word. */ ! 3717: end = rl_point; ! 3718: ! 3719: if (rl_point) ! 3720: { ! 3721: if (rl_completer_quote_characters) ! 3722: { ! 3723: /* We have a list of characters which can be used in pairs to quote ! 3724: substrings for completion. Try to find the start of an unclosed ! 3725: quoted substring. ! 3726: FIXME: Doesn't yet handle '\' escapes to hid embedded quotes */ ! 3727: for (scan = 0; scan < end; scan++) ! 3728: { ! 3729: if (quote_char != '\0') ! 3730: { ! 3731: /* Ignore everything until the matching close quote char */ ! 3732: if (the_line[scan] == quote_char) ! 3733: { ! 3734: /* Found matching close quote. Abandon this substring. */ ! 3735: quote_char = '\0'; ! 3736: rl_point = end; ! 3737: } ! 3738: } ! 3739: else if (rindex (rl_completer_quote_characters, the_line[scan])) ! 3740: { ! 3741: /* Found start of a quoted substring. */ ! 3742: quote_char = the_line[scan]; ! 3743: rl_point = scan + 1; ! 3744: } ! 3745: } ! 3746: } ! 3747: if (rl_point == end) ! 3748: { ! 3749: /* We didn't find an unclosed quoted substring upon which to do ! 3750: completion, so use the word break characters to find the ! 3751: substring on which to do completion. */ ! 3752: while (--rl_point && ! 3753: !rindex (rl_completer_word_break_characters, ! 3754: the_line[rl_point])) {;} ! 3755: } ! 3756: ! 3757: /* If we are at a word break, then advance past it. */ ! 3758: if (rindex (rl_completer_word_break_characters, the_line[rl_point])) ! 3759: { ! 3760: /* If the character that caused the word break was a quoting ! 3761: character, then remember it as the delimiter. */ ! 3762: if (rindex ("\"'", the_line[rl_point]) && (end - rl_point) > 1) ! 3763: delimiter = the_line[rl_point]; ! 3764: ! 3765: /* If the character isn't needed to determine something special ! 3766: about what kind of completion to perform, then advance past it. */ ! 3767: ! 3768: if (!rl_special_prefixes || ! 3769: !rindex (rl_special_prefixes, the_line[rl_point])) ! 3770: rl_point++; ! 3771: } ! 3772: } ! 3773: ! 3774: start = rl_point; ! 3775: rl_point = end; ! 3776: text = rl_copy (start, end); ! 3777: ! 3778: /* If the user wants to TRY to complete, but then wants to give ! 3779: up and use the default completion function, they set the ! 3780: variable rl_attempted_completion_function. */ ! 3781: if (rl_attempted_completion_function) ! 3782: { ! 3783: matches = ! 3784: (char **)(*rl_attempted_completion_function) (text, start, end); ! 3785: ! 3786: if (matches) ! 3787: { ! 3788: our_func = (Function *)NULL; ! 3789: goto after_usual_completion; ! 3790: } ! 3791: } ! 3792: ! 3793: matches = completion_matches (text, our_func); ! 3794: ! 3795: after_usual_completion: ! 3796: free (text); ! 3797: ! 3798: if (!matches) ! 3799: ding (); ! 3800: else ! 3801: { ! 3802: register int i; ! 3803: ! 3804: some_matches: ! 3805: ! 3806: /* It seems to me that in all the cases we handle we would like ! 3807: to ignore duplicate possibilities. Scan for the text to ! 3808: insert being identical to the other completions. */ ! 3809: if (rl_ignore_completion_duplicates) ! 3810: { ! 3811: char *lowest_common; ! 3812: int j, newlen = 0; ! 3813: ! 3814: /* Sort the items. */ ! 3815: /* It is safe to sort this array, because the lowest common ! 3816: denominator found in matches[0] will remain in place. */ ! 3817: for (i = 0; matches[i]; i++); ! 3818: qsort (matches, i, sizeof (char *), compare_strings); ! 3819: ! 3820: /* Remember the lowest common denominator for it may be unique. */ ! 3821: lowest_common = savestring (matches[0]); ! 3822: ! 3823: for (i = 0; matches[i + 1]; i++) ! 3824: { ! 3825: if (strcmp (matches[i], matches[i + 1]) == 0) ! 3826: { ! 3827: free (matches[i]); ! 3828: matches[i] = (char *)-1; ! 3829: } ! 3830: else ! 3831: newlen++; ! 3832: } ! 3833: ! 3834: /* We have marked all the dead slots with (char *)-1. ! 3835: Copy all the non-dead entries into a new array. */ ! 3836: { ! 3837: char **temp_array = ! 3838: (char **)malloc ((3 + newlen) * sizeof (char *)); ! 3839: ! 3840: for (i = 1, j = 1; matches[i]; i++) ! 3841: { ! 3842: if (matches[i] != (char *)-1) ! 3843: temp_array[j++] = matches[i]; ! 3844: } ! 3845: ! 3846: temp_array[j] = (char *)NULL; ! 3847: ! 3848: if (matches[0] != (char *)-1) ! 3849: free (matches[0]); ! 3850: ! 3851: free (matches); ! 3852: ! 3853: matches = temp_array; ! 3854: } ! 3855: ! 3856: /* Place the lowest common denominator back in [0]. */ ! 3857: matches[0] = lowest_common; ! 3858: ! 3859: /* If there is one string left, and it is identical to the ! 3860: lowest common denominator, then the LCD is the string to ! 3861: insert. */ ! 3862: if (j == 2 && strcmp (matches[0], matches[1]) == 0) ! 3863: { ! 3864: free (matches[1]); ! 3865: matches[1] = (char *)NULL; ! 3866: } ! 3867: } ! 3868: ! 3869: switch (what_to_do) ! 3870: { ! 3871: case TAB: ! 3872: /* If we are matching filenames, then here is our chance to ! 3873: do clever processing by re-examining the list. Call the ! 3874: ignore function with the array as a parameter. It can ! 3875: munge the array, deleting matches as it desires. */ ! 3876: if (rl_ignore_some_completions_function && ! 3877: our_func == (int (*)())filename_completion_function) ! 3878: (void)(*rl_ignore_some_completions_function)(matches); ! 3879: ! 3880: /* If we are doing completions on quoted substrings, and any matches ! 3881: contain any of the completer word break characters, then auto- ! 3882: matically prepend the substring with a quote character (just ! 3883: pick the first one from the list of such) if it does not already ! 3884: begin with a quote string. FIXME: Need to remove any such ! 3885: automatically inserted quote character when it no longer is ! 3886: necessary, such as if we change the string we are completing on ! 3887: and the new set of matches don't require a quoted substring? */ ! 3888: ! 3889: replacement = matches[0]; ! 3890: if (matches[0] != NULL ! 3891: && rl_completer_quote_characters != NULL ! 3892: && (quote_char == '\0')) ! 3893: { ! 3894: for (i = 1; matches[i] != NULL; i++) ! 3895: { ! 3896: if (strpbrk (matches[i], rl_completer_word_break_characters)) ! 3897: { ! 3898: /* Found an embedded word break character in a potential ! 3899: match, so need to prepend a quote character if we are ! 3900: replacing the completion string. */ ! 3901: replacement = (char *)alloca (strlen (matches[0]) + 2); ! 3902: quote_char = *rl_completer_quote_characters; ! 3903: *replacement = quote_char; ! 3904: strcpy (replacement + 1, matches[0]); ! 3905: break; ! 3906: } ! 3907: } ! 3908: } ! 3909: if (replacement) ! 3910: { ! 3911: rl_delete_text (start, rl_point); ! 3912: rl_point = start; ! 3913: rl_insert_text (replacement); ! 3914: } ! 3915: ! 3916: /* If there are more matches, ring the bell to indicate. ! 3917: If this was the only match, and we are hacking files, ! 3918: check the file to see if it was a directory. If so, ! 3919: add a '/' to the name. If not, and we are at the end ! 3920: of the line, then add a space. */ ! 3921: if (matches[1]) ! 3922: { ! 3923: ding (); /* There are other matches remaining. */ ! 3924: } ! 3925: else ! 3926: { ! 3927: char temp_string[16]; ! 3928: int temp_index = 0; ! 3929: ! 3930: if (quote_char) ! 3931: { ! 3932: temp_string[temp_index++] = quote_char; ! 3933: } ! 3934: temp_string[temp_index++] = delimiter ? delimiter : ' '; ! 3935: temp_string[temp_index++] = '\0'; ! 3936: ! 3937: if (rl_filename_completion_desired) ! 3938: { ! 3939: struct stat finfo; ! 3940: char *filename = tilde_expand (matches[0]); ! 3941: ! 3942: if ((stat (filename, &finfo) == 0) && ! 3943: S_ISDIR (finfo.st_mode)) ! 3944: { ! 3945: if (the_line[rl_point] != '/') ! 3946: rl_insert_text ("/"); ! 3947: } ! 3948: else ! 3949: { ! 3950: if (rl_point == rl_end) ! 3951: rl_insert_text (temp_string); ! 3952: } ! 3953: free (filename); ! 3954: } ! 3955: else ! 3956: { ! 3957: if (rl_point == rl_end) ! 3958: rl_insert_text (temp_string); ! 3959: } ! 3960: } ! 3961: break; ! 3962: ! 3963: case '*': ! 3964: { ! 3965: int i = 1; ! 3966: ! 3967: rl_delete_text (start, rl_point); ! 3968: rl_point = start; ! 3969: rl_begin_undo_group (); ! 3970: if (matches[1]) ! 3971: { ! 3972: while (matches[i]) ! 3973: { ! 3974: rl_insert_text (matches[i++]); ! 3975: rl_insert_text (" "); ! 3976: } ! 3977: } ! 3978: else ! 3979: { ! 3980: rl_insert_text (matches[0]); ! 3981: rl_insert_text (" "); ! 3982: } ! 3983: rl_end_undo_group (); ! 3984: } ! 3985: break; ! 3986: ! 3987: case '?': ! 3988: { ! 3989: int len, count, limit, max = 0; ! 3990: int j, k, l; ! 3991: ! 3992: /* Handle simple case first. What if there is only one answer? */ ! 3993: if (!matches[1]) ! 3994: { ! 3995: char *temp; ! 3996: ! 3997: if (rl_filename_completion_desired) ! 3998: temp = rindex (matches[0], '/'); ! 3999: else ! 4000: temp = (char *)NULL; ! 4001: ! 4002: if (!temp) ! 4003: temp = matches[0]; ! 4004: else ! 4005: temp++; ! 4006: ! 4007: crlf (); ! 4008: fprintf (out_stream, "%s", temp); ! 4009: crlf (); ! 4010: goto restart; ! 4011: } ! 4012: ! 4013: /* There is more than one answer. Find out how many there are, ! 4014: and find out what the maximum printed length of a single entry ! 4015: is. */ ! 4016: for (i = 1; matches[i]; i++) ! 4017: { ! 4018: char *temp = (char *)NULL; ! 4019: ! 4020: /* If we are hacking filenames, then only count the characters ! 4021: after the last slash in the pathname. */ ! 4022: if (rl_filename_completion_desired) ! 4023: temp = rindex (matches[i], '/'); ! 4024: else ! 4025: temp = (char *)NULL; ! 4026: ! 4027: if (!temp) ! 4028: temp = matches[i]; ! 4029: else ! 4030: temp++; ! 4031: ! 4032: if (strlen (temp) > max) ! 4033: max = strlen (temp); ! 4034: } ! 4035: ! 4036: len = i; ! 4037: ! 4038: /* If there are many items, then ask the user if she ! 4039: really wants to see them all. */ ! 4040: if (len >= rl_completion_query_items) ! 4041: { ! 4042: crlf (); ! 4043: fprintf (out_stream, ! 4044: "There are %d possibilities. Do you really", len); ! 4045: crlf (); ! 4046: fprintf (out_stream, "wish to see them all? (y or n)"); ! 4047: fflush (out_stream); ! 4048: if (!get_y_or_n ()) ! 4049: { ! 4050: crlf (); ! 4051: goto restart; ! 4052: } ! 4053: } ! 4054: /* How many items of MAX length can we fit in the screen window? */ ! 4055: max += 2; ! 4056: limit = screenwidth / max; ! 4057: if (limit != 1 && (limit * max == screenwidth)) ! 4058: limit--; ! 4059: ! 4060: /* Avoid a possible floating exception. If max > screenwidth, ! 4061: limit will be 0 and a divide-by-zero fault will result. */ ! 4062: if (limit == 0) ! 4063: limit = 1; ! 4064: ! 4065: /* How many iterations of the printing loop? */ ! 4066: count = (len + (limit - 1)) / limit; ! 4067: ! 4068: /* Watch out for special case. If LEN is less than LIMIT, then ! 4069: just do the inner printing loop. */ ! 4070: if (len < limit) count = 1; ! 4071: ! 4072: /* Sort the items if they are not already sorted. */ ! 4073: if (!rl_ignore_completion_duplicates) ! 4074: qsort (matches, len, sizeof (char *), compare_strings); ! 4075: ! 4076: /* Print the sorted items, up-and-down alphabetically, like ! 4077: ls might. */ ! 4078: crlf (); ! 4079: ! 4080: for (i = 1; i < count + 1; i++) ! 4081: { ! 4082: for (j = 0, l = i; j < limit; j++) ! 4083: { ! 4084: if (l > len || !matches[l]) ! 4085: { ! 4086: break; ! 4087: } ! 4088: else ! 4089: { ! 4090: char *temp = (char *)NULL; ! 4091: ! 4092: if (rl_filename_completion_desired) ! 4093: temp = rindex (matches[l], '/'); ! 4094: else ! 4095: temp = (char *)NULL; ! 4096: ! 4097: if (!temp) ! 4098: temp = matches[l]; ! 4099: else ! 4100: temp++; ! 4101: ! 4102: fprintf (out_stream, "%s", temp); ! 4103: for (k = 0; k < max - strlen (temp); k++) ! 4104: putc (' ', out_stream); ! 4105: } ! 4106: l += count; ! 4107: } ! 4108: crlf (); ! 4109: } ! 4110: restart: ! 4111: ! 4112: rl_on_new_line (); ! 4113: } ! 4114: break; ! 4115: ! 4116: default: ! 4117: abort (); ! 4118: } ! 4119: ! 4120: for (i = 0; matches[i]; i++) ! 4121: free (matches[i]); ! 4122: free (matches); ! 4123: } ! 4124: ! 4125: /* Check to see if the line has changed through all of this manipulation. */ ! 4126: if (saved_line_buffer) ! 4127: { ! 4128: if (strcmp (the_line, saved_line_buffer) != 0) ! 4129: completion_changed_buffer = 1; ! 4130: else ! 4131: completion_changed_buffer = 0; ! 4132: ! 4133: free (saved_line_buffer); ! 4134: } ! 4135: } ! 4136: ! 4137: /* Stupid comparison routine for qsort () ing strings. */ ! 4138: static int ! 4139: compare_strings (s1, s2) ! 4140: char **s1, **s2; ! 4141: { ! 4142: return (strcmp (*s1, *s2)); ! 4143: } ! 4144: ! 4145: /* A completion function for usernames. ! 4146: TEXT contains a partial username preceded by a random ! 4147: character (usually `~'). */ ! 4148: char * ! 4149: username_completion_function (text, state) ! 4150: int state; ! 4151: char *text; ! 4152: { ! 4153: #ifdef __GO32__ ! 4154: return (char *)NULL; ! 4155: #else /* !__GO32__ */ ! 4156: static char *username = (char *)NULL; ! 4157: static struct passwd *entry; ! 4158: static int namelen, first_char, first_char_loc; ! 4159: ! 4160: if (!state) ! 4161: { ! 4162: if (username) ! 4163: free (username); ! 4164: ! 4165: first_char = *text; ! 4166: ! 4167: if (first_char == '~') ! 4168: first_char_loc = 1; ! 4169: else ! 4170: first_char_loc = 0; ! 4171: ! 4172: username = savestring (&text[first_char_loc]); ! 4173: namelen = strlen (username); ! 4174: setpwent (); ! 4175: } ! 4176: ! 4177: while (entry = getpwent ()) ! 4178: { ! 4179: if (strncmp (username, entry->pw_name, namelen) == 0) ! 4180: break; ! 4181: } ! 4182: ! 4183: if (!entry) ! 4184: { ! 4185: endpwent (); ! 4186: return ((char *)NULL); ! 4187: } ! 4188: else ! 4189: { ! 4190: char *value = (char *)xmalloc (2 + strlen (entry->pw_name)); ! 4191: ! 4192: *value = *text; ! 4193: ! 4194: strcpy (value + first_char_loc, entry->pw_name); ! 4195: ! 4196: if (first_char == '~') ! 4197: rl_filename_completion_desired = 1; ! 4198: ! 4199: return (value); ! 4200: } ! 4201: #endif /* !__GO32__ */ ! 4202: } ! 4203: ! 4204: /* **************************************************************** */ ! 4205: /* */ ! 4206: /* Undo, and Undoing */ ! 4207: /* */ ! 4208: /* **************************************************************** */ ! 4209: ! 4210: /* Non-zero tells rl_delete_text and rl_insert_text to not add to ! 4211: the undo list. */ ! 4212: int doing_an_undo = 0; ! 4213: ! 4214: /* The current undo list for THE_LINE. */ ! 4215: UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; ! 4216: ! 4217: /* Remember how to undo something. Concatenate some undos if that ! 4218: seems right. */ ! 4219: rl_add_undo (what, start, end, text) ! 4220: enum undo_code what; ! 4221: int start, end; ! 4222: char *text; ! 4223: { ! 4224: UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); ! 4225: temp->what = what; ! 4226: temp->start = start; ! 4227: temp->end = end; ! 4228: temp->text = text; ! 4229: temp->next = rl_undo_list; ! 4230: rl_undo_list = temp; ! 4231: } ! 4232: ! 4233: /* Free the existing undo list. */ ! 4234: free_undo_list () ! 4235: { ! 4236: while (rl_undo_list) { ! 4237: UNDO_LIST *release = rl_undo_list; ! 4238: rl_undo_list = rl_undo_list->next; ! 4239: ! 4240: if (release->what == UNDO_DELETE) ! 4241: free (release->text); ! 4242: ! 4243: free (release); ! 4244: } ! 4245: } ! 4246: ! 4247: /* Undo the next thing in the list. Return 0 if there ! 4248: is nothing to undo, or non-zero if there was. */ ! 4249: int ! 4250: rl_do_undo () ! 4251: { ! 4252: UNDO_LIST *release; ! 4253: int waiting_for_begin = 0; ! 4254: ! 4255: undo_thing: ! 4256: if (!rl_undo_list) ! 4257: return (0); ! 4258: ! 4259: doing_an_undo = 1; ! 4260: ! 4261: switch (rl_undo_list->what) { ! 4262: ! 4263: /* Undoing deletes means inserting some text. */ ! 4264: case UNDO_DELETE: ! 4265: rl_point = rl_undo_list->start; ! 4266: rl_insert_text (rl_undo_list->text); ! 4267: free (rl_undo_list->text); ! 4268: break; ! 4269: ! 4270: /* Undoing inserts means deleting some text. */ ! 4271: case UNDO_INSERT: ! 4272: rl_delete_text (rl_undo_list->start, rl_undo_list->end); ! 4273: rl_point = rl_undo_list->start; ! 4274: break; ! 4275: ! 4276: /* Undoing an END means undoing everything 'til we get to ! 4277: a BEGIN. */ ! 4278: case UNDO_END: ! 4279: waiting_for_begin++; ! 4280: break; ! 4281: ! 4282: /* Undoing a BEGIN means that we are done with this group. */ ! 4283: case UNDO_BEGIN: ! 4284: if (waiting_for_begin) ! 4285: waiting_for_begin--; ! 4286: else ! 4287: abort (); ! 4288: break; ! 4289: } ! 4290: ! 4291: doing_an_undo = 0; ! 4292: ! 4293: release = rl_undo_list; ! 4294: rl_undo_list = rl_undo_list->next; ! 4295: free (release); ! 4296: ! 4297: if (waiting_for_begin) ! 4298: goto undo_thing; ! 4299: ! 4300: return (1); ! 4301: } ! 4302: ! 4303: /* Begin a group. Subsequent undos are undone as an atomic operation. */ ! 4304: rl_begin_undo_group () ! 4305: { ! 4306: rl_add_undo (UNDO_BEGIN, 0, 0, 0); ! 4307: } ! 4308: ! 4309: /* End an undo group started with rl_begin_undo_group (). */ ! 4310: rl_end_undo_group () ! 4311: { ! 4312: rl_add_undo (UNDO_END, 0, 0, 0); ! 4313: } ! 4314: ! 4315: /* Save an undo entry for the text from START to END. */ ! 4316: rl_modifying (start, end) ! 4317: int start, end; ! 4318: { ! 4319: if (start > end) ! 4320: { ! 4321: int t = start; ! 4322: start = end; ! 4323: end = t; ! 4324: } ! 4325: ! 4326: if (start != end) ! 4327: { ! 4328: char *temp = rl_copy (start, end); ! 4329: rl_begin_undo_group (); ! 4330: rl_add_undo (UNDO_DELETE, start, end, temp); ! 4331: rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); ! 4332: rl_end_undo_group (); ! 4333: } ! 4334: } ! 4335: ! 4336: /* Revert the current line to its previous state. */ ! 4337: rl_revert_line () ! 4338: { ! 4339: if (!rl_undo_list) ding (); ! 4340: else { ! 4341: while (rl_undo_list) ! 4342: rl_do_undo (); ! 4343: } ! 4344: } ! 4345: ! 4346: /* Do some undoing of things that were done. */ ! 4347: rl_undo_command (count) ! 4348: { ! 4349: if (count < 0) return; /* Nothing to do. */ ! 4350: ! 4351: while (count) ! 4352: { ! 4353: if (rl_do_undo ()) ! 4354: { ! 4355: count--; ! 4356: } ! 4357: else ! 4358: { ! 4359: ding (); ! 4360: break; ! 4361: } ! 4362: } ! 4363: } ! 4364: ! 4365: /* **************************************************************** */ ! 4366: /* */ ! 4367: /* History Utilities */ ! 4368: /* */ ! 4369: /* **************************************************************** */ ! 4370: ! 4371: /* We already have a history library, and that is what we use to control ! 4372: the history features of readline. However, this is our local interface ! 4373: to the history mechanism. */ ! 4374: ! 4375: /* While we are editing the history, this is the saved ! 4376: version of the original line. */ ! 4377: HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL; ! 4378: ! 4379: /* Set the history pointer back to the last entry in the history. */ ! 4380: start_using_history () ! 4381: { ! 4382: using_history (); ! 4383: if (saved_line_for_history) ! 4384: free_history_entry (saved_line_for_history); ! 4385: ! 4386: saved_line_for_history = (HIST_ENTRY *)NULL; ! 4387: } ! 4388: ! 4389: /* Free the contents (and containing structure) of a HIST_ENTRY. */ ! 4390: free_history_entry (entry) ! 4391: HIST_ENTRY *entry; ! 4392: { ! 4393: if (!entry) return; ! 4394: if (entry->line) ! 4395: free (entry->line); ! 4396: free (entry); ! 4397: } ! 4398: ! 4399: /* Perhaps put back the current line if it has changed. */ ! 4400: maybe_replace_line () ! 4401: { ! 4402: HIST_ENTRY *temp = current_history (); ! 4403: ! 4404: /* If the current line has changed, save the changes. */ ! 4405: if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) ! 4406: { ! 4407: temp = replace_history_entry (where_history (), the_line, rl_undo_list); ! 4408: free (temp->line); ! 4409: free (temp); ! 4410: } ! 4411: } ! 4412: ! 4413: /* Put back the saved_line_for_history if there is one. */ ! 4414: maybe_unsave_line () ! 4415: { ! 4416: if (saved_line_for_history) ! 4417: { ! 4418: int line_len; ! 4419: ! 4420: line_len = strlen (saved_line_for_history->line); ! 4421: ! 4422: if (line_len >= rl_line_buffer_len) ! 4423: rl_extend_line_buffer (line_len); ! 4424: ! 4425: strcpy (the_line, saved_line_for_history->line); ! 4426: rl_undo_list = (UNDO_LIST *)saved_line_for_history->data; ! 4427: free_history_entry (saved_line_for_history); ! 4428: saved_line_for_history = (HIST_ENTRY *)NULL; ! 4429: rl_end = rl_point = strlen (the_line); ! 4430: } ! 4431: else ! 4432: ding (); ! 4433: } ! 4434: ! 4435: /* Save the current line in saved_line_for_history. */ ! 4436: maybe_save_line () ! 4437: { ! 4438: if (!saved_line_for_history) ! 4439: { ! 4440: saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); ! 4441: saved_line_for_history->line = savestring (the_line); ! 4442: saved_line_for_history->data = (char *)rl_undo_list; ! 4443: } ! 4444: } ! 4445: ! 4446: /* **************************************************************** */ ! 4447: /* */ ! 4448: /* History Commands */ ! 4449: /* */ ! 4450: /* **************************************************************** */ ! 4451: ! 4452: /* Meta-< goes to the start of the history. */ ! 4453: rl_beginning_of_history () ! 4454: { ! 4455: rl_get_previous_history (1 + where_history ()); ! 4456: } ! 4457: ! 4458: /* Meta-> goes to the end of the history. (The current line). */ ! 4459: rl_end_of_history () ! 4460: { ! 4461: maybe_replace_line (); ! 4462: using_history (); ! 4463: maybe_unsave_line (); ! 4464: } ! 4465: ! 4466: /* Move down to the next history line. */ ! 4467: rl_get_next_history (count) ! 4468: int count; ! 4469: { ! 4470: HIST_ENTRY *temp = (HIST_ENTRY *)NULL; ! 4471: ! 4472: if (count < 0) ! 4473: { ! 4474: rl_get_previous_history (-count); ! 4475: return; ! 4476: } ! 4477: ! 4478: if (!count) ! 4479: return; ! 4480: ! 4481: maybe_replace_line (); ! 4482: ! 4483: while (count) ! 4484: { ! 4485: temp = next_history (); ! 4486: if (!temp) ! 4487: break; ! 4488: --count; ! 4489: } ! 4490: ! 4491: if (!temp) ! 4492: maybe_unsave_line (); ! 4493: else ! 4494: { ! 4495: int line_len; ! 4496: ! 4497: line_len = strlen (temp->line); ! 4498: ! 4499: if (line_len >= rl_line_buffer_len) ! 4500: rl_extend_line_buffer (line_len); ! 4501: ! 4502: strcpy (the_line, temp->line); ! 4503: rl_undo_list = (UNDO_LIST *)temp->data; ! 4504: rl_end = rl_point = strlen (the_line); ! 4505: #if defined (VI_MODE) ! 4506: if (rl_editing_mode == vi_mode) ! 4507: rl_point = 0; ! 4508: #endif /* VI_MODE */ ! 4509: } ! 4510: } ! 4511: ! 4512: /* Get the previous item out of our interactive history, making it the current ! 4513: line. If there is no previous history, just ding. */ ! 4514: rl_get_previous_history (count) ! 4515: int count; ! 4516: { ! 4517: HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL; ! 4518: HIST_ENTRY *temp = (HIST_ENTRY *)NULL; ! 4519: ! 4520: if (count < 0) ! 4521: { ! 4522: rl_get_next_history (-count); ! 4523: return; ! 4524: } ! 4525: ! 4526: if (!count) ! 4527: return; ! 4528: ! 4529: /* If we don't have a line saved, then save this one. */ ! 4530: maybe_save_line (); ! 4531: ! 4532: /* If the current line has changed, save the changes. */ ! 4533: maybe_replace_line (); ! 4534: ! 4535: while (count) ! 4536: { ! 4537: temp = previous_history (); ! 4538: if (!temp) ! 4539: break; ! 4540: else ! 4541: old_temp = temp; ! 4542: --count; ! 4543: } ! 4544: ! 4545: /* If there was a large argument, and we moved back to the start of the ! 4546: history, that is not an error. So use the last value found. */ ! 4547: if (!temp && old_temp) ! 4548: temp = old_temp; ! 4549: ! 4550: if (!temp) ! 4551: ding (); ! 4552: else ! 4553: { ! 4554: int line_len; ! 4555: ! 4556: line_len = strlen (temp->line); ! 4557: ! 4558: if (line_len >= rl_line_buffer_len) ! 4559: rl_extend_line_buffer (line_len); ! 4560: ! 4561: strcpy (the_line, temp->line); ! 4562: rl_undo_list = (UNDO_LIST *)temp->data; ! 4563: rl_end = rl_point = line_len; ! 4564: ! 4565: #if defined (VI_MODE) ! 4566: if (rl_editing_mode == vi_mode) ! 4567: rl_point = 0; ! 4568: #endif /* VI_MODE */ ! 4569: } ! 4570: } ! 4571: ! 4572: ! 4573: /* **************************************************************** */ ! 4574: /* */ ! 4575: /* I-Search and Searching */ ! 4576: /* */ ! 4577: /* **************************************************************** */ ! 4578: ! 4579: /* Search backwards through the history looking for a string which is typed ! 4580: interactively. Start with the current line. */ ! 4581: rl_reverse_search_history (sign, key) ! 4582: int sign; ! 4583: int key; ! 4584: { ! 4585: rl_search_history (-sign, key); ! 4586: } ! 4587: ! 4588: /* Search forwards through the history looking for a string which is typed ! 4589: interactively. Start with the current line. */ ! 4590: rl_forward_search_history (sign, key) ! 4591: int sign; ! 4592: int key; ! 4593: { ! 4594: rl_search_history (sign, key); ! 4595: } ! 4596: ! 4597: /* Display the current state of the search in the echo-area. ! 4598: SEARCH_STRING contains the string that is being searched for, ! 4599: DIRECTION is zero for forward, or 1 for reverse, ! 4600: WHERE is the history list number of the current line. If it is ! 4601: -1, then this line is the starting one. */ ! 4602: rl_display_search (search_string, reverse_p, where) ! 4603: char *search_string; ! 4604: int reverse_p, where; ! 4605: { ! 4606: char *message = (char *)NULL; ! 4607: ! 4608: message = ! 4609: (char *)alloca (1 + (search_string ? strlen (search_string) : 0) + 30); ! 4610: ! 4611: *message = '\0'; ! 4612: ! 4613: #if defined (NOTDEF) ! 4614: if (where != -1) ! 4615: sprintf (message, "[%d]", where + history_base); ! 4616: #endif /* NOTDEF */ ! 4617: ! 4618: strcat (message, "("); ! 4619: ! 4620: if (reverse_p) ! 4621: strcat (message, "reverse-"); ! 4622: ! 4623: strcat (message, "i-search)`"); ! 4624: ! 4625: if (search_string) ! 4626: strcat (message, search_string); ! 4627: ! 4628: strcat (message, "': "); ! 4629: rl_message (message, 0, 0); ! 4630: rl_redisplay (); ! 4631: } ! 4632: ! 4633: /* Search through the history looking for an interactively typed string. ! 4634: This is analogous to i-search. We start the search in the current line. ! 4635: DIRECTION is which direction to search; >= 0 means forward, < 0 means ! 4636: backwards. */ ! 4637: rl_search_history (direction, invoking_key) ! 4638: int direction; ! 4639: int invoking_key; ! 4640: { ! 4641: /* The string that the user types in to search for. */ ! 4642: char *search_string = (char *)alloca (128); ! 4643: ! 4644: /* The current length of SEARCH_STRING. */ ! 4645: int search_string_index; ! 4646: ! 4647: /* The list of lines to search through. */ ! 4648: char **lines; ! 4649: ! 4650: /* The length of LINES. */ ! 4651: int hlen; ! 4652: ! 4653: /* Where we get LINES from. */ ! 4654: HIST_ENTRY **hlist = history_list (); ! 4655: ! 4656: register int i = 0; ! 4657: int orig_point = rl_point; ! 4658: int orig_line = where_history (); ! 4659: int last_found_line = orig_line; ! 4660: int c, done = 0; ! 4661: ! 4662: /* The line currently being searched. */ ! 4663: char *sline; ! 4664: ! 4665: /* Offset in that line. */ ! 4666: int index; ! 4667: ! 4668: /* Non-zero if we are doing a reverse search. */ ! 4669: int reverse = (direction < 0); ! 4670: ! 4671: /* Create an arrary of pointers to the lines that we want to search. */ ! 4672: maybe_replace_line (); ! 4673: if (hlist) ! 4674: for (i = 0; hlist[i]; i++); ! 4675: ! 4676: /* Allocate space for this many lines, +1 for the current input line, ! 4677: and remember those lines. */ ! 4678: lines = (char **)alloca ((1 + (hlen = i)) * sizeof (char *)); ! 4679: for (i = 0; i < hlen; i++) ! 4680: lines[i] = hlist[i]->line; ! 4681: ! 4682: if (saved_line_for_history) ! 4683: lines[i] = saved_line_for_history->line; ! 4684: else ! 4685: /* So I have to type it in this way instead. */ ! 4686: { ! 4687: char *alloced_line; ! 4688: ! 4689: /* Keep that mips alloca happy. */ ! 4690: alloced_line = (char *)alloca (1 + strlen (the_line)); ! 4691: lines[i] = alloced_line; ! 4692: strcpy (lines[i], &the_line[0]); ! 4693: } ! 4694: ! 4695: hlen++; ! 4696: ! 4697: /* The line where we start the search. */ ! 4698: i = orig_line; ! 4699: ! 4700: /* Initialize search parameters. */ ! 4701: *search_string = '\0'; ! 4702: search_string_index = 0; ! 4703: ! 4704: /* Normalize DIRECTION into 1 or -1. */ ! 4705: if (direction >= 0) ! 4706: direction = 1; ! 4707: else ! 4708: direction = -1; ! 4709: ! 4710: rl_display_search (search_string, reverse, -1); ! 4711: ! 4712: sline = the_line; ! 4713: index = rl_point; ! 4714: ! 4715: while (!done) ! 4716: { ! 4717: c = rl_read_key (); ! 4718: ! 4719: /* Hack C to Do What I Mean. */ ! 4720: { ! 4721: Function *f = (Function *)NULL; ! 4722: ! 4723: if (keymap[c].type == ISFUNC) ! 4724: { ! 4725: f = keymap[c].function; ! 4726: ! 4727: if (f == rl_reverse_search_history) ! 4728: c = reverse ? -1 : -2; ! 4729: else if (f == rl_forward_search_history) ! 4730: c = !reverse ? -1 : -2; ! 4731: } ! 4732: } ! 4733: ! 4734: switch (c) ! 4735: { ! 4736: case ESC: ! 4737: done = 1; ! 4738: continue; ! 4739: ! 4740: /* case invoking_key: */ ! 4741: case -1: ! 4742: goto search_again; ! 4743: ! 4744: /* switch directions */ ! 4745: case -2: ! 4746: direction = -direction; ! 4747: reverse = (direction < 0); ! 4748: ! 4749: goto do_search; ! 4750: ! 4751: case CTRL ('G'): ! 4752: strcpy (the_line, lines[orig_line]); ! 4753: rl_point = orig_point; ! 4754: rl_end = strlen (the_line); ! 4755: rl_clear_message (); ! 4756: return; ! 4757: ! 4758: default: ! 4759: if (c < 32 || c > 126) ! 4760: { ! 4761: rl_execute_next (c); ! 4762: done = 1; ! 4763: continue; ! 4764: } ! 4765: else ! 4766: { ! 4767: search_string[search_string_index++] = c; ! 4768: search_string[search_string_index] = '\0'; ! 4769: goto do_search; ! 4770: ! 4771: search_again: ! 4772: ! 4773: if (!search_string_index) ! 4774: continue; ! 4775: else ! 4776: { ! 4777: if (reverse) ! 4778: --index; ! 4779: else ! 4780: if (index != strlen (sline)) ! 4781: ++index; ! 4782: else ! 4783: ding (); ! 4784: } ! 4785: do_search: ! 4786: ! 4787: while (1) ! 4788: { ! 4789: if (reverse) ! 4790: { ! 4791: while (index >= 0) ! 4792: if (strncmp ! 4793: (search_string, sline + index, search_string_index) ! 4794: == 0) ! 4795: goto string_found; ! 4796: else ! 4797: index--; ! 4798: } ! 4799: else ! 4800: { ! 4801: register int limit = ! 4802: (strlen (sline) - search_string_index) + 1; ! 4803: ! 4804: while (index < limit) ! 4805: { ! 4806: if (strncmp (search_string, ! 4807: sline + index, ! 4808: search_string_index) == 0) ! 4809: goto string_found; ! 4810: index++; ! 4811: } ! 4812: } ! 4813: ! 4814: next_line: ! 4815: i += direction; ! 4816: ! 4817: /* At limit for direction? */ ! 4818: if ((reverse && i < 0) || ! 4819: (!reverse && i == hlen)) ! 4820: goto search_failed; ! 4821: ! 4822: sline = lines[i]; ! 4823: if (reverse) ! 4824: index = strlen (sline); ! 4825: else ! 4826: index = 0; ! 4827: ! 4828: /* If the search string is longer than the current ! 4829: line, no match. */ ! 4830: if (search_string_index > strlen (sline)) ! 4831: goto next_line; ! 4832: ! 4833: /* Start actually searching. */ ! 4834: if (reverse) ! 4835: index -= search_string_index; ! 4836: } ! 4837: ! 4838: search_failed: ! 4839: /* We cannot find the search string. Ding the bell. */ ! 4840: ding (); ! 4841: i = last_found_line; ! 4842: break; ! 4843: ! 4844: string_found: ! 4845: /* We have found the search string. Just display it. But don't ! 4846: actually move there in the history list until the user accepts ! 4847: the location. */ ! 4848: { ! 4849: int line_len; ! 4850: ! 4851: line_len = strlen (lines[i]); ! 4852: ! 4853: if (line_len >= rl_line_buffer_len) ! 4854: rl_extend_line_buffer (line_len); ! 4855: ! 4856: strcpy (the_line, lines[i]); ! 4857: rl_point = index; ! 4858: rl_end = line_len; ! 4859: last_found_line = i; ! 4860: rl_display_search ! 4861: (search_string, reverse, (i == orig_line) ? -1 : i); ! 4862: } ! 4863: } ! 4864: } ! 4865: continue; ! 4866: } ! 4867: ! 4868: /* The searching is over. The user may have found the string that she ! 4869: was looking for, or else she may have exited a failing search. If ! 4870: INDEX is -1, then that shows that the string searched for was not ! 4871: found. We use this to determine where to place rl_point. */ ! 4872: { ! 4873: int now = last_found_line; ! 4874: ! 4875: /* First put back the original state. */ ! 4876: strcpy (the_line, lines[orig_line]); ! 4877: ! 4878: if (now < orig_line) ! 4879: rl_get_previous_history (orig_line - now); ! 4880: else ! 4881: rl_get_next_history (now - orig_line); ! 4882: ! 4883: /* If the index of the "matched" string is less than zero, then the ! 4884: final search string was never matched, so put point somewhere ! 4885: reasonable. */ ! 4886: if (index < 0) ! 4887: index = strlen (the_line); ! 4888: ! 4889: rl_point = index; ! 4890: rl_clear_message (); ! 4891: } ! 4892: } ! 4893: ! 4894: /* Make C be the next command to be executed. */ ! 4895: rl_execute_next (c) ! 4896: int c; ! 4897: { ! 4898: rl_pending_input = c; ! 4899: } ! 4900: ! 4901: /* **************************************************************** */ ! 4902: /* */ ! 4903: /* Killing Mechanism */ ! 4904: /* */ ! 4905: /* **************************************************************** */ ! 4906: ! 4907: /* What we assume for a max number of kills. */ ! 4908: #define DEFAULT_MAX_KILLS 10 ! 4909: ! 4910: /* The real variable to look at to find out when to flush kills. */ ! 4911: int rl_max_kills = DEFAULT_MAX_KILLS; ! 4912: ! 4913: /* Where to store killed text. */ ! 4914: char **rl_kill_ring = (char **)NULL; ! 4915: ! 4916: /* Where we are in the kill ring. */ ! 4917: int rl_kill_index = 0; ! 4918: ! 4919: /* How many slots we have in the kill ring. */ ! 4920: int rl_kill_ring_length = 0; ! 4921: ! 4922: /* How to say that you only want to save a certain amount ! 4923: of kill material. */ ! 4924: rl_set_retained_kills (num) ! 4925: int num; ! 4926: {} ! 4927: ! 4928: /* The way to kill something. This appends or prepends to the last ! 4929: kill, if the last command was a kill command. if FROM is less ! 4930: than TO, then the text is appended, otherwise prepended. If the ! 4931: last command was not a kill command, then a new slot is made for ! 4932: this kill. */ ! 4933: rl_kill_text (from, to) ! 4934: int from, to; ! 4935: { ! 4936: int slot; ! 4937: char *text = rl_copy (from, to); ! 4938: ! 4939: /* Is there anything to kill? */ ! 4940: if (from == to) ! 4941: { ! 4942: free (text); ! 4943: last_command_was_kill++; ! 4944: return; ! 4945: } ! 4946: ! 4947: /* Delete the copied text from the line. */ ! 4948: rl_delete_text (from, to); ! 4949: ! 4950: /* First, find the slot to work with. */ ! 4951: if (!last_command_was_kill) ! 4952: { ! 4953: /* Get a new slot. */ ! 4954: if (!rl_kill_ring) ! 4955: { ! 4956: /* If we don't have any defined, then make one. */ ! 4957: rl_kill_ring = (char **) ! 4958: xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *)); ! 4959: slot = 1; ! 4960: } ! 4961: else ! 4962: { ! 4963: /* We have to add a new slot on the end, unless we have ! 4964: exceeded the max limit for remembering kills. */ ! 4965: slot = rl_kill_ring_length; ! 4966: if (slot == rl_max_kills) ! 4967: { ! 4968: register int i; ! 4969: free (rl_kill_ring[0]); ! 4970: for (i = 0; i < slot; i++) ! 4971: rl_kill_ring[i] = rl_kill_ring[i + 1]; ! 4972: } ! 4973: else ! 4974: { ! 4975: rl_kill_ring = ! 4976: (char **) ! 4977: xrealloc (rl_kill_ring, ! 4978: ((slot = (rl_kill_ring_length += 1)) + 1) ! 4979: * sizeof (char *)); ! 4980: } ! 4981: } ! 4982: slot--; ! 4983: } ! 4984: else ! 4985: { ! 4986: slot = rl_kill_ring_length - 1; ! 4987: } ! 4988: ! 4989: /* If the last command was a kill, prepend or append. */ ! 4990: if (last_command_was_kill && rl_editing_mode != vi_mode) ! 4991: { ! 4992: char *old = rl_kill_ring[slot]; ! 4993: char *new = (char *)xmalloc (1 + strlen (old) + strlen (text)); ! 4994: ! 4995: if (from < to) ! 4996: { ! 4997: strcpy (new, old); ! 4998: strcat (new, text); ! 4999: } ! 5000: else ! 5001: { ! 5002: strcpy (new, text); ! 5003: strcat (new, old); ! 5004: } ! 5005: free (old); ! 5006: free (text); ! 5007: rl_kill_ring[slot] = new; ! 5008: } ! 5009: else ! 5010: { ! 5011: rl_kill_ring[slot] = text; ! 5012: } ! 5013: rl_kill_index = slot; ! 5014: last_command_was_kill++; ! 5015: } ! 5016: ! 5017: /* Now REMEMBER! In order to do prepending or appending correctly, kill ! 5018: commands always make rl_point's original position be the FROM argument, ! 5019: and rl_point's extent be the TO argument. */ ! 5020: ! 5021: /* **************************************************************** */ ! 5022: /* */ ! 5023: /* Killing Commands */ ! 5024: /* */ ! 5025: /* **************************************************************** */ ! 5026: ! 5027: /* Delete the word at point, saving the text in the kill ring. */ ! 5028: rl_kill_word (count) ! 5029: int count; ! 5030: { ! 5031: int orig_point = rl_point; ! 5032: ! 5033: if (count < 0) ! 5034: rl_backward_kill_word (-count); ! 5035: else ! 5036: { ! 5037: rl_forward_word (count); ! 5038: ! 5039: if (rl_point != orig_point) ! 5040: rl_kill_text (orig_point, rl_point); ! 5041: ! 5042: rl_point = orig_point; ! 5043: } ! 5044: } ! 5045: ! 5046: /* Rubout the word before point, placing it on the kill ring. */ ! 5047: rl_backward_kill_word (count) ! 5048: int count; ! 5049: { ! 5050: int orig_point = rl_point; ! 5051: ! 5052: if (count < 0) ! 5053: rl_kill_word (-count); ! 5054: else ! 5055: { ! 5056: rl_backward_word (count); ! 5057: ! 5058: if (rl_point != orig_point) ! 5059: rl_kill_text (orig_point, rl_point); ! 5060: } ! 5061: } ! 5062: ! 5063: /* Kill from here to the end of the line. If DIRECTION is negative, kill ! 5064: back to the line start instead. */ ! 5065: rl_kill_line (direction) ! 5066: int direction; ! 5067: { ! 5068: int orig_point = rl_point; ! 5069: ! 5070: if (direction < 0) ! 5071: rl_backward_kill_line (1); ! 5072: else ! 5073: { ! 5074: rl_end_of_line (); ! 5075: if (orig_point != rl_point) ! 5076: rl_kill_text (orig_point, rl_point); ! 5077: rl_point = orig_point; ! 5078: } ! 5079: } ! 5080: ! 5081: /* Kill backwards to the start of the line. If DIRECTION is negative, kill ! 5082: forwards to the line end instead. */ ! 5083: rl_backward_kill_line (direction) ! 5084: int direction; ! 5085: { ! 5086: int orig_point = rl_point; ! 5087: ! 5088: if (direction < 0) ! 5089: rl_kill_line (1); ! 5090: else ! 5091: { ! 5092: if (!rl_point) ! 5093: ding (); ! 5094: else ! 5095: { ! 5096: rl_beg_of_line (); ! 5097: rl_kill_text (orig_point, rl_point); ! 5098: } ! 5099: } ! 5100: } ! 5101: ! 5102: /* Yank back the last killed text. This ignores arguments. */ ! 5103: rl_yank () ! 5104: { ! 5105: if (!rl_kill_ring) rl_abort (); ! 5106: rl_insert_text (rl_kill_ring[rl_kill_index]); ! 5107: } ! 5108: ! 5109: /* If the last command was yank, or yank_pop, and the text just ! 5110: before point is identical to the current kill item, then ! 5111: delete that text from the line, rotate the index down, and ! 5112: yank back some other text. */ ! 5113: rl_yank_pop () ! 5114: { ! 5115: int l; ! 5116: ! 5117: if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) || ! 5118: !rl_kill_ring) ! 5119: { ! 5120: rl_abort (); ! 5121: } ! 5122: ! 5123: l = strlen (rl_kill_ring[rl_kill_index]); ! 5124: if (((rl_point - l) >= 0) && ! 5125: (strncmp (the_line + (rl_point - l), ! 5126: rl_kill_ring[rl_kill_index], l) == 0)) ! 5127: { ! 5128: rl_delete_text ((rl_point - l), rl_point); ! 5129: rl_point -= l; ! 5130: rl_kill_index--; ! 5131: if (rl_kill_index < 0) ! 5132: rl_kill_index = rl_kill_ring_length - 1; ! 5133: rl_yank (); ! 5134: } ! 5135: else ! 5136: rl_abort (); ! 5137: ! 5138: } ! 5139: ! 5140: /* Yank the COUNTth argument from the previous history line. */ ! 5141: rl_yank_nth_arg (count, ignore) ! 5142: int count; ! 5143: { ! 5144: register HIST_ENTRY *entry = previous_history (); ! 5145: char *arg; ! 5146: ! 5147: if (entry) ! 5148: next_history (); ! 5149: else ! 5150: { ! 5151: ding (); ! 5152: return; ! 5153: } ! 5154: ! 5155: arg = history_arg_extract (count, count, entry->line); ! 5156: if (!arg || !*arg) ! 5157: { ! 5158: ding (); ! 5159: return; ! 5160: } ! 5161: ! 5162: rl_begin_undo_group (); ! 5163: ! 5164: #if defined (VI_MODE) ! 5165: /* Vi mode always inserts a space befoe yanking the argument, and it ! 5166: inserts it right *after* rl_point. */ ! 5167: if (rl_editing_mode == vi_mode) ! 5168: rl_point++; ! 5169: #endif /* VI_MODE */ ! 5170: ! 5171: if (rl_point && the_line[rl_point - 1] != ' ') ! 5172: rl_insert_text (" "); ! 5173: ! 5174: rl_insert_text (arg); ! 5175: free (arg); ! 5176: ! 5177: rl_end_undo_group (); ! 5178: } ! 5179: ! 5180: /* How to toggle back and forth between editing modes. */ ! 5181: rl_vi_editing_mode () ! 5182: { ! 5183: #if defined (VI_MODE) ! 5184: rl_editing_mode = vi_mode; ! 5185: rl_vi_insertion_mode (); ! 5186: #endif /* VI_MODE */ ! 5187: } ! 5188: ! 5189: rl_emacs_editing_mode () ! 5190: { ! 5191: rl_editing_mode = emacs_mode; ! 5192: keymap = emacs_standard_keymap; ! 5193: } ! 5194: ! 5195: ! 5196: /* **************************************************************** */ ! 5197: /* */ ! 5198: /* Completion */ ! 5199: /* */ ! 5200: /* **************************************************************** */ ! 5201: ! 5202: /* Non-zero means that case is not significant in completion. */ ! 5203: int completion_case_fold = 0; ! 5204: ! 5205: /* Return an array of (char *) which is a list of completions for TEXT. ! 5206: If there are no completions, return a NULL pointer. ! 5207: The first entry in the returned array is the substitution for TEXT. ! 5208: The remaining entries are the possible completions. ! 5209: The array is terminated with a NULL pointer. ! 5210: ! 5211: ENTRY_FUNCTION is a function of two args, and returns a (char *). ! 5212: The first argument is TEXT. ! 5213: The second is a state argument; it should be zero on the first call, and ! 5214: non-zero on subsequent calls. It returns a NULL pointer to the caller ! 5215: when there are no more matches. ! 5216: */ ! 5217: char ** ! 5218: completion_matches (text, entry_function) ! 5219: char *text; ! 5220: char *(*entry_function) (); ! 5221: { ! 5222: /* Number of slots in match_list. */ ! 5223: int match_list_size; ! 5224: ! 5225: /* The list of matches. */ ! 5226: char **match_list = ! 5227: (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *)); ! 5228: ! 5229: /* Number of matches actually found. */ ! 5230: int matches = 0; ! 5231: ! 5232: /* Temporary string binder. */ ! 5233: char *string; ! 5234: ! 5235: match_list[1] = (char *)NULL; ! 5236: ! 5237: while (string = (*entry_function) (text, matches)) ! 5238: { ! 5239: if (matches + 1 == match_list_size) ! 5240: match_list = (char **)xrealloc ! 5241: (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); ! 5242: ! 5243: match_list[++matches] = string; ! 5244: match_list[matches + 1] = (char *)NULL; ! 5245: } ! 5246: ! 5247: /* If there were any matches, then look through them finding out the ! 5248: lowest common denominator. That then becomes match_list[0]. */ ! 5249: if (matches) ! 5250: { ! 5251: register int i = 1; ! 5252: int low = 100000; /* Count of max-matched characters. */ ! 5253: ! 5254: /* If only one match, just use that. */ ! 5255: if (matches == 1) ! 5256: { ! 5257: match_list[0] = match_list[1]; ! 5258: match_list[1] = (char *)NULL; ! 5259: } ! 5260: else ! 5261: { ! 5262: /* Otherwise, compare each member of the list with ! 5263: the next, finding out where they stop matching. */ ! 5264: ! 5265: while (i < matches) ! 5266: { ! 5267: register int c1, c2, si; ! 5268: ! 5269: if (completion_case_fold) ! 5270: { ! 5271: for (si = 0; ! 5272: (c1 = to_lower(match_list[i][si])) && ! 5273: (c2 = to_lower(match_list[i + 1][si])); ! 5274: si++) ! 5275: if (c1 != c2) break; ! 5276: } ! 5277: else ! 5278: { ! 5279: for (si = 0; ! 5280: (c1 = match_list[i][si]) && ! 5281: (c2 = match_list[i + 1][si]); ! 5282: si++) ! 5283: if (c1 != c2) break; ! 5284: } ! 5285: ! 5286: if (low > si) low = si; ! 5287: i++; ! 5288: } ! 5289: match_list[0] = (char *)xmalloc (low + 1); ! 5290: strncpy (match_list[0], match_list[1], low); ! 5291: match_list[0][low] = '\0'; ! 5292: } ! 5293: } ! 5294: else /* There were no matches. */ ! 5295: { ! 5296: free (match_list); ! 5297: match_list = (char **)NULL; ! 5298: } ! 5299: return (match_list); ! 5300: } ! 5301: ! 5302: /* Okay, now we write the entry_function for filename completion. In the ! 5303: general case. Note that completion in the shell is a little different ! 5304: because of all the pathnames that must be followed when looking up the ! 5305: completion for a command. */ ! 5306: char * ! 5307: filename_completion_function (text, state) ! 5308: int state; ! 5309: char *text; ! 5310: { ! 5311: static DIR *directory; ! 5312: static char *filename = (char *)NULL; ! 5313: static char *dirname = (char *)NULL; ! 5314: static char *users_dirname = (char *)NULL; ! 5315: static int filename_len; ! 5316: ! 5317: dirent *entry = (dirent *)NULL; ! 5318: ! 5319: /* If we don't have any state, then do some initialization. */ ! 5320: if (!state) ! 5321: { ! 5322: char *temp; ! 5323: ! 5324: if (dirname) free (dirname); ! 5325: if (filename) free (filename); ! 5326: if (users_dirname) free (users_dirname); ! 5327: ! 5328: filename = savestring (text); ! 5329: if (!*text) text = "."; ! 5330: dirname = savestring (text); ! 5331: ! 5332: temp = rindex (dirname, '/'); ! 5333: ! 5334: if (temp) ! 5335: { ! 5336: strcpy (filename, ++temp); ! 5337: *temp = '\0'; ! 5338: } ! 5339: else ! 5340: strcpy (dirname, "."); ! 5341: ! 5342: /* We aren't done yet. We also support the "~user" syntax. */ ! 5343: ! 5344: /* Save the version of the directory that the user typed. */ ! 5345: users_dirname = savestring (dirname); ! 5346: { ! 5347: char *temp_dirname; ! 5348: ! 5349: temp_dirname = tilde_expand (dirname); ! 5350: free (dirname); ! 5351: dirname = temp_dirname; ! 5352: ! 5353: if (rl_symbolic_link_hook) ! 5354: (*rl_symbolic_link_hook) (&dirname); ! 5355: } ! 5356: directory = opendir (dirname); ! 5357: filename_len = strlen (filename); ! 5358: ! 5359: rl_filename_completion_desired = 1; ! 5360: } ! 5361: ! 5362: /* At this point we should entertain the possibility of hacking wildcarded ! 5363: filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name ! 5364: contains globbing characters, then build an array of directories to ! 5365: glob on, and glob on the first one. */ ! 5366: ! 5367: /* Now that we have some state, we can read the directory. */ ! 5368: ! 5369: while (directory && (entry = readdir (directory))) ! 5370: { ! 5371: /* Special case for no filename. ! 5372: All entries except "." and ".." match. */ ! 5373: if (!filename_len) ! 5374: { ! 5375: if ((strcmp (entry->d_name, ".") != 0) && ! 5376: (strcmp (entry->d_name, "..") != 0)) ! 5377: break; ! 5378: } ! 5379: else ! 5380: { ! 5381: /* Otherwise, if these match upto the length of filename, then ! 5382: it is a match. */ ! 5383: if (entry->d_name[0] == filename[0] && /* Quick test */ ! 5384: (strncmp (filename, entry->d_name, filename_len) == 0)) ! 5385: { ! 5386: break; ! 5387: } ! 5388: } ! 5389: } ! 5390: ! 5391: if (!entry) ! 5392: { ! 5393: if (directory) ! 5394: { ! 5395: closedir (directory); ! 5396: directory = (DIR *)NULL; ! 5397: } ! 5398: return (char *)NULL; ! 5399: } ! 5400: else ! 5401: { ! 5402: char *temp; ! 5403: ! 5404: if (dirname && (strcmp (dirname, ".") != 0)) ! 5405: { ! 5406: temp = (char *) ! 5407: xmalloc (1 + strlen (users_dirname) + strlen (entry->d_name)); ! 5408: strcpy (temp, users_dirname); ! 5409: strcat (temp, entry->d_name); ! 5410: } ! 5411: else ! 5412: { ! 5413: temp = (savestring (entry->d_name)); ! 5414: } ! 5415: return (temp); ! 5416: } ! 5417: } ! 5418: ! 5419: ! 5420: /* **************************************************************** */ ! 5421: /* */ ! 5422: /* Binding keys */ ! 5423: /* */ ! 5424: /* **************************************************************** */ ! 5425: ! 5426: /* rl_add_defun (char *name, Function *function, int key) ! 5427: Add NAME to the list of named functions. Make FUNCTION ! 5428: be the function that gets called. ! 5429: If KEY is not -1, then bind it. */ ! 5430: rl_add_defun (name, function, key) ! 5431: char *name; ! 5432: Function *function; ! 5433: int key; ! 5434: { ! 5435: if (key != -1) ! 5436: rl_bind_key (key, function); ! 5437: rl_add_funmap_entry (name, function); ! 5438: } ! 5439: ! 5440: /* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */ ! 5441: int ! 5442: rl_bind_key (key, function) ! 5443: int key; ! 5444: Function *function; ! 5445: { ! 5446: if (key < 0) ! 5447: return (key); ! 5448: ! 5449: if (key > 127 && key < 256) ! 5450: { ! 5451: if (keymap[ESC].type == ISKMAP) ! 5452: { ! 5453: Keymap escmap = (Keymap)keymap[ESC].function; ! 5454: ! 5455: key -= 128; ! 5456: escmap[key].type = ISFUNC; ! 5457: escmap[key].function = function; ! 5458: return (0); ! 5459: } ! 5460: return (key); ! 5461: } ! 5462: ! 5463: keymap[key].type = ISFUNC; ! 5464: keymap[key].function = function; ! 5465: return (0); ! 5466: } ! 5467: ! 5468: /* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid ! 5469: KEY. */ ! 5470: int ! 5471: rl_bind_key_in_map (key, function, map) ! 5472: int key; ! 5473: Function *function; ! 5474: Keymap map; ! 5475: { ! 5476: int result; ! 5477: Keymap oldmap = keymap; ! 5478: ! 5479: keymap = map; ! 5480: result = rl_bind_key (key, function); ! 5481: keymap = oldmap; ! 5482: return (result); ! 5483: } ! 5484: ! 5485: /* Make KEY do nothing in the currently selected keymap. ! 5486: Returns non-zero in case of error. */ ! 5487: int ! 5488: rl_unbind_key (key) ! 5489: int key; ! 5490: { ! 5491: return (rl_bind_key (key, (Function *)NULL)); ! 5492: } ! 5493: ! 5494: /* Make KEY do nothing in MAP. ! 5495: Returns non-zero in case of error. */ ! 5496: int ! 5497: rl_unbind_key_in_map (key, map) ! 5498: int key; ! 5499: Keymap map; ! 5500: { ! 5501: return (rl_bind_key_in_map (key, (Function *)NULL, map)); ! 5502: } ! 5503: ! 5504: /* Bind the key sequence represented by the string KEYSEQ to ! 5505: FUNCTION. This makes new keymaps as necessary. The initial ! 5506: place to do bindings is in MAP. */ ! 5507: rl_set_key (keyseq, function, map) ! 5508: char *keyseq; ! 5509: Function *function; ! 5510: Keymap map; ! 5511: { ! 5512: rl_generic_bind (ISFUNC, keyseq, function, map); ! 5513: } ! 5514: ! 5515: /* Bind the key sequence represented by the string KEYSEQ to ! 5516: the string of characters MACRO. This makes new keymaps as ! 5517: necessary. The initial place to do bindings is in MAP. */ ! 5518: rl_macro_bind (keyseq, macro, map) ! 5519: char *keyseq, *macro; ! 5520: Keymap map; ! 5521: { ! 5522: char *macro_keys; ! 5523: int macro_keys_len; ! 5524: ! 5525: macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1); ! 5526: ! 5527: if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len)) ! 5528: { ! 5529: free (macro_keys); ! 5530: return; ! 5531: } ! 5532: rl_generic_bind (ISMACR, keyseq, macro_keys, map); ! 5533: } ! 5534: ! 5535: /* Bind the key sequence represented by the string KEYSEQ to ! 5536: the arbitrary pointer DATA. TYPE says what kind of data is ! 5537: pointed to by DATA, right now this can be a function (ISFUNC), ! 5538: a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps ! 5539: as necessary. The initial place to do bindings is in MAP. */ ! 5540: ! 5541: static void ! 5542: rl_generic_bind (type, keyseq, data, map) ! 5543: int type; ! 5544: char *keyseq, *data; ! 5545: Keymap map; ! 5546: { ! 5547: char *keys; ! 5548: int keys_len; ! 5549: register int i; ! 5550: ! 5551: /* If no keys to bind to, exit right away. */ ! 5552: if (!keyseq || !*keyseq) ! 5553: { ! 5554: if (type == ISMACR) ! 5555: free (data); ! 5556: return; ! 5557: } ! 5558: ! 5559: keys = (char *)alloca (1 + (2 * strlen (keyseq))); ! 5560: ! 5561: /* Translate the ASCII representation of KEYSEQ into an array ! 5562: of characters. Stuff the characters into ARRAY, and the ! 5563: length of ARRAY into LENGTH. */ ! 5564: if (rl_translate_keyseq (keyseq, keys, &keys_len)) ! 5565: return; ! 5566: ! 5567: /* Bind keys, making new keymaps as necessary. */ ! 5568: for (i = 0; i < keys_len; i++) ! 5569: { ! 5570: if (i + 1 < keys_len) ! 5571: { ! 5572: if (map[keys[i]].type != ISKMAP) ! 5573: { ! 5574: if (map[i].type == ISMACR) ! 5575: free ((char *)map[i].function); ! 5576: ! 5577: map[keys[i]].type = ISKMAP; ! 5578: map[keys[i]].function = (Function *)rl_make_bare_keymap (); ! 5579: } ! 5580: map = (Keymap)map[keys[i]].function; ! 5581: } ! 5582: else ! 5583: { ! 5584: if (map[keys[i]].type == ISMACR) ! 5585: free ((char *)map[keys[i]].function); ! 5586: ! 5587: map[keys[i]].function = (Function *)data; ! 5588: map[keys[i]].type = type; ! 5589: } ! 5590: } ! 5591: } ! 5592: ! 5593: /* Translate the ASCII representation of SEQ, stuffing the ! 5594: values into ARRAY, an array of characters. LEN gets the ! 5595: final length of ARRAY. Return non-zero if there was an ! 5596: error parsing SEQ. */ ! 5597: rl_translate_keyseq (seq, array, len) ! 5598: char *seq, *array; ! 5599: int *len; ! 5600: { ! 5601: register int i, c, l = 0; ! 5602: ! 5603: for (i = 0; c = seq[i]; i++) ! 5604: { ! 5605: if (c == '\\') ! 5606: { ! 5607: c = seq[++i]; ! 5608: ! 5609: if (!c) ! 5610: break; ! 5611: ! 5612: if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || ! 5613: (c == 'e')) ! 5614: { ! 5615: /* Handle special case of backwards define. */ ! 5616: if (strncmp (&seq[i], "C-\\M-", 5) == 0) ! 5617: { ! 5618: array[l++] = ESC; ! 5619: i += 5; ! 5620: array[l++] = CTRL (to_upper (seq[i])); ! 5621: if (!seq[i]) ! 5622: i--; ! 5623: continue; ! 5624: } ! 5625: ! 5626: switch (c) ! 5627: { ! 5628: case 'M': ! 5629: i++; ! 5630: array[l++] = ESC; ! 5631: break; ! 5632: ! 5633: case 'C': ! 5634: i += 2; ! 5635: /* Special hack for C-?... */ ! 5636: if (seq[i] == '?') ! 5637: array[l++] = RUBOUT; ! 5638: else ! 5639: array[l++] = CTRL (to_upper (seq[i])); ! 5640: break; ! 5641: ! 5642: case 'e': ! 5643: array[l++] = ESC; ! 5644: } ! 5645: ! 5646: continue; ! 5647: } ! 5648: } ! 5649: array[l++] = c; ! 5650: } ! 5651: ! 5652: *len = l; ! 5653: array[l] = '\0'; ! 5654: return (0); ! 5655: } ! 5656: ! 5657: /* Return a pointer to the function that STRING represents. ! 5658: If STRING doesn't have a matching function, then a NULL pointer ! 5659: is returned. */ ! 5660: Function * ! 5661: rl_named_function (string) ! 5662: char *string; ! 5663: { ! 5664: register int i; ! 5665: ! 5666: for (i = 0; funmap[i]; i++) ! 5667: if (stricmp (funmap[i]->name, string) == 0) ! 5668: return (funmap[i]->function); ! 5669: return ((Function *)NULL); ! 5670: } ! 5671: ! 5672: /* The last key bindings file read. */ ! 5673: #ifdef __MSDOS__ ! 5674: /* Don't know what to do, but this is a guess */ ! 5675: static char *last_readline_init_file = "/INPUTRC"; ! 5676: #else ! 5677: static char *last_readline_init_file = "~/.inputrc"; ! 5678: #endif ! 5679: ! 5680: /* Re-read the current keybindings file. */ ! 5681: rl_re_read_init_file (count, ignore) ! 5682: int count, ignore; ! 5683: { ! 5684: rl_read_init_file ((char *)NULL); ! 5685: } ! 5686: ! 5687: /* Do key bindings from a file. If FILENAME is NULL it defaults ! 5688: to `~/.inputrc'. If the file existed and could be opened and ! 5689: read, 0 is returned, otherwise errno is returned. */ ! 5690: int ! 5691: rl_read_init_file (filename) ! 5692: char *filename; ! 5693: { ! 5694: register int i; ! 5695: char *buffer, *openname, *line, *end; ! 5696: struct stat finfo; ! 5697: int file; ! 5698: ! 5699: /* Default the filename. */ ! 5700: if (!filename) ! 5701: filename = last_readline_init_file; ! 5702: ! 5703: openname = tilde_expand (filename); ! 5704: ! 5705: if (!openname || *openname == '\000') ! 5706: return ENOENT; ! 5707: ! 5708: if ((stat (openname, &finfo) < 0) || ! 5709: (file = open (openname, O_RDONLY, 0666)) < 0) ! 5710: { ! 5711: free (openname); ! 5712: return (errno); ! 5713: } ! 5714: else ! 5715: free (openname); ! 5716: ! 5717: last_readline_init_file = filename; ! 5718: ! 5719: /* Read the file into BUFFER. */ ! 5720: buffer = (char *)xmalloc (finfo.st_size + 1); ! 5721: i = read (file, buffer, finfo.st_size); ! 5722: close (file); ! 5723: ! 5724: if (i != finfo.st_size) ! 5725: return (errno); ! 5726: ! 5727: /* Loop over the lines in the file. Lines that start with `#' are ! 5728: comments; all other lines are commands for readline initialization. */ ! 5729: line = buffer; ! 5730: end = buffer + finfo.st_size; ! 5731: while (line < end) ! 5732: { ! 5733: /* Find the end of this line. */ ! 5734: for (i = 0; line + i != end && line[i] != '\n'; i++); ! 5735: ! 5736: /* Mark end of line. */ ! 5737: line[i] = '\0'; ! 5738: ! 5739: /* If the line is not a comment, then parse it. */ ! 5740: if (*line != '#') ! 5741: rl_parse_and_bind (line); ! 5742: ! 5743: /* Move to the next line. */ ! 5744: line += i + 1; ! 5745: } ! 5746: return (0); ! 5747: } ! 5748: ! 5749: /* **************************************************************** */ ! 5750: /* */ ! 5751: /* Parser Directives */ ! 5752: /* */ ! 5753: /* **************************************************************** */ ! 5754: ! 5755: /* Conditionals. */ ! 5756: ! 5757: /* Calling programs set this to have their argv[0]. */ ! 5758: char *rl_readline_name = "other"; ! 5759: ! 5760: /* Stack of previous values of parsing_conditionalized_out. */ ! 5761: static unsigned char *if_stack = (unsigned char *)NULL; ! 5762: static int if_stack_depth = 0; ! 5763: static int if_stack_size = 0; ! 5764: ! 5765: /* Push parsing_conditionalized_out, and set parser state based on ARGS. */ ! 5766: parser_if (args) ! 5767: char *args; ! 5768: { ! 5769: register int i; ! 5770: ! 5771: /* Push parser state. */ ! 5772: if (if_stack_depth + 1 >= if_stack_size) ! 5773: { ! 5774: if (!if_stack) ! 5775: if_stack = (unsigned char *)xmalloc (if_stack_size = 20); ! 5776: else ! 5777: if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20); ! 5778: } ! 5779: if_stack[if_stack_depth++] = parsing_conditionalized_out; ! 5780: ! 5781: /* If parsing is turned off, then nothing can turn it back on except ! 5782: for finding the matching endif. In that case, return right now. */ ! 5783: if (parsing_conditionalized_out) ! 5784: return; ! 5785: ! 5786: /* Isolate first argument. */ ! 5787: for (i = 0; args[i] && !whitespace (args[i]); i++); ! 5788: ! 5789: if (args[i]) ! 5790: args[i++] = '\0'; ! 5791: ! 5792: /* Handle "if term=foo" and "if mode=emacs" constructs. If this ! 5793: isn't term=foo, or mode=emacs, then check to see if the first ! 5794: word in ARGS is the same as the value stored in rl_readline_name. */ ! 5795: if (rl_terminal_name && strnicmp (args, "term=", 5) == 0) ! 5796: { ! 5797: char *tem, *tname; ! 5798: ! 5799: /* Terminals like "aaa-60" are equivalent to "aaa". */ ! 5800: tname = savestring (rl_terminal_name); ! 5801: tem = rindex (tname, '-'); ! 5802: if (tem) ! 5803: *tem = '\0'; ! 5804: ! 5805: if (stricmp (args + 5, tname) == 0) ! 5806: parsing_conditionalized_out = 0; ! 5807: else ! 5808: parsing_conditionalized_out = 1; ! 5809: } ! 5810: #if defined (VI_MODE) ! 5811: else if (strnicmp (args, "mode=", 5) == 0) ! 5812: { ! 5813: int mode; ! 5814: ! 5815: if (stricmp (args + 5, "emacs") == 0) ! 5816: mode = emacs_mode; ! 5817: else if (stricmp (args + 5, "vi") == 0) ! 5818: mode = vi_mode; ! 5819: else ! 5820: mode = no_mode; ! 5821: ! 5822: if (mode == rl_editing_mode) ! 5823: parsing_conditionalized_out = 0; ! 5824: else ! 5825: parsing_conditionalized_out = 1; ! 5826: } ! 5827: #endif /* VI_MODE */ ! 5828: /* Check to see if the first word in ARGS is the same as the ! 5829: value stored in rl_readline_name. */ ! 5830: else if (stricmp (args, rl_readline_name) == 0) ! 5831: parsing_conditionalized_out = 0; ! 5832: else ! 5833: parsing_conditionalized_out = 1; ! 5834: } ! 5835: ! 5836: /* Invert the current parser state if there is anything on the stack. */ ! 5837: parser_else (args) ! 5838: char *args; ! 5839: { ! 5840: register int i; ! 5841: ! 5842: if (!if_stack_depth) ! 5843: { ! 5844: /* Error message? */ ! 5845: return; ! 5846: } ! 5847: ! 5848: /* Check the previous (n - 1) levels of the stack to make sure that ! 5849: we haven't previously turned off parsing. */ ! 5850: for (i = 0; i < if_stack_depth - 1; i++) ! 5851: if (if_stack[i] == 1) ! 5852: return; ! 5853: ! 5854: /* Invert the state of parsing if at top level. */ ! 5855: parsing_conditionalized_out = !parsing_conditionalized_out; ! 5856: } ! 5857: ! 5858: /* Terminate a conditional, popping the value of ! 5859: parsing_conditionalized_out from the stack. */ ! 5860: parser_endif (args) ! 5861: char *args; ! 5862: { ! 5863: if (if_stack_depth) ! 5864: parsing_conditionalized_out = if_stack[--if_stack_depth]; ! 5865: else ! 5866: { ! 5867: /* *** What, no error message? *** */ ! 5868: } ! 5869: } ! 5870: ! 5871: /* Associate textual names with actual functions. */ ! 5872: static struct { ! 5873: char *name; ! 5874: Function *function; ! 5875: } parser_directives [] = { ! 5876: { "if", parser_if }, ! 5877: { "endif", parser_endif }, ! 5878: { "else", parser_else }, ! 5879: { (char *)0x0, (Function *)0x0 } ! 5880: }; ! 5881: ! 5882: /* Handle a parser directive. STATEMENT is the line of the directive ! 5883: without any leading `$'. */ ! 5884: static int ! 5885: handle_parser_directive (statement) ! 5886: char *statement; ! 5887: { ! 5888: register int i; ! 5889: char *directive, *args; ! 5890: ! 5891: /* Isolate the actual directive. */ ! 5892: ! 5893: /* Skip whitespace. */ ! 5894: for (i = 0; whitespace (statement[i]); i++); ! 5895: ! 5896: directive = &statement[i]; ! 5897: ! 5898: for (; statement[i] && !whitespace (statement[i]); i++); ! 5899: ! 5900: if (statement[i]) ! 5901: statement[i++] = '\0'; ! 5902: ! 5903: for (; statement[i] && whitespace (statement[i]); i++); ! 5904: ! 5905: args = &statement[i]; ! 5906: ! 5907: /* Lookup the command, and act on it. */ ! 5908: for (i = 0; parser_directives[i].name; i++) ! 5909: if (stricmp (directive, parser_directives[i].name) == 0) ! 5910: { ! 5911: (*parser_directives[i].function) (args); ! 5912: return (0); ! 5913: } ! 5914: ! 5915: /* *** Should an error message be output? */ ! 5916: return (1); ! 5917: } ! 5918: ! 5919: /* Ugly but working hack for binding prefix meta. */ ! 5920: #define PREFIX_META_HACK ! 5921: ! 5922: static int substring_member_of_array (); ! 5923: ! 5924: /* Read the binding command from STRING and perform it. ! 5925: A key binding command looks like: Keyname: function-name\0, ! 5926: a variable binding command looks like: set variable value. ! 5927: A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */ ! 5928: rl_parse_and_bind (string) ! 5929: char *string; ! 5930: { ! 5931: extern char *possible_control_prefixes[], *possible_meta_prefixes[]; ! 5932: char *funname, *kname; ! 5933: register int c; ! 5934: int key, i; ! 5935: ! 5936: while (string && whitespace (*string)) ! 5937: string++; ! 5938: ! 5939: if (!string || !*string || *string == '#') ! 5940: return; ! 5941: ! 5942: /* If this is a parser directive, act on it. */ ! 5943: if (*string == '$') ! 5944: { ! 5945: handle_parser_directive (&string[1]); ! 5946: return; ! 5947: } ! 5948: ! 5949: /* If we are supposed to be skipping parsing right now, then do it. */ ! 5950: if (parsing_conditionalized_out) ! 5951: return; ! 5952: ! 5953: i = 0; ! 5954: /* If this keyname is a complex key expression surrounded by quotes, ! 5955: advance to after the matching close quote. */ ! 5956: if (*string == '"') ! 5957: { ! 5958: for (i = 1; c = string[i]; i++) ! 5959: { ! 5960: if (c == '"' && string[i - 1] != '\\') ! 5961: break; ! 5962: } ! 5963: } ! 5964: ! 5965: /* Advance to the colon (:) or whitespace which separates the two objects. */ ! 5966: for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ ); ! 5967: ! 5968: /* Mark the end of the command (or keyname). */ ! 5969: if (string[i]) ! 5970: string[i++] = '\0'; ! 5971: ! 5972: /* If this is a command to set a variable, then do that. */ ! 5973: if (stricmp (string, "set") == 0) ! 5974: { ! 5975: char *var = string + i; ! 5976: char *value; ! 5977: ! 5978: /* Make VAR point to start of variable name. */ ! 5979: while (*var && whitespace (*var)) var++; ! 5980: ! 5981: /* Make value point to start of value string. */ ! 5982: value = var; ! 5983: while (*value && !whitespace (*value)) value++; ! 5984: if (*value) ! 5985: *value++ = '\0'; ! 5986: while (*value && whitespace (*value)) value++; ! 5987: ! 5988: rl_variable_bind (var, value); ! 5989: return; ! 5990: } ! 5991: ! 5992: /* Skip any whitespace between keyname and funname. */ ! 5993: for (; string[i] && whitespace (string[i]); i++); ! 5994: funname = &string[i]; ! 5995: ! 5996: /* Now isolate funname. ! 5997: For straight function names just look for whitespace, since ! 5998: that will signify the end of the string. But this could be a ! 5999: macro definition. In that case, the string is quoted, so skip ! 6000: to the matching delimiter. */ ! 6001: if (*funname == '\'' || *funname == '"') ! 6002: { ! 6003: int delimiter = string[i++]; ! 6004: ! 6005: for (; c = string[i]; i++) ! 6006: { ! 6007: if (c == delimiter && string[i - 1] != '\\') ! 6008: break; ! 6009: } ! 6010: if (c) ! 6011: i++; ! 6012: } ! 6013: ! 6014: /* Advance to the end of the string. */ ! 6015: for (; string[i] && !whitespace (string[i]); i++); ! 6016: ! 6017: /* No extra whitespace at the end of the string. */ ! 6018: string[i] = '\0'; ! 6019: ! 6020: /* If this is a new-style key-binding, then do the binding with ! 6021: rl_set_key (). Otherwise, let the older code deal with it. */ ! 6022: if (*string == '"') ! 6023: { ! 6024: char *seq = (char *)alloca (1 + strlen (string)); ! 6025: register int j, k = 0; ! 6026: ! 6027: for (j = 1; string[j]; j++) ! 6028: { ! 6029: if (string[j] == '"' && string[j - 1] != '\\') ! 6030: break; ! 6031: ! 6032: seq[k++] = string[j]; ! 6033: } ! 6034: seq[k] = '\0'; ! 6035: ! 6036: /* Binding macro? */ ! 6037: if (*funname == '\'' || *funname == '"') ! 6038: { ! 6039: j = strlen (funname); ! 6040: ! 6041: if (j && funname[j - 1] == *funname) ! 6042: funname[j - 1] = '\0'; ! 6043: ! 6044: rl_macro_bind (seq, &funname[1], keymap); ! 6045: } ! 6046: else ! 6047: rl_set_key (seq, rl_named_function (funname), keymap); ! 6048: ! 6049: return; ! 6050: } ! 6051: ! 6052: /* Get the actual character we want to deal with. */ ! 6053: kname = rindex (string, '-'); ! 6054: if (!kname) ! 6055: kname = string; ! 6056: else ! 6057: kname++; ! 6058: ! 6059: key = glean_key_from_name (kname); ! 6060: ! 6061: /* Add in control and meta bits. */ ! 6062: if (substring_member_of_array (string, possible_control_prefixes)) ! 6063: key = CTRL (to_upper (key)); ! 6064: ! 6065: if (substring_member_of_array (string, possible_meta_prefixes)) ! 6066: key = META (key); ! 6067: ! 6068: /* Temporary. Handle old-style keyname with macro-binding. */ ! 6069: if (*funname == '\'' || *funname == '"') ! 6070: { ! 6071: char seq[2]; ! 6072: int fl = strlen (funname); ! 6073: ! 6074: seq[0] = key; seq[1] = '\0'; ! 6075: if (fl && funname[fl - 1] == *funname) ! 6076: funname[fl - 1] = '\0'; ! 6077: ! 6078: rl_macro_bind (seq, &funname[1], keymap); ! 6079: } ! 6080: #if defined (PREFIX_META_HACK) ! 6081: /* Ugly, but working hack to keep prefix-meta around. */ ! 6082: else if (stricmp (funname, "prefix-meta") == 0) ! 6083: { ! 6084: char seq[2]; ! 6085: ! 6086: seq[0] = key; ! 6087: seq[1] = '\0'; ! 6088: rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, keymap); ! 6089: } ! 6090: #endif /* PREFIX_META_HACK */ ! 6091: else ! 6092: rl_bind_key (key, rl_named_function (funname)); ! 6093: } ! 6094: ! 6095: rl_variable_bind (name, value) ! 6096: char *name, *value; ! 6097: { ! 6098: if (stricmp (name, "editing-mode") == 0) ! 6099: { ! 6100: if (strnicmp (value, "vi", 2) == 0) ! 6101: { ! 6102: #if defined (VI_MODE) ! 6103: keymap = vi_insertion_keymap; ! 6104: rl_editing_mode = vi_mode; ! 6105: #else ! 6106: #if defined (NOTDEF) ! 6107: /* What state is the terminal in? I'll tell you: ! 6108: non-determinate! That means we cannot do any output. */ ! 6109: ding (); ! 6110: #endif /* NOTDEF */ ! 6111: #endif /* VI_MODE */ ! 6112: } ! 6113: else if (strnicmp (value, "emacs", 5) == 0) ! 6114: { ! 6115: keymap = emacs_standard_keymap; ! 6116: rl_editing_mode = emacs_mode; ! 6117: } ! 6118: } ! 6119: else if (stricmp (name, "horizontal-scroll-mode") == 0) ! 6120: { ! 6121: if (!*value || stricmp (value, "On") == 0) ! 6122: horizontal_scroll_mode = 1; ! 6123: else ! 6124: horizontal_scroll_mode = 0; ! 6125: } ! 6126: else if (stricmp (name, "mark-modified-lines") == 0) ! 6127: { ! 6128: if (!*value || stricmp (value, "On") == 0) ! 6129: mark_modified_lines = 1; ! 6130: else ! 6131: mark_modified_lines = 0; ! 6132: } ! 6133: else if (stricmp (name, "prefer-visible-bell") == 0) ! 6134: { ! 6135: if (!*value || stricmp (value, "On") == 0) ! 6136: prefer_visible_bell = 1; ! 6137: else ! 6138: prefer_visible_bell = 0; ! 6139: } ! 6140: else if (stricmp (name, "comment-begin") == 0) ! 6141: { ! 6142: #if defined (VI_MODE) ! 6143: extern char *rl_vi_comment_begin; ! 6144: ! 6145: if (*value) ! 6146: { ! 6147: if (rl_vi_comment_begin) ! 6148: free (rl_vi_comment_begin); ! 6149: ! 6150: rl_vi_comment_begin = savestring (value); ! 6151: } ! 6152: #endif /* VI_MODE */ ! 6153: } ! 6154: } ! 6155: ! 6156: /* Return the character which matches NAME. ! 6157: For example, `Space' returns ' '. */ ! 6158: ! 6159: typedef struct { ! 6160: char *name; ! 6161: int value; ! 6162: } assoc_list; ! 6163: ! 6164: assoc_list name_key_alist[] = { ! 6165: { "DEL", 0x7f }, ! 6166: { "ESC", '\033' }, ! 6167: { "Escape", '\033' }, ! 6168: { "LFD", '\n' }, ! 6169: { "Newline", '\n' }, ! 6170: { "RET", '\r' }, ! 6171: { "Return", '\r' }, ! 6172: { "Rubout", 0x7f }, ! 6173: { "SPC", ' ' }, ! 6174: { "Space", ' ' }, ! 6175: { "Tab", 0x09 }, ! 6176: { (char *)0x0, 0 } ! 6177: }; ! 6178: ! 6179: int ! 6180: glean_key_from_name (name) ! 6181: char *name; ! 6182: { ! 6183: register int i; ! 6184: ! 6185: for (i = 0; name_key_alist[i].name; i++) ! 6186: if (stricmp (name, name_key_alist[i].name) == 0) ! 6187: return (name_key_alist[i].value); ! 6188: ! 6189: return (*name); ! 6190: } ! 6191: ! 6192: ! 6193: /* **************************************************************** */ ! 6194: /* */ ! 6195: /* Key Binding and Function Information */ ! 6196: /* */ ! 6197: /* **************************************************************** */ ! 6198: ! 6199: /* Each of the following functions produces information about the ! 6200: state of keybindings and functions known to Readline. The info ! 6201: is always printed to rl_outstream, and in such a way that it can ! 6202: be read back in (i.e., passed to rl_parse_and_bind (). */ ! 6203: ! 6204: /* Print the names of functions known to Readline. */ ! 6205: void ! 6206: rl_list_funmap_names (ignore) ! 6207: int ignore; ! 6208: { ! 6209: register int i; ! 6210: char **funmap_names; ! 6211: extern char **rl_funmap_names (); ! 6212: ! 6213: funmap_names = rl_funmap_names (); ! 6214: ! 6215: if (!funmap_names) ! 6216: return; ! 6217: ! 6218: for (i = 0; funmap_names[i]; i++) ! 6219: fprintf (rl_outstream, "%s\n", funmap_names[i]); ! 6220: ! 6221: free (funmap_names); ! 6222: } ! 6223: ! 6224: /* Return a NULL terminated array of strings which represent the key ! 6225: sequences that are used to invoke FUNCTION in MAP. */ ! 6226: static char ** ! 6227: invoking_keyseqs_in_map (function, map) ! 6228: Function *function; ! 6229: Keymap map; ! 6230: { ! 6231: register int key; ! 6232: char **result; ! 6233: int result_index, result_size; ! 6234: ! 6235: result = (char **)NULL; ! 6236: result_index = result_size = 0; ! 6237: ! 6238: for (key = 0; key < 128; key++) ! 6239: { ! 6240: switch (map[key].type) ! 6241: { ! 6242: case ISMACR: ! 6243: /* Macros match, if, and only if, the pointers are identical. ! 6244: Thus, they are treated exactly like functions in here. */ ! 6245: case ISFUNC: ! 6246: /* If the function in the keymap is the one we are looking for, ! 6247: then add the current KEY to the list of invoking keys. */ ! 6248: if (map[key].function == function) ! 6249: { ! 6250: char *keyname = (char *)xmalloc (5); ! 6251: ! 6252: if (CTRL_P (key)) ! 6253: sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key))); ! 6254: else if (key == RUBOUT) ! 6255: sprintf (keyname, "\\C-?"); ! 6256: else ! 6257: sprintf (keyname, "%c", key); ! 6258: ! 6259: if (result_index + 2 > result_size) ! 6260: { ! 6261: if (!result) ! 6262: result = (char **) xmalloc ! 6263: ((result_size = 10) * sizeof (char *)); ! 6264: else ! 6265: result = (char **) xrealloc ! 6266: (result, (result_size += 10) * sizeof (char *)); ! 6267: } ! 6268: ! 6269: result[result_index++] = keyname; ! 6270: result[result_index] = (char *)NULL; ! 6271: } ! 6272: break; ! 6273: ! 6274: case ISKMAP: ! 6275: { ! 6276: char **seqs = (char **)NULL; ! 6277: ! 6278: /* Find the list of keyseqs in this map which have FUNCTION as ! 6279: their target. Add the key sequences found to RESULT. */ ! 6280: if (map[key].function) ! 6281: seqs = ! 6282: invoking_keyseqs_in_map (function, (Keymap)map[key].function); ! 6283: ! 6284: if (seqs) ! 6285: { ! 6286: register int i; ! 6287: ! 6288: for (i = 0; seqs[i]; i++) ! 6289: { ! 6290: char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); ! 6291: ! 6292: if (key == ESC) ! 6293: sprintf (keyname, "\\e"); ! 6294: else if (CTRL_P (key)) ! 6295: sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key))); ! 6296: else if (key == RUBOUT) ! 6297: sprintf (keyname, "\\C-?"); ! 6298: else ! 6299: sprintf (keyname, "%c", key); ! 6300: ! 6301: strcat (keyname, seqs[i]); ! 6302: ! 6303: if (result_index + 2 > result_size) ! 6304: { ! 6305: if (!result) ! 6306: result = (char **) ! 6307: xmalloc ((result_size = 10) * sizeof (char *)); ! 6308: else ! 6309: result = (char **) ! 6310: xrealloc (result, ! 6311: (result_size += 10) * sizeof (char *)); ! 6312: } ! 6313: ! 6314: result[result_index++] = keyname; ! 6315: result[result_index] = (char *)NULL; ! 6316: } ! 6317: } ! 6318: } ! 6319: break; ! 6320: } ! 6321: } ! 6322: return (result); ! 6323: } ! 6324: ! 6325: /* Return a NULL terminated array of strings which represent the key ! 6326: sequences that can be used to invoke FUNCTION using the current keymap. */ ! 6327: char ** ! 6328: rl_invoking_keyseqs (function) ! 6329: Function *function; ! 6330: { ! 6331: return (invoking_keyseqs_in_map (function, keymap)); ! 6332: } ! 6333: ! 6334: /* Print all of the current functions and their bindings to ! 6335: rl_outstream. If an explicit argument is given, then print ! 6336: the output in such a way that it can be read back in. */ ! 6337: int ! 6338: rl_dump_functions (count) ! 6339: int count; ! 6340: { ! 6341: void rl_function_dumper (); ! 6342: ! 6343: rl_function_dumper (rl_explicit_arg); ! 6344: rl_on_new_line (); ! 6345: return (0); ! 6346: } ! 6347: ! 6348: /* Print all of the functions and their bindings to rl_outstream. If ! 6349: PRINT_READABLY is non-zero, then print the output in such a way ! 6350: that it can be read back in. */ ! 6351: void ! 6352: rl_function_dumper (print_readably) ! 6353: int print_readably; ! 6354: { ! 6355: register int i; ! 6356: char **rl_funmap_names (), **names; ! 6357: char *name; ! 6358: ! 6359: names = rl_funmap_names (); ! 6360: ! 6361: fprintf (rl_outstream, "\n"); ! 6362: ! 6363: for (i = 0; name = names[i]; i++) ! 6364: { ! 6365: Function *function; ! 6366: char **invokers; ! 6367: ! 6368: function = rl_named_function (name); ! 6369: invokers = invoking_keyseqs_in_map (function, keymap); ! 6370: ! 6371: if (print_readably) ! 6372: { ! 6373: if (!invokers) ! 6374: fprintf (rl_outstream, "# %s (not bound)\n", name); ! 6375: else ! 6376: { ! 6377: register int j; ! 6378: ! 6379: for (j = 0; invokers[j]; j++) ! 6380: { ! 6381: fprintf (rl_outstream, "\"%s\": %s\n", ! 6382: invokers[j], name); ! 6383: free (invokers[j]); ! 6384: } ! 6385: ! 6386: free (invokers); ! 6387: } ! 6388: } ! 6389: else ! 6390: { ! 6391: if (!invokers) ! 6392: fprintf (rl_outstream, "%s is not bound to any keys\n", ! 6393: name); ! 6394: else ! 6395: { ! 6396: register int j; ! 6397: ! 6398: fprintf (rl_outstream, "%s can be found on ", name); ! 6399: ! 6400: for (j = 0; invokers[j] && j < 5; j++) ! 6401: { ! 6402: fprintf (rl_outstream, "\"%s\"%s", invokers[j], ! 6403: invokers[j + 1] ? ", " : ".\n"); ! 6404: } ! 6405: ! 6406: if (j == 5 && invokers[j]) ! 6407: fprintf (rl_outstream, "...\n"); ! 6408: ! 6409: for (j = 0; invokers[j]; j++) ! 6410: free (invokers[j]); ! 6411: ! 6412: free (invokers); ! 6413: } ! 6414: } ! 6415: } ! 6416: } ! 6417: ! 6418: ! 6419: /* **************************************************************** */ ! 6420: /* */ ! 6421: /* String Utility Functions */ ! 6422: /* */ ! 6423: /* **************************************************************** */ ! 6424: ! 6425: static char *strindex (); ! 6426: ! 6427: /* Return pointer to first occurance in STRING1 of any character from STRING2, ! 6428: or NULL if no occurance found. */ ! 6429: static char * ! 6430: strpbrk (string1, string2) ! 6431: char *string1, *string2; ! 6432: { ! 6433: register char *scan; ! 6434: ! 6435: for (; *string1 != '\0'; string1++) ! 6436: { ! 6437: for (scan = string2; *scan != '\0'; scan++) ! 6438: { ! 6439: if (*string1 == *scan) ! 6440: { ! 6441: return (string1); ! 6442: } ! 6443: } ! 6444: } ! 6445: return (NULL); ! 6446: } ! 6447: ! 6448: /* Return non-zero if any members of ARRAY are a substring in STRING. */ ! 6449: static int ! 6450: substring_member_of_array (string, array) ! 6451: char *string, **array; ! 6452: { ! 6453: while (*array) ! 6454: { ! 6455: if (strindex (string, *array)) ! 6456: return (1); ! 6457: array++; ! 6458: } ! 6459: return (0); ! 6460: } ! 6461: ! 6462: /* Whoops, Unix doesn't have strnicmp. */ ! 6463: ! 6464: /* Compare at most COUNT characters from string1 to string2. Case ! 6465: doesn't matter. */ ! 6466: static int ! 6467: strnicmp (string1, string2, count) ! 6468: char *string1, *string2; ! 6469: { ! 6470: register char ch1, ch2; ! 6471: ! 6472: while (count) ! 6473: { ! 6474: ch1 = *string1++; ! 6475: ch2 = *string2++; ! 6476: if (to_upper(ch1) == to_upper(ch2)) ! 6477: count--; ! 6478: else break; ! 6479: } ! 6480: return (count); ! 6481: } ! 6482: ! 6483: /* strcmp (), but caseless. */ ! 6484: static int ! 6485: stricmp (string1, string2) ! 6486: char *string1, *string2; ! 6487: { ! 6488: register char ch1, ch2; ! 6489: ! 6490: while (*string1 && *string2) ! 6491: { ! 6492: ch1 = *string1++; ! 6493: ch2 = *string2++; ! 6494: if (to_upper(ch1) != to_upper(ch2)) ! 6495: return (1); ! 6496: } ! 6497: return (*string1 | *string2); ! 6498: } ! 6499: ! 6500: /* Determine if s2 occurs in s1. If so, return a pointer to the ! 6501: match in s1. The compare is case insensitive. */ ! 6502: static char * ! 6503: strindex (s1, s2) ! 6504: register char *s1, *s2; ! 6505: { ! 6506: register int i, l = strlen (s2); ! 6507: register int len = strlen (s1); ! 6508: ! 6509: for (i = 0; (len - i) >= l; i++) ! 6510: if (strnicmp (&s1[i], s2, l) == 0) ! 6511: return (s1 + i); ! 6512: return ((char *)NULL); ! 6513: } ! 6514: ! 6515: ! 6516: /* **************************************************************** */ ! 6517: /* */ ! 6518: /* USG (System V) Support */ ! 6519: /* */ ! 6520: /* **************************************************************** */ ! 6521: ! 6522: /* When compiling and running in the `Posix' environment, Ultrix does ! 6523: not restart system calls, so this needs to do it. */ ! 6524: int ! 6525: rl_getc (stream) ! 6526: FILE *stream; ! 6527: { ! 6528: int result; ! 6529: unsigned char c; ! 6530: ! 6531: #ifdef __GO32__ ! 6532: if (isatty(0)) ! 6533: return getkey(); ! 6534: #endif /* __GO32__ */ ! 6535: ! 6536: while (1) ! 6537: { ! 6538: result = read (fileno (stream), &c, sizeof (char)); ! 6539: ! 6540: if (result == sizeof (char)) ! 6541: return (c); ! 6542: ! 6543: /* If zero characters are returned, then the file that we are ! 6544: reading from is empty! Return EOF in that case. */ ! 6545: if (result == 0) ! 6546: return (EOF); ! 6547: ! 6548: #ifndef __GO32__ ! 6549: /* If the error that we received was SIGINT, then try again, ! 6550: this is simply an interrupted system call to read (). ! 6551: Otherwise, some error ocurred, also signifying EOF. */ ! 6552: if (errno != EINTR) ! 6553: return (EOF); ! 6554: #endif /* !__GO32__ */ ! 6555: } ! 6556: } ! 6557: ! 6558: #if defined (STATIC_MALLOC) ! 6559: ! 6560: /* **************************************************************** */ ! 6561: /* */ ! 6562: /* xmalloc and xrealloc () */ ! 6563: /* */ ! 6564: /* **************************************************************** */ ! 6565: ! 6566: static void memory_error_and_abort (); ! 6567: ! 6568: static char * ! 6569: xmalloc (bytes) ! 6570: int bytes; ! 6571: { ! 6572: char *temp = (char *)malloc (bytes); ! 6573: ! 6574: if (!temp) ! 6575: memory_error_and_abort (); ! 6576: return (temp); ! 6577: } ! 6578: ! 6579: static char * ! 6580: xrealloc (pointer, bytes) ! 6581: char *pointer; ! 6582: int bytes; ! 6583: { ! 6584: char *temp; ! 6585: ! 6586: if (!pointer) ! 6587: temp = (char *)malloc (bytes); ! 6588: else ! 6589: temp = (char *)realloc (pointer, bytes); ! 6590: ! 6591: if (!temp) ! 6592: memory_error_and_abort (); ! 6593: ! 6594: return (temp); ! 6595: } ! 6596: ! 6597: static void ! 6598: memory_error_and_abort () ! 6599: { ! 6600: fprintf (stderr, "readline: Out of virtual memory!\n"); ! 6601: abort (); ! 6602: } ! 6603: #endif /* STATIC_MALLOC */ ! 6604: ! 6605: ! 6606: /* **************************************************************** */ ! 6607: /* */ ! 6608: /* Testing Readline */ ! 6609: /* */ ! 6610: /* **************************************************************** */ ! 6611: ! 6612: #if defined (TEST) ! 6613: ! 6614: main () ! 6615: { ! 6616: HIST_ENTRY **history_list (); ! 6617: char *temp = (char *)NULL; ! 6618: char *prompt = "readline% "; ! 6619: int done = 0; ! 6620: ! 6621: while (!done) ! 6622: { ! 6623: temp = readline (prompt); ! 6624: ! 6625: /* Test for EOF. */ ! 6626: if (!temp) ! 6627: exit (1); ! 6628: ! 6629: /* If there is anything on the line, print it and remember it. */ ! 6630: if (*temp) ! 6631: { ! 6632: fprintf (stderr, "%s\r\n", temp); ! 6633: add_history (temp); ! 6634: } ! 6635: ! 6636: /* Check for `command' that we handle. */ ! 6637: if (strcmp (temp, "quit") == 0) ! 6638: done = 1; ! 6639: ! 6640: if (strcmp (temp, "list") == 0) ! 6641: { ! 6642: HIST_ENTRY **list = history_list (); ! 6643: register int i; ! 6644: if (list) ! 6645: { ! 6646: for (i = 0; list[i]; i++) ! 6647: { ! 6648: fprintf (stderr, "%d: %s\r\n", i, list[i]->line); ! 6649: free (list[i]->line); ! 6650: } ! 6651: free (list); ! 6652: } ! 6653: } ! 6654: free (temp); ! 6655: } ! 6656: } ! 6657: ! 6658: #endif /* TEST */ ! 6659: ! 6660: ! 6661: /* ! 6662: * Local variables: ! 6663: * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap" ! 6664: * end: ! 6665: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.