always send DSRCPR at init, use it to verify u7

for NCOPTION_PRESERVE_CURSOR, we want to know the location
of the cursor at startup. go ahead and always send a DSRCPR
in terminal interrogation. if we get a reply to it, hey, we
just verified that the terminal knows DSRCPR.

if we find a u7 value in terminfo that's different from the
standard DSRCPR, we ought send that in addition. #1816
pull/1838/head
nick black 3 years ago committed by Nick Black
parent 166212f234
commit 9f92986a6b

@ -106,6 +106,12 @@ typedef enum {
// registration of these signal handlers.
#define NCOPTION_NO_QUIT_SIGHANDLERS 0x0008
// Initialize the standard plane's virtual cursor to match the physical cursor
// at context creation time. Together with NCOPTION_NO_ALTERNATE_SCREEN and a
// scrolling standard plane, this facilitates easy scrolling-style programs in
// rendered mode.
#define NCOPTION_PRESERVE_CURSOR 0x0010ull
// Notcurses typically prints version info in notcurses_init() and performance
// info in notcurses_stop(). This inhibits that output.
#define NCOPTION_SUPPRESS_BANNERS 0x0020

@ -117,7 +117,7 @@ tinfo_debug_styles(struct ncplane* n, const char* indent){
// notcurses_render() without the alternate screen, no?
int main(void){
notcurses_options nopts = {
.flags = NCOPTION_NO_ALTERNATE_SCREEN,
.flags = NCOPTION_NO_ALTERNATE_SCREEN | NCOPTION_PRESERVE_CURSOR,
};
struct notcurses* nc = notcurses_init(&nopts, NULL);
if(nc == NULL){

@ -650,6 +650,8 @@ typedef enum {
STATE_XTSMGRAPHICS_DRAIN, // drain out XTSMGRAPHICS to 'S'
STATE_APPSYNC_REPORT, // got DECRPT ?2026
STATE_APPSYNC_REPORT_DRAIN, // drain out decrpt to 'y'
STATE_CURSOR, // reading row of cursor location to ';'
STATE_CURSOR_COL, // reading col of cursor location to 'R'
} initstates_e;
typedef struct query_state {
@ -661,12 +663,13 @@ typedef struct query_state {
// stringstate is the state at which this string was initialized, and can be
// one of STATE_XTVERSION1, STATE_XTGETTCAP_TERMNAME1, STATE_TDA1, and STATE_BG1
initstates_e state, stringstate;
int numeric; // currently-lexed numeric
char runstring[80]; // running string
size_t stridx; // position to write in string
uint32_t bg; // queried default background or 0
bool xtgettcap_good; // high when we've received DCS 1
bool appsync; // application-synchronized updates advertised
int numeric; // currently-lexed numeric
char runstring[80]; // running string
size_t stridx; // position to write in string
uint32_t bg; // queried default background or 0
int cursor_y, cursor_x;// cursor location
bool xtgettcap_good; // high when we've received DCS 1
bool appsync; // application-synchronized updates advertised
} query_state;
static int
@ -879,10 +882,38 @@ pump_control_read(query_state* inits, unsigned char c){
inits->state = STATE_DA; // could also be DECRPM/XTSMGRAPHICS
}else if(c == '>'){
inits->state = STATE_SDA;
}else if(isdigit(c)){
inits->numeric = 0;
inits->state = STATE_CURSOR;
}else if(c >= 0x40 && c <= 0x7E){
inits->state = STATE_NULL;
}
break;
case STATE_CURSOR:
if(isdigit(c)){
if(ruts_hex(&inits->numeric, c)){
return -1;
}
}else if(c == ';'){
inits->cursor_y = inits->numeric;
inits->state = STATE_CURSOR_COL;
inits->numeric = 0;
}else{
inits->state = STATE_NULL;
}
break;
case STATE_CURSOR_COL:
if(isdigit(c)){
if(ruts_hex(&inits->numeric, c)){
return -1;
}
}else if(c == 'R'){
inits->cursor_x = inits->numeric;
inits->state = STATE_NULL;
}else{
inits->state = STATE_NULL;
}
break;
case STATE_DCS: // terminated by ST
if(c == '\\'){
//fprintf(stderr, "terminated DCS\n");
@ -1168,7 +1199,7 @@ err:
}
int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
unsigned* appsync){
unsigned* appsync, int* cursor_y, int* cursor_x){
ncinputlayer* nilayer = &tcache->input;
setbuffer(infp, NULL, 0);
nilayer->inputescapes = NULL;
@ -1188,6 +1219,8 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
.tcache = tcache,
.state = STATE_NULL,
.qterm = TERMINAL_UNKNOWN,
.cursor_x = -1,
.cursor_y = -1,
};
if(control_read(csifd, &inits)){
input_free_esctrie(&nilayer->inputescapes);
@ -1198,6 +1231,8 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
tcache->termversion = inits.version;
*detected = inits.qterm;
*appsync = inits.appsync;
*cursor_x = inits.cursor_x;
*cursor_y = inits.cursor_y;
}
}
return 0;

@ -34,7 +34,8 @@ typedef enum {
// advertised support for application-sychronized updates, |appsync| will be
// non-zero.
int ncinputlayer_init(struct tinfo* tcache, FILE* infp,
queried_terminals_e* detected, unsigned* appsync);
queried_terminals_e* detected, unsigned* appsync,
int* cursor_y, int* cursor_x);
void ncinputlayer_stop(struct ncinputlayer* nilayer);

@ -150,6 +150,46 @@ grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
return 0;
}
// Device Attributes; replies with (depending on decTerminalID resource):
// ⇒ CSI ? 1 ; 2 c ("VT100 with Advanced Video Option")
// ⇒ CSI ? 1 ; 0 c ("VT101 with No Options")
// ⇒ CSI ? 4 ; 6 c ("VT132 with Advanced Video and Graphics")
// ⇒ CSI ? 6 c ("VT102")
// ⇒ CSI ? 7 c ("VT131")
// ⇒ CSI ? 1 2 ; Ps c ("VT125")
// ⇒ CSI ? 6 2 ; Ps c ("VT220")
// ⇒ CSI ? 6 3 ; Ps c ("VT320")
// ⇒ CSI ? 6 4 ; Ps c ("VT420")
// 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!
#define DSRCPR "\e[6n"
// 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.
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
if(blocking_write(fd, queries, strlen(queries))){
return -1;
}
return 0;
}
static int
init_terminfo_esc(tinfo* ti, const char* name, escape_e idx,
size_t* tablelen, size_t* tableused){
@ -164,14 +204,15 @@ init_terminfo_esc(tinfo* ti, const char* name, escape_e idx,
return 0;
}
// older kitty terminfo doesn't include u7. remove this when we can FIXME.
// if we get a response to the standard cursor locator escape, we know this
// terminal supports it, hah.
static int
add_u7_escape(tinfo* ti, size_t* tablelen, size_t* tableused){
const char* u7 = get_escape(ti, ESCAPE_DSRCPR);
if(u7){
return 0; // already present
}
if(grow_esc_table(ti, "\e[6n", ESCAPE_DSRCPR, tablelen, tableused)){
if(grow_esc_table(ti, DSRCPR, ESCAPE_DSRCPR, tablelen, tableused)){
return -1;
}
return 0;
@ -221,9 +262,6 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
if(add_smulx_escapes(ti, tablelen, tableused)){
return -1;
}
if(add_u7_escape(ti, tablelen, tableused)){
return -1;
}
}else if(qterm == TERMINAL_ALACRITTY){
termname = "Alacritty";
ti->caps.quadrants = true;
@ -286,41 +324,6 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
return 0;
}
// Device Attributes; replies with (depending on decTerminalID resource):
// ⇒ CSI ? 1 ; 2 c ("VT100 with Advanced Video Option")
// ⇒ CSI ? 1 ; 0 c ("VT101 with No Options")
// ⇒ CSI ? 4 ; 6 c ("VT132 with Advanced Video and Graphics")
// ⇒ CSI ? 6 c ("VT102")
// ⇒ CSI ? 7 c ("VT131")
// ⇒ CSI ? 1 2 ; Ps c ("VT125")
// ⇒ CSI ? 6 2 ; Ps c ("VT220")
// ⇒ CSI ? 6 3 ; Ps c ("VT320")
// ⇒ CSI ? 6 4 ; Ps c ("VT420")
// 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\\"
// 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.
static int
send_initial_queries(int fd){
const char queries[] = CSI_BGQ
"\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
if(blocking_write(fd, queries, strlen(queries))){
return -1;
}
return 0;
}
// termname is just the TERM environment variable. some details are not
// exposed via terminfo, and we must make heuristic decisions based on
// the detected terminal type, yuck :/.
@ -501,7 +504,9 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
}
}
unsigned appsync_advertised;
if(ncinputlayer_init(ti, stdin, &qterm, &appsync_advertised)){
int cursor_x = -1;
int cursor_y = -1;
if(ncinputlayer_init(ti, stdin, &qterm, &appsync_advertised, &cursor_y, &cursor_x)){
goto err;
}
if(nocbreak){
@ -512,6 +517,12 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
}
}
}
if(cursor_x >= 0 && cursor_y >= 0){
if(add_u7_escape(ti, &tablelen, &tableused)){
return -1;
}
// FIXME set cursor up
}
if(appsync_advertised){
if(add_appsync_escapes(ti, &tablelen, &tableused)){
goto err;

Loading…
Cancel
Save