Insert a missing ampersand that meant that the last version didn't even
[u/mdw/putty] / mac / macctrls.c
CommitLineData
8a7e67ec 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
42union 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
71struct 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
82static void macctrl_layoutset(struct mac_layoutstate *, struct controlset *,
83 WindowPtr, struct macctrls *);
84static void macctrl_text(struct macctrls *, WindowPtr,
85 struct mac_layoutstate *, union control *);
86static void macctrl_radio(struct macctrls *, WindowPtr,
87 struct mac_layoutstate *, union control *);
88static void macctrl_checkbox(struct macctrls *, WindowPtr,
89 struct mac_layoutstate *, union control *);
90static void macctrl_button(struct macctrls *, WindowPtr,
91 struct mac_layoutstate *, union control *);
92
93static 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
106void 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
129static 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
178static 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
213static 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
247static 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
270static 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
302void 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
326void 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
368void 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
405void 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
418void 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
438void dlg_update_start(union control *ctrl, void *dlg)
439{
440
441 /* No-op for now */
442}
443
444void dlg_update_done(union control *ctrl, void *dlg)
445{
446
447 /* No-op for now */
448}
449
450void 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
460union control *dlg_last_focused(void *dlg)
461{
462
463 return NULL;
464}
465
466void dlg_beep(void *dlg)
467{
468
469 SysBeep(30);
470}
471
472void 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
481void dlg_end(void *dlg, int value)
482{
483
484};
485
486void dlg_refresh(union control *ctrl, void *dlg)
487{
488
489};
490
491void *dlg_get_privdata(union control *ctrl, void *dlg)
492{
493
494 return NULL;
495}
496
497void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
498{
499
500 fatalbox("dlg_set_privdata");
501}
502
503void *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
514void 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
530int 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
548void 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
557int 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
569void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
570{
571
572};
573
574void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
575{
576
577};
578
579
580/*
581 * List Box control
582 */
583
584void dlg_listbox_clear(union control *ctrl, void *dlg)
585{
586
587};
588
589void dlg_listbox_del(union control *ctrl, void *dlg, int index)
590{
591
592};
593
594void dlg_listbox_add(union control *ctrl, void *dlg, char const *text)
595{
596
597};
598
599void dlg_listbox_addwithindex(union control *ctrl, void *dlg,
600 char const *text, int id)
601{
602
603};
604
605int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
606{
607
608 return 0;
609};
610
611int dlg_listbox_index(union control *ctrl, void *dlg)
612{
613
614 return 0;
615};
616
617int dlg_listbox_issel(union control *ctrl, void *dlg, int index)
618{
619
620 return 0;
621};
622
623void dlg_listbox_select(union control *ctrl, void *dlg, int index)
624{
625
626};
627
628
629/*
630 * Text control
631 */
632
633void 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
648void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn)
649{
650
651}
652
653void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
654{
655
656}
657
658
659/*
660 * Font Selector control
661 */
662
663void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn)
664{
665
666}
667
668void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn)
669{
670
671}
672
673
674/*
675 * Printer enumeration
676 */
677
678printer_enum *printer_start_enum(int *nprinters)
679{
680
681 *nprinters = 0;
682 return NULL;
683}
684
685char *printer_get_name(printer_enum *pe, int thing)
686{
687
688 return "<none>";
689}
690
691void printer_finish_enum(printer_enum *pe)
692{
693
694}
695
696
697/*
698 * Colour selection stuff
699 */
700
701void dlg_coloursel_start(union control *ctrl, void *dlg,
702 int r, int g, int b)
703{
704
705}
706
707int 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 */