build and destroy input sequence trie #78

pull/124/head
nick black 5 years ago committed by Nick Black
parent 37b0e416c0
commit cbbc18c3a3

@ -8,7 +8,7 @@ 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]);
// 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;
}
@ -16,17 +16,83 @@ fprintf(stderr, "DEOCCUPY: %u@%u read: %d\n", nc->inputbuf_occupied, nc->inputbu
return candidate;
}
// we assumed escapes can only be composed of 7-bit chars
typedef struct esctrie {
ncspecial_key special; // escape terminating here
struct esctrie** trie; // if non-NULL, next level of radix-128 trie
} esctrie;
static esctrie*
create_esctrie_node(ncspecial_key special){
esctrie* e = malloc(sizeof(*e));
if(e){
e->special = special;
e->trie = NULL;
}
return e;
}
void input_free_esctrie(esctrie** eptr){
esctrie* e;
if( (e = *eptr) ){
if(e->trie){
int z;
for(z = 0 ; z < 0x80 ; ++z){
if(e->trie[z]){
input_free_esctrie(&e->trie[z]);
}
}
free(e->trie);
}
free(e);
}
}
int input_add_escape(notcurses* nc, const char* esc, ncspecial_key special){
esctrie** cur;
fprintf(stderr, "ADDING: %s for %d\n", esc, special);
if(esc[0] != ESC || strlen(esc) < 2){ // assume ESC prefix + content
return -1;
}
do{
++esc;
int validate = *esc;
if(validate < 0 || validate >= 0x80){
return -1;
}
if(nc->inputescapes == NULL){
cur = &nc->inputescapes;
}else if(validate){
if((*cur)->trie == NULL){
const size_t tsize = sizeof((*cur)->trie) * 0x80;
(*cur)->trie = malloc(tsize);
memset((*cur)->trie, 0, tsize);
}
cur = &(*cur)->trie[validate];
}
if(*cur == NULL){
if((*cur = create_esctrie_node(NCKEY_INVALID)) == NULL){
return -1;
}
}
}while(*esc);
if((*cur)->special){ // already had one here!
return -1;
}
(*cur)->special = special;
return 0;
}
// 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),
// return it, and pop it from the queue.
static int
handle_getc(notcurses* nc, cell* c, int kpress, ncspecial_key* special){
fprintf(stderr, "KEYPRESS: %d\n", kpress);
// fprintf(stderr, "KEYPRESS: %d\n", kpress);
if(kpress < 0){
return -1;
}
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);

@ -23,6 +23,7 @@ struct AVCodec;
struct AVCodecParameters;
struct AVPacket;
struct SwsContext;
struct esctrie;
// A plane is memory for some rectilinear virtual window, plus current cursor
// state for that window. A notcurses context describes a single terminal, and
@ -121,10 +122,17 @@ typedef struct notcurses {
unsigned inputbuf_occupied;
unsigned inputbuf_valid_starts;
unsigned inputbuf_write_at;
struct esctrie* inputescapes; // trie of input escapes -> ncspecial_keys
} notcurses;
extern sig_atomic_t resize_seen;
// add this escape sequence to the trie, resolving to the specified specialkey
int input_add_escape(notcurses* nc, const char* esc, ncspecial_key special);
// free up the input escapes trie
void input_free_esctrie(struct esctrie** trie);
#ifdef __cplusplus
}
#endif

@ -607,6 +607,7 @@ notcurses* notcurses_init(const notcurses_options* opts){
ret->stats.render_min_bytes = ~0UL;
ret->ttyfp = opts->outfp;
ret->renderfp = opts->renderfp;
ret->inputescapes = NULL;
ret->ttyinfp = stdin; // FIXME
if(make_nonblocking(ret->ttyinfp)){
free(ret);
@ -729,6 +730,7 @@ int notcurses_stop(notcurses* nc){
nc->top = p->z;
free_plane(p);
}
input_free_esctrie(&nc->inputescapes);
ret |= pthread_mutex_destroy(&nc->lock);
free(nc);
}

Loading…
Cancel
Save