From 73324ce2a495aff299044a6179a440092a171eef Mon Sep 17 00:00:00 2001 From: nick black Date: Sun, 11 Jul 2021 00:43:36 -0400 Subject: [PATCH] yank locate_cursor_early() #1692 --- src/lib/direct.c | 69 +++++++++++++++++++++++++++++++++++ src/lib/notcurses.c | 4 +-- src/lib/termdesc.c | 88 --------------------------------------------- src/lib/termdesc.h | 6 +--- 4 files changed, 72 insertions(+), 95 deletions(-) diff --git a/src/lib/direct.c b/src/lib/direct.c index bec438deb..8abf976e0 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -179,6 +179,75 @@ int ncdirect_cursor_disable(ncdirect* nc){ return -1; } +static int +cursor_yx_get(int ttyfd, const char* u7, int* y, int* x){ + if(tty_emit(u7, ttyfd)){ + return -1; + } + bool done = false; + enum { // what we expect now + CURSOR_ESC, // 27 (0x1b) + CURSOR_LSQUARE, + CURSOR_ROW, // delimited by a semicolon + CURSOR_COLUMN, + CURSOR_R, + } state = CURSOR_ESC; + int row = 0, column = 0; + int r; + char in; + do{ + while((r = read(ttyfd, &in, 1)) == 1){ + bool valid = false; + switch(state){ + case CURSOR_ESC: valid = (in == NCKEY_ESC); state = CURSOR_LSQUARE; break; + case CURSOR_LSQUARE: valid = (in == '['); state = CURSOR_ROW; break; + case CURSOR_ROW: + if(isdigit(in)){ + row *= 10; + row += in - '0'; + valid = true; + }else if(in == ';'){ + state = CURSOR_COLUMN; + valid = true; + } + break; + case CURSOR_COLUMN: + if(isdigit(in)){ + column *= 10; + column += in - '0'; + valid = true; + }else if(in == 'R'){ + state = CURSOR_R; + valid = true; + } + break; + case CURSOR_R: default: // logical error, whoops + break; + } + if(!valid){ + logerror("Unexpected result (%c, %d) from terminal\n", in, in); + break; + } + if(state == CURSOR_R){ + done = true; + break; + } + } + // need to loop 0 to handle slow terminals, see for instance screen =[ + }while(!done && (r >= 0 || (errno == EINTR || errno == EAGAIN || errno == EBUSY))); + if(!done){ + logerror("Error reading cursor location\n"); + return -1; + } + if(y){ + *y = row; + } + if(x){ + *x = column; + } + return 0; +} + // if we're lacking hpa/vpa, *and* -1 is passed for one of x/y, *and* we've // not got a real ctermfd, we're pretty fucked. we just punt and substitute // 0 for that case, which hopefully only happens when running headless unit diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 7fa7e1dd5..663289131 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1169,8 +1169,8 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){ goto err; } if(ret->rstate.logendy >= 0){ // if either is set, both are - if(!ret->suppress_banner){ - if(locate_cursor_early(ret, &ret->rstate.logendy, &ret->rstate.logendx)){ + if(!ret->suppress_banner && ret->ttyfd >= 0){ + if(locate_cursor(&ret->tcache, ret->ttyfd, &ret->rstate.logendy, &ret->rstate.logendx)){ free_plane(ret->stdplane); goto err; } diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index 78df45ec7..bda356995 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -771,74 +771,6 @@ char* termdesc_longterm(const tinfo* ti){ return ret; } -int cursor_yx_get(int ttyfd, const char* u7, int* y, int* x){ - if(tty_emit(u7, ttyfd)){ - return -1; - } - bool done = false; - enum { // what we expect now - CURSOR_ESC, // 27 (0x1b) - CURSOR_LSQUARE, - CURSOR_ROW, // delimited by a semicolon - CURSOR_COLUMN, - CURSOR_R, - } state = CURSOR_ESC; - int row = 0, column = 0; - int r; - char in; - do{ - while((r = read(ttyfd, &in, 1)) == 1){ - bool valid = false; - switch(state){ - case CURSOR_ESC: valid = (in == NCKEY_ESC); state = CURSOR_LSQUARE; break; - case CURSOR_LSQUARE: valid = (in == '['); state = CURSOR_ROW; break; - case CURSOR_ROW: - if(isdigit(in)){ - row *= 10; - row += in - '0'; - valid = true; - }else if(in == ';'){ - state = CURSOR_COLUMN; - valid = true; - } - break; - case CURSOR_COLUMN: - if(isdigit(in)){ - column *= 10; - column += in - '0'; - valid = true; - }else if(in == 'R'){ - state = CURSOR_R; - valid = true; - } - break; - case CURSOR_R: default: // logical error, whoops - break; - } - if(!valid){ - logerror("Unexpected result (%c, %d) from terminal\n", in, in); - break; - } - if(state == CURSOR_R){ - done = true; - break; - } - } - // need to loop 0 to handle slow terminals, see for instance screen =[ - }while(!done && (r >= 0 || (errno == EINTR || errno == EAGAIN || errno == EBUSY))); - if(!done){ - logerror("Error reading cursor location\n"); - return -1; - } - if(y){ - *y = row; - } - if(x){ - *x = column; - } - return 0; -} - // send a u7 request, and wait until we have a cursor report int locate_cursor(tinfo* ti, int fd, int* cursor_y, int* cursor_x){ if(fd < 0){ @@ -874,23 +806,3 @@ int locate_cursor(tinfo* ti, int fd, int* cursor_y, int* cursor_x){ } return 0; } - -int locate_cursor_early(struct notcurses* nc, int* cursor_y, int* cursor_x){ - int ret = 0; - if(nc->ttyfd >= 0){ - const char* u7 = get_escape(&nc->tcache, ESCAPE_DSRCPR); - // FIXME ought check for cursor inversion! - ret = cursor_yx_get(nc->ttyfd, u7, cursor_y, cursor_x); - if(ret == 0){ - if(nc->tcache.inverted_cursor){ - int tmp = *cursor_y; - *cursor_y = *cursor_x; - *cursor_x = tmp; - } - // we use 0-based coordinates, but known terminals use 1-based coordinates - --*cursor_y; - --*cursor_x; - } - } - return ret; -} diff --git a/src/lib/termdesc.h b/src/lib/termdesc.h index 226c03981..9ce95c01d 100644 --- a/src/lib/termdesc.h +++ b/src/lib/termdesc.h @@ -213,11 +213,7 @@ void free_terminfo_cache(tinfo* ti); // return a heap-allocated copy of termname + termversion char* termdesc_longterm(const tinfo* ti); -// get the cursor location early (after interrogate_terminfo(), but before -// handing control back to the user). blocking call. FIXME this should go away -// once we have proper input handling that separates out control sequences. -int locate_cursor_early(struct notcurses* nc, int* cursor_y, int* cursor_x); -int cursor_yx_get(int ttyfd, const char* u7, int* y, int* x); +int locate_cursor(tinfo* ti, int fd, int* cursor_y, int* cursor_x); #ifdef __cplusplus }