diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 0515a83a2..c12d9a75b 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -24,8 +24,6 @@ #include "version.h" #include "egcpool.h" -#define ESC "\x1b" - // only one notcurses object can be the target of signal handlers, due to their // process-wide nature. static notcurses* _Atomic signal_nc = ATOMIC_VAR_INIT(NULL); // ugh @@ -901,16 +899,32 @@ int ncplane_default(ncplane* ncp, cell* c){ // 3 for foreground, 4 for background, ugh FIXME static int -term_esc_rgb(FILE* out, int esc, unsigned r, unsigned g, unsigned b){ - #define RGBESC1 ESC "[" +term_esc_rgb(notcurses* nc __attribute__ ((unused)), FILE* out, int esc, + unsigned r, unsigned g, unsigned b){ + // The correct way to do this is using tiparm+tputs, but doing so (at least + // as of terminfo 6.1.20191019) both emits ~3% more bytes for a run of 'rgb' + // and gives rise to some corrupted cells (possibly due to special handling of + // values < 256; I'm not at this time sure). So we just cons up our own. + /*if(esc == 4){ + return term_emit("setab", tiparm(nc->setab, (int)((r << 16u) | (g << 8u) | b)), out, false); + }else if(esc == 3){ + return term_emit("setaf", tiparm(nc->setaf, (int)((r << 16u) | (g << 8u) | b)), out, false); + }else{ + return -1; + }*/ + #define RGBESC1 "\x1b" "[" #define RGBESC2 "8;2;" // rrr;ggg;bbbm char rgbesc[] = RGBESC1 " " RGBESC2 " "; int len = strlen(RGBESC1); - rgbesc[len++] = esc + '0'; + rgbesc[len++] = esc; len += strlen(RGBESC2); - if(r > 99){ rgbesc[len++] = r / 100 + '0'; } - if(r > 9){ rgbesc[len++] = (r % 100) / 10 + '0'; } + if(r > 99){ + rgbesc[len++] = r / 100 + '0'; + } + if(r > 9){ + rgbesc[len++] = (r % 100) / 10 + '0'; + } rgbesc[len++] = (r % 10) + '0'; rgbesc[len++] = ';'; if(g > 99){ rgbesc[len++] = g / 100 + '0'; } @@ -923,7 +937,7 @@ term_esc_rgb(FILE* out, int esc, unsigned r, unsigned g, unsigned b){ rgbesc[len++] = 'm'; rgbesc[len] = '\0'; int w; - if((w = fprintf(out, "%.*s", len, rgbesc)) < len){ + if((w = fputs_unlocked(rgbesc, out)) < len){ return -1; } return 0; @@ -937,7 +951,7 @@ term_bg_rgb8(notcurses* nc, FILE* out, unsigned r, unsigned g, unsigned b){ // we're also in that case working with hopefully more robust terminals. // If it doesn't work, eh, it doesn't work. Fuck the world; save yourself. if(nc->RGBflag){ - return term_esc_rgb(out, 4, r, g, b); + return term_esc_rgb(nc, out, '4', r, g, b); }else{ if(nc->setab == NULL){ return -1; @@ -962,7 +976,7 @@ term_fg_rgb8(notcurses* nc, FILE* out, unsigned r, unsigned g, unsigned b){ // we're also in that case working with hopefully more robust terminals. // If it doesn't work, eh, it doesn't work. Fuck the world; save yourself. if(nc->RGBflag){ - return term_esc_rgb(out, 3, r, g, b); + return term_esc_rgb(nc, out, '3', r, g, b); }else{ if(nc->setaf == NULL){ return -1; @@ -997,19 +1011,19 @@ term_putc(FILE* out, const ncplane* n, const cell* c){ if(cell_simple_p(c)){ if(c->gcluster == 0 || iscntrl(c->gcluster)){ // fprintf(stderr, "[ ]\n"); - if(fputc(' ', out) == EOF){ + if(fputc_unlocked(' ', out) == EOF){ return -1; } }else{ // fprintf(stderr, "[%c]\n", c->gcluster); - if(fputc(c->gcluster, out) == EOF){ + if(fputc_unlocked(c->gcluster, out) == EOF){ return -1; } } }else{ const char* ext = extended_gcluster(n, c); // fprintf(stderr, "[%s]\n", ext); - if(fprintf(out, "%s", ext) < 0){ // FIXME check for short write? + if(fputs_unlocked(ext, out) < 0){ // FIXME check for short write? return -1; } }