nick black 3 years ago
parent 6e19e0536e
commit b170ee98e1
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -633,6 +633,8 @@ typedef enum {
STATE_TDA2, // tertiary DA, got '|', first hex nibble
STATE_TDA3, // tertiary DA, second hex nibble
STATE_SDA, // secondary DA (CSI > Pp ; Pv ; Pc c)
STATE_SDA_VER, // secondary DA, got semi, reading to next semi
STATE_SDA_DRAIN, // drain secondary DA to 'c'
STATE_DA, // primary DA (CSI ? ... c) OR XTSMGRAPHICS OR DECRPM
STATE_DA_1, // got '1', XTSMGRAPHICS color registers or primary DA
STATE_DA_1_SEMI, // got '1;'
@ -817,6 +819,32 @@ stash_string(query_state* inits){
return 0;
}
// use the version extracted from Secondary Device Attributes, assuming that
// it is Alacritty (we ought check the specified terminfo database entry).
// Alacritty writes its crate version with each more significant portion
// multiplied by 100^{portion ID}, where major, minor, patch are 2, 1, 0.
// what happens when a component exceeds 99? who cares. support XTVERSION.
static char*
set_sda_version(query_state* inits){
int maj, min, patch;
if(inits->numeric <= 0){
return NULL;
}
maj = inits->numeric / 10000;
min = (inits->numeric % 10000) / 100;
patch = inits->numeric % 100;
if(maj >= 100 || min >= 100 || patch >= 100){
return NULL;
}
// 3x components (two digits max each), 2x '.', NUL would suggest 9 bytes,
// but older gcc __builtin___sprintf_chk insists on 13. fuck it. FIXME.
char* buf = malloc(13);
if(buf){
sprintf(buf, "%d.%d.%d", maj, min, patch);
}
return buf;
}
// FIXME ought implement the full Williams automaton
// FIXME sloppy af in general
// returns 1 after handling the Device Attributes response, 0 if more input
@ -880,7 +908,15 @@ pump_control_read(query_state* inits, unsigned char c){
if(c == '?'){
inits->state = STATE_DA; // could also be DECRPM/XTSMGRAPHICS
}else if(c == '>'){
inits->state = STATE_SDA;
// SDA yields up Alacritty's crate version, but it doesn't unambiguously
// identify Alacritty. If we've got any other version information, skip
// directly to STATE_SDA_DRAIN, rather than doing STATE_SDA_VER.
if(inits->qterm || inits->version){
loginfo("Identified terminal already; ignoring DA2\n");
inits->state = STATE_SDA_DRAIN;
}else{
inits->state = STATE_SDA;
}
}else if(isdigit(c)){
inits->numeric = 0;
if(ruts_numeric(&inits->numeric, c)){
@ -1018,11 +1054,31 @@ pump_control_read(query_state* inits, unsigned char c){
}
inits->state = STATE_TDA2;
if(ruts_string(inits, STATE_TDA1)){
inits->state = STATE_DCS_DRAIN;
inits->state = STATE_DCS_DRAIN; // FIXME return -1?
}
inits->numeric = 0;
break;
case STATE_SDA:
if(c == ';'){
inits->state = STATE_SDA_VER;
inits->numeric = 0;
}else if(c == 'c'){
inits->state = STATE_NULL;
}
break;
case STATE_SDA_VER:
if(c == ';'){
inits->state = STATE_SDA_DRAIN;
loginfo("Got DA2 Pv: %u\n", inits->numeric);
// if a version was set, we couldn't have arrived here
if((inits->version = set_sda_version(inits)) == NULL){
return -1;
}
}else if(ruts_numeric(&inits->numeric, c)){
return -1;
}
break;
case STATE_SDA_DRAIN:
if(c == 'c'){
inits->state = STATE_NULL;
}
@ -1234,7 +1290,7 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
query_state inits = {
.tcache = tcache,
.state = STATE_NULL,
.qterm = TERMINAL_UNKNOWN,
.qterm = *detected,
.cursor_x = -1,
.cursor_y = -1,
};

@ -242,6 +242,14 @@ grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
return 0;
}
// Tertiary Device Attributes, necessary to identify VTE.
// https://vt100.net/docs/vt510-rm/DA3.html
// Replies with DCS ! | ... ST
#define TRIDEVATTR "\x1b[=c"
// Primary Device Attributes, necessary to elicit a response from terminals
// which don't respond to other queries. All known terminals respond to DA1.
// https://vt100.net/docs/vt510-rm/DA1.html
// 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")
@ -252,22 +260,38 @@ grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
// ⇒ CSI ? 6 2 ; Ps c ("VT220")
// ⇒ CSI ? 6 3 ; Ps c ("VT320")
// ⇒ CSI ? 6 4 ; Ps c ("VT420")
#define PRIDEVATTR "\x1b[c"
// XTVERSION. Replies with DCS > | ... ST
#define XTVERSION "\x1b[>0q"
// XTGETTCAP['TN'] (Terminal Name)
#define XTGETTCAPTN "\x1bP+q544e\x1b\\"
// Secondary Device Attributes, necessary to get Alacritty's version. Since
// this doesn't uniquely identify a terminal, we ask it last, so that if any
// queries which *do* unambiguously identify a terminal have succeeded, this
// needn't be paid attention to.
// https://vt100.net/docs/vt510-rm/DA2.html
// Replies with CSI > 6 1 ; Pv ; [01] c
#define SECDEVATTR "\x1b[>c"
// 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.
// FIXME Konsole doesn't currently handle TDA, so we have to consume the 0c
// in our state machine =[
#define IDQUERIES "\x1b[=c" /* Tertiary Device Attributes */ \
"\x1b[>0q" /* XTVERSION */ \
"\x1bP+q544e\x1b\\" /* XTGETTCAP['TN'] */
#define IDQUERIES TRIDEVATTR \
XTVERSION \
XTGETTCAPTN \
SECDEVATTR
// 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\\"
#define CSI_BGQ "\x1b]11;?\e\\"
// 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 DSRCPR "\x1b[6n"
// check for Synchronized Update Mode support. the p is necessary, but Konsole
// doesn't consume it, so we have to handle that in our state machine =[.
@ -285,7 +309,7 @@ grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
"\x1b[?1;3;256S" /* try to set 256 cregs */ \
CREGSXTSM \
GEOMXTSM \
"\x1b[c" /* Device Attributes */
PRIDEVATTR
// 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.
@ -381,6 +405,12 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
}
if(qterm == TERMINAL_UNKNOWN){
match_termname(termname, &qterm);
// we pick up alacritty's version via a weird hack involving Secondary
// Device Attributes. if we're not alacritty, don't trust that version.
if(qterm != TERMINAL_ALACRITTY){
free(ti->termversion);
ti->termversion = NULL;
}
}
// st had neithercaps.sextants nor caps.quadrants last i checked (0.8.4)
ti->caps.braille = true; // most everyone has working caps.braille, even from fonts

Loading…
Cancel
Save