#include <assert.h>
#include <limits.h>
#include <stdarg.h>
+#include <stdlib.h>
#define DEFINE_INTORPTR_FNS
struct controlbox *ctrl_new_box(void)
{
- struct controlbox *ret = smalloc(sizeof(struct controlbox));
+ struct controlbox *ret = snew(struct controlbox);
ret->nctrlsets = ret->ctrlsetsize = 0;
ret->ctrlsets = NULL;
ret->nfrees = ret->freesize = 0;
ret->frees = NULL;
+ ret->freefuncs = NULL;
return ret;
}
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);
}
char *path, char *title)
{
- struct controlset *s = smalloc(sizeof(struct controlset));
+ struct controlset *s = snew(struct controlset);
int index = ctrl_find_set(b, path, 1);
s->pathname = dupstr(path);
s->boxname = NULL;
s->ctrls = NULL;
if (b->nctrlsets >= b->ctrlsetsize) {
b->ctrlsetsize = b->nctrlsets + 32;
- b->ctrlsets = srealloc(b->ctrlsets,
- b->ctrlsetsize*sizeof(*b->ctrlsets));
+ b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);
}
if (index < b->nctrlsets)
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
return b->ctrlsets[index];
index++;
}
- s = smalloc(sizeof(struct controlset));
+ s = snew(struct controlset);
s->pathname = dupstr(path);
s->boxname = dupstr(name);
s->boxtitle = boxtitle ? dupstr(boxtitle) : NULL;
s->ctrls = NULL;
if (b->nctrlsets >= b->ctrlsetsize) {
b->ctrlsetsize = b->nctrlsets + 32;
- b->ctrlsets = srealloc(b->ctrlsets,
- b->ctrlsetsize*sizeof(*b->ctrlsets));
+ b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);
}
if (index < b->nctrlsets)
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
}
/* 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;
+ /*
+ * This is an internal allocation routine, so it's allowed to
+ * use smalloc directly.
+ */
p = smalloc(size);
if (b->nfrees >= b->freesize) {
b->freesize = b->nfrees + 32;
- b->frees = srealloc(b->frees, b->freesize*sizeof(*b->frees));
+ 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)
{
- union control *c = smalloc(sizeof(union control));
+ union control *c = snew(union control);
if (s->ncontrols >= s->ctrlsize) {
s->ctrlsize = s->ncontrols + 32;
- s->ctrls = srealloc(s->ctrls, s->ctrlsize * sizeof(*s->ctrls));
+ s->ctrls = sresize(s->ctrls, s->ctrlsize, union control *);
}
s->ctrls[s->ncontrols++] = c;
/*
} else {
va_list ap;
int i;
- c->columns.percentages = smalloc(ncolumns * sizeof(int));
+ c->columns.percentages = snewn(ncolumns, int);
va_start(ap, ncolumns);
for (i = 0; i < ncolumns; i++)
c->columns.percentages[i] = va_arg(ap, int);
while (va_arg(ap, char *) != NULL) {
i++;
if (c->radio.shortcut == NO_SHORTCUT)
- va_arg(ap, int); /* char promotes to int in arg lists */
- va_arg(ap, intorptr);
+ (void)va_arg(ap, int); /* char promotes to int in arg lists */
+ (void)va_arg(ap, intorptr);
}
va_end(ap);
c->radio.nbuttons = i;
if (c->radio.shortcut == NO_SHORTCUT)
- c->radio.shortcuts = smalloc(c->radio.nbuttons * sizeof(char));
+ c->radio.shortcuts = snewn(c->radio.nbuttons, char);
else
c->radio.shortcuts = NULL;
- c->radio.buttons = smalloc(c->radio.nbuttons * sizeof(char *));
- c->radio.buttondata = smalloc(c->radio.nbuttons * sizeof(intorptr));
+ c->radio.buttons = snewn(c->radio.nbuttons, char *);
+ c->radio.buttondata = snewn(c->radio.nbuttons, intorptr);
/*
* Second pass along variable argument list to actually fill in
* the structure.
c->button.label = label ? dupstr(label) : NULL;
c->button.shortcut = shortcut;
c->button.isdefault = 0;
+ c->button.iscancel = 0;
return c;
}
c->listbox.draglist = 0;
c->listbox.multisel = 0;
c->listbox.percentwidth = percentage;
+ c->listbox.ncols = 0;
+ c->listbox.percentages = NULL;
return c;
}
c->listbox.draglist = 1;
c->listbox.multisel = 0;
c->listbox.percentwidth = 100;
+ c->listbox.ncols = 0;
+ c->listbox.percentages = NULL;
return c;
}
}
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));
- }
-}