-/**************************************************************************
- *
- * Mode-setting logic
- *
- **************************************************************************/
-
-/* some BSD systems have these built in, some systems are missing
- * one or more definitions. The safest solution is to override unless the
- * commonly-altered ones are defined.
- */
-#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
-#undef CEOF
-#undef CERASE
-#undef CINTR
-#undef CKILL
-#undef CLNEXT
-#undef CRPRNT
-#undef CQUIT
-#undef CSTART
-#undef CSTOP
-#undef CSUSP
-#endif
-
-/* control-character defaults */
-#ifndef CEOF
-#define CEOF CTRL('D')
-#endif
-#ifndef CERASE
-#define CERASE CTRL('H')
-#endif
-#ifndef CINTR
-#define CINTR 127 /* ^? */
-#endif
-#ifndef CKILL
-#define CKILL CTRL('U')
-#endif
-#ifndef CLNEXT
-#define CLNEXT CTRL('v')
-#endif
-#ifndef CRPRNT
-#define CRPRNT CTRL('r')
-#endif
-#ifndef CQUIT
-#define CQUIT CTRL('\\')
-#endif
-#ifndef CSTART
-#define CSTART CTRL('Q')
-#endif
-#ifndef CSTOP
-#define CSTOP CTRL('S')
-#endif
-#ifndef CSUSP
-#define CSUSP CTRL('Z')
-#endif
-
-#if defined(_POSIX_VDISABLE)
-#define DISABLED(val) (((_POSIX_VDISABLE != -1) \
- && ((val) == _POSIX_VDISABLE)) \
- || ((val) <= 0))
-#else
-#define DISABLED(val) ((int)(val) <= 0)
-#endif
-
-#define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val)
-
-static bool set_tabs(void);
-
-/*
- * Reset the terminal mode bits to a sensible state. Very useful after
- * a child program dies in raw mode.
- */
-static void
-reset_mode(void)
-{
-#ifdef TERMIOS
- tcgetattr(STDERR_FILENO, &mode);
-#else
- stty(STDERR_FILENO, &mode);
-#endif
-
-#ifdef TERMIOS
-#if defined(VDISCARD) && defined(CDISCARD)
- mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
-#endif
- mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
- mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
-#if defined(VFLUSH) && defined(CFLUSH)
- mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
-#endif
- mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
- mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
-#if defined(VLNEXT) && defined(CLNEXT)
- mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
-#endif
- mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
-#if defined(VREPRINT) && defined(CRPRNT)
- mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
-#endif
-#if defined(VSTART) && defined(CSTART)
- mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
-#endif
-#if defined(VSTOP) && defined(CSTOP)
- mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
-#endif
-#if defined(VSUSP) && defined(CSUSP)
- mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
-#endif
-#if defined(VWERASE) && defined(CWERASE)
- mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
-#endif
-
- mode.c_iflag &= ~((unsigned) (IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
-#ifdef IUCLC
- | IUCLC
-#endif
-#ifdef IXANY
- | IXANY
-#endif
- | IXOFF));
-
- mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
-#ifdef IMAXBEL
- | IMAXBEL
-#endif
- );
-
- mode.c_oflag &= ~((unsigned) (0
-#ifdef OLCUC
- | OLCUC
-#endif
-#ifdef OCRNL
- | OCRNL
-#endif
-#ifdef ONOCR
- | ONOCR
-#endif
-#ifdef ONLRET
- | ONLRET
-#endif
-#ifdef OFILL
- | OFILL
-#endif
-#ifdef OFDEL
- | OFDEL
-#endif
-#ifdef NLDLY
- | NLDLY
-#endif
-#ifdef CRDLY
- | CRDLY
-#endif
-#ifdef TABDLY
- | TABDLY
-#endif
-#ifdef BSDLY
- | BSDLY
-#endif
-#ifdef VTDLY
- | VTDLY
-#endif
-#ifdef FFDLY
- | FFDLY
-#endif
- ));
-
- mode.c_oflag |= (OPOST
-#ifdef ONLCR
- | ONLCR
-#endif
- );
-
- mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL));
- mode.c_cflag |= (CS8 | CREAD);
- mode.c_lflag &= ~((unsigned) (ECHONL | NOFLSH
-#ifdef TOSTOP
- | TOSTOP
-#endif
-#ifdef ECHOPTR
- | ECHOPRT
-#endif
-#ifdef XCASE
- | XCASE
-#endif
- ));
-
- mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
-#ifdef ECHOCTL
- | ECHOCTL
-#endif
-#ifdef ECHOKE
- | ECHOKE
-#endif
- );
-#endif
-
- SET_TTY(STDERR_FILENO, &mode);
-}
-
-/*
- * Returns a "good" value for the erase character. This is loosely based on
- * the BSD4.4 logic.
- */
-#ifdef TERMIOS
-static int
-default_erase(void)
-{
- int result;
-
- if (over_strike
- && key_backspace != 0
- && strlen(key_backspace) == 1)
- result = key_backspace[0];
- else
- result = CERASE;
-
- return result;
-}
-#endif
-
-/*
- * Update the values of the erase, interrupt, and kill characters in 'mode'.
- *
- * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
- * characters if they're unset, or if we specify them as options. This differs
- * from BSD 4.4 tset, which always sets erase.
- */
-static void
-set_control_chars(void)
-{
-#ifdef TERMIOS
- if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) {
- mode.c_cc[VERASE] = UChar((terasechar >= 0)
- ? terasechar
- : default_erase());
- }
-
- if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) {
- mode.c_cc[VINTR] = UChar((intrchar >= 0)
- ? intrchar
- : CINTR);
- }
-
- if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) {
- mode.c_cc[VKILL] = UChar((tkillchar >= 0)
- ? tkillchar
- : CKILL);
- }
-#endif
-}
-
-/*
- * Set up various conversions in 'mode', including parity, tabs, returns,
- * echo, and case, according to the termcap entry. If the program we're
- * running was named with a leading upper-case character, map external
- * uppercase to internal lowercase.
- */
-static void
-set_conversions(void)
-{
-#ifdef __OBSOLETE__
- /*
- * Conversion logic for some *really* ancient terminal glitches,
- * not supported in terminfo. Left here for succeeding generations
- * to marvel at.
- */
- if (tgetflag("UC")) {
-#ifdef IUCLC
- mode.c_iflag |= IUCLC;
- mode.c_oflag |= OLCUC;
-#endif
- } else if (tgetflag("LC")) {
-#ifdef IUCLC
- mode.c_iflag &= ~IUCLC;
- mode.c_oflag &= ~OLCUC;
-#endif
- }
- mode.c_iflag &= ~(PARMRK | INPCK);
- mode.c_lflag |= ICANON;
- if (tgetflag("EP")) {
- mode.c_cflag |= PARENB;
- mode.c_cflag &= ~PARODD;
- }
- if (tgetflag("OP")) {
- mode.c_cflag |= PARENB;
- mode.c_cflag |= PARODD;
- }
-#endif /* __OBSOLETE__ */
-
-#ifdef TERMIOS
-#ifdef ONLCR
- mode.c_oflag |= ONLCR;
-#endif
- mode.c_iflag |= ICRNL;
- mode.c_lflag |= ECHO;
-#ifdef OXTABS
- mode.c_oflag |= OXTABS;
-#endif /* OXTABS */
-
- /* test used to be tgetflag("NL") */
- if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
- /* Newline, not linefeed. */
-#ifdef ONLCR
- mode.c_oflag &= ~((unsigned) ONLCR);
-#endif
- mode.c_iflag &= ~((unsigned) ICRNL);
- }
-#ifdef __OBSOLETE__
- if (tgetflag("HD")) /* Half duplex. */
- mode.c_lflag &= ~ECHO;
-#endif /* __OBSOLETE__ */
-#ifdef OXTABS
- /* test used to be tgetflag("pt") */
- if (has_hardware_tabs) /* Print tabs. */
- mode.c_oflag &= ~OXTABS;
-#endif /* OXTABS */
- mode.c_lflag |= (ECHOE | ECHOK);
-#endif
-}
-
-/* Output startup string. */
-static void
-set_init(void)
-{
- char *p;
- bool settle;
-
-#ifdef __OBSOLETE__
- if (pad_char != (char *) 0) /* Get/set pad character. */
- PC = pad_char[0];
-#endif /* OBSOLETE */
-
-#ifdef TAB3
- if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
- oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
- SET_TTY(STDERR_FILENO, &oldmode);
- }
-#endif
- settle = set_tabs();
-
- if (isreset) {
- if ((p = reset_1string) != 0) {
- tputs(p, 0, outc);
- settle = TRUE;
- }
- if ((p = reset_2string) != 0) {
- tputs(p, 0, outc);
- settle = TRUE;
- }
- /* What about rf, rs3, as per terminfo man page? */
- /* also might be nice to send rmacs, rmul, rmm */
- if ((p = reset_file) != 0
- || (p = init_file) != 0) {
- cat(p);
- settle = TRUE;
- }
- }
-
- if (settle) {
- (void) putc('\r', stderr);
- (void) fflush(stderr);
- (void) napms(1000); /* Settle the terminal. */
- }
-}
-
-/*
- * Set the hardware tabs on the terminal, using the ct (clear all tabs),
- * st (set one tab) and ch (horizontal cursor addressing) capabilities.
- * This is done before if and is, so they can patch in case we blow this.
- * Return TRUE if we set any tab stops, FALSE if not.
- */
-static bool
-set_tabs(void)
-{
- if (set_tab && clear_all_tabs) {
- int c;
- int lim =
-#if HAVE_SIZECHANGE
- tcolumns
-#else
- columns
-#endif
- ;
-
- (void) putc('\r', stderr); /* Force to left margin. */
- tputs(clear_all_tabs, 0, outc);
-
- for (c = 8; c < lim; c += 8) {
- /* Get to the right column. In BSD tset, this
- * used to try a bunch of half-clever things
- * with cup and hpa, for an average saving of
- * somewhat less than two character times per
- * tab stop, less than .01 sec at 2400cps. We
- * lost all this cruft because it seemed to be
- * introducing some odd bugs.
- * -----------12345678----------- */
- (void) fputs(" ", stderr);
- tputs(set_tab, 0, outc);
- }
- putc('\r', stderr);
- return (TRUE);
- }
- return (FALSE);
-}
-