Windows: implement cbreak_mode() #2096

pull/2122/head
nick black 3 years ago
parent b46f4aed8d
commit 5d0eeb7ec4
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -20,14 +20,15 @@ void sigwinch_handler(int signo){
resize_seen = signo;
}
int cbreak_mode(int ttyfd, const struct termios* tpreserved){
int cbreak_mode(tinfo* ti){
#ifndef __MINGW64__
int ttyfd = ti->ttyfd;
if(ttyfd < 0){
return 0;
}
// assume it's not a true terminal (e.g. we might be redirected to a file)
struct termios modtermios;
memcpy(&modtermios, tpreserved, sizeof(modtermios));
memcpy(&modtermios, ti->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
@ -41,7 +42,17 @@ int cbreak_mode(int ttyfd, const struct termios* tpreserved){
}
return 0;
#else
return -1; // FIXME
DWORD mode;
if(!GetConsoleMode(ti->inhandle, &mode)){
logerror("error acquiring input mode\n");
return -1;
}
mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if(!SetConsoleMode(ti->inhandle, mode)){
logerror("error setting input mode\n");
return -1;
}
return 0;
#endif
}

@ -52,7 +52,7 @@ int ncinputlayer_init(struct tinfo* tcache, FILE* infp,
void ncinputlayer_stop(struct ncinputlayer* nilayer);
// FIXME absorb into ncinputlayer_init()
int cbreak_mode(int ttyfd, const struct termios* tpreserved);
int cbreak_mode(struct tinfo* ti);
// assuming the user context is not active, go through current data looking
// for a cursor location report. if we find none, block on input, and read if

@ -255,7 +255,6 @@ int update_term_dimensions(int* rows, int* cols, tinfo* tcache, int margin_b){
}
return 0;
}
// FIXME
#ifndef __MINGW64__
struct winsize ws;
int i = ioctl(tcache->ttyfd, TIOCGWINSZ, &ws);
@ -300,10 +299,9 @@ int update_term_dimensions(int* rows, int* cols, tinfo* tcache, int margin_b){
}
}
#else
/*
CONSOLE_SCREEN_BUFFER_INFO csbi;
int columns, rows;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)){
if(GetConsoleScreenBufferInfo(tcache->inhandle, &csbi)){
if(cols){
*cols = csbi.srWindow.Right - csbi.srWindow.Left + 1;
}
@ -311,14 +309,13 @@ int update_term_dimensions(int* rows, int* cols, tinfo* tcache, int margin_b){
*rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
}
}else{
*/
if(rows){
*rows = tcache->default_rows;
}
if(cols){
*cols = tcache->default_cols;
}
//}
}
#endif
if(tcache->sixel_maxy_pristine){
int sixelrows = *rows - 1;

@ -694,20 +694,20 @@ int interrogate_terminfo(tinfo* ti, const char* termtype, FILE* out, unsigned ut
}
if(tcgetattr(ti->ttyfd, ti->tpreserved)){
logpanic("Couldn't preserve terminal state for %d (%s)\n", ti->ttyfd, strerror(errno));
free(ti->tpreserved);
free(ti->tpreserved);
return -1;
}
// enter cbreak mode regardless of user preference until we've performed
// terminal interrogation. at that point, we might restore original mode.
if(cbreak_mode(ti->ttyfd, ti->tpreserved)){
free(ti->tpreserved);
if(cbreak_mode(ti)){
free(ti->tpreserved);
return -1;
}
// if we already know our terminal (e.g. on the linux console), there's no
// need to send the identification queries. the controls are sufficient.
bool minimal = (ti->qterm != TERMINAL_UNKNOWN);
if(send_initial_queries(ti->ttyfd, minimal)){
free(ti->tpreserved);
free(ti->tpreserved);
return -1;
}
}

@ -200,6 +200,9 @@ typedef struct tinfo {
char* linux_fb_dev; // device corresponding to linux_fb_dev
uint8_t* linux_fbuffer; // mmap()ed framebuffer
size_t linux_fb_len; // size of map
#elif defined(__MINGW64__)
HANDLE inhandle;
HANDLE outhandle;
#endif
// some terminals (e.g. kmscon) return cursor coordinates inverted from the

@ -43,6 +43,16 @@ int prepare_windows_terminal(tinfo* ti, size_t* tablelen, size_t* tableused){
}
ti->caps.rgb = true;
ti->caps.colors = 256;
ti->inhandle = GetStdHandle(STD_INPUT_HANDLE);
ti->outhandle = GetStdHandle(STD_OUTPUT_HANDLE);
if(ti->inhandle == INVALID_HANDLE_VALUE){
logerror("couldn't get input handle\n");
return -1;
}
if(ti->outhandle == INVALID_HANDLE_VALUE){
logerror("couldn't get output handle\n");
return -1;
}
if(!SetConsoleOutputCP(65001)){
logerror("couldn't set output page to utf8\n");
return -1;
@ -51,34 +61,29 @@ int prepare_windows_terminal(tinfo* ti, size_t* tablelen, size_t* tableused){
logerror("couldn't set input page to utf8\n");
return -1;
}
HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
if(in == INVALID_HANDLE_VALUE){
logerror("couldn't get input handle\n");
return -1;
}
// if we're a true Windows Terminal, SetConsoleMode() ought succeed.
// otherwise, we're something else; go ahead and query.
// disable: ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT
if(!SetConsoleMode(in, ENABLE_MOUSE_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_QUICK_EDIT_MODE
| ENABLE_EXTENDED_FLAGS
| ENABLE_WINDOW_INPUT
| ENABLE_VIRTUAL_TERMINAL_INPUT)){
logerror("couldn't set input console mode\n");
// otherwise, we're something else; go ahead and try.
if(!SetConsoleMode(ti->outhandle, ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
| DISABLE_NEWLINE_AUTO_RETURN
| ENABLE_LVB_GRID_WORLDWIDE)){
logerror("couldn't set output console mode\n");
return -1;
}
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
if(out == INVALID_HANDLE_VALUE){
logerror("couldn't get output handle\n");
DWORD inmode;
if(!GetConsoleMode(ti->inhandle, &inmode)){
logerror("couldn't get input console mode\n");
return -1;
}
if(!SetConsoleMode(out, ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
| DISABLE_NEWLINE_AUTO_RETURN
| ENABLE_LVB_GRID_WORLDWIDE)){
logerror("couldn't set output console mode\n");
// we don't explicitly disable ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT
// yet; those are handled in cbreak_mode(). just get ENABLE_INSERT_MODE.
inmode &= ~ENABLE_INSERT_MODE;
inmode |= ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT
| ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS
| ENABLE_WINDOW_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT;
if(!SetConsoleMode(ti->inhandle, inmode)){
logerror("couldn't set input console mode\n");
return -1;
}
ti->caps.quadrants = true;

Loading…
Cancel
Save