1 /* $Id: macctrls.c,v 1.17 2003/03/28 00:50:04 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>
37 #include <TextUtils.h>
38 #include <ToolUtils.h>
50 /* Range of menu IDs for popup menus */
56 struct macctrl_generic
{
65 /* Template from which this was generated */
67 /* Next control in this panel */
73 struct macctrl_generic generic
;
77 struct macctrl_generic generic
;
81 struct macctrl_generic generic
;
85 struct macctrl_generic generic
;
89 struct macctrl_generic generic
;
93 struct macctrl_generic generic
;
102 struct mac_layoutstate
{
105 unsigned int panelnum
;
108 #define ctrlevent(mcs, mc, event) do { \
109 if ((mc)->generic.ctrl->generic.handler != NULL) \
110 (*(mc)->generic.ctrl->generic.handler)((mc)->generic.ctrl, (mcs),\
111 (mcs)->data, (event)); \
114 #define findbyctrl(mcs, ctrl) \
115 find234((mcs)->byctrl, (ctrl), macctrl_cmp_byctrl_find)
117 static void macctrl_layoutset(struct mac_layoutstate
*, struct controlset
*,
118 WindowPtr
, struct macctrls
*);
119 static void macctrl_switchtopanel(struct macctrls
*, unsigned int);
120 static void macctrl_text(struct macctrls
*, WindowPtr
,
121 struct mac_layoutstate
*, union control
*);
122 static void macctrl_editbox(struct macctrls
*, WindowPtr
,
123 struct mac_layoutstate
*, union control
*);
124 static void macctrl_radio(struct macctrls
*, WindowPtr
,
125 struct mac_layoutstate
*, union control
*);
126 static void macctrl_checkbox(struct macctrls
*, WindowPtr
,
127 struct mac_layoutstate
*, union control
*);
128 static void macctrl_button(struct macctrls
*, WindowPtr
,
129 struct mac_layoutstate
*, union control
*);
130 static void macctrl_popup(struct macctrls
*, WindowPtr
,
131 struct mac_layoutstate
*, union control
*);
132 #if !TARGET_API_MAC_CARBON
133 static pascal SInt32
macctrl_sys7_text_cdef(SInt16
, ControlRef
,
134 ControlDefProcMessage
, SInt32
);
135 static pascal SInt32
macctrl_sys7_editbox_cdef(SInt16
, ControlRef
,
136 ControlDefProcMessage
, SInt32
);
137 static pascal SInt32
macctrl_sys7_default_cdef(SInt16
, ControlRef
,
138 ControlDefProcMessage
, SInt32
);
141 #if !TARGET_API_MAC_CARBON
143 * This trick enables us to keep all the CDEF code in the main
144 * application, which makes life easier. For details, see
145 * <http://developer.apple.com/technotes/tn/tn2003.html#custom_code_base>.
148 #pragma options align=mac68k
150 short jmpabs
; /* 4EF9 */
151 ControlDefUPP theUPP
;
153 #pragma options align=reset
156 static void macctrl_init()
158 #if !TARGET_API_MAC_CARBON
159 static int inited
= 0;
163 cdef
= (PatchCDEF
)GetResource(kControlDefProcResourceType
, CDEF_Text
);
164 (*cdef
)->theUPP
= NewControlDefProc(macctrl_sys7_text_cdef
);
165 cdef
= (PatchCDEF
)GetResource(kControlDefProcResourceType
, CDEF_EditBox
);
166 (*cdef
)->theUPP
= NewControlDefProc(macctrl_sys7_editbox_cdef
);
167 cdef
= (PatchCDEF
)GetResource(kControlDefProcResourceType
, CDEF_Default
);
168 (*cdef
)->theUPP
= NewControlDefProc(macctrl_sys7_default_cdef
);
174 static int macctrl_cmp_byctrl(void *av
, void *bv
)
176 union macctrl
*a
= (union macctrl
*)av
;
177 union macctrl
*b
= (union macctrl
*)bv
;
179 if (a
->generic
.ctrl
< b
->generic
.ctrl
)
181 else if (a
->generic
.ctrl
> b
->generic
.ctrl
)
187 static int macctrl_cmp_byctrl_find(void *av
, void *bv
)
189 union control
*a
= (union control
*)av
;
190 union macctrl
*b
= (union macctrl
*)bv
;
192 if (a
< b
->generic
.ctrl
)
194 else if (a
> b
->generic
.ctrl
)
200 void macctrl_layoutbox(struct controlbox
*cb
, WindowPtr window
,
201 struct macctrls
*mcs
)
204 struct mac_layoutstate curstate
;
209 #if TARGET_API_MAC_CARBON
210 GetPortBounds(GetWindowPort(window
), &rect
);
212 rect
= window
->portRect
;
214 curstate
.pos
.h
= rect
.left
+ 13;
215 curstate
.pos
.v
= rect
.bottom
- 59;
216 curstate
.width
= rect
.right
- rect
.left
- (13 * 2);
217 if (mac_gestalts
.apprvers
>= 0x100)
218 CreateRootControl(window
, &root
);
219 mcs
->window
= window
;
220 mcs
->byctrl
= newtree234(macctrl_cmp_byctrl
);
221 /* Count the number of panels */
223 for (i
= 1; i
< cb
->nctrlsets
; i
++)
224 if (strcmp(cb
->ctrlsets
[i
]->pathname
, cb
->ctrlsets
[i
-1]->pathname
))
226 mcs
->panels
= smalloc(sizeof(*mcs
->panels
) * mcs
->npanels
);
227 memset(mcs
->panels
, 0, sizeof(*mcs
->panels
) * mcs
->npanels
);
228 curstate
.panelnum
= 0;
229 for (i
= 0; i
< cb
->nctrlsets
; i
++) {
230 if (i
> 0 && strcmp(cb
->ctrlsets
[i
]->pathname
,
231 cb
->ctrlsets
[i
-1]->pathname
)) {
232 curstate
.pos
.v
= rect
.top
+ 13;
234 assert(curstate
.panelnum
< mcs
->npanels
);
236 macctrl_layoutset(&curstate
, cb
->ctrlsets
[i
], window
, mcs
);
238 macctrl_switchtopanel(mcs
, 1);
241 static void macctrl_layoutset(struct mac_layoutstate
*curstate
,
242 struct controlset
*s
,
243 WindowPtr window
, struct macctrls
*mcs
)
247 fprintf(stderr
, "--- begin set ---\n");
248 fprintf(stderr
, "pathname = %s\n", s
->pathname
);
249 if (s
->boxname
&& *s
->boxname
)
250 fprintf(stderr
, "boxname = %s\n", s
->boxname
);
252 fprintf(stderr
, "boxtitle = %s\n", s
->boxtitle
);
255 for (i
= 0; i
< s
->ncontrols
; i
++) {
256 union control
*ctrl
= s
->ctrls
[i
];
259 switch (ctrl
->generic
.type
) {
260 case CTRL_TEXT
: s
= "text"; break;
261 case CTRL_EDITBOX
: s
= "editbox"; break;
262 case CTRL_RADIO
: s
= "radio"; break;
263 case CTRL_CHECKBOX
: s
= "checkbox"; break;
264 case CTRL_BUTTON
: s
= "button"; break;
265 case CTRL_LISTBOX
: s
= "listbox"; break;
266 case CTRL_COLUMNS
: s
= "columns"; break;
267 case CTRL_FILESELECT
: s
= "fileselect"; break;
268 case CTRL_FONTSELECT
: s
= "fontselect"; break;
269 case CTRL_TABDELAY
: s
= "tabdelay"; break;
270 default: s
= "unknown"; break;
272 fprintf(stderr
, " control: %s\n", s
);
273 switch (ctrl
->generic
.type
) {
275 macctrl_text(mcs
, window
, curstate
, ctrl
);
278 macctrl_editbox(mcs
, window
, curstate
, ctrl
);
281 macctrl_radio(mcs
, window
, curstate
, ctrl
);
284 macctrl_checkbox(mcs
, window
, curstate
, ctrl
);
287 macctrl_button(mcs
, window
, curstate
, ctrl
);
290 if (ctrl
->listbox
.height
== 0)
291 macctrl_popup(mcs
, window
, curstate
, ctrl
);
297 static void macctrl_switchtopanel(struct macctrls
*mcs
, unsigned int which
)
302 #define hideshow(c) do { \
303 if (i == which) ShowControl(c); else HideControl(c); \
306 mcs
->curpanel
= which
;
307 /* Panel 0 is special and always visible. */
308 for (i
= 1; i
< mcs
->npanels
; i
++)
309 for (mc
= mcs
->panels
[i
]; mc
!= NULL
; mc
= mc
->generic
.next
)
310 switch (mc
->generic
.type
) {
312 hideshow(mc
->text
.tbctrl
);
314 case MACCTRL_EDITBOX
:
315 hideshow(mc
->editbox
.tbctrl
);
318 for (j
= 0; j
< mc
->generic
.ctrl
->radio
.nbuttons
; j
++)
319 hideshow(mc
->radio
.tbctrls
[j
]);
321 case MACCTRL_CHECKBOX
:
322 hideshow(mc
->checkbox
.tbctrl
);
325 hideshow(mc
->button
.tbctrl
);
328 hideshow(mc
->popup
.tbctrl
);
333 static void macctrl_text(struct macctrls
*mcs
, WindowPtr window
,
334 struct mac_layoutstate
*curstate
,
337 union macctrl
*mc
= smalloc(sizeof *mc
);
340 fprintf(stderr
, " label = %s\n", ctrl
->text
.label
);
341 mc
->generic
.type
= MACCTRL_TEXT
;
342 mc
->generic
.ctrl
= ctrl
;
343 mc
->generic
.privdata
= NULL
;
344 bounds
.left
= curstate
->pos
.h
;
345 bounds
.right
= bounds
.left
+ curstate
->width
;
346 bounds
.top
= curstate
->pos
.v
;
347 bounds
.bottom
= bounds
.top
+ 16;
348 if (mac_gestalts
.apprvers
>= 0x100) {
352 mc
->text
.tbctrl
= NewControl(window
, &bounds
, NULL
, TRUE
, 0, 0, 0,
353 kControlStaticTextProc
, (long)mc
);
354 SetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
355 kControlStaticTextTextTag
,
356 strlen(ctrl
->text
.label
), ctrl
->text
.label
);
357 GetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
358 kControlStaticTextTextHeightTag
,
359 sizeof(height
), &height
, &olen
);
360 fprintf(stderr
, " height = %d\n", height
);
361 SizeControl(mc
->text
.tbctrl
, curstate
->width
, height
);
362 curstate
->pos
.v
+= height
+ 6;
366 c2pstrcpy(title
, ctrl
->text
.label
);
367 mc
->text
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 0,
368 SYS7_TEXT_PROC
, (long)mc
);
370 add234(mcs
->byctrl
, mc
);
371 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
372 mcs
->panels
[curstate
->panelnum
] = mc
;
375 #if !TARGET_API_MAC_CARBON
376 static pascal SInt32
macctrl_sys7_text_cdef(SInt16 variant
, ControlRef control
,
377 ControlDefProcMessage msg
, SInt32 param
)
383 if ((*control
)->contrlVis
)
384 TETextBox((*control
)->contrlTitle
+ 1, (*control
)->contrlTitle
[0],
385 &(*control
)->contrlRect
, teFlushDefault
);
388 if (param
& (1 << 31)) {
394 rgn
= (RgnHandle
)param
;
395 RectRgn(rgn
, &(*control
)->contrlRect
);
399 rgn
= (RgnHandle
)param
;
408 static void macctrl_editbox(struct macctrls
*mcs
, WindowPtr window
,
409 struct mac_layoutstate
*curstate
,
412 union macctrl
*mc
= smalloc(sizeof *mc
);
415 fprintf(stderr
, " label = %s\n", ctrl
->editbox
.label
);
416 fprintf(stderr
, " percentwidth = %d\n", ctrl
->editbox
.percentwidth
);
417 if (ctrl
->editbox
.password
) fprintf(stderr
, " password\n");
418 if (ctrl
->editbox
.has_list
) fprintf(stderr
, " has list\n");
419 mc
->generic
.type
= MACCTRL_EDITBOX
;
420 mc
->generic
.ctrl
= ctrl
;
421 mc
->generic
.privdata
= NULL
;
422 bounds
.left
= curstate
->pos
.h
;
423 bounds
.right
= bounds
.left
+ curstate
->width
;
424 bounds
.top
= curstate
->pos
.v
;
425 bounds
.bottom
= bounds
.top
+ 22;
426 if (mac_gestalts
.apprvers
>= 0x100) {
427 InsetRect(&bounds
, 2, 2);
428 mc
->text
.tbctrl
= NewControl(window
, &bounds
, NULL
, TRUE
, 0, 0, 0,
429 ctrl
->editbox
.password ?
430 kControlEditTextPasswordProc
:
431 kControlEditTextProc
, (long)mc
);
433 mc
->text
.tbctrl
= NewControl(window
, &bounds
, NULL
, TRUE
, 0, 0, 0,
434 SYS7_EDITBOX_PROC
, (long)mc
);
436 curstate
->pos
.v
+= 28;
437 add234(mcs
->byctrl
, mc
);
438 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
439 mcs
->panels
[curstate
->panelnum
] = mc
;
440 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
443 #if !TARGET_API_MAC_CARBON
444 static pascal SInt32
macctrl_sys7_editbox_cdef(SInt16 variant
,
446 ControlDefProcMessage msg
,
456 rect
= (*control
)->contrlRect
;
457 InsetRect(&rect
, 3, 3); /* 2 if it's 20 pixels high */
458 te
= TENew(&rect
, &rect
);
459 ssfs
= GetScriptVariable(smSystemScript
, smScriptSysFondSize
);
460 (*te
)->txSize
= LoWord(ssfs
);
461 (*te
)->txFont
= HiWord(ssfs
);
462 (*control
)->contrlData
= (Handle
)te
;
465 TEDispose((TEHandle
)(*control
)->contrlData
);
468 if ((*control
)->contrlVis
) {
469 rect
= (*control
)->contrlRect
;
472 InsetRect(&rect
, 3, 3);
473 TEUpdate(&rect
, (TEHandle
)(*control
)->contrlData
);
477 if (param
& (1 << 31)) {
483 rgn
= (RgnHandle
)param
;
484 RectRgn(rgn
, &(*control
)->contrlRect
);
488 rgn
= (RgnHandle
)param
;
497 static void macctrl_radio(struct macctrls
*mcs
, WindowPtr window
,
498 struct mac_layoutstate
*curstate
,
501 union macctrl
*mc
= smalloc(sizeof *mc
);
504 unsigned int i
, colwidth
;
506 fprintf(stderr
, " label = %s\n", ctrl
->radio
.label
);
507 mc
->generic
.type
= MACCTRL_RADIO
;
508 mc
->generic
.ctrl
= ctrl
;
509 mc
->generic
.privdata
= NULL
;
511 smalloc(sizeof(*mc
->radio
.tbctrls
) * ctrl
->radio
.nbuttons
);
512 colwidth
= (curstate
->width
+ 13) / ctrl
->radio
.ncolumns
;
513 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
514 fprintf(stderr
, " button = %s\n", ctrl
->radio
.buttons
[i
]);
515 bounds
.top
= curstate
->pos
.v
- 2;
516 bounds
.bottom
= bounds
.top
+ 18;
517 bounds
.left
= curstate
->pos
.h
+ colwidth
* (i
% ctrl
->radio
.ncolumns
);
518 if (i
== ctrl
->radio
.nbuttons
- 1 ||
519 i
% ctrl
->radio
.ncolumns
== ctrl
->radio
.ncolumns
- 1) {
520 bounds
.right
= curstate
->pos
.h
+ curstate
->width
;
521 curstate
->pos
.v
+= 18;
523 bounds
.right
= bounds
.left
+ colwidth
- 13;
524 c2pstrcpy(title
, ctrl
->radio
.buttons
[i
]);
525 mc
->radio
.tbctrls
[i
] = NewControl(window
, &bounds
, title
, TRUE
,
526 0, 0, 1, radioButProc
, (long)mc
);
528 curstate
->pos
.v
+= 4;
529 add234(mcs
->byctrl
, mc
);
530 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
531 mcs
->panels
[curstate
->panelnum
] = mc
;
532 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
535 static void macctrl_checkbox(struct macctrls
*mcs
, WindowPtr window
,
536 struct mac_layoutstate
*curstate
,
539 union macctrl
*mc
= smalloc(sizeof *mc
);
543 fprintf(stderr
, " label = %s\n", ctrl
->checkbox
.label
);
544 mc
->generic
.type
= MACCTRL_CHECKBOX
;
545 mc
->generic
.ctrl
= ctrl
;
546 mc
->generic
.privdata
= NULL
;
547 bounds
.left
= curstate
->pos
.h
;
548 bounds
.right
= bounds
.left
+ curstate
->width
;
549 bounds
.top
= curstate
->pos
.v
;
550 bounds
.bottom
= bounds
.top
+ 16;
551 c2pstrcpy(title
, ctrl
->checkbox
.label
);
552 mc
->checkbox
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
553 checkBoxProc
, (long)mc
);
554 add234(mcs
->byctrl
, mc
);
555 curstate
->pos
.v
+= 22;
556 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
557 mcs
->panels
[curstate
->panelnum
] = mc
;
558 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
561 static void macctrl_button(struct macctrls
*mcs
, WindowPtr window
,
562 struct mac_layoutstate
*curstate
,
565 union macctrl
*mc
= smalloc(sizeof *mc
);
569 fprintf(stderr
, " label = %s\n", ctrl
->button
.label
);
570 if (ctrl
->button
.isdefault
)
571 fprintf(stderr
, " is default\n");
572 mc
->generic
.type
= MACCTRL_BUTTON
;
573 mc
->generic
.ctrl
= ctrl
;
574 mc
->generic
.privdata
= NULL
;
575 bounds
.left
= curstate
->pos
.h
;
576 bounds
.right
= bounds
.left
+ 100; /* XXX measure string */
577 bounds
.top
= curstate
->pos
.v
;
578 bounds
.bottom
= bounds
.top
+ 20;
579 c2pstrcpy(title
, ctrl
->button
.label
);
580 mc
->button
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
581 pushButProc
, (long)mc
);
582 if (mac_gestalts
.apprvers
>= 0x100) {
583 Boolean isdefault
= ctrl
->button
.isdefault
;
585 SetControlData(mc
->button
.tbctrl
, kControlEntireControl
,
586 kControlPushButtonDefaultTag
,
587 sizeof(isdefault
), &isdefault
);
588 } else if (ctrl
->button
.isdefault
) {
589 InsetRect(&bounds
, -4, -4);
590 NewControl(window
, &bounds
, title
, TRUE
, 0, 0, 1,
591 SYS7_DEFAULT_PROC
, (long)mc
);
593 if (mac_gestalts
.apprvers
>= 0x110) {
594 Boolean iscancel
= ctrl
->button
.iscancel
;
596 SetControlData(mc
->button
.tbctrl
, kControlEntireControl
,
597 kControlPushButtonCancelTag
,
598 sizeof(iscancel
), &iscancel
);
600 add234(mcs
->byctrl
, mc
);
601 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
602 mcs
->panels
[curstate
->panelnum
] = mc
;
603 curstate
->pos
.v
+= 26;
606 #if !TARGET_API_MAC_CARBON
607 static pascal SInt32
macctrl_sys7_default_cdef(SInt16 variant
,
609 ControlDefProcMessage msg
,
618 if ((*control
)->contrlVis
) {
619 rect
= (*control
)->contrlRect
;
622 oval
= (rect
.bottom
- rect
.top
) / 2 + 2;
623 FrameRoundRect(&rect
, oval
, oval
);
627 if (param
& (1 << 31)) {
633 rgn
= (RgnHandle
)param
;
634 RectRgn(rgn
, &(*control
)->contrlRect
);
638 rgn
= (RgnHandle
)param
;
647 static void macctrl_popup(struct macctrls
*mcs
, WindowPtr window
,
648 struct mac_layoutstate
*curstate
,
651 union macctrl
*mc
= smalloc(sizeof *mc
);
654 unsigned int labelwidth
;
655 static int nextmenuid
= MENU_MIN
;
660 * <http://developer.apple.com/qa/tb/tb42.html> explains how to
661 * create a popup menu with dynamic content.
663 assert(ctrl
->listbox
.height
== 0);
664 assert(!ctrl
->listbox
.draglist
);
665 assert(!ctrl
->listbox
.multisel
);
667 fprintf(stderr
, " label = %s\n", ctrl
->listbox
.label
);
668 fprintf(stderr
, " percentwidth = %d\n", ctrl
->listbox
.percentwidth
);
670 mc
->generic
.type
= MACCTRL_POPUP
;
671 mc
->generic
.ctrl
= ctrl
;
672 mc
->generic
.privdata
= NULL
;
673 c2pstrcpy(title
, ctrl
->button
.label
);
675 /* Find a spare menu ID and create the menu */
676 while (GetMenuHandle(nextmenuid
) != NULL
)
677 if (++nextmenuid
>= MENU_MAX
) nextmenuid
= MENU_MIN
;
678 menuid
= nextmenuid
++;
679 menu
= NewMenu(menuid
, "\pdummy");
680 if (menu
== NULL
) return;
681 mc
->popup
.menu
= menu
;
682 mc
->popup
.menuid
= menuid
;
683 InsertMenu(menu
, kInsertHierarchicalMenu
);
685 /* The menu starts off empty */
687 mc
->popup
.ids
= NULL
;
689 bounds
.left
= curstate
->pos
.h
;
690 bounds
.right
= bounds
.left
+ curstate
->width
;
691 bounds
.top
= curstate
->pos
.v
;
692 bounds
.bottom
= bounds
.top
+ 20;
693 /* XXX handle percentwidth == 100 */
694 labelwidth
= curstate
->width
* (100 - ctrl
->listbox
.percentwidth
) / 100;
695 mc
->popup
.tbctrl
= NewControl(window
, &bounds
, title
, TRUE
,
696 popupTitleLeftJust
, menuid
, labelwidth
,
697 popupMenuProc
+ popupFixedWidth
, (long)mc
);
698 add234(mcs
->byctrl
, mc
);
699 curstate
->pos
.v
+= 26;
700 mc
->generic
.next
= mcs
->panels
[curstate
->panelnum
];
701 mcs
->panels
[curstate
->panelnum
] = mc
;
702 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
706 void macctrl_activate(WindowPtr window
, EventRecord
*event
)
708 struct macctrls
*mcs
= mac_winctrls(window
);
709 Boolean active
= (event
->modifiers
& activeFlag
) != 0;
712 ControlPartCode state
;
716 SetPort((GrafPtr
)GetWindowPort(window
));
717 if (mac_gestalts
.apprvers
>= 0x100)
718 SetThemeWindowBackground(window
, active ?
719 kThemeBrushModelessDialogBackgroundActive
:
720 kThemeBrushModelessDialogBackgroundInactive
,
722 state
= active ? kControlNoPart
: kControlInactivePart
;
723 for (i
= 0; i
<= mcs
->curpanel
; i
+= mcs
->curpanel
)
724 for (mc
= mcs
->panels
[i
]; mc
!= NULL
; mc
= mc
->generic
.next
)
725 switch (mc
->generic
.type
) {
727 HiliteControl(mc
->text
.tbctrl
, state
);
729 case MACCTRL_EDITBOX
:
730 HiliteControl(mc
->editbox
.tbctrl
, state
);
733 for (j
= 0; j
< mc
->generic
.ctrl
->radio
.nbuttons
; j
++)
734 HiliteControl(mc
->radio
.tbctrls
[j
], state
);
736 case MACCTRL_CHECKBOX
:
737 HiliteControl(mc
->checkbox
.tbctrl
, state
);
740 HiliteControl(mc
->button
.tbctrl
, state
);
743 HiliteControl(mc
->popup
.tbctrl
, state
);
749 void macctrl_click(WindowPtr window
, EventRecord
*event
)
752 ControlHandle control
;
753 int part
, trackresult
;
756 struct macctrls
*mcs
= mac_winctrls(window
);
761 SetPort((GrafPtr
)GetWindowPort(window
));
762 mouse
= event
->where
;
763 GlobalToLocal(&mouse
);
764 part
= FindControl(mouse
, window
, &control
);
765 if (control
!= NULL
) {
766 if (mac_gestalts
.apprvers
>= 0x100) {
767 if (GetControlFeatures(control
, &features
) == noErr
&&
768 (features
& kControlSupportsFocus
) &&
769 (features
& kControlGetsFocusOnClick
))
770 SetKeyboardFocus(window
, control
, part
);
771 trackresult
= HandleControlClick(control
, mouse
, event
->modifiers
,
772 (ControlActionUPP
)-1);
774 trackresult
= TrackControl(control
, mouse
, (ControlActionUPP
)-1);
775 mc
= (union macctrl
*)GetControlReference(control
);
776 switch (mc
->generic
.type
) {
778 if (trackresult
!= 0) {
779 for (i
= 0; i
< mc
->generic
.ctrl
->radio
.nbuttons
; i
++)
780 if (mc
->radio
.tbctrls
[i
] == control
)
781 SetControlValue(mc
->radio
.tbctrls
[i
],
782 kControlRadioButtonCheckedValue
);
784 SetControlValue(mc
->radio
.tbctrls
[i
],
785 kControlRadioButtonUncheckedValue
);
786 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
789 case MACCTRL_CHECKBOX
:
790 if (trackresult
!= 0) {
791 SetControlValue(control
, !GetControlValue(control
));
792 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
796 if (trackresult
!= 0)
797 ctrlevent(mcs
, mc
, EVENT_ACTION
);
800 ctrlevent(mcs
, mc
, EVENT_SELCHANGE
);
807 void macctrl_key(WindowPtr window
, EventRecord
*event
)
810 struct macctrls
*mcs
= mac_winctrls(window
);
813 if (mac_gestalts
.apprvers
>= 0x100 &&
814 GetKeyboardFocus(window
, &control
) == noErr
&& control
!= NULL
) {
815 HandleControlKey(control
, (event
->message
& keyCodeMask
) >> 8,
816 event
->message
& charCodeMask
, event
->modifiers
);
817 mc
= (union macctrl
*)GetControlReference(control
);
818 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
822 void macctrl_update(WindowPtr window
)
824 #if TARGET_API_MAC_CARBON
832 SetPort((GrafPtr
)GetWindowPort(window
));
833 if (mac_gestalts
.apprvers
>= 0x101) {
834 #if TARGET_API_MAC_CARBON
835 GetPortBounds(GetWindowPort(window
), &rect
);
837 rect
= window
->portRect
;
839 InsetRect(&rect
, -1, -1);
840 DrawThemeModelessDialogFrame(&rect
, mac_frontwindow() == window ?
841 kThemeStateActive
: kThemeStateInactive
);
843 #if TARGET_API_MAC_CARBON
845 GetPortVisibleRegion(GetWindowPort(window
), visrgn
);
846 UpdateControls(window
, visrgn
);
849 UpdateControls(window
, window
->visRgn
);
855 #if TARGET_API_MAC_CARBON
856 #define EnableItem EnableMenuItem
857 #define DisableItem DisableMenuItem
859 void macctrl_adjustmenus(WindowPtr window
)
863 menu
= GetMenuHandle(mFile
);
864 DisableItem(menu
, iSave
); /* XXX enable if modified */
865 EnableItem(menu
, iSaveAs
);
866 EnableItem(menu
, iDuplicate
);
868 menu
= GetMenuHandle(mEdit
);
869 DisableItem(menu
, 0);
872 void macctrl_close(WindowPtr window
)
874 struct macctrls
*mcs
= mac_winctrls(window
);
878 * Mostly, we don't bother disposing of the Toolbox controls,
879 * since that will happen automatically when the window is
880 * disposed of. Popup menus are an exception, because we have to
881 * dispose of the menu ourselves, and doing that while the control
882 * still holds a reference to it seems rude.
884 while ((mc
= index234(mcs
->byctrl
, 0)) != NULL
) {
885 if (mc
->generic
.privdata
!= NULL
&& mc
->generic
.freeprivdata
)
886 sfree(mc
->generic
.privdata
);
887 switch (mc
->generic
.type
) {
889 DisposeControl(mc
->popup
.tbctrl
);
890 DeleteMenu(mc
->popup
.menuid
);
891 DisposeMenu(mc
->popup
.menu
);
894 del234(mcs
->byctrl
, mc
);
898 freetree234(mcs
->byctrl
);
904 void dlg_update_start(union control
*ctrl
, void *dlg
)
910 void dlg_update_done(union control
*ctrl
, void *dlg
)
916 void dlg_set_focus(union control
*ctrl
, void *dlg
)
919 if (mac_gestalts
.apprvers
>= 0x100) {
920 /* Use SetKeyboardFocus() */
922 /* Do our own mucking around */
926 union control
*dlg_last_focused(union control
*ctrl
, void *dlg
)
932 void dlg_beep(void *dlg
)
938 void dlg_error_msg(void *dlg
, char *msg
)
942 c2pstrcpy(pmsg
, msg
);
943 ParamText(pmsg
, NULL
, NULL
, NULL
);
944 StopAlert(128, NULL
);
947 void dlg_end(void *dlg
, int value
)
952 void dlg_refresh(union control
*ctrl
, void *dlg
)
954 struct macctrls
*mcs
= dlg
;
959 mc
= findbyctrl(mcs
, ctrl
);
961 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
964 void *dlg_get_privdata(union control
*ctrl
, void *dlg
)
966 struct macctrls
*mcs
= dlg
;
967 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
970 return mc
->generic
.privdata
;
973 void dlg_set_privdata(union control
*ctrl
, void *dlg
, void *ptr
)
975 struct macctrls
*mcs
= dlg
;
976 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
979 mc
->generic
.privdata
= ptr
;
980 mc
->generic
.freeprivdata
= FALSE
;
983 void *dlg_alloc_privdata(union control
*ctrl
, void *dlg
, size_t size
)
985 struct macctrls
*mcs
= dlg
;
986 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
989 mc
->generic
.privdata
= smalloc(size
);
990 mc
->generic
.freeprivdata
= TRUE
;
991 return mc
->generic
.privdata
;
996 * Radio Button control
999 void dlg_radiobutton_set(union control
*ctrl
, void *dlg
, int whichbutton
)
1001 struct macctrls
*mcs
= dlg
;
1002 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1006 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
1007 if (i
== whichbutton
)
1008 SetControlValue(mc
->radio
.tbctrls
[i
],
1009 kControlRadioButtonCheckedValue
);
1011 SetControlValue(mc
->radio
.tbctrls
[i
],
1012 kControlRadioButtonUncheckedValue
);
1017 int dlg_radiobutton_get(union control
*ctrl
, void *dlg
)
1019 struct macctrls
*mcs
= dlg
;
1020 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1024 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
1025 if (GetControlValue(mc
->radio
.tbctrls
[i
]) ==
1026 kControlRadioButtonCheckedValue
)
1037 void dlg_checkbox_set(union control
*ctrl
, void *dlg
, int checked
)
1039 struct macctrls
*mcs
= dlg
;
1040 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1043 SetControlValue(mc
->checkbox
.tbctrl
,
1044 checked ? kControlCheckBoxCheckedValue
:
1045 kControlCheckBoxUncheckedValue
);
1048 int dlg_checkbox_get(union control
*ctrl
, void *dlg
)
1050 struct macctrls
*mcs
= dlg
;
1051 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1054 return GetControlValue(mc
->checkbox
.tbctrl
);
1062 void dlg_editbox_set(union control
*ctrl
, void *dlg
, char const *text
)
1064 struct macctrls
*mcs
= dlg
;
1065 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1069 assert(mc
->generic
.type
== MACCTRL_EDITBOX
);
1071 SetPort((GrafPtr
)(GetWindowPort(mcs
->window
)));
1072 if (mac_gestalts
.apprvers
>= 0x100)
1073 SetControlData(mc
->editbox
.tbctrl
, kControlEntireControl
,
1074 ctrl
->editbox
.password ?
1075 kControlEditTextPasswordTag
:
1076 kControlEditTextTextTag
,
1077 strlen(text
), text
);
1079 TESetText(text
, strlen(text
),
1080 (TEHandle
)(*mc
->editbox
.tbctrl
)->contrlData
);
1081 DrawOneControl(mc
->editbox
.tbctrl
);
1085 void dlg_editbox_get(union control
*ctrl
, void *dlg
, char *buffer
, int length
)
1087 struct macctrls
*mcs
= dlg
;
1088 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1093 assert(mc
->generic
.type
== MACCTRL_EDITBOX
);
1094 if (mac_gestalts
.apprvers
>= 0x100) {
1095 if (GetControlData(mc
->editbox
.tbctrl
, kControlEntireControl
,
1096 ctrl
->editbox
.password ?
1097 kControlEditTextPasswordTag
:
1098 kControlEditTextTextTag
,
1099 length
- 1, buffer
, &olen
) != noErr
)
1101 if (olen
> length
- 1)
1104 te
= (TEHandle
)(*mc
->editbox
.tbctrl
)->contrlData
;
1105 olen
= (*te
)->teLength
;
1106 if (olen
> length
- 1)
1108 memcpy(buffer
, *(*te
)->hText
, olen
);
1110 buffer
[olen
] = '\0';
1111 fprintf(stderr
, "dlg_editbox_get: %s\n", buffer
);
1119 static void dlg_macpopup_clear(union control
*ctrl
, void *dlg
)
1121 struct macctrls
*mcs
= dlg
;
1122 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1123 MenuRef menu
= mc
->popup
.menu
;
1126 fprintf(stderr
, " popup_clear\n");
1127 n
= CountMenuItems(menu
);
1128 for (i
= 0; i
< n
; i
++)
1129 DeleteMenuItem(menu
, n
- i
);
1131 sfree(mc
->popup
.ids
);
1132 mc
->popup
.ids
= NULL
;
1133 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1136 void dlg_listbox_clear(union control
*ctrl
, void *dlg
)
1139 if (ctrl
->listbox
.height
== 0)
1140 dlg_macpopup_clear(ctrl
, dlg
);
1143 static void dlg_macpopup_del(union control
*ctrl
, void *dlg
, int index
)
1145 struct macctrls
*mcs
= dlg
;
1146 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1147 MenuRef menu
= mc
->popup
.menu
;
1149 fprintf(stderr
, " popup_del %d\n", index
);
1150 DeleteMenuItem(menu
, index
+ 1);
1151 if (mc
->popup
.ids
!= NULL
)
1152 memcpy(mc
->popup
.ids
+ index
, mc
->popup
.ids
+ index
+ 1,
1153 (mc
->popup
.nids
- index
- 1) * sizeof(*mc
->popup
.ids
));
1154 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1157 void dlg_listbox_del(union control
*ctrl
, void *dlg
, int index
)
1160 if (ctrl
->listbox
.height
== 0)
1161 dlg_macpopup_del(ctrl
, dlg
, index
);
1164 static void dlg_macpopup_add(union control
*ctrl
, void *dlg
, char const *text
)
1166 struct macctrls
*mcs
= dlg
;
1167 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1168 MenuRef menu
= mc
->popup
.menu
;
1171 fprintf(stderr
, " popup_add %s\n", text
);
1172 assert(text
[0] != '\0');
1173 c2pstrcpy(itemstring
, text
);
1174 AppendMenu(menu
, "\pdummy");
1175 SetMenuItemText(menu
, CountMenuItems(menu
), itemstring
);
1176 SetControlMaximum(mc
->popup
.tbctrl
, CountMenuItems(menu
));
1179 void dlg_listbox_add(union control
*ctrl
, void *dlg
, char const *text
)
1182 if (ctrl
->listbox
.height
== 0)
1183 dlg_macpopup_add(ctrl
, dlg
, text
);
1186 static void dlg_macpopup_addwithid(union control
*ctrl
, void *dlg
,
1187 char const *text
, int id
)
1189 struct macctrls
*mcs
= dlg
;
1190 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1191 MenuRef menu
= mc
->popup
.menu
;
1194 fprintf(stderr
, " popup_addwthindex %s, %d\n", text
, id
);
1195 dlg_macpopup_add(ctrl
, dlg
, text
);
1196 index
= CountMenuItems(menu
) - 1;
1197 if (mc
->popup
.nids
<= index
) {
1198 mc
->popup
.nids
= index
+ 1;
1199 mc
->popup
.ids
= srealloc(mc
->popup
.ids
,
1200 mc
->popup
.nids
* sizeof(*mc
->popup
.ids
));
1202 mc
->popup
.ids
[index
] = id
;
1205 void dlg_listbox_addwithid(union control
*ctrl
, void *dlg
,
1206 char const *text
, int id
)
1209 if (ctrl
->listbox
.height
== 0)
1210 dlg_macpopup_addwithid(ctrl
, dlg
, text
, id
);
1213 int dlg_listbox_getid(union control
*ctrl
, void *dlg
, int index
)
1215 struct macctrls
*mcs
= dlg
;
1216 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1218 if (ctrl
->listbox
.height
== 0) {
1219 assert(mc
->popup
.ids
!= NULL
&& mc
->popup
.nids
> index
);
1220 return mc
->popup
.ids
[index
];
1225 int dlg_listbox_index(union control
*ctrl
, void *dlg
)
1227 struct macctrls
*mcs
= dlg
;
1228 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1230 if (ctrl
->listbox
.height
== 0)
1231 return GetControlValue(mc
->popup
.tbctrl
) - 1;
1235 int dlg_listbox_issel(union control
*ctrl
, void *dlg
, int index
)
1237 struct macctrls
*mcs
= dlg
;
1238 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1240 if (ctrl
->listbox
.height
== 0)
1241 return GetControlValue(mc
->popup
.tbctrl
) - 1 == index
;
1245 void dlg_listbox_select(union control
*ctrl
, void *dlg
, int index
)
1247 struct macctrls
*mcs
= dlg
;
1248 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1250 if (ctrl
->listbox
.height
== 0)
1251 SetControlValue(mc
->popup
.tbctrl
, index
+ 1);
1259 void dlg_text_set(union control
*ctrl
, void *dlg
, char const *text
)
1261 struct macctrls
*mcs
= dlg
;
1262 union macctrl
*mc
= findbyctrl(mcs
, ctrl
);
1266 if (mac_gestalts
.apprvers
>= 0x100)
1267 SetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
1268 kControlStaticTextTextTag
, strlen(text
), text
);
1270 c2pstrcpy(title
, text
);
1271 SetControlTitle(mc
->text
.tbctrl
, title
);
1277 * File Selector control
1280 void dlg_filesel_set(union control
*ctrl
, void *dlg
, Filename fn
)
1285 void dlg_filesel_get(union control
*ctrl
, void *dlg
, Filename
*fn
)
1292 * Font Selector control
1295 void dlg_fontsel_set(union control
*ctrl
, void *dlg
, FontSpec fn
)
1300 void dlg_fontsel_get(union control
*ctrl
, void *dlg
, FontSpec
*fn
)
1307 * Printer enumeration
1310 printer_enum
*printer_start_enum(int *nprinters
)
1317 char *printer_get_name(printer_enum
*pe
, int thing
)
1323 void printer_finish_enum(printer_enum
*pe
)
1330 * Colour selection stuff
1333 void dlg_coloursel_start(union control
*ctrl
, void *dlg
,
1334 int r
, int g
, int b
)
1339 int dlg_coloursel_results(union control
*ctrl
, void *dlg
,
1340 int *r
, int *g
, int *b
)
1348 * c-file-style: "simon"