1 /* $Id: macctrls.c,v 1.14 2003/03/25 23:23:03 ben Exp $ */
3 * Copyright (c) 2003 Ben Harris
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
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
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
29 #include <Appearance.h>
31 #include <ControlDefinitions.h>
33 #include <Resources.h>
35 #include <TextUtils.h>
47 /* Range of menu IDs for popup menus */
53 struct macctrl_generic
{
62 /* Template from which this was generated */
64 /* Next control in this panel */
70 struct macctrl_generic generic
;
74 struct macctrl_generic generic
;
78 struct macctrl_generic generic
;
82 struct macctrl_generic generic
;
86 struct macctrl_generic generic
;
90 struct macctrl_generic generic
;
99 struct mac_layoutstate
{
102 unsigned int panelnum
;
105 #define ctrlevent(mcs, mc, event) do { \
106 if ((mc)->generic.ctrl->generic.handler != NULL) \
107 (*(mc)->generic.ctrl->generic.handler)((mc)->generic.ctrl, (mcs),\
108 (mcs)->data, (event)); \
111 #define findbyctrl(mcs, ctrl) \
112 find234((mcs)->byctrl, (ctrl), macctrl_cmp_byctrl_find)
114 static void macctrl_layoutset(struct mac_layoutstate
*, struct controlset
*,
115 WindowPtr
, struct macctrls
*);
116 static void macctrl_switchtopanel(struct macctrls
*, unsigned int);
117 static void macctrl_text(struct macctrls
*, WindowPtr
,
118 struct mac_layoutstate
*, union control
*);
119 static void macctrl_editbox(struct macctrls
*, WindowPtr
,
120 struct mac_layoutstate
*, union control
*);
121 static void macctrl_radio(struct macctrls
*, WindowPtr
,
122 struct mac_layoutstate
*, union control
*);
123 static void macctrl_checkbox(struct macctrls
*, WindowPtr
,
124 struct mac_layoutstate
*, union control
*);
125 static void macctrl_button(struct macctrls
*, WindowPtr
,
126 struct mac_layoutstate
*, union control
*);
127 static void macctrl_popup(struct macctrls
*, WindowPtr
,
128 struct mac_layoutstate
*, union control
*);
129 #if !TARGET_API_MAC_CARBON
130 static pascal SInt32
macctrl_sys7_text_cdef(SInt16
, ControlRef
,
131 ControlDefProcMessage
, SInt32
);
132 static pascal SInt32
macctrl_sys7_default_cdef(SInt16
, ControlRef
,
133 ControlDefProcMessage
, SInt32
);
136 #if !TARGET_API_MAC_CARBON
138 * This trick enables us to keep all the CDEF code in the main
139 * application, which makes life easier. For details, see
140 * <http://developer.apple.com/technotes/tn/tn2003.html#custom_code_base>.
143 #pragma options align=mac68k
145 short jmpabs
; /* 4EF9 */
146 ControlDefUPP theUPP
;
148 #pragma options align=reset
151 static void macctrl_init()
153 #if !TARGET_API_MAC_CARBON
154 static int inited
= 0;
158 cdef
= (PatchCDEF
)GetResource(kControlDefProcResourceType
, CDEF_Text
);
159 (*cdef
)->theUPP
= NewControlDefProc(macctrl_sys7_text_cdef
);
160 cdef
= (PatchCDEF
)GetResource(kControlDefProcResourceType
, CDEF_Default
);
161 (*cdef
)->theUPP
= NewControlDefProc(macctrl_sys7_default_cdef
);
167 static int macctrl_cmp_byctrl(void *av
, void *bv
)
169 union macctrl
*a
= (union macctrl
*)av
;
170 union macctrl
*b
= (union macctrl
*)bv
;
172 if (a
->generic
.ctrl
< b
->generic
.ctrl
)
174 else if (a
->generic
.ctrl
> b
->generic
.ctrl
)
180 static int macctrl_cmp_byctrl_find(void *av
, void *bv
)
182 union control
*a
= (union control
*)av
;
183 union macctrl
*b
= (union macctrl
*)bv
;
185 if (a
< b
->generic
.ctrl
)
187 else if (a
> b
->generic
.ctrl
)
193 void macctrl_layoutbox(struct controlbox
*cb
, WindowPtr window
,
194 struct macctrls
*mcs
)
197 struct mac_layoutstate curstate
;
202 #if TARGET_API_MAC_CARBON
203 GetPortBounds(GetWindowPort(window
), &rect
);
205 rect
= window
->portRect
;
207 curstate
.pos
.h
= rect
.left
+ 13;
208 curstate
.pos
.v
= rect
.bottom
- 59;
209 curstate
.width
= rect
.right
- rect
.left
- (13 * 2);
210 if (mac_gestalts
.apprvers
>= 0x100)
211 CreateRootControl(window
, &root
);
212 mcs
->window
= window
;
213 mcs
->byctrl
= newtree234(macctrl_cmp_byctrl
);
214 /* Count the number of panels */
216 for (i
= 1; i
< cb
->nctrlsets
; i
++)
217 if (strcmp(cb
->ctrlsets
[i
]->pathname
, cb
->ctrlsets
[i
-1]->pathname
))
219 mcs
->panels
= smalloc(sizeof(*mcs
->panels
) * mcs
->npanels
);
220 memset(mcs
->panels
, 0, sizeof(*mcs
->panels
) * mcs
->npanels
);
221 curstate
.panelnum
= 0;
222 for (i
= 0; i
< cb
->nctrlsets
; i
++) {
223 if (i
> 0 && strcmp(cb
->ctrlsets
[i
]->pathname
,
224 cb
->ctrlsets
[i
-1]->pathname
)) {
225 curstate
.pos
.v
= rect
.top
+ 13;
227 assert(curstate
.panelnum
< mcs
->npanels
);
229 macctrl_layoutset(&curstate
, cb
->ctrlsets
[i
], window
, mcs
);
231 macctrl_switchtopanel(mcs
, 1);
234 static void macctrl_layoutset(struct mac_layoutstate
*curstate
,
235 struct controlset
*s
,
236 WindowPtr window
, struct macctrls
*mcs
)
240 fprintf(stderr
, "--- begin set ---\n");
241 fprintf(stderr
, "pathname = %s\n", s
->pathname
);
242 if (s
->boxname
&& *s
->boxname
)
243 fprintf(stderr
, "boxname = %s\n", s
->boxname
);
245 fprintf(stderr
, "boxtitle = %s\n", s
->boxtitle
);
248 for (i
= 0; i
< s
->ncontrols
; i
++) {
249 union control
*ctrl
= s
->ctrls
[i
];
252 switch (ctrl
->generic
.type
) {
253 case CTRL_TEXT
: s
= "text"; break;
254 case CTRL_EDITBOX
: s
= "editbox"; break;
255 case CTRL_RADIO
: s
= "radio"; break;
256 case CTRL_CHECKBOX
: s
= "checkbox"; break;
257 case CTRL_BUTTON
: s
= "button"; break;
258 case CTRL_LISTBOX
: s
= "listbox"; break;
259 case CTRL_COLUMNS
: s
= "columns"; break;
260 case CTRL_FILESELECT
: s
= "fileselect"; break;
261 case CTRL_FONTSELECT
: s
= "fontselect"; break;
262 case CTRL_TABDELAY
: s
= "tabdelay"; break;
263 default: s
= "unknown"; break;
265 fprintf(stderr
, " control: %s\n", s
);
266 switch (ctrl
->generic
.type
) {
268 macctrl_text(mcs
, window
, curstate
, ctrl
);
271 macctrl_editbox(mcs
, window
, curstate
, ctrl
);
274 macctrl_radio(mcs
, window
, curstate
, ctrl
);
277 macctrl_checkbox(mcs
, window
, curstate
, ctrl
);
280 macctrl_button(mcs
, window
, curstate
, ctrl
);
283 if (ctrl
->listbox
.height
== 0)
284 macctrl_popup(mcs
, window
, curstate
, ctrl
);
290 static void macctrl_switchtopanel(struct macctrls
*mcs
, unsigned int which
)
295 #define hideshow(c) do { \
296 if (i == which) ShowControl(c); else HideControl(c); \
299 mcs
->curpanel
= which
;
300 /* Panel 0 is special and always visible. */
301 for (i
= 1; i
< mcs
->npanels
; i
++)
302 for (mc
= mcs
->panels
[i
]; mc
!= NULL
; mc
= mc
->generic
.next
)
303 switch (mc
->generic
.type
) {
305 hideshow(mc
->text
.tbctrl
);
307 case MACCTRL_EDITBOX
:
308 hideshow(mc
->editbox
.tbctrl
);
311 for (j
= 0; j
< mc
->generic
.ctrl
->radio
.nbuttons
; j
++)
312 hideshow(mc
->radio
.tbctrls
[j
]);
314 case MACCTRL_CHECKBOX
:
315 hideshow(mc
->checkbox
.tbctrl
);
318 hideshow(mc
->button
.tbctrl
);
321 hideshow(mc
->popup
.tbctrl
);
326 static void macctrl_text(struct macctrls
*mcs
, WindowPtr window
,
327 struct mac_layoutstate
*curstate
,
330 union macctrl
*mc
= smalloc(sizeof *mc
);
333 fprintf(stderr
, " label = %s\n", ctrl
->text
.label
);
334 mc
->generic
.type
= MACCTRL_TEXT
;
335 mc
->generic
.ctrl
= ctrl
;
336 mc
->generic
.privdata
= NULL
;
337 bounds
.left
= curstate
->pos
.h
;
338 bounds
.right
= bounds
.left
+ curstate
->width
;
339 bounds
.top
= curstate
->pos
.v
;
340 bounds
.bottom
= bounds
.top
+ 16;
341 if (mac_gestalts
.apprvers
>= 0x100) {
345 mc
->text
.tbctrl
= NewControl(window
, &bounds
, NULL
, TRUE
, 0, 0, 0,
346 kControlStaticTextProc
, (long)mc
);
347 SetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
348 kControlStaticTextTextTag
,
349 strlen(ctrl
->text
.label
), ctrl
->text
.label
);
350 GetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
351 kControlStaticTextTextHeightTag
,
352 sizeof(height
), &height
, &olen
);
353 fprintf(stderr
, " height = %d\n", height
);
354 SizeControl(mc
->text
.tbctrl
, curstate
->width
, height
);
355 curstate
->pos
.v
+= height
+ 6;
359 c2pstrcpy(title
, ctrl
->text
.label
);
360 mc
->text
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 0,
361 SYS7_TEXT_PROC
, (long)mc
);
363 add234(mcs
->byctrl
, mc
);
364 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
365 mcs
->panels
[curstate
->panelnum
] = mc
;
368 #if !TARGET_API_MAC_CARBON
369 static pascal SInt32
macctrl_sys7_text_cdef(SInt16 variant
, ControlRef control
,
370 ControlDefProcMessage msg
, SInt32 param
)
376 if ((*control
)->contrlVis
)
377 TETextBox((*control
)->contrlTitle
+ 1, (*control
)->contrlTitle
[0],
378 &(*control
)->contrlRect
, teFlushDefault
);
381 if (param
& (1 << 31)) {
387 rgn
= (RgnHandle
)param
;
388 RectRgn(rgn
, &(*control
)->contrlRect
);
392 rgn
= (RgnHandle
)param
;
401 static void macctrl_editbox(struct macctrls
*mcs
, WindowPtr window
,
402 struct mac_layoutstate
*curstate
,
405 union macctrl
*mc
= smalloc(sizeof *mc
);
408 fprintf(stderr
, " label = %s\n", ctrl
->editbox
.label
);
409 fprintf(stderr
, " percentwidth = %d\n", ctrl
->editbox
.percentwidth
);
410 if (ctrl
->editbox
.password
) fprintf(stderr
, " password\n");
411 if (ctrl
->editbox
.has_list
) fprintf(stderr
, " has list\n");
412 mc
->generic
.type
= MACCTRL_EDITBOX
;
413 mc
->generic
.ctrl
= ctrl
;
414 mc
->generic
.privdata
= NULL
;
415 bounds
.left
= curstate
->pos
.h
;
416 bounds
.right
= bounds
.left
+ curstate
->width
;
417 bounds
.top
= curstate
->pos
.v
+ 2;
418 bounds
.bottom
= bounds
.top
+ 18;
419 if (mac_gestalts
.apprvers
>= 0x100) {
420 mc
->text
.tbctrl
= NewControl(window
, &bounds
, NULL
, TRUE
, 0, 0, 0,
421 ctrl
->editbox
.password ?
422 kControlEditTextPasswordProc
:
423 kControlEditTextProc
, (long)mc
);
424 curstate
->pos
.v
+= 28;
425 add234(mcs
->byctrl
, mc
);
426 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
427 mcs
->panels
[curstate
->panelnum
] = mc
;
428 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
430 /* Do a System 7 version */
434 static void macctrl_radio(struct macctrls
*mcs
, WindowPtr window
,
435 struct mac_layoutstate
*curstate
,
438 union macctrl
*mc
= smalloc(sizeof *mc
);
441 unsigned int i
, colwidth
;
443 fprintf(stderr
, " label = %s\n", ctrl
->radio
.label
);
444 mc
->generic
.type
= MACCTRL_RADIO
;
445 mc
->generic
.ctrl
= ctrl
;
446 mc
->generic
.privdata
= NULL
;
448 smalloc(sizeof(*mc
->radio
.tbctrls
) * ctrl
->radio
.nbuttons
);
449 colwidth
= (curstate
->width
+ 13) / ctrl
->radio
.ncolumns
;
450 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
451 fprintf(stderr
, " button = %s\n", ctrl
->radio
.buttons
[i
]);
452 bounds
.top
= curstate
->pos
.v
- 2;
453 bounds
.bottom
= bounds
.top
+ 18;
454 bounds
.left
= curstate
->pos
.h
+ colwidth
* (i
% ctrl
->radio
.ncolumns
);
455 if (i
== ctrl
->radio
.nbuttons
- 1 ||
456 i
% ctrl
->radio
.ncolumns
== ctrl
->radio
.ncolumns
- 1) {
457 bounds
.right
= curstate
->pos
.h
+ curstate
->width
;
458 curstate
->pos
.v
+= 18;
460 bounds
.right
= bounds
.left
+ colwidth
- 13;
461 c2pstrcpy(title
, ctrl
->radio
.buttons
[i
]);
462 mc
->radio
.tbctrls
[i
] = NewControl(window
, &bounds
, title
, TRUE
,
463 0, 0, 1, radioButProc
, (long)mc
);
465 curstate
->pos
.v
+= 4;
466 add234(mcs
->byctrl
, mc
);
467 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
468 mcs
->panels
[curstate
->panelnum
] = mc
;
469 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
472 static void macctrl_checkbox(struct macctrls
*mcs
, WindowPtr window
,
473 struct mac_layoutstate
*curstate
,
476 union macctrl
*mc
= smalloc(sizeof *mc
);
480 fprintf(stderr
, " label = %s\n", ctrl
->checkbox
.label
);
481 mc
->generic
.type
= MACCTRL_CHECKBOX
;
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 c2pstrcpy(title
, ctrl
->checkbox
.label
);
489 mc
->checkbox
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
490 checkBoxProc
, (long)mc
);
491 add234(mcs
->byctrl
, mc
);
492 curstate
->pos
.v
+= 22;
493 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
494 mcs
->panels
[curstate
->panelnum
] = mc
;
495 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
498 static void macctrl_button(struct macctrls
*mcs
, WindowPtr window
,
499 struct mac_layoutstate
*curstate
,
502 union macctrl
*mc
= smalloc(sizeof *mc
);
506 fprintf(stderr
, " label = %s\n", ctrl
->button
.label
);
507 if (ctrl
->button
.isdefault
)
508 fprintf(stderr
, " is default\n");
509 mc
->generic
.type
= MACCTRL_BUTTON
;
510 mc
->generic
.ctrl
= ctrl
;
511 mc
->generic
.privdata
= NULL
;
512 bounds
.left
= curstate
->pos
.h
;
513 bounds
.right
= bounds
.left
+ 100; /* XXX measure string */
514 bounds
.top
= curstate
->pos
.v
;
515 bounds
.bottom
= bounds
.top
+ 20;
516 c2pstrcpy(title
, ctrl
->button
.label
);
517 mc
->button
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
518 pushButProc
, (long)mc
);
519 if (mac_gestalts
.apprvers
>= 0x100) {
520 Boolean isdefault
= ctrl
->button
.isdefault
;
522 SetControlData(mc
->button
.tbctrl
, kControlEntireControl
,
523 kControlPushButtonDefaultTag
,
524 sizeof(isdefault
), &isdefault
);
525 } else if (ctrl
->button
.isdefault
) {
526 InsetRect(&bounds
, -4, -4);
527 NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
528 SYS7_DEFAULT_PROC
, (long)mc
);
530 if (mac_gestalts
.apprvers
>= 0x110) {
531 Boolean iscancel
= ctrl
->button
.iscancel
;
533 SetControlData(mc
->button
.tbctrl
, kControlEntireControl
,
534 kControlPushButtonCancelTag
,
535 sizeof(iscancel
), &iscancel
);
537 add234(mcs
->byctrl
, mc
);
538 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
539 mcs
->panels
[curstate
->panelnum
] = mc
;
540 curstate
->pos
.v
+= 26;
543 #if !TARGET_API_MAC_CARBON
544 static pascal SInt32
macctrl_sys7_default_cdef(SInt16 variant
,
546 ControlDefProcMessage msg
,
555 if ((*control
)->contrlVis
) {
556 rect
= (*control
)->contrlRect
;
559 oval
= (rect
.bottom
- rect
.top
) / 2 + 2;
560 FrameRoundRect(&rect
, oval
, oval
);
564 if (param
& (1 << 31)) {
570 rgn
= (RgnHandle
)param
;
571 RectRgn(rgn
, &(*control
)->contrlRect
);
575 rgn
= (RgnHandle
)param
;
584 static void macctrl_popup(struct macctrls
*mcs
, WindowPtr window
,
585 struct mac_layoutstate
*curstate
,
588 union macctrl
*mc
= smalloc(sizeof *mc
);
591 unsigned int labelwidth
;
592 static int nextmenuid
= MENU_MIN
;
597 * <http://developer.apple.com/qa/tb/tb42.html> explains how to
598 * create a popup menu with dynamic content.
600 assert(ctrl
->listbox
.height
== 0);
601 assert(!ctrl
->listbox
.draglist
);
602 assert(!ctrl
->listbox
.multisel
);
604 fprintf(stderr
, " label = %s\n", ctrl
->listbox
.label
);
605 fprintf(stderr
, " percentwidth = %d\n", ctrl
->listbox
.percentwidth
);
607 mc
->generic
.type
= MACCTRL_POPUP
;
608 mc
->generic
.ctrl
= ctrl
;
609 mc
->generic
.privdata
= NULL
;
610 c2pstrcpy(title
, ctrl
->button
.label
);
612 /* Find a spare menu ID and create the menu */
613 while (GetMenuHandle(nextmenuid
) != NULL
)
614 if (++nextmenuid
>= MENU_MAX
) nextmenuid
= MENU_MIN
;
615 menuid
= nextmenuid
++;
616 menu
= NewMenu(menuid
, "\pdummy");
617 if (menu
== NULL
) return;
618 mc
->popup
.menu
= menu
;
619 mc
->popup
.menuid
= menuid
;
620 InsertMenu(menu
, kInsertHierarchicalMenu
);
622 /* The menu starts off empty */
624 mc
->popup
.ids
= NULL
;
626 bounds
.left
= curstate
->pos
.h
;
627 bounds
.right
= bounds
.left
+ curstate
->width
;
628 bounds
.top
= curstate
->pos
.v
;
629 bounds
.bottom
= bounds
.top
+ 20;
630 /* XXX handle percentwidth == 100 */
631 labelwidth
= curstate
->width
* (100 - ctrl
->listbox
.percentwidth
) / 100;
632 mc
->popup
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
,
633 popupTitleLeftJust
, menuid
, labelwidth
,
634 popupMenuProc
+ popupFixedWidth
, (long)mc
);
635 add234(mcs
->byctrl
, mc
);
636 curstate
->pos
.v
+= 26;
637 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
638 mcs
->panels
[curstate
->panelnum
] = mc
;
639 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
643 void macctrl_activate(WindowPtr window
, EventRecord
*event
)
645 struct macctrls
*mcs
= mac_winctrls(window
);
646 Boolean active
= (event
->modifiers
& activeFlag
) != 0;
649 ControlPartCode state
;
653 SetPort((GrafPtr
)GetWindowPort(window
));
654 if (mac_gestalts
.apprvers
>= 0x100)
655 SetThemeWindowBackground(window
, active ?
656 kThemeBrushModelessDialogBackgroundActive
:
657 kThemeBrushModelessDialogBackgroundInactive
,
659 state
= active ? kControlNoPart
: kControlInactivePart
;
660 for (i
= 0; i
<= mcs
->curpanel
; i
+= mcs
->curpanel
)
661 for (mc
= mcs
->panels
[i
]; mc
!= NULL
; mc
= mc
->generic
.next
)
662 switch (mc
->generic
.type
) {
664 HiliteControl(mc
->text
.tbctrl
, state
);
666 case MACCTRL_EDITBOX
:
667 HiliteControl(mc
->editbox
.tbctrl
, state
);
670 for (j
= 0; j
< mc
->generic
.ctrl
->radio
.nbuttons
; j
++)
671 HiliteControl(mc
->radio
.tbctrls
[j
], state
);
673 case MACCTRL_CHECKBOX
:
674 HiliteControl(mc
->checkbox
.tbctrl
, state
);
677 HiliteControl(mc
->button
.tbctrl
, state
);
680 HiliteControl(mc
->popup
.tbctrl
, state
);
686 void macctrl_click(WindowPtr window
, EventRecord
*event
)
689 ControlHandle control
;
690 int part
, trackresult
;
693 struct macctrls
*mcs
= mac_winctrls(window
);
698 SetPort((GrafPtr
)GetWindowPort(window
));
699 mouse
= event
->where
;
700 GlobalToLocal(&mouse
);
701 part
= FindControl(mouse
, window
, &control
);
702 if (control
!= NULL
) {
703 if (mac_gestalts
.apprvers
>= 0x100) {
704 if (GetControlFeatures(control
, &features
) == noErr
&&
705 (features
& kControlSupportsFocus
) &&
706 (features
& kControlGetsFocusOnClick
))
707 SetKeyboardFocus(window
, control
, part
);
708 trackresult
= HandleControlClick(control
, mouse
, event
->modifiers
,
709 (ControlActionUPP
)-1);
711 trackresult
= TrackControl(control
, mouse
, (ControlActionUPP
)-1);
712 mc
= (union macctrl
*)GetControlReference(control
);
713 switch (mc
->generic
.type
) {
715 if (trackresult
!= 0) {
716 for (i
= 0; i
< mc
->generic
.ctrl
->radio
.nbuttons
; i
++)
717 if (mc
->radio
.tbctrls
[i
] == control
)
718 SetControlValue(mc
->radio
.tbctrls
[i
],
719 kControlRadioButtonCheckedValue
);
721 SetControlValue(mc
->radio
.tbctrls
[i
],
722 kControlRadioButtonUncheckedValue
);
723 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
726 case MACCTRL_CHECKBOX
:
727 if (trackresult
!= 0) {
728 SetControlValue(control
, !GetControlValue(control
));
729 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
733 if (trackresult
!= 0)
734 ctrlevent(mcs
, mc
, EVENT_ACTION
);
737 ctrlevent(mcs
, mc
, EVENT_SELCHANGE
);
744 void macctrl_key(WindowPtr window
, EventRecord
*event
)
747 struct macctrls
*mcs
= mac_winctrls(window
);
750 if (mac_gestalts
.apprvers
>= 0x100 &&
751 GetKeyboardFocus(window
, &control
) == noErr
&& control
!= NULL
) {
752 HandleControlKey(control
, (event
->message
& keyCodeMask
) >> 8,
753 event
->message
& charCodeMask
, event
->modifiers
);
754 mc
= (union macctrl
*)GetControlReference(control
);
755 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
759 void macctrl_update(WindowPtr window
)
761 #if TARGET_API_MAC_CARBON
769 SetPort((GrafPtr
)GetWindowPort(window
));
770 if (mac_gestalts
.apprvers
>= 0x101) {
771 #if TARGET_API_MAC_CARBON
772 GetPortBounds(GetWindowPort(window
), &rect
);
774 rect
= window
->portRect
;
776 InsetRect(&rect
, -1, -1);
777 DrawThemeModelessDialogFrame(&rect
, mac_frontwindow() == window ?
778 kThemeStateActive
: kThemeStateInactive
);
780 #if TARGET_API_MAC_CARBON
782 GetPortVisibleRegion(GetWindowPort(window
), visrgn
);
783 UpdateControls(window
, visrgn
);
786 UpdateControls(window
, window
->visRgn
);
792 #if TARGET_API_MAC_CARBON
793 #define EnableItem EnableMenuItem
794 #define DisableItem DisableMenuItem
796 void macctrl_adjustmenus(WindowPtr window
)
800 menu
= GetMenuHandle(mFile
);
801 DisableItem(menu
, iSave
); /* XXX enable if modified */
802 EnableItem(menu
, iSaveAs
);
803 EnableItem(menu
, iDuplicate
);
805 menu
= GetMenuHandle(mEdit
);
806 DisableItem(menu
, 0);
809 void macctrl_close(WindowPtr window
)
811 struct macctrls
*mcs
= mac_winctrls(window
);
815 * Mostly, we don't bother disposing of the Toolbox controls,
816 * since that will happen automatically when the window is
817 * disposed of. Popup menus are an exception, because we have to
818 * dispose of the menu ourselves, and doing that while the control
819 * still holds a reference to it seems rude.
821 while ((mc
= index234(mcs
->byctrl
, 0)) != NULL
) {
822 if (mc
->generic
.privdata
!= NULL
&& mc
->generic
.freeprivdata
)
823 sfree(mc
->generic
.privdata
);
824 switch (mc
->generic
.type
) {
826 DisposeControl(mc
->popup
.tbctrl
);
827 DeleteMenu(mc
->popup
.menuid
);
828 DisposeMenu(mc
->popup
.menu
);
831 del234(mcs
->byctrl
, mc
);
835 freetree234(mcs
->byctrl
);
841 void dlg_update_start(union control
*ctrl
, void *dlg
)
847 void dlg_update_done(union control
*ctrl
, void *dlg
)
853 void dlg_set_focus(union control
*ctrl
, void *dlg
)
856 if (mac_gestalts
.apprvers
>= 0x100) {
857 /* Use SetKeyboardFocus() */
859 /* Do our own mucking around */
863 union control
*dlg_last_focused(union control
*ctrl
, void *dlg
)
869 void dlg_beep(void *dlg
)
875 void dlg_error_msg(void *dlg
, char *msg
)
879 c2pstrcpy(pmsg
, msg
);
880 ParamText(pmsg
, NULL
, NULL
, NULL
);
881 StopAlert(128, NULL
);
884 void dlg_end(void *dlg
, int value
)
889 void dlg_refresh(union control
*ctrl
, void *dlg
)
891 struct macctrls
*mcs
= dlg
;
896 mc
= findbyctrl(mcs
, ctrl
);
898 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
901 void *dlg_get_privdata(union control
*ctrl
, void *dlg
)
903 struct macctrls
*mcs
= dlg
;
904 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
907 return mc
->generic
.privdata
;
910 void dlg_set_privdata(union control
*ctrl
, void *dlg
, void *ptr
)
912 struct macctrls
*mcs
= dlg
;
913 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
916 mc
->generic
.privdata
= ptr
;
917 mc
->generic
.freeprivdata
= FALSE
;
920 void *dlg_alloc_privdata(union control
*ctrl
, void *dlg
, size_t size
)
922 struct macctrls
*mcs
= dlg
;
923 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
926 mc
->generic
.privdata
= smalloc(size
);
927 mc
->generic
.freeprivdata
= TRUE
;
928 return mc
->generic
.privdata
;
933 * Radio Button control
936 void dlg_radiobutton_set(union control
*ctrl
, void *dlg
, int whichbutton
)
938 struct macctrls
*mcs
= dlg
;
939 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
943 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
944 if (i
== whichbutton
)
945 SetControlValue(mc
->radio
.tbctrls
[i
],
946 kControlRadioButtonCheckedValue
);
948 SetControlValue(mc
->radio
.tbctrls
[i
],
949 kControlRadioButtonUncheckedValue
);
954 int dlg_radiobutton_get(union control
*ctrl
, void *dlg
)
956 struct macctrls
*mcs
= dlg
;
957 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
961 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
962 if (GetControlValue(mc
->radio
.tbctrls
[i
]) ==
963 kControlRadioButtonCheckedValue
)
974 void dlg_checkbox_set(union control
*ctrl
, void *dlg
, int checked
)
976 struct macctrls
*mcs
= dlg
;
977 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
980 SetControlValue(mc
->checkbox
.tbctrl
,
981 checked ? kControlCheckBoxCheckedValue
:
982 kControlCheckBoxUncheckedValue
);
985 int dlg_checkbox_get(union control
*ctrl
, void *dlg
)
987 struct macctrls
*mcs
= dlg
;
988 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
991 return GetControlValue(mc
->checkbox
.tbctrl
);
999 void dlg_editbox_set(union control
*ctrl
, void *dlg
, char const *text
)
1001 struct macctrls
*mcs
= dlg
;
1002 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1006 assert(mc
->generic
.type
== MACCTRL_EDITBOX
);
1007 if (mac_gestalts
.apprvers
>= 0x100) {
1008 SetControlData(mc
->editbox
.tbctrl
, kControlEntireControl
,
1009 ctrl
->editbox
.password ?
1010 kControlEditTextPasswordTag
:
1011 kControlEditTextTextTag
,
1012 strlen(text
), text
);
1014 SetPort((GrafPtr
)(GetWindowPort(mcs
->window
)));
1015 DrawOneControl(mc
->editbox
.tbctrl
);
1020 void dlg_editbox_get(union control
*ctrl
, void *dlg
, char *buffer
, int length
)
1022 struct macctrls
*mcs
= dlg
;
1023 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1027 assert(mc
->generic
.type
== MACCTRL_EDITBOX
);
1028 if (mac_gestalts
.apprvers
>= 0x100) {
1029 if (GetControlData(mc
->editbox
.tbctrl
, kControlEntireControl
,
1030 ctrl
->editbox
.password ?
1031 kControlEditTextPasswordTag
:
1032 kControlEditTextTextTag
,
1033 length
- 1, buffer
, &olen
) != noErr
)
1035 if (olen
> length
- 1)
1036 buffer
[length
- 1] = '\0';
1038 buffer
[olen
] = '\0';
1039 buffer
[olen
] = '\0';
1042 fprintf(stderr
, "dlg_editbox_get: %s\n", buffer
);
1050 static void dlg_macpopup_clear(union control
*ctrl
, void *dlg
)
1052 struct macctrls
*mcs
= dlg
;
1053 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1054 MenuRef menu
= mc
->popup
.menu
;
1057 fprintf(stderr
, " popup_clear\n");
1058 n
= CountMenuItems(menu
);
1059 for (i
= 0; i
< n
; i
++)
1060 DeleteMenuItem(menu
, n
- i
);
1062 sfree(mc
->popup
.ids
);
1063 mc
->popup
.ids
= NULL
;
1064 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1067 void dlg_listbox_clear(union control
*ctrl
, void *dlg
)
1070 if (ctrl
->listbox
.height
== 0)
1071 dlg_macpopup_clear(ctrl
, dlg
);
1074 static void dlg_macpopup_del(union control
*ctrl
, void *dlg
, int index
)
1076 struct macctrls
*mcs
= dlg
;
1077 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1078 MenuRef menu
= mc
->popup
.menu
;
1080 fprintf(stderr
, " popup_del %d\n", index
);
1081 DeleteMenuItem(menu
, index
+ 1);
1082 if (mc
->popup
.ids
!= NULL
)
1083 memcpy(mc
->popup
.ids
+ index
, mc
->popup
.ids
+ index
+ 1,
1084 (mc
->popup
.nids
- index
- 1) * sizeof(*mc
->popup
.ids
));
1085 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1088 void dlg_listbox_del(union control
*ctrl
, void *dlg
, int index
)
1091 if (ctrl
->listbox
.height
== 0)
1092 dlg_macpopup_del(ctrl
, dlg
, index
);
1095 static void dlg_macpopup_add(union control
*ctrl
, void *dlg
, char const *text
)
1097 struct macctrls
*mcs
= dlg
;
1098 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1099 MenuRef menu
= mc
->popup
.menu
;
1102 fprintf(stderr
, " popup_add %s\n", text
);
1103 assert(text
[0] != '\0');
1104 c2pstrcpy(itemstring
, text
);
1105 AppendMenu(menu
, "\pdummy");
1106 SetMenuItemText(menu
, CountMenuItems(menu
), itemstring
);
1107 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1110 void dlg_listbox_add(union control
*ctrl
, void *dlg
, char const *text
)
1113 if (ctrl
->listbox
.height
== 0)
1114 dlg_macpopup_add(ctrl
, dlg
, text
);
1117 static void dlg_macpopup_addwithindex(union control
*ctrl
, void *dlg
,
1118 char const *text
, int id
)
1120 struct macctrls
*mcs
= dlg
;
1121 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1122 MenuRef menu
= mc
->popup
.menu
;
1125 fprintf(stderr
, " popup_addwthindex %s, %d\n", text
, id
);
1126 dlg_macpopup_add(ctrl
, dlg
, text
);
1127 index
= CountMenuItems(menu
) - 1;
1128 if (mc
->popup
.nids
<= index
) {
1129 mc
->popup
.nids
= index
+ 1;
1130 mc
->popup
.ids
= srealloc(mc
->popup
.ids
,
1131 mc
->popup
.nids
* sizeof(*mc
->popup
.ids
));
1133 mc
->popup
.ids
[index
] = id
;
1136 void dlg_listbox_addwithindex(union control
*ctrl
, void *dlg
,
1137 char const *text
, int id
)
1140 if (ctrl
->listbox
.height
== 0)
1141 dlg_macpopup_addwithindex(ctrl
, dlg
, text
, id
);
1144 int dlg_listbox_getid(union control
*ctrl
, void *dlg
, int index
)
1146 struct macctrls
*mcs
= dlg
;
1147 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1149 if (ctrl
->listbox
.height
== 0) {
1150 assert(mc
->popup
.ids
!= NULL
&& mc
->popup
.nids
> index
);
1151 return mc
->popup
.ids
[index
];
1156 int dlg_listbox_index(union control
*ctrl
, void *dlg
)
1158 struct macctrls
*mcs
= dlg
;
1159 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1161 if (ctrl
->listbox
.height
== 0)
1162 return GetControlValue(mc
->popup
.tbctrl
) - 1;
1166 int dlg_listbox_issel(union control
*ctrl
, void *dlg
, int index
)
1168 struct macctrls
*mcs
= dlg
;
1169 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1171 if (ctrl
->listbox
.height
== 0)
1172 return GetControlValue(mc
->popup
.tbctrl
) - 1 == index
;
1176 void dlg_listbox_select(union control
*ctrl
, void *dlg
, int index
)
1178 struct macctrls
*mcs
= dlg
;
1179 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1181 if (ctrl
->listbox
.height
== 0)
1182 SetControlValue(mc
->popup
.tbctrl
, index
+ 1);
1190 void dlg_text_set(union control
*ctrl
, void *dlg
, char const *text
)
1192 struct macctrls
*mcs
= dlg
;
1193 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1197 if (mac_gestalts
.apprvers
>= 0x100)
1198 SetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
1199 kControlStaticTextTextTag
, strlen(text
), text
);
1201 c2pstrcpy(title
, text
);
1202 SetControlTitle(mc
->text
.tbctrl
, title
);
1208 * File Selector control
1211 void dlg_filesel_set(union control
*ctrl
, void *dlg
, Filename fn
)
1216 void dlg_filesel_get(union control
*ctrl
, void *dlg
, Filename
*fn
)
1223 * Font Selector control
1226 void dlg_fontsel_set(union control
*ctrl
, void *dlg
, FontSpec fn
)
1231 void dlg_fontsel_get(union control
*ctrl
, void *dlg
, FontSpec
*fn
)
1238 * Printer enumeration
1241 printer_enum
*printer_start_enum(int *nprinters
)
1248 char *printer_get_name(printer_enum
*pe
, int thing
)
1254 void printer_finish_enum(printer_enum
*pe
)
1261 * Colour selection stuff
1264 void dlg_coloursel_start(union control
*ctrl
, void *dlg
,
1265 int r
, int g
, int b
)
1270 int dlg_coloursel_results(union control
*ctrl
, void *dlg
,
1271 int *r
, int *g
, int *b
)
1279 * c-file-style: "simon"