diff --git a/src/lib/input.c b/src/lib/input.c index 4df7fb7c3..d6c265409 100644 --- a/src/lib/input.c +++ b/src/lib/input.c @@ -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, diff --git a/src/lib/internal.h b/src/lib/internal.h index 79f45eee8..1dce2583a 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -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 diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index 92356d88a..1ccfb1239 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -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");