]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mac/macctrls.c
354f9dec121a23986e5775bec94c458aa1b86f04
[PuTTY.git] / mac / macctrls.c
1 /* $Id: macctrls.c,v 1.1 2003/03/17 21:40:37 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 <Sound.h>
33 #include <TextUtils.h>
34 #include <Windows.h>
35
36 #include "putty.h"
37 #include "mac.h"
38 #include "macresid.h"
39 #include "dialog.h"
40 #include "tree234.h"
41
42 union macctrl {
43     struct macctrl_generic {
44         enum {
45             MACCTRL_TEXT,
46             MACCTRL_RADIO,
47             MACCTRL_CHECKBOX,
48             MACCTRL_BUTTON
49         } type;
50         /* Template from which this was generated */
51         union control *ctrl;
52     } generic;
53     struct {
54         struct macctrl_generic generic;
55         ControlRef tbctrl;
56     } text;
57     struct {
58         struct macctrl_generic generic;
59         ControlRef *tbctrls;
60     } radio;
61     struct {
62         struct macctrl_generic generic;
63         ControlRef tbctrl;
64     } checkbox;
65     struct {
66         struct macctrl_generic generic;
67         ControlRef tbctrl;
68     } button;
69 };
70
71 struct mac_layoutstate {
72     Point pos;
73     unsigned int width;
74 };
75
76 #define ctrlevent(mcs, mc, event) do {                                  \
77     if ((mc)->generic.ctrl->generic.handler != NULL)                    \
78         (*(mc)->generic.ctrl->generic.handler)((mc)->generic.ctrl, (mc),\
79                                                (mcs)->data, (event));   \
80 } while (0)
81
82 static void macctrl_layoutset(struct mac_layoutstate *, struct controlset *, 
83                               WindowPtr, struct macctrls *);
84 static void macctrl_text(struct macctrls *, WindowPtr,
85                          struct mac_layoutstate *, union control *);
86 static void macctrl_radio(struct macctrls *, WindowPtr,
87                           struct mac_layoutstate *, union control *);
88 static void macctrl_checkbox(struct macctrls *, WindowPtr,
89                              struct mac_layoutstate *, union control *);
90 static void macctrl_button(struct macctrls *, WindowPtr,
91                            struct mac_layoutstate *, union control *);
92
93 static int macctrl_cmp_byctrl(void *av, void *bv)
94 {
95     union macctrl *a = (union macctrl *)av;
96     union macctrl *b = (union macctrl *)bv;
97
98     if (a->generic.ctrl < b->generic.ctrl)
99         return -1;
100     else if (a->generic.ctrl > b->generic.ctrl)
101         return +1;
102     else
103         return 0;
104 }
105
106 void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
107                        struct macctrls *mcs)
108 {
109     int i;
110     struct mac_layoutstate curstate;
111     ControlRef root;
112     Rect rect;
113     
114 #if TARGET_API_MAC_CARBON
115     GetPortBounds(GetWindowPort(window), &rect);
116 #else
117     rect = window->portRect;
118 #endif
119     curstate.pos.h = rect.left + 13;
120     curstate.pos.v = rect.top + 13;
121     curstate.width = rect.right - rect.left - (13 * 2);
122     if (mac_gestalts.apprvers >= 0x100)
123         CreateRootControl(window, &root);
124     mcs->byctrl = newtree234(macctrl_cmp_byctrl);
125     for (i = 0; i < cb->nctrlsets; i++)
126         macctrl_layoutset(&curstate, cb->ctrlsets[i], window, mcs);
127 }
128
129 static void macctrl_layoutset(struct mac_layoutstate *curstate,
130                               struct controlset *s,
131                               WindowPtr window, struct macctrls *mcs)
132 {
133     unsigned int i;
134
135     fprintf(stderr, "--- begin set ---\n");
136     if (s->boxname && *s->boxname)
137         fprintf(stderr, "boxname = %s\n", s->boxname);
138     if (s->boxtitle)
139         fprintf(stderr, "boxtitle = %s\n", s->boxtitle);
140
141
142     for (i = 0; i < s->ncontrols; i++) {
143         union control *ctrl = s->ctrls[i];
144         char const *s;
145
146         switch (ctrl->generic.type) {
147           case CTRL_TEXT: s = "text"; break;
148           case CTRL_EDITBOX: s = "editbox"; break;
149           case CTRL_RADIO: s = "radio"; break;
150           case CTRL_CHECKBOX: s = "checkbox"; break;
151           case CTRL_BUTTON: s = "button"; break;
152           case CTRL_LISTBOX: s = "listbox"; break;
153           case CTRL_COLUMNS: s = "columns"; break;
154           case CTRL_FILESELECT: s = "fileselect"; break;
155           case CTRL_FONTSELECT: s = "fontselect"; break;
156           case CTRL_TABDELAY: s = "tabdelay"; break;
157           default: s = "unknown"; break;
158         }
159         fprintf(stderr, "  control: %s\n", s);
160         switch (ctrl->generic.type) {
161           case CTRL_TEXT:
162             macctrl_text(mcs, window, curstate, ctrl);
163             break;
164           case CTRL_RADIO:
165             macctrl_radio(mcs, window, curstate, ctrl);
166             break;
167           case CTRL_CHECKBOX:
168             macctrl_checkbox(mcs, window, curstate, ctrl);
169             break;
170           case CTRL_BUTTON:
171             macctrl_button(mcs, window, curstate, ctrl);
172             break;
173
174         }
175     }
176 }
177
178 static void macctrl_text(struct macctrls *mcs, WindowPtr window,
179                          struct mac_layoutstate *curstate,
180                          union control *ctrl)
181 {
182     union macctrl *mc = smalloc(sizeof *mc);
183     Rect bounds;
184
185     fprintf(stderr, "    label = %s\n", ctrl->text.label);
186     mc->generic.type = MACCTRL_TEXT;
187     mc->generic.ctrl = ctrl;
188     bounds.left = curstate->pos.h;
189     bounds.right = bounds.left + curstate->width;
190     bounds.top = curstate->pos.v;
191     bounds.bottom = bounds.top + 16;
192     if (mac_gestalts.apprvers >= 0x100) {
193         SInt16 height;
194         Size olen;
195
196         mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
197                                      kControlStaticTextProc, (long)mc);
198         SetControlData(mc->text.tbctrl, kControlEntireControl,
199                        kControlStaticTextTextTag,
200                        strlen(ctrl->text.label), ctrl->text.label);
201         GetControlData(mc->text.tbctrl, kControlEntireControl,
202                        kControlStaticTextTextHeightTag,
203                        sizeof(height), &height, &olen);
204         fprintf(stderr, "    height = %d\n", height);
205         SizeControl(mc->text.tbctrl, curstate->width, height);
206         curstate->pos.v += height + 6;
207     } else {
208         /* Do something useful */
209     }
210     add234(mcs->byctrl, mc);
211 }
212
213 static void macctrl_radio(struct macctrls *mcs, WindowPtr window,
214                           struct mac_layoutstate *curstate,
215                           union control *ctrl)
216 {
217     union macctrl *mc = smalloc(sizeof *mc);
218     Rect bounds;
219     Str255 title;
220     unsigned int i, colwidth;
221
222     fprintf(stderr, "    label = %s\n", ctrl->radio.label);
223     mc->generic.type = MACCTRL_RADIO;
224     mc->generic.ctrl = ctrl;
225     mc->radio.tbctrls =
226         smalloc(sizeof(*mc->radio.tbctrls) * ctrl->radio.nbuttons);
227     colwidth = (curstate->width + 13) / ctrl->radio.ncolumns;
228     for (i = 0; i < ctrl->radio.nbuttons; i++) {
229         fprintf(stderr, "    button = %s\n", ctrl->radio.buttons[i]);
230         bounds.top = curstate->pos.v;
231         bounds.bottom = bounds.top + 16;
232         bounds.left = curstate->pos.h + colwidth * (i % ctrl->radio.ncolumns);
233         if (i == ctrl->radio.nbuttons - 1 ||
234             i % ctrl->radio.ncolumns == ctrl->radio.ncolumns - 1) {
235             bounds.right = curstate->pos.h + curstate->width;
236             curstate->pos.v += 22;
237         } else
238             bounds.right = bounds.left + colwidth - 13;
239         c2pstrcpy(title, ctrl->radio.buttons[i]);
240         mc->radio.tbctrls[i] = NewControl(window, &bounds, title, TRUE,
241                                           0, 0, 1, radioButProc, (long)mc);
242     }
243     add234(mcs->byctrl, mc);
244     ctrlevent(mcs, mc, EVENT_REFRESH);
245 }
246
247 static void macctrl_checkbox(struct macctrls *mcs, WindowPtr window,
248                              struct mac_layoutstate *curstate,
249                              union control *ctrl)
250 {
251     union macctrl *mc = smalloc(sizeof *mc);
252     Rect bounds;
253     Str255 title;
254
255     fprintf(stderr, "    label = %s\n", ctrl->checkbox.label);
256     mc->generic.type = MACCTRL_CHECKBOX;
257     mc->generic.ctrl = ctrl;
258     bounds.left = curstate->pos.h;
259     bounds.right = bounds.left + curstate->width;
260     bounds.top = curstate->pos.v;
261     bounds.bottom = bounds.top + 16;
262     c2pstrcpy(title, ctrl->checkbox.label);
263     mc->checkbox.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
264                                      checkBoxProc, (long)mc);
265     add234(mcs->byctrl, mc);
266     curstate->pos.v += 22;
267     ctrlevent(mcs, mc, EVENT_REFRESH);
268 }
269
270 static void macctrl_button(struct macctrls *mcs, WindowPtr window,
271                            struct mac_layoutstate *curstate,
272                            union control *ctrl)
273 {
274     union macctrl *mc = smalloc(sizeof *mc);
275     Rect bounds;
276     Str255 title;
277
278     fprintf(stderr, "    label = %s\n", ctrl->button.label);
279     if (ctrl->button.isdefault)
280         fprintf(stderr, "    is default\n");
281     mc->generic.type = MACCTRL_BUTTON;
282     mc->generic.ctrl = ctrl;
283     bounds.left = curstate->pos.h;
284     bounds.right = bounds.left + 100; /* XXX measure string */
285     bounds.top = curstate->pos.v;
286     bounds.bottom = bounds.top + 20;
287     c2pstrcpy(title, ctrl->button.label);
288     mc->button.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
289                                    pushButProc, (long)mc);
290     if (mac_gestalts.apprvers >= 0x100) {
291         Boolean isdefault = ctrl->button.isdefault;
292
293         SetControlData(mc->button.tbctrl, kControlEntireControl,
294                        kControlPushButtonDefaultTag,
295                        sizeof(isdefault), &isdefault);
296     }
297     add234(mcs->byctrl, mc);
298     curstate->pos.v += 26;
299 }
300
301
302 void macctrl_activate(WindowPtr window, EventRecord *event)
303 {
304     Boolean active = (event->modifiers & activeFlag) != 0;
305     GrafPtr saveport;
306     ControlRef root;
307
308     GetPort(&saveport);
309     SetPort((GrafPtr)GetWindowPort(window));
310     if (mac_gestalts.apprvers >= 0x100) {
311         SetThemeWindowBackground(window, active ?
312                                  kThemeBrushModelessDialogBackgroundActive :
313                                  kThemeBrushModelessDialogBackgroundInactive,
314                                  TRUE);
315         GetRootControl(window, &root);
316         if (active)
317             ActivateControl(root);
318         else
319             DeactivateControl(root);
320     } else {
321         /* (De)activate controls one at a time */
322     }
323     SetPort(saveport);
324 }
325
326 void macctrl_click(WindowPtr window, EventRecord *event)
327 {
328     Point mouse;
329     ControlHandle control;
330     int part;
331     GrafPtr saveport;
332     union macctrl *mc;
333     struct macctrls *mcs = mac_winctrls(window);
334     int i;
335
336     GetPort(&saveport);
337     SetPort((GrafPtr)GetWindowPort(window));
338     mouse = event->where;
339     GlobalToLocal(&mouse);
340     part = FindControl(mouse, window, &control);
341     if (control != NULL)
342         if (TrackControl(control, mouse, NULL) != 0) {
343             mc = (union macctrl *)GetControlReference(control);
344             switch (mc->generic.type) {
345               case MACCTRL_RADIO:
346                 for (i = 0; i < mc->generic.ctrl->radio.nbuttons; i++) {
347                     if (mc->radio.tbctrls[i] == control)
348                         SetControlValue(mc->radio.tbctrls[i],
349                                         kControlRadioButtonCheckedValue);
350                     else
351                         SetControlValue(mc->radio.tbctrls[i],
352                                         kControlRadioButtonUncheckedValue);
353                 }
354                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
355                 break;
356               case MACCTRL_CHECKBOX:
357                 SetControlValue(control, !GetControlValue(control));
358                 ctrlevent(mcs, mc, EVENT_VALCHANGE);
359                 break;
360               case MACCTRL_BUTTON:
361                 ctrlevent(mcs, mc, EVENT_ACTION);
362                 break;
363             }
364         }
365     SetPort(saveport);
366 }
367
368 void macctrl_update(WindowPtr window)
369 {
370 #if TARGET_API_MAC_CARBON
371     RgnHandle visrgn;
372 #endif
373     Rect rect;
374     GrafPtr saveport;
375
376     BeginUpdate(window);
377     GetPort(&saveport);
378     SetPort((GrafPtr)GetWindowPort(window));
379     if (mac_gestalts.apprvers >= 0x101) {
380 #if TARGET_API_MAC_CARBON
381         GetPortBounds(GetWindowPort(window), &rect);
382 #else
383         rect = window->portRect;
384 #endif
385         InsetRect(&rect, -1, -1);
386         DrawThemeModelessDialogFrame(&rect, mac_frontwindow() == window ?
387                                      kThemeStateActive : kThemeStateInactive);
388     }
389 #if TARGET_API_MAC_CARBON
390     visrgn = NewRgn();
391     GetPortVisibleRegion(GetWindowPort(window), visrgn);
392     UpdateControls(window, visrgn);
393     DisposeRgn(visrgn);
394 #else
395     UpdateControls(window, window->visRgn);
396 #endif
397     SetPort(saveport);
398     EndUpdate(window);
399 }
400
401 #if TARGET_API_MAC_CARBON
402 #define EnableItem EnableMenuItem
403 #define DisableItem DisableMenuItem
404 #endif
405 void macctrl_adjustmenus(WindowPtr window)
406 {
407     MenuHandle menu;
408
409     menu = GetMenuHandle(mFile);
410     DisableItem(menu, iSave); /* XXX enable if modified */
411     EnableItem(menu, iSaveAs);
412     EnableItem(menu, iDuplicate);
413
414     menu = GetMenuHandle(mEdit);
415     DisableItem(menu, 0);
416 }
417
418 void macctrl_close(WindowPtr window)
419 {
420     struct macctrls *mcs = mac_winctrls(window);
421     union macctrl *mc;
422
423     while ((mc = index234(mcs->byctrl, 0)) != NULL) {
424         del234(mcs->byctrl, mc);
425         sfree(mc);
426     }
427
428     freetree234(mcs->byctrl);
429     mcs->byctrl = NULL;
430
431 /* XXX
432     DisposeWindow(window);
433     if (s->window == NULL)
434         sfree(s);
435 */
436 }
437
438 void dlg_update_start(union control *ctrl, void *dlg)
439 {
440
441     /* No-op for now */
442 }
443
444 void dlg_update_done(union control *ctrl, void *dlg)
445 {
446
447     /* No-op for now */
448 }
449
450 void dlg_set_focus(union control *ctrl, void *dlg)
451 {
452
453     if (mac_gestalts.apprvers >= 0x100) {
454         /* Use SetKeyboardFocus() */
455     } else {
456         /* Do our own mucking around */
457     }
458 }
459
460 union control *dlg_last_focused(void *dlg)
461 {
462
463     return NULL;
464 }
465
466 void dlg_beep(void *dlg)
467 {
468
469     SysBeep(30);
470 }
471
472 void dlg_error_msg(void *dlg, char *msg)
473 {
474     Str255 pmsg;
475
476     c2pstrcpy(pmsg, msg);
477     ParamText(pmsg, NULL, NULL, NULL);
478     StopAlert(128, NULL);
479 }
480
481 void dlg_end(void *dlg, int value)
482 {
483
484 };
485
486 void dlg_refresh(union control *ctrl, void *dlg)
487 {
488
489 };
490
491 void *dlg_get_privdata(union control *ctrl, void *dlg)
492 {
493
494     return NULL;
495 }
496
497 void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
498 {
499
500     fatalbox("dlg_set_privdata");
501 }
502
503 void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
504 {
505
506     fatalbox("dlg_alloc_privdata");
507 }
508
509
510 /*
511  * Radio Button control
512  */
513
514 void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton)
515 {
516     union macctrl *mc = dlg;
517     int i;
518
519     for (i = 0; i < ctrl->radio.nbuttons; i++) {
520         if (i == whichbutton)
521             SetControlValue(mc->radio.tbctrls[i],
522                             kControlRadioButtonCheckedValue);
523         else
524             SetControlValue(mc->radio.tbctrls[i],
525                             kControlRadioButtonUncheckedValue);
526     }
527
528 };
529
530 int dlg_radiobutton_get(union control *ctrl, void *dlg)
531 {
532     union macctrl *mc = dlg;
533     int i;
534
535     for (i = 0; i < ctrl->radio.nbuttons; i++) {
536         if (GetControlValue(mc->radio.tbctrls[i])  ==
537             kControlRadioButtonCheckedValue)
538             return i;
539     }
540     return -1;
541 };
542
543
544 /*
545  * Check Box control
546  */
547
548 void dlg_checkbox_set(union control *ctrl, void *dlg, int checked)
549 {
550     union macctrl *mc = dlg;
551
552     SetControlValue(mc->checkbox.tbctrl,
553                     checked ? kControlCheckBoxCheckedValue :
554                               kControlCheckBoxUncheckedValue);
555 }
556
557 int dlg_checkbox_get(union control *ctrl, void *dlg)
558 {
559     union macctrl *mc = dlg;
560
561     return GetControlValue(mc->checkbox.tbctrl);
562 }
563
564
565 /*
566  * Edit Box control
567  */
568
569 void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
570 {
571
572 };
573
574 void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
575 {
576
577 };
578
579
580 /*
581  * List Box control
582  */
583
584 void dlg_listbox_clear(union control *ctrl, void *dlg)
585 {
586
587 };
588
589 void dlg_listbox_del(union control *ctrl, void *dlg, int index)
590 {
591
592 };
593
594 void dlg_listbox_add(union control *ctrl, void *dlg, char const *text)
595 {
596
597 };
598
599 void dlg_listbox_addwithindex(union control *ctrl, void *dlg,
600                               char const *text, int id)
601 {
602
603 };
604
605 int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
606 {
607
608     return 0;
609 };
610
611 int dlg_listbox_index(union control *ctrl, void *dlg)
612 {
613
614     return 0;
615 };
616
617 int dlg_listbox_issel(union control *ctrl, void *dlg, int index)
618 {
619
620     return 0;
621 };
622
623 void dlg_listbox_select(union control *ctrl, void *dlg, int index)
624 {
625
626 };
627
628
629 /*
630  * Text control
631  */
632
633 void dlg_text_set(union control *ctrl, void *dlg, char const *text)
634 {
635     union macctrl *mc = dlg;
636
637     if (mac_gestalts.apprvers >= 0x100)
638         SetControlData(mc->text.tbctrl, kControlEntireControl,
639                        kControlStaticTextTextTag,
640                        strlen(ctrl->text.label), ctrl->text.label);
641 }
642
643
644 /*
645  * File Selector control
646  */
647
648 void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn)
649 {
650
651 }
652
653 void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
654 {
655
656 }
657
658
659 /*
660  * Font Selector control
661  */
662
663 void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn)
664 {
665
666 }
667
668 void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn)
669 {
670
671 }
672
673
674 /*
675  * Printer enumeration
676  */
677
678 printer_enum *printer_start_enum(int *nprinters)
679 {
680
681     *nprinters = 0;
682     return NULL;
683 }
684
685 char *printer_get_name(printer_enum *pe, int thing)
686 {
687
688     return "<none>";
689 }
690
691 void printer_finish_enum(printer_enum *pe)
692 {
693
694 }
695
696
697 /*
698  * Colour selection stuff
699  */
700
701 void dlg_coloursel_start(union control *ctrl, void *dlg,
702                          int r, int g, int b)
703 {
704
705 }
706
707 int dlg_coloursel_results(union control *ctrl, void *dlg,
708                           int *r, int *g, int *b)
709 {
710
711     return 0;
712 }
713
714 /*
715  * Local Variables:
716  * c-file-style: "simon"
717  * End:
718  */