Annotation of GNUtools/debug/gdb/readline/readline.c, revision 1.1

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, &lt) != -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, &macro_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:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.