|
|
@ -321,70 +321,72 @@ static int
|
|
|
|
stash_string(inputctx* ictx){
|
|
|
|
stash_string(inputctx* ictx){
|
|
|
|
struct initial_responses* inits = ictx->initdata;
|
|
|
|
struct initial_responses* inits = ictx->initdata;
|
|
|
|
//fprintf(stderr, "string terminator after %d [%s]\n", inits->stringstate, inits->runstring);
|
|
|
|
//fprintf(stderr, "string terminator after %d [%s]\n", inits->stringstate, inits->runstring);
|
|
|
|
switch(ictx->stringstate){
|
|
|
|
if(inits){
|
|
|
|
case STATE_XTVERSION1:{
|
|
|
|
switch(ictx->stringstate){
|
|
|
|
static const struct {
|
|
|
|
case STATE_XTVERSION1:{
|
|
|
|
const char* prefix;
|
|
|
|
static const struct {
|
|
|
|
char suffix;
|
|
|
|
const char* prefix;
|
|
|
|
queried_terminals_e term;
|
|
|
|
char suffix;
|
|
|
|
} xtvers[] = {
|
|
|
|
queried_terminals_e term;
|
|
|
|
{ .prefix = "XTerm(", .suffix = ')', .term = TERMINAL_XTERM, },
|
|
|
|
} xtvers[] = {
|
|
|
|
{ .prefix = "WezTerm ", .suffix = 0, .term = TERMINAL_WEZTERM, },
|
|
|
|
{ .prefix = "XTerm(", .suffix = ')', .term = TERMINAL_XTERM, },
|
|
|
|
{ .prefix = "contour ", .suffix = 0, .term = TERMINAL_CONTOUR, },
|
|
|
|
{ .prefix = "WezTerm ", .suffix = 0, .term = TERMINAL_WEZTERM, },
|
|
|
|
{ .prefix = "kitty(", .suffix = ')', .term = TERMINAL_KITTY, },
|
|
|
|
{ .prefix = "contour ", .suffix = 0, .term = TERMINAL_CONTOUR, },
|
|
|
|
{ .prefix = "foot(", .suffix = ')', .term = TERMINAL_FOOT, },
|
|
|
|
{ .prefix = "kitty(", .suffix = ')', .term = TERMINAL_KITTY, },
|
|
|
|
{ .prefix = "mlterm(", .suffix = ')', .term = TERMINAL_MLTERM, },
|
|
|
|
{ .prefix = "foot(", .suffix = ')', .term = TERMINAL_FOOT, },
|
|
|
|
{ .prefix = "tmux ", .suffix = 0, .term = TERMINAL_TMUX, },
|
|
|
|
{ .prefix = "mlterm(", .suffix = ')', .term = TERMINAL_MLTERM, },
|
|
|
|
{ .prefix = "iTerm2 ", .suffix = 0, .term = TERMINAL_ITERM, },
|
|
|
|
{ .prefix = "tmux ", .suffix = 0, .term = TERMINAL_TMUX, },
|
|
|
|
{ .prefix = "mintty ", .suffix = 0, .term = TERMINAL_MINTTY, },
|
|
|
|
{ .prefix = "iTerm2 ", .suffix = 0, .term = TERMINAL_ITERM, },
|
|
|
|
{ .prefix = NULL, .suffix = 0, .term = TERMINAL_UNKNOWN, },
|
|
|
|
{ .prefix = "mintty ", .suffix = 0, .term = TERMINAL_MINTTY, },
|
|
|
|
}, *xtv;
|
|
|
|
{ .prefix = NULL, .suffix = 0, .term = TERMINAL_UNKNOWN, },
|
|
|
|
for(xtv = xtvers ; xtv->prefix ; ++xtv){
|
|
|
|
}, *xtv;
|
|
|
|
if(strncmp(ictx->runstring, xtv->prefix, strlen(xtv->prefix)) == 0){
|
|
|
|
for(xtv = xtvers ; xtv->prefix ; ++xtv){
|
|
|
|
if(extract_xtversion(ictx, strlen(xtv->prefix), xtv->suffix) == 0){
|
|
|
|
if(strncmp(ictx->runstring, xtv->prefix, strlen(xtv->prefix)) == 0){
|
|
|
|
inits->qterm = xtv->term;
|
|
|
|
if(extract_xtversion(ictx, strlen(xtv->prefix), xtv->suffix) == 0){
|
|
|
|
|
|
|
|
inits->qterm = xtv->term;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xtv->prefix == NULL){
|
|
|
|
|
|
|
|
logwarn("Unrecognizable XTVERSION [%s]\n", ictx->runstring);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}case STATE_XTGETTCAP_TERMNAME1:
|
|
|
|
|
|
|
|
if(strcmp(ictx->runstring, "xterm-kitty") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_KITTY;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "mlterm") == 0){
|
|
|
|
|
|
|
|
// MLterm prior to late 3.9.1 only reports via XTGETTCAP
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_MLTERM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_TDA1:
|
|
|
|
|
|
|
|
if(strcmp(ictx->runstring, "~VTE") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_VTE;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "~~TY") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_TERMINOLOGY;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "FOOT") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_FOOT;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BG1:{
|
|
|
|
|
|
|
|
int r, g, b;
|
|
|
|
|
|
|
|
if(sscanf(ictx->runstring, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3){
|
|
|
|
|
|
|
|
// great! =]
|
|
|
|
|
|
|
|
}else if(sscanf(ictx->runstring, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3){
|
|
|
|
|
|
|
|
r /= 256;
|
|
|
|
|
|
|
|
g /= 256;
|
|
|
|
|
|
|
|
b /= 256;
|
|
|
|
|
|
|
|
}else{
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
inits->bg = (r << 16u) | (g << 8u) | b;
|
|
|
|
if(xtv->prefix == NULL){
|
|
|
|
|
|
|
|
logwarn("Unrecognizable XTVERSION [%s]\n", ictx->runstring);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}case STATE_XTGETTCAP_TERMNAME1:
|
|
|
|
|
|
|
|
if(strcmp(ictx->runstring, "xterm-kitty") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_KITTY;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "mlterm") == 0){
|
|
|
|
|
|
|
|
// MLterm prior to late 3.9.1 only reports via XTGETTCAP
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_MLTERM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_TDA1:
|
|
|
|
|
|
|
|
if(strcmp(ictx->runstring, "~VTE") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_VTE;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "~~TY") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_TERMINOLOGY;
|
|
|
|
|
|
|
|
}else if(strcmp(ictx->runstring, "FOOT") == 0){
|
|
|
|
|
|
|
|
inits->qterm = TERMINAL_FOOT;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BG1:{
|
|
|
|
|
|
|
|
int r, g, b;
|
|
|
|
|
|
|
|
if(sscanf(ictx->runstring, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3){
|
|
|
|
|
|
|
|
// great! =]
|
|
|
|
|
|
|
|
}else if(sscanf(ictx->runstring, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3){
|
|
|
|
|
|
|
|
r /= 256;
|
|
|
|
|
|
|
|
g /= 256;
|
|
|
|
|
|
|
|
b /= 256;
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}default:
|
|
|
|
inits->bg = (r << 16u) | (g << 8u) | b;
|
|
|
|
// don't generally enable this -- XTerm terminates TDA with ST
|
|
|
|
break;
|
|
|
|
//fprintf(stderr, "invalid string [%s] stashed %d\n", inits->runstring, inits->stringstate);
|
|
|
|
}default:
|
|
|
|
break;
|
|
|
|
// don't generally enable this -- XTerm terminates TDA with ST
|
|
|
|
}
|
|
|
|
//fprintf(stderr, "invalid string [%s] stashed %d\n", inits->runstring, inits->stringstate);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ictx->runstring[0] = '\0';
|
|
|
|
ictx->runstring[0] = '\0';
|
|
|
|
ictx->stridx = 0;
|
|
|
|
ictx->stridx = 0;
|
|
|
@ -451,7 +453,9 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case STATE_APC:
|
|
|
|
case STATE_APC:
|
|
|
|
if(c == 'G'){
|
|
|
|
if(c == 'G'){
|
|
|
|
ictx->initdata->kitty_graphics = true;
|
|
|
|
if(ictx->initdata){
|
|
|
|
|
|
|
|
ictx->initdata->kitty_graphics = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ictx->state = STATE_APC_DRAIN;
|
|
|
|
ictx->state = STATE_APC_DRAIN;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -503,11 +507,13 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
// SDA yields up Alacritty's crate version, but it doesn't unambiguously
|
|
|
|
// SDA yields up Alacritty's crate version, but it doesn't unambiguously
|
|
|
|
// identify Alacritty. If we've got any other version information, skip
|
|
|
|
// identify Alacritty. If we've got any other version information, skip
|
|
|
|
// directly to STATE_SDA_DRAIN, rather than doing STATE_SDA_VER.
|
|
|
|
// directly to STATE_SDA_DRAIN, rather than doing STATE_SDA_VER.
|
|
|
|
if(ictx->initdata->qterm || ictx->initdata->version){
|
|
|
|
if(ictx->initdata){
|
|
|
|
loginfo("Identified terminal already; ignoring DA2\n");
|
|
|
|
if(ictx->initdata->qterm || ictx->initdata->version){
|
|
|
|
ictx->state = STATE_SDA_DRAIN;
|
|
|
|
loginfo("Identified terminal already; ignoring DA2\n");
|
|
|
|
}else{
|
|
|
|
ictx->state = STATE_SDA_DRAIN;
|
|
|
|
ictx->state = STATE_SDA;
|
|
|
|
}else{
|
|
|
|
|
|
|
|
ictx->state = STATE_SDA;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(isdigit(c)){
|
|
|
|
}else if(isdigit(c)){
|
|
|
|
ictx->numeric = 0;
|
|
|
|
ictx->numeric = 0;
|
|
|
@ -562,16 +568,22 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
}else if(c == 't'){
|
|
|
|
}else if(c == 't'){
|
|
|
|
//fprintf(stderr, "CELLS X: %d\n", ictx->numeric);
|
|
|
|
//fprintf(stderr, "CELLS X: %d\n", ictx->numeric);
|
|
|
|
ictx->initdata->dimx = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
ictx->initdata->dimy = ictx->p2;
|
|
|
|
ictx->initdata->dimx = ictx->numeric;
|
|
|
|
|
|
|
|
ictx->initdata->dimy = ictx->p2;
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
}else if(c == ';'){
|
|
|
|
}else if(c == ';'){
|
|
|
|
if(ictx->p2 == 4){
|
|
|
|
if(ictx->p2 == 4){
|
|
|
|
ictx->initdata->pixy = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
ictx->state = STATE_PIXELS_WIDTH;
|
|
|
|
ictx->initdata->pixy = ictx->numeric;
|
|
|
|
|
|
|
|
ictx->state = STATE_PIXELS_WIDTH;
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->numeric = 0;
|
|
|
|
ictx->numeric = 0;
|
|
|
|
}else if(ictx->p2 == 8){
|
|
|
|
}else if(ictx->p2 == 8){
|
|
|
|
ictx->initdata->dimy = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
|
|
|
|
ictx->initdata->dimy = ictx->numeric;
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->state = STATE_CELLS_WIDTH;
|
|
|
|
ictx->state = STATE_CELLS_WIDTH;
|
|
|
|
ictx->numeric = 0;
|
|
|
|
ictx->numeric = 0;
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
@ -588,8 +600,10 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(c == 't'){
|
|
|
|
}else if(c == 't'){
|
|
|
|
ictx->initdata->pixx = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
loginfo("got pixel geometry: %d/%d\n", ictx->initdata->pixy, ictx->initdata->pixx);
|
|
|
|
ictx->initdata->pixx = ictx->numeric;
|
|
|
|
|
|
|
|
loginfo("got pixel geometry: %d/%d\n", ictx->initdata->pixy, ictx->initdata->pixx);
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
@ -601,8 +615,10 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(c == 't'){
|
|
|
|
}else if(c == 't'){
|
|
|
|
ictx->initdata->dimx = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
loginfo("got cell geometry: %d/%d\n", ictx->initdata->dimy, ictx->initdata->dimx);
|
|
|
|
ictx->initdata->dimx = ictx->numeric;
|
|
|
|
|
|
|
|
loginfo("got cell geometry: %d/%d\n", ictx->initdata->dimy, ictx->initdata->dimx);
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
@ -722,12 +738,14 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
case STATE_SDA_VER:
|
|
|
|
case STATE_SDA_VER:
|
|
|
|
if(c == ';'){
|
|
|
|
if(c == ';'){
|
|
|
|
ictx->state = STATE_SDA_DRAIN;
|
|
|
|
ictx->state = STATE_SDA_DRAIN;
|
|
|
|
loginfo("Got DA2 Pv: %u\n", ictx->numeric);
|
|
|
|
if(ictx->initdata){
|
|
|
|
// if a version was set, we couldn't have arrived here. alacritty
|
|
|
|
loginfo("Got DA2 Pv: %u\n", ictx->numeric);
|
|
|
|
// writes its crate version here, in an encoded form. nothing else
|
|
|
|
// if a version was set, we couldn't have arrived here. alacritty
|
|
|
|
// necessarily does, though, so allow failure. this value will be
|
|
|
|
// writes its crate version here, in an encoded form. nothing else
|
|
|
|
// interpreted as the version only if TERM indicates alacritty.
|
|
|
|
// necessarily does, though, so allow failure. this value will be
|
|
|
|
ictx->initdata->version = set_sda_version(ictx);
|
|
|
|
// interpreted as the version only if TERM indicates alacritty.
|
|
|
|
|
|
|
|
ictx->initdata->version = set_sda_version(ictx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}else if(ruts_numeric(&ictx->numeric, c)){
|
|
|
|
}else if(ruts_numeric(&ictx->numeric, c)){
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -807,8 +825,10 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(c == 'S'){
|
|
|
|
}else if(c == 'S'){
|
|
|
|
if(ictx->p2 == 1){
|
|
|
|
if(ictx->p2 == 1){
|
|
|
|
ictx->initdata->color_registers = ictx->numeric;
|
|
|
|
if(ictx->initdata){
|
|
|
|
loginfo("sixel color registers: %d\n", ictx->initdata->color_registers);
|
|
|
|
ictx->initdata->color_registers = ictx->numeric;
|
|
|
|
|
|
|
|
loginfo("sixel color registers: %d\n", ictx->initdata->color_registers);
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->numeric = 0;
|
|
|
|
ictx->numeric = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
@ -836,9 +856,11 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(c == 'S'){
|
|
|
|
}else if(c == 'S'){
|
|
|
|
ictx->initdata->sixelx = ictx->p4;
|
|
|
|
if(ictx->initdata){
|
|
|
|
ictx->initdata->sixely = ictx->numeric;
|
|
|
|
ictx->initdata->sixelx = ictx->p4;
|
|
|
|
loginfo("max sixel geometry: %dx%d\n", ictx->initdata->sixely, ictx->initdata->sixelx);
|
|
|
|
ictx->initdata->sixely = ictx->numeric;
|
|
|
|
|
|
|
|
loginfo("max sixel geometry: %dx%d\n", ictx->initdata->sixely, ictx->initdata->sixelx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}else if(c >= 0x40 && c <= 0x7E){
|
|
|
|
}else if(c >= 0x40 && c <= 0x7E){
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
ictx->state = STATE_NULL;
|
|
|
|
if(c == 'c'){
|
|
|
|
if(c == 'c'){
|
|
|
@ -848,7 +870,9 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case STATE_APPSYNC_REPORT:
|
|
|
|
case STATE_APPSYNC_REPORT:
|
|
|
|
if(ictx->numeric == '2'){
|
|
|
|
if(ictx->numeric == '2'){
|
|
|
|
ictx->initdata->appsync_supported = 1;
|
|
|
|
if(ictx->initdata){
|
|
|
|
|
|
|
|
ictx->initdata->appsync_supported = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
ictx->state = STATE_APPSYNC_REPORT_DRAIN;
|
|
|
|
ictx->state = STATE_APPSYNC_REPORT_DRAIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1174,6 +1198,23 @@ uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int notcurses_getvec(notcurses* n, const struct timespec* ts,
|
|
|
|
|
|
|
|
ncinput* ni, int vcount){
|
|
|
|
|
|
|
|
for(int v = 0 ; v < vcount ; ++v){
|
|
|
|
|
|
|
|
// FIXME need to manage ts; right now, we could delay up to ts * vcount!
|
|
|
|
|
|
|
|
uint32_t u = notcurses_get(n, ts, &ni[v]);
|
|
|
|
|
|
|
|
if(u == (uint32_t)-1){
|
|
|
|
|
|
|
|
if(v == 0){
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
|
|
|
}else if(u == 0){
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return vcount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t ncdirect_get(ncdirect* n, const struct timespec* ts, ncinput* ni){
|
|
|
|
uint32_t ncdirect_get(ncdirect* n, const struct timespec* ts, ncinput* ni){
|
|
|
|
return internal_get(n->tcache.ictx, ts, ni, 0, 0);
|
|
|
|
return internal_get(n->tcache.ictx, ts, ni, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|