/src/mswin/rdln/readline.c
C | 6803 lines | 4776 code | 973 blank | 1054 comment | 896 complexity | 8f48c6c0d52777e3efdce5f1bec6d038 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
- /* Copyright 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
- The Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- The Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* Remove these declarations when we have a complete libgnu.a. */
- #if defined(__MSC_VER)
- #include <../../nrnconf.h>
- #endif
- #ifdef WIN32
- #define STATIC_MALLOC
- #define rindex strrchr
- #endif
- /* #define STATIC_MALLOC */
- #if defined(_MSC_VER) || defined(__MWERKS__)
- #include <unistd.h>
- #include <malloc.h>
- #include <string.h>
- #endif
- /* Caseless strcmp (). */
- #if defined(__MWERKS__)
- static int stricmp (), strnicmp ();
- #endif
- #if !defined (STATIC_MALLOC)
- extern char *xmalloc (), *xrealloc ();
- #else
- static char *xmalloc (), *xrealloc ();
- #endif /* STATIC_MALLOC */
- #include "sysdep.h"
- #include <stdio.h>
- #include <fcntl.h>
- #ifdef WIN32
- #define NO_SYS_FILE
- #endif
- #ifndef NO_SYS_FILE
- #include <sys/file.h>
- #endif
- #include <signal.h>
- #if defined (HAVE_UNISTD_H)
- # include <unistd.h>
- #endif
- #ifndef WIN32
- #define NEW_TTY_DRIVER
- #endif
- #define HAVE_BSD_SIGNALS
- /* #define USE_XON_XOFF */
- #if __GO32__
- #define GRX 1
- #endif
- #if GRX
- extern int egagrph;
- #endif
- #ifdef __MSDOS__
- #undef NEW_TTY_DRIVER
- #undef HAVE_BSD_SIGNALS
- #endif
- /* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
- #if defined (USG) && !defined (hpux)
- #undef HAVE_BSD_SIGNALS
- #endif
- /* System V machines use termio. */
- #if !defined (_POSIX_VERSION)
- # if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (__H3050R) || defined (__H3050RX)
- # undef NEW_TTY_DRIVER
- # define TERMIO_TTY_DRIVER
- # include <termio.h>
- # if !defined (TCOON)
- # define TCOON 1
- # endif
- # endif /* USG || hpux || Xenix || sgi || DUGX */
- #endif /* !_POSIX_VERSION */
- /* Posix systems use termios and the Posix signal functions. */
- #if defined (_POSIX_VERSION)
- # if !defined (TERMIOS_MISSING)
- # undef NEW_TTY_DRIVER
- # define TERMIOS_TTY_DRIVER
- # include <termios.h>
- # endif /* !TERMIOS_MISSING */
- # define HAVE_POSIX_SIGNALS
- # if !defined (O_NDELAY)
- # define O_NDELAY O_NONBLOCK /* Posix-style non-blocking i/o */
- # endif /* O_NDELAY */
- #endif /* _POSIX_VERSION */
- /* Other (BSD) machines use sgtty. */
- #if defined (NEW_TTY_DRIVER)
- #include <sgtty.h>
- #endif
- /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
- it is not already defined. It is used both to determine if a
- special character is disabled and to disable certain special
- characters. Posix systems should set to 0, USG systems to -1. */
- #if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
- # if defined (_POSIX_VERSION)
- # define _POSIX_VDISABLE 0
- # else /* !_POSIX_VERSION */
- # define _POSIX_VDISABLE -1
- # endif /* !_POSIX_VERSION */
- #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
- /* Define some macros for dealing with assorted signalling disciplines.
- These macros provide a way to use signal blocking and disabling
- without smothering your code in a pile of #ifdef's.
- SIGNALS_UNBLOCK; Stop blocking all signals.
- {
- SIGNALS_DECLARE_SAVED (name); Declare a variable to save the
- signal blocking state.
- ...
- SIGNALS_BLOCK (SIGSTOP, name); Block a signal, and save the previous
- state for restoration later.
- ...
- SIGNALS_RESTORE (name); Restore previous signals.
- }
- */
- #ifdef HAVE_POSIX_SIGNALS
- /* POSIX signals */
- #define SIGNALS_UNBLOCK \
- do { sigset_t set; \
- sigemptyset (&set); \
- sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); \
- } while (0)
- #define SIGNALS_DECLARE_SAVED(name) sigset_t name
- #define SIGNALS_BLOCK(SIG, saved) \
- do { sigset_t set; \
- sigemptyset (&set); \
- sigaddset (&set, SIG); \
- sigprocmask (SIG_BLOCK, &set, &saved); \
- } while (0)
- #define SIGNALS_RESTORE(saved) \
- sigprocmask (SIG_SETMASK, &saved, (sigset_t *)NULL)
- #else /* HAVE_POSIX_SIGNALS */
- #ifdef HAVE_BSD_SIGNALS
- /* BSD signals */
- #define SIGNALS_UNBLOCK sigsetmask (0)
- #define SIGNALS_DECLARE_SAVED(name) int name
- #define SIGNALS_BLOCK(SIG, saved) saved = sigblock (sigmask (SIG))
- #define SIGNALS_RESTORE(saved) sigsetmask (saved)
- #else /* HAVE_BSD_SIGNALS */
- /* None of the Above */
- #define SIGNALS_UNBLOCK /* nothing */
- #define SIGNALS_DECLARE_SAVED(name) /* nothing */
- #define SIGNALS_BLOCK(SIG, saved) /* nothing */
- #define SIGNALS_RESTORE(saved) /* nothing */
- #endif /* HAVE_BSD_SIGNALS */
- #endif /* HAVE_POSIX_SIGNALS */
- /* End of signal handling definitions. */
- #include <errno.h>
- #include <setjmp.h>
- #include <sys/stat.h>
- /* Posix macro to check file in statbuf for directory-ness. */
- #if defined (S_IFDIR) && !defined (S_ISDIR)
- #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
- #endif
- #if !defined(__MSDOS__) && !defined(WIN32)
- /* These next are for filename completion. Perhaps this belongs
- in a different place. */
- #include <pwd.h>
- #endif /* __MSDOS__ */
- #if defined (USG) && !defined (isc386) && !defined (sgi)
- struct passwd *getpwuid (), *getpwent ();
- #endif
- /* #define HACK_TERMCAP_MOTION */
- /* Some standard library routines. */
- #include "readline.h"
- #include "history.h"
- #ifndef digit
- #define digit(c) ((c) >= '0' && (c) <= '9')
- #endif
- #ifndef isletter
- #define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
- #endif
- #ifndef digit_value
- #define digit_value(c) ((c) - '0')
- #endif
- #ifndef member
- #define member(c, s) ((c) ? index ((s), (c)) : 0)
- #endif
- #ifndef isident
- #define isident(c) ((isletter(c) || digit(c) || c == '_'))
- #endif
- #ifndef exchange
- #define exchange(x, y) {int temp = x; x = y; y = temp;}
- #endif
- #if !defined (rindex)
- extern char *rindex ();
- #endif /* rindex */
- #if !defined (index)
- extern char *index ();
- #endif /* index */
- extern char *getenv ();
- extern char *tilde_expand ();
- char* tilde_expand() { return savestring("/");}
- static update_line ();
- static void output_character_function ();
- static delete_chars ();
- static void insert_some_chars ();
- #if defined (VOID_SIGHANDLER)
- # define sighandler void
- #else
- # define sighandler int
- #endif /* VOID_SIGHANDLER */
- /* This typedef is equivalant to the one for Function; it allows us
- to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
- typedef sighandler SigHandler ();
- /* If on, then readline handles signals in a way that doesn't screw. */
- #ifndef WIN32
- #define HANDLE_SIGNALS
- #endif
- #if defined(__GO32__)
- #ifdef RSX
- #include <termio.h>
- #else
- #include <pc.h>
- #endif
- #undef HANDLE_SIGNALS
- #endif
- /* **************************************************************** */
- /* */
- /* Line editing input utility */
- /* */
- /* **************************************************************** */
- /* A pointer to the keymap that is currently in use.
- By default, it is the standard emacs keymap. */
- Keymap keymap = emacs_standard_keymap;
- #define no_mode -1
- #define vi_mode 0
- #define emacs_mode 1
- /* The current style of editing. */
- int rl_editing_mode = emacs_mode;
- /* Non-zero if the previous command was a kill command. */
- static int last_command_was_kill = 0;
- /* The current value of the numeric argument specified by the user. */
- int rl_numeric_arg = 1;
- /* Non-zero if an argument was typed. */
- int rl_explicit_arg = 0;
- /* Temporary value used while generating the argument. */
- int rl_arg_sign = 1;
- /* Non-zero means we have been called at least once before. */
- static int rl_initialized = 0;
- /* If non-zero, this program is running in an EMACS buffer. */
- static char *running_in_emacs = (char *)NULL;
- /* The current offset in the current input line. */
- int rl_point;
- /* Mark in the current input line. */
- int rl_mark;
- /* Length of the current input line. */
- int rl_end;
- /* Make this non-zero to return the current input_line. */
- int rl_done;
- /* The last function executed by readline. */
- Function *rl_last_func = (Function *)NULL;
- /* Top level environment for readline_internal (). */
- static jmp_buf readline_top_level;
- /* The streams we interact with. */
- static FILE *in_stream, *out_stream;
- /* The names of the streams that we do input and output to. */
- FILE *rl_instream, *rl_outstream;
- /* Non-zero means echo characters as they are read. */
- int readline_echoing_p = 1;
- /* Current prompt. */
- char *rl_prompt;
- /* The number of characters read in order to type this complete command. */
- int rl_key_sequence_length = 0;
- /* If non-zero, then this is the address of a function to call just
- before readline_internal () prints the first prompt. */
- Function *rl_startup_hook = (Function *)NULL;
- /* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
- Function *rl_symbolic_link_hook = (Function *)NULL;
- /* What we use internally. You should always refer to RL_LINE_BUFFER. */
- static char *the_line;
- /* The character that can generate an EOF. Really read from
- the terminal driver... just defaulted here. */
- static int eof_char = CTRL ('D');
- /* Non-zero makes this the next keystroke to read. */
- int rl_pending_input = 0;
- /* Pointer to a useful terminal name. */
- char *rl_terminal_name = (char *)NULL;
- /* Line buffer and maintenence. */
- char *rl_line_buffer = (char *)NULL;
- int rl_line_buffer_len = 0;
- #define DEFAULT_BUFFER_SIZE 256
- /* **************************************************************** */
- /* */
- /* `Forward' declarations */
- /* */
- /* **************************************************************** */
- /* Non-zero means do not parse any lines other than comments and
- parser directives. */
- static unsigned char parsing_conditionalized_out = 0;
- /* Non-zero means to save keys that we dispatch on in a kbd macro. */
- static int defining_kbd_macro = 0;
- /* **************************************************************** */
- /* */
- /* Top Level Functions */
- /* */
- /* **************************************************************** */
- static void rl_prep_terminal (), rl_deprep_terminal ();
- static void clear_to_eol (), rl_generic_bind ();
- /* Read a line of input. Prompt with PROMPT. A NULL PROMPT means
- none. A return value of NULL means that EOF was encountered. */
- char *
- readline (prompt)
- char *prompt;
- {
- char *readline_internal ();
- char *value;
- rl_prompt = prompt;
- /* If we are at EOF return a NULL string. */
- if (rl_pending_input == EOF)
- {
- rl_pending_input = 0;
- return ((char *)NULL);
- }
- rl_initialize ();
- rl_prep_terminal ();
- #if defined (HANDLE_SIGNALS)
- rl_set_signals ();
- #endif
- value = readline_internal ();
- rl_deprep_terminal ();
- #if defined (HANDLE_SIGNALS)
- rl_clear_signals ();
- #endif
- return (value);
- }
- /* Read a line of input from the global rl_instream, doing output on
- the global rl_outstream.
- If rl_prompt is non-null, then that is our prompt. */
- char *
- readline_internal ()
- {
- int lastc, c, eof_found;
- in_stream = rl_instream;
- out_stream = rl_outstream;
- lastc = -1;
- eof_found = 0;
- if (rl_startup_hook)
- (*rl_startup_hook) ();
- if (!readline_echoing_p)
- {
- if (rl_prompt)
- {
- fprintf (out_stream, "%s", rl_prompt);
- fflush (out_stream);
- }
- }
- else
- {
- rl_on_new_line ();
- rl_redisplay ();
- #if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode ();
- #endif /* VI_MODE */
- }
- while (!rl_done)
- {
- int lk = last_command_was_kill;
- int code = setjmp (readline_top_level);
- if (code)
- rl_redisplay ();
- if (!rl_pending_input)
- {
- /* Then initialize the argument and number of keys read. */
- rl_init_argument ();
- rl_key_sequence_length = 0;
- }
- c = rl_read_key ();
- #ifdef WIN32
- if (!winio_exists()) {
- eof_found = 1;
- break;
- }
- #endif
- /* EOF typed to a non-blank line is a <NL>. */
- if (c == EOF && rl_end)
- c = NEWLINE;
- /* The character eof_char typed to blank line, and not as the
- previous character is interpreted as EOF. */
- if (((c == eof_char && lastc != c) || c == EOF) && !rl_end)
- {
- eof_found = 1;
- break;
- }
- lastc = c;
- rl_dispatch (c, keymap);
- /* If there was no change in last_command_was_kill, then no kill
- has taken place. Note that if input is pending we are reading
- a prefix command, so nothing has changed yet. */
- if (!rl_pending_input)
- {
- if (lk == last_command_was_kill)
- last_command_was_kill = 0;
- }
- #if defined (VI_MODE)
- /* In vi mode, when you exit insert mode, the cursor moves back
- over the previous character. We explicitly check for that here. */
- if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
- rl_vi_check ();
- #endif /* VI_MODE */
- if (!rl_done)
- rl_redisplay ();
- }
- /* Restore the original of this history line, iff the line that we
- are editing was originally in the history, AND the line has changed. */
- {
- HIST_ENTRY *entry = current_history ();
- if (entry && rl_undo_list)
- {
- char *temp = savestring (the_line);
- rl_revert_line ();
- entry = replace_history_entry (where_history (), the_line,
- (HIST_ENTRY *)NULL);
- free_history_entry (entry);
- strcpy (the_line, temp);
- free (temp);
- }
- }
- /* At any rate, it is highly likely that this line has an undo list. Get
- rid of it now. */
- if (rl_undo_list)
- free_undo_list ();
- if (eof_found)
- return (char *)NULL;
- else
- return (savestring (the_line));
- }
- /* **************************************************************** */
- /* */
- /* Signal Handling */
- /* */
- /* **************************************************************** */
- #if defined (SIGWINCH)
- static SigHandler *old_sigwinch = (SigHandler *)NULL;
- static sighandler
- rl_handle_sigwinch (sig)
- int sig;
- {
- char *term;
- term = rl_terminal_name;
- if (readline_echoing_p)
- {
- if (!term)
- term = getenv ("TERM");
- if (!term)
- term = "dumb";
- rl_reset_terminal (term);
- #if defined (NOTDEF)
- crlf ();
- rl_forced_update_display ();
- #endif /* NOTDEF */
- }
- if (old_sigwinch &&
- old_sigwinch != (SigHandler *)SIG_IGN &&
- old_sigwinch != (SigHandler *)SIG_DFL)
- (*old_sigwinch) (sig);
- #if !defined (VOID_SIGHANDLER)
- return (0);
- #endif /* VOID_SIGHANDLER */
- }
- #endif /* SIGWINCH */
- #if defined (HANDLE_SIGNALS)
- /* Interrupt handling. */
- static SigHandler
- *old_int = (SigHandler *)NULL,
- *old_tstp = (SigHandler *)NULL,
- *old_ttou = (SigHandler *)NULL,
- *old_ttin = (SigHandler *)NULL,
- *old_cont = (SigHandler *)NULL,
- *old_alrm = (SigHandler *)NULL;
- /* Handle an interrupt character. */
- static sighandler
- rl_signal_handler (sig)
- int sig;
- {
- #if !defined (HAVE_BSD_SIGNALS)
- /* Since the signal will not be blocked while we are in the signal
- handler, ignore it until rl_clear_signals resets the catcher. */
- if (sig == SIGINT)
- signal (sig, SIG_IGN);
- #endif /* !HAVE_BSD_SIGNALS */
- switch (sig)
- {
- case SIGINT:
- free_undo_list ();
- rl_clear_message ();
- rl_init_argument ();
- #if defined (SIGTSTP)
- case SIGTSTP:
- case SIGTTOU:
- case SIGTTIN:
- #endif /* SIGTSTP */
- case SIGALRM:
- rl_clean_up_for_exit ();
- rl_deprep_terminal ();
- rl_clear_signals ();
- rl_pending_input = 0;
- kill (getpid (), sig);
- SIGNALS_UNBLOCK;
- rl_prep_terminal ();
- rl_set_signals ();
- }
- #if !defined (VOID_SIGHANDLER)
- return (0);
- #endif /* !VOID_SIGHANDLER */
- }
- rl_set_signals ()
- {
- old_int = (SigHandler *)signal (SIGINT, rl_signal_handler);
- if (old_int == (SigHandler *)SIG_IGN)
- signal (SIGINT, SIG_IGN);
- old_alrm = (SigHandler *)signal (SIGALRM, rl_signal_handler);
- if (old_alrm == (SigHandler *)SIG_IGN)
- signal (SIGALRM, SIG_IGN);
- #if defined (SIGTSTP)
- old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler);
- if (old_tstp == (SigHandler *)SIG_IGN)
- signal (SIGTSTP, SIG_IGN);
- #endif
- #if defined (SIGTTOU)
- old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler);
- old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler);
- if (old_tstp == (SigHandler *)SIG_IGN)
- {
- signal (SIGTTOU, SIG_IGN);
- signal (SIGTTIN, SIG_IGN);
- }
- #endif
- #if defined (SIGWINCH)
- old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch);
- #endif
- }
- rl_clear_signals ()
- {
- signal (SIGINT, old_int);
- signal (SIGALRM, old_alrm);
- #if defined (SIGTSTP)
- signal (SIGTSTP, old_tstp);
- #endif
- #if defined (SIGTTOU)
- signal (SIGTTOU, old_ttou);
- signal (SIGTTIN, old_ttin);
- #endif
- #if defined (SIGWINCH)
- signal (SIGWINCH, old_sigwinch);
- #endif
- }
- #endif /* HANDLE_SIGNALS */
- /* **************************************************************** */
- /* */
- /* Character Input Buffering */
- /* */
- /* **************************************************************** */
- #if defined (USE_XON_XOFF)
- /* If the terminal was in xoff state when we got to it, then xon_char
- contains the character that is supposed to start it again. */
- static int xon_char, xoff_state;
- #endif /* USE_XON_XOFF */
- static int pop_index = 0, push_index = 0, ibuffer_len = 511;
- static unsigned char ibuffer[512];
- /* Non-null means it is a pointer to a function to run while waiting for
- character input. */
- Function *rl_event_hook = (Function *)NULL;
- #define any_typein (push_index != pop_index)
- /* Add KEY to the buffer of characters to be read. */
- rl_stuff_char (key)
- int key;
- {
- if (key == EOF)
- {
- key = NEWLINE;
- rl_pending_input = EOF;
- }
- ibuffer[push_index++] = key;
- if (push_index >= ibuffer_len)
- push_index = 0;
- }
- /* Return the amount of space available in the
- buffer for stuffing characters. */
- int
- ibuffer_space ()
- {
- if (pop_index > push_index)
- return (pop_index - push_index);
- else
- return (ibuffer_len - (push_index - pop_index));
- }
- /* Get a key from the buffer of characters to be read.
- Return the key in KEY.
- Result is KEY if there was a key, or 0 if there wasn't. */
- int
- rl_get_char (key)
- int *key;
- {
- if (push_index == pop_index)
- return (0);
- *key = ibuffer[pop_index++];
- if (pop_index >= ibuffer_len)
- pop_index = 0;
- return (1);
- }
- /* Stuff KEY into the *front* of the input buffer.
- Returns non-zero if successful, zero if there is
- no space left in the buffer. */
- int
- rl_unget_char (key)
- int key;
- {
- if (ibuffer_space ())
- {
- pop_index--;
- if (pop_index < 0)
- pop_index = ibuffer_len - 1;
- ibuffer[pop_index] = key;
- return (1);
- }
- return (0);
- }
- /* If a character is available to be read, then read it
- and stuff it into IBUFFER. Otherwise, just return. */
- rl_gather_tyi ()
- {
- #ifdef WIN32
- while (kbhit() && ibuffer_space()) {
- rl_stuff_char(winio_getc());
- }
- #else
- #if defined(__GO32__)
- char input;
- if (isatty(0))
- {
- int i = rl_getc();
- if (i != EOF)
- rl_stuff_char(i);
- }
- else
- if (kbhit() && ibuffer_space())
- rl_stuff_char(getkey());
- #else
- int tty = fileno (in_stream);
- register int tem, result = -1;
- long chars_avail;
- char input;
- #if defined (FIONREAD)
- result = ioctl (tty, FIONREAD, &chars_avail);
- #endif
- if (result == -1)
- {
- int flags;
- flags = fcntl (tty, F_GETFL, 0);
- fcntl (tty, F_SETFL, (flags | O_NDELAY));
- chars_avail = read (tty, &input, 1);
- fcntl (tty, F_SETFL, flags);
- if (chars_avail == -1 && errno == EAGAIN)
- return;
- }
- /* If there's nothing available, don't waste time trying to read
- something. */
- if (chars_avail == 0)
- return;
- tem = ibuffer_space ();
- if (chars_avail > tem)
- chars_avail = tem;
- /* One cannot read all of the available input. I can only read a single
- character at a time, or else programs which require input can be
- thwarted. If the buffer is larger than one character, I lose.
- Damn! */
- if (tem < ibuffer_len)
- chars_avail = 0;
- if (result != -1)
- {
- while (chars_avail--)
- rl_stuff_char (rl_getc (in_stream));
- }
- else
- {
- if (chars_avail)
- rl_stuff_char (input);
- }
- #endif /* def __GO32__/else */
- #endif
- }
- static int next_macro_key ();
- /* Read a key, including pending input. */
- int
- rl_read_key ()
- {
- int c;
- rl_key_sequence_length++;
- if (rl_pending_input)
- {
- c = rl_pending_input;
- rl_pending_input = 0;
- }
- else
- {
- /* If input is coming from a macro, then use that. */
- if (c = next_macro_key ())
- return (c);
- /* If the user has an event function, then call it periodically. */
- if (rl_event_hook)
- {
- while (rl_event_hook && !rl_get_char (&c))
- {
- (*rl_event_hook) ();
- if (!winio_rdln_ok()) {
- printf("%s", rl_prompt);
- printf("%s", the_line);
- }
- rl_gather_tyi ();
- }
- }
- else
- {
- if (!rl_get_char (&c))
- c = rl_getc (in_stream);
- }
- }
- return (c);
- }
- /* I'm beginning to hate the declaration rules for various compilers. */
- static void add_macro_char (), with_macro_input ();
- /* Do the command associated with KEY in MAP.
- If the associated command is really a keymap, then read
- another key, and dispatch into that map. */
- rl_dispatch (key, map)
- register int key;
- Keymap map;
- {
- if (defining_kbd_macro)
- add_macro_char (key);
- if (key > 127 && key < 256)
- {
- if (map[ESC].type == ISKMAP)
- {
- map = (Keymap)map[ESC].function;
- key -= 128;
- rl_dispatch (key, map);
- }
- else
- ding ();
- return;
- }
- switch (map[key].type)
- {
- case ISFUNC:
- {
- Function *func = map[key].function;
- if (func != (Function *)NULL)
- {
- /* Special case rl_do_lowercase_version (). */
- if (func == rl_do_lowercase_version)
- {
- rl_dispatch (to_lower (key), map);
- return;
- }
- (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
- /* If we have input pending, then the last command was a prefix
- command. Don't change the state of rl_last_func. Otherwise,
- remember the last command executed in this variable. */
- if (!rl_pending_input)
- rl_last_func = map[key].function;
- }
- else
- {
- rl_abort ();
- return;
- }
- }
- break;
- case ISKMAP:
- if (map[key].function != (Function *)NULL)
- {
- int newkey;
- rl_key_sequence_length++;
- newkey = rl_read_key ();
- rl_dispatch (newkey, (Keymap)map[key].function);
- }
- else
- {
- rl_abort ();
- return;
- }
- break;
- case ISMACR:
- if (map[key].function != (Function *)NULL)
- {
- char *macro;
- macro = savestring ((char *)map[key].function);
- with_macro_input (macro);
- return;
- }
- break;
- }
- }
- /* **************************************************************** */
- /* */
- /* Hacking Keyboard Macros */
- /* */
- /* **************************************************************** */
- /* The currently executing macro string. If this is non-zero,
- then it is a malloc ()'ed string where input is coming from. */
- static char *executing_macro = (char *)NULL;
- /* The offset in the above string to the next character to be read. */
- static int executing_macro_index = 0;
- /* The current macro string being built. Characters get stuffed
- in here by add_macro_char (). */
- static char *current_macro = (char *)NULL;
- /* The size of the buffer allocated to current_macro. */
- static int current_macro_size = 0;
- /* The index at which characters are being added to current_macro. */
- static int current_macro_index = 0;
- /* A structure used to save nested macro strings.
- It is a linked list of string/index for each saved macro. */
- struct saved_macro {
- struct saved_macro *next;
- char *string;
- int index;
- };
- /* The list of saved macros. */
- struct saved_macro *macro_list = (struct saved_macro *)NULL;
- /* Forward declarations of static functions. Thank you C. */
- static void push_executing_macro (), pop_executing_macro ();
- /* This one has to be declared earlier in the file. */
- /* static void add_macro_char (); */
- /* Set up to read subsequent input from STRING.
- STRING is free ()'ed when we are done with it. */
- static void
- with_macro_input (string)
- char *string;
- {
- push_executing_macro ();
- executing_macro = string;
- executing_macro_index = 0;
- }
- /* Return the next character available from a macro, or 0 if
- there are no macro characters. */
- static int
- next_macro_key ()
- {
- if (!executing_macro)
- return (0);
- if (!executing_macro[executing_macro_index])
- {
- pop_executing_macro ();
- return (next_macro_key ());
- }
- return (executing_macro[executing_macro_index++]);
- }
- /* Save the currently executing macro on a stack of saved macros. */
- static void
- push_executing_macro ()
- {
- struct saved_macro *saver;
- saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
- saver->next = macro_list;
- saver->index = executing_macro_index;
- saver->string = executing_macro;
- macro_list = saver;
- }
- /* Discard the current macro, replacing it with the one
- on the top of the stack of saved macros. */
- static void
- pop_executing_macro ()
- {
- if (executing_macro)
- free (executing_macro);
- executing_macro = (char *)NULL;
- executing_macro_index = 0;
- if (macro_list)
- {
- struct saved_macro *disposer = macro_list;
- executing_macro = macro_list->string;
- executing_macro_index = macro_list->index;
- macro_list = macro_list->next;
- free (disposer);
- }
- }
- /* Add a character to the macro being built. */
- static void
- add_macro_char (c)
- int c;
- {
- if (current_macro_index + 1 >= current_macro_size)
- {
- if (!current_macro)
- current_macro = (char *)xmalloc (current_macro_size = 25);
- else
- current_macro =
- (char *)xrealloc (current_macro, current_macro_size += 25);
- }
- current_macro[current_macro_index++] = c;
- current_macro[current_macro_index] = '\0';
- }
- /* Begin defining a keyboard macro.
- Keystrokes are recorded as they are executed.
- End the definition with rl_end_kbd_macro ().
- If a numeric argument was explicitly typed, then append this
- definition to the end of the existing macro, and start by
- re-executing the existing macro. */
- rl_start_kbd_macro (ignore1, ignore2)
- int ignore1, ignore2;
- {
- if (defining_kbd_macro)
- rl_abort ();
- if (rl_explicit_arg)
- {
- if (current_macro)
- with_macro_input (savestring (current_macro));
- }
- else
- current_macro_index = 0;
- defining_kbd_macro = 1;
- }
- /* Stop defining a keyboard macro.
- A numeric argument says to execute the macro right now,
- that many times, counting the definition as the first time. */
- rl_end_kbd_macro (count, ignore)
- int count, ignore;
- {
- if (!defining_kbd_macro)
- rl_abort ();
- current_macro_index -= (rl_key_sequence_length - 1);
- current_macro[current_macro_index] = '\0';
- defining_kbd_macro = 0;
- rl_call_last_kbd_macro (--count, 0);
- }
- /* Execute the most recently defined keyboard macro.
- COUNT says how many times to execute it. */
- rl_call_last_kbd_macro (count, ignore)
- int count, ignore;
- {
- if (!current_macro)
- rl_abort ();
- while (count--)
- with_macro_input (savestring (current_macro));
- }
- /* **************************************************************** */
- /* */
- /* Initializations */
- /* */
- /* **************************************************************** */
- /* Initliaze readline (and terminal if not already). */
- rl_initialize ()
- {
- extern char *rl_display_prompt;
- /* If we have never been called before, initialize the
- terminal and data structures. */
- if (!rl_initialized)
- {
- readline_initialize_everything ();
- rl_initialized++;
- }
- /* Initalize the current line information. */
- rl_point = rl_end = 0;
- the_line = rl_line_buffer;
- the_line[0] = 0;
- /* We aren't done yet. We haven't even gotten started yet! */
- rl_done = 0;
- /* Tell the history routines what is going on. */
- start_using_history ();
- /* Make the display buffer match the state of the line. */
- {
- extern char *rl_display_prompt;
- extern int forced_display;
- rl_on_new_line ();
- rl_display_prompt = rl_prompt ? rl_prompt : "";
- forced_display = 1;
- }
- /* No such function typed yet. */
- rl_last_func = (Function *)NULL;
- /* Parsing of key-bindings begins in an enabled state. */
- parsing_conditionalized_out = 0;
- }
- /* Initialize the entire state of the world. */
- readline_initialize_everything ()
- {
- /* Find out if we are running in Emacs. */
- running_in_emacs = getenv ("EMACS");
- /* Set up input and output if they aren't already. */
- if (!rl_instream)
- rl_instream = stdin;
- if (!rl_outstream)
- rl_outstream = stdout;
- /* Allocate data structures. */
- if (!rl_line_buffer)
- rl_line_buffer =
- (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
- /* Initialize the terminal interface. */
- init_terminal_io ((char *)NULL);
- /* Bind tty characters to readline functions. */
- readline_default_bindings ();
- /* Initialize the function names. */
- rl_initialize_funmap ();
- /* Read in the init file. */
- rl_read_init_file ((char *)NULL);
- /* If the completion parser's default word break characters haven't
- been set yet, then do so now. */
- {
- extern char *rl_completer_word_break_characters;
- extern char *rl_basic_word_break_characters;
- if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = rl_basic_word_break_characters;
- }
- }
- /* If this system allows us to look at the values of the regular
- input editing characters, then bind them to their readline
- equivalents, iff the characters are not bound to keymaps. */
- readline_default_bindings ()
- {
- #if !defined(__GO32__) && !defined(WIN32)
- #if defined (NEW_TTY_DRIVER)
- struct sgttyb ttybuff;
- int tty = fileno (rl_instream);
- if (ioctl (tty, TIOCGETP, &ttybuff) != -1)
- {
- int erase, kill;
- erase = ttybuff.sg_erase;
- kill = ttybuff.sg_kill;
- if (erase != -1 && keymap[erase].type == ISFUNC)
- keymap[erase].function = rl_rubout;
- if (kill != -1 && keymap[kill].type == ISFUNC)
- keymap[kill].function = rl_unix_line_discard;
- }
- #if defined (TIOCGLTC)
- {
- struct ltchars lt;
- if (ioctl (tty, TIOCGLTC, <) != -1)
- {
- int erase, nextc;
- erase = lt.t_werasc;
- nextc = lt.t_lnextc;
- if (erase != -1 && keymap[erase].type == ISFUNC)
- keymap[erase].function = rl_unix_word_rubout;
- if (nextc != -1 && keymap[nextc].type == ISFUNC)
- keymap[nextc].function = rl_quoted_insert;
- }
- }
- #endif /* TIOCGLTC */
- #else /* not NEW_TTY_DRIVER */
- #if defined (TERMIOS_TTY_DRIVER)
- struct termios ttybuff;
- #else
- struct termio ttybuff;
- #endif /* TERMIOS_TTY_DRIVER */
- int tty = fileno (rl_instream);
- #if defined (TERMIOS_TTY_DRIVER)
- if (tcgetattr (tty, &ttybuff) != -1)
- #else
- if (ioctl (tty, TCGETA, &ttybuff) != -1)
- #endif /* !TERMIOS_TTY_DRIVER */
- {
- int erase, kill;
- erase = ttybuff.c_cc[VERASE];
- kill = ttybuff.c_cc[VKILL];
- if (erase != _POSIX_VDISABLE &&
- keymap[(unsigned char)erase].type == ISFUNC)
- keymap[(unsigned char)erase].function = rl_rubout;
- if (kill != _POSIX_VDISABLE &&
- keymap[(unsigned char)kill].type == ISFUNC)
- keymap[(unsigned char)kill].function = rl_unix_line_discard;
- #if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
- {
- int nextc;
- nextc = ttybuff.c_cc[VLNEXT];
- if (nextc != _POSIX_VDISABLE &&
- keymap[(unsigned char)nextc].type == ISFUNC)
- keymap[(unsigned char)nextc].function = rl_quoted_insert;
- }
- #endif /* VLNEXT && TERMIOS_TTY_DRIVER */
- #if defined (VWERASE)
- {
- int werase;
- werase = ttybuff.c_cc[VWERASE];
- if (werase != _POSIX_VDISABLE &&
- keymap[(unsigned char)werase].type == ISFUNC)
- keymap[(unsigned char)werase].function = rl_unix_word_rubout;
- }
- #endif /* VWERASE */
- }
- #endif /* !NEW_TTY_DRIVER */
- #endif /* def __GO32__ */
- }
- /* **************************************************************** */
- /* */
- /* Numeric Arguments */
- /* */
- /* **************************************************************** */
- /* Handle C-u style numeric args, as well as M--, and M-digits. */
- /* Add the current digit to the argument in progress. */
- rl_digit_argument (ignore, key)
- int ignore, key;
- {
- rl_pending_input = key;
- rl_digit_loop ();
- }
- /* What to do when you abort reading an argument. */
- rl_discard_argument ()
- {
- ding ();
- rl_clear_message ();
- rl_init_argument ();
- }
- /* Create a default argument. */
- rl_init_argument ()
- {
- rl_numeric_arg = rl_arg_sign = 1;
- rl_explicit_arg = 0;
- }
- /* C-u, universal argument. Multiply the current argument by 4.
- Read a key. If the key has nothing to do with arguments, then
- dispatch on it. If the key is the abort character then abort. */
- rl_universal_argument ()
- {
- rl_numeric_arg *= 4;
- rl_digit_loop ();
- }
- rl_digit_loop ()
- {
- int key, c;
- while (1)
- {
- rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
- key = c = rl_read_key ();
- if (keymap[c].type == ISFUNC &&
- keymap[c].function == rl_universal_argument)
- {
- rl_numeric_arg *= 4;
- continue;
- }
- c = UNMETA (c);
- if (numeric (c))
- {
- if (rl_explicit_arg)
- rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
- else
- rl_numeric_arg = (c - '0');
- rl_explicit_arg = 1;
- }
- else
- {
- if (c == '-' && !rl_explicit_arg)
- {
- rl_numeric_arg = 1;
- rl_arg_sign = -1;
- }
- else
- {
- rl_clear_message ();
- rl_dispatch (key, keymap);
- return;
- }
- }
- }
- }
- /* **************************************************************** */
- /* */
- /* Display stuff */
- /* */
- /* **************************************************************** */
- /* This is the stuff that is hard for me. I never seem to write good
- display routines in C. Let's see how I do this time. */
- /* (PWP) Well... Good for a simple line updater, but totally ignores
- the problems of input lines longer than the screen width.
- update_line and the code that calls it makes a multiple line,
- automatically wrapping line update. Carefull attention needs
- to be paid to the vertical position variables.
- handling of terminals with autowrap on (incl. DEC braindamage)
- could be improved a bit. Right now I just cheat and decrement
- screenwidth by one. */
- /* Keep two buffers; one which reflects the current contents of the
- screen, and the other to draw what we think the new contents should
- be. Then compare the buffers, and make whatever changes to the
- screen itself that we should. Finally, make the buffer that we
- just drew into be the one which reflects the current contents of the
- screen, and place the cursor where it belongs.
- Commands that want to can fix the display themselves, and then let
- this function know that the display has been fixed by setting the
- RL_DISPLAY_FIXED variable. This is good for efficiency. */
- /* Termcap variables: */
- extern char *term_up, *term_dc, *term_cr;
- extern int screenheight, screenwidth, terminal_can_insert;
- /* What YOU turn on when you have handled all redisplay yourself. */
- int rl_display_fixed = 0;
- /* The visible cursor position. If you print some text, adjust this. */
- int last_c_pos = 0;
- int last_v_pos = 0;
- /* The last left edge of text that was displayed. This is used when
- doing horizontal scrolling. It shifts in thirds of a screenwidth. */
- static int last_lmargin = 0;
- /* The line display buffers. One is the line currently displayed on
- the screen. The other is the line about to be displayed. */
- static char *visible_line = (char *)NULL;
- static char *invisible_line = (char *)NULL;
- /* Number of lines currently on screen minus 1. */
- int vis_botlin = 0;
- /* A buffer for `modeline' messages. */
- char msg_buf[128];
- /* Non-zero forces the redisplay even if we thought it was unnecessary. */
- int forced_display = 0;
- /* The stuff that gets printed out before the actual text of the line.
- This is usually pointing to rl_prompt. */
- char *rl_display_prompt = (char *)NULL;
- /* Default and initial buffer size. Can grow. */
- static int line_size = 1024;
- /* Non-zero means to always use horizontal scrolling in line display. */
- static int horizontal_scroll_mode = 0;
- /* Non-zero means to display an asterisk at the starts of history lines
- which have been modified. */
- static int mark_modified_lines = 0;
- /* Non-zero means to use a visible bell if one is available rather than
- simply ringing the terminal bell. */
- static int prefer_visible_bell = 0;
- /* I really disagree with this, but my boss (among others) insists that we
- support compilers that don't work. I don't think we are gaining by doing
- so; what is the advantage in producing better code if we can't use it? */
- /* The following two declarations belong inside the
- function block, not here. */
- static void move_cursor_relative ();
- static void output_some_chars ();
- static void output_character_function ();
- static int compare_strings ();
- /* Basic redisplay algorithm. */
- rl_redisplay ()
- {
- register int in, out, c, linenum;
- register char *line = invisible_line;
- char *prompt_this_line;
- int c_pos = 0;
- int inv_botlin = 0; /* Number of lines in newly drawn buffer. */
- extern int readline_echoing_p;
- if (!readline_echoing_p)
- return;
- if (!rl_display_prompt)
- rl_display_prompt = "";
- if (!invisible_line)
- {
- visible_line = (char *)xmalloc (line_size);
- invisible_line = (char *)xmalloc (line_size);
- line = invisible_line;
- for (in = 0; in < line_size; in++)
- {
- visible_line[in] = 0;
- invisible_line[in] = 1;
- }
- rl_on_new_line ();
- }
- /* Draw the line into the buffer. */
- c_pos = -1;
- /* Mark the line as modified or not. We only do this for history
- lines. */
- out = 0;
- if (mark_modified_lines && current_history () && rl_undo_list)
- {
- line[out++] = '*';
- line[out] = '\0';
- }
- /* If someone thought that the redisplay was handled, but the currently
- visible line has a different modification state than the one about
- to become visible, then correct the callers misconception. */
- if (visible_line[0] != invisible_line[0])
- rl_display_fixed = 0;
- prompt_this_line = rindex (rl_display_prompt, '\n');
- if (!prompt_this_line)
- prompt_this_line = rl_display_prompt;
- else
- {
- prompt_this_line++;
- if (forced_display)
- output_some_chars (rl_display_prompt,
- prompt_this_line - rl_display_prompt);
- }
- strncpy (line + out, prompt_this_line, strlen (prompt_this_line));
- out += strlen (prompt_this_line);
- line[out] = '\0';
- for (in = 0; in < rl_end; in++)
- {
- c = (unsigned char)the_line[in];
- if (out + 1 >= line_size)
- {
- line_size *= 2;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
- if (in == rl_point)
- c_pos = out;
- if (c > 127)
- {
- line[out++] = 'M';
- line[out++] = '-';
- line[out++] = c - 128;
- }
- #define DISPLAY_TABS
- #if defined (DISPLAY_TABS)
- else if (c == '\t')
- {
- register int newout = (out | (int)7) + 1;
- while (out < newout)
- line[out++] = ' ';
- }
- #endif
- else if (c < 32)
- {
- line[out++] = 'C';
- line[out++] = '-';
- line[out++] = c + 64;
- }
- else if (c == 127)
- {
- line[out++] = 'C';
- line[out++] = '-';
- line[out++] = '?';
- }
- else
- line[out++] = c;
- }
- line[out] = '\0';
- if (c_pos < 0)
- c_pos = out;
- /* PWP: now is when things get a bit hairy. The visible and invisible
- line buffers are really multiple lines, which would wrap every
- (screenwidth - 1) characters. Go through each in turn, finding
- the changed region and updating it. The line order is top to bottom. */
- /* If we can move the cursor up and down, then use multiple lines,
- otherwise, let long lines display in a single terminal line, and
- horizontally scroll it. */
- if (!horizontal_scroll_mode && term_up && *term_up)
- {
- int total_screen_chars = (screenwidth * screenheight);
- if (!rl_display_fixed || forced_display)
- {
- forced_display = 0;
- /* If we have more than a screenful of material to display, then
- only display a screenful. We should display the last screen,
- not the first. I'll fix this in a minute. */
- if (out >= total_screen_chars)
- out = total_screen_chars - 1;
- /* Number of screen lines to display. */
- inv_botlin = out / screenwidth;
- /* For each line in the buffer, do the updating display. */
- for (linenum = 0; linenum <= inv_botlin; linenum++)
- update_line (linenum > vis_botlin ? ""
- : &visible_line[linenum * screenwidth],
- &invisible_line[linenum * screenwidth],
- linenum);
- /* We may have deleted some lines. If so, clear the left over
- blank ones at the bottom out. */
- if (vis_botlin > inv_botlin)
- {
- char *tt;
- for (; linenum <= vis_botlin; linenum++)
- {
- tt = &visible_line[linenum * screenwidth];
- move_vert (linenum);
- move_cursor_relative (0, tt);
- clear_to_eol ((linenum == vis_botlin)?
- strlen (tt) : screenwidth);
- }
- }
- vis_botlin = inv_botlin;
- /* Move the cursor where it should be. */
- move_vert (c_pos / screenwidth);
- move_cursor_relative (c_pos % screenwidth,
- &invisible_line[(c_pos / screenwidth) * screenwidth]);
- }
- }
- else /* Do horizontal scrolling. */
- {
- int lmargin;
- /* Always at top line. */
- last_v_pos = 0;
- /* If the display position of the cursor would be off the edge
- of the screen, start the display of this line at an offset that
- leaves the cursor on the screen. */
- if (c_pos - last_lmargin > screenwidth - 2)
- lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
- else if (c_pos - last_lmargin < 1)
- lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
- else
- lmargin = last_lmargin;
- /* If the first character on the screen isn't the first character
- in the display line, indicate this with a special character. */
- if (lmargin > 0)
- line[lmargin] = '<';
- if (lmargin + screenwidth < out)
- line[lmargin + screenwidth - 1] = '>';
- if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
- {
- forced_display = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin], 0);
- move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
- last_lmargin = lmargin;
- }
- }
- fflush (out_stream);
- /* Swap visible and non-visible lines. */
- {
- char *temp = visible_line;
- visible_line = invisible_line;
- invisible_line = temp;
- rl_display_fixed = 0;
- }
- }
- /* PWP: update_line() is based on finding the middle difference of each
- line on the screen; vis:
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
- old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
- new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
- All are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handeled.
- Could be made even smarter, but this works well enough */
- static
- update_line (old, new, current_line)
- register char *old, *new;
- int current_line;
- {
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
- int lendiff, wsatend;
- /* Find first difference. */
- for (ofd = old, nfd = new;
- (ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
- ;
- /* Move to the end of the screen line. */
- for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
- for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
- /* If no difference, continue to next line. */
- if (ofd == oe && nfd == ne)
- return;
- wsatend = 1; /* flag for trailing whitespace */
- ols = oe - 1; /* find last same */
- nls = ne - 1;
- while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
- {
- if (*ols != ' ')
- wsatend = 0;
- ols--;
- nls--;
- }
- if (wsatend)
- {
- ols = oe;
- nls = ne;
- }
- else if (*ols != *nls)
- {
- if (*ols) /* don't step past the NUL */
- ols++;
- if (*nls)
- nls++;
- }
- move_vert (current_line);
- move_cursor_relative (ofd - old, old);
- /* if (len (new) > len (old)) */
- lendiff = (nls - nfd) - (ols - ofd);
- /* Insert (diff(len(old),len(new)) ch */
- if (lendiff > 0)
- {
- if (terminal_can_insert)
- {
- extern char *term_IC;
- /* Sometimes it is cheaper to print the characters rather than
- use the terminal's capabilities. */
- if ((2 * (ne - nfd)) < lendiff && !term_IC)
- {
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- }
- else
- {
- if (*ols)
- {
- insert_some_chars (nfd, lendiff);
- last_c_pos += lendiff;
- }
- else
- {
- /* At the end of a line the characters do not have to
- be "inserted". They can just be placed on the screen. */
- output_some_chars (nfd, lendiff);
- last_c_pos += lendiff;
- }
- /* Copy (new) chars to screen from first diff to last match. */
- if (((nls - nfd) - lendiff) > 0)
- {
- output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
- last_c_pos += ((nls - nfd) - lendiff);
- }
- }
- }
- else
- { /* cannot insert chars, write to EOL */
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- }
- }
- else /* Delete characters from line. */
- {
- /* If possible and inexpensive to use terminal deletion, then do so. */
- if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
- {
- if (lendiff)
- delete_chars (-lendiff); /* delete (diff) characters */
- /* Copy (new) chars to screen from first diff to last match */
- if ((nls - nfd) > 0)
- {
- output_some_chars (nfd, (nls - nfd));
- last_c_pos += (nls - nfd);
- }
- }
- /* Otherwise, print over the existing material. */
- else
- {
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- clear_to_eol ((oe - old) - (ne - new));
- }
- }
- }
- /* (PWP) tell the update routines that we have moved onto a
- new (empty) line. */
- rl_on_new_line ()
- {
- if (visible_line)
- visible_line[0] = '\0';
- last_c_pos = last_v_pos = 0;
- vis_botlin = last_lmargin = 0;
- }
- /* Actually update the display, period. */
- rl_forced_update_display ()
- {
- if (visible_line)
- {
- register char *temp = visible_line;
- while (*temp) *temp++ = '\0';
- }
- rl_on_new_line ();
- forced_display++;
- rl_redisplay ();
- }
- /* Move the cursor from last_c_pos to NEW, which are buffer indices.
- DATA is the contents of the screen line of interest; i.e., where
- the movement is being done. */
- static void
- move_cursor_relative (new, data)
- int new;
- char *data;
- {
- #ifdef WIN32
- winio_rel_move(new);
- last_c_pos = new;
- return;
- #else
- register int i;
- #if GRX
- if (egagrph) {
- grx_rel_move(new);
- last_c_pos = new;
- return;
- }
- #endif
- /* It may be faster to output a CR, and then move forwards instead
- of moving backwards. */
- if (new + 1 < last_c_pos - new)
- {
- #ifdef __MSDOS__
- putc('\r', out_stream);
- #else
- tputs (term_cr, 1, output_character_function);
- #endif
- last_c_pos = 0;
- }
- if (last_c_pos == new) return;
- if (last_c_pos < new)
- {
- /* Move the cursor forward. We do it by printing the command
- to move the cursor forward if there is one, else print that
- portion of the output buffer again. Which is cheaper? */
- /* The above comment is left here for posterity. It is faster
- to print one character (non-control) than to print a control
- sequence telling the terminal to move forward one character.
- That kind of control is for people who don't know what the
- data is underneath the cursor. */
- #if defined (HACK_TERMCAP_MOTION)
- extern char *term_forward_char;
- if (term_forward_char)
- for (i = last_c_pos; i < new; i++)
- tputs (term_forward_char, 1, output_character_function);
- else
- for (i = last_c_pos; i < new; i++)
- putc (data[i], out_stream);
- #else
- for (i = last_c_pos; i < new; i++)
- putc (data[i], out_stream);
- #endif /* HACK_TERMCAP_MOTION */
- }
- else
- backspace (last_c_pos - new);
- last_c_pos = new;
- #endif
- }
- /* PWP: move the cursor up or down. */
- move_vert (to)
- int to;
- {
- #ifdef WIN32
- #else
- void output_character_function ();
- register int delta, i;
- if (last_v_pos == to) return;
- if (to > screenheight)
- return;
- #if defined(__GO32__)
- {
- int cur_r, cur_c;
- ScreenGetCursor(&cur_r, &cur_c);
- ScreenSetCursor(cur_r+to-last_v_pos, cur_c);
- }
- #else /* __GO32__ */
- if ((delta = to - last_v_pos) > 0)
- {
- for (i = 0; i < delta; i++)
- putc ('\n', out_stream);
- tputs (term_cr, 1, output_character_function);
- last_c_pos = 0;
- }
- else
- { /* delta < 0 */
- if (term_up && *term_up)
- for (i = 0; i < -delta; i++)
- tputs (term_up, 1, output_…
Large files files are truncated, but you can click here to view the full file