track widgets from planes #2342, hook up ncmenu

dankamongmen/windows-tester
nick black 3 years ago committed by nick black
parent 519f7f5a74
commit baae0c3d06

@ -113,6 +113,12 @@ typedef struct ncplane {
int margin_b, margin_r;// bottom and right margins, stored for resize
bool scrolling; // is scrolling enabled? always disabled by default
bool fixedbound; // are we fixed relative to the parent's scrolling?
// we need to track any widget to which we are bound, so that (1) we don't
// end up bound to two widgets and (2) we can clean them up on shutdown
// (assuming they weren't explicitly cleaned up by the client).
void* widget; // widget to which we are bound, can be NULL
void(*wdestruct)(void*); // widget destructor, NULL iff widget is NULL
} ncplane;
// current presentation state of the terminal. it is carried across render
@ -428,7 +434,25 @@ ncplane_stdplane_const(const ncplane* n){
return notcurses_stdplane_const(ncplane_notcurses_const(n));
}
// initialize libav
// set the plane's widget and wdestruct fields, returning non-zero if they're
// already non-NULL (i.e. if the plane is already bound), unless we pass NULL
// (which ought be done from the widget destructor, to avoid corecursion).
static inline int
ncplane_set_widget(ncplane* n, void* w, void(*wdestruct)(void*)){
if(n->widget){
if(w){
logerror("plane is already bound to a widget\n");
return -1;
}
}else if(w == NULL){
return -1;
}
n->widget = w;
n->wdestruct = wdestruct;
return 0;
}
// initialize visualization backend (ffmpeg/oiio)
int ncvisual_init(int loglevel);
static inline int

@ -412,6 +412,7 @@ ncmenu* ncmenu_create(ncplane* n, const ncmenu_options* opts){
};
ret->ncp = ncplane_create(n, &nopts);
if(ret->ncp){
ncplane_set_widget(ret->ncp, ret, ncmenu_destroy);
ret->unrolledsection = -1;
ret->headerchannels = opts->headerchannels;
ret->dissectchannels = opts->headerchannels;
@ -769,7 +770,9 @@ int ncmenu_destroy(ncmenu* n){
int ret = 0;
if(n){
free_menu_sections(n);
ncplane_destroy(n->ncp);
if(ncplane_set_widget(n->ncp, NULL, NULL) == 0){
ncplane_destroy(n->ncp);
}
free(n);
}
return ret;

@ -346,6 +346,13 @@ ncpile_destroy(ncpile* pile){
void free_plane(ncplane* p){
if(p){
if(p->widget){
void* w = p->widget;
void (*wdestruct)(void*) = p->wdestruct;
p->widget = NULL;
p->wdestruct = NULL;
wdestruct(w);
}
// ncdirect fakes an ncplane with no ->pile
if(ncplane_pile(p)){
notcurses* nc = ncplane_notcurses(p);
@ -444,6 +451,8 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
}
p->scrolling = false;
p->fixedbound = nopts->flags & NCPLANE_OPTION_FIXED;
p->widget = NULL;
p->wdestruct = NULL;
if(nopts->flags & NCPLANE_OPTION_MARGINALIZED){
p->margin_b = nopts->margin_b;
p->margin_r = nopts->margin_r;

@ -54,7 +54,8 @@ int main(int argc, char** argv){
struct ncplane* std = notcurses_stdplane(nc);
ncplane_set_scrolling(std, true);
ncsubproc_options nopts = {};
struct ncsubproc* nsproc = ncsubproc_createvp(std, &nopts, *argv, argv, cb, eofcb);
struct ncsubproc* nsproc = ncsubproc_createvp(std, &nopts, *argv,
(const char* const*)argv, cb, eofcb);
if(nsproc == NULL){
notcurses_stop(nc);
return EXIT_FAILURE;

@ -76,7 +76,7 @@ TEST_CASE("Menu") {
ncmenu_destroy(ncm);
}
// don't call ncmenu_destroy(), invoking destruction in notcurses_stop()
// don't call ncmenu_destroy(), invoking destruction in notcurses_stop().
SUBCASE("MenuNoFree") {
struct ncmenu_item file_items[] = {
{ .desc = "I would like a new file", .shortcut = ncinput(), },

Loading…
Cancel
Save