]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mac/macctrls.c
a654d632ae65469059de49943de80206a21646ce
[PuTTY.git] / mac / macctrls.c
1 /* $Id: macctrls.c,v 1.34 2003/04/14 21:34:46 ben Exp $ */
2 /*
3  * Copyright (c) 2003 Ben Harris
4  * All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  * 
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 #include <MacTypes.h>
29 #include <Appearance.h>
30 #include <Controls.h>
31 #include <ControlDefinitions.h>
32 #include <Events.h>
33 #include <Lists.h>
34 #include <Menus.h>
35 #include <Resources.h>
36 #include <Script.h>
37 #include <Sound.h>
38 #include <TextEdit.h>
39 #include <TextUtils.h>
40 #include <ToolUtils.h>
41 #include <Windows.h>
42
43 #include <assert.h>
44 #include <string.h>
45
46 #include "putty.h"
47 #include "mac.h"
48 #include "macresid.h"
49 #include "dialog.h"
50 #include "tree234.h"
51
52 /* Range of menu IDs for popup menus */
53 #define MENU_MIN        1024
54 #define MENU_MAX        2048
55
56
57 union macctrl {
58     struct macctrl_generic {
59         enum {
60             MACCTRL_TEXT,
61             MACCTRL_EDITBOX,
62             MACCTRL_RADIO,
63             MACCTRL_CHECKBOX,
64             MACCTRL_BUTTON,
65             MACCTRL_LISTBOX,
66             MACCTRL_POPUP
67         } type;
68         /* Template from which this was generated */
69         union control *ctrl;
70         /* Next control in this panel */
71         union macctrl *next;
72         void *privdata;
73         int freeprivdata;
74     } generic;
75     struct {
76         struct macctrl_generic generic;
77         ControlRef tbctrl;
78     } text;
79     struct {
80         struct macctrl_generic generic;
81         ControlRef tbctrl;
82         ControlRef tblabel;
83     } editbox;
84     struct {
85         struct macctrl_generic generic;
86         ControlRef *tbctrls;
87         ControlRef tblabel;
88     } radio;
89     struct {
90         struct macctrl_generic generic;
91         ControlRef tbctrl;
92     } checkbox;
93     struct {
94         struct macctrl_generic generic;
95         ControlRef tbctrl;
96         ControlRef tbring;
97     } button;
98     struct {
99         struct macctrl_generic generic;
100         ControlRef tbctrl;
101         ListHandle list;
102         unsigned int nids;
103         int *ids;
104     } listbox;
105     struct {
106         struct macctrl_generic generic;
107         ControlRef tbctrl;
108         MenuRef menu;
109         int menuid;
110         unsigned int nids;
111         int *ids;
112     } popup;
113 };
114
115 struct mac_layoutstate {
116     Point pos;
117     unsigned int width;
118     unsigned int panelnum;
119 };
120
121 #define ctrlevent(mcs, mc, event) do {                                  \
122     if ((mc)->generic.ctrl->generic.handler != NULL)                    \
123         (*(mc)->generic.ctrl->generic.handler)((mc)->generic.ctrl, (mcs),\
124                                                (mcs)->data, (event));   \
125 } while (0)
126
127 #define findbyctrl(mcs, ctrl)                                           \
128     find234((mcs)->byctrl, (ctrl), macctrl_cmp_byctrl_find)
129
130 static void macctrl_layoutset(struct mac_layoutstate *, struct controlset *, 
131                               WindowPtr, struct macctrls *);
132 static void macctrl_switchtopanel(struct macctrls *, unsigned int);
133 static void macctrl_setfocus(struct macctrls *, union macctrl *);
134 static void macctrl_text(struct macctrls *, WindowPtr,
135                          struct mac_layoutstate *, union control *);
136 static void macctrl_editbox(struct macctrls *, WindowPtr,
137                             struct mac_layoutstate *, union control *);
138 static void macctrl_radio(struct macctrls *, WindowPtr,
139                           struct mac_layoutstate *, union control *);
140 static void macctrl_checkbox(struct macctrls *, WindowPtr,
141                              struct mac_layoutstate *, union control *);
142 static void macctrl_button(struct macctrls *, WindowPtr,
143                            struct mac_layoutstate *, union control *);
144 static void macctrl_listbox(struct macctrls *, WindowPtr,
145                             struct mac_layoutstate *, union control *);
146 static void macctrl_popup(struct macctrls *, WindowPtr,
147                           struct mac_layoutstate *, union control *);
148 #if !TARGET_API_MAC_CARBON
149 static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16, ControlRef,
150                                                ControlDefProcMessage, SInt32);
151 static pascal SInt32 macctrl_sys7_default_cdef(SInt16, ControlRef,
152                                                ControlDefProcMessage, SInt32);
153 static pascal SInt32 macctrl_sys7_listbox_cdef(SInt16, ControlRef,
154                                                ControlDefProcMessage, SInt32);
155 #endif
156
157 #if !TARGET_API_MAC_CARBON
158 /*
159  * This trick enables us to keep all the CDEF code in the main
160  * application, which makes life easier.  For details, see
161  * <http://developer.apple.com/technotes/tn/tn2003.html#custom_code_base>.
162  */
163
164 #pragma options align=mac68k
165 typedef struct {
166     short               jmpabs; /* 4EF9 */
167     ControlDefUPP       theUPP;
168 } **PatchCDEF;
169 #pragma options align=reset
170 #endif
171
172 static void macctrl_init()
173 {
174 #if !TARGET_API_MAC_CARBON
175     static int inited = 0;
176     PatchCDEF cdef;
177
178     if (inited) return;
179     cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_EditBox);
180     (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_editbox_cdef);
181     cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_Default);
182     (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_default_cdef);
183     cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_ListBox);
184     (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_listbox_cdef);
185     inited = 1;
186 #endif
187 }
188
189
190 static int macctrl_cmp_byctrl(void *av, void *bv)
191 {
192     union macctrl *a = (union macctrl *)av;
193     union macctrl *b = (union macctrl *)bv;
194
195     if (a->generic.ctrl < b->generic.ctrl)
196         return -1;
197     else if (a->generic.ctrl > b->generic.ctrl)
198         return +1;
199     else
200         return 0;
201 }
202
203 static int macctrl_cmp_byctrl_find(void *av, void *bv)
204 {
205     union control *a = (union control *)av;
206     union macctrl *b = (union macctrl *)bv;
207
208     if (a < b->generic.ctrl)
209         return -1;
210     else if (a > b->generic.ctrl)
211         return +1;
212     else
213         return 0;
214 }
215
216 static union control panellist;
217
218 static void panellist_handler(union control *ctrl, void *dlg, void *data,
219                               int event)
220 {
221     struct macctrls *mcs = dlg;
222
223     if (event == EVENT_SELCHANGE)
224         macctrl_switchtopanel(mcs, dlg_listbox_index(ctrl, dlg) + 1);
225 }
226
227 void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
228                        struct macctrls *mcs)
229 {
230     int i;
231     struct mac_layoutstate curstate;
232     ControlRef root;
233     Rect rect;
234
235     macctrl_init();
236     if (mac_gestalts.apprvers >= 0x100)
237         CreateRootControl(window, &root);
238 #if TARGET_API_MAC_CARBON
239     GetPortBounds(GetWindowPort(window), &rect);
240 #else
241     rect = window->portRect;
242 #endif
243     mcs->window = window;
244     mcs->byctrl = newtree234(macctrl_cmp_byctrl);
245     mcs->focus = NULL;
246     mcs->defbutton = NULL;
247     mcs->canbutton = NULL;
248     /* Count the number of panels */
249     mcs->npanels = 1;
250     for (i = 1; i < cb->nctrlsets; i++)
251         if (strcmp(cb->ctrlsets[i]->pathname, cb->ctrlsets[i-1]->pathname))
252             mcs->npanels++;
253     mcs->panels = snewn(mcs->npanels, union macctrl *);
254     memset(mcs->panels, 0, sizeof(*mcs->panels) * mcs->npanels);
255     curstate.panelnum = 0;
256
257     curstate.pos.h = rect.left + 13;
258     curstate.pos.v = rect.top + 13;
259     curstate.width = 160;
260     panellist.listbox.type = CTRL_LISTBOX;
261     panellist.listbox.handler = &panellist_handler;
262     panellist.listbox.height = 15;
263     panellist.listbox.percentwidth = 100;
264     macctrl_listbox(mcs, window, &curstate, &panellist);
265
266     curstate.pos.h = rect.left + 13 + 160 + 13;
267     curstate.pos.v = rect.bottom - 33;
268     curstate.width = rect.right - (rect.left + 13 + 160) - (13 * 2);
269     for (i = 0; i < cb->nctrlsets; i++) {
270         if (i > 0 && strcmp(cb->ctrlsets[i]->pathname,
271                             cb->ctrlsets[i-1]->pathname)) {
272             curstate.pos.v = rect.top + 13;
273             curstate.panelnum++;
274             assert(curstate.panelnum < mcs->npanels);
275             dlg_listbox_add(&panellist, mcs, cb->ctrlsets[i]->pathname);
276         }
277         macctrl_layoutset(&curstate, cb->ctrlsets[i], window, mcs);
278     }
279     macctrl_switchtopanel(mcs, 1);
280     /* 14 = proxies, 19 = portfwd, 20 = SSH bugs */
281 }
282
283 #define MAXCOLS 16
284
285 static void macctrl_layoutset(struct mac_layoutstate *curstate,
286                               struct controlset *s,
287                               WindowPtr window, struct macctrls *mcs)
288 {
289     unsigned int i, j, ncols, colstart;
290     struct mac_layoutstate cols[MAXCOLS];
291
292     fprintf(stderr, "--- begin set ---\n");
293     fprintf(stderr, "pathname = %s\n", s->pathname);
294     if (s->boxname && *s->boxname)
295         fprintf(stderr, "boxname = %s\n", s->boxname);
296     if (s->boxtitle)
297         fprintf(stderr, "boxtitle = %s\n", s->boxtitle);
298
299     cols[0] = *curstate;
300     ncols = 1;
301
302     for (i = 0; i < s->ncontrols; i++) {
303         union control *ctrl = s->ctrls[i];
304         char const *s;
305
306         colstart = COLUMN_START(ctrl->generic.column);
307         switch (ctrl->generic.type) {
308           case CTRL_TEXT: s = "text"; break;
309           case CTRL_EDITBOX: s = "editbox"; break;
310           case CTRL_RADIO: s = "radio"; break;
311           case CTRL_CHECKBOX: s = "checkbox"; break;
312           case CTRL_BUTTON: s = "button"; break;
313           case CTRL_LISTBOX: s = "listbox"; break;
314           case CTRL_COLUMNS: s = "columns"; break;
315           case CTRL_FILESELECT: s = "fileselect"; break;
316           case CTRL_FONTSELECT: s = "fontselect"; break;
317           case CTRL_TABDELAY: s = "tabdelay"; break;
318           default: s = "unknown"; break;
319         }
320         fprintf(stderr, "  control: %s\n", s);
321         switch (ctrl->generic.type) {
322           case CTRL_COLUMNS:
323             if (ctrl->columns.ncols != 1) {
324                 ncols = ctrl->columns.ncols;
325                 fprintf(stderr, "  split to %d\n", ncols);
326                 assert(ncols <= MAXCOLS);
327                 for (j = 0; j < ncols; j++) {
328                     cols[j] = cols[0];
329                     if (j > 0)
330                         cols[j].pos.h = cols[j-1].pos.h + cols[j-1].width + 6;
331                     if (j == ncols - 1)
332                         cols[j].width = curstate->width -
333                             (cols[j].pos.h - curstate->pos.h);
334                     else
335                         cols[j].width = (curstate->width + 6) * 
336                             ctrl->columns.percentages[j] / 100 - 6;
337                 }
338             } else {
339                 fprintf(stderr, "  join\n");
340                 for (j = 0; j < ncols; j++)
341                     if (cols[j].pos.v > cols[0].pos.v)
342                         cols[0].pos.v = cols[j].pos.v;
343                 cols[0].width = curstate->width;
344                 ncols = 1;
345             }
346             break;
347           case CTRL_TEXT:
348             macctrl_text(mcs, window, &cols[colstart], ctrl);
349             break;
350           case CTRL_EDITBOX:
351             macctrl_editbox(mcs, window, &cols[colstart], ctrl);
352             break;
353           case CTRL_RADIO:
354             macctrl_radio(mcs, window, &cols[colstart], ctrl);
355             break;
356           case CTRL_CHECKBOX:
357             macctrl_checkbox(mcs, window, &cols[colstart], ctrl);
358             break;
359           case CTRL_BUTTON:
360             macctrl_button(mcs, window, &cols[colstart], ctrl);
361             break;
362           case CTRL_LISTBOX:
363             if (ctrl->listbox.height == 0)
364                 macctrl_popup(mcs, window, &cols[colstart], ctrl);
365             else
366                 macctrl_listbox(mcs, window, &cols[colstart], ctrl);
367             break;
368         }
369     }
370     for (j = 0; j < ncols; j++)
371         if (cols[j].pos.v > curstate->pos.v)
372             curstate->pos.v = cols[j].pos.v;
373 }
374
375 static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
376 {
377     unsigned int i, j;
378     union macctrl *mc;
379
380 #define hideshow(c) do {                                                \
381     if (i == which) ShowControl(c); else HideControl(c);                \
382 } while (0)
383
384     mcs->curpanel = which;
385     /* Panel 0 is special and always visible. */
386     for (i = 1; i < mcs->npanels; i++)
387         for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
388 #if !TARGET_API_MAC_CARBON
389             if (mcs->focus == mc)
390                 macctrl_setfocus(mcs, NULL);
391 #endif
392             switch (mc->generic.type) {
393               case MACCTRL_TEXT:
394                 hideshow(mc->text.tbctrl);
395                 break;
396               case MACCTRL_EDITBOX:
397                 hideshow(mc->editbox.tbctrl);
398                 if (mc->editbox.tblabel != NULL)
399                     hideshow(mc->editbox.tblabel);
400                 break;
401               case MACCTRL_RADIO:
402                 for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
403                     hideshow(mc->radio.tbctrls[j]);
404                 if (mc->radio.tblabel != NULL)
405                     hideshow(mc->radio.tblabel);
406                 break;
407               case MACCTRL_CHECKBOX:
408                 hideshow(mc->checkbox.tbctrl);
409                 break;
410               case MACCTRL_BUTTON:
411                 hideshow(mc->button.tbctrl);
412                 break;
413               case MACCTRL_LISTBOX:
414                 hideshow(mc->listbox.tbctrl);
415                 /*
416                  * At least under Mac OS 8.1, hiding a list box
417                  * doesn't hide its scroll bars.
418                  */
419 #if TARGET_API_MAC_CARBON
420                 hideshow(GetListVerticalScrollBar(mc->listbox.list));
421 #else
422                 hideshow((*mc->listbox.list)->vScroll);
423 #endif
424                 break;
425               case MACCTRL_POPUP:
426                 hideshow(mc->popup.tbctrl);
427                 break;
428             }
429         }
430 }
431
432 #if !TARGET_API_MAC_CARBON
433 /*
434  * System 7 focus manipulation
435  */
436 static void macctrl_defocus(union macctrl *mc)
437 {
438
439     assert(mac_gestalts.apprvers < 0x100);
440     switch (mc->generic.type) {
441       case MACCTRL_EDITBOX:
442         TEDeactivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
443         break;
444     }
445 }
446
447 static void macctrl_enfocus(union macctrl *mc)
448 {
449
450     assert(mac_gestalts.apprvers < 0x100);
451     switch (mc->generic.type) {
452       case MACCTRL_EDITBOX:
453         TEActivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
454         break;
455     }
456 }
457
458 static void macctrl_setfocus(struct macctrls *mcs, union macctrl *mc)
459 {
460
461     if (mcs->focus == mc)
462         return;
463     if (mcs->focus != NULL)
464         macctrl_defocus(mcs->focus);
465     mcs->focus = mc;
466     if (mc != NULL)
467         macctrl_enfocus(mc);
468 }
469 #endif
470
471 static void macctrl_text(struct macctrls *mcs, WindowPtr window,
472                          struct mac_layoutstate *curstate,
473                          union control *ctrl)
474 {
475     union macctrl *mc = snew(union macctrl);
476     Rect bounds;
477     SInt16 height;
478
479     assert(ctrl->text.label != NULL);
480     fprintf(stderr, "    label = %s\n", ctrl->text.label);
481     mc->generic.type = MACCTRL_TEXT;
482     mc->generic.ctrl = ctrl;
483     mc->generic.privdata = NULL;
484     bounds.left = curstate->pos.h;
485     bounds.right = bounds.left + curstate->width;
486     bounds.top = curstate->pos.v;
487     bounds.bottom = bounds.top + 16;
488     if (mac_gestalts.apprvers >= 0x100) {
489         Size olen;
490
491         mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
492                                      kControlStaticTextProc, (long)mc);
493         SetControlData(mc->text.tbctrl, kControlEntireControl,
494                        kControlStaticTextTextTag,
495                        strlen(ctrl->text.label), ctrl->text.label);
496         GetControlData(mc->text.tbctrl, kControlEntireControl,
497                        kControlStaticTextTextHeightTag,
498                        sizeof(height), &height, &olen);
499     }
500 #if !TARGET_API_MAC_CARBON
501     else {
502         TEHandle te;
503
504         mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
505                                      SYS7_TEXT_PROC, (long)mc);
506         te = (TEHandle)(*mc->text.tbctrl)->contrlData;
507         TESetText(ctrl->text.label, strlen(ctrl->text.label), te);
508         height = TEGetHeight(1, (*te)->nLines, te);
509     }
510 #endif
511     fprintf(stderr, "    height = %d\n", height);
512     SizeControl(mc->text.tbctrl, curstate->width, height);
513     curstate->pos.v += height + 6;
514     add234(mcs->byctrl, mc);
515     mc->generic.next = mcs->panels[curstate->panelnum];
516     mcs->panels[curstate->panelnum] = mc;
517 }
518
519 static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
520                             struct mac_layoutstate *curstate,
521                             union control *ctrl)
522 {
523     union macctrl *mc = snew(union macctrl);
524     Rect lbounds, bounds;
525
526     if (ctrl->editbox.label != NULL)
527         fprintf(stderr, "    label = %s\n", ctrl->editbox.label);
528     fprintf(stderr, "    percentwidth = %d\n", ctrl->editbox.percentwidth);
529     if (ctrl->editbox.password) fprintf(stderr, "    password\n");
530     if (ctrl->editbox.has_list) fprintf(stderr, "    has list\n");
531     mc->generic.type = MACCTRL_EDITBOX;
532     mc->generic.ctrl = ctrl;
533     mc->generic.privdata = NULL;
534     lbounds.left = curstate->pos.h;
535     lbounds.top = curstate->pos.v;
536     if (ctrl->editbox.percentwidth == 100) {
537         if (ctrl->editbox.label != NULL) {
538             lbounds.right = lbounds.left + curstate->width;
539             lbounds.bottom = lbounds.top + 16;
540             curstate->pos.v += 18;
541         }
542         bounds.left = curstate->pos.h;
543         bounds.right = bounds.left + curstate->width;
544     } else {
545         lbounds.right = lbounds.left +
546             curstate->width * (100 - ctrl->editbox.percentwidth) / 100;
547         lbounds.bottom = lbounds.top + 22;
548         bounds.left = lbounds.right;
549         bounds.right = lbounds.left + curstate->width;
550     }
551     bounds.top = curstate->pos.v;
552     bounds.bottom = bounds.top + 22;
553     if (mac_gestalts.apprvers >= 0x100) {
554         if (ctrl->editbox.label == NULL)
555             mc->editbox.tblabel = NULL;
556         else {
557             mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
558                                              0, 0, 0, kControlStaticTextProc,
559                                              (long)mc);
560             SetControlData(mc->editbox.tblabel, kControlEntireControl,
561                            kControlStaticTextTextTag,
562                            strlen(ctrl->editbox.label), ctrl->editbox.label);
563         }
564         InsetRect(&bounds, 3, 3);
565         mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
566                                         ctrl->editbox.password ?
567                                         kControlEditTextPasswordProc :
568                                         kControlEditTextProc, (long)mc);
569     }
570 #if !TARGET_API_MAC_CARBON
571     else {
572         if (ctrl->editbox.label == NULL)
573             mc->editbox.tblabel = NULL;
574         else {
575             mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
576                                              0, 0, 0, SYS7_TEXT_PROC,
577                                              (long)mc);
578             TESetText(ctrl->editbox.label, strlen(ctrl->editbox.label),
579                       (TEHandle)(*mc->editbox.tblabel)->contrlData);
580         }
581         mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
582                                         SYS7_EDITBOX_PROC, (long)mc);
583     }
584 #endif
585     curstate->pos.v += 28;
586     add234(mcs->byctrl, mc);
587     mc->generic.next = mcs->panels[curstate->panelnum];
588     mcs->panels[curstate->panelnum] = mc;
589     ctrlevent(mcs, mc, EVENT_REFRESH);
590 }
591
592 #if !TARGET_API_MAC_CARBON
593 static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
594                                                ControlRef control,
595                                                ControlDefProcMessage msg,
596                                                SInt32 param)
597 {
598     RgnHandle rgn;
599     Rect rect;
600     TEHandle te;
601     long ssfs;
602     Point mouse;
603
604     switch (msg) {
605       case initCntl:
606         rect = (*control)->contrlRect;
607         if (variant == SYS7_EDITBOX_VARIANT)
608             InsetRect(&rect, 3, 3); /* 2 if it's 20 pixels high */
609         te = TENew(&rect, &rect);
610         ssfs = GetScriptVariable(smSystemScript, smScriptSysFondSize);
611         (*te)->txSize = LoWord(ssfs);
612         (*te)->txFont = HiWord(ssfs);
613         (*control)->contrlData = (Handle)te;
614         return noErr;
615       case dispCntl:
616         TEDispose((TEHandle)(*control)->contrlData);
617         return 0;
618       case drawCntl:
619         if ((*control)->contrlVis) {
620             rect = (*control)->contrlRect;
621             if (variant == SYS7_EDITBOX_VARIANT) {
622                 PenNormal();
623                 FrameRect(&rect);
624                 InsetRect(&rect, 3, 3);
625             }
626             (*(TEHandle)(*control)->contrlData)->viewRect = rect;
627             TEUpdate(&rect, (TEHandle)(*control)->contrlData);
628         }
629         return 0;
630       case testCntl:
631         if (variant == SYS7_TEXT_VARIANT)
632             return kControlNoPart;
633         mouse.h = LoWord(param);
634         mouse.v = HiWord(param);
635         rect = (*control)->contrlRect;
636         InsetRect(&rect, 3, 3);
637         return PtInRect(mouse, &rect) ? kControlEditTextPart : kControlNoPart;
638       case calcCRgns:
639         if (param & (1 << 31)) {
640             param &= ~(1 << 31);
641             goto calcthumbrgn;
642         }
643         /* FALLTHROUGH */
644       case calcCntlRgn:
645         rgn = (RgnHandle)param;
646         RectRgn(rgn, &(*control)->contrlRect);
647         return 0;
648       case calcThumbRgn:
649       calcthumbrgn:
650         rgn = (RgnHandle)param;
651         SetEmptyRgn(rgn);
652         return 0;
653     }
654
655     return 0;
656 }
657 #endif
658
659 static void macctrl_radio(struct macctrls *mcs, WindowPtr window,
660                           struct mac_layoutstate *curstate,
661                           union control *ctrl)
662 {
663     union macctrl *mc = snew(union macctrl);
664     Rect bounds;
665     Str255 title;
666     unsigned int i, colwidth;
667
668     if (ctrl->radio.label != NULL)
669         fprintf(stderr, "    label = %s\n", ctrl->radio.label);
670     mc->generic.type = MACCTRL_RADIO;
671     mc->generic.ctrl = ctrl;
672     mc->generic.privdata = NULL;
673     mc->radio.tbctrls = snewn(ctrl->radio.nbuttons, ControlRef);
674     colwidth = (curstate->width + 13) / ctrl->radio.ncolumns;
675     bounds.top = curstate->pos.v;
676     bounds.bottom = bounds.top + 16;
677     bounds.left = curstate->pos.h;
678     bounds.right = bounds.left + curstate->width;
679     if (ctrl->radio.label == NULL)
680         mc->radio.tblabel = NULL;
681     else {
682         if (mac_gestalts.apprvers >= 0x100) {
683             mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
684                                            0, 0, 0, kControlStaticTextProc,
685                                            (long)mc);
686             SetControlData(mc->radio.tblabel, kControlEntireControl,
687                            kControlStaticTextTextTag,
688                            strlen(ctrl->radio.label), ctrl->radio.label);
689         }
690 #if !TARGET_API_MAC_CARBON
691         else {
692             mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
693                                            0, 0, 0, SYS7_TEXT_PROC, (long)mc);
694             TESetText(ctrl->radio.label, strlen(ctrl->radio.label),
695                       (TEHandle)(*mc->radio.tblabel)->contrlData);
696         }
697 #endif
698         curstate->pos.v += 18;
699     }
700     for (i = 0; i < ctrl->radio.nbuttons; i++) {
701         fprintf(stderr, "    button = %s\n", ctrl->radio.buttons[i]);
702         bounds.top = curstate->pos.v - 2;
703         bounds.bottom = bounds.top + 18;
704         bounds.left = curstate->pos.h + colwidth * (i % ctrl->radio.ncolumns);
705         if (i == ctrl->radio.nbuttons - 1 ||
706             i % ctrl->radio.ncolumns == ctrl->radio.ncolumns - 1) {
707             bounds.right = curstate->pos.h + curstate->width;
708             curstate->pos.v += 18;
709         } else
710             bounds.right = bounds.left + colwidth - 13;
711         c2pstrcpy(title, ctrl->radio.buttons[i]);
712         mc->radio.tbctrls[i] = NewControl(window, &bounds, title, TRUE,
713                                           0, 0, 1, radioButProc, (long)mc);
714     }
715     curstate->pos.v += 4;
716     add234(mcs->byctrl, mc);
717     mc->generic.next = mcs->panels[curstate->panelnum];
718     mcs->panels[curstate->panelnum] = mc;
719     ctrlevent(mcs, mc, EVENT_REFRESH);
720 }
721
722 static void macctrl_checkbox(struct macctrls *mcs, WindowPtr window,
723                              struct mac_layoutstate *curstate,
724                              union control *ctrl)
725 {
726     union macctrl *mc = snew(union macctrl);
727     Rect bounds;
728     Str255 title;
729
730     assert(ctrl->checkbox.label != NULL);
731     fprintf(stderr, "    label = %s\n", ctrl->checkbox.label);
732     mc->generic.type = MACCTRL_CHECKBOX;
733     mc->generic.ctrl = ctrl;
734     mc->generic.privdata = NULL;
735     bounds.left = curstate->pos.h;
736     bounds.right = bounds.left + curstate->width;
737     bounds.top = curstate->pos.v;
738     bounds.bottom = bounds.top + 16;
739     c2pstrcpy(title, ctrl->checkbox.label);
740     mc->checkbox.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
741                                      checkBoxProc, (long)mc);
742     add234(mcs->byctrl, mc);
743     curstate->pos.v += 22;
744     mc->generic.next = mcs->panels[curstate->panelnum];
745     mcs->panels[curstate->panelnum] = mc;
746     ctrlevent(mcs, mc, EVENT_REFRESH);
747 }
748
749 static void macctrl_button(struct macctrls *mcs, WindowPtr window,
750                            struct mac_layoutstate *curstate,
751                            union control *ctrl)
752 {
753     union macctrl *mc = snew(union macctrl);
754     Rect bounds;
755     Str255 title;
756
757     assert(ctrl->button.label != NULL);
758     fprintf(stderr, "    label = %s\n", ctrl->button.label);
759     if (ctrl->button.isdefault)
760         fprintf(stderr, "    is default\n");
761     mc->generic.type = MACCTRL_BUTTON;
762     mc->generic.ctrl = ctrl;
763     mc->generic.privdata = NULL;
764     bounds.left = curstate->pos.h;
765     bounds.right = bounds.left + curstate->width;
766     bounds.top = curstate->pos.v;
767     bounds.bottom = bounds.top + 20;
768     c2pstrcpy(title, ctrl->button.label);
769     mc->button.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
770                                    pushButProc, (long)mc);
771     mc->button.tbring = NULL;
772     if (mac_gestalts.apprvers >= 0x100) {
773         Boolean isdefault = ctrl->button.isdefault;
774
775         SetControlData(mc->button.tbctrl, kControlEntireControl,
776                        kControlPushButtonDefaultTag,
777                        sizeof(isdefault), &isdefault);
778     } else if (ctrl->button.isdefault) {
779         InsetRect(&bounds, -4, -4);
780         mc->button.tbring = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
781                                        SYS7_DEFAULT_PROC, (long)mc);
782     }
783     if (mac_gestalts.apprvers >= 0x110) {
784         Boolean iscancel = ctrl->button.iscancel;
785
786         SetControlData(mc->button.tbctrl, kControlEntireControl,
787                        kControlPushButtonCancelTag,
788                        sizeof(iscancel), &iscancel);
789     }
790     if (ctrl->button.isdefault)
791         mcs->defbutton = mc;
792     if (ctrl->button.iscancel)
793         mcs->canbutton = mc;
794     add234(mcs->byctrl, mc);
795     mc->generic.next = mcs->panels[curstate->panelnum];
796     mcs->panels[curstate->panelnum] = mc;
797     curstate->pos.v += 26;
798 }
799
800 #if !TARGET_API_MAC_CARBON
801 static pascal SInt32 macctrl_sys7_default_cdef(SInt16 variant,
802                                                ControlRef control,
803                                                ControlDefProcMessage msg,
804                                                SInt32 param)
805 {
806     RgnHandle rgn;
807     Rect rect;
808     int oval;
809     PenState savestate;
810
811     switch (msg) {
812       case drawCntl:
813         if ((*control)->contrlVis) {
814             rect = (*control)->contrlRect;
815             GetPenState(&savestate);
816             PenNormal();
817             PenSize(3, 3);
818             if ((*control)->contrlHilite == kControlInactivePart)
819                 PenPat(&qd.gray);
820             oval = (rect.bottom - rect.top) / 2 + 2;
821             FrameRoundRect(&rect, oval, oval);
822             SetPenState(&savestate);
823         }
824         return 0;
825       case calcCRgns:
826         if (param & (1 << 31)) {
827             param &= ~(1 << 31);
828             goto calcthumbrgn;
829         }
830         /* FALLTHROUGH */
831       case calcCntlRgn:
832         rgn = (RgnHandle)param;
833         RectRgn(rgn, &(*control)->contrlRect);
834         return 0;
835       case calcThumbRgn:
836       calcthumbrgn:
837         rgn = (RgnHandle)param;
838         SetEmptyRgn(rgn);
839         return 0;
840     }
841
842     return 0;
843 }
844 #endif
845
846 static void macctrl_listbox(struct macctrls *mcs, WindowPtr window,
847                             struct mac_layoutstate *curstate,
848                             union control *ctrl)
849 {
850     union macctrl *mc = snew(union macctrl);
851     Rect bounds;
852     Size olen;
853
854     if (ctrl->listbox.label != NULL)
855         fprintf(stderr, "    label = %s\n", ctrl->listbox.label);
856     fprintf(stderr, "    height = %d\n", ctrl->listbox.height);
857     if (ctrl->listbox.draglist)
858         fprintf(stderr, "    draglist\n");
859     if (ctrl->listbox.multisel)
860         fprintf(stderr, "    multisel\n");
861     fprintf(stderr, "    ncols = %d\n", ctrl->listbox.ncols);
862     assert(ctrl->listbox.percentwidth == 100);
863     mc->generic.type = MACCTRL_LISTBOX;
864     mc->generic.ctrl = ctrl;
865     mc->generic.privdata = NULL;
866     /* The list starts off empty */
867     mc->listbox.nids = 0;
868     mc->listbox.ids = NULL;
869     bounds.left = curstate->pos.h;
870     bounds.right = bounds.left + curstate->width;
871     bounds.top = curstate->pos.v;
872     bounds.bottom = bounds.top + 20 * ctrl->listbox.height;
873
874     if (mac_gestalts.apprvers >= 0x100) {
875         InsetRect(&bounds, 3, 3);
876         mc->listbox.tbctrl = NewControl(window, &bounds, NULL, TRUE,
877                                         ldes_Default, 0, 0,
878                                         kControlListBoxProc, (long)mc);
879         if (GetControlData(mc->listbox.tbctrl, kControlEntireControl,
880                            kControlListBoxListHandleTag,
881                            sizeof(mc->listbox.list), &mc->listbox.list,
882                            &olen) != noErr) {
883             DisposeControl(mc->listbox.tbctrl);
884             sfree(mc);
885             return;
886         }
887     }
888 #if !TARGET_API_MAC_CARBON
889     else {
890         InsetRect(&bounds, -3, -3);
891         mc->listbox.tbctrl = NewControl(window, &bounds, NULL, TRUE,
892                                         0, 0, 0,
893                                         SYS7_LISTBOX_PROC, (long)mc);
894         mc->listbox.list = (ListHandle)(*mc->listbox.tbctrl)->contrlData;
895         (*mc->listbox.list)->refCon = (long)mc;
896     }
897 #endif
898     if (!ctrl->listbox.multisel) {
899 #if TARGET_API_MAC_CARBON
900         SetListSelectionFlags(mc->listbox.list, lOnlyOne);
901 #else
902         (*mc->listbox.list)->selFlags = lOnlyOne;
903 #endif
904     }
905     add234(mcs->byctrl, mc);
906     curstate->pos.v += 6 + 20 * ctrl->listbox.height;
907     mc->generic.next = mcs->panels[curstate->panelnum];
908     mcs->panels[curstate->panelnum] = mc;
909     ctrlevent(mcs, mc, EVENT_REFRESH);
910 }
911
912 #if !TARGET_API_MAC_CARBON
913 static pascal SInt32 macctrl_sys7_listbox_cdef(SInt16 variant,
914                                                ControlRef control,
915                                                ControlDefProcMessage msg,
916                                                SInt32 param)
917 {
918     RgnHandle rgn;
919     Rect rect;
920     ListHandle list;
921     long ssfs;
922     Point mouse;
923     ListBounds bounds;
924     Point csize;
925     short savefont;
926     short savesize;
927     GrafPtr curport;
928
929     switch (msg) {
930       case initCntl:
931         rect = (*control)->contrlRect;
932         InsetRect(&rect, 4, 4);
933         rect.right -= 15; /* scroll bar */
934         bounds.top = bounds.bottom = bounds.left = 0;
935         bounds.right = 1;
936         csize.h = csize.v = 0;
937         GetPort(&curport);
938         savefont = curport->txFont;
939         savesize = curport->txSize;
940         ssfs = GetScriptVariable(smSystemScript, smScriptSysFondSize);
941         TextFont(HiWord(ssfs));
942         TextSize(LoWord(ssfs));
943         list = LNew(&rect, &bounds, csize, 0, (*control)->contrlOwner,
944                     TRUE, FALSE, FALSE, TRUE);
945         SetControlReference((*list)->vScroll, (long)list);
946         (*control)->contrlData = (Handle)list;
947         TextFont(savefont);
948         TextSize(savesize);
949         return noErr;
950       case dispCntl:
951         /*
952          * If the dialogue box is being destroyed, the scroll bar
953          * might have gone already.  In our situation, this is the
954          * only time we destroy a control, so NULL out the scroll bar
955          * handle to prevent LDispose trying to free it.
956          */
957         list = (ListHandle)(*control)->contrlData;
958         (*list)->vScroll = NULL;
959         LDispose(list);
960         return 0;
961       case drawCntl:
962         if ((*control)->contrlVis) {
963             rect = (*control)->contrlRect;
964             /* XXX input focus highlighting? */
965             InsetRect(&rect, 3, 3);
966             PenNormal();
967             FrameRect(&rect);
968             list = (ListHandle)(*control)->contrlData;
969             LActivate((*control)->contrlHilite != kControlInactivePart, list);
970             GetPort(&curport);
971             LUpdate(curport->visRgn, list);
972         }
973         return 0;
974       case testCntl:
975         mouse.h = LoWord(param);
976         mouse.v = HiWord(param);
977         rect = (*control)->contrlRect;
978         InsetRect(&rect, 4, 4);
979         /*
980          * We deliberately exclude the scrollbar so that LClick() can see it.
981          */
982         rect.right -= 15;
983         return PtInRect(mouse, &rect) ? kControlListBoxPart : kControlNoPart;
984       case calcCRgns:
985         if (param & (1 << 31)) {
986             param &= ~(1 << 31);
987             goto calcthumbrgn;
988         }
989         /* FALLTHROUGH */
990       case calcCntlRgn:
991         rgn = (RgnHandle)param;
992         RectRgn(rgn, &(*control)->contrlRect);
993         return 0;
994       case calcThumbRgn:
995       calcthumbrgn:
996         rgn = (RgnHandle)param;
997         SetEmptyRgn(rgn);
998         return 0;
999     }
1000
1001     return 0;
1002 }
1003 #endif
1004
1005 static void macctrl_popup(struct macctrls *mcs, WindowPtr window,
1006                           struct mac_layoutstate *curstate,
1007                           union control *ctrl)
1008 {
1009     union macctrl *mc = snew(union macctrl);
1010     Rect bounds;
1011     Str255 title;
1012     unsigned int labelwidth;
1013     static int nextmenuid = MENU_MIN;
1014     int menuid;
1015     MenuRef menu;
1016
1017     /* 
1018      * <http://developer.apple.com/qa/tb/tb42.html> explains how to
1019      * create a popup menu with dynamic content.
1020      */
1021     assert(ctrl->listbox.height == 0);
1022     assert(!ctrl->listbox.draglist);
1023     assert(!ctrl->listbox.multisel);
1024
1025     if (ctrl->listbox.label != NULL)
1026         fprintf(stderr, "    label = %s\n", ctrl->listbox.label);
1027     fprintf(stderr, "    percentwidth = %d\n", ctrl->listbox.percentwidth);
1028
1029     mc->generic.type = MACCTRL_POPUP;
1030     mc->generic.ctrl = ctrl;
1031     mc->generic.privdata = NULL;
1032     c2pstrcpy(title, ctrl->button.label == NULL ? "" : ctrl->button.label);
1033
1034     /* Find a spare menu ID and create the menu */
1035     while (GetMenuHandle(nextmenuid) != NULL)
1036         if (++nextmenuid >= MENU_MAX) nextmenuid = MENU_MIN;
1037     menuid = nextmenuid++;
1038     menu = NewMenu(menuid, "\pdummy");
1039     if (menu == NULL) return;
1040     mc->popup.menu = menu;
1041     mc->popup.menuid = menuid;
1042     InsertMenu(menu, kInsertHierarchicalMenu);
1043
1044     /* The menu starts off empty */
1045     mc->popup.nids = 0;
1046     mc->popup.ids = NULL;
1047
1048     bounds.left = curstate->pos.h;
1049     bounds.right = bounds.left + curstate->width;
1050     bounds.top = curstate->pos.v;
1051     bounds.bottom = bounds.top + 20;
1052     /* XXX handle percentwidth == 100 */
1053     labelwidth = curstate->width * (100 - ctrl->listbox.percentwidth) / 100;
1054     mc->popup.tbctrl = NewControl(window, &bounds, title, TRUE,
1055                                   popupTitleLeftJust, menuid, labelwidth,
1056                                   popupMenuProc + popupFixedWidth, (long)mc);
1057     add234(mcs->byctrl, mc);
1058     curstate->pos.v += 26;
1059     mc->generic.next = mcs->panels[curstate->panelnum];
1060     mcs->panels[curstate->panelnum] = mc;
1061     ctrlevent(mcs, mc, EVENT_REFRESH);
1062 }
1063
1064
1065 void macctrl_activate(WindowPtr window, EventRecord *event)
1066 {
1067     struct macctrls *mcs = mac_winctrls(window);
1068     Boolean active = (event->modifiers & activeFlag) != 0;
1069     GrafPtr saveport;
1070     int i, j;
1071     ControlPartCode state;
1072     union macctrl *mc;
1073
1074     GetPort(&saveport);
1075     SetPort((GrafPtr)GetWindowPort(window));
1076     if (mac_gestalts.apprvers >= 0x100)
1077         SetThemeWindowBackground(window, active ?
1078                                  kThemeBrushModelessDialogBackgroundActive :
1079                                  kThemeBrushModelessDialogBackgroundInactive,
1080                                  TRUE);
1081     state = active ? kControlNoPart : kControlInactivePart;
1082     for (i = 0; i <= mcs->curpanel; i += mcs->curpanel)
1083         for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
1084             switch (mc->generic.type) {
1085               case MACCTRL_TEXT:
1086                 HiliteControl(mc->text.tbctrl, state);
1087                 break;
1088               case MACCTRL_EDITBOX:
1089                 HiliteControl(mc->editbox.tbctrl, state);
1090                 if (mc->editbox.tblabel != NULL)
1091                     HiliteControl(mc->editbox.tblabel, state);
1092                 break;
1093               case MACCTRL_RADIO:
1094                 for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
1095                     HiliteControl(mc->radio.tbctrls[j], state);
1096                 if (mc->radio.tblabel != NULL)
1097                     HiliteControl(mc->radio.tblabel, state);
1098                 break;
1099               case MACCTRL_CHECKBOX:
1100                 HiliteControl(mc->checkbox.tbctrl, state);
1101                 break;
1102               case MACCTRL_BUTTON:
1103                 HiliteControl(mc->button.tbctrl, state);
1104                 if (mc->button.tbring != NULL)
1105                     HiliteControl(mc->button.tbring, state);                
1106                 break;
1107               case MACCTRL_LISTBOX:
1108                 HiliteControl(mc->listbox.tbctrl, state);
1109                 break;
1110               case MACCTRL_POPUP:
1111                 HiliteControl(mc->popup.tbctrl, state);
1112                 break;
1113             }
1114 #if !TARGET_API_MAC_CARBON
1115             if (mcs->focus == mc) {
1116                 if (active)
1117                     macctrl_enfocus(mc);
1118                 else
1119                     macctrl_defocus(mc);
1120             }
1121 #endif
1122         }
1123     SetPort(saveport);
1124 }
1125
1126 void macctrl_click(WindowPtr window, EventRecord *event)
1127 {
1128     Point mouse;
1129     ControlHandle control, oldfocus;
1130     int part, trackresult;
1131     GrafPtr saveport;
1132     union macctrl *mc;
1133     struct macctrls *mcs = mac_winctrls(window);
1134     int i;
1135     UInt32 features;
1136
1137     GetPort(&saveport);
1138     SetPort((GrafPtr)GetWindowPort(window));
1139     mouse = event->where;
1140     GlobalToLocal(&mouse);
1141     part = FindControl(mouse, window, &control);
1142     if (control != NULL) {
1143 #if !TARGET_API_MAC_CARBON
1144         /*
1145          * Special magic for scroll bars in list boxes, whose refcon
1146          * is the list.
1147          */
1148         if (part == kControlUpButtonPart || part == kControlDownButtonPart ||
1149             part == kControlPageUpPart || part == kControlPageDownPart ||
1150             part == kControlIndicatorPart)
1151             mc = (union macctrl *)
1152                 (*(ListHandle)GetControlReference(control))->refCon;
1153        else
1154 #endif
1155             mc = (union macctrl *)GetControlReference(control);
1156         fprintf(stderr, "control = %p, part = %d,  mc = %p\n",
1157                 control, part, mc);
1158         if (mac_gestalts.apprvers >= 0x100) {
1159             if (GetControlFeatures(control, &features) == noErr &&
1160                 (features & kControlSupportsFocus) &&
1161                 (features & kControlGetsFocusOnClick) &&
1162                 GetKeyboardFocus(window, &oldfocus) == noErr &&
1163                 control != oldfocus)
1164                 SetKeyboardFocus(window, control, part);
1165             trackresult = HandleControlClick(control, mouse, event->modifiers,
1166                                              (ControlActionUPP)-1);
1167         } else {
1168 #if !TARGET_API_MAC_CARBON
1169             if (mc->generic.type == MACCTRL_EDITBOX &&
1170                 control == mc->editbox.tbctrl) {
1171                 TEHandle te = (TEHandle)(*control)->contrlData;
1172
1173                 macctrl_setfocus(mcs, mc);
1174                 TEClick(mouse, !!(event->modifiers & shiftKey), te);
1175                 goto done;
1176             }
1177             if (mc->generic.type == MACCTRL_LISTBOX &&
1178                 (control == mc->listbox.tbctrl ||
1179                  control == (*mc->listbox.list)->vScroll)) {
1180
1181                 fprintf(stderr, "list = %p\n", mc->listbox.list);
1182                 macctrl_setfocus(mcs, mc);
1183                 if (LClick(mouse, event->modifiers, mc->listbox.list))
1184                     /* double-click */
1185                     ctrlevent(mcs, mc, EVENT_ACTION);
1186                 else
1187                     ctrlevent(mcs, mc, EVENT_SELCHANGE);
1188                 goto done;
1189             }
1190 #endif
1191             trackresult = TrackControl(control, mouse, (ControlActionUPP)-1);
1192         }
1193         switch (mc->generic.type) {
1194           case MACCTRL_RADIO:
1195             if (trackresult != 0) {
1196                 for (i = 0; i < mc->generic.ctrl->radio.nbuttons; i++)
1197                     if (mc->radio.tbctrls[i] == control)
1198                         SetControlValue(mc->radio.tbctrls[i],
1199                                         kControlRadioButtonCheckedValue);
1200                     else
1201                         SetControlValue(mc->radio.tbctrls[i],
1202                                         kControlRadioButtonUncheckedValue);
1203                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
1204             }
1205             break;
1206           case MACCTRL_CHECKBOX:
1207             if (trackresult != 0) {
1208                 SetControlValue(control, !GetControlValue(control));
1209                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
1210             }
1211             break;
1212           case MACCTRL_BUTTON:
1213             if (trackresult != 0)
1214                 ctrlevent(mcs, mc, EVENT_ACTION);
1215             break;
1216           case MACCTRL_LISTBOX:
1217             /* FIXME spot double-click */
1218             ctrlevent(mcs, mc, EVENT_SELCHANGE);
1219             break;
1220           case MACCTRL_POPUP:
1221             ctrlevent(mcs, mc, EVENT_SELCHANGE);
1222             break;
1223         }
1224     }
1225   done:
1226     SetPort(saveport);
1227 }
1228
1229 void macctrl_key(WindowPtr window, EventRecord *event)
1230 {
1231     ControlRef control;
1232     struct macctrls *mcs = mac_winctrls(window);
1233     union macctrl *mc;
1234     unsigned long dummy;
1235
1236     switch (event->message & charCodeMask) {
1237       case kEnterCharCode:
1238       case kReturnCharCode:
1239         if (mcs->defbutton != NULL) {
1240             assert(mcs->defbutton->generic.type == MACCTRL_BUTTON);
1241             HiliteControl(mcs->defbutton->button.tbctrl, kControlButtonPart);
1242             /*
1243              * I'd like to delay unhilighting the button until after
1244              * the event has been processed, but by them the entire
1245              * dialgue box might have been destroyed.
1246              */
1247             Delay(6, &dummy);
1248             HiliteControl(mcs->defbutton->button.tbctrl, kControlNoPart);
1249             ctrlevent(mcs, mcs->defbutton, EVENT_ACTION);
1250         }
1251         return;
1252       case kEscapeCharCode:
1253         if (mcs->canbutton != NULL) {
1254             assert(mcs->canbutton->generic.type == MACCTRL_BUTTON);
1255             HiliteControl(mcs->canbutton->button.tbctrl, kControlButtonPart);
1256             Delay(6, &dummy);
1257             HiliteControl(mcs->defbutton->button.tbctrl, kControlNoPart);
1258             ctrlevent(mcs, mcs->canbutton, EVENT_ACTION);
1259         }
1260         return;
1261     }
1262     if (mac_gestalts.apprvers >= 0x100) {
1263         if (GetKeyboardFocus(window, &control) == noErr && control != NULL) {
1264             HandleControlKey(control, (event->message & keyCodeMask) >> 8,
1265                              event->message & charCodeMask, event->modifiers);
1266             mc = (union macctrl *)GetControlReference(control);
1267             switch (mc->generic.type) {
1268               case MACCTRL_LISTBOX:
1269                 ctrlevent(mcs, mc, EVENT_SELCHANGE);
1270                 break;
1271               default:
1272                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
1273                 break;
1274             }
1275         }
1276     }
1277 #if !TARGET_API_MAC_CARBON
1278     else {
1279         TEHandle te;
1280
1281         if (mcs->focus != NULL) {
1282             mc = mcs->focus;
1283             switch (mc->generic.type) {
1284               case MACCTRL_EDITBOX:
1285                 te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
1286                 TEKey(event->message & charCodeMask, te);
1287                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
1288                 break;
1289             }
1290         }
1291     }
1292 #endif
1293 }
1294
1295 void macctrl_update(WindowPtr window)
1296 {
1297 #if TARGET_API_MAC_CARBON
1298     RgnHandle visrgn;
1299 #endif
1300     Rect rect;
1301     GrafPtr saveport;
1302
1303     BeginUpdate(window);
1304     GetPort(&saveport);
1305     SetPort((GrafPtr)GetWindowPort(window));
1306     if (mac_gestalts.apprvers >= 0x101) {
1307 #if TARGET_API_MAC_CARBON
1308         GetPortBounds(GetWindowPort(window), &rect);
1309 #else
1310         rect = window->portRect;
1311 #endif
1312         InsetRect(&rect, -1, -1);
1313         DrawThemeModelessDialogFrame(&rect, mac_frontwindow() == window ?
1314                                      kThemeStateActive : kThemeStateInactive);
1315     }
1316 #if TARGET_API_MAC_CARBON
1317     visrgn = NewRgn();
1318     GetPortVisibleRegion(GetWindowPort(window), visrgn);
1319     UpdateControls(window, visrgn);
1320     DisposeRgn(visrgn);
1321 #else
1322     UpdateControls(window, window->visRgn);
1323 #endif
1324     SetPort(saveport);
1325     EndUpdate(window);
1326 }
1327
1328 #if TARGET_API_MAC_CARBON
1329 #define EnableItem EnableMenuItem
1330 #define DisableItem DisableMenuItem
1331 #endif
1332 void macctrl_adjustmenus(WindowPtr window)
1333 {
1334     MenuHandle menu;
1335
1336     menu = GetMenuHandle(mFile);
1337     DisableItem(menu, iSave); /* XXX enable if modified */
1338     EnableItem(menu, iSaveAs);
1339     EnableItem(menu, iDuplicate);
1340
1341     menu = GetMenuHandle(mEdit);
1342     DisableItem(menu, 0);
1343 }
1344
1345 void macctrl_close(WindowPtr window)
1346 {
1347     struct macctrls *mcs = mac_winctrls(window);
1348     union macctrl *mc;
1349
1350     /*
1351      * Mostly, we don't bother disposing of the Toolbox controls,
1352      * since that will happen automatically when the window is
1353      * disposed of.  Popup menus are an exception, because we have to
1354      * dispose of the menu ourselves, and doing that while the control
1355      * still holds a reference to it seems rude.
1356      */
1357     while ((mc = index234(mcs->byctrl, 0)) != NULL) {
1358         if (mc->generic.privdata != NULL && mc->generic.freeprivdata)
1359             sfree(mc->generic.privdata);
1360         switch (mc->generic.type) {
1361           case MACCTRL_POPUP:
1362             DisposeControl(mc->popup.tbctrl);
1363             DeleteMenu(mc->popup.menuid);
1364             DisposeMenu(mc->popup.menu);
1365             break;
1366         }
1367         del234(mcs->byctrl, mc);
1368         sfree(mc);
1369     }
1370
1371     freetree234(mcs->byctrl);
1372     mcs->byctrl = NULL;
1373     sfree(mcs->panels);
1374     mcs->panels = NULL;
1375 }
1376
1377 void dlg_update_start(union control *ctrl, void *dlg)
1378 {
1379
1380     /* No-op for now */
1381 }
1382
1383 void dlg_update_done(union control *ctrl, void *dlg)
1384 {
1385
1386     /* No-op for now */
1387 }
1388
1389 void dlg_set_focus(union control *ctrl, void *dlg)
1390 {
1391
1392     if (mac_gestalts.apprvers >= 0x100) {
1393         /* Use SetKeyboardFocus() */
1394     } else {
1395         /* Do our own mucking around */
1396     }
1397 }
1398
1399 union control *dlg_last_focused(union control *ctrl, void *dlg)
1400 {
1401
1402     return NULL;
1403 }
1404
1405 void dlg_beep(void *dlg)
1406 {
1407
1408     SysBeep(30);
1409 }
1410
1411 void dlg_error_msg(void *dlg, char *msg)
1412 {
1413     Str255 pmsg;
1414
1415     c2pstrcpy(pmsg, msg);
1416     ParamText(pmsg, NULL, NULL, NULL);
1417     StopAlert(128, NULL);
1418 }
1419
1420 void dlg_end(void *dlg, int value)
1421 {
1422     struct macctrls *mcs = dlg;
1423
1424     if (mcs->end != NULL)
1425         (*mcs->end)(mcs->window, value);
1426 };
1427
1428 void dlg_refresh(union control *ctrl, void *dlg)
1429 {
1430     struct macctrls *mcs = dlg;
1431     union macctrl *mc;
1432
1433     if (ctrl == NULL)
1434         return; /* FIXME */
1435     mc = findbyctrl(mcs, ctrl);
1436     assert(mc != NULL);
1437     ctrlevent(mcs, mc, EVENT_REFRESH);
1438 };
1439
1440 void *dlg_get_privdata(union control *ctrl, void *dlg)
1441 {
1442     struct macctrls *mcs = dlg;
1443     union macctrl *mc = findbyctrl(mcs, ctrl);
1444
1445     assert(mc != NULL);
1446     return mc->generic.privdata;
1447 }
1448
1449 void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
1450 {
1451     struct macctrls *mcs = dlg;
1452     union macctrl *mc = findbyctrl(mcs, ctrl);
1453
1454     assert(mc != NULL);
1455     mc->generic.privdata = ptr;
1456     mc->generic.freeprivdata = FALSE;
1457 }
1458
1459 void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
1460 {
1461     struct macctrls *mcs = dlg;
1462     union macctrl *mc = findbyctrl(mcs, ctrl);
1463
1464     assert(mc != NULL);
1465     mc->generic.privdata = smalloc(size);
1466     mc->generic.freeprivdata = TRUE;
1467     return mc->generic.privdata;
1468 }
1469
1470
1471 /*
1472  * Radio Button control
1473  */
1474
1475 void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton)
1476 {
1477     struct macctrls *mcs = dlg;
1478     union macctrl *mc = findbyctrl(mcs, ctrl);
1479     int i;
1480
1481     if (mc == NULL) return;
1482     for (i = 0; i < ctrl->radio.nbuttons; i++) {
1483         if (i == whichbutton)
1484             SetControlValue(mc->radio.tbctrls[i],
1485                             kControlRadioButtonCheckedValue);
1486         else
1487             SetControlValue(mc->radio.tbctrls[i],
1488                             kControlRadioButtonUncheckedValue);
1489     }
1490
1491 };
1492
1493 int dlg_radiobutton_get(union control *ctrl, void *dlg)
1494 {
1495     struct macctrls *mcs = dlg;
1496     union macctrl *mc = findbyctrl(mcs, ctrl);
1497     int i;
1498
1499     assert(mc != NULL);
1500     for (i = 0; i < ctrl->radio.nbuttons; i++) {
1501         if (GetControlValue(mc->radio.tbctrls[i])  ==
1502             kControlRadioButtonCheckedValue)
1503             return i;
1504     }
1505     return -1;
1506 };
1507
1508
1509 /*
1510  * Check Box control
1511  */
1512
1513 void dlg_checkbox_set(union control *ctrl, void *dlg, int checked)
1514 {
1515     struct macctrls *mcs = dlg;
1516     union macctrl *mc = findbyctrl(mcs, ctrl);
1517
1518     if (mc == NULL) return;
1519     SetControlValue(mc->checkbox.tbctrl,
1520                     checked ? kControlCheckBoxCheckedValue :
1521                               kControlCheckBoxUncheckedValue);
1522 }
1523
1524 int dlg_checkbox_get(union control *ctrl, void *dlg)
1525 {
1526     struct macctrls *mcs = dlg;
1527     union macctrl *mc = findbyctrl(mcs, ctrl);
1528
1529     assert(mc != NULL);
1530     return GetControlValue(mc->checkbox.tbctrl);
1531 }
1532
1533
1534 /*
1535  * Edit Box control
1536  */
1537
1538 void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
1539 {
1540     struct macctrls *mcs = dlg;
1541     union macctrl *mc = findbyctrl(mcs, ctrl);
1542     GrafPtr saveport;
1543
1544     if (mc == NULL) return;
1545     assert(mc->generic.type == MACCTRL_EDITBOX);
1546     GetPort(&saveport);
1547     SetPort((GrafPtr)(GetWindowPort(mcs->window)));
1548     if (mac_gestalts.apprvers >= 0x100)
1549         SetControlData(mc->editbox.tbctrl, kControlEntireControl,
1550                        ctrl->editbox.password ?
1551                        kControlEditTextPasswordTag :
1552                        kControlEditTextTextTag,
1553                        strlen(text), text);
1554 #if !TARGET_API_MAC_CARBON
1555     else
1556         TESetText(text, strlen(text),
1557                   (TEHandle)(*mc->editbox.tbctrl)->contrlData);
1558 #endif
1559     DrawOneControl(mc->editbox.tbctrl);
1560     SetPort(saveport);
1561 }
1562
1563 void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
1564 {
1565     struct macctrls *mcs = dlg;
1566     union macctrl *mc = findbyctrl(mcs, ctrl);
1567     Size olen;
1568
1569     assert(mc != NULL);
1570     assert(mc->generic.type == MACCTRL_EDITBOX);
1571     if (mac_gestalts.apprvers >= 0x100) {
1572         if (GetControlData(mc->editbox.tbctrl, kControlEntireControl,
1573                            ctrl->editbox.password ?
1574                            kControlEditTextPasswordTag :
1575                            kControlEditTextTextTag,
1576                            length - 1, buffer, &olen) != noErr)
1577             olen = 0;
1578         if (olen > length - 1)
1579             olen = length - 1;
1580     }
1581 #if !TARGET_API_MAC_CARBON
1582     else {
1583         TEHandle te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
1584
1585         olen = (*te)->teLength;
1586         if (olen > length - 1)
1587             olen = length - 1;
1588         memcpy(buffer, *(*te)->hText, olen);
1589     }
1590 #endif
1591     buffer[olen] = '\0';
1592     fprintf(stderr, "dlg_editbox_get: %s\n", buffer);
1593 }
1594
1595
1596 /*
1597  * List Box control
1598  */
1599
1600 static void dlg_macpopup_clear(union control *ctrl, void *dlg)
1601 {
1602     struct macctrls *mcs = dlg;
1603     union macctrl *mc = findbyctrl(mcs, ctrl);
1604     MenuRef menu = mc->popup.menu;
1605     unsigned int i, n;
1606
1607     if (mc == NULL) return;
1608     fprintf(stderr, "      popup_clear\n");
1609     n = CountMenuItems(menu);
1610     for (i = 0; i < n; i++)
1611         DeleteMenuItem(menu, n - i);
1612     mc->popup.nids = 0;
1613     sfree(mc->popup.ids);
1614     mc->popup.ids = NULL;
1615     SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1616 }
1617
1618 static void dlg_maclist_clear(union control *ctrl, void *dlg)
1619 {
1620     struct macctrls *mcs = dlg;
1621     union macctrl *mc = findbyctrl(mcs, ctrl);
1622
1623     if (mc == NULL) return;
1624     fprintf(stderr, "      maclist_clear\n");
1625     LDelRow(0, 0, mc->listbox.list);
1626     mc->listbox.nids = 0;
1627     sfree(mc->listbox.ids);
1628     mc->listbox.ids = NULL;
1629     DrawOneControl(mc->listbox.tbctrl);
1630 }
1631
1632 void dlg_listbox_clear(union control *ctrl, void *dlg)
1633 {
1634
1635     switch (ctrl->generic.type) {
1636       case CTRL_LISTBOX:
1637         if (ctrl->listbox.height == 0)
1638             dlg_macpopup_clear(ctrl, dlg);
1639         else
1640             dlg_maclist_clear(ctrl, dlg);
1641         break;
1642     }
1643 }
1644
1645 static void dlg_macpopup_del(union control *ctrl, void *dlg, int index)
1646 {
1647     struct macctrls *mcs = dlg;
1648     union macctrl *mc = findbyctrl(mcs, ctrl);
1649     MenuRef menu = mc->popup.menu;
1650
1651     if (mc == NULL) return;
1652     fprintf(stderr, "      popup_del %d\n", index);
1653     DeleteMenuItem(menu, index + 1);
1654     if (mc->popup.ids != NULL)
1655         memcpy(mc->popup.ids + index, mc->popup.ids + index + 1,
1656                (mc->popup.nids - index - 1) * sizeof(*mc->popup.ids));
1657     SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1658 }
1659
1660 static void dlg_maclist_del(union control *ctrl, void *dlg, int index)
1661 {
1662     struct macctrls *mcs = dlg;
1663     union macctrl *mc = findbyctrl(mcs, ctrl);
1664
1665     if (mc == NULL) return;
1666     fprintf(stderr, "      maclist_del %d\n", index);
1667     LDelRow(1, index, mc->listbox.list);
1668     if (mc->listbox.ids != NULL)
1669         memcpy(mc->listbox.ids + index, mc->listbox.ids + index + 1,
1670                (mc->listbox.nids - index - 1) * sizeof(*mc->listbox.ids));
1671     DrawOneControl(mc->listbox.tbctrl);
1672 }
1673
1674 void dlg_listbox_del(union control *ctrl, void *dlg, int index)
1675 {
1676
1677     switch (ctrl->generic.type) {
1678       case CTRL_LISTBOX:
1679         if (ctrl->listbox.height == 0)
1680             dlg_macpopup_del(ctrl, dlg, index);
1681         else
1682             dlg_maclist_del(ctrl, dlg, index);
1683         break;
1684     }
1685 }
1686
1687 static void dlg_macpopup_add(union control *ctrl, void *dlg, char const *text)
1688 {
1689     struct macctrls *mcs = dlg;
1690     union macctrl *mc = findbyctrl(mcs, ctrl);
1691     MenuRef menu = mc->popup.menu;
1692     Str255 itemstring;
1693
1694     if (mc == NULL) return;
1695     fprintf(stderr, "      popup_add %s\n", text);
1696     assert(text[0] != '\0');
1697     c2pstrcpy(itemstring, text);
1698     AppendMenu(menu, "\pdummy");
1699     SetMenuItemText(menu, CountMenuItems(menu), itemstring);
1700     SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1701 }
1702
1703
1704 static void dlg_maclist_add(union control *ctrl, void *dlg, char const *text)
1705 {
1706     struct macctrls *mcs = dlg;
1707     union macctrl *mc = findbyctrl(mcs, ctrl);
1708     ListBounds bounds;
1709     Cell cell = { 0, 0 };
1710
1711     if (mc == NULL) return;
1712     fprintf(stderr, "      maclist_add %s\n", text);
1713 #if TARGET_API_MAC_CARBON
1714     GetListDataBounds(mc->listbox.list, &bounds);
1715 #else
1716     bounds = (*mc->listbox.list)->dataBounds;
1717 #endif
1718     cell.v = bounds.bottom;
1719     LAddRow(1, cell.v, mc->listbox.list);
1720     LSetCell(text, strlen(text), cell, mc->listbox.list);
1721     DrawOneControl(mc->listbox.tbctrl);
1722 }
1723
1724 void dlg_listbox_add(union control *ctrl, void *dlg, char const *text)
1725 {
1726
1727     switch (ctrl->generic.type) {
1728       case CTRL_LISTBOX:
1729         if (ctrl->listbox.height == 0)
1730             dlg_macpopup_add(ctrl, dlg, text);
1731         else
1732             dlg_maclist_add(ctrl, dlg, text);
1733         break;
1734     }
1735 }
1736
1737 static void dlg_macpopup_addwithid(union control *ctrl, void *dlg,
1738                                    char const *text, int id)
1739 {
1740     struct macctrls *mcs = dlg;
1741     union macctrl *mc = findbyctrl(mcs, ctrl);
1742     MenuRef menu = mc->popup.menu;
1743     unsigned int index;
1744
1745     if (mc == NULL) return;
1746     fprintf(stderr, "      popup_addwthid %s, %d\n", text, id);
1747     dlg_macpopup_add(ctrl, dlg, text);
1748     index = CountMenuItems(menu) - 1;
1749     if (mc->popup.nids <= index) {
1750         mc->popup.nids = index + 1;
1751         mc->popup.ids = sresize(mc->popup.ids, mc->popup.nids, int);
1752     }
1753     mc->popup.ids[index] = id;
1754 }
1755
1756 static void dlg_maclist_addwithid(union control *ctrl, void *dlg,
1757                                   char const *text, int id)
1758 {
1759     struct macctrls *mcs = dlg;
1760     union macctrl *mc = findbyctrl(mcs, ctrl);
1761     ListBounds bounds;
1762     int index;
1763
1764     if (mc == NULL) return;
1765     fprintf(stderr, "      maclist_addwithid %s %d\n", text, id);
1766     dlg_maclist_add(ctrl, dlg, text);
1767 #if TARGET_API_MAC_CARBON
1768     GetListDataBounds(mc->listbox.list, &bounds);
1769 #else
1770     bounds = (*mc->listbox.list)->dataBounds;
1771 #endif
1772     index = bounds.bottom;
1773     if (mc->listbox.nids <= index) {
1774         mc->listbox.nids = index + 1;
1775         mc->listbox.ids = sresize(mc->listbox.ids, mc->listbox.nids, int);
1776     }
1777     mc->listbox.ids[index] = id;
1778 }
1779
1780 void dlg_listbox_addwithid(union control *ctrl, void *dlg,
1781                            char const *text, int id)
1782 {
1783
1784     switch (ctrl->generic.type) {
1785       case CTRL_LISTBOX:
1786         if (ctrl->listbox.height == 0)
1787             dlg_macpopup_addwithid(ctrl, dlg, text, id);
1788         else
1789             dlg_maclist_addwithid(ctrl, dlg, text, id);
1790         break;
1791     }
1792 }
1793
1794 int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
1795 {
1796     struct macctrls *mcs = dlg;
1797     union macctrl *mc = findbyctrl(mcs, ctrl);
1798
1799     assert(mc != NULL);
1800     switch (ctrl->generic.type) {
1801       case CTRL_LISTBOX:
1802         if (ctrl->listbox.height == 0) {
1803             assert(mc->popup.ids != NULL && mc->popup.nids > index);
1804             return mc->popup.ids[index];
1805         } else {
1806             assert(mc->listbox.ids != NULL && mc->listbox.nids > index);
1807             return mc->listbox.ids[index];
1808         }
1809     }
1810     return -1;
1811 }
1812
1813 int dlg_listbox_index(union control *ctrl, void *dlg)
1814 {
1815     struct macctrls *mcs = dlg;
1816     union macctrl *mc = findbyctrl(mcs, ctrl);
1817     Cell cell = { 0, 0 };
1818
1819     assert(mc != NULL);
1820     switch (ctrl->generic.type) {
1821       case CTRL_LISTBOX:
1822         if (ctrl->listbox.height == 0)
1823             return GetControlValue(mc->popup.tbctrl) - 1;
1824         else {
1825             if (LGetSelect(TRUE, &cell, mc->listbox.list))
1826                 return cell.v;
1827             else
1828                 return -1;
1829         }
1830     }
1831     return -1;
1832 }
1833
1834 int dlg_listbox_issel(union control *ctrl, void *dlg, int index)
1835 {
1836     struct macctrls *mcs = dlg;
1837     union macctrl *mc = findbyctrl(mcs, ctrl);
1838     Cell cell = { 0, 0 };
1839
1840     assert(mc != NULL);
1841     switch (ctrl->generic.type) {
1842       case CTRL_LISTBOX:
1843         if (ctrl->listbox.height == 0)
1844             return GetControlValue(mc->popup.tbctrl) - 1 == index;
1845         else {
1846             cell.v = index;
1847             return LGetSelect(FALSE, &cell, mc->listbox.list);
1848         }
1849     }
1850     return FALSE;
1851 }
1852
1853 void dlg_listbox_select(union control *ctrl, void *dlg, int index)
1854 {
1855     struct macctrls *mcs = dlg;
1856     union macctrl *mc = findbyctrl(mcs, ctrl);
1857
1858     if (mc == NULL) return;
1859     switch (ctrl->generic.type) {
1860       case CTRL_LISTBOX:
1861         if (ctrl->listbox.height == 0)
1862             SetControlValue(mc->popup.tbctrl, index + 1);
1863         break;
1864     }
1865 }
1866
1867
1868 /*
1869  * Text control
1870  */
1871
1872 void dlg_text_set(union control *ctrl, void *dlg, char const *text)
1873 {
1874     struct macctrls *mcs = dlg;
1875     union macctrl *mc = findbyctrl(mcs, ctrl);
1876
1877     if (mc == NULL) return;
1878     if (mac_gestalts.apprvers >= 0x100)
1879         SetControlData(mc->text.tbctrl, kControlEntireControl,
1880                        kControlStaticTextTextTag, strlen(text), text);
1881 #if !TARGET_API_MAC_CARBON
1882     else
1883         TESetText(text, strlen(text),
1884                   (TEHandle)(*mc->text.tbctrl)->contrlData);
1885 #endif
1886 }
1887
1888
1889 /*
1890  * File Selector control
1891  */
1892
1893 void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn)
1894 {
1895
1896 }
1897
1898 void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
1899 {
1900
1901 }
1902
1903
1904 /*
1905  * Font Selector control
1906  */
1907
1908 void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn)
1909 {
1910
1911 }
1912
1913 void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn)
1914 {
1915
1916 }
1917
1918
1919 /*
1920  * Printer enumeration
1921  */
1922
1923 printer_enum *printer_start_enum(int *nprinters)
1924 {
1925
1926     *nprinters = 0;
1927     return NULL;
1928 }
1929
1930 char *printer_get_name(printer_enum *pe, int thing)
1931 {
1932
1933     return "<none>";
1934 }
1935
1936 void printer_finish_enum(printer_enum *pe)
1937 {
1938
1939 }
1940
1941
1942 /*
1943  * Colour selection stuff
1944  */
1945
1946 void dlg_coloursel_start(union control *ctrl, void *dlg,
1947                          int r, int g, int b)
1948 {
1949
1950 }
1951
1952 int dlg_coloursel_results(union control *ctrl, void *dlg,
1953                           int *r, int *g, int *b)
1954 {
1955
1956     return 0;
1957 }
1958
1959 /*
1960  * Local Variables:
1961  * c-file-style: "simon"
1962  * End:
1963  */