X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/4ca761b162db788d98d164ed4881c7ec61760c40..3d5040f8f85f049cbb072a827a6184b4b4314b08:/dialog.c diff --git a/dialog.c b/dialog.c index 53b64298..84869195 100644 --- 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) @@ -456,140 +472,3 @@ void ctrl_free(union control *ctrl) } sfree(ctrl); } - -void dlg_stdradiobutton_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - int button; - /* - * For a standard radio button set, the context parameter gives - * offsetof(targetfield, Config), and the extra data per button - * gives the value the target field should take if that button - * is the one selected. - */ - if (event == EVENT_REFRESH) { - for (button = 0; button < ctrl->radio.nbuttons; button++) - if (*(int *)ATOFFSET(data, ctrl->radio.context.i) == - ctrl->radio.buttondata[button].i) - break; - /* We expected that `break' to happen, in all circumstances. */ - assert(button < ctrl->radio.nbuttons); - dlg_radiobutton_set(ctrl, dlg, button); - } else if (event == EVENT_VALCHANGE) { - button = dlg_radiobutton_get(ctrl, dlg); - assert(button >= 0 && button < ctrl->radio.nbuttons); - *(int *)ATOFFSET(data, ctrl->radio.context.i) = - ctrl->radio.buttondata[button].i; - } -} - -void dlg_stdcheckbox_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - int offset, invert; - - /* - * For a standard checkbox, the context parameter gives - * offsetof(targetfield, Config), optionally ORed with - * CHECKBOX_INVERT. - */ - offset = ctrl->checkbox.context.i; - if (offset & CHECKBOX_INVERT) { - offset &= ~CHECKBOX_INVERT; - invert = 1; - } else - invert = 0; - - /* - * C lacks a logical XOR, so the following code uses the idiom - * (!a ^ !b) to obtain the logical XOR of a and b. (That is, 1 - * iff exactly one of a and b is nonzero, otherwise 0.) - */ - - if (event == EVENT_REFRESH) { - dlg_checkbox_set(ctrl,dlg, (!*(int *)ATOFFSET(data,offset) ^ !invert)); - } else if (event == EVENT_VALCHANGE) { - *(int *)ATOFFSET(data, offset) = !dlg_checkbox_get(ctrl,dlg) ^ !invert; - } -} - -void dlg_stdeditbox_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - /* - * The standard edit-box handler expects the main `context' - * field to contain the `offsetof' a field in the structure - * pointed to by `data'. The secondary `context2' field - * indicates the type of this field: - * - * - if context2 > 0, the field is a char array and context2 - * gives its size. - * - if context2 == -1, the field is an int and the edit box - * is numeric. - * - if context2 < -1, the field is an int and the edit box is - * _floating_, and (-context2) gives the scale. (E.g. if - * context2 == -1000, then typing 1.2 into the box will set - * the field to 1200.) - */ - int offset = ctrl->editbox.context.i; - int length = ctrl->editbox.context2.i; - - if (length > 0) { - char *field = (char *)ATOFFSET(data, offset); - if (event == EVENT_REFRESH) { - dlg_editbox_set(ctrl, dlg, field); - } else if (event == EVENT_VALCHANGE) { - dlg_editbox_get(ctrl, dlg, field, length); - } - } else if (length < 0) { - int *field = (int *)ATOFFSET(data, offset); - char data[80]; - if (event == EVENT_REFRESH) { - if (length == -1) - sprintf(data, "%d", *field); - else - sprintf(data, "%g", (double)*field / (double)(-length)); - dlg_editbox_set(ctrl, dlg, data); - } else if (event == EVENT_VALCHANGE) { - dlg_editbox_get(ctrl, dlg, data, lenof(data)); - if (length == -1) - *field = atoi(data); - else - *field = (int)((-length) * atof(data)); - } - } -} - -void dlg_stdfilesel_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - /* - * The standard file-selector handler expects the `context' - * field to contain the `offsetof' a Filename field in the - * structure pointed to by `data'. - */ - int offset = ctrl->fileselect.context.i; - - if (event == EVENT_REFRESH) { - dlg_filesel_set(ctrl, dlg, *(Filename *)ATOFFSET(data, offset)); - } else if (event == EVENT_VALCHANGE) { - dlg_filesel_get(ctrl, dlg, (Filename *)ATOFFSET(data, offset)); - } -} - -void dlg_stdfontsel_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - /* - * The standard file-selector handler expects the `context' - * field to contain the `offsetof' a FontSpec field in the - * structure pointed to by `data'. - */ - int offset = ctrl->fontselect.context.i; - - if (event == EVENT_REFRESH) { - dlg_fontsel_set(ctrl, dlg, *(FontSpec *)ATOFFSET(data, offset)); - } else if (event == EVENT_VALCHANGE) { - dlg_fontsel_get(ctrl, dlg, (FontSpec *)ATOFFSET(data, offset)); - } -}