2 * Exports and types from dialog.c.
6 * This will come in handy for generic control handlers. Anyone
7 * knows how to make this more portable, let me know :-)
9 #define ATOFFSET(data, offset) ( (void *) ( (char *)(data) + (offset) ) )
12 * This is the big union which defines a single control, of any
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.
26 #define NO_SHORTCUT '\0'
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 */
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.
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,
52 typedef union { void *p
; int i
; } intorptr
;
59 #if defined DEFINE_INTORPTR_FNS || defined INLINE
65 PREFIX intorptr
I(int i
) { intorptr ret
; ret
.i
= i
; return ret
; }
66 PREFIX intorptr
P(void *p
) { intorptr ret
; ret
.p
= p
; return ret
; }
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.
75 * If a control belongs in exactly one column, just specifying the
76 * column number is perfectly adequate.
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 )
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
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
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.
112 typedef void (*handler_fn
)(union control
*ctrl
, void *dlg
,
113 void *data
, int event
);
115 #define STANDARD_PREFIX \
120 handler_fn handler; \
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.
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.
139 * Yes, this does mean that any non-NULL value in this
140 * field is expected to be dynamically allocated and
143 * For CTRL_COLUMNS, this field MUST be NULL.
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.
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.
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.
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
168 * The `dlg' parameter is passed back to the platform-
169 * specific routines to read and write the actual control
174 * Almost all of the above functions will find it useful to
175 * be able to store a piece of `void *' or `int' data.
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.
198 char shortcut
; /* keyboard shortcut */
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
206 int password
; /* details of input are hidden */
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
215 * Edit boxes tend to need two items of context, so here's
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.
230 * There are separate fields for `ncolumns' and `nbuttons'
231 * for several reasons.
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'.
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
255 * This points to a dynamically allocated array of `char *'
256 * pointers, each of which points to a dynamically
259 char **buttons
; /* `nbuttons' button labels */
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.
265 char *shortcuts
; /* `nbuttons' shortcuts; may be NULL */
267 * This points to a dynamically allocated array of
268 * intorptr, giving helpful data for each button.
270 intorptr
*buttondata
; /* `nbuttons' entries; may be NULL */
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.
288 char shortcut
; /* keyboard shortcut */
290 * Height of the list box, in approximate number of lines.
291 * If this is zero, the list is a drop-down list.
293 int height
; /* height in lines */
295 * If this is set, the list elements can be reordered by
296 * the user (by drag-and-drop or by Up and Down buttons,
297 * whatever the per-platform implementation feels
298 * comfortable with). This is not guaranteed to work on a
299 * drop-down list, so don't try it!
303 * If this is set, the list can have more than one element
304 * selected at a time. This is not guaranteed to work on a
305 * drop-down list, so don't try it!
309 * Percentage of the dialog-box width used by the list box.
310 * If this is set to 100, the label is on its own line;
311 * otherwise the label is on the same line as the box
312 * itself. Setting this to anything other than 100 is not
313 * guaranteed to work on a _non_-drop-down list, so don't
318 * Some list boxes contain strings that contain tab
319 * characters. If `ncols' is greater than 0, then
320 * `percentages' is expected to be non-zero and to contain
321 * the respective widths of `ncols' columns, which together
322 * will exactly fit the width of the list box. Otherwise
323 * `percentages' must be NULL.
325 int ncols
; /* number of columns */
326 int *percentages
; /* % width of each column */
332 * `filter' dictates what type of files will be selected by
333 * default; for example, when selecting private key files
334 * the file selector would do well to only show .PPK files
335 * (on those systems where this is the chosen extension).
337 * The precise contents of `filter' are platform-defined,
338 * unfortunately. The special value NULL means `all files'
339 * and is always a valid fallback.
341 * Unlike almost all strings in this structure, this value
342 * is NOT expected to require freeing (although of course
343 * you can always use ctrl_alloc if you do need to create
344 * one on the fly). This is because the likely mode of use
345 * is to define string constants in a platform-specific
346 * header file, and directly reference those. Or worse, a
347 * particular platform might choose to cast integers into
348 * this pointer type...
352 * Some systems like to know whether a file selector is
353 * choosing a file to read or one to write (and possibly
358 * On at least some platforms, the file selector is a
359 * separate dialog box, and contains a user-settable title.
361 * This value _is_ expected to require freeing.
366 /* In this variant, `label' MUST be NULL. */
368 int ncols
; /* number of columns */
369 int *percentages
; /* % width of each column */
371 * Every time this control type appears, exactly one of
372 * `ncols' and the previous number of columns MUST be one.
373 * Attempting to allow a seamless transition from a four-
374 * to a five-column layout, for example, would be way more
375 * trouble than it was worth. If you must lay things out
376 * like that, define eight unevenly sized columns and use
377 * column-spanning a lot. But better still, just don't.
379 * `percentages' may be NULL if ncols==1, to save space.
388 #undef STANDARD_PREFIX
391 * `controlset' is a container holding an array of `union control'
392 * structures, together with a panel name and a title for the whole
393 * set. In Windows and any similar-looking GUI, each `controlset'
394 * in the config will be a container box within a panel.
396 * Special case: if `boxname' is NULL, the control set gives an
397 * overall title for an entire panel of controls.
400 char *pathname
; /* panel path, e.g. "SSH/Tunnels" */
401 char *boxname
; /* internal short name of controlset */
402 char *boxtitle
; /* title of container box */
403 int ncolumns
; /* current no. of columns at bottom */
404 int ncontrols
; /* number of `union control' in array */
405 int ctrlsize
; /* allocated size of array */
406 union control
**ctrls
; /* actual array */
410 * This is the container structure which holds a complete set of
414 int nctrlsets
; /* number of ctrlsets */
415 int ctrlsetsize
; /* ctrlset size */
416 struct controlset
**ctrlsets
; /* actual array of ctrlsets */
419 void **frees
; /* array of aux data areas to free */
422 struct controlbox
*ctrl_new_box(void);
423 void ctrl_free_box(struct controlbox
*);
426 * Standard functions used for populating a controlbox structure.
429 /* Set up a panel title. */
430 struct controlset
*ctrl_settitle(struct controlbox
*,
431 char *path
, char *title
);
432 /* Retrieve a pointer to a controlset, creating it if absent. */
433 struct controlset
*ctrl_getset(struct controlbox
*,
434 char *path
, char *name
, char *boxtitle
);
435 void ctrl_free_set(struct controlset
*);
437 void ctrl_free(union control
*);
440 * This function works like `malloc', but the memory it returns
441 * will be automatically freed when the controlbox is freed. Note
442 * that a controlbox is a dialog-box _template_, not an instance,
443 * and so data allocated through this function is better not used
444 * to hold modifiable per-instance things. It's mostly here for
445 * allocating structures to be passed as control handler params.
447 void *ctrl_alloc(struct controlbox
*b
, size_t size
);
450 * Individual routines to create `union control' structures in a controlset.
452 * Most of these routines allow the most common fields to be set
453 * directly, and put default values in the rest. Each one returns a
454 * pointer to the `union control' it created, so that final tweaks
458 /* `ncolumns' is followed by that many percentages, as integers. */
459 union control
*ctrl_columns(struct controlset
*, int ncolumns
, ...);
460 union control
*ctrl_editbox(struct controlset
*, char *label
, char shortcut
,
461 int percentage
, intorptr helpctx
,
463 intorptr context
, intorptr context2
);
464 union control
*ctrl_combobox(struct controlset
*, char *label
, char shortcut
,
465 int percentage
, intorptr helpctx
,
467 intorptr context
, intorptr context2
);
469 * `ncolumns' is followed by (alternately) radio button titles and
470 * intorptrs, until a NULL in place of a title string is seen. Each
471 * title is expected to be followed by a shortcut _iff_ `shortcut'
474 union control
*ctrl_radiobuttons(struct controlset
*, char *label
,
475 char shortcut
, int ncolumns
,
477 handler_fn handler
, intorptr context
, ...);
478 union control
*ctrl_pushbutton(struct controlset
*,char *label
,char shortcut
,
480 handler_fn handler
, intorptr context
);
481 union control
*ctrl_listbox(struct controlset
*,char *label
,char shortcut
,
483 handler_fn handler
, intorptr context
);
484 union control
*ctrl_droplist(struct controlset
*, char *label
, char shortcut
,
485 int percentage
, intorptr helpctx
,
486 handler_fn handler
, intorptr context
);
487 union control
*ctrl_draglist(struct controlset
*,char *label
,char shortcut
,
489 handler_fn handler
, intorptr context
);
490 union control
*ctrl_filesel(struct controlset
*,char *label
,char shortcut
,
491 char const *filter
, int write
, char *title
,
493 handler_fn handler
, intorptr context
);
494 union control
*ctrl_fontsel(struct controlset
*,char *label
,char shortcut
,
496 handler_fn handler
, intorptr context
);
497 union control
*ctrl_text(struct controlset
*, char *text
, intorptr helpctx
);
498 union control
*ctrl_checkbox(struct controlset
*, char *label
, char shortcut
,
500 handler_fn handler
, intorptr context
);
501 union control
*ctrl_tabdelay(struct controlset
*, union control
*);
504 * Standard handler routines to cover most of the common cases in
508 * The standard radio-button handler expects the main `context'
509 * field to contain the `offsetof' of an int field in the structure
510 * pointed to by `data', and expects each of the individual button
511 * data to give a value for that int field.
513 void dlg_stdradiobutton_handler(union control
*ctrl
, void *dlg
,
514 void *data
, int event
);
516 * The standard checkbox handler expects the main `context' field
517 * to contain the `offsetof' an int field in the structure pointed
518 * to by `data', optionally ORed with CHECKBOX_INVERT to indicate
519 * that the sense of the datum is opposite to the sense of the
522 #define CHECKBOX_INVERT (1<<30)
523 void dlg_stdcheckbox_handler(union control
*ctrl
, void *dlg
,
524 void *data
, int event
);
526 * The standard edit-box handler expects the main `context' field
527 * to contain the `offsetof' a field in the structure pointed to by
528 * `data'. The secondary `context2' field indicates the type of
531 * - if context2 > 0, the field is a char array and context2 gives
533 * - if context2 == -1, the field is an int and the edit box is
535 * - if context2 < -1, the field is an int and the edit box is
536 * _floating_, and (-context2) gives the scale. (E.g. if
537 * context2 == -1000, then typing 1.2 into the box will set the
540 void dlg_stdeditbox_handler(union control
*ctrl
, void *dlg
,
541 void *data
, int event
);
543 * The standard file-selector handler expects the main `context'
544 * field to contain the `offsetof' a Filename field in the
545 * structure pointed to by `data'.
547 void dlg_stdfilesel_handler(union control
*ctrl
, void *dlg
,
548 void *data
, int event
);
550 * The standard font-selector handler expects the main `context'
551 * field to contain the `offsetof' a Font field in the structure
552 * pointed to by `data'.
554 void dlg_stdfontsel_handler(union control
*ctrl
, void *dlg
,
555 void *data
, int event
);
558 * Routines the platform-independent dialog code can call to read
559 * and write the values of controls.
561 void dlg_radiobutton_set(union control
*ctrl
, void *dlg
, int whichbutton
);
562 int dlg_radiobutton_get(union control
*ctrl
, void *dlg
);
563 void dlg_checkbox_set(union control
*ctrl
, void *dlg
, int checked
);
564 int dlg_checkbox_get(union control
*ctrl
, void *dlg
);
565 void dlg_editbox_set(union control
*ctrl
, void *dlg
, char const *text
);
566 void dlg_editbox_get(union control
*ctrl
, void *dlg
, char *buffer
, int length
);
567 /* The `listbox' functions can also apply to combo boxes. */
568 void dlg_listbox_clear(union control
*ctrl
, void *dlg
);
569 void dlg_listbox_del(union control
*ctrl
, void *dlg
, int index
);
570 void dlg_listbox_add(union control
*ctrl
, void *dlg
, char const *text
);
572 * Each listbox entry may have a numeric id associated with it.
573 * Note that some front ends only permit a string to be stored at
574 * each position, which means that _if_ you put two identical
575 * strings in any listbox then you MUST not assign them different
576 * IDs and expect to get meaningful results back.
578 void dlg_listbox_addwithindex(union control
*ctrl
, void *dlg
,
579 char const *text
, int id
);
580 int dlg_listbox_getid(union control
*ctrl
, void *dlg
, int index
);
581 /* dlg_listbox_index returns <0 if no single element is selected. */
582 int dlg_listbox_index(union control
*ctrl
, void *dlg
);
583 int dlg_listbox_issel(union control
*ctrl
, void *dlg
, int index
);
584 void dlg_listbox_select(union control
*ctrl
, void *dlg
, int index
);
585 void dlg_text_set(union control
*ctrl
, void *dlg
, char const *text
);
586 void dlg_filesel_set(union control
*ctrl
, void *dlg
, Filename fn
);
587 void dlg_filesel_get(union control
*ctrl
, void *dlg
, Filename
*fn
);
588 void dlg_fontsel_set(union control
*ctrl
, void *dlg
, FontSpec fn
);
589 void dlg_fontsel_get(union control
*ctrl
, void *dlg
, FontSpec
*fn
);
591 * Bracketing a large set of updates in these two functions will
592 * cause the front end (if possible) to delay updating the screen
593 * until it's all complete, thus avoiding flicker.
595 void dlg_update_start(union control
*ctrl
, void *dlg
);
596 void dlg_update_done(union control
*ctrl
, void *dlg
);
598 * Set input focus into a particular control.
600 void dlg_set_focus(union control
*ctrl
, void *dlg
);
602 * Return the `ctrl' structure for the control that had the input
603 * focus before this one. This is NOT GUARANTEED to work on all
604 * platforms, so don't base any critical functionality on it!
606 union control
*dlg_last_focused(void *dlg
);
608 * During event processing, you might well want to give an error
609 * indication to the user. dlg_beep() is a quick and easy generic
610 * error; dlg_error() puts up a message-box or equivalent.
612 void dlg_beep(void *dlg
);
613 void dlg_error_msg(void *dlg
, char *msg
);
615 * This function signals to the front end that the dialog's
616 * processing is completed, and passes an integer value (typically
619 void dlg_end(void *dlg
, int value
);
622 * Routines to manage a (per-platform) colour selector.
623 * dlg_coloursel_start() is called in an event handler, and
624 * schedules the running of a colour selector after the event
625 * handler returns. The colour selector will send EVENT_CALLBACK to
626 * the control that spawned it, when it's finished;
627 * dlg_coloursel_results() fetches the results, as integers from 0
628 * to 255; it returns nonzero on success, or zero if the colour
629 * selector was dismissed by hitting Cancel or similar.
631 * dlg_coloursel_start() accepts an RGB triple which is used to
632 * initialise the colour selector to its starting value.
634 void dlg_coloursel_start(union control
*ctrl
, void *dlg
,
635 int r
, int g
, int b
);
636 int dlg_coloursel_results(union control
*ctrl
, void *dlg
,
637 int *r
, int *g
, int *b
);
640 * This routine is used by the platform-independent code to
641 * indicate that the value of a particular control is likely to
642 * have changed. It triggers a call of the handler for that control
643 * with `event' set to EVENT_REFRESH.
645 * If `ctrl' is NULL, _all_ controls in the dialog get refreshed
646 * (for loading or saving entire sets of settings).
648 void dlg_refresh(union control
*ctrl
, void *dlg
);
651 * It's perfectly possible that individual controls might need to
652 * allocate or store per-dialog-instance data, so here's a
655 * `dlg_get_privdata' and `dlg_set_privdata' allow the user to get
656 * and set a void * pointer associated with the control in
657 * question. `dlg_alloc_privdata' will allocate memory, store a
658 * pointer to that memory in the private data field, and arrange
659 * for it to be automatically deallocated on dialog cleanup.
661 void *dlg_get_privdata(union control
*ctrl
, void *dlg
);
662 void dlg_set_privdata(union control
*ctrl
, void *dlg
, void *ptr
);
663 void *dlg_alloc_privdata(union control
*ctrl
, void *dlg
, size_t size
);
666 * Standard helper functions for reading a controlbox structure.
670 * Find the index of next controlset in a controlbox for a given
671 * path, or -1 if no such controlset exists. If -1 is passed as
672 * input, finds the first. Intended usage is something like
674 * for (index=-1; (index=ctrl_find_path(ctrlbox, index, path)) >= 0 ;) {
675 * ... process this controlset ...
678 int ctrl_find_path(struct controlbox
*b
, char *path
, int index
);
679 int ctrl_path_elements(char *path
);
680 /* Return the number of matching path elements at the starts of p1 and p2,
681 * or INT_MAX if the paths are identical. */
682 int ctrl_path_compare(char *p1
, char *p2
);