mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
[input] simplify startup automaton, unpop csi inputs
This commit is contained in:
parent
3a93d0b52d
commit
823e79416b
223
src/lib/input.c
223
src/lib/input.c
@ -366,6 +366,7 @@ handle_getc(ncinputlayer* nc, int kpress, ncinput* ni, int leftmargin, int topma
|
||||
if(kpress < 0){
|
||||
return -1;
|
||||
}
|
||||
unsigned csiidx = 0;
|
||||
if(kpress == NCKEY_ESC){
|
||||
const esctrie* esc = nc->inputescapes;
|
||||
int candidate = 0;
|
||||
@ -380,6 +381,9 @@ handle_getc(ncinputlayer* nc, int kpress, ncinput* ni, int leftmargin, int topma
|
||||
}
|
||||
candidate = pop_input_keypress(nc);
|
||||
logdebug("trie candidate: %c %d (%d)\n", candidate, esc->special, candidate);
|
||||
if(csi){
|
||||
nc->csibuf[csiidx++] = candidate;
|
||||
}
|
||||
if(esc->trie == NULL){
|
||||
esc = NULL;
|
||||
}else if(candidate >= 0x80 || candidate < 0){
|
||||
@ -396,8 +400,9 @@ handle_getc(ncinputlayer* nc, int kpress, ncinput* ni, int leftmargin, int topma
|
||||
return esc->special;
|
||||
}
|
||||
if(csi){
|
||||
// FIXME might need to unpop more than one
|
||||
unpop_keypress(nc, candidate);
|
||||
while(csiidx){
|
||||
unpop_keypress(nc, nc->csibuf[--csiidx]);
|
||||
}
|
||||
return handle_csi(nc, ni, leftmargin, topmargin);
|
||||
}
|
||||
// interpret it as alt + candidate FIXME broken for first char matching
|
||||
@ -962,20 +967,11 @@ typedef enum {
|
||||
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;'
|
||||
STATE_DA_1_0, // got '1;0', XTSMGRAPHICS color registers or VT101
|
||||
STATE_DA_1_SEMI_2, // got '1;2', XTSMGRAPHICS color reg fail or VT100
|
||||
STATE_DA_6, // got '6', could be VT102 or VT220/VT320/VT420
|
||||
STATE_DA, // primary DA (CSI ? ... c) OR XTSMGRAPHICS OR DECRPM or kittykbd
|
||||
STATE_DA_DRAIN, // drain out the primary DA to an alpha
|
||||
STATE_SIXEL,// XTSMGRAPHICS about Sixel geometry (got '2')
|
||||
STATE_SIXEL_SEMI1, // got first semicolon in sixel geometry, want Ps
|
||||
STATE_SIXEL_SUCCESS, // got Ps == 0, want second semicolon
|
||||
STATE_SIXEL_WIDTH, // reading maximum sixel width until ';'
|
||||
STATE_SIXEL_HEIGHT, // reading maximum sixel height until 'S'
|
||||
STATE_SIXEL_CREGS, // reading max color registers until 'S'
|
||||
STATE_XTSMGRAPHICS_DRAIN, // drain out XTSMGRAPHICS to 'S'
|
||||
STATE_DA_SEMI, // got first semicolon following numeric
|
||||
STATE_DA_SEMI2, // got second semicolon following numeric ; numeric
|
||||
STATE_DA_SEMI3, // got third semicolon following numeric ; numeric ; numeric
|
||||
STATE_APPSYNC_REPORT, // got DECRPT ?2026
|
||||
STATE_APPSYNC_REPORT_DRAIN, // drain out decrpt to 'y'
|
||||
// cursor location report: CSI row ; col R
|
||||
@ -1009,6 +1005,8 @@ typedef struct query_state {
|
||||
int dimy; // screen height in cells
|
||||
int cursor_y, cursor_x;// cursor location
|
||||
int cursor_or_pixel; // holding cell until we determine which state
|
||||
int three; // third param (XTSMGRAPHICS)
|
||||
int four; // fourth param (XTSMGRAPHICS)
|
||||
|
||||
bool xtgettcap_good; // high when we've received DCS 1
|
||||
bool appsync; // application-synchronized updates advertised
|
||||
@ -1274,7 +1272,7 @@ pump_control_read(query_state* inits, unsigned char c){
|
||||
break;
|
||||
case STATE_CSI: // terminated by 0x40--0x7E ('@'--'~')
|
||||
if(c == '?'){
|
||||
inits->state = STATE_DA; // could also be DECRPM/XTSMGRAPHICS
|
||||
inits->state = STATE_DA; // could also be DECRPM/XTSMGRAPHICS/kittykbd
|
||||
}else if(c == '>'){
|
||||
// SDA yields up Alacritty's crate version, but it doesn't unambiguously
|
||||
// identify Alacritty. If we've got any other version information, skip
|
||||
@ -1511,148 +1509,105 @@ pump_control_read(query_state* inits, unsigned char c){
|
||||
// CSI ? 6 2 ; Ps c ("VT220")
|
||||
// CSI ? 6 3 ; Ps c ("VT320")
|
||||
// CSI ? 6 4 ; Ps c ("VT420")
|
||||
// KITTYKBD: CSI ? flags u
|
||||
case STATE_DA: // return success on end of DA
|
||||
//fprintf(stderr, "DA: %c\n", c);
|
||||
if(c == '1'){
|
||||
inits->state = STATE_DA_1;
|
||||
}else if(c == '2'){
|
||||
if(ruts_numeric(&inits->numeric, c)){ // stash for DECRPT
|
||||
// FIXME several of these numbers could be DECRPM/XTSM/kittykbd. probably
|
||||
// just want to read number, *then* make transition on non-number.
|
||||
if(isdigit(c)){
|
||||
if(ruts_numeric(&inits->numeric, c)){ // stash for DECRPM/XTSM/kittykbd
|
||||
return -1;
|
||||
}
|
||||
inits->state = STATE_SIXEL;
|
||||
}else if(c == '4' || c == '7'){ // VT132, VT131
|
||||
inits->state = STATE_DA_DRAIN;
|
||||
}else if(c == '6'){
|
||||
inits->state = STATE_DA_6;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
}
|
||||
break;
|
||||
case STATE_DA_1:
|
||||
//fprintf(stderr, "DA1: %c\n", c);
|
||||
if(c == 'c'){
|
||||
inits->state = STATE_NULL;
|
||||
return 1;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
}else if(c == 'u'){ // kitty keyboard
|
||||
inits->tcache->kittykbd = inits->numeric;
|
||||
loginfo("keyboard protocol 0x%x\n", inits->tcache->kittykbd);
|
||||
inits->state = STATE_NULL;
|
||||
}else if(c == ';'){
|
||||
inits->state = STATE_DA_1_SEMI;
|
||||
} // FIXME error?
|
||||
break;
|
||||
case STATE_DA_1_SEMI:
|
||||
//fprintf(stderr, "DA1SEMI: %c\n", c);
|
||||
if(c == '2'){ // VT100 with Advanced Video Option *or* setcregs failure
|
||||
inits->state = STATE_DA_1_SEMI_2;
|
||||
}else if(c == '0'){
|
||||
inits->state = STATE_DA_1_0;
|
||||
inits->cursor_or_pixel = inits->numeric;
|
||||
inits->numeric = 0;
|
||||
inits->state = STATE_DA_SEMI;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
} // FIXME error?
|
||||
if(c == 'c'){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DA_1_SEMI_2:
|
||||
if(c == 'c'){
|
||||
case STATE_DA_SEMI:
|
||||
if(c == ';'){
|
||||
inits->three = inits->numeric;
|
||||
inits->numeric = 0;
|
||||
inits->state = STATE_DA_SEMI2;
|
||||
}else if(isdigit(c)){
|
||||
if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
}else if(c == '$'){
|
||||
if(inits->cursor_or_pixel == 2026){
|
||||
inits->state = STATE_APPSYNC_REPORT;
|
||||
loginfo("terminal reported SUM support\n");
|
||||
}else{
|
||||
inits->state = STATE_APPSYNC_REPORT_DRAIN;
|
||||
}
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
return 1;
|
||||
if(c == 'c'){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DA_SEMI2:
|
||||
if(c == ';'){
|
||||
inits->four = inits->numeric;
|
||||
inits->numeric = 0;
|
||||
inits->state = STATE_DA_SEMI3;
|
||||
}else if(isdigit(c)){
|
||||
if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
}else if(c == 'S'){
|
||||
if(inits->cursor_or_pixel == 1){
|
||||
inits->tcache->color_registers = inits->numeric;
|
||||
loginfo("sixel color registers: %d\n", inits->tcache->color_registers);
|
||||
inits->numeric = 0;
|
||||
}
|
||||
inits->state = STATE_NULL;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
if(c == 'c'){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DA_1_0:
|
||||
//fprintf(stderr, "DA_!_0: %c\n", c);
|
||||
if(c == 'c'){
|
||||
inits->state = STATE_NULL;
|
||||
return 1;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
}else if(c == ';'){
|
||||
inits->state = STATE_SIXEL_CREGS;
|
||||
} // FIXME error?
|
||||
break;
|
||||
case STATE_SIXEL_CREGS:
|
||||
if(c == 'S'){
|
||||
//fprintf(stderr, "CREGS: %d\n", inits->numeric);
|
||||
inits->tcache->color_registers = inits->numeric;
|
||||
inits->state = STATE_NULL;
|
||||
}else if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case STATE_DA_6:
|
||||
if(c == 'c'){
|
||||
inits->state = STATE_NULL;
|
||||
return 1;
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
}
|
||||
// FIXME
|
||||
break;
|
||||
case STATE_DA_DRAIN:
|
||||
if(c == 'c'){
|
||||
if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
return 1;
|
||||
if(c == 'c'){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DA_SEMI3:
|
||||
if(c == ';'){
|
||||
inits->numeric = 0;
|
||||
inits->state = STATE_DA_DRAIN;
|
||||
}else if(isdigit(c)){
|
||||
if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
}else if(c == 'S'){
|
||||
inits->tcache->sixel_maxx = inits->four;
|
||||
inits->tcache->sixel_maxy = inits->numeric;
|
||||
loginfo("max sixel geometry: %dx%d\n", inits->tcache->sixel_maxy, inits->tcache->sixel_maxx);
|
||||
}else if(c >= 0x40 && c <= 0x7E){
|
||||
inits->state = STATE_NULL;
|
||||
}
|
||||
break;
|
||||
case STATE_SIXEL:
|
||||
if(c == ';'){
|
||||
if(inits->numeric == 2026){
|
||||
inits->state = STATE_APPSYNC_REPORT;
|
||||
}else{
|
||||
inits->state = STATE_SIXEL_SEMI1;
|
||||
if(c == 'c'){
|
||||
return 1;
|
||||
}
|
||||
}else if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}else{
|
||||
// FIXME error?
|
||||
}
|
||||
break;
|
||||
case STATE_SIXEL_SEMI1:
|
||||
//fprintf(stderr, "SIXLE`l`: %c\n", c);
|
||||
if(c == '0'){
|
||||
inits->state = STATE_SIXEL_SUCCESS;
|
||||
}else if(c == '2'){
|
||||
inits->state = STATE_XTSMGRAPHICS_DRAIN;
|
||||
}else{
|
||||
// FIXME error?
|
||||
}
|
||||
break;
|
||||
case STATE_SIXEL_SUCCESS:
|
||||
if(c == ';'){
|
||||
inits->numeric = 0;
|
||||
inits->state = STATE_SIXEL_WIDTH;
|
||||
}else{
|
||||
// FIXME error?
|
||||
}
|
||||
break;
|
||||
case STATE_SIXEL_WIDTH:
|
||||
if(c == ';'){
|
||||
//fprintf(stderr, "HEIGHT: %d\n", inits->numeric);
|
||||
inits->tcache->sixel_maxx = inits->numeric;
|
||||
inits->state = STATE_SIXEL_HEIGHT;
|
||||
inits->numeric = 0;
|
||||
}else if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case STATE_SIXEL_HEIGHT:
|
||||
if(c == 'S'){
|
||||
//fprintf(stderr, "HEIGHT: %d\n", inits->numeric);
|
||||
inits->tcache->sixel_maxy_pristine = inits->numeric;
|
||||
inits->state = STATE_NULL;
|
||||
}else if(ruts_numeric(&inits->numeric, c)){
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case STATE_XTSMGRAPHICS_DRAIN:
|
||||
if(c == 'S'){
|
||||
inits->state = STATE_NULL;
|
||||
}
|
||||
break;
|
||||
case STATE_APPSYNC_REPORT:
|
||||
if(c == '2'){
|
||||
if(inits->numeric == '2'){
|
||||
inits->appsync = 1;
|
||||
inits->state = STATE_APPSYNC_REPORT_DRAIN;
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ typedef struct ncinputlayer {
|
||||
int ttyfd; // file descriptor for connected tty
|
||||
int infd; // file descriptor for processing input, from stdin
|
||||
unsigned char inputbuf[BUFSIZ];
|
||||
unsigned char csibuf[BUFSIZ]; // running buffer while parsing CSIs
|
||||
// we keep a wee ringbuffer of input queued up for delivery. if
|
||||
// inputbuf_occupied == sizeof(inputbuf), there is no room. otherwise, data
|
||||
// can be read to inputbuf_write_at until we fill up. the first datum
|
||||
@ -198,6 +199,8 @@ typedef struct tinfo {
|
||||
int default_rows; // LINES environment var / lines terminfo / 24
|
||||
int default_cols; // COLUMNS environment var / cols terminfo / 80
|
||||
|
||||
unsigned kittykbd; // kitty keyboard support level
|
||||
|
||||
int gpmfd; // connection to GPM daemon
|
||||
pthread_t gpmthread; // thread handle for GPM watcher
|
||||
#ifdef __linux__
|
||||
|
Loading…
x
Reference in New Issue
Block a user