get everything prepped for reliable keyboard escapes #78
parent
04e067c202
commit
37b0e416c0
@ -1,79 +1,110 @@
|
|||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
static const unsigned char ESC = 0x1b; // 27
|
||||||
|
|
||||||
sig_atomic_t resize_seen = 0;
|
sig_atomic_t resize_seen = 0;
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
pop_input_keypress(notcurses* nc){
|
||||||
|
int candidate = nc->inputbuf[nc->inputbuf_valid_starts];
|
||||||
|
fprintf(stderr, "DEOCCUPY: %u@%u read: %d\n", nc->inputbuf_occupied, nc->inputbuf_valid_starts, nc->inputbuf[nc->inputbuf_valid_starts]);
|
||||||
|
if(++nc->inputbuf_valid_starts == sizeof(nc->inputbuf) / sizeof(*nc->inputbuf)){
|
||||||
|
nc->inputbuf_valid_starts = 0;
|
||||||
|
}
|
||||||
|
--nc->inputbuf_occupied;
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
// add the keypress we just read to our input queue (assuming there is room).
|
// add the keypress we just read to our input queue (assuming there is room).
|
||||||
// if there is a full UTF8 codepoint or keystroke (composed or otherwise),
|
// if there is a full UTF8 codepoint or keystroke (composed or otherwise),
|
||||||
// return it, and pop it from the queue.
|
// return it, and pop it from the queue.
|
||||||
static int
|
static int
|
||||||
handle_getc(const notcurses* nc __attribute__ ((unused)), cell* c, int kpress,
|
handle_getc(notcurses* nc, cell* c, int kpress, ncspecial_key* special){
|
||||||
ncspecial_key* special){
|
|
||||||
fprintf(stderr, "KEYPRESS: %d\n", kpress);
|
fprintf(stderr, "KEYPRESS: %d\n", kpress);
|
||||||
if(kpress < 0){
|
if(kpress < 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// FIXME add it to the queue, then consult queue
|
if(kpress == ESC){
|
||||||
|
fprintf(stderr, "ESCAPE OH SHIT\n");
|
||||||
|
// FIXME delay a little waiting for more?
|
||||||
|
while(nc->inputbuf_occupied){
|
||||||
|
int candidate = pop_input_keypress(nc);
|
||||||
|
// FIXME walk trie via candidate, exiting (and ungetc()ing) on failure
|
||||||
|
fprintf(stderr, "CANDIDATE: %c\n", candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
*special = 0;
|
*special = 0;
|
||||||
if(kpress == 0x04){ // ctrl-d
|
if(kpress == 0x04){ // ctrl-d, treated as EOF
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// FIXME look for keypad
|
|
||||||
if(kpress < 0x80){
|
if(kpress < 0x80){
|
||||||
c->gcluster = kpress;
|
c->gcluster = kpress;
|
||||||
}else{
|
}else{
|
||||||
// FIXME
|
// FIXME load up zee utf8
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int notcurses_getc(const notcurses* nc, cell* c, ncspecial_key* special){
|
// blocks up through ts (infinite with NULL ts), returning number of events
|
||||||
if(resize_seen){
|
// (0 on timeout) or -1 on error/interruption.
|
||||||
resize_seen = 0;
|
static int
|
||||||
c->gcluster = 0;
|
block_on_input(FILE* fp, const struct timespec* ts, sigset_t* sigmask){
|
||||||
*special = NCKEY_RESIZE;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// FIXME check queue
|
|
||||||
int r = getc(nc->ttyinfp);
|
|
||||||
if(r < 0){
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
return handle_getc(nc, c, r, special);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we set our infd to non-blocking on entry, so to do a blocking call (without
|
|
||||||
// burning cpu) we'll need to set up a poll().
|
|
||||||
int notcurses_getc_blocking(const notcurses* nc, cell* c, ncspecial_key* special){
|
|
||||||
struct pollfd pfd = {
|
struct pollfd pfd = {
|
||||||
.fd = fileno(nc->ttyinfp),
|
.fd = fileno(fp),
|
||||||
.events = POLLIN | POLLRDHUP,
|
.events = POLLIN | POLLRDHUP,
|
||||||
.revents = 0,
|
.revents = 0,
|
||||||
};
|
};
|
||||||
int pret, r;
|
sigdelset(sigmask, SIGWINCH);
|
||||||
sigset_t smask;
|
sigdelset(sigmask, SIGINT);
|
||||||
sigfillset(&smask);
|
sigdelset(sigmask, SIGQUIT);
|
||||||
sigdelset(&smask, SIGWINCH);
|
sigdelset(sigmask, SIGSEGV);
|
||||||
sigdelset(&smask, SIGINT);
|
return ppoll(&pfd, 1, ts, sigmask);
|
||||||
sigdelset(&smask, SIGQUIT);
|
}
|
||||||
sigdelset(&smask, SIGSEGV);
|
|
||||||
while((pret = ppoll(&pfd, 1, NULL, &smask)) >= 0){
|
static bool
|
||||||
if(pret == 0){
|
input_queue_full(const notcurses* nc){
|
||||||
continue;
|
return nc->inputbuf_occupied == sizeof(nc->inputbuf) / sizeof(*nc->inputbuf);
|
||||||
}
|
}
|
||||||
r = notcurses_getc(nc, c, special);
|
|
||||||
if(r < 0){
|
static int
|
||||||
break; // want EINTR handling below
|
handle_input(notcurses* nc, cell* c, ncspecial_key* special){
|
||||||
|
int r;
|
||||||
|
c->gcluster = 0;
|
||||||
|
// getc() returns unsigned chars cast to ints
|
||||||
|
while(!input_queue_full(nc) && (r = getc(nc->ttyinfp)) >= 0){
|
||||||
|
nc->inputbuf[nc->inputbuf_write_at] = (unsigned char)r;
|
||||||
|
fprintf(stderr, "OCCUPY: %u@%u read: %d\n", nc->inputbuf_occupied, nc->inputbuf_write_at, nc->inputbuf[nc->inputbuf_write_at]);
|
||||||
|
if(++nc->inputbuf_write_at == sizeof(nc->inputbuf) / sizeof(*nc->inputbuf)){
|
||||||
|
nc->inputbuf_write_at = 0;
|
||||||
}
|
}
|
||||||
return r;
|
++nc->inputbuf_occupied;
|
||||||
}
|
}
|
||||||
if(errno == EINTR){
|
// highest priority is resize notifications, since they don't queue
|
||||||
if(resize_seen){
|
if(resize_seen){
|
||||||
resize_seen = 0;
|
resize_seen = 0;
|
||||||
c->gcluster = 0;
|
|
||||||
*special = NCKEY_RESIZE;
|
*special = NCKEY_RESIZE;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
// if there was some error in getc(), we still dole out the existing queue
|
||||||
|
if(nc->inputbuf_occupied == 0){
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
r = pop_input_keypress(nc);
|
||||||
|
return handle_getc(nc, c, r, special);
|
||||||
|
}
|
||||||
|
|
||||||
|
// infp has always been set non-blocking
|
||||||
|
int notcurses_getc(notcurses* nc, cell* c, ncspecial_key* special,
|
||||||
|
const struct timespec *ts, sigset_t* sigmask){
|
||||||
|
errno = 0;
|
||||||
|
int r = handle_input(nc, c, special);
|
||||||
|
if(r > 0){
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if(errno == EAGAIN || errno == EWOULDBLOCK){
|
||||||
|
block_on_input(nc->ttyinfp, ts, sigmask);
|
||||||
|
r = handle_input(nc, c, special);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue