mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
extract fill_buffer #1692
This commit is contained in:
parent
73324ce2a4
commit
2240880718
@ -431,15 +431,12 @@ enqueue_cursor_report(ncinputlayer* nc, const ncinput* ni){
|
|||||||
}
|
}
|
||||||
clr->y = ni->y;
|
clr->y = ni->y;
|
||||||
clr->x = ni->x;
|
clr->x = ni->x;
|
||||||
pthread_mutex_lock(&nc->creport_lock);
|
|
||||||
// i don't think we ever want to have more than one here. we don't actually
|
// i don't think we ever want to have more than one here. we don't actually
|
||||||
// have any control logic which leads to multiple outstanding requests, so
|
// have any control logic which leads to multiple outstanding requests, so
|
||||||
// any that arrive are presumably garbage from the bulk input (and probably
|
// any that arrive are presumably garbage from the bulk input (and probably
|
||||||
// ought be returned to the user).
|
// ought be returned to the user).
|
||||||
free(nc->creport_queue);
|
free(nc->creport_queue);
|
||||||
nc->creport_queue = clr;
|
nc->creport_queue = clr;
|
||||||
pthread_mutex_unlock(&nc->creport_lock);
|
|
||||||
pthread_cond_signal(&nc->creport_cond);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,16 +464,18 @@ handle_queued_input(ncinputlayer* nc, ncinput* ni, int leftmargin, int topmargin
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is where the user input chain actually calls read(2).
|
// this is the only function which actually reads, and it can be called from
|
||||||
static char32_t
|
// either our context (looking for cursor reports) or the user's. all it does
|
||||||
handle_input(ncinputlayer* nc, ncinput* ni, int leftmargin, int topmargin,
|
// is attempt to fill up the input ringbuffer, exiting either when that
|
||||||
const sigset_t* sigmask){
|
// condition is met, or when we get an EAGAIN. it does no processing.
|
||||||
|
static int
|
||||||
|
fill_buffer(ncinputlayer* nc, const sigset_t* sigmask){
|
||||||
ssize_t r = 0;
|
ssize_t r = 0;
|
||||||
size_t rlen;
|
size_t rlen;
|
||||||
//fprintf(stderr, "OCCUPY: %u@%u read: %d %zd\n", nc->inputbuf_occupied, nc->inputbuf_write_at, nc->inputbuf[nc->inputbuf_write_at], r);
|
//fprintf(stderr, "OCCUPY: %u@%u read: %d %zd\n", nc->inputbuf_occupied, nc->inputbuf_write_at, nc->inputbuf[nc->inputbuf_write_at], r);
|
||||||
if((rlen = input_queue_space(nc)) > 0){
|
if((rlen = input_queue_space(nc)) > 0){
|
||||||
// if we have at least as much available as we do room to the end, read
|
// if we have at least as much available as we do room to the end, read
|
||||||
// all the way to the end. otherwise, read as much as we have available.
|
// only to the end. otherwise, read as much as we have available.
|
||||||
if(rlen >= sizeof(nc->inputbuf) / sizeof(*nc->inputbuf) - nc->inputbuf_write_at){
|
if(rlen >= sizeof(nc->inputbuf) / sizeof(*nc->inputbuf) - nc->inputbuf_write_at){
|
||||||
rlen = sizeof(nc->inputbuf) / sizeof(*nc->inputbuf) - nc->inputbuf_write_at;
|
rlen = sizeof(nc->inputbuf) / sizeof(*nc->inputbuf) - nc->inputbuf_write_at;
|
||||||
}
|
}
|
||||||
@ -486,12 +485,31 @@ handle_input(ncinputlayer* nc, ncinput* ni, int leftmargin, int topmargin,
|
|||||||
nc->inputbuf_write_at = 0;
|
nc->inputbuf_write_at = 0;
|
||||||
}
|
}
|
||||||
nc->inputbuf_occupied += r;
|
nc->inputbuf_occupied += r;
|
||||||
|
// specify a 0 timeout, meaning we only check to see if there's more
|
||||||
|
// input available immediately. basically, if we only read through the
|
||||||
|
// end of the ringbuffer, this gets us the first part filled as well.
|
||||||
|
// this is less about performance, and more about avoiding partial
|
||||||
|
// reads of multibyte characters and control sequences.
|
||||||
const struct timespec ts = {};
|
const struct timespec ts = {};
|
||||||
if(block_on_input(nc->infd, &ts, sigmask) < 1){
|
if(block_on_input(nc->infd, &ts, sigmask) < 1){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(r < 0){
|
||||||
|
if(errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// user-mode call to actual input i/o, which will get the next character from
|
||||||
|
// the input buffer.
|
||||||
|
static char32_t
|
||||||
|
handle_input(ncinputlayer* nc, ncinput* ni, int leftmargin, int topmargin,
|
||||||
|
const sigset_t* sigmask){
|
||||||
|
fill_buffer(nc, sigmask);
|
||||||
// highest priority is resize notifications, since they don't queue
|
// highest priority is resize notifications, since they don't queue
|
||||||
if(resize_seen){
|
if(resize_seen){
|
||||||
resize_seen = 0;
|
resize_seen = 0;
|
||||||
@ -693,12 +711,12 @@ prep_special_keys(ncinputlayer* nc){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ncinputlayer_stop(ncinputlayer* nilayer){
|
void ncinputlayer_stop(ncinputlayer* nilayer){
|
||||||
if(pthread_mutex_destroy(&nilayer->creport_lock)){
|
|
||||||
logerror("Error destroying cqueue mutex\n");
|
|
||||||
}
|
|
||||||
if(pthread_cond_destroy(&nilayer->creport_cond)){
|
if(pthread_cond_destroy(&nilayer->creport_cond)){
|
||||||
logerror("Error destroying cqueue condvar\n");
|
logerror("Error destroying cqueue condvar\n");
|
||||||
}
|
}
|
||||||
|
if(pthread_mutex_destroy(&nilayer->lock)){
|
||||||
|
logerror("Error destroying mutex\n");
|
||||||
|
}
|
||||||
cursorreport* clr;
|
cursorreport* clr;
|
||||||
while( (clr = nilayer->creport_queue) ){
|
while( (clr = nilayer->creport_queue) ){
|
||||||
nilayer->creport_queue = clr->next;
|
nilayer->creport_queue = clr->next;
|
||||||
@ -1378,11 +1396,16 @@ err:
|
|||||||
int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
|
int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
|
||||||
unsigned* appsync, int* cursor_y, int* cursor_x){
|
unsigned* appsync, int* cursor_y, int* cursor_x){
|
||||||
ncinputlayer* nilayer = &tcache->input;
|
ncinputlayer* nilayer = &tcache->input;
|
||||||
|
// FIXME unsafe to do after infp has been used; do we need this?
|
||||||
setbuffer(infp, NULL, 0);
|
setbuffer(infp, NULL, 0);
|
||||||
|
if(pthread_mutex_init(&nilayer->lock, NULL)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
nilayer->inputescapes = NULL;
|
nilayer->inputescapes = NULL;
|
||||||
nilayer->infd = fileno(infp);
|
nilayer->infd = fileno(infp);
|
||||||
nilayer->ttyfd = isatty(nilayer->infd) ? -1 : get_tty_fd(infp);
|
nilayer->ttyfd = isatty(nilayer->infd) ? -1 : get_tty_fd(infp);
|
||||||
if(prep_special_keys(nilayer)){
|
if(prep_special_keys(nilayer)){
|
||||||
|
pthread_mutex_destroy(&nilayer->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nilayer->inputbuf_occupied = 0;
|
nilayer->inputbuf_occupied = 0;
|
||||||
@ -1390,7 +1413,6 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
|
|||||||
nilayer->inputbuf_write_at = 0;
|
nilayer->inputbuf_write_at = 0;
|
||||||
nilayer->input_events = 0;
|
nilayer->input_events = 0;
|
||||||
nilayer->creport_queue = NULL;
|
nilayer->creport_queue = NULL;
|
||||||
pthread_mutex_init(&nilayer->creport_lock, NULL);
|
|
||||||
pthread_cond_init(&nilayer->creport_cond, NULL);
|
pthread_cond_init(&nilayer->creport_cond, NULL);
|
||||||
int csifd = nilayer->ttyfd >= 0 ? nilayer->ttyfd : nilayer->infd;
|
int csifd = nilayer->ttyfd >= 0 ? nilayer->ttyfd : nilayer->infd;
|
||||||
if(isatty(csifd)){
|
if(isatty(csifd)){
|
||||||
@ -1404,6 +1426,8 @@ int ncinputlayer_init(tinfo* tcache, FILE* infp, queried_terminals_e* detected,
|
|||||||
if(control_read(csifd, &inits)){
|
if(control_read(csifd, &inits)){
|
||||||
input_free_esctrie(&nilayer->inputescapes);
|
input_free_esctrie(&nilayer->inputescapes);
|
||||||
free(inits.version);
|
free(inits.version);
|
||||||
|
pthread_cond_destroy(&nilayer->creport_cond);
|
||||||
|
pthread_mutex_destroy(&nilayer->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tcache->bg_collides_default = inits.bg;
|
tcache->bg_collides_default = inits.bg;
|
||||||
|
@ -784,19 +784,19 @@ int locate_cursor(tinfo* ti, int fd, int* cursor_y, int* cursor_x){
|
|||||||
}
|
}
|
||||||
bool emitted_u7 = false; // only want to send one max
|
bool emitted_u7 = false; // only want to send one max
|
||||||
cursorreport* clr;
|
cursorreport* clr;
|
||||||
pthread_mutex_lock(&ti->input.creport_lock);
|
pthread_mutex_lock(&ti->input.lock);
|
||||||
while((clr = ti->input.creport_queue) == NULL){
|
while((clr = ti->input.creport_queue) == NULL){
|
||||||
if(!emitted_u7){
|
if(!emitted_u7){
|
||||||
// FIXME i'd rather not do this while holding the lock =[
|
// FIXME i'd rather not do this while holding the lock =[
|
||||||
if(tty_emit(u7, fd)){
|
if(tty_emit(u7, fd)){
|
||||||
pthread_mutex_unlock(&ti->input.creport_lock);
|
pthread_mutex_unlock(&ti->input.lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
emitted_u7 = true;
|
emitted_u7 = true;
|
||||||
}
|
}
|
||||||
pthread_cond_wait(&ti->input.creport_cond, &ti->input.creport_lock);
|
pthread_cond_wait(&ti->input.creport_cond, &ti->input.lock);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&ti->input.creport_lock);
|
pthread_mutex_unlock(&ti->input.lock);
|
||||||
*cursor_y = clr->y;
|
*cursor_y = clr->y;
|
||||||
*cursor_x = clr->x;
|
*cursor_x = clr->x;
|
||||||
if(ti->inverted_cursor){
|
if(ti->inverted_cursor){
|
||||||
|
@ -84,6 +84,9 @@ typedef struct cursorreport {
|
|||||||
// read data only from stdin and control only from the tty. if we have
|
// read data only from stdin and control only from the tty. if we have
|
||||||
// no connected tty, only data is available.
|
// no connected tty, only data is available.
|
||||||
typedef struct ncinputlayer {
|
typedef struct ncinputlayer {
|
||||||
|
// only allow one reader at a time, whether it's the user trying to do so,
|
||||||
|
// or our desire for a cursor report competing with the user.
|
||||||
|
pthread_mutex_t lock;
|
||||||
// ttyfd is only valid if we are connected to a tty, *and* stdin is not
|
// ttyfd is only valid if we are connected to a tty, *and* stdin is not
|
||||||
// connected to that tty. in that case, we read control sequences only
|
// connected to that tty. in that case, we read control sequences only
|
||||||
// from ttyfd.
|
// from ttyfd.
|
||||||
@ -103,7 +106,6 @@ typedef struct ncinputlayer {
|
|||||||
uint64_t input_events;
|
uint64_t input_events;
|
||||||
struct esctrie* inputescapes; // trie of input escapes -> ncspecial_keys
|
struct esctrie* inputescapes; // trie of input escapes -> ncspecial_keys
|
||||||
cursorreport* creport_queue; // queue of cursor reports
|
cursorreport* creport_queue; // queue of cursor reports
|
||||||
pthread_mutex_t creport_lock;
|
|
||||||
pthread_cond_t creport_cond;
|
pthread_cond_t creport_cond;
|
||||||
} ncinputlayer;
|
} ncinputlayer;
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@ int main(void){
|
|||||||
// FIXME do full permutations?
|
// FIXME do full permutations?
|
||||||
ncplane_set_styles(n, NCSTYLE_NONE);
|
ncplane_set_styles(n, NCSTYLE_NONE);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ none");
|
ncplane_putstr_yx(n, y++, 0, "a ═ none");
|
||||||
ncplane_set_styles(n, NCSTYLE_BLINK);
|
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ blink");
|
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC);
|
ncplane_set_styles(n, NCSTYLE_ITALIC);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic");
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic");
|
||||||
ncplane_set_styles(n, NCSTYLE_BOLD);
|
ncplane_set_styles(n, NCSTYLE_BOLD);
|
||||||
@ -32,16 +30,18 @@ int main(void){
|
|||||||
ncplane_putstr_yx(n, y++, 0, "a ═ struck");
|
ncplane_putstr_yx(n, y++, 0, "a ═ struck");
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_BOLD);
|
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_BOLD);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic bold");
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic bold");
|
||||||
|
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_BOLD | NCSTYLE_STRUCK);
|
||||||
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic bold struck");
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERCURL);
|
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERCURL);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic undercurl");
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic undercurl");
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERLINE);
|
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERLINE);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic underline");
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic underline");
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_STRUCK);
|
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_STRUCK);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic struck");
|
ncplane_putstr_yx(n, y++, 0, "a ═ italic struck");
|
||||||
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_STRUCK);
|
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ italic struck");
|
|
||||||
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_BOLD);
|
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_BOLD);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ struck bold");
|
ncplane_putstr_yx(n, y++, 0, "a ═ struck bold");
|
||||||
|
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_BOLD | NCSTYLE_ITALIC);
|
||||||
|
ncplane_putstr_yx(n, y++, 0, "a ═ struck bold italic");
|
||||||
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERCURL);
|
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERCURL);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ struck undercurl");
|
ncplane_putstr_yx(n, y++, 0, "a ═ struck undercurl");
|
||||||
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERLINE);
|
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERLINE);
|
||||||
@ -66,10 +66,6 @@ int main(void){
|
|||||||
ncplane_putstr_yx(n, y++, 0, "a ═ bold underline italic struck");
|
ncplane_putstr_yx(n, y++, 0, "a ═ bold underline italic struck");
|
||||||
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERCURL | NCSTYLE_ITALIC | NCSTYLE_STRUCK);
|
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERCURL | NCSTYLE_ITALIC | NCSTYLE_STRUCK);
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ bold undercurl italic struck");
|
ncplane_putstr_yx(n, y++, 0, "a ═ bold undercurl italic struck");
|
||||||
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERLINE | NCSTYLE_ITALIC | NCSTYLE_STRUCK | NCSTYLE_BLINK);
|
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ bold underline italic struck blink");
|
|
||||||
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERCURL | NCSTYLE_ITALIC | NCSTYLE_STRUCK | NCSTYLE_BLINK);
|
|
||||||
ncplane_putstr_yx(n, y++, 0, "a ═ bold undercurl italic struck blink");
|
|
||||||
|
|
||||||
ncplane_set_styles(n, NCSTYLE_NONE);
|
ncplane_set_styles(n, NCSTYLE_NONE);
|
||||||
if(notcurses_render(nc)){
|
if(notcurses_render(nc)){
|
||||||
|
Loading…
Reference in New Issue
Block a user