Add an extended version of ctrl_alloc which permits you to provide a
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 14 Jul 2013 10:46:29 +0000 (10:46 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 14 Jul 2013 10:46:29 +0000 (10:46 +0000)
custom free function, in case you need to ctrl_alloc a structure which
then has additional dynamically allocated things dangling off it.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9922 cda61777-01e9-0310-a592-d414129be87e

dialog.c
dialog.h

index 127783a..8486919 100644 (file)
--- a/dialog.c
+++ b/dialog.c
@@ -47,6 +47,7 @@ struct controlbox *ctrl_new_box(void)
     ret->ctrlsets = NULL;
     ret->nfrees = ret->freesize = 0;
     ret->frees = NULL;
+    ret->freefuncs = NULL;
 
     return ret;
 }
@@ -59,9 +60,10 @@ void ctrl_free_box(struct controlbox *b)
        ctrl_free_set(b->ctrlsets[i]);
     }
     for (i = 0; i < b->nfrees; i++)
-       sfree(b->frees[i]);
+       b->freefuncs[i](b->frees[i]);
     sfree(b->ctrlsets);
     sfree(b->frees);
+    sfree(b->freefuncs);
     sfree(b);
 }
 
@@ -181,7 +183,8 @@ struct controlset *ctrl_getset(struct controlbox *b,
 }
 
 /* Allocate some private data in a controlbox. */
-void *ctrl_alloc(struct controlbox *b, size_t size)
+void *ctrl_alloc_with_free(struct controlbox *b, size_t size,
+                           ctrl_freefn_t freefunc)
 {
     void *p;
     /*
@@ -192,11 +195,24 @@ void *ctrl_alloc(struct controlbox *b, size_t size)
     if (b->nfrees >= b->freesize) {
        b->freesize = b->nfrees + 32;
        b->frees = sresize(b->frees, b->freesize, void *);
+       b->freefuncs = sresize(b->freefuncs, b->freesize, ctrl_freefn_t);
     }
-    b->frees[b->nfrees++] = p;
+    b->frees[b->nfrees] = p;
+    b->freefuncs[b->nfrees] = freefunc;
+    b->nfrees++;
     return p;
 }
 
+static void ctrl_default_free(void *p)
+{
+    sfree(p);
+}
+
+void *ctrl_alloc(struct controlbox *b, size_t size)
+{
+    return ctrl_alloc_with_free(b, size, ctrl_default_free);
+}
+
 static union control *ctrl_new(struct controlset *s, int type,
                               intorptr helpctx, handler_fn handler,
                               intorptr context)
index 5977413..9ea8599 100644 (file)
--- a/dialog.h
+++ b/dialog.h
@@ -427,6 +427,8 @@ struct controlset {
     union control **ctrls;            /* actual array */
 };
 
+typedef void (*ctrl_freefn_t)(void *);    /* used by ctrl_alloc_with_free */
+
 /*
  * This is the container structure which holds a complete set of
  * controls.
@@ -438,6 +440,7 @@ struct controlbox {
     int nfrees;
     int freesize;
     void **frees;                     /* array of aux data areas to free */
+    ctrl_freefn_t *freefuncs;          /* parallel array of free functions */
 };
 
 struct controlbox *ctrl_new_box(void);
@@ -464,8 +467,14 @@ void ctrl_free(union control *);
  * and so data allocated through this function is better not used
  * to hold modifiable per-instance things. It's mostly here for
  * allocating structures to be passed as control handler params.
+ *
+ * ctrl_alloc_with_free also allows you to provide a function to free
+ * the structure, in case there are other dynamically allocated bits
+ * and pieces dangling off it.
  */
 void *ctrl_alloc(struct controlbox *b, size_t size);
+void *ctrl_alloc_with_free(struct controlbox *b, size_t size,
+                           ctrl_freefn_t freefunc);
 
 /*
  * Individual routines to create `union control' structures in a controlset.