diff --git a/src/lib/internal.h b/src/lib/internal.h index 3895157d2..709c9077d 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -279,6 +279,20 @@ typedef struct notcurses { void sigwinch_handler(int signo); +// create a new ncplane, and remove it from the z-axis. used for menus. gross. +static inline ncplane* +ncplane_new_uncoupled(notcurses* nc, int rows, int cols, int yoff, int xoff, void* opaque){ + ncplane* n = ncplane_new(nc, rows, cols, yoff, xoff, opaque); + if(n == NULL){ + return n; + } + assert(nc->top == n); + nc->top = n->z; + assert(nc->top != n); + n->z = NULL; + return n; +} + // Search the provided multibyte (UTF8) string 's' for the provided unicode // codepoint 'cp'. If found, return the column offset of the EGC in which the // codepoint appears in 'col', and the byte offset as the return value. If not diff --git a/src/lib/menu.c b/src/lib/menu.c index e2efdbb75..769ff7154 100644 --- a/src/lib/menu.c +++ b/src/lib/menu.c @@ -53,7 +53,11 @@ dup_menu_item(ncmenu_int_item* dst, const struct ncmenu_item* src){ return -1; } memset(&ps, 0, sizeof(ps)); - wcrtomb(sdup + n, src->shortcut.id, &ps); + if(wcrtomb(sdup + n, src->shortcut.id, &ps) == (size_t)-1){ // shouldn't happen + free(sdup); + free(dst->desc); + return -1; + } dst->shortdesc = sdup; dst->shortdesccols = mbswidth(dst->shortdesc); return 0; @@ -246,7 +250,7 @@ ncmenu* ncmenu_create(notcurses* nc, const ncmenu_options* opts){ totalwidth = dimx; } int ypos = opts->bottom ? dimy - totalheight : 0; - ret->ncp = ncplane_new(nc, totalheight, totalwidth, ypos, 0, NULL); + ret->ncp = ncplane_new_uncoupled(nc, totalheight, totalwidth, ypos, 0, NULL); if(ret->ncp){ ret->unrolledsection = -1; ret->headerchannels = opts->headerchannels; diff --git a/src/lib/render.c b/src/lib/render.c index f3f6117cb..6a2f00d27 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -328,8 +328,9 @@ fprintf(stderr, "POOL: %p NC: %p SRC: %p\n", nc->pool.pool, nc, crender->p);*/ // which cells were changed. We solve for each coordinate's cell by walking // down the z-buffer, looking at intersections with ncplanes. This implies // locking down the EGC, the attributes, and the channels for each cell. +// 'top' is accepted so that a menu can override other planes...kinda gross :/. static inline int -notcurses_render_internal(notcurses* nc, struct crender* rvec){ +notcurses_render_internal(notcurses* nc, ncplane* top, struct crender* rvec){ if(reshape_shadow_fb(nc)){ return -1; } @@ -347,7 +348,7 @@ notcurses_render_internal(notcurses* nc, struct crender* rvec){ cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT); } } - ncplane* p = nc->top; + ncplane* p = top; while(p){ if(paint(nc, p, rvec, fb)){ return -1; @@ -843,7 +844,12 @@ int notcurses_render(notcurses* nc){ size_t crenderlen = sizeof(struct crender) * nc->stdscr->leny * nc->stdscr->lenx; struct crender* crender = malloc(crenderlen); memset(crender, 0, crenderlen); - if(notcurses_render_internal(nc, crender) == 0){ + ncplane* top = nc->top; + if(nc->menu){ + top = nc->menu->ncp; + nc->menu->ncp->z = nc->top; + } + if(notcurses_render_internal(nc, top, crender) == 0){ bytes = notcurses_rasterize(nc, crender); } free(crender);