diff --git a/src/lib/direct.cpp b/src/lib/direct.cpp index 35f324f84..459a0f9a9 100644 --- a/src/lib/direct.cpp +++ b/src/lib/direct.cpp @@ -400,7 +400,6 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){ const bool bgdefault = ncdirect_bg_default_p(n); const uint32_t fgrgb = channels_fg_rgb(n->channels); const uint32_t bgrgb = channels_bg_rgb(n->channels); - bool pixelmode = false; for(int y = 0 ; y < dimy ; ++y){ if(xoff){ if(ncdirect_cursor_move_yx(n, -1, xoff)){ @@ -414,28 +413,15 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){ if(egc == nullptr){ return -1; } - if(!channels_pixel_p(channels)){ - if(pixelmode){ - if(term_emit(n->tcache.pixeloff, n->ttyfp, false)){ - return -1; - } - pixelmode = false; - } - if(channels_fg_alpha(channels) == CELL_ALPHA_TRANSPARENT){ - ncdirect_set_fg_default(n); - }else{ - ncdirect_set_fg_rgb(n, channels_fg_rgb(channels)); - } - if(channels_bg_alpha(channels) == CELL_ALPHA_TRANSPARENT){ - ncdirect_set_bg_default(n); - }else{ - ncdirect_set_bg_rgb(n, channels_bg_rgb(channels)); - } - }else if(!pixelmode){ - if(term_emit(n->tcache.pixelon, n->ttyfp, false)){ - return -1; - } - pixelmode = true; + if(channels_fg_alpha(channels) == CELL_ALPHA_TRANSPARENT){ + ncdirect_set_fg_default(n); + }else{ + ncdirect_set_fg_rgb(n, channels_fg_rgb(channels)); + } + if(channels_bg_alpha(channels) == CELL_ALPHA_TRANSPARENT){ + ncdirect_set_bg_default(n); + }else{ + ncdirect_set_bg_rgb(n, channels_bg_rgb(channels)); } //fprintf(stderr, "%03d/%03d [%s] (%03dx%03d)\n", y, x, egc, dimy, dimx); if(fprintf(n->ttyfp, "%s", strlen(egc) == 0 ? " " : egc) < 0){ @@ -447,23 +433,16 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){ // yes, we want to reset colors and emit an explicit new line following // each line of output; this is necessary if our output is lifted out and // used in something e.g. paste(1). - if(pixelmode){ - if(term_emit(n->tcache.pixeloff, n->ttyfp, false)){ - return -1; - } - pixelmode = false; - }else{ - // FIXME replace with a SGR clear - ncdirect_set_fg_default(n); - ncdirect_set_bg_default(n); - if(putc('\n', n->ttyfp) == EOF){ + // FIXME replace with a SGR clear + ncdirect_set_fg_default(n); + ncdirect_set_bg_default(n); + if(putc('\n', n->ttyfp) == EOF){ + return -1; + } + if(y == toty){ + if(ncdirect_cursor_down(n, 1)){ return -1; } - if(y == toty){ - if(ncdirect_cursor_down(n, 1)){ - return -1; - } - } } } // restore the previous colors diff --git a/src/lib/internal.h b/src/lib/internal.h index d7a06d79a..bfa79f01e 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -128,8 +128,6 @@ typedef struct rasterstate { bool bgpalelidable; bool fgdefelidable; bool bgdefelidable; - // are we in a pixel graphics mode? - bool pixelmode; } rasterstate; // Tablets are the toplevel entitites within an ncreel. Each corresponds to diff --git a/src/lib/render.c b/src/lib/render.c index 3f41fb843..1120151e8 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -580,58 +580,22 @@ ncfputc(char c, FILE* out){ #endif } -static int -enter_pixel_mode(notcurses* nc, FILE* out){ - if(!nc->rstate.pixelmode){ - if(term_emit(nc->tcache.pixelon, out, false)){ - return -1; - } - } - nc->rstate.pixelmode = true; - return 0; -} - -static int -leave_pixel_mode(notcurses* nc, FILE* out){ - if(term_emit(nc->tcache.pixeloff, out, false)){ - return -1; - } - nc->rstate.pixelmode = false; - return 0; -} - // write the nccell's UTF-8 extended grapheme cluster to the provided FILE*. static int -term_putc(notcurses* nc, FILE* out, const egcpool* e, const nccell* c){ - if(cell_pixels_p(c)){ - if(!nc->rstate.pixelmode){ - if(enter_pixel_mode(nc, out)){ +term_putc(FILE* out, const egcpool* e, const nccell* c){ + if(cell_simple_p(c)){ +//fprintf(stderr, "[%.4s] %08x\n", (const char*)&c->gcluster, c->gcluster); } + // we must not have any 'cntrl' characters at this point + if(c->gcluster == 0){ + if(ncfputc(' ', out) == EOF){ return -1; } - } - if(ncfputs(egcpool_extended_gcluster(e, c), out) == EOF){ + }else if(ncfputs((const char*)&c->gcluster, out) == EOF){ return -1; } }else{ - if(nc->rstate.pixelmode){ - if(leave_pixel_mode(nc, out)){ - return -1; - } - } - if(cell_simple_p(c)){ - //fprintf(stderr, "[%.4s] %08x\n", (const char*)&c->gcluster, c->gcluster); } - // we must not have any 'cntrl' characters at this point - if(c->gcluster == 0){ - if(ncfputc(' ', out) == EOF){ - return -1; - } - }else if(ncfputs((const char*)&c->gcluster, out) == EOF){ - return -1; - } - }else{ - if(ncfputs(egcpool_extended_gcluster(e, c), out) == EOF){ - return -1; - } + if(ncfputs(egcpool_extended_gcluster(e, c), out) == EOF){ + return -1; } } return 0; @@ -863,19 +827,17 @@ update_palette(notcurses* nc, FILE* out){ // our understanding of our horizontal location is faulty. // FIXME fall back to synthesized moves in the absence of capabilities (i.e. // textronix lacks cup; fake it with horiz+vert moves) +// if hardposupdate is non-zero, we always perform a cup static inline int -goto_location(notcurses* nc, FILE* out, int y, int x){ +goto_location(notcurses* nc, FILE* out, int y, int x, unsigned hardposupdate){ int ret = 0; // if we don't have hpa, force a cup even if we're only 1 char away. the only // terminal i know supporting cup sans hpa is vt100, and vt100 can suck it. // you can't use cuf for backwards moves anyway; again, vt100 can suck it. - if(nc->rstate.y == y && nc->tcache.hpa){ // only need move x + if(nc->rstate.y == y && nc->tcache.hpa && !hardposupdate){ // only need move x if(nc->rstate.x == x){ // needn't move shit return 0; } - if(nc->rstate.pixelmode && leave_pixel_mode(nc, out)){ - return -1; - } if(x == nc->rstate.x + 1 && nc->tcache.cuf1){ ret = term_emit(nc->tcache.cuf1, out, false); }else{ @@ -883,9 +845,6 @@ goto_location(notcurses* nc, FILE* out, int y, int x){ } }else{ // cup is required, no need to check for existence - if(nc->rstate.pixelmode && leave_pixel_mode(nc, out)){ - return -1; - } ret = term_emit(tiparm(nc->tcache.cup, y, x), out, false); } if(ret == 0){ @@ -958,6 +917,7 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){ // we explicitly move the cursor at the beginning of each output line, so no // need to home it expliticly. update_palette(nc, out); + bool hardposupdate = false; //fprintf(stderr, "pile %p ymax: %d xmax: %d\n", p, p->dimy + nc->stdplane->absy, p->dimx + nc->stdplane->absx); for(y = nc->stdplane->absy ; y < p->dimy + nc->stdplane->absy ; ++y){ const int innery = y - nc->stdplane->absy; @@ -975,9 +935,10 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){ } }else{ ++nc->stats.cellemissions; - if(goto_location(nc, out, y, x)){ + if(goto_location(nc, out, y, x, hardposupdate)){ return -1; } + hardposupdate = false; if(!cell_pixels_p(srccell)){ // set the style. this can change the color back to the default; if it // does, we need update our elision possibilities. @@ -1069,9 +1030,13 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){ } } //fprintf(stderr, "RAST %08x [%s] to %d/%d cols: %u %016lx\n", srccell->gcluster, pool_extended_gcluster(&nc->pool, srccell), y, x, srccell->width, srccell->channels); - if(term_putc(nc, out, &nc->pool, srccell)){ + if(term_putc(out, &nc->pool, srccell)){ return -1; } + // if we just emitted a sixel, always force a hard cursor relocation + if(cell_pixels_p(srccell)){ + hardposupdate = true; + } ++nc->rstate.x; if(srccell->width >= 2){ x += srccell->width - 1; @@ -1400,7 +1365,7 @@ int notcurses_cursor_enable(notcurses* nc, int y, int x){ if(nc->ttyfd < 0 || !nc->tcache.cnorm){ return -1; } - if(goto_location(nc, nc->ttyfp, y + nc->stdplane->absy, x + nc->stdplane->absx)){ + if(goto_location(nc, nc->ttyfp, y + nc->stdplane->absy, x + nc->stdplane->absx, 0)){ return -1; } // if we were already positive, we're already visible, no need to write cnorm