direct mode: use cbreak mode for terminal

* factor out cbreak_mode() #919
* call it from direct mode when we have a terminal fd
* restore the terminal state in ncdirect_stop()
pull/966/head
nick black 4 years ago committed by Nick Black
parent 8595c21495
commit 4b037bc4b8

@ -426,7 +426,12 @@ ncdirect* ncdirect_init(const char* termtype, FILE* outfp){
ret->ttyfp = outfp;
memset(&ret->palette, 0, sizeof(ret->palette));
// we don't need a controlling tty for everything we do; allow a failure here
ret->ctermfd = get_controlling_tty(ret->ttyfp);
if((ret->ctermfd = get_controlling_tty(ret->ttyfp)) >= 0){
if(cbreak_mode(ret->ctermfd, &ret->tpreserved)){
delete(ret);
return nullptr;
}
}
int termerr;
if(setupterm(termtype, ret->ctermfd, &termerr) != OK){
fprintf(stderr, "Terminfo error %d (see terminfo(3ncurses))\n", termerr);
@ -468,6 +473,7 @@ int ncdirect_stop(ncdirect* nc){
if(nc->tcache.cnorm && tty_emit("cnorm", nc->tcache.cnorm, nc->ctermfd)){
ret = -1;
}
tcsetattr(nc->ctermfd, TCSANOW, &nc->tpreserved);
ret |= close(nc->ctermfd);
}
delete(nc);

@ -261,6 +261,7 @@ typedef struct ncdirect {
uint16_t stylemask; // current styles
bool fgdefault, bgdefault; // are FG/BG currently using default colors?
bool utf8; // are we using utf-8 encoding, as hoped?
struct termios tpreserved; // terminal state upon entry
} ncdirect;
typedef struct notcurses {
@ -966,6 +967,8 @@ cellcmp_and_dupfar(egcpool* dampool, cell* damcell,
return 1;
}
int cbreak_mode(int ttyfd, struct termios* tpreserved);
#ifdef __cplusplus
}
#endif

@ -819,6 +819,28 @@ get_tty_fd(notcurses* nc, FILE* ttyfp){
return fd;
}
int cbreak_mode(int ttyfd, struct termios* tpreserved){
if(tcgetattr(ttyfd, tpreserved)){
fprintf(stderr, "Couldn't preserve terminal state for %d (%s)\n", ttyfd, strerror(errno));
return -1;
}
// assume it's not a true terminal (e.g. we might be redirected to a file)
struct termios modtermios;
memcpy(&modtermios, tpreserved, sizeof(modtermios));
// see termios(3). disabling ECHO and ICANON means input will not be echoed
// to the screen, input is made available without enter-based buffering, and
// line editing is disabled. since we have not gone into raw mode, ctrl+c
// etc. still have their typical effects. ICRNL maps return to 13 (Ctrl+M)
// instead of 10 (Ctrl+J).
modtermios.c_lflag &= (~ECHO & ~ICANON);
modtermios.c_iflag &= (~ICRNL);
if(tcsetattr(ttyfd, TCSANOW, &modtermios)){
fprintf(stderr, "Error disabling echo / canonical on %d (%s)\n", ttyfd, strerror(errno));
return -1;
}
return 0;
}
notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
notcurses_options defaultopts;
memset(&defaultopts, 0, sizeof(defaultopts));
@ -893,27 +915,9 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
is_linux_console(ret, !!(opts->flags & NCOPTION_NO_FONT_CHANGES));
notcurses_mouse_disable(ret);
if(ret->ttyfd >= 0){
if(tcgetattr(ret->ttyfd, &ret->tpreserved)){
logerror(ret, "Couldn't preserve terminal state for %d (%s)\n", ret->ttyfd, strerror(errno));
if(cbreak_mode(ret->ttyfd, &ret->tpreserved)){
free(ret);
return NULL;
// assume it's not a true terminal (e.g. we might be redirected to a file)
}else{
struct termios modtermios;
memcpy(&modtermios, &ret->tpreserved, sizeof(modtermios));
// see termios(3). disabling ECHO and ICANON means input will not be echoed
// to the screen, input is made available without enter-based buffering, and
// line editing is disabled. since we have not gone into raw mode, ctrl+c
// etc. still have their typical effects. ICRNL maps return to 13 (Ctrl+M)
// instead of 10 (Ctrl+J).
modtermios.c_lflag &= (~ECHO & ~ICANON);
modtermios.c_iflag &= (~ICRNL);
if(tcsetattr(ret->ttyfd, TCSANOW, &modtermios)){
fprintf(stderr, "Error disabling echo / canonical on %d (%s)\n",
ret->ttyfd, strerror(errno));
free(ret);
return NULL;
}
}
}
if(setup_signals(ret,

Loading…
Cancel
Save