From 7c72bb55edd47e593896d48699ccb4866f0cc52b Mon Sep 17 00:00:00 2001 From: nick black Date: Tue, 29 Jun 2021 05:53:38 -0400 Subject: [PATCH] When terminal is identified, send minimal queries We might have already unambiguously identified our terminal by the time we start probing (the Linux console, for instance, is identified via ioctl()s). If we have, we still want to send non-identification-related queries in, particularly to get the cursor position. This fixes up notcurses-info on the Linux console (#1837). --- src/lib/input.c | 48 ++++++++++++++++++++++----------------------- src/lib/termdesc.c | 49 ++++++++++++++++++++++++++++------------------ 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/lib/input.c b/src/lib/input.c index c3a688afa..2a7069761 100644 --- a/src/lib/input.c +++ b/src/lib/input.c @@ -1213,31 +1213,29 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected, nilayer->inputbuf_valid_starts = 0; nilayer->inputbuf_write_at = 0; nilayer->input_events = 0; - if(*detected == TERMINAL_UNKNOWN){ - int csifd = nilayer->ttyfd >= 0 ? nilayer->ttyfd : nilayer->infd; - if(isatty(csifd)){ - query_state inits = { - .tcache = tcache, - .state = STATE_NULL, - .qterm = TERMINAL_UNKNOWN, - .cursor_x = -1, - .cursor_y = -1, - }; - if(control_read(csifd, &inits)){ - input_free_esctrie(&nilayer->inputescapes); - free(inits.version); - return -1; - } - tcache->bg_collides_default = inits.bg; - tcache->termversion = inits.version; - *detected = inits.qterm; - *appsync = inits.appsync; - if(cursor_x){ - *cursor_x = inits.cursor_x - 1; - } - if(cursor_y){ - *cursor_y = inits.cursor_y - 1; - } + int csifd = nilayer->ttyfd >= 0 ? nilayer->ttyfd : nilayer->infd; + if(isatty(csifd)){ + query_state inits = { + .tcache = tcache, + .state = STATE_NULL, + .qterm = TERMINAL_UNKNOWN, + .cursor_x = -1, + .cursor_y = -1, + }; + if(control_read(csifd, &inits)){ + input_free_esctrie(&nilayer->inputescapes); + free(inits.version); + return -1; + } + tcache->bg_collides_default = inits.bg; + tcache->termversion = inits.version; + *detected = inits.qterm; + *appsync = inits.appsync; + if(cursor_x){ + *cursor_x = inits.cursor_x - 1; + } + if(cursor_y){ + *cursor_y = inits.cursor_y - 1; } } return 0; diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index b6f7c96b3..86e285fa7 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -250,29 +250,41 @@ grow_esc_table(tinfo* ti, const char* tstr, escape_e esc, // ⇒ CSI ? 6 3 ; Ps c ("VT320") // ⇒ CSI ? 6 4 ; Ps c ("VT420") +// these three queries (terminated with a Primary Device Attributes, to which +// all known terminals reply) hopefully can uniquely and unquestionably +// identify the terminal to which we are talking. +#define IDQUERIES "\x1b[=0c" /* Tertiary Device Attributes */ \ + "\x1b[>0q" /* XTVERSION */ \ + "\x1bP+q544e\x1b\\" /* XTGETTCAP['TN'] */ + // query background, replies in X color https://www.x.org/releases/X11R7.7/doc/man/man7/X.7.xhtml#heading11 #define CSI_BGQ "\e]11;?\e\\" -// ought be using the u7 terminfo string here, if it exists. the great thing -// is, if we get a response to this, we know we can use it for u7! +// FIXME ought be using the u7 terminfo string here, if it exists. the great +// thing is, if we get a response to this, we know we can use it for u7! #define DSRCPR "\e[6n" +#define DIRECTIVES CSI_BGQ \ + DSRCPR \ + "\x1b[?2026$p" /* query for Synchronized Updates */ \ + "\x1b[?1;3;256S" /* try to set 256 cregs */ \ + "\x1b[?2;1;0S" /* XTSMGRAPHICS (cregs) */ \ + "\x1b[?1;1;0S" /* XTSMGRAPHICS (geometry) */ \ + "\x1b[c" /* Device Attributes */ + // we send an XTSMGRAPHICS to set up 256 color registers (the most we can // currently take advantage of; we need at least 64 to use sixel at all. // maybe that works, maybe it doesn't. then query both color registers -// and geometry. send XTGETTCAP for terminal name. +// and geometry. send XTGETTCAP for terminal name. if 'minimal' is set, don't +// send any identification queries. static int -send_initial_queries(int fd){ - const char queries[] = CSI_BGQ - DSRCPR - "\x1b[?2026$p" // query for App-sync updates - "\x1b[=0c" // Tertiary Device Attributes - "\x1b[>0q" // XTVERSION - "\x1bP+q544e\x1b\\" // XTGETTCAP['TN'] - "\x1b[?1;3;256S" // try to set 256 cregs - "\x1b[?2;1;0S" // XTSMGRAPHICS (cregs) - "\x1b[?1;1;0S" // XTSMGRAPHICS (geometry) - "\x1b[c"; // Device Attributes +send_initial_queries(int fd, bool minimal){ + const char *queries; + if(minimal){ + queries = DIRECTIVES; + }else{ + queries = IDQUERIES DIRECTIVES; + } if(blocking_write(fd, queries, strlen(queries))){ return -1; } @@ -504,11 +516,10 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8, } } if(fd >= 0){ - if(qterm == TERMINAL_UNKNOWN){ - if(send_initial_queries(fd)){ - fprintf(stderr, "Error issuing terminal queries on %d\n", fd); - return -1; - } + bool minimal = (qterm != TERMINAL_UNKNOWN); + if(send_initial_queries(fd, minimal)){ + fprintf(stderr, "Error issuing terminal queries on %d\n", fd); + return -1; } if(tcgetattr(fd, &ti->tpreserved)){ fprintf(stderr, "Couldn't preserve terminal state for %d (%s)\n", fd, strerror(errno));