1 /* $Id: macctrls.c,v 1.1 2003/03/17 21:40:37 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 <TextUtils.h>
43 struct macctrl_generic
{
50 /* Template from which this was generated */
54 struct macctrl_generic generic
;
58 struct macctrl_generic generic
;
62 struct macctrl_generic generic
;
66 struct macctrl_generic generic
;
71 struct mac_layoutstate
{
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)); \
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
*);
93 static int macctrl_cmp_byctrl(void *av
, void *bv
)
95 union macctrl
*a
= (union macctrl
*)av
;
96 union macctrl
*b
= (union macctrl
*)bv
;
98 if (a
->generic
.ctrl
< b
->generic
.ctrl
)
100 else if (a
->generic
.ctrl
> b
->generic
.ctrl
)
106 void macctrl_layoutbox(struct controlbox
*cb
, WindowPtr window
,
107 struct macctrls
*mcs
)
110 struct mac_layoutstate curstate
;
114 #if TARGET_API_MAC_CARBON
115 GetPortBounds(GetWindowPort(window
), &rect
);
117 rect
= window
->portRect
;
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
);
129 static void macctrl_layoutset(struct mac_layoutstate
*curstate
,
130 struct controlset
*s
,
131 WindowPtr window
, struct macctrls
*mcs
)
135 fprintf(stderr
, "--- begin set ---\n");
136 if (s
->boxname
&& *s
->boxname
)
137 fprintf(stderr
, "boxname = %s\n", s
->boxname
);
139 fprintf(stderr
, "boxtitle = %s\n", s
->boxtitle
);
142 for (i
= 0; i
< s
->ncontrols
; i
++) {
143 union control
*ctrl
= s
->ctrls
[i
];
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;
159 fprintf(stderr
, " control: %s\n", s
);
160 switch (ctrl
->generic
.type
) {
162 macctrl_text(mcs
, window
, curstate
, ctrl
);
165 macctrl_radio(mcs
, window
, curstate
, ctrl
);
168 macctrl_checkbox(mcs
, window
, curstate
, ctrl
);
171 macctrl_button(mcs
, window
, curstate
, ctrl
);
178 static void macctrl_text(struct macctrls
*mcs
, WindowPtr window
,
179 struct mac_layoutstate
*curstate
,
182 union macctrl
*mc
= smalloc(sizeof *mc
);
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) {
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;
208 /* Do something useful */
210 add234(mcs
->byctrl
, mc
);
213 static void macctrl_radio(struct macctrls
*mcs
, WindowPtr window
,
214 struct mac_layoutstate
*curstate
,
217 union macctrl
*mc
= smalloc(sizeof *mc
);
220 unsigned int i
, colwidth
;
222 fprintf(stderr
, " label = %s\n", ctrl
->radio
.label
);
223 mc
->generic
.type
= MACCTRL_RADIO
;
224 mc
->generic
.ctrl
= ctrl
;
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;
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
);
243 add234(mcs
->byctrl
, mc
);
244 ctrlevent(mcs
, mc
, EVENT_REFRESH
);
247 static void macctrl_checkbox(struct macctrls
*mcs
, WindowPtr window
,
248 struct mac_layoutstate
*curstate
,
251 union macctrl
*mc
= smalloc(sizeof *mc
);
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
);
270 static void macctrl_button(struct macctrls
*mcs
, WindowPtr window
,
271 struct mac_layoutstate
*curstate
,
274 union macctrl
*mc
= smalloc(sizeof *mc
);
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
;
293 SetControlData(mc
->button
.tbctrl
, kControlEntireControl
,
294 kControlPushButtonDefaultTag
,
295 sizeof(isdefault
), &isdefault
);
297 add234(mcs
->byctrl
, mc
);
298 curstate
->pos
.v
+= 26;
302 void macctrl_activate(WindowPtr window
, EventRecord
*event
)
304 Boolean active
= (event
->modifiers
& activeFlag
) != 0;
309 SetPort((GrafPtr
)GetWindowPort(window
));
310 if (mac_gestalts
.apprvers
>= 0x100) {
311 SetThemeWindowBackground(window
, active ?
312 kThemeBrushModelessDialogBackgroundActive
:
313 kThemeBrushModelessDialogBackgroundInactive
,
315 GetRootControl(window
, &root
);
317 ActivateControl(root
);
319 DeactivateControl(root
);
321 /* (De)activate controls one at a time */
326 void macctrl_click(WindowPtr window
, EventRecord
*event
)
329 ControlHandle control
;
333 struct macctrls
*mcs
= mac_winctrls(window
);
337 SetPort((GrafPtr
)GetWindowPort(window
));
338 mouse
= event
->where
;
339 GlobalToLocal(&mouse
);
340 part
= FindControl(mouse
, window
, &control
);
342 if (TrackControl(control
, mouse
, NULL
) != 0) {
343 mc
= (union macctrl
*)GetControlReference(control
);
344 switch (mc
->generic
.type
) {
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
);
351 SetControlValue(mc
->radio
.tbctrls
[i
],
352 kControlRadioButtonUncheckedValue
);
354 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
356 case MACCTRL_CHECKBOX
:
357 SetControlValue(control
, !GetControlValue(control
));
358 ctrlevent(mcs
, mc
, EVENT_VALCHANGE
);
361 ctrlevent(mcs
, mc
, EVENT_ACTION
);
368 void macctrl_update(WindowPtr window
)
370 #if TARGET_API_MAC_CARBON
378 SetPort((GrafPtr
)GetWindowPort(window
));
379 if (mac_gestalts
.apprvers
>= 0x101) {
380 #if TARGET_API_MAC_CARBON
381 GetPortBounds(GetWindowPort(window
), &rect
);
383 rect
= window
->portRect
;
385 InsetRect(&rect
, -1, -1);
386 DrawThemeModelessDialogFrame(&rect
, mac_frontwindow() == window ?
387 kThemeStateActive
: kThemeStateInactive
);
389 #if TARGET_API_MAC_CARBON
391 GetPortVisibleRegion(GetWindowPort(window
), visrgn
);
392 UpdateControls(window
, visrgn
);
395 UpdateControls(window
, window
->visRgn
);
401 #if TARGET_API_MAC_CARBON
402 #define EnableItem EnableMenuItem
403 #define DisableItem DisableMenuItem
405 void macctrl_adjustmenus(WindowPtr window
)
409 menu
= GetMenuHandle(mFile
);
410 DisableItem(menu
, iSave
); /* XXX enable if modified */
411 EnableItem(menu
, iSaveAs
);
412 EnableItem(menu
, iDuplicate
);
414 menu
= GetMenuHandle(mEdit
);
415 DisableItem(menu
, 0);
418 void macctrl_close(WindowPtr window
)
420 struct macctrls
*mcs
= mac_winctrls(window
);
423 while ((mc
= index234(mcs
->byctrl
, 0)) != NULL
) {
424 del234(mcs
->byctrl
, mc
);
428 freetree234(mcs
->byctrl
);
432 DisposeWindow(window);
433 if (s->window == NULL)
438 void dlg_update_start(union control
*ctrl
, void *dlg
)
444 void dlg_update_done(union control
*ctrl
, void *dlg
)
450 void dlg_set_focus(union control
*ctrl
, void *dlg
)
453 if (mac_gestalts
.apprvers
>= 0x100) {
454 /* Use SetKeyboardFocus() */
456 /* Do our own mucking around */
460 union control
*dlg_last_focused(void *dlg
)
466 void dlg_beep(void *dlg
)
472 void dlg_error_msg(void *dlg
, char *msg
)
476 c2pstrcpy(pmsg
, msg
);
477 ParamText(pmsg
, NULL
, NULL
, NULL
);
478 StopAlert(128, NULL
);
481 void dlg_end(void *dlg
, int value
)
486 void dlg_refresh(union control
*ctrl
, void *dlg
)
491 void *dlg_get_privdata(union control
*ctrl
, void *dlg
)
497 void dlg_set_privdata(union control
*ctrl
, void *dlg
, void *ptr
)
500 fatalbox("dlg_set_privdata");
503 void *dlg_alloc_privdata(union control
*ctrl
, void *dlg
, size_t size
)
506 fatalbox("dlg_alloc_privdata");
511 * Radio Button control
514 void dlg_radiobutton_set(union control
*ctrl
, void *dlg
, int whichbutton
)
516 union macctrl
*mc
= dlg
;
519 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
520 if (i
== whichbutton
)
521 SetControlValue(mc
->radio
.tbctrls
[i
],
522 kControlRadioButtonCheckedValue
);
524 SetControlValue(mc
->radio
.tbctrls
[i
],
525 kControlRadioButtonUncheckedValue
);
530 int dlg_radiobutton_get(union control
*ctrl
, void *dlg
)
532 union macctrl
*mc
= dlg
;
535 for (i
= 0; i
< ctrl
->radio
.nbuttons
; i
++) {
536 if (GetControlValue(mc
->radio
.tbctrls
[i
]) ==
537 kControlRadioButtonCheckedValue
)
548 void dlg_checkbox_set(union control
*ctrl
, void *dlg
, int checked
)
550 union macctrl
*mc
= dlg
;
552 SetControlValue(mc
->checkbox
.tbctrl
,
553 checked ? kControlCheckBoxCheckedValue
:
554 kControlCheckBoxUncheckedValue
);
557 int dlg_checkbox_get(union control
*ctrl
, void *dlg
)
559 union macctrl
*mc
= dlg
;
561 return GetControlValue(mc
->checkbox
.tbctrl
);
569 void dlg_editbox_set(union control
*ctrl
, void *dlg
, char const *text
)
574 void dlg_editbox_get(union control
*ctrl
, void *dlg
, char *buffer
, int length
)
584 void dlg_listbox_clear(union control
*ctrl
, void *dlg
)
589 void dlg_listbox_del(union control
*ctrl
, void *dlg
, int index
)
594 void dlg_listbox_add(union control
*ctrl
, void *dlg
, char const *text
)
599 void dlg_listbox_addwithindex(union control
*ctrl
, void *dlg
,
600 char const *text
, int id
)
605 int dlg_listbox_getid(union control
*ctrl
, void *dlg
, int index
)
611 int dlg_listbox_index(union control
*ctrl
, void *dlg
)
617 int dlg_listbox_issel(union control
*ctrl
, void *dlg
, int index
)
623 void dlg_listbox_select(union control
*ctrl
, void *dlg
, int index
)
633 void dlg_text_set(union control
*ctrl
, void *dlg
, char const *text
)
635 union macctrl
*mc
= dlg
;
637 if (mac_gestalts
.apprvers
>= 0x100)
638 SetControlData(mc
->text
.tbctrl
, kControlEntireControl
,
639 kControlStaticTextTextTag
,
640 strlen(ctrl
->text
.label
), ctrl
->text
.label
);
645 * File Selector control
648 void dlg_filesel_set(union control
*ctrl
, void *dlg
, Filename fn
)
653 void dlg_filesel_get(union control
*ctrl
, void *dlg
, Filename
*fn
)
660 * Font Selector control
663 void dlg_fontsel_set(union control
*ctrl
, void *dlg
, FontSpec fn
)
668 void dlg_fontsel_get(union control
*ctrl
, void *dlg
, FontSpec
*fn
)
675 * Printer enumeration
678 printer_enum
*printer_start_enum(int *nprinters
)
685 char *printer_get_name(printer_enum
*pe
, int thing
)
691 void printer_finish_enum(printer_enum
*pe
)
698 * Colour selection stuff
701 void dlg_coloursel_start(union control
*ctrl
, void *dlg
,
707 int dlg_coloursel_results(union control
*ctrl
, void *dlg
,
708 int *r
, int *g
, int *b
)
716 * c-file-style: "simon"