Windows: on cygwin/msys2, use regular cursor lookup #2098

pull/2122/head
nick black 3 years ago
parent 8097b937c0
commit 83744f17bb

@ -38,10 +38,14 @@ int cbreak_mode(tinfo* ti){
return -1;
}
#else
// we don't yet have a way to take Cygwin/MSYS2 out of canonical mode. we'll
// hit this stanza in MSYS2; allow the GetConsoleMode() to fail for now. this
// means we'll need enter pressed after the query response, obviously an
// unacceptable state of affairs...FIXME
DWORD mode;
if(!GetConsoleMode(ti->inhandle, &mode)){
logerror("error acquiring input mode\n");
return -1;
return 0; // FIXME is it safe?
}
mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if(!SetConsoleMode(ti->inhandle, mode)){
@ -1649,7 +1653,9 @@ control_read(int ttyfd, query_state* qstate){
}
errno = 0;
do{
loginfo("reading replies from %d...\n", ttyfd);
while((s = read(ttyfd, buf, BUFSIZ)) != -1){
loginfo("read %lld from %d\n", (long long)s, ttyfd);
for(ssize_t idx = 0; idx < s ; ++idx){
int r = pump_control_read(qstate, buf[idx]);
if(r == 1){ // success!
@ -1679,7 +1685,7 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
nilayer->inputescapes = NULL;
nilayer->infd = fileno(infp);
loginfo("input fd: %d\n", nilayer->infd);
nilayer->ttyfd = isatty(nilayer->infd) ? -1 : get_tty_fd(infp);
nilayer->ttyfd = tty_check(nilayer->infd) ? -1 : get_tty_fd(infp);
if(*detected == TERMINAL_MSTERMINAL){
if(prep_windows_special_keys(nilayer)){
return -1;
@ -1698,7 +1704,7 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
nilayer->inner_wants_data = false;
pthread_cond_init(&nilayer->creport_cond, NULL);
int csifd = nilayer->ttyfd >= 0 ? nilayer->ttyfd : nilayer->infd;
if(isatty(csifd)){
if(tty_check(csifd)){
query_state inits = {
.tcache = tcache,
.state = STATE_NULL,

@ -1733,6 +1733,18 @@ prefix_data(const char* base){
return path;
}
// within unix, we can just use isatty(3). on windows, things work
// differently. for a true Windows Terminal, we'll have HANDLE pointers
// rather than file descriptors. in cygwin/msys2, isatty(3) always fails.
// so for __MINGW64__, always return true. otherwise return isatty(fd).
static inline int
tty_check(int fd){
#ifdef __MINGW64__
return fd >= 0 ? 1 : 0;
#endif
return isatty(fd);
}
#undef ALLOC
#undef API

@ -931,7 +931,6 @@ char* termdesc_longterm(const tinfo* ti){
return ret;
}
#ifndef __MINGW64__
// when we have input->ttyfd, everything's simple -- we're reading from a
// different source than the user is, so we can just write the query, and block
// on the response, easy peasy.
@ -962,61 +961,62 @@ locate_cursor_simple(int fd, const char* u7, int* cursor_y, int* cursor_x){
loginfo("Located cursor with %d: %d/%d\n", fd, *cursor_y, *cursor_x);
return 0;
}
#endif
// send a u7 request, and wait until we have a cursor report. if input's ttyfd
// is valid, we can just camp there. otherwise, we need dance with potential
// user input looking at infd.
int locate_cursor(tinfo* ti, int* cursor_y, int* cursor_x){
#ifndef __MINGW64__
const char* u7 = get_escape(ti, ESCAPE_U7);
if(u7 == NULL){
logwarn("No support in terminfo\n");
return -1;
}
if(ti->input.ttyfd >= 0){
return locate_cursor_simple(ti->input.ttyfd, u7, cursor_y, cursor_x);
}
int fd = ti->input.infd;
if(fd < 0){
logwarn("No valid path for cursor report\n");
return -1;
}
bool emitted_u7 = false; // only want to send one max
cursorreport* clr;
loginfo("Acquiring input lock\n");
pthread_mutex_lock(&ti->input.lock);
while((clr = ti->input.creport_queue) == NULL){
logdebug("No report yet\n");
if(!emitted_u7){
logdebug("Emitting u7\n");
// FIXME i'd rather not do this while holding the lock =[
if(tty_emit(u7, fd)){
pthread_mutex_unlock(&ti->input.lock);
return -1;
if(ti->qterm != TERMINAL_MSTERMINAL){
const char* u7 = get_escape(ti, ESCAPE_U7);
if(u7 == NULL){
logwarn("No support in terminfo\n");
return -1;
}
if(ti->ttyfd >= 0){
return locate_cursor_simple(ti->ttyfd, u7, cursor_y, cursor_x);
}
int fd = ti->input.infd;
if(fd < 0){
logwarn("No valid path for cursor report\n");
return -1;
}
bool emitted_u7 = false; // only want to send one max
cursorreport* clr;
loginfo("Acquiring input lock\n");
pthread_mutex_lock(&ti->input.lock);
while((clr = ti->input.creport_queue) == NULL){
logdebug("No report yet\n");
if(!emitted_u7){
logdebug("Emitting u7\n");
// FIXME i'd rather not do this while holding the lock =[
if(tty_emit(u7, fd)){
pthread_mutex_unlock(&ti->input.lock);
return -1;
}
emitted_u7 = true;
}
emitted_u7 = true;
// this can block. we must enter holding the input lock, and it will
// return to us holding the input lock.
ncinput_extract_clrs(ti);
if( (clr = ti->input.creport_queue) ){
break;
}
pthread_cond_wait(&ti->input.creport_cond, &ti->input.lock);
}
// this can block. we must enter holding the input lock, and it will
// return to us holding the input lock.
ncinput_extract_clrs(ti);
if( (clr = ti->input.creport_queue) ){
break;
ti->input.creport_queue = clr->next;
pthread_mutex_unlock(&ti->input.lock);
loginfo("Got a report from %d %d/%d\n", fd, clr->y, clr->x);
*cursor_y = clr->y;
*cursor_x = clr->x;
if(ti->inverted_cursor){
int tmp = *cursor_y;
*cursor_y = *cursor_x;
*cursor_x = tmp;
}
pthread_cond_wait(&ti->input.creport_cond, &ti->input.lock);
}
ti->input.creport_queue = clr->next;
pthread_mutex_unlock(&ti->input.lock);
loginfo("Got a report from %d %d/%d\n", fd, clr->y, clr->x);
*cursor_y = clr->y;
*cursor_x = clr->x;
if(ti->inverted_cursor){
int tmp = *cursor_y;
*cursor_y = *cursor_x;
*cursor_x = tmp;
}
free(clr);
#else
free(clr);
return 0;
}
#ifdef __MINGW64__
CONSOLE_SCREEN_BUFFER_INFO conbuf;
if(!GetConsoleScreenBufferInfo(ti->outhandle, &conbuf)){
logerror("couldn't get cursor info\n");

Loading…
Cancel
Save