| /* rltty.c -- functions to prepare and restore the terminal for readline's |
| use. */ |
| |
| /* Copyright (C) 1992-2005 Free Software Foundation, Inc. |
| |
| This file is part of the GNU Readline Library (Readline), a library |
| for reading lines of text with interactive input and history editing. |
| |
| Readline 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 3 of the License, or |
| (at your option) any later version. |
| |
| Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #define READLINE_LIBRARY |
| |
| #if defined (HAVE_CONFIG_H) |
| # include <config.h> |
| #endif |
| |
| #include <sys/types.h> |
| #include <signal.h> |
| #include <errno.h> |
| #include <stdio.h> |
| |
| #if defined (HAVE_UNISTD_H) |
| # include <unistd.h> |
| #endif /* HAVE_UNISTD_H */ |
| |
| #include "rldefs.h" |
| |
| #if defined (GWINSZ_IN_SYS_IOCTL) |
| # include <sys/ioctl.h> |
| #endif /* GWINSZ_IN_SYS_IOCTL */ |
| |
| #include "rltty.h" |
| #include "readline.h" |
| #include "rlprivate.h" |
| |
| #if !defined (errno) |
| extern int errno; |
| #endif /* !errno */ |
| |
| rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal; |
| rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal; |
| |
| static void set_winsize PARAMS((int)); |
| |
| /* **************************************************************** */ |
| /* */ |
| /* Saving and Restoring the TTY */ |
| /* */ |
| /* **************************************************************** */ |
| |
| /* Non-zero means that the terminal is in a prepped state. */ |
| static int terminal_prepped; |
| |
| static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars; |
| |
| /* If non-zero, means that this process has called tcflow(fd, TCOOFF) |
| and output is suspended. */ |
| #if defined (__ksr1__) |
| static int ksrflow; |
| #endif |
| |
| /* Dummy call to force a backgrounded readline to stop before it tries |
| to get the tty settings. */ |
| static void |
| set_winsize (tty) |
| int tty; |
| { |
| #if defined (TIOCGWINSZ) |
| struct winsize w; |
| |
| if (ioctl (tty, TIOCGWINSZ, &w) == 0) |
| (void) ioctl (tty, TIOCSWINSZ, &w); |
| #endif /* TIOCGWINSZ */ |
| } |
| |
| #if defined (NO_TTY_DRIVER) |
| /* Nothing */ |
| #elif defined (NEW_TTY_DRIVER) |
| |
| /* Values for the `flags' field of a struct bsdtty. This tells which |
| elements of the struct bsdtty have been fetched from the system and |
| are valid. */ |
| #define SGTTY_SET 0x01 |
| #define LFLAG_SET 0x02 |
| #define TCHARS_SET 0x04 |
| #define LTCHARS_SET 0x08 |
| |
| struct bsdtty { |
| struct sgttyb sgttyb; /* Basic BSD tty driver information. */ |
| int lflag; /* Local mode flags, like LPASS8. */ |
| #if defined (TIOCGETC) |
| struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */ |
| #endif |
| #if defined (TIOCGLTC) |
| struct ltchars ltchars; /* 4.2 BSD editing characters */ |
| #endif |
| int flags; /* Bitmap saying which parts of the struct are valid. */ |
| }; |
| |
| #define TIOTYPE struct bsdtty |
| |
| static TIOTYPE otio; |
| |
| static void save_tty_chars PARAMS((TIOTYPE *)); |
| static int _get_tty_settings PARAMS((int, TIOTYPE *)); |
| static int get_tty_settings PARAMS((int, TIOTYPE *)); |
| static int _set_tty_settings PARAMS((int, TIOTYPE *)); |
| static int set_tty_settings PARAMS((int, TIOTYPE *)); |
| |
| static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); |
| |
| static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t)); |
| |
| static void |
| save_tty_chars (tiop) |
| TIOTYPE *tiop; |
| { |
| _rl_last_tty_chars = _rl_tty_chars; |
| |
| if (tiop->flags & SGTTY_SET) |
| { |
| _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase; |
| _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill; |
| } |
| |
| if (tiop->flags & TCHARS_SET) |
| { |
| _rl_intr_char = _rl_tty_chars.t_intr = tiop->tchars.t_intrc; |
| _rl_quit_char = _rl_tty_chars.t_quit = tiop->tchars.t_quitc; |
| |
| _rl_tty_chars.t_start = tiop->tchars.t_startc; |
| _rl_tty_chars.t_stop = tiop->tchars.t_stopc; |
| _rl_tty_chars.t_eof = tiop->tchars.t_eofc; |
| _rl_tty_chars.t_eol = '\n'; |
| _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc; |
| } |
| |
| if (tiop->flags & LTCHARS_SET) |
| { |
| _rl_susp_char = _rl_tty_chars.t_susp = tiop->ltchars.t_suspc; |
| |
| _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc; |
| _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc; |
| _rl_tty_chars.t_flush = tiop->ltchars.t_flushc; |
| _rl_tty_chars.t_werase = tiop->ltchars.t_werasc; |
| _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc; |
| } |
| |
| _rl_tty_chars.t_status = -1; |
| } |
| |
| static int |
| get_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| set_winsize (tty); |
| |
| tiop->flags = tiop->lflag = 0; |
| |
| errno = 0; |
| if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0) |
| return -1; |
| tiop->flags |= SGTTY_SET; |
| |
| #if defined (TIOCLGET) |
| if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0) |
| tiop->flags |= LFLAG_SET; |
| #endif |
| |
| #if defined (TIOCGETC) |
| if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0) |
| tiop->flags |= TCHARS_SET; |
| #endif |
| |
| #if defined (TIOCGLTC) |
| if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0) |
| tiop->flags |= LTCHARS_SET; |
| #endif |
| |
| return 0; |
| } |
| |
| static int |
| set_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| if (tiop->flags & SGTTY_SET) |
| { |
| ioctl (tty, TIOCSETN, &(tiop->sgttyb)); |
| tiop->flags &= ~SGTTY_SET; |
| } |
| _rl_echoing_p = 1; |
| |
| #if defined (TIOCLSET) |
| if (tiop->flags & LFLAG_SET) |
| { |
| ioctl (tty, TIOCLSET, &(tiop->lflag)); |
| tiop->flags &= ~LFLAG_SET; |
| } |
| #endif |
| |
| #if defined (TIOCSETC) |
| if (tiop->flags & TCHARS_SET) |
| { |
| ioctl (tty, TIOCSETC, &(tiop->tchars)); |
| tiop->flags &= ~TCHARS_SET; |
| } |
| #endif |
| |
| #if defined (TIOCSLTC) |
| if (tiop->flags & LTCHARS_SET) |
| { |
| ioctl (tty, TIOCSLTC, &(tiop->ltchars)); |
| tiop->flags &= ~LTCHARS_SET; |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| static void |
| prepare_terminal_settings (meta_flag, oldtio, tiop) |
| int meta_flag; |
| TIOTYPE oldtio, *tiop; |
| { |
| _rl_echoing_p = (oldtio.sgttyb.sg_flags & ECHO); |
| _rl_echoctl = (oldtio.sgttyb.sg_flags & ECHOCTL); |
| |
| /* Copy the original settings to the structure we're going to use for |
| our settings. */ |
| tiop->sgttyb = oldtio.sgttyb; |
| tiop->lflag = oldtio.lflag; |
| #if defined (TIOCGETC) |
| tiop->tchars = oldtio.tchars; |
| #endif |
| #if defined (TIOCGLTC) |
| tiop->ltchars = oldtio.ltchars; |
| #endif |
| tiop->flags = oldtio.flags; |
| |
| /* First, the basic settings to put us into character-at-a-time, no-echo |
| input mode. */ |
| tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD); |
| tiop->sgttyb.sg_flags |= CBREAK; |
| |
| /* If this terminal doesn't care how the 8th bit is used, then we can |
| use it for the meta-key. If only one of even or odd parity is |
| specified, then the terminal is using parity, and we cannot. */ |
| #if !defined (ANYP) |
| # define ANYP (EVENP | ODDP) |
| #endif |
| if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) || |
| ((oldtio.sgttyb.sg_flags & ANYP) == 0)) |
| { |
| tiop->sgttyb.sg_flags |= ANYP; |
| |
| /* Hack on local mode flags if we can. */ |
| #if defined (TIOCLGET) |
| # if defined (LPASS8) |
| tiop->lflag |= LPASS8; |
| # endif /* LPASS8 */ |
| #endif /* TIOCLGET */ |
| } |
| |
| #if defined (TIOCGETC) |
| # if defined (USE_XON_XOFF) |
| /* Get rid of terminal output start and stop characters. */ |
| tiop->tchars.t_stopc = -1; /* C-s */ |
| tiop->tchars.t_startc = -1; /* C-q */ |
| |
| /* If there is an XON character, bind it to restart the output. */ |
| if (oldtio.tchars.t_startc != -1) |
| rl_bind_key (oldtio.tchars.t_startc, rl_restart_output); |
| # endif /* USE_XON_XOFF */ |
| |
| /* If there is an EOF char, bind _rl_eof_char to it. */ |
| if (oldtio.tchars.t_eofc != -1) |
| _rl_eof_char = oldtio.tchars.t_eofc; |
| |
| # if defined (NO_KILL_INTR) |
| /* Get rid of terminal-generated SIGQUIT and SIGINT. */ |
| tiop->tchars.t_quitc = -1; /* C-\ */ |
| tiop->tchars.t_intrc = -1; /* C-c */ |
| # endif /* NO_KILL_INTR */ |
| #endif /* TIOCGETC */ |
| |
| #if defined (TIOCGLTC) |
| /* Make the interrupt keys go away. Just enough to make people happy. */ |
| tiop->ltchars.t_dsuspc = -1; /* C-y */ |
| tiop->ltchars.t_lnextc = -1; /* C-v */ |
| #endif /* TIOCGLTC */ |
| } |
| |
| #else /* !defined (NEW_TTY_DRIVER) */ |
| |
| #if !defined (VMIN) |
| # define VMIN VEOF |
| #endif |
| |
| #if !defined (VTIME) |
| # define VTIME VEOL |
| #endif |
| |
| #if defined (TERMIOS_TTY_DRIVER) |
| # define TIOTYPE struct termios |
| # define DRAIN_OUTPUT(fd) tcdrain (fd) |
| # define GETATTR(tty, tiop) (tcgetattr (tty, tiop)) |
| # ifdef M_UNIX |
| # define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop)) |
| # else |
| # define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop)) |
| # endif /* !M_UNIX */ |
| #else |
| # define TIOTYPE struct termio |
| # define DRAIN_OUTPUT(fd) |
| # define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop)) |
| # define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop)) |
| #endif /* !TERMIOS_TTY_DRIVER */ |
| |
| static TIOTYPE otio; |
| |
| static void save_tty_chars PARAMS((TIOTYPE *)); |
| static int _get_tty_settings PARAMS((int, TIOTYPE *)); |
| static int get_tty_settings PARAMS((int, TIOTYPE *)); |
| static int _set_tty_settings PARAMS((int, TIOTYPE *)); |
| static int set_tty_settings PARAMS((int, TIOTYPE *)); |
| |
| static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); |
| |
| static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t)); |
| static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE)); |
| |
| #if defined (FLUSHO) |
| # define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) |
| #else |
| # define OUTPUT_BEING_FLUSHED(tp) 0 |
| #endif |
| |
| static void |
| save_tty_chars (tiop) |
| TIOTYPE *tiop; |
| { |
| _rl_last_tty_chars = _rl_tty_chars; |
| |
| _rl_tty_chars.t_eof = tiop->c_cc[VEOF]; |
| _rl_tty_chars.t_eol = tiop->c_cc[VEOL]; |
| #ifdef VEOL2 |
| _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2]; |
| #endif |
| _rl_tty_chars.t_erase = tiop->c_cc[VERASE]; |
| #ifdef VWERASE |
| _rl_tty_chars.t_werase = tiop->c_cc[VWERASE]; |
| #endif |
| _rl_tty_chars.t_kill = tiop->c_cc[VKILL]; |
| #ifdef VREPRINT |
| _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT]; |
| #endif |
| _rl_intr_char = _rl_tty_chars.t_intr = tiop->c_cc[VINTR]; |
| _rl_quit_char = _rl_tty_chars.t_quit = tiop->c_cc[VQUIT]; |
| #ifdef VSUSP |
| _rl_susp_char = _rl_tty_chars.t_susp = tiop->c_cc[VSUSP]; |
| #endif |
| #ifdef VDSUSP |
| _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP]; |
| #endif |
| #ifdef VSTART |
| _rl_tty_chars.t_start = tiop->c_cc[VSTART]; |
| #endif |
| #ifdef VSTOP |
| _rl_tty_chars.t_stop = tiop->c_cc[VSTOP]; |
| #endif |
| #ifdef VLNEXT |
| _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT]; |
| #endif |
| #ifdef VDISCARD |
| _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD]; |
| #endif |
| #ifdef VSTATUS |
| _rl_tty_chars.t_status = tiop->c_cc[VSTATUS]; |
| #endif |
| } |
| |
| #if defined (_AIX) || defined (_AIX41) |
| /* Currently this is only used on AIX */ |
| static void |
| rltty_warning (msg) |
| char *msg; |
| { |
| _rl_errmsg ("warning: %s", msg); |
| } |
| #endif |
| |
| #if defined (_AIX) |
| void |
| setopost(tp) |
| TIOTYPE *tp; |
| { |
| if ((tp->c_oflag & OPOST) == 0) |
| { |
| _rl_errmsg ("warning: turning on OPOST for terminal\r"); |
| tp->c_oflag |= OPOST|ONLCR; |
| } |
| } |
| #endif |
| |
| static int |
| _get_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| int ioctl_ret; |
| |
| while (1) |
| { |
| ioctl_ret = GETATTR (tty, tiop); |
| if (ioctl_ret < 0) |
| { |
| if (errno != EINTR) |
| return -1; |
| else |
| continue; |
| } |
| if (OUTPUT_BEING_FLUSHED (tiop)) |
| { |
| #if defined (FLUSHO) |
| _rl_errmsg ("warning: turning off output flushing"); |
| tiop->c_lflag &= ~FLUSHO; |
| break; |
| #else |
| continue; |
| #endif |
| } |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int |
| get_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| set_winsize (tty); |
| |
| errno = 0; |
| if (_get_tty_settings (tty, tiop) < 0) |
| return -1; |
| |
| #if defined (_AIX) |
| setopost(tiop); |
| #endif |
| |
| return 0; |
| } |
| |
| static int |
| _set_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| while (SETATTR (tty, tiop) < 0) |
| { |
| if (errno != EINTR) |
| return -1; |
| errno = 0; |
| } |
| return 0; |
| } |
| |
| static int |
| set_tty_settings (tty, tiop) |
| int tty; |
| TIOTYPE *tiop; |
| { |
| if (_set_tty_settings (tty, tiop) < 0) |
| return -1; |
| |
| #if 0 |
| |
| #if defined (TERMIOS_TTY_DRIVER) |
| # if defined (__ksr1__) |
| if (ksrflow) |
| { |
| ksrflow = 0; |
| tcflow (tty, TCOON); |
| } |
| # else /* !ksr1 */ |
| tcflow (tty, TCOON); /* Simulate a ^Q. */ |
| # endif /* !ksr1 */ |
| #else |
| ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ |
| #endif /* !TERMIOS_TTY_DRIVER */ |
| |
| #endif /* 0 */ |
| |
| return 0; |
| } |
| |
| static void |
| prepare_terminal_settings (meta_flag, oldtio, tiop) |
| int meta_flag; |
| TIOTYPE oldtio, *tiop; |
| { |
| _rl_echoing_p = (oldtio.c_lflag & ECHO); |
| #if defined (ECHOCTL) |
| _rl_echoctl = (oldtio.c_lflag & ECHOCTL); |
| #endif |
| |
| tiop->c_lflag &= ~(ICANON | ECHO); |
| |
| if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) |
| _rl_eof_char = oldtio.c_cc[VEOF]; |
| |
| #if defined (USE_XON_XOFF) |
| #if defined (IXANY) |
| tiop->c_iflag &= ~(IXON | IXOFF | IXANY); |
| #else |
| /* `strict' Posix systems do not define IXANY. */ |
| tiop->c_iflag &= ~(IXON | IXOFF); |
| #endif /* IXANY */ |
| #endif /* USE_XON_XOFF */ |
| |
| /* Only turn this off if we are using all 8 bits. */ |
| if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag) |
| tiop->c_iflag &= ~(ISTRIP | INPCK); |
| |
| /* Make sure we differentiate between CR and NL on input. */ |
| tiop->c_iflag &= ~(ICRNL | INLCR); |
| |
| #if !defined (HANDLE_SIGNALS) |
| tiop->c_lflag &= ~ISIG; |
| #else |
| tiop->c_lflag |= ISIG; |
| #endif |
| |
| tiop->c_cc[VMIN] = 1; |
| tiop->c_cc[VTIME] = 0; |
| |
| #if defined (FLUSHO) |
| if (OUTPUT_BEING_FLUSHED (tiop)) |
| { |
| tiop->c_lflag &= ~FLUSHO; |
| oldtio.c_lflag &= ~FLUSHO; |
| } |
| #endif |
| |
| /* Turn off characters that we need on Posix systems with job control, |
| just to be sure. This includes ^Y and ^V. This should not really |
| be necessary. */ |
| #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE) |
| |
| #if defined (VLNEXT) |
| tiop->c_cc[VLNEXT] = _POSIX_VDISABLE; |
| #endif |
| |
| #if defined (VDSUSP) |
| tiop->c_cc[VDSUSP] = _POSIX_VDISABLE; |
| #endif |
| |
| #endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ |
| } |
| #endif /* !NEW_TTY_DRIVER */ |
| |
| /* Put the terminal in CBREAK mode so that we can detect key presses. */ |
| #if defined (NO_TTY_DRIVER) |
| void |
| rl_prep_terminal (meta_flag) |
| int meta_flag; |
| { |
| _rl_echoing_p = 1; |
| } |
| |
| void |
| rl_deprep_terminal () |
| { |
| } |
| |
| #else /* ! NO_TTY_DRIVER */ |
| void |
| rl_prep_terminal (meta_flag) |
| int meta_flag; |
| { |
| int tty; |
| TIOTYPE tio; |
| |
| if (terminal_prepped) |
| return; |
| |
| /* Try to keep this function from being INTerrupted. */ |
| _rl_block_sigint (); |
| |
| tty = rl_instream ? fileno (rl_instream) : fileno (stdin); |
| |
| if (get_tty_settings (tty, &tio) < 0) |
| { |
| #if defined (ENOTSUP) |
| /* MacOS X and Linux, at least, lie about the value of errno if |
| tcgetattr fails. */ |
| if (errno == ENOTTY || errno == EINVAL || errno == ENOTSUP) |
| #else |
| if (errno == ENOTTY || errno == EINVAL) |
| #endif |
| _rl_echoing_p = 1; /* XXX */ |
| |
| _rl_release_sigint (); |
| return; |
| } |
| |
| otio = tio; |
| |
| if (_rl_bind_stty_chars) |
| { |
| #if defined (VI_MODE) |
| /* If editing in vi mode, make sure we restore the bindings in the |
| insertion keymap no matter what keymap we ended up in. */ |
| if (rl_editing_mode == vi_mode) |
| rl_tty_unset_default_bindings (vi_insertion_keymap); |
| else |
| #endif |
| rl_tty_unset_default_bindings (_rl_keymap); |
| } |
| save_tty_chars (&otio); |
| RL_SETSTATE(RL_STATE_TTYCSAVED); |
| if (_rl_bind_stty_chars) |
| { |
| #if defined (VI_MODE) |
| /* If editing in vi mode, make sure we set the bindings in the |
| insertion keymap no matter what keymap we ended up in. */ |
| if (rl_editing_mode == vi_mode) |
| _rl_bind_tty_special_chars (vi_insertion_keymap, tio); |
| else |
| #endif |
| _rl_bind_tty_special_chars (_rl_keymap, tio); |
| } |
| |
| prepare_terminal_settings (meta_flag, otio, &tio); |
| |
| if (set_tty_settings (tty, &tio) < 0) |
| { |
| _rl_release_sigint (); |
| return; |
| } |
| |
| if (_rl_enable_keypad) |
| _rl_control_keypad (1); |
| |
| fflush (rl_outstream); |
| terminal_prepped = 1; |
| RL_SETSTATE(RL_STATE_TERMPREPPED); |
| |
| _rl_release_sigint (); |
| } |
| |
| /* Restore the terminal's normal settings and modes. */ |
| void |
| rl_deprep_terminal () |
| { |
| int tty; |
| |
| if (!terminal_prepped) |
| return; |
| |
| /* Try to keep this function from being interrupted. */ |
| _rl_block_sigint (); |
| |
| tty = rl_instream ? fileno (rl_instream) : fileno (stdout); |
| |
| if (_rl_enable_keypad) |
| _rl_control_keypad (0); |
| |
| fflush (rl_outstream); |
| |
| if (set_tty_settings (tty, &otio) < 0) |
| { |
| _rl_release_sigint (); |
| return; |
| } |
| |
| terminal_prepped = 0; |
| RL_UNSETSTATE(RL_STATE_TERMPREPPED); |
| |
| _rl_release_sigint (); |
| } |
| #endif /* !NO_TTY_DRIVER */ |
| |
| /* **************************************************************** */ |
| /* */ |
| /* Bogus Flow Control */ |
| /* */ |
| /* **************************************************************** */ |
| |
| int |
| rl_restart_output (count, key) |
| int count, key; |
| { |
| #if defined (__MINGW32__) |
| return 0; |
| #else /* !__MING32__ */ |
| |
| int fildes = fileno (rl_outstream); |
| #if defined (TIOCSTART) |
| #if defined (apollo) |
| ioctl (&fildes, TIOCSTART, 0); |
| #else |
| ioctl (fildes, TIOCSTART, 0); |
| #endif /* apollo */ |
| |
| #else /* !TIOCSTART */ |
| # if defined (TERMIOS_TTY_DRIVER) |
| # if defined (__ksr1__) |
| if (ksrflow) |
| { |
| ksrflow = 0; |
| tcflow (fildes, TCOON); |
| } |
| # else /* !ksr1 */ |
| tcflow (fildes, TCOON); /* Simulate a ^Q. */ |
| # endif /* !ksr1 */ |
| # else /* !TERMIOS_TTY_DRIVER */ |
| # if defined (TCXONC) |
| ioctl (fildes, TCXONC, TCOON); |
| # endif /* TCXONC */ |
| # endif /* !TERMIOS_TTY_DRIVER */ |
| #endif /* !TIOCSTART */ |
| |
| return 0; |
| #endif /* !__MINGW32__ */ |
| } |
| |
| int |
| rl_stop_output (count, key) |
| int count, key; |
| { |
| #if defined (__MINGW32__) |
| return 0; |
| #else |
| |
| int fildes = fileno (rl_instream); |
| |
| #if defined (TIOCSTOP) |
| # if defined (apollo) |
| ioctl (&fildes, TIOCSTOP, 0); |
| # else |
| ioctl (fildes, TIOCSTOP, 0); |
| # endif /* apollo */ |
| #else /* !TIOCSTOP */ |
| # if defined (TERMIOS_TTY_DRIVER) |
| # if defined (__ksr1__) |
| ksrflow = 1; |
| # endif /* ksr1 */ |
| tcflow (fildes, TCOOFF); |
| # else |
| # if defined (TCXONC) |
| ioctl (fildes, TCXONC, TCOON); |
| # endif /* TCXONC */ |
| # endif /* !TERMIOS_TTY_DRIVER */ |
| #endif /* !TIOCSTOP */ |
| |
| return 0; |
| #endif /* !__MINGW32__ */ |
| } |
| |
| /* **************************************************************** */ |
| /* */ |
| /* Default Key Bindings */ |
| /* */ |
| /* **************************************************************** */ |
| |
| #if !defined (NO_TTY_DRIVER) |
| #define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func) |
| #endif |
| |
| #if defined (NO_TTY_DRIVER) |
| |
| #define SET_SPECIAL(sc, func) |
| #define RESET_SPECIAL(c) |
| |
| #elif defined (NEW_TTY_DRIVER) |
| static void |
| set_special_char (kmap, tiop, sc, func) |
| Keymap kmap; |
| TIOTYPE *tiop; |
| int sc; |
| rl_command_func_t *func; |
| { |
| if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC) |
| kmap[(unsigned char)sc].function = func; |
| } |
| |
| #define RESET_SPECIAL(c) \ |
| if (c != -1 && kmap[(unsigned char)c].type == ISFUNC) \ |
| kmap[(unsigned char)c].function = rl_insert; |
| |
| static void |
| _rl_bind_tty_special_chars (kmap, ttybuff) |
| Keymap kmap; |
| TIOTYPE ttybuff; |
| { |
| if (ttybuff.flags & SGTTY_SET) |
| { |
| SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout); |
| SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard); |
| } |
| |
| # if defined (TIOCGLTC) |
| if (ttybuff.flags & LTCHARS_SET) |
| { |
| SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout); |
| SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert); |
| } |
| # endif /* TIOCGLTC */ |
| } |
| |
| #else /* !NEW_TTY_DRIVER */ |
| static void |
| set_special_char (kmap, tiop, sc, func) |
| Keymap kmap; |
| TIOTYPE *tiop; |
| int sc; |
| rl_command_func_t *func; |
| { |
| unsigned char uc; |
| |
| uc = tiop->c_cc[sc]; |
| if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) |
| kmap[uc].function = func; |
| } |
| |
| /* used later */ |
| #define RESET_SPECIAL(uc) \ |
| if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \ |
| kmap[uc].function = rl_insert; |
| |
| static void |
| _rl_bind_tty_special_chars (kmap, ttybuff) |
| Keymap kmap; |
| TIOTYPE ttybuff; |
| { |
| SET_SPECIAL (VERASE, rl_rubout); |
| SET_SPECIAL (VKILL, rl_unix_line_discard); |
| |
| # if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) |
| SET_SPECIAL (VLNEXT, rl_quoted_insert); |
| # endif /* VLNEXT && TERMIOS_TTY_DRIVER */ |
| |
| # if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER) |
| SET_SPECIAL (VWERASE, rl_unix_word_rubout); |
| # endif /* VWERASE && TERMIOS_TTY_DRIVER */ |
| } |
| |
| #endif /* !NEW_TTY_DRIVER */ |
| |
| /* Set the system's default editing characters to their readline equivalents |
| in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */ |
| void |
| rltty_set_default_bindings (kmap) |
| Keymap kmap; |
| { |
| #if !defined (NO_TTY_DRIVER) |
| TIOTYPE ttybuff; |
| int tty; |
| |
| tty = fileno (rl_instream); |
| |
| if (get_tty_settings (tty, &ttybuff) == 0) |
| _rl_bind_tty_special_chars (kmap, ttybuff); |
| #endif |
| } |
| |
| /* New public way to set the system default editing chars to their readline |
| equivalents. */ |
| void |
| rl_tty_set_default_bindings (kmap) |
| Keymap kmap; |
| { |
| rltty_set_default_bindings (kmap); |
| } |
| |
| /* Rebind all of the tty special chars that readline worries about back |
| to self-insert. Call this before saving the current terminal special |
| chars with save_tty_chars(). This only works on POSIX termios or termio |
| systems. */ |
| void |
| rl_tty_unset_default_bindings (kmap) |
| Keymap kmap; |
| { |
| /* Don't bother before we've saved the tty special chars at least once. */ |
| if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0) |
| return; |
| |
| RESET_SPECIAL (_rl_tty_chars.t_erase); |
| RESET_SPECIAL (_rl_tty_chars.t_kill); |
| |
| # if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) |
| RESET_SPECIAL (_rl_tty_chars.t_lnext); |
| # endif /* VLNEXT && TERMIOS_TTY_DRIVER */ |
| |
| # if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER) |
| RESET_SPECIAL (_rl_tty_chars.t_werase); |
| # endif /* VWERASE && TERMIOS_TTY_DRIVER */ |
| } |
| |
| #if defined (HANDLE_SIGNALS) |
| |
| #if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER) |
| int |
| _rl_disable_tty_signals () |
| { |
| return 0; |
| } |
| |
| int |
| _rl_restore_tty_signals () |
| { |
| return 0; |
| } |
| #else |
| |
| static TIOTYPE sigstty, nosigstty; |
| static int tty_sigs_disabled = 0; |
| |
| int |
| _rl_disable_tty_signals () |
| { |
| if (tty_sigs_disabled) |
| return 0; |
| |
| if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0) |
| return -1; |
| |
| nosigstty = sigstty; |
| |
| nosigstty.c_lflag &= ~ISIG; |
| nosigstty.c_iflag &= ~IXON; |
| |
| if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0) |
| return (_set_tty_settings (fileno (rl_instream), &sigstty)); |
| |
| tty_sigs_disabled = 1; |
| return 0; |
| } |
| |
| int |
| _rl_restore_tty_signals () |
| { |
| int r; |
| |
| if (tty_sigs_disabled == 0) |
| return 0; |
| |
| r = _set_tty_settings (fileno (rl_instream), &sigstty); |
| |
| if (r == 0) |
| tty_sigs_disabled = 0; |
| |
| return r; |
| } |
| #endif /* !NEW_TTY_DRIVER */ |
| |
| #endif /* HANDLE_SIGNALS */ |