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