Been meaning to do this for years: introduce a configuration option
[u/mdw/putty] / dialog.h
CommitLineData
fe8abbf4 1/*
2 * Exports and types from dialog.c.
3 */
4
5/*
6 * This will come in handy for generic control handlers. Anyone
7 * knows how to make this more portable, let me know :-)
8 */
9#define ATOFFSET(data, offset) ( (void *) ( (char *)(data) + (offset) ) )
10
11/*
12 * This is the big union which defines a single control, of any
13 * type.
14 *
15 * General principles:
16 * - _All_ pointers in this structure are expected to point to
17 * dynamically allocated things, unless otherwise indicated.
18 * - `char' fields giving keyboard shortcuts are expected to be
19 * NO_SHORTCUT if no shortcut is desired for a particular control.
20 * - The `label' field can often be NULL, which will cause the
21 * control to not have a label at all. This doesn't apply to
22 * checkboxes and push buttons, in which the label is not
23 * separate from the control.
24 */
25
26#define NO_SHORTCUT '\0'
27
28enum {
29 CTRL_TEXT, /* just a static line of text */
30 CTRL_EDITBOX, /* label plus edit box */
31 CTRL_RADIO, /* label plus radio buttons */
32 CTRL_CHECKBOX, /* checkbox (contains own label) */
33 CTRL_BUTTON, /* simple push button (no label) */
34 CTRL_LISTBOX, /* label plus list box */
35 CTRL_COLUMNS, /* divide window into columns */
36 CTRL_FILESELECT, /* label plus filename selector */
37 CTRL_FONTSELECT, /* label plus font selector */
38 CTRL_TABDELAY /* see `tabdelay' below */
39};
40
41/*
42 * Many controls have `intorptr' unions for storing user data,
43 * since the user might reasonably want to store either an integer
44 * or a void * pointer. Here I define a union, and two convenience
45 * functions to create that union from actual integers or pointers.
46 *
47 * The convenience functions are declared as inline if possible.
48 * Otherwise, they're declared here and defined when this header is
49 * included with DEFINE_INTORPTR_FNS defined. This is a total pain,
50 * but such is life.
51 */
52typedef union { void *p; int i; } intorptr;
53
c6f21f1b 54#ifndef INLINE
55intorptr I(int i);
56intorptr P(void *p);
57#endif
58
fe8abbf4 59#if defined DEFINE_INTORPTR_FNS || defined INLINE
60#ifdef INLINE
61#define PREFIX INLINE
62#else
63#define PREFIX
64#endif
65PREFIX intorptr I(int i) { intorptr ret; ret.i = i; return ret; }
66PREFIX intorptr P(void *p) { intorptr ret; ret.p = p; return ret; }
67#undef PREFIX
fe8abbf4 68#endif
69
70/*
71 * Each control has an `int' field specifying which columns it
72 * occupies in a multi-column part of the dialog box. These macros
73 * pack and unpack that field.
74 *
75 * If a control belongs in exactly one column, just specifying the
76 * column number is perfectly adequate.
77 */
78#define COLUMN_FIELD(start, span) ( (((span)-1) << 16) + (start) )
79#define COLUMN_START(field) ( (field) & 0xFFFF )
80#define COLUMN_SPAN(field) ( (((field) >> 16) & 0xFFFF) + 1 )
81
82union control;
83
84/*
85 * The number of event types is being deliberately kept small, on
86 * the grounds that not all platforms might be able to report a
87 * large number of subtle events. We have:
88 * - the special REFRESH event, called when a control's value
89 * needs setting
90 * - the ACTION event, called when the user does something that
91 * positively requests action (double-clicking a list box item,
92 * or pushing a push-button)
93 * - the VALCHANGE event, called when the user alters the setting
94 * of the control in a way that is usually considered to alter
95 * the underlying data (toggling a checkbox or radio button,
96 * moving the items around in a drag-list, editing an edit
97 * control)
98 * - the SELCHANGE event, called when the user alters the setting
99 * of the control in a more minor way (changing the selected
100 * item in a list box).
101 * - the CALLBACK event, which happens after the handler routine
102 * has requested a subdialog (file selector, font selector,
103 * colour selector) and it has come back with information.
104 */
105enum {
106 EVENT_REFRESH,
107 EVENT_ACTION,
108 EVENT_VALCHANGE,
109 EVENT_SELCHANGE,
110 EVENT_CALLBACK
111};
112typedef void (*handler_fn)(union control *ctrl, void *dlg,
113 void *data, int event);
114
115#define STANDARD_PREFIX \
116 int type; \
117 char *label; \
118 int tabdelay; \
119 int column; \
120 handler_fn handler; \
121 intorptr context; \
122 intorptr helpctx
123
124union control {
125 /*
126 * The first possibility in this union is the generic header
127 * shared by all the structures, which we are therefore allowed
128 * to access through any one of them.
129 */
130 struct {
131 int type;
132 /*
133 * Every control except CTRL_COLUMNS has _some_ sort of
134 * label. By putting it in the `generic' union as well as
135 * everywhere else, we avoid having to have an irritating
136 * switch statement when we go through and deallocate all
137 * the memory in a config-box structure.
138 *
139 * Yes, this does mean that any non-NULL value in this
140 * field is expected to be dynamically allocated and
141 * freeable.
142 *
143 * For CTRL_COLUMNS, this field MUST be NULL.
144 */
145 char *label;
146 /*
147 * If `tabdelay' is non-zero, it indicates that this
148 * particular control should not yet appear in the tab
149 * order. A subsequent CTRL_TABDELAY entry will place it.
150 */
151 int tabdelay;
152 /*
153 * Indicate which column(s) this control occupies. This can
154 * be unpacked into starting column and column span by the
155 * COLUMN macros above.
156 */
157 int column;
158 /*
159 * Most controls need to provide a function which gets
160 * called when that control's setting is changed, or when
161 * the control's setting needs initialising.
162 *
163 * The `data' parameter points to the writable data being
164 * modified as a result of the configuration activity; for
165 * example, the PuTTY `Config' structure, although not
166 * necessarily.
167 *
168 * The `dlg' parameter is passed back to the platform-
169 * specific routines to read and write the actual control
170 * state.
171 */
172 handler_fn handler;
173 /*
174 * Almost all of the above functions will find it useful to
175 * be able to store a piece of `void *' or `int' data.
176 */
177 intorptr context;
178 /*
179 * For any control, we also allow the storage of a piece of
180 * data for use by context-sensitive help. For example, on
181 * Windows you can click the magic question mark and then
182 * click a control, and help for that control should spring
183 * up. Hence, here is a slot in which to store per-control
184 * data that a particular platform-specific driver can use
185 * to ensure it brings up the right piece of help text.
186 */
187 intorptr helpctx;
188 } generic;
189 struct {
190 STANDARD_PREFIX;
191 union control *ctrl;
192 } tabdelay;
193 struct {
194 STANDARD_PREFIX;
195 } text;
196 struct {
197 STANDARD_PREFIX;
198 char shortcut; /* keyboard shortcut */
199 /*
200 * Percentage of the dialog-box width used by the edit box.
201 * If this is set to 100, the label is on its own line;
202 * otherwise the label is on the same line as the box
203 * itself.
204 */
205 int percentwidth;
206 int password; /* details of input are hidden */
207 /*
208 * A special case of the edit box is the combo box, which
209 * has a drop-down list built in. (Note that a _non_-
210 * editable drop-down list is done as a special case of a
211 * list box.)
212 */
213 int has_list;
214 /*
215 * Edit boxes tend to need two items of context, so here's
216 * a spare.
217 */
218 intorptr context2;
219 } editbox;
220 struct {
221 STANDARD_PREFIX;
222 /*
223 * `shortcut' here is a single keyboard shortcut which is
224 * expected to select the whole group of radio buttons. It
225 * can be NO_SHORTCUT if required, and there is also a way
226 * to place individual shortcuts on each button; see below.
227 */
228 char shortcut;
229 /*
230 * There are separate fields for `ncolumns' and `nbuttons'
231 * for several reasons.
232 *
233 * Firstly, we sometimes want the last of a set of buttons
234 * to have a longer label than the rest; we achieve this by
235 * setting `ncolumns' higher than `nbuttons', and the
236 * layout code is expected to understand that the final
237 * button should be given all the remaining space on the
238 * line. This sounds like a ludicrously specific special
239 * case (if we're doing this sort of thing, why not have
240 * the general ability to have a particular button span
241 * more than one column whether it's the last one or not?)
242 * but actually it's reasonably common for the sort of
243 * three-way control you get a lot of in PuTTY: `yes'
244 * versus `no' versus `some more complex way to decide'.
245 *
246 * Secondly, setting `nbuttons' higher than `ncolumns' lets
247 * us have more than one line of radio buttons for a single
248 * setting. A very important special case of this is
249 * setting `ncolumns' to 1, so that each button is on its
250 * own line.
251 */
252 int ncolumns;
253 int nbuttons;
254 /*
255 * This points to a dynamically allocated array of `char *'
256 * pointers, each of which points to a dynamically
257 * allocated string.
258 */
259 char **buttons; /* `nbuttons' button labels */
260 /*
261 * This points to a dynamically allocated array of `char'
262 * giving the individual keyboard shortcuts for each radio
263 * button. The array may be NULL if none are required.
264 */
265 char *shortcuts; /* `nbuttons' shortcuts; may be NULL */
266 /*
267 * This points to a dynamically allocated array of
268 * intorptr, giving helpful data for each button.
269 */
270 intorptr *buttondata; /* `nbuttons' entries; may be NULL */
271 } radio;
272 struct {
273 STANDARD_PREFIX;
274 char shortcut;
275 } checkbox;
276 struct {
277 STANDARD_PREFIX;
278 char shortcut;
279 /*
280 * At least Windows has the concept of a `default push
281 * button', which gets implicitly pressed when you hit
282 * Return even if it doesn't have the input focus.
283 */
284 int isdefault;
0bd8d76d 285 /*
286 * Also, the reverse of this: a default cancel-type button,
287 * which is implicitly pressed when you hit Escape.
288 */
289 int iscancel;
fe8abbf4 290 } button;
291 struct {
292 STANDARD_PREFIX;
293 char shortcut; /* keyboard shortcut */
294 /*
295 * Height of the list box, in approximate number of lines.
296 * If this is zero, the list is a drop-down list.
297 */
298 int height; /* height in lines */
299 /*
300 * If this is set, the list elements can be reordered by
301 * the user (by drag-and-drop or by Up and Down buttons,
302 * whatever the per-platform implementation feels
303 * comfortable with). This is not guaranteed to work on a
304 * drop-down list, so don't try it!
305 */
306 int draglist;
307 /*
8eed910d 308 * If this is non-zero, the list can have more than one
309 * element selected at a time. This is not guaranteed to
310 * work on a drop-down list, so don't try it!
311 *
312 * Different non-zero values request slightly different
313 * types of multi-selection (this may well be meaningful
314 * only in GTK, so everyone else can ignore it if they
315 * want). 1 means the list box expects to have individual
316 * items selected, whereas 2 means it expects the user to
317 * want to select a large contiguous range at a time.
fe8abbf4 318 */
319 int multisel;
320 /*
321 * Percentage of the dialog-box width used by the list box.
322 * If this is set to 100, the label is on its own line;
323 * otherwise the label is on the same line as the box
324 * itself. Setting this to anything other than 100 is not
325 * guaranteed to work on a _non_-drop-down list, so don't
326 * try it!
327 */
328 int percentwidth;
329 /*
330 * Some list boxes contain strings that contain tab
331 * characters. If `ncols' is greater than 0, then
332 * `percentages' is expected to be non-zero and to contain
333 * the respective widths of `ncols' columns, which together
334 * will exactly fit the width of the list box. Otherwise
335 * `percentages' must be NULL.
336 */
337 int ncols; /* number of columns */
338 int *percentages; /* % width of each column */
339 } listbox;
340 struct {
341 STANDARD_PREFIX;
342 char shortcut;
343 /*
344 * `filter' dictates what type of files will be selected by
345 * default; for example, when selecting private key files
346 * the file selector would do well to only show .PPK files
347 * (on those systems where this is the chosen extension).
348 *
349 * The precise contents of `filter' are platform-defined,
350 * unfortunately. The special value NULL means `all files'
351 * and is always a valid fallback.
352 *
353 * Unlike almost all strings in this structure, this value
354 * is NOT expected to require freeing (although of course
355 * you can always use ctrl_alloc if you do need to create
356 * one on the fly). This is because the likely mode of use
357 * is to define string constants in a platform-specific
358 * header file, and directly reference those. Or worse, a
359 * particular platform might choose to cast integers into
360 * this pointer type...
361 */
362 char const *filter;
363 /*
364 * Some systems like to know whether a file selector is
365 * choosing a file to read or one to write (and possibly
366 * create).
367 */
368 int for_writing;
369 /*
370 * On at least some platforms, the file selector is a
371 * separate dialog box, and contains a user-settable title.
372 *
373 * This value _is_ expected to require freeing.
374 */
375 char *title;
376 } fileselect;
377 struct {
378 /* In this variant, `label' MUST be NULL. */
379 STANDARD_PREFIX;
380 int ncols; /* number of columns */
381 int *percentages; /* % width of each column */
382 /*
383 * Every time this control type appears, exactly one of
384 * `ncols' and the previous number of columns MUST be one.
385 * Attempting to allow a seamless transition from a four-
386 * to a five-column layout, for example, would be way more
387 * trouble than it was worth. If you must lay things out
388 * like that, define eight unevenly sized columns and use
389 * column-spanning a lot. But better still, just don't.
390 *
391 * `percentages' may be NULL if ncols==1, to save space.
392 */
393 } columns;
394 struct {
395 STANDARD_PREFIX;
396 char shortcut;
397 } fontselect;
398};
399
400#undef STANDARD_PREFIX
401
402/*
403 * `controlset' is a container holding an array of `union control'
404 * structures, together with a panel name and a title for the whole
405 * set. In Windows and any similar-looking GUI, each `controlset'
406 * in the config will be a container box within a panel.
407 *
408 * Special case: if `boxname' is NULL, the control set gives an
409 * overall title for an entire panel of controls.
410 */
411struct controlset {
412 char *pathname; /* panel path, e.g. "SSH/Tunnels" */
413 char *boxname; /* internal short name of controlset */
414 char *boxtitle; /* title of container box */
415 int ncolumns; /* current no. of columns at bottom */
416 int ncontrols; /* number of `union control' in array */
417 int ctrlsize; /* allocated size of array */
418 union control **ctrls; /* actual array */
419};
420
421/*
422 * This is the container structure which holds a complete set of
423 * controls.
424 */
425struct controlbox {
426 int nctrlsets; /* number of ctrlsets */
427 int ctrlsetsize; /* ctrlset size */
428 struct controlset **ctrlsets; /* actual array of ctrlsets */
429 int nfrees;
430 int freesize;
431 void **frees; /* array of aux data areas to free */
432};
433
434struct controlbox *ctrl_new_box(void);
435void ctrl_free_box(struct controlbox *);
436
437/*
438 * Standard functions used for populating a controlbox structure.
439 */
440
441/* Set up a panel title. */
442struct controlset *ctrl_settitle(struct controlbox *,
443 char *path, char *title);
444/* Retrieve a pointer to a controlset, creating it if absent. */
445struct controlset *ctrl_getset(struct controlbox *,
446 char *path, char *name, char *boxtitle);
447void ctrl_free_set(struct controlset *);
448
449void ctrl_free(union control *);
450
451/*
452 * This function works like `malloc', but the memory it returns
453 * will be automatically freed when the controlbox is freed. Note
454 * that a controlbox is a dialog-box _template_, not an instance,
455 * and so data allocated through this function is better not used
456 * to hold modifiable per-instance things. It's mostly here for
457 * allocating structures to be passed as control handler params.
458 */
459void *ctrl_alloc(struct controlbox *b, size_t size);
460
461/*
462 * Individual routines to create `union control' structures in a controlset.
463 *
464 * Most of these routines allow the most common fields to be set
465 * directly, and put default values in the rest. Each one returns a
466 * pointer to the `union control' it created, so that final tweaks
467 * can be made.
468 */
469
470/* `ncolumns' is followed by that many percentages, as integers. */
471union control *ctrl_columns(struct controlset *, int ncolumns, ...);
472union control *ctrl_editbox(struct controlset *, char *label, char shortcut,
473 int percentage, intorptr helpctx,
474 handler_fn handler,
475 intorptr context, intorptr context2);
476union control *ctrl_combobox(struct controlset *, char *label, char shortcut,
477 int percentage, intorptr helpctx,
478 handler_fn handler,
479 intorptr context, intorptr context2);
480/*
481 * `ncolumns' is followed by (alternately) radio button titles and
482 * intorptrs, until a NULL in place of a title string is seen. Each
483 * title is expected to be followed by a shortcut _iff_ `shortcut'
484 * is NO_SHORTCUT.
485 */
486union control *ctrl_radiobuttons(struct controlset *, char *label,
487 char shortcut, int ncolumns,
488 intorptr helpctx,
489 handler_fn handler, intorptr context, ...);
490union control *ctrl_pushbutton(struct controlset *,char *label,char shortcut,
491 intorptr helpctx,
492 handler_fn handler, intorptr context);
493union control *ctrl_listbox(struct controlset *,char *label,char shortcut,
494 intorptr helpctx,
495 handler_fn handler, intorptr context);
496union control *ctrl_droplist(struct controlset *, char *label, char shortcut,
497 int percentage, intorptr helpctx,
498 handler_fn handler, intorptr context);
499union control *ctrl_draglist(struct controlset *,char *label,char shortcut,
500 intorptr helpctx,
501 handler_fn handler, intorptr context);
502union control *ctrl_filesel(struct controlset *,char *label,char shortcut,
503 char const *filter, int write, char *title,
504 intorptr helpctx,
505 handler_fn handler, intorptr context);
506union control *ctrl_fontsel(struct controlset *,char *label,char shortcut,
507 intorptr helpctx,
508 handler_fn handler, intorptr context);
509union control *ctrl_text(struct controlset *, char *text, intorptr helpctx);
510union control *ctrl_checkbox(struct controlset *, char *label, char shortcut,
511 intorptr helpctx,
512 handler_fn handler, intorptr context);
513union control *ctrl_tabdelay(struct controlset *, union control *);
514
515/*
516 * Standard handler routines to cover most of the common cases in
517 * the config box.
518 */
519/*
520 * The standard radio-button handler expects the main `context'
521 * field to contain the `offsetof' of an int field in the structure
522 * pointed to by `data', and expects each of the individual button
523 * data to give a value for that int field.
524 */
525void dlg_stdradiobutton_handler(union control *ctrl, void *dlg,
526 void *data, int event);
527/*
528 * The standard checkbox handler expects the main `context' field
529 * to contain the `offsetof' an int field in the structure pointed
530 * to by `data', optionally ORed with CHECKBOX_INVERT to indicate
531 * that the sense of the datum is opposite to the sense of the
532 * checkbox.
533 */
534#define CHECKBOX_INVERT (1<<30)
535void dlg_stdcheckbox_handler(union control *ctrl, void *dlg,
536 void *data, int event);
537/*
538 * The standard edit-box handler expects the main `context' field
539 * to contain the `offsetof' a field in the structure pointed to by
540 * `data'. The secondary `context2' field indicates the type of
541 * this field:
542 *
543 * - if context2 > 0, the field is a char array and context2 gives
544 * its size.
545 * - if context2 == -1, the field is an int and the edit box is
546 * numeric.
547 * - if context2 < -1, the field is an int and the edit box is
548 * _floating_, and (-context2) gives the scale. (E.g. if
549 * context2 == -1000, then typing 1.2 into the box will set the
550 * field to 1200.)
551 */
552void dlg_stdeditbox_handler(union control *ctrl, void *dlg,
553 void *data, int event);
554/*
555 * The standard file-selector handler expects the main `context'
556 * field to contain the `offsetof' a Filename field in the
557 * structure pointed to by `data'.
558 */
559void dlg_stdfilesel_handler(union control *ctrl, void *dlg,
560 void *data, int event);
561/*
562 * The standard font-selector handler expects the main `context'
563 * field to contain the `offsetof' a Font field in the structure
564 * pointed to by `data'.
565 */
566void dlg_stdfontsel_handler(union control *ctrl, void *dlg,
567 void *data, int event);
568
569/*
570 * Routines the platform-independent dialog code can call to read
571 * and write the values of controls.
572 */
573void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton);
574int dlg_radiobutton_get(union control *ctrl, void *dlg);
575void dlg_checkbox_set(union control *ctrl, void *dlg, int checked);
576int dlg_checkbox_get(union control *ctrl, void *dlg);
577void dlg_editbox_set(union control *ctrl, void *dlg, char const *text);
578void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length);
579/* The `listbox' functions can also apply to combo boxes. */
580void dlg_listbox_clear(union control *ctrl, void *dlg);
581void dlg_listbox_del(union control *ctrl, void *dlg, int index);
582void dlg_listbox_add(union control *ctrl, void *dlg, char const *text);
583/*
584 * Each listbox entry may have a numeric id associated with it.
585 * Note that some front ends only permit a string to be stored at
586 * each position, which means that _if_ you put two identical
587 * strings in any listbox then you MUST not assign them different
588 * IDs and expect to get meaningful results back.
589 */
4eaff8d4 590void dlg_listbox_addwithid(union control *ctrl, void *dlg,
591 char const *text, int id);
fe8abbf4 592int dlg_listbox_getid(union control *ctrl, void *dlg, int index);
593/* dlg_listbox_index returns <0 if no single element is selected. */
594int dlg_listbox_index(union control *ctrl, void *dlg);
595int dlg_listbox_issel(union control *ctrl, void *dlg, int index);
596void dlg_listbox_select(union control *ctrl, void *dlg, int index);
597void dlg_text_set(union control *ctrl, void *dlg, char const *text);
598void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn);
599void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn);
600void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn);
601void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn);
602/*
603 * Bracketing a large set of updates in these two functions will
604 * cause the front end (if possible) to delay updating the screen
605 * until it's all complete, thus avoiding flicker.
606 */
607void dlg_update_start(union control *ctrl, void *dlg);
608void dlg_update_done(union control *ctrl, void *dlg);
609/*
610 * Set input focus into a particular control.
611 */
612void dlg_set_focus(union control *ctrl, void *dlg);
613/*
7374c779 614 * Change the label text on a control.
615 */
616void dlg_label_change(union control *ctrl, void *dlg, char const *text);
617/*
0bd8d76d 618 * Return the `ctrl' structure for the most recent control that had
619 * the input focus apart from the one mentioned. This is NOT
620 * GUARANTEED to work on all platforms, so don't base any critical
621 * functionality on it!
fe8abbf4 622 */
0bd8d76d 623union control *dlg_last_focused(union control *ctrl, void *dlg);
fe8abbf4 624/*
625 * During event processing, you might well want to give an error
626 * indication to the user. dlg_beep() is a quick and easy generic
627 * error; dlg_error() puts up a message-box or equivalent.
628 */
629void dlg_beep(void *dlg);
630void dlg_error_msg(void *dlg, char *msg);
631/*
632 * This function signals to the front end that the dialog's
633 * processing is completed, and passes an integer value (typically
634 * a success status).
635 */
636void dlg_end(void *dlg, int value);
637
638/*
639 * Routines to manage a (per-platform) colour selector.
640 * dlg_coloursel_start() is called in an event handler, and
641 * schedules the running of a colour selector after the event
642 * handler returns. The colour selector will send EVENT_CALLBACK to
643 * the control that spawned it, when it's finished;
644 * dlg_coloursel_results() fetches the results, as integers from 0
645 * to 255; it returns nonzero on success, or zero if the colour
646 * selector was dismissed by hitting Cancel or similar.
647 *
648 * dlg_coloursel_start() accepts an RGB triple which is used to
649 * initialise the colour selector to its starting value.
650 */
651void dlg_coloursel_start(union control *ctrl, void *dlg,
652 int r, int g, int b);
653int dlg_coloursel_results(union control *ctrl, void *dlg,
654 int *r, int *g, int *b);
655
656/*
657 * This routine is used by the platform-independent code to
658 * indicate that the value of a particular control is likely to
659 * have changed. It triggers a call of the handler for that control
660 * with `event' set to EVENT_REFRESH.
661 *
662 * If `ctrl' is NULL, _all_ controls in the dialog get refreshed
663 * (for loading or saving entire sets of settings).
664 */
665void dlg_refresh(union control *ctrl, void *dlg);
666
667/*
4e6d4091 668 * It's perfectly possible that individual controls might need to
669 * allocate or store per-dialog-instance data, so here's a
670 * mechanism.
671 *
672 * `dlg_get_privdata' and `dlg_set_privdata' allow the user to get
673 * and set a void * pointer associated with the control in
674 * question. `dlg_alloc_privdata' will allocate memory, store a
675 * pointer to that memory in the private data field, and arrange
676 * for it to be automatically deallocated on dialog cleanup.
677 */
678void *dlg_get_privdata(union control *ctrl, void *dlg);
679void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr);
680void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size);
681
682/*
fe8abbf4 683 * Standard helper functions for reading a controlbox structure.
684 */
685
686/*
687 * Find the index of next controlset in a controlbox for a given
688 * path, or -1 if no such controlset exists. If -1 is passed as
689 * input, finds the first. Intended usage is something like
690 *
691 * for (index=-1; (index=ctrl_find_path(ctrlbox, index, path)) >= 0 ;) {
692 * ... process this controlset ...
693 * }
694 */
695int ctrl_find_path(struct controlbox *b, char *path, int index);
696int ctrl_path_elements(char *path);
697/* Return the number of matching path elements at the starts of p1 and p2,
698 * or INT_MAX if the paths are identical. */
699int ctrl_path_compare(char *p1, char *p2);