From: Richard W.M. Jones Date: Wed, 19 Mar 2008 13:50:36 +0000 (+0100) Subject: handle component destruction X-Git-Tag: r0-52-9~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c101e99edef4c7b391a2b8eba2c34123d8025454;p=thirdparty%2Fnewt.git handle component destruction Handle component destruction in a way which is more friendly to garbage collection. --- diff --git a/button.c b/button.c index fa819eb..8eb5e5a 100644 --- a/button.c +++ b/button.c @@ -45,6 +45,7 @@ static newtComponent createButton(int left, int row, const char * text, int comp return NULL; } co->data = bu; + co->destroyCallback = NULL; bu->text = strdup(text); bu->compact = compact; diff --git a/checkbox.c b/checkbox.c index 85cd49e..198d662 100644 --- a/checkbox.c +++ b/checkbox.c @@ -126,6 +126,7 @@ newtComponent newtCheckbox(int left, int top, const char * text, char defValue, co->ops = &cbOps; co->callback = NULL; + co->destroyCallback = NULL; co->height = 1; co->width = wstrlen(text, -1) + 4; co->top = top; diff --git a/checkboxtree.c b/checkboxtree.c index e574d55..9c37756 100644 --- a/checkboxtree.c +++ b/checkboxtree.c @@ -333,6 +333,7 @@ newtComponent newtCheckboxTreeMulti(int left, int top, int height, char *seq, in co = malloc(sizeof(*co)); ct = malloc(sizeof(struct CheckboxTree)); co->callback = NULL; + co->destroyCallback = NULL; co->data = ct; co->left = left; co->top = top; diff --git a/entry.c b/entry.c index 5693c3e..fc2382f 100644 --- a/entry.c +++ b/entry.c @@ -78,6 +78,7 @@ newtComponent newtEntry(int left, int top, const char * initialValue, int width, co->width = width; co->isMapped = 0; co->callback = NULL; + co->destroyCallback = NULL; co->ops = &entryOps; diff --git a/form.c b/form.c index 075c13d..ae1c6a0 100644 --- a/form.c +++ b/form.c @@ -448,6 +448,7 @@ newtComponent newtForm(newtComponent vertBar, void * help, int flags) { co->takesFocus = 0; /* we may have 0 components */ co->ops = &formOps; + co->destroyCallback = NULL; form->help = help; form->flags = flags; @@ -785,6 +786,26 @@ static struct eventResult formEvent(newtComponent co, struct event ev) { return er; } +/* Destroy a component. Components which have been added to a form + * are destroyed when the form is destroyed; this is just for the + * (rare) case of components which for whatever reason weren't added + * to a form. + */ +void newtComponentDestroy(newtComponent co) { + /* If the user registered a destroy callback for this component, + * now is a good time to call it. + */ + if (co->destroyCallback) + co->destroyCallback(co, co->destroyCallbackData); + + if (co->ops->destroy) { + co->ops->destroy(co); + } else { + if (co->data) free(co->data); + free(co); + } +} + /* this also destroys all of the components on the form */ void newtFormDestroy(newtComponent co) { newtComponent subco; @@ -794,12 +815,7 @@ void newtFormDestroy(newtComponent co) { /* first, destroy all of the components */ for (i = 0; i < form->numComps; i++) { subco = form->elements[i].co; - if (subco->ops->destroy) { - subco->ops->destroy(subco); - } else { - if (subco->data) free(subco->data); - free(subco); - } + newtComponentDestroy(subco); } if (form->hotKeys) free(form->hotKeys); @@ -1119,6 +1135,13 @@ void newtComponentAddCallback(newtComponent co, newtCallback f, void * data) { co->callbackData = data; } +/* Add a callback which is called when the component is destroyed. */ +void newtComponentAddDestroyCallback(newtComponent co, + newtCallback f, void * data) { + co->destroyCallback = f; + co->destroyCallbackData = data; +} + void newtComponentTakesFocus(newtComponent co, int val) { co->takesFocus = val; } diff --git a/label.c b/label.c index ad8665b..a0c17a4 100644 --- a/label.c +++ b/label.c @@ -28,6 +28,7 @@ newtComponent newtLabel(int left, int top, const char * text) { co = malloc(sizeof(*co)); la = malloc(sizeof(struct label)); co->data = la; + co->destroyCallback = NULL; co->ops = &labelOps; diff --git a/listbox.c b/listbox.c index c802e7c..1a77e0e 100644 --- a/listbox.c +++ b/listbox.c @@ -133,6 +133,7 @@ newtComponent newtListbox(int left, int top, int height, int flags) { co->ops = &listboxOps; co->takesFocus = 1; co->callback = NULL; + co->destroyCallback = NULL; updateWidth(co, li, 5); diff --git a/newt.0.52.ver b/newt.0.52.ver index fe9bdd3..df7c4d7 100644 --- a/newt.0.52.ver +++ b/newt.0.52.ver @@ -141,3 +141,9 @@ NEWT_0.52.6 { newtSetColor; newtPopWindowNoRefresh; } NEWT_0.52; + +NEWT_0.52.9 { + global: + newtComponentAddDestroyCallback; + newtComponentDestroy; +} NEWT_0.52.6; diff --git a/newt.h b/newt.h index daa5513..88f2dd8 100644 --- a/newt.h +++ b/newt.h @@ -255,10 +255,20 @@ void newtScaleSet(newtComponent co, unsigned long long amount); void newtComponentAddCallback(newtComponent co, newtCallback f, void * data); void newtComponentTakesFocus(newtComponent co, int val); +/* This callback is called when a component is destroyed. */ +void newtComponentAddDestroyCallback(newtComponent co, + newtCallback f, void * data); + /* this also destroys all of the components (including other forms) on the form */ void newtFormDestroy(newtComponent form); +/* NB: You SHOULD NOT call this for components which have been added + * to a form (ie. almost all components). They are destroyed along + * with the form when you call newtFormDestroy. + */ +void newtComponentDestroy(newtComponent co); + /* Key codes */ #define NEWT_KEY_TAB '\t' diff --git a/newt_pr.h b/newt_pr.h index cc839ad..5d60ebe 100644 --- a/newt_pr.h +++ b/newt_pr.h @@ -40,6 +40,9 @@ struct newtComponent_struct { newtCallback callback; void * callbackData; + newtCallback destroyCallback; + void * destroyCallbackData; + void * data; } ; diff --git a/scale.c b/scale.c index 07cebd5..f9a1f40 100644 --- a/scale.c +++ b/scale.c @@ -28,6 +28,7 @@ newtComponent newtScale(int left, int top, int width, long long fullValue) { co = malloc(sizeof(*co)); sc = malloc(sizeof(struct scale)); co->data = sc; + co->destroyCallback = NULL; co->ops = &scaleOps; diff --git a/scrollbar.c b/scrollbar.c index 96ed513..b89ede2 100644 --- a/scrollbar.c +++ b/scrollbar.c @@ -46,6 +46,7 @@ newtComponent newtVerticalScrollbar(int left, int top, int height, co = malloc(sizeof(*co)); sb = malloc(sizeof(*sb)); co->data = sb; + co->destroyCallback = NULL; if (height >= 2) { sb->arrows = 1; diff --git a/textbox.c b/textbox.c index fcfb41f..873a23c 100644 --- a/textbox.c +++ b/textbox.c @@ -105,6 +105,7 @@ newtComponent newtTextbox(int left, int top, int width, int height, int flags) { co->left = left; co->takesFocus = 0; co->width = width; + co->destroyCallback = NULL; tb->doWrap = flags & NEWT_FLAG_WRAP; tb->numLines = 0;