diff --git a/doc/man/man3/notcurses_stop.3.md b/doc/man/man3/notcurses_stop.3.md index 5641a675d..e7455d8e1 100644 --- a/doc/man/man3/notcurses_stop.3.md +++ b/doc/man/man3/notcurses_stop.3.md @@ -18,7 +18,7 @@ notcurses_stop - free up resources and restore initial terminal state **struct notcurses** provided as **nc**, and attempts to restore the terminal to its state prior to calling notcurses_init(3). It also unregisters any signal handlers put into place by notcurses_init(3). **nc** must not be used following -the call. +the call, and all references to ncplanes, cells, etc. are invalidated. # NOTES diff --git a/src/lib/fade.c b/src/lib/fade.c index 3f9fb681d..d9491f6a9 100644 --- a/src/lib/fade.c +++ b/src/lib/fade.c @@ -79,23 +79,13 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){ return 0; } -int ncplane_fadein(ncplane* n, const struct timespec* ts, fadecb fader){ - planepalette pp; - if(!n->nc->RGBflag && !n->nc->CCCflag){ // terminal can't fade - if(fader){ - fader(n->nc, n); - }else{ - notcurses_render(n->nc); - } - return -1; - } - if(alloc_ncplane_palette(n, &pp)){ - return -1; - } - int maxfsteps = pp.maxg > pp.maxr ? (pp.maxb > pp.maxg ? pp.maxb : pp.maxg) : - (pp.maxb > pp.maxr ? pp.maxb : pp.maxr); - int maxbsteps = pp.maxbg > pp.maxbr ? (pp.maxbb > pp.maxbg ? pp.maxbb : pp.maxbg) : - (pp.maxbb > pp.maxbr ? pp.maxbb : pp.maxbr); +static int +ncplane_fadein_internal(ncplane* n, const struct timespec* ts, + fadecb fader, planepalette* pp){ + int maxfsteps = pp->maxg > pp->maxr ? (pp->maxb > pp->maxg ? pp->maxb : pp->maxg) : + (pp->maxb > pp->maxr ? pp->maxb : pp->maxr); + int maxbsteps = pp->maxbg > pp->maxbr ? (pp->maxbb > pp->maxbg ? pp->maxbb : pp->maxbg) : + (pp->maxbb > pp->maxbr ? pp->maxbb : pp->maxbr); int maxsteps = maxfsteps > maxbsteps ? maxfsteps : maxbsteps; if(maxsteps == 0){ maxsteps = 1; @@ -121,12 +111,12 @@ int ncplane_fadein(ncplane* n, const struct timespec* ts, fadecb fader){ // possibility of a resize event :/ int dimy, dimx; ncplane_dim_yx(n, &dimy, &dimx); - for(y = 0 ; y < pp.rows && y < dimy ; ++y){ - for(x = 0 ; x < pp.cols && x < dimx; ++x){ + for(y = 0 ; y < pp->rows && y < dimy ; ++y){ + for(x = 0 ; x < pp->cols && x < dimx; ++x){ unsigned r, g, b; - channels_fg_rgb(pp.channels[pp.cols * y + x], &r, &g, &b); + channels_fg_rgb(pp->channels[pp->cols * y + x], &r, &g, &b); unsigned br, bg, bb; - channels_bg_rgb(pp.channels[pp.cols * y + x], &br, &bg, &bb); + channels_bg_rgb(pp->channels[pp->cols * y + x], &br, &bg, &bb); cell* c = &n->fb[dimx * y + x]; if(!cell_fg_default_p(c)){ r = r * iter / maxsteps; @@ -162,7 +152,6 @@ int ncplane_fadein(ncplane* n, const struct timespec* ts, fadecb fader){ break; } }while(true); - free(pp.channels); return ret; } @@ -261,10 +250,35 @@ int ncplane_fadeout(ncplane* n, const struct timespec* ts, fadecb fader){ return ret; } +int ncplane_fadein(ncplane* n, const struct timespec* ts, fadecb fader){ + planepalette pp; + if(!n->nc->RGBflag && !n->nc->CCCflag){ // terminal can't fade + if(fader){ + fader(n->nc, n); + }else{ + notcurses_render(n->nc); + } + return -1; + } + if(alloc_ncplane_palette(n, &pp)){ + return -1; + } + int ret = ncplane_fadein_internal(n, ts, fader, &pp); + free(pp.channels); + return ret; +} + int ncplane_pulse(ncplane* n, const struct timespec* ts, fadecb fader){ + planepalette pp; int ret; + if(!n->nc->RGBflag && !n->nc->CCCflag){ // terminal can't fade + return -1; + } + if(alloc_ncplane_palette(n, &pp)){ + return -1; + } for(;;){ - ret = ncplane_fadein(n, ts, fader); + ret = ncplane_fadein_internal(n, ts, fader, &pp); if(ret){ break; } @@ -273,5 +287,6 @@ int ncplane_pulse(ncplane* n, const struct timespec* ts, fadecb fader){ break; } } + free(pp.channels); return ret; } diff --git a/tests/fade.cpp b/tests/fade.cpp index 459e9053a..006d62036 100644 --- a/tests/fade.cpp +++ b/tests/fade.cpp @@ -1,6 +1,22 @@ #include "main.h" #include #include +#include "internal.h" + +struct timespec pulsestart; + +int pulser(struct notcurses* nc, struct ncplane* ncp __attribute__ ((unused))){ + if(notcurses_render(nc)){ + return -1; + } + struct timespec now; + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + auto delta = timespec_to_ns(&now) - timespec_to_ns(&pulsestart); + if(delta > 1000000000){ + return 1; + } + return 0; +} TEST_CASE("Fade") { if(getenv("TERM") == nullptr){ @@ -31,7 +47,7 @@ TEST_CASE("Fade") { if(rgb < 32){ rgb = 0xffffffu; } - cell_set_fg_rgb(&c, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff, rgb & 0xff); + cell_set_fg(&c, rgb); cell_set_bg_rgb(&c, rgb & 0xff, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff); CHECK(0 < ncplane_putc(n_, &c)); } @@ -42,14 +58,25 @@ TEST_CASE("Fade") { struct timespec ts; ts.tv_sec = 1; ts.tv_nsec = 0; - REQUIRE(0 == ncplane_fadeout(n_, &ts, nullptr)); + CHECK(0 == ncplane_fadeout(n_, &ts, nullptr)); } SUBCASE("FadeIn") { struct timespec ts; ts.tv_sec = 1; ts.tv_nsec = 0; - REQUIRE(0 == ncplane_fadein(n_, &ts, nullptr)); + CHECK(0 == ncplane_fadein(n_, &ts, nullptr)); + } + + SUBCASE("Pulse") { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 250000000; + ncplane_erase(n_); + ncplane_set_fg(n_, 0xffd700); + CHECK(0 < ncplane_printf_aligned(n_, dimy - 1, NCALIGN_CENTER, "pulllllllse")); + clock_gettime(CLOCK_MONOTONIC_RAW, &pulsestart); + CHECK(0 < ncplane_pulse(n_, &ts, pulser)); } CHECK(0 == notcurses_stop(nc_));