[input] break up events #2174

pull/2197/head
nick black 3 years ago committed by nick black
parent 24eac43f4f
commit e12aceccce

@ -198,7 +198,7 @@ void Tick(ncpp::NotCurses* nc, uint64_t sec) {
void Ticker(ncpp::NotCurses* nc) {
do{
std::this_thread::sleep_for(std::chrono::milliseconds{100});
std::this_thread::sleep_for(std::chrono::milliseconds{1000});
const uint64_t sec = (timenow_to_ns() - start) / NANOSECS_IN_SEC;
Tick(nc, sec);
}while(!done);
@ -309,6 +309,11 @@ int input_demo(ncpp::NotCurses* nc) {
n->printf("Unicode: [0x%08x] '%lc'", r, (wchar_t)r);
}
}
int x;
n->get_cursor_yx(nullptr, &x);
for(int i = x ; i < n->get_dim_x() ; ++i){
n->putc(' ');
}
if(!dim_rows(n)){
break;
}

@ -1000,6 +1000,7 @@ kitty_kbd(inputctx* ictx){
// FIXME sloppy af in general
// returns 1 after handling the Device Attributes response, 0 if more input
// ought be fed to the machine, and -1 on an invalid state transition.
// returns 2 on a valid accept state that is not the final state.
static int
pump_control_read(inputctx* ictx, unsigned char c){
logdebug("state: %2d char: %1c %3d %02x\n", ictx->state, isprint(c) ? c : ' ', c, c);
@ -1044,6 +1045,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_APC_ST:
if(c == '\\'){
ictx->state = STATE_NULL;
return 2;
}else{
ictx->state = STATE_APC_DRAIN;
}
@ -1070,7 +1072,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
return -1;
}
ictx->state = STATE_NULL;
break;
return 2;
}
ictx->numeric = c;
if(ruts_string(ictx, STATE_BG1)){
@ -1181,6 +1183,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
}
}
ictx->state = STATE_NULL;
return 2;
}else if(c == 't'){
//fprintf(stderr, "CELLS X: %d\n", ictx->numeric);
if(ictx->initdata){
@ -1188,6 +1191,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
ictx->initdata->dimy = ictx->p2;
}
ictx->state = STATE_NULL;
return 2;
}else if(c == 'u'){
// kitty keyboard protocol
kitty_kbd(ictx);
@ -1225,6 +1229,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
loginfo("got pixel geometry: %d/%d\n", ictx->initdata->pixy, ictx->initdata->pixx);
}
ictx->state = STATE_NULL;
return 2;
}else{
ictx->state = STATE_NULL;
}
@ -1240,6 +1245,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
loginfo("got cell geometry: %d/%d\n", ictx->initdata->dimy, ictx->initdata->dimx);
}
ictx->state = STATE_NULL;
return 2;
}else{
ictx->state = STATE_NULL;
}
@ -1373,6 +1379,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_SDA_DRAIN:
if(c == 'c'){
ictx->state = STATE_NULL;
return 2;
}
break;
// primary device attributes and XTSMGRAPHICS replies are generally
@ -1480,6 +1487,8 @@ pump_control_read(inputctx* ictx, unsigned char c){
ictx->initdata->sixelx = ictx->p4;
ictx->initdata->sixely = ictx->numeric;
loginfo("max sixel geometry: %dx%d\n", ictx->initdata->sixely, ictx->initdata->sixelx);
ictx->state = STATE_NULL;
return 2;
}
}else if(c >= 0x40 && c <= 0x7E){
ictx->state = STATE_NULL;
@ -1499,6 +1508,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_APPSYNC_REPORT_DRAIN:
if(c == 'y'){
ictx->state = STATE_NULL;
return 2;
}
break;
default:
@ -1526,7 +1536,6 @@ handoff_initial_responses(inputctx* ictx){
static int
process_escape(inputctx* ictx, const unsigned char* buf, int buflen){
assert(1 <= buflen);
ictx->midescape = 0;
// FIXME given that we keep our state across invocations, we want buf offset
// by the amount we handled the last iteration, if any was left over...
// until then, we reset the state on entry. remove that once we preserve!
@ -1610,7 +1619,8 @@ process_escapes(inputctx* ictx, unsigned char* buf, int* bufused){
// the end of the tbuf, in which case we really do try reading more. if
// this was not a sequence, we'll catch it on the next read.
if(consumed < 0){
if(!ictx->midescape){
int tavailable = sizeof(ictx->tbuf) - (offset + *bufused - consumed);
if(!ictx->midescape || tavailable){
consumed = -consumed;
int available = sizeof(ictx->ibuf) - ictx->ibufvalid;
if(available){
@ -1622,6 +1632,7 @@ process_escapes(inputctx* ictx, unsigned char* buf, int* bufused){
}
*bufused -= consumed;
offset += consumed;
ictx->midescape = 0;
}
break;
}
@ -1741,9 +1752,10 @@ process_melange(inputctx* ictx, const unsigned char* buf, int* bufused){
consumed = process_escape(ictx, buf + offset, *bufused);
if(consumed < 0){
if(ictx->midescape){
if(-consumed != *bufused){ // not at the end; treat it as input
// no need to move between buffers; simply ensure we process it as
// input, and don't mark anything as consumed.
if(offset + *bufused - consumed != sizeof(ictx->ibuf)){
// not at the end; treat it as input. no need to move between
// buffers; simply ensure we process it as input, and don't mark
// anything as consumed.
ictx->midescape = 0;
}
}
@ -1796,14 +1808,22 @@ int ncinput_shovel(inputctx* ictx, const void* buf, int len){
return 0;
}
// FIXME if ictx->midescape is set, need a nonblocking read!
// here, we always block for an arbitrarily long time, or not at all,
// doing the latter only when ictx->midescape is set. |rtfd| and/or |rifd|
// are set high iff they are ready for reading, and otherwise cleared.
static int
block_on_input(inputctx* ictx){
struct timespec* ts = NULL; // FIXME
block_on_input(inputctx* ictx, unsigned* rtfd, unsigned* rifd){
*rtfd = *rifd = 0;
unsigned nonblock = ictx->midescape;
if(nonblock){
loginfo("nonblocking read to check for completion\n");
ictx->midescape = 0;
}
#ifdef __MINGW64__
int timeoutms = ts ? ts->tv_sec * 1000 + ts->tv_nsec / 1000000 : -1;
int timeoutms = nonblock ? 0 : -1;
DWORD d = WaitForMultipleObjects(1, &ictx->stdinhandle, FALSE, timeoutms);
if(d == WAIT_TIMEOUT){
*rifd = 1;
return 0;
}else if(d == WAIT_FAILED){
return -1;
@ -1832,14 +1852,16 @@ block_on_input(inputctx* ictx){
}
int events;
#if defined(__APPLE__) || defined(__MINGW64__)
int timeoutms = ts ? ts->tv_sec * 1000 + ts->tv_nsec / 1000000 : -1;
int timeoutms = nonblock ? 0 : -1;
while((events = poll(pfds, pfdcount, timeoutms)) < 0){ // FIXME smask?
#else
sigset_t smask;
sigfillset(&smask);
sigdelset(&smask, SIGCONT);
sigdelset(&smask, SIGWINCH);
while((events = ppoll(pfds, pfdcount, ts, &smask)) < 0){
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, };
struct timespec* pts = nonblock ? &ts : NULL;
while((events = ppoll(pfds, pfdcount, pts, &smask)) < 0){
#endif
if(errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){
return -1;
@ -1847,6 +1869,15 @@ block_on_input(inputctx* ictx){
return resize_seen;
}
}
loginfo("got events: %d\n", events);
if(pfds[0].revents){
*rifd = 1;
if(events == 2){
*rtfd = 1;
}
}else{
*rtfd = 1;
}
return events;
#endif
}
@ -1855,16 +1886,21 @@ block_on_input(inputctx* ictx){
// don't loop around this call without some kind of readiness notification.
static void
read_inputs_nblock(inputctx* ictx){
unsigned rtfd, rifd;
// FIXME also need to wake up if our output queues have space that has
// opened up for us to write into, lest we deadlock with full buffers...
block_on_input(ictx);
block_on_input(ictx, &rtfd, &rifd);
// first we read from the terminal, if that's a distinct source.
read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf),
&ictx->tbufvalid);
if(rtfd){
read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf),
&ictx->tbufvalid);
}
// now read bulk, possibly with term escapes intermingled within (if there
// was not a distinct terminal source).
read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf),
&ictx->ibufvalid);
if(rifd){
read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf),
&ictx->ibufvalid);
}
}
static void*

@ -86,6 +86,7 @@ reset_terminal(){
tios.c_lflag |= ISIG | ICANON | ECHO;
tcsetattr(fd, TCSADRAIN, &tios);
}
printf("\x1b[<u"); // pop any kitty keyboard state we set
char* str = tigetstr("sgr0");
if(str != (char*)-1){
printf("%s", str);

Loading…
Cancel
Save