op/fgop/bgop into escape block #1525

pull/1693/head
nick black 3 years ago committed by Nick Black
parent 6767a36996
commit 1207765cc8

@ -21,7 +21,9 @@ tinfo_debug_caps(const tinfo* ti, FILE* debugfp, int rows, int cols,
fprintf(debugfp, "%ssgr: %c sgr0: %c\n",
indent, capyn(ti->sgr), capyn(ti->sgr0));
fprintf(debugfp, "%sop: %c fgop: %c bgop: %c\n",
indent, capyn(ti->op), capyn(ti->fgop), capyn(ti->bgop));
indent, capyn(get_escape(ti, ESCAPE_OP)),
capyn(get_escape(ti, ESCAPE_FGOP)),
capyn(get_escape(ti, ESCAPE_BGOP)));
fprintf(debugfp, "%srows: %u cols: %u rpx: %u cpx: %u (%dx%d)\n",
indent, rows, cols, ti->cellpixy, ti->cellpixx, rows * ti->cellpixy, cols * ti->cellpixx);
if(!ti->pixel_query_done){

@ -702,15 +702,7 @@ ncdirect_stop_minimal(void* vnc){
if(nc->initialized_readline){
rl_deprep_terminal();
}
if(nc->tcache.op && term_emit(nc->tcache.op, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit(nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit(nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
ret |= reset_term_attributes(&nc->tcache, nc->ttyfp);
if(nc->ctermfd >= 0){
if(nc->tcache.pixel_shutdown){
ret |= nc->tcache.pixel_shutdown(nc->ctermfd);
@ -917,11 +909,15 @@ int ncdirect_set_fg_default(ncdirect* nc){
if(ncdirect_fg_default_p(nc)){
return 0;
}
if(nc->tcache.fgop){
if(term_emit(nc->tcache.fgop, nc->ttyfp, false)){
const char* esc;
if((esc = get_escape(&nc->tcache, ESCAPE_FGOP)) != NULL){
if(term_emit(esc, nc->ttyfp, false)){
return -1;
}
}else if((esc = get_escape(&nc->tcache, ESCAPE_OP)) != NULL){
if(term_emit(esc, nc->ttyfp, false)){
return -1;
}
}else if(term_emit(nc->tcache.op, nc->ttyfp, false) == 0){
if(!ncdirect_bg_default_p(nc)){
if(ncdirect_set_bg_rgb(nc, ncchannels_bg_rgb(nc->channels))){
return -1;
@ -936,11 +932,15 @@ int ncdirect_set_bg_default(ncdirect* nc){
if(ncdirect_bg_default_p(nc)){
return 0;
}
if(nc->tcache.bgop){
if(term_emit(nc->tcache.bgop, nc->ttyfp, false)){
const char* esc;
if((esc = get_escape(&nc->tcache, ESCAPE_BGOP)) != NULL){
if(term_emit(esc, nc->ttyfp, false)){
return -1;
}
}else if((esc = get_escape(&nc->tcache, ESCAPE_OP)) != NULL){
if(term_emit(esc, nc->ttyfp, false)){
return -1;
}
}else if(term_emit(nc->tcache.op, nc->ttyfp, false) == 0){
if(!ncdirect_fg_default_p(nc)){
if(ncdirect_set_fg_rgb(nc, ncchannels_fg_rgb(nc->channels))){
return -1;

@ -613,6 +613,8 @@ void init_lang(notcurses* nc); // nc may be NULL, only used for logging
int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
unsigned utf8, unsigned noaltscreen);
int reset_term_attributes(const tinfo* ti, FILE* fp);
void free_terminfo_cache(tinfo* ti);
// perform queries that require writing to the terminal, and reading a

@ -36,20 +36,18 @@ void notcurses_version_components(int* major, int* minor, int* patch, int* tweak
// reset the current colors, styles, and palette. called on startup (to purge
// any preexisting styling) and shutdown (to not affect further programs).
// nc->ttyfd must be valid.
static int
reset_term_attributes(notcurses* nc){
int reset_term_attributes(const tinfo* ti, FILE* fp){
int ret = 0;
if(nc->tcache.op && tty_emit(nc->tcache.op, nc->ttyfd)){
const char* esc;
if((esc = get_escape(ti, ESCAPE_OP)) && term_emit(esc, fp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && tty_emit(nc->tcache.sgr0, nc->ttyfd)){
if(ti->sgr0 && term_emit(ti->sgr0, fp, true)){
ret = -1;
}
if(nc->tcache.oc && tty_emit(nc->tcache.oc, nc->ttyfd)){
if(ti->oc && term_emit(ti->oc, fp, true)){
ret = -1;
}
ret |= notcurses_mouse_disable(nc);
return ret;
}
@ -73,7 +71,8 @@ notcurses_stop_minimal(void* vnc){
if(nc->tcache.pixel_shutdown){
ret |= nc->tcache.pixel_shutdown(nc->ttyfd);
}
ret |= reset_term_attributes(nc);
ret |= reset_term_attributes(&nc->tcache, nc->ttyfp);
ret |= notcurses_mouse_disable(nc);
if(nc->tcache.rmcup && tty_emit(nc->tcache.rmcup, nc->ttyfd)){
ret = -1;
}
@ -1081,7 +1080,7 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){
goto err;
}
if(ret->ttyfd >= 0){
reset_term_attributes(ret);
reset_term_attributes(&ret->tcache, ret->ttyfp);
if(!(opts->flags & NCOPTION_NO_CLEAR_BITMAPS)){
if(sprite_clear_all(&ret->tcache, ret->ttyfd)){
free_plane(ret->stdplane);

@ -833,16 +833,19 @@ goto_location(notcurses* nc, FILE* out, int y, int x){
// necessary return to default (if one is necessary), and update rstate.
static inline int
raster_defaults(notcurses* nc, bool fgdef, bool bgdef, FILE* out){
if(!nc->tcache.op){ // if we don't have op, we don't have fgop/bgop
const char* op = get_escape(&nc->tcache, ESCAPE_OP);
if(op == NULL){ // if we don't have op, we don't have fgop/bgop
return 0;
}
const char* fgop = get_escape(&nc->tcache, ESCAPE_FGOP);
const char* bgop = get_escape(&nc->tcache, ESCAPE_BGOP);
bool mustsetfg = fgdef && !nc->rstate.fgdefelidable;
bool mustsetbg = bgdef && !nc->rstate.bgdefelidable;
if(!mustsetfg && !mustsetbg){ // don't need emit anything
if(!mustsetfg && !mustsetbg){ // needn't emit anything
++nc->stats.defaultelisions;
return 0;
}else if((mustsetfg && mustsetbg) || !nc->tcache.fgop){
if(term_emit(nc->tcache.op, out, false)){
}else if((mustsetfg && mustsetbg) || !fgop || !bgop){
if(term_emit(op, out, false)){
return -1;
}
nc->rstate.fgdefelidable = true;
@ -851,15 +854,15 @@ raster_defaults(notcurses* nc, bool fgdef, bool bgdef, FILE* out){
nc->rstate.bgelidable = false;
nc->rstate.fgpalelidable = false;
nc->rstate.bgpalelidable = false;
}else if(mustsetfg){
if(term_emit(nc->tcache.fgop, out, false)){
}else if(mustsetfg){ // if we reach here, we must have fgop
if(term_emit(fgop, out, false)){
return -1;
}
nc->rstate.fgdefelidable = true;
nc->rstate.fgelidable = false;
nc->rstate.fgpalelidable = false;
}else{
if(term_emit(nc->tcache.bgop, out, false)){
}else{ // mustsetbg and !mustsetfg and bgop != NULL
if(term_emit(bgop, out, false)){
return -1;
}
nc->rstate.bgdefelidable = true;

@ -29,7 +29,9 @@ typedef enum {
ESCAPE_VPA, // "vpa" move cursor to absolute vertical position
ESCAPE_SETAF, // "setaf" set foreground color
ESCAPE_SETAB, // "setab" set background color
ESCAPE_DEFS, // "op" set foreground and background color to defaults
ESCAPE_OP, // "op" set foreground and background color to defaults
ESCAPE_FGOP, // set foreground only to default
ESCAPE_BGOP, // set background only to default
ESCAPE_SGR, // "sgr" set graphics rendering (styles)
ESCAPE_SGR0, // "sgr0" turn off all styles
ESCAPE_CIVIS, // "civis" make the cursor invisiable
@ -45,12 +47,9 @@ typedef enum {
typedef struct tinfo {
uint16_t escindices[ESCAPE_MAX]; // table of 1-biased indices into esctable
char* esctable; // packed table of escape sequences
char* op; // set foreground and background color to default
char* sgr; // set many graphics properties at once
unsigned colors;// number of colors terminfo reported usable for this screen
char* sgr0; // restore default presentation properties
char* fgop; // set foreground to default
char* bgop; // set background to default
char* cuu; // move N cells up
char* cub; // move N cells left
char* cuf; // move N cells right

@ -201,6 +201,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
// Not all terminals support setting the fore/background independently
{ ESCAPE_SETAF, "setaf", },
{ ESCAPE_SETAB, "setab", },
{ ESCAPE_OP, "op", },
{ ESCAPE_MAX, NULL, },
};
size_t tablelen = 0;
@ -209,8 +210,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
char* tstr;
if(terminfostr(&tstr, strtdesc->tinfo) == 0){
if(grow_esc_table(ti, tstr, strtdesc->esc, &tablelen, &tableused)){
free(ti->esctable);
return -1;
goto err;
}
}else{
ti->escindices[strtdesc->esc] = 0;
@ -218,7 +218,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
}
if(ti->escindices[ESCAPE_CUP] == 0){
fprintf(stderr, "Required terminfo capability 'cup' not defined\n");
return -1;
goto err;
}
// neither of these is supported on e.g. the "linux" virtual console.
if(!noaltscreen){
@ -229,7 +229,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
ti->AMflag = tigetflag("am") == 1;
if(!ti->AMflag){
fprintf(stderr, "Required terminfo capability 'am' not defined\n");
return -1;
goto err;
}
ti->BCEflag = tigetflag("bce") == 1;
terminfostr(&ti->civis, "civis"); // cursor invisible
@ -247,7 +247,6 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
terminfostr(&ti->italoff, "ritm"); // end italic mode
terminfostr(&ti->sgr, "sgr"); // define video attributes
terminfostr(&ti->sgr0, "sgr0"); // turn off all video attributes
terminfostr(&ti->op, "op"); // restore defaults to default pair
terminfostr(&ti->oc, "oc"); // restore defaults to all colors
terminfostr(&ti->home, "home"); // home the cursor
terminfostr(&ti->clearscr, "clear");// clear screen, home cursor
@ -295,23 +294,31 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname,
if(fd >= 0){
if(tty_emit(tiparm(ti->smkx), fd) < 0){
fprintf(stderr, "Error entering keypad transmit mode\n");
return -1;
goto err;
}
}
}
// if op is defined as ansi 39 + ansi 49, make the split definitions
// available. this ought be asserted by extension capability "ax", but
// no terminal i've found seems to do so. =[
if(ti->op && strcmp(ti->op, "\x1b[39;49m") == 0){
ti->fgop = "\x1b[39m";
ti->bgop = "\x1b[49m";
const char* op = get_escape(ti, ESCAPE_OP);
if(op && strcmp(op, "\x1b[39;49m") == 0){
if(grow_esc_table(ti, "\x1b[39m", ESCAPE_FGOP, &tablelen, &tableused) ||
grow_esc_table(ti, "\x1b[49m", ESCAPE_BGOP, &tablelen, &tableused)){
goto err;
}
}
pthread_mutex_init(&ti->pixel_query, NULL);
ti->pixel_query_done = false;
if(apply_term_heuristics(ti, termname, fd)){
return -1;
pthread_mutex_destroy(&ti->pixel_query);
goto err;
}
return 0;
err:
free(ti->esctable);
return -1;
}
// FIXME need unit tests on this

@ -133,6 +133,8 @@ TEST_CASE("FdsAndSubprocs"
CHECK(0 == notcurses_render(nc_));
}
// assuming the path /dev/nope doesn't exist, cat ought be successfully
// launched (fork() and exec() both succeed), but then immediately fail.
SUBCASE("SubprocDestroyCmdFailed") {
char * const argv[] = { strdup("/bin/cat"), strdup("/dev/nope"), nullptr, };
bool outofline_cancelled = false;

Loading…
Cancel
Save