From b1bee31d6196eb9ce4b74be7b818c9cff31fc4ec Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 7 Apr 2021 10:07:26 +0200 Subject: [PATCH] Helper functions for setting TTY in raw and cooked mode Signed-off-by: Joachim Wiberg --- src/util.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 4 ++++ 2 files changed, 68 insertions(+) diff --git a/src/util.c b/src/util.c index de880c0d..745ff95a 100644 --- a/src/util.c +++ b/src/util.c @@ -41,6 +41,22 @@ #include /* strlcat() */ #include "util.h" +#ifdef HAVE_TERMIOS_H +/* + * This flag is used on *BSD when calling tcsetattr() to prevent it + * from changing speed, duplex, parity. GNU says we should use the + * CIGNORE flag to c_cflag, but that doesn't exist so ... we rely on + * our initial tcgetattr() and prey that nothing changes on the TTY + * before we exit and restore with tcsetattr() + */ +#ifndef TCSASOFT +#define TCSASOFT 0 +#endif + +static struct termios ttold; +static struct termios ttnew; +#endif + int ttrows = 24; int ttcols = 80; char *prognm = NULL; @@ -308,6 +324,54 @@ int ttinit(void) return ttcols; } + +/* + * This function sets the terminal to RAW mode, as defined for the current + * shell. This is called both by ttopen() above and by spawncli() to + * get the current terminal settings and then change them to what + * mg expects. Thus, tty changes done while spawncli() is in effect + * will be reflected in mg. + */ +int ttraw(void) +{ + if (tcgetattr(0, &ttold) == -1) { + fprintf(stderr, "%s: failed querying tty attrs: %s\n", + prognm, strerror(errno)); + return 1; + } + + (void)memcpy(&ttnew, &ttold, sizeof(ttnew)); + /* Set terminal to 'raw' mode and ignore a 'break' */ + ttnew.c_cc[VMIN] = 1; + ttnew.c_cc[VTIME] = 0; + ttnew.c_iflag |= IGNBRK; + ttnew.c_iflag &= ~(BRKINT | PARMRK | INLCR | IGNCR | ICRNL | IXON); + ttnew.c_oflag &= ~OPOST; + ttnew.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); + + if (tcsetattr(0, TCSASOFT | TCSADRAIN, &ttnew) == -1) { + fprintf(stderr, "%s: failed setting tty in raw mode: %s\n", + prognm, strerror(errno)); + return 1; + } + + return 0; +} + +/* + * This function restores all terminal settings to their default values, + * in anticipation of exiting or suspending the editor. + */ +int ttcooked(void) +{ + if (tcsetattr(0, TCSASOFT | TCSADRAIN, &ttold) == -1) { + fprintf(stderr, "%s: failed restoring tty to cooked mode: %s\n", + prognm, strerror(errno)); + return 1; + } + + return 0; +} #endif /* HAVE_TERMIOS_H */ /** diff --git a/src/util.h b/src/util.h index 5f038fc7..9d37d24e 100644 --- a/src/util.h +++ b/src/util.h @@ -62,8 +62,12 @@ char *sanitize (char *arg, size_t len); #ifdef HAVE_TERMIOS_H int ttinit (void); +int ttraw (void); +int ttcooked (void); #else #define ttinit() ttcols +#define ttraw() 0 +#define ttcooked() 0 #endif static inline char *strterm(char *str, size_t len)