Optimized general cursor moves #483

pull/495/head
nick black 5 years ago committed by Nick Black
parent 355ea6d3d7
commit e27895ef2e

@ -118,6 +118,11 @@ typedef struct renderstate {
FILE* mstreamfp;// FILE* for rendering memstream
size_t mstrsize;// size of rendering memstream
// the current cursor position. this is independent of whether the cursor is
// visible. it is the cell at which the next write will take place. this is
// modified by: output, cursor moves, clearing the screen (during refresh)
int y, x;
uint32_t curattr;// current attributes set (does not include colors)
unsigned lastr; // foreground rgb, overloaded for palindexed fg
unsigned lastg;
@ -296,6 +301,7 @@ typedef struct notcurses {
int colors; // number of colors terminfo reported usable for this screen
char* cup; // move cursor
char* cuf; // move n cells right
char* cub; // move n cells right
char* cuf1; // move 1 cell right
char* cub1; // move 1 cell left
char* civis; // hide cursor

@ -602,8 +602,9 @@ interrogate_terminfo(notcurses* nc, const notcurses_options* opts, int* dimy, in
term_verify_seq(&nc->cleareol, "el");
term_verify_seq(&nc->clearbol, "el1");
term_verify_seq(&nc->cuf, "cuf"); // n non-destructive spaces
term_verify_seq(&nc->cub, "cub"); // n non-destructive backspaces
term_verify_seq(&nc->cuf1, "cuf1"); // non-destructive space
term_verify_seq(&nc->cub1, "cub1");
term_verify_seq(&nc->cub1, "cub1"); // non-destructive backspace
term_verify_seq(&nc->smkx, "smkx"); // set application mode
if(nc->smkx){
if(putp(tiparm(nc->smkx)) != OK){

@ -801,6 +801,40 @@ update_palette(notcurses* nc, FILE* out){
return 0;
}
// sync the cursor to the specified location with as little overhead as
// possible (with nothing, if already at the right location).
// FIXME fall back to synthesized moves in the absence of capabilities (i.e.
// textronix lacks cup; fake it with horiz+vert moves)
static inline int
stage_cursor(notcurses* nc, FILE* out, int y, int x){
int ret;
if(nc->rstate.y == y){
if(nc->rstate.x == x){
return 0;
}else if(nc->rstate.x < x){
if(nc->rstate.x == x - 1){
ret = term_emit("cuf1", tiparm(nc->cuf1), out, false);
}else{
ret = term_emit("cuf", tiparm(nc->cuf, x - nc->rstate.x), out, false);
}
}else{
if(nc->rstate.x == x + 1){
ret = term_emit("cub1", tiparm(nc->cub1), out, false);
}else{
ret = term_emit("cub", tiparm(nc->cub, nc->rstate.x - x), out, false);
}
}
}else{
if((ret = term_emit("cup", tiparm(nc->cup, y, x), out, false)) >= 0){
nc->rstate.y = y;
}
}
if(ret >= 0){
nc->rstate.x = x;
}
return ret;
}
// Producing the frame requires three steps:
// * render -- build up a flat framebuffer from a set of ncplanes
// * rasterize -- build up a UTF-8 stream of escapes and EGCs
@ -852,12 +886,7 @@ notcurses_rasterize(notcurses* nc, const struct crender* rvec){
}
}else{
++nc->stats.cellemissions;
if(needmove == 1 && nc->cuf1){
ret |= term_emit("cuf1", tiparm(nc->cuf1), out, false);
}else if(needmove){ // FIXME might want to use cufN for horizontal move
ret |= term_emit("cup", tiparm(nc->cup, y, x), out, false);
}
needmove = 0;
ret |= stage_cursor(nc, out, y, x);
// set the style. this can change the color back to the default; if it
// does, we need update our elision possibilities.
bool normalized;
@ -962,7 +991,11 @@ fprintf(stderr, "RAST %u [%c] to %d/%d\n", srccell->gcluster, srccell->gcluster,
}else{
fprintf(stderr, "RAST %u [%s] to %d/%d\n", srccell->gcluster, egcpool_extended_gcluster(&nc->pool, srccell), y, x);
}*/
ret |= term_putc(out, &nc->pool, srccell);
if(term_putc(out, &nc->pool, srccell) == 0){
nc->rstate.x += 1 + cell_wide_left_p(srccell);
}else{
ret = -1;
}
}
if(cell_wide_left_p(srccell)){
++x;
@ -989,14 +1022,19 @@ fprintf(stderr, "RAST %u [%s] to %d/%d\n", srccell->gcluster, egcpool_extended_g
// the screen if need be.
static int
home_cursor(notcurses* nc, bool flush){
int ret = -1;
if(nc->home){
return term_emit("home", nc->home, nc->ttyfp, flush);
ret = term_emit("home", nc->home, nc->ttyfp, flush);
}else if(nc->cup){
return term_emit("cup", tiparm(nc->cup, 1, 1), nc->ttyfp, flush);
ret = term_emit("cup", tiparm(nc->cup, 1, 1), nc->ttyfp, flush);
}else if(nc->clearscr){
return term_emit("clear", nc->clearscr, nc->ttyfp, flush);
ret = term_emit("clear", nc->clearscr, nc->ttyfp, flush);
}
return -1;
if(ret >= 0){
nc->rstate.x = 0;
nc->rstate.y = 0;
}
return ret;
}
int notcurses_refresh(notcurses* nc, int* restrict dimy, int* restrict dimx){

Loading…
Cancel
Save