diff --git a/src/lib/direct.c b/src/lib/direct.c index 018df3069..abb369aa5 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -877,46 +877,10 @@ char* ncdirect_readline(ncdirect* n, const char* prompt){ static inline int ncdirect_style_emit(ncdirect* n, unsigned stylebits, FILE* out){ - int r = -1; - const char* esc; - if(stylebits == 0 && (esc = get_escape(&n->tcache, ESCAPE_SGR0))){ - r = term_emit(esc, out, false); - }else if( (esc = get_escape(&n->tcache, ESCAPE_SGR)) ){ - r = term_emit(tiparm(esc, - 0, // standout - stylebits & NCSTYLE_UNDERLINE, - 0, // reverse - 0, // blink - 0, // dim - stylebits & NCSTYLE_BOLD, - 0, // invisible - 0, // protect // - 0), out, false); - }else{ - // no sgr, interesting. return failure if our stylebits were provided? - // back off to individual enablers? FIXME - return 0; - } - // sgr will blow away non-sgr properties if they were set beforehand - n->stylemask &= ~(NCSTYLE_ITALIC | NCSTYLE_STRUCK | NCSTYLE_UNDERCURL); - if(term_setstyle(n->ttyfp, n->stylemask, stylebits, NCSTYLE_ITALIC, - get_escape(&n->tcache, ESCAPE_SITM), - get_escape(&n->tcache, ESCAPE_RITM))){ - return -1; - } - if(term_setstyle(n->ttyfp, n->stylemask, stylebits, NCSTYLE_STRUCK, - get_escape(&n->tcache, ESCAPE_SMXX), - get_escape(&n->tcache, ESCAPE_RMXX))){ - return -1; - } - if(term_setstyle(n->ttyfp, n->stylemask, stylebits, NCSTYLE_UNDERCURL, - get_escape(&n->tcache, ESCAPE_SMULX), - get_escape(&n->tcache, ESCAPE_SMULNOX))){ - return -1; - } - n->stylemask = stylebits; - // sgr resets colors, so set them back up if not defaults - if(r == 0){ + unsigned normalized = 0; + int r = coerce_styles(out, &n->tcache, &n->stylemask, stylebits, &normalized); + // sgr0 resets colors, so set them back up if not defaults and it was used + if(normalized){ // emitting an sgr resets colors. if we want to be default, that's no // problem, and our channels remain correct. otherwise, clear our // channel, and set them back up. diff --git a/src/lib/internal.h b/src/lib/internal.h index f472f122f..af2152fd9 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -259,13 +259,13 @@ typedef struct rasterstate { // 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 lastr; // foreground rgb, overloaded for palindexed fg unsigned lastg; unsigned lastb; - unsigned lastbr; // background rgb, overloaded for palindexed bg + unsigned lastbr; // background rgb, overloaded for palindexed bg unsigned lastbg; unsigned lastbb; + uint16_t curattr; // current attributes set (does not include colors) // we elide a color escape iff the color has not changed between two cells bool fgelidable; bool bgelidable; @@ -1237,8 +1237,61 @@ term_fg_palindex(const notcurses* nc, FILE* out, unsigned pal){ return 0; } -int term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit, - const char* ton, const char* toff); +// check the current and target style bitmasks against the specified 'stylebit'. +// if they are different, and we have the necessary capability, write the +// applicable terminfo entry to 'out'. returns -1 only on a true error. +static int +term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit, + const char* ton, const char* toff){ + int ret = 0; + unsigned curon = cur & stylebit; + unsigned targon = targ & stylebit; + if(curon != targon){ + if(targon){ + if(ton){ + ret = term_emit(ton, out, false); + } + }else{ + if(toff){ // how did this happen? we can turn it on, but not off? + ret = term_emit(toff, out, false); + } + } + } + if(ret < 0){ + return -1; + } + return 0; +} + +// emit escapes such that the current style is equal to newstyle. if this +// required an sgr0 (which resets colors), normalized will be non-zero upon +// a successful return. +static inline int +coerce_styles(FILE* out, const tinfo* ti, uint16_t* curstyle, + uint16_t newstyle, unsigned* normalized){ + *normalized = 0; // we never currently use sgr0 + int ret = 0; + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_BOLD, + get_escape(ti, ESCAPE_BOLD), get_escape(ti, ESCAPE_NOBOLD)); + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_ITALIC, + get_escape(ti, ESCAPE_SITM), get_escape(ti, ESCAPE_RITM)); + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_STRUCK, + get_escape(ti, ESCAPE_SMXX), get_escape(ti, ESCAPE_RMXX)); + // underline and undercurl are exclusive. if we set one, don't go unsetting + // the other. + if(newstyle & NCSTYLE_UNDERLINE){ // turn on underline, or do nothing + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERLINE, + get_escape(ti, ESCAPE_SMUL), get_escape(ti, ESCAPE_RMUL)); + }else if(newstyle & NCSTYLE_UNDERCURL){ // turn on undercurl, or do nothing + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERCURL, + get_escape(ti, ESCAPE_SMULX), get_escape(ti, ESCAPE_SMULNOX)); + }else{ // turn off any underlining + ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERCURL | NCSTYLE_UNDERLINE, + NULL, get_escape(ti, ESCAPE_RMUL)); + } + *curstyle = newstyle; + return ret; +} // how many edges need touch a corner for it to be printed? static inline unsigned diff --git a/src/lib/render.c b/src/lib/render.c index 65a37ac1c..eeed3de84 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -545,61 +545,6 @@ term_putc(FILE* out, const egcpool* e, const nccell* c){ return 0; } -// check the current and target style bitmasks against the specified 'stylebit'. -// if they are different, and we have the necessary capability, write the -// applicable terminfo entry to 'out'. returns -1 only on a true error. -int term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit, - const char* ton, const char* toff){ - int ret = 0; - unsigned curon = cur & stylebit; - unsigned targon = targ & stylebit; - if(curon != targon){ - if(targon){ - if(ton){ - ret = term_emit(ton, out, false); - } - }else{ - if(toff){ // how did this happen? we can turn it on, but not off? - ret = term_emit(toff, out, false); - } - } - } - if(ret < 0){ - return -1; - } - return 0; -} - -// emit escapes such that the current style is equal to newstyle. if this -// required an sgr0 (which resets colors), normalized will be non-zero upon -// a successful return. -static inline int -coerce_styles(FILE* out, const tinfo* ti, uint32_t* curstyle, - uint32_t newstyle, unsigned* normalized){ - *normalized = 0; // we never currently use sgr0 - int ret = 0; - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_BOLD, - get_escape(ti, ESCAPE_BOLD), get_escape(ti, ESCAPE_NOBOLD)); - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_ITALIC, - get_escape(ti, ESCAPE_SITM), get_escape(ti, ESCAPE_RITM)); - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_STRUCK, - get_escape(ti, ESCAPE_SMXX), get_escape(ti, ESCAPE_RMXX)); - // underline and undercurl are exclusive. if we set one, don't go unsetting - // the other. - if(newstyle & NCSTYLE_UNDERLINE){ // turn on underline, or do nothing - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERLINE, - get_escape(ti, ESCAPE_SMUL), get_escape(ti, ESCAPE_RMUL)); - }else if(newstyle & NCSTYLE_UNDERCURL){ // turn on undercurl, or do nothing - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERCURL, - get_escape(ti, ESCAPE_SMULX), get_escape(ti, ESCAPE_SMULNOX)); - }else{ // turn off any underlining - ret |= term_setstyle(out, *curstyle, newstyle, NCSTYLE_UNDERCURL | NCSTYLE_UNDERLINE, - NULL, get_escape(ti, ESCAPE_RMUL)); - } - *curstyle = newstyle; - return ret; -} - // write any escape sequences necessary to set the desired style static inline int term_setstyles(FILE* out, notcurses* nc, const nccell* c){ diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index e18f235c0..9d6a9bfdb 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -469,7 +469,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8, { NCSTYLE_STRUCK, "smxx", 0 }, { 0, NULL, 0 } }; - if(get_escape(ti, ESCAPE_BOLD) == NULL){ + if(get_escape(ti, ESCAPE_BOLD)){ if(grow_esc_table(ti, "\e[22m", ESCAPE_NOBOLD, &tablelen, &tableused)){ goto err; }