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 | |
28 | enum { |
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 | */ |
52 | typedef 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 |
60 | PREFIX intorptr I(int i) { intorptr ret; ret.i = i; return ret; } |
61 | PREFIX intorptr P(void *p) { intorptr ret; ret.p = p; return ret; } |
62 | #undef PREFIX |
63 | #else |
64 | intorptr I(int i); |
65 | intorptr 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 | |
80 | union 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 | */ |
103 | enum { |
104 | EVENT_REFRESH, |
105 | EVENT_ACTION, |
106 | EVENT_VALCHANGE, |
107 | EVENT_SELCHANGE, |
108 | EVENT_CALLBACK |
109 | }; |
110 | typedef 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 | |
122 | union 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 | */ |
397 | struct 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 | */ |
411 | struct 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 | |
420 | struct controlbox *ctrl_new_box(void); |
421 | void ctrl_free_box(struct controlbox *); |
422 | |
423 | /* |
424 | * Standard functions used for populating a controlbox structure. |
425 | */ |
426 | |
427 | /* Set up a panel title. */ |
428 | struct controlset *ctrl_settitle(struct controlbox *, |
429 | char *path, char *title); |
430 | /* Retrieve a pointer to a controlset, creating it if absent. */ |
431 | struct controlset *ctrl_getset(struct controlbox *, |
432 | char *path, char *name, char *boxtitle); |
433 | void ctrl_free_set(struct controlset *); |
434 | |
435 | void 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 | */ |
445 | void *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. */ |
457 | union control *ctrl_columns(struct controlset *, int ncolumns, ...); |
458 | union control *ctrl_editbox(struct controlset *, char *label, char shortcut, |
459 | int percentage, intorptr helpctx, |
460 | handler_fn handler, |
461 | intorptr context, intorptr context2); |
462 | union 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 | */ |
472 | union control *ctrl_radiobuttons(struct controlset *, char *label, |
473 | char shortcut, int ncolumns, |
474 | intorptr helpctx, |
475 | handler_fn handler, intorptr context, ...); |
476 | union control *ctrl_pushbutton(struct controlset *,char *label,char shortcut, |
477 | intorptr helpctx, |
478 | handler_fn handler, intorptr context); |
479 | union control *ctrl_listbox(struct controlset *,char *label,char shortcut, |
480 | intorptr helpctx, |
481 | handler_fn handler, intorptr context); |
482 | union control *ctrl_droplist(struct controlset *, char *label, char shortcut, |
483 | int percentage, intorptr helpctx, |
484 | handler_fn handler, intorptr context); |
485 | union control *ctrl_draglist(struct controlset *,char *label,char shortcut, |
486 | intorptr helpctx, |
487 | handler_fn handler, intorptr context); |
488 | union 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); |
492 | union control *ctrl_fontsel(struct controlset *,char *label,char shortcut, |
493 | intorptr helpctx, |
494 | handler_fn handler, intorptr context); |
495 | union control *ctrl_text(struct controlset *, char *text, intorptr helpctx); |
496 | union control *ctrl_checkbox(struct controlset *, char *label, char shortcut, |
497 | intorptr helpctx, |
498 | handler_fn handler, intorptr context); |
499 | union 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 | */ |
511 | void 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) |
521 | void 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 | */ |
538 | void 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 | */ |
545 | void 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 | */ |
552 | void 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 | */ |
559 | void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton); |
560 | int dlg_radiobutton_get(union control *ctrl, void *dlg); |
561 | void dlg_checkbox_set(union control *ctrl, void *dlg, int checked); |
562 | int dlg_checkbox_get(union control *ctrl, void *dlg); |
563 | void dlg_editbox_set(union control *ctrl, void *dlg, char const *text); |
564 | void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length); |
565 | /* The `listbox' functions can also apply to combo boxes. */ |
566 | void dlg_listbox_clear(union control *ctrl, void *dlg); |
567 | void dlg_listbox_del(union control *ctrl, void *dlg, int index); |
568 | void 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 | */ |
576 | void dlg_listbox_addwithindex(union control *ctrl, void *dlg, |
577 | char const *text, int id); |
578 | int dlg_listbox_getid(union control *ctrl, void *dlg, int index); |
579 | /* dlg_listbox_index returns <0 if no single element is selected. */ |
580 | int dlg_listbox_index(union control *ctrl, void *dlg); |
581 | int dlg_listbox_issel(union control *ctrl, void *dlg, int index); |
582 | void dlg_listbox_select(union control *ctrl, void *dlg, int index); |
583 | void dlg_text_set(union control *ctrl, void *dlg, char const *text); |
584 | void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn); |
585 | void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn); |
586 | void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn); |
587 | void 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 | */ |
593 | void dlg_update_start(union control *ctrl, void *dlg); |
594 | void dlg_update_done(union control *ctrl, void *dlg); |
595 | /* |
596 | * Set input focus into a particular control. |
597 | */ |
598 | void 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 | */ |
604 | union 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 | */ |
610 | void dlg_beep(void *dlg); |
611 | void 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 | */ |
617 | void 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 | */ |
632 | void dlg_coloursel_start(union control *ctrl, void *dlg, |
633 | int r, int g, int b); |
634 | int 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 | */ |
646 | void dlg_refresh(union control *ctrl, void *dlg); |
647 | |
648 | /* |
4e6d4091 |
649 | * It's perfectly possible that individual controls might need to |
650 | * allocate or store per-dialog-instance data, so here's a |
651 | * mechanism. |
652 | * |
653 | * `dlg_get_privdata' and `dlg_set_privdata' allow the user to get |
654 | * and set a void * pointer associated with the control in |
655 | * question. `dlg_alloc_privdata' will allocate memory, store a |
656 | * pointer to that memory in the private data field, and arrange |
657 | * for it to be automatically deallocated on dialog cleanup. |
658 | */ |
659 | void *dlg_get_privdata(union control *ctrl, void *dlg); |
660 | void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr); |
661 | void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size); |
662 | |
663 | /* |
fe8abbf4 |
664 | * Standard helper functions for reading a controlbox structure. |
665 | */ |
666 | |
667 | /* |
668 | * Find the index of next controlset in a controlbox for a given |
669 | * path, or -1 if no such controlset exists. If -1 is passed as |
670 | * input, finds the first. Intended usage is something like |
671 | * |
672 | * for (index=-1; (index=ctrl_find_path(ctrlbox, index, path)) >= 0 ;) { |
673 | * ... process this controlset ... |
674 | * } |
675 | */ |
676 | int ctrl_find_path(struct controlbox *b, char *path, int index); |
677 | int ctrl_path_elements(char *path); |
678 | /* Return the number of matching path elements at the starts of p1 and p2, |
679 | * or INT_MAX if the paths are identical. */ |
680 | int ctrl_path_compare(char *p1, char *p2); |