]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - dialog.h
The long-awaited config box revamp! I've taken the whole config box
[PuTTY.git] / dialog.h
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 /*
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  */
661 int ctrl_find_path(struct controlbox *b, char *path, int index);
662 int 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. */
665 int ctrl_path_compare(char *p1, char *p2);