notcurses_stop: position cursor at bottom-left without alternate screen #1337

pull/1338/head
nick black 3 years ago
parent 8b3c0478c5
commit 15d5c48d93
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -58,7 +58,7 @@ int ncdirect_cursor_up(ncdirect* nc, int num){
if(!nc->tcache.cuu){
return -1;
}
return term_emit("cuu", tiparm(nc->tcache.cuu, num), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.cuu, num), nc->ttyfp, false);
}
int ncdirect_cursor_left(ncdirect* nc, int num){
@ -68,7 +68,7 @@ int ncdirect_cursor_left(ncdirect* nc, int num){
if(!nc->tcache.cub){
return -1;
}
return term_emit("cub", tiparm(nc->tcache.cub, num), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.cub, num), nc->ttyfp, false);
}
int ncdirect_cursor_right(ncdirect* nc, int num){
@ -78,7 +78,7 @@ int ncdirect_cursor_right(ncdirect* nc, int num){
if(!nc->tcache.cuf){ // FIXME fall back to cuf1
return -1;
}
return term_emit("cuf", tiparm(nc->tcache.cuf, num), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.cuf, num), nc->ttyfp, false);
}
int ncdirect_cursor_down(ncdirect* nc, int num){
@ -88,14 +88,14 @@ int ncdirect_cursor_down(ncdirect* nc, int num){
if(!nc->tcache.cud){
return -1;
}
return term_emit("cud", tiparm(nc->tcache.cud, num), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.cud, num), nc->ttyfp, false);
}
int ncdirect_clear(ncdirect* nc){
if(!nc->tcache.clearscr){
return -1; // FIXME scroll output off the screen
}
return term_emit("clear", nc->tcache.clearscr, nc->ttyfp, true);
return term_emit(nc->tcache.clearscr, nc->ttyfp, true);
}
int ncdirect_dim_x(const ncdirect* nc){
@ -126,14 +126,14 @@ int ncdirect_cursor_enable(ncdirect* nc){
if(!nc->tcache.cnorm){
return -1;
}
return term_emit("cnorm", nc->tcache.cnorm, nc->ttyfp, true);
return term_emit(nc->tcache.cnorm, nc->ttyfp, true);
}
int ncdirect_cursor_disable(ncdirect* nc){
if(!nc->tcache.civis){
return -1;
}
return term_emit("civis", nc->tcache.civis, nc->ttyfp, true);
return term_emit(nc->tcache.civis, nc->ttyfp, true);
}
int ncdirect_cursor_move_yx(ncdirect* n, int y, int x){
@ -141,18 +141,18 @@ int ncdirect_cursor_move_yx(ncdirect* n, int y, int x){
if(!n->tcache.hpa){
return -1;
}
return term_emit("hpa", tiparm(n->tcache.hpa, x), n->ttyfp, false);
return term_emit(tiparm(n->tcache.hpa, x), n->ttyfp, false);
}else if(x == -1){ // keep column the same, vertical move only
if(!n->tcache.vpa){
return -1;
}
return term_emit("vpa", tiparm(n->tcache.vpa, y), n->ttyfp, false);
return term_emit(tiparm(n->tcache.vpa, y), n->ttyfp, false);
}
if(n->tcache.cup){
return term_emit("cup", tiparm(n->tcache.cup, y, x), n->ttyfp, false);
return term_emit(tiparm(n->tcache.cup, y, x), n->ttyfp, false);
}else if(n->tcache.vpa && n->tcache.hpa){
if(term_emit("hpa", tiparm(n->tcache.hpa, x), n->ttyfp, false) == 0 &&
term_emit("vpa", tiparm(n->tcache.vpa, y), n->ttyfp, false) == 0){
if(term_emit(tiparm(n->tcache.hpa, x), n->ttyfp, false) == 0 &&
term_emit(tiparm(n->tcache.vpa, y), n->ttyfp, false) == 0){
return 0;
}
}
@ -362,14 +362,14 @@ int ncdirect_cursor_push(ncdirect* n){
if(n->tcache.sc == nullptr){
return -1;
}
return term_emit("sc", n->tcache.sc, n->ttyfp, false);
return term_emit(n->tcache.sc, n->ttyfp, false);
}
int ncdirect_cursor_pop(ncdirect* n){
if(n->tcache.rc == nullptr){
return -1;
}
return term_emit("rc", n->tcache.rc, n->ttyfp, false);
return term_emit(n->tcache.rc, n->ttyfp, false);
}
static inline int
@ -542,14 +542,14 @@ int ncdirect_set_fg_palindex(ncdirect* nc, int pidx){
if(channels_set_fg_palindex(&nc->channels, pidx) < 0){
return -1;
}
return term_emit("setaf", tiparm(nc->tcache.setaf, pidx), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.setaf, pidx), nc->ttyfp, false);
}
int ncdirect_set_bg_palindex(ncdirect* nc, int pidx){
if(channels_set_bg_palindex(&nc->channels, pidx) < 0){
return -1;
}
return term_emit("setab", tiparm(nc->tcache.setab, pidx), nc->ttyfp, false);
return term_emit(tiparm(nc->tcache.setab, pidx), nc->ttyfp, false);
}
int ncdirect_vprintf_aligned(ncdirect* n, int y, ncalign_e align, const char* fmt, va_list ap){
@ -600,17 +600,17 @@ ncdirect_stop_minimal(void* vnc){
if(nc->initialized_readline){
rl_deprep_terminal();
}
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
if(nc->tcache.op && term_emit(nc->tcache.op, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, true)){
if(nc->tcache.sgr0 && term_emit(nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
if(nc->tcache.oc && term_emit(nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
if(nc->ctermfd >= 0){
if(nc->tcache.cnorm && tty_emit("cnorm", nc->tcache.cnorm, nc->ctermfd)){
if(nc->tcache.cnorm && tty_emit(nc->tcache.cnorm, nc->ctermfd)){
ret = -1;
}
ret |= tcsetattr(nc->ctermfd, TCSANOW, &nc->tpreserved);
@ -709,16 +709,16 @@ static inline int
ncdirect_style_emit(ncdirect* n, unsigned stylebits, FILE* out){
int r = -1;
if(stylebits == 0 && n->tcache.sgr0){
r = term_emit("sgr0", n->tcache.sgr0, n->ttyfp, false);
r = term_emit(n->tcache.sgr0, n->ttyfp, false);
}else if(n->tcache.sgr){
r = term_emit("sgr", tiparm(n->tcache.sgr, stylebits & NCSTYLE_STANDOUT,
stylebits & NCSTYLE_UNDERLINE,
stylebits & NCSTYLE_REVERSE,
stylebits & NCSTYLE_BLINK,
stylebits & NCSTYLE_DIM,
stylebits & NCSTYLE_BOLD,
stylebits & NCSTYLE_INVIS,
stylebits & NCSTYLE_PROTECT, 0), out, false);
r = term_emit(tiparm(n->tcache.sgr, stylebits & NCSTYLE_STANDOUT,
stylebits & NCSTYLE_UNDERLINE,
stylebits & NCSTYLE_REVERSE,
stylebits & NCSTYLE_BLINK,
stylebits & NCSTYLE_DIM,
stylebits & NCSTYLE_BOLD,
stylebits & NCSTYLE_INVIS,
stylebits & NCSTYLE_PROTECT, 0), out, false);
}
// sgr resets colors, so set them back up if not defaults
if(r == 0){
@ -809,10 +809,10 @@ int ncdirect_set_fg_default(ncdirect* nc){
return 0;
}
if(nc->tcache.fgop){
if(term_emit("fgop", nc->tcache.fgop, nc->ttyfp, false)){
if(term_emit(nc->tcache.fgop, nc->ttyfp, false)){
return -1;
}
}else if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
}else if(term_emit(nc->tcache.op, nc->ttyfp, false) == 0){
if(!ncdirect_bg_default_p(nc)){
if(ncdirect_set_bg_rgb(nc, channels_bg_rgb(nc->channels))){
return -1;
@ -828,10 +828,10 @@ int ncdirect_set_bg_default(ncdirect* nc){
return 0;
}
if(nc->tcache.bgop){
if(term_emit("bgop", nc->tcache.bgop, nc->ttyfp, false)){
if(term_emit(nc->tcache.bgop, nc->ttyfp, false)){
return -1;
}
}else if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
}else if(term_emit(nc->tcache.op, nc->ttyfp, false) == 0){
if(!ncdirect_fg_default_p(nc)){
if(ncdirect_set_fg_rgb(nc, channels_fg_rgb(nc->channels))){
return -1;

@ -505,7 +505,7 @@ rgb_greyscale(int r, int g, int b){
}
static inline int
tty_emit(const char* name __attribute__ ((unused)), const char* seq, int fd){
tty_emit(const char* seq, int fd){
if(!seq){
return -1;
}
@ -523,27 +523,25 @@ tty_emit(const char* name __attribute__ ((unused)), const char* seq, int fd){
}
}while(written < slen);
if(written < slen){
//fprintf(stderr, "Error emitting %zub %s escape (%s)\n", strlen(seq), name, strerror(errno));
//fprintf(stderr, "Error emitting %zub escape (%s)\n", strlen(seq), strerror(errno));
return -1;
}
return 0;
}
static inline int
term_emit(const char* name __attribute__ ((unused)), const char* seq,
FILE* out, bool flush){
term_emit(const char* seq, FILE* out, bool flush){
if(!seq){
return -1;
}
if(fputs(seq, out) == EOF){
//fprintf(stderr, "Error emitting %zub %s escape (%s)\n", strlen(seq), name, strerror(errno));
//fprintf(stderr, "Error emitting %zub escape (%s)\n", strlen(seq), strerror(errno));
return -1;
}
if(flush){
while(fflush(out) == EOF){
if(errno != EAGAIN){
fprintf(stderr, "Error flushing after %zub %s sequence (%s)\n",
strlen(seq), name, strerror(errno));
fprintf(stderr, "Error flushing after %zub sequence (%s)\n", strlen(seq), strerror(errno));
return -1;
}
}
@ -556,7 +554,7 @@ term_bg_palindex(const notcurses* nc, FILE* out, unsigned pal){
if(nc->tcache.setab == NULL){
return 0;
}
return term_emit("setab", tiparm(nc->tcache.setab, pal), out, false);
return term_emit(tiparm(nc->tcache.setab, pal), out, false);
}
static inline int
@ -564,7 +562,7 @@ term_fg_palindex(const notcurses* nc, FILE* out, unsigned pal){
if(nc->tcache.setaf == NULL){
return 0;
}
return term_emit("setaf", tiparm(nc->tcache.setaf, pal), out, false);
return term_emit(tiparm(nc->tcache.setaf, pal), out, false);
}
static inline const char*

@ -39,13 +39,13 @@ void notcurses_version_components(int* major, int* minor, int* patch, int* tweak
static int
reset_term_attributes(notcurses* nc){
int ret = 0;
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, false)){
if(nc->tcache.op && term_emit(nc->tcache.op, nc->ttyfp, false)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, false)){
if(nc->tcache.sgr0 && term_emit(nc->tcache.sgr0, nc->ttyfp, false)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
if(nc->tcache.oc && term_emit(nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
ret |= notcurses_mouse_disable(nc);
@ -63,10 +63,10 @@ notcurses_stop_minimal(void* vnc){
// they apply to the screen (alternate or otherwise) we're actually using.
ret |= reset_term_attributes(nc);
if(nc->ttyfd >= 0){
if(nc->tcache.rmcup && tty_emit("rmcup", nc->tcache.rmcup, nc->ttyfd)){
if(nc->tcache.rmcup && tty_emit(nc->tcache.rmcup, nc->ttyfd)){
ret = -1;
}
if(nc->tcache.cnorm && tty_emit("cnorm", nc->tcache.cnorm, nc->ttyfd)){
if(nc->tcache.cnorm && tty_emit(nc->tcache.cnorm, nc->ttyfd)){
ret = -1;
}
ret |= tcsetattr(nc->ttyfd, TCSANOW, &nc->tpreserved);
@ -811,7 +811,7 @@ init_banner(const notcurses* nc){
fprintf(stderr, "\n Warning! Encoding is not UTF-8; output may be degraded.\n");
}
if(nc->tcache.sgr0){
term_emit("sgr0", nc->tcache.sgr0, stderr, true);
term_emit(nc->tcache.sgr0, stderr, true);
}
}
}
@ -1050,11 +1050,11 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){
goto err;
}
if(ret->ttyfd >= 0){
if(ret->tcache.smkx && tty_emit("smkx", ret->tcache.smkx, ret->ttyfd)){
if(ret->tcache.smkx && tty_emit(ret->tcache.smkx, ret->ttyfd)){
free_plane(ret->stdplane);
goto err;
}
if(ret->tcache.civis && tty_emit("civis", ret->tcache.civis, ret->ttyfd)){
if(ret->tcache.civis && tty_emit(ret->tcache.civis, ret->ttyfd)){
free_plane(ret->stdplane);
goto err;
}
@ -1068,19 +1068,19 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){
// flush on the switch to alternate screen, lest initial output be swept away
if(ret->ttyfd >= 0){
if(ret->tcache.smcup){
if(tty_emit("smcup", ret->tcache.smcup, ret->ttyfd)){
if(tty_emit(ret->tcache.smcup, ret->ttyfd)){
free_plane(ret->stdplane);
goto err;
}
// explicit clear even though smcup *might* clear
if(tty_emit("clear", ret->tcache.clearscr, ret->ttyfd)){
if(tty_emit(ret->tcache.clearscr, ret->ttyfd)){
notcurses_refresh(ret, NULL, NULL);
}
}else if(!(opts->flags & NCOPTION_NO_ALTERNATE_SCREEN)){
// if they expected the alternate screen, but we didn't have one to
// offer, at least clear the screen. try using "clear"; if that doesn't
// fly, use notcurses_refresh() to force a clearing via iterated writes.
if(tty_emit("clear", ret->tcache.clearscr, ret->ttyfd)){
if(tty_emit(ret->tcache.clearscr, ret->ttyfd)){
notcurses_refresh(ret, NULL, NULL);
}
}
@ -1142,6 +1142,12 @@ int notcurses_stop(notcurses* nc){
if(nc->rstate.mstreamfp){
fclose(nc->rstate.mstreamfp);
}
// if we were not using the alternate screen, our cursor's wherever we last
// wrote. move it to the bottom left of the screen.
if(!nc->tcache.smcup){
tty_emit(tiparm(nc->tcache.hpa, 0), nc->ttyfd);
tty_emit(tiparm(nc->tcache.vpa, nc->lfdimy - 1), nc->ttyfd);
}
if(nc->ttyfd >= 0){
ret |= close(nc->ttyfd);
}
@ -2026,7 +2032,7 @@ ncplane* ncplane_above(ncplane* n){
#define SET_SGR_MODE_MOUSE "1006"
int notcurses_mouse_enable(notcurses* n){
if(n->ttyfd >= 0){
return tty_emit("mouse", ESC "[?" SET_BTN_EVENT_MOUSE ";"
return tty_emit(ESC "[?" SET_BTN_EVENT_MOUSE ";"
/*SET_FOCUS_EVENT_MOUSE ";" */SET_SGR_MODE_MOUSE "h",
n->ttyfd);
}
@ -2037,7 +2043,7 @@ int notcurses_mouse_enable(notcurses* n){
// the sequences 1000 etc?
int notcurses_mouse_disable(notcurses* n){
if(n->ttyfd >= 0){
return tty_emit("mouse", ESC "[?" SET_BTN_EVENT_MOUSE ";"
return tty_emit(ESC "[?" SET_BTN_EVENT_MOUSE ";"
/*SET_FOCUS_EVENT_MOUSE ";" */SET_SGR_MODE_MOUSE "l",
n->ttyfd);
}

@ -609,11 +609,11 @@ int term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit,
if(curon != targon){
if(targon){
if(ton){
ret = term_emit("ton", ton, out, false);
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", toff, out, false);
ret = term_emit(toff, out, false);
}
}
}
@ -640,18 +640,18 @@ term_setstyles(FILE* out, uint32_t* curattr, const nccell* c, bool* normalized,
*normalized = true; // FIXME this is pretty conservative
// if everything's 0, emit the shorter sgr0
if(sgr0 && ((cellattr & NCSTYLE_MASK) == 0)){
if(term_emit("sgr0", sgr0, out, false) < 0){
if(term_emit(sgr0, out, false) < 0){
ret = -1;
}
}else if(term_emit("sgr", tiparm(sgr, cellattr & NCSTYLE_STANDOUT,
cellattr & NCSTYLE_UNDERLINE,
cellattr & NCSTYLE_REVERSE,
cellattr & NCSTYLE_BLINK,
cellattr & NCSTYLE_DIM,
cellattr & NCSTYLE_BOLD,
cellattr & NCSTYLE_INVIS,
cellattr & NCSTYLE_PROTECT, 0),
out, false) < 0){
}else if(term_emit(tiparm(sgr, cellattr & NCSTYLE_STANDOUT,
cellattr & NCSTYLE_UNDERLINE,
cellattr & NCSTYLE_REVERSE,
cellattr & NCSTYLE_BLINK,
cellattr & NCSTYLE_DIM,
cellattr & NCSTYLE_BOLD,
cellattr & NCSTYLE_INVIS,
cellattr & NCSTYLE_PROTECT, 0),
out, false) < 0){
ret = -1;
}
// sgr will blow away italics/struck if they were set beforehand
@ -755,9 +755,9 @@ term_bg_rgb8(bool RGBflag, const char* setab, int colors, FILE* out,
// a single screen, start... combining close ones? For 8-color mode, simple
// interpolation. I have no idea what to do for 88 colors. FIXME
if(colors >= 256){
return term_emit("setab", tiparm(setab, rgb_quantize_256(r, g, b)), out, false);
return term_emit(tiparm(setab, rgb_quantize_256(r, g, b)), out, false);
}else if(colors >= 8){
return term_emit("setab", tiparm(setab, rgb_quantize_8(r, g, b)), out, false);
return term_emit(tiparm(setab, rgb_quantize_8(r, g, b)), out, false);
}
}
return 0;
@ -782,9 +782,9 @@ term_fg_rgb8(bool RGBflag, const char* setaf, int colors, FILE* out,
// a single screen, start... combining close ones? For 8-color mode, simple
// interpolation. I have no idea what to do for 88 colors. FIXME
if(colors >= 256){
return term_emit("setaf", tiparm(setaf, rgb_quantize_256(r, g, b)), out, false);
return term_emit(tiparm(setaf, rgb_quantize_256(r, g, b)), out, false);
}else if(colors >= 8){
return term_emit("setaf", tiparm(setaf, rgb_quantize_8(r, g, b)), out, false);
return term_emit(tiparm(setaf, rgb_quantize_8(r, g, b)), out, false);
}
}
return 0;
@ -802,7 +802,7 @@ update_palette(notcurses* nc, FILE* out){
r = r * 1000 / 255;
g = g * 1000 / 255;
b = b * 1000 / 255;
term_emit("initc", tiparm(nc->tcache.initc, damageidx, r, g, b), out, false);
term_emit(tiparm(nc->tcache.initc, damageidx, r, g, b), out, false);
nc->palette_damage[damageidx] = false;
}
}
@ -827,13 +827,13 @@ goto_location(notcurses* nc, FILE* out, int y, int x){
return 0;
}
if(x == nc->rstate.x + 1 && nc->tcache.cuf1){
ret = term_emit("cuf1", nc->tcache.cuf1, out, false);
ret = term_emit(nc->tcache.cuf1, out, false);
}else{
ret = term_emit("hpa", tiparm(nc->tcache.hpa, x), out, false);
ret = term_emit(tiparm(nc->tcache.hpa, x), out, false);
}
}else{
// cup is required, no need to check for existence
ret = term_emit("cup", tiparm(nc->tcache.cup, y, x), out, false);
ret = term_emit(tiparm(nc->tcache.cup, y, x), out, false);
}
if(ret == 0){
nc->rstate.x = x;
@ -855,7 +855,7 @@ raster_defaults(notcurses* nc, bool fgdef, bool bgdef, FILE* out){
++nc->stats.defaultelisions;
return 0;
}else if((mustsetfg && mustsetbg) || !nc->tcache.fgop){
if(term_emit("op", nc->tcache.op, out, false)){
if(term_emit(nc->tcache.op, out, false)){
return -1;
}
nc->rstate.fgdefelidable = true;
@ -865,14 +865,14 @@ raster_defaults(notcurses* nc, bool fgdef, bool bgdef, FILE* out){
nc->rstate.fgpalelidable = false;
nc->rstate.bgpalelidable = false;
}else if(mustsetfg){
if(term_emit("fgop", nc->tcache.fgop, out, false)){
if(term_emit(nc->tcache.fgop, out, false)){
return -1;
}
nc->rstate.fgdefelidable = true;
nc->rstate.fgelidable = false;
nc->rstate.fgpalelidable = false;
}else{
if(term_emit("bgop", nc->tcache.bgop, out, false)){
if(term_emit(nc->tcache.bgop, out, false)){
return -1;
}
nc->rstate.bgdefelidable = true;
@ -1089,11 +1089,11 @@ static int
home_cursor(notcurses* nc, bool flush){
int ret = -1;
if(nc->tcache.home){
ret = term_emit("home", nc->tcache.home, nc->ttyfp, flush);
ret = term_emit(nc->tcache.home, nc->ttyfp, flush);
}else if(nc->tcache.cup){
ret = term_emit("cup", tiparm(nc->tcache.cup, 1, 1), nc->ttyfp, flush);
ret = term_emit(tiparm(nc->tcache.cup, 1, 1), nc->ttyfp, flush);
}else if(nc->tcache.clearscr){
ret = term_emit("clear", nc->tcache.clearscr, nc->ttyfp, flush);
ret = term_emit(nc->tcache.clearscr, nc->ttyfp, flush);
}
if(ret >= 0){
nc->rstate.x = 0;
@ -1360,7 +1360,7 @@ int notcurses_cursor_enable(notcurses* nc, int y, int x){
nc->cursorx = x;
return 0;
}
if(tty_emit("cnorm", nc->tcache.cnorm, nc->ttyfd) || fflush(nc->ttyfp) == EOF){
if(tty_emit(nc->tcache.cnorm, nc->ttyfd) || fflush(nc->ttyfp) == EOF){
return -1;
}
nc->cursory = y;
@ -1375,7 +1375,7 @@ int notcurses_cursor_disable(notcurses* nc){
}
if(nc->ttyfd >= 0){
if(nc->tcache.civis){
if(!tty_emit("civis", nc->tcache.civis, nc->ttyfd) && !fflush(nc->ttyfp)){
if(!tty_emit(nc->tcache.civis, nc->ttyfd) && !fflush(nc->ttyfp)){
nc->cursory = -1;
nc->cursorx = -1;
return 0;

Loading…
Cancel
Save