Cope with NULL labels in every control where it makes sense, and assert that
[u/mdw/putty] / mac / macctrls.c
1 /* $Id: macctrls.c,v 1.27 2003/04/05 15:55:22 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 <Menus.h>
33 #include <Resources.h>
34 #include <Script.h>
35 #include <Sound.h>
36 #include <TextEdit.h>
37 #include <TextUtils.h>
38 #include <ToolUtils.h>
39 #include <Windows.h>
40
41 #include <assert.h>
42 #include <string.h>
43
44 #include "putty.h"
45 #include "mac.h"
46 #include "macresid.h"
47 #include "dialog.h"
48 #include "tree234.h"
49
50 /* Range of menu IDs for popup menus */
51 #define MENU_MIN 1024
52 #define MENU_MAX 2048
53
54
55 union macctrl {
56 struct macctrl_generic {
57 enum {
58 MACCTRL_TEXT,
59 MACCTRL_EDITBOX,
60 MACCTRL_RADIO,
61 MACCTRL_CHECKBOX,
62 MACCTRL_BUTTON,
63 MACCTRL_POPUP
64 } type;
65 /* Template from which this was generated */
66 union control *ctrl;
67 /* Next control in this panel */
68 union macctrl *next;
69 void *privdata;
70 int freeprivdata;
71 } generic;
72 struct {
73 struct macctrl_generic generic;
74 ControlRef tbctrl;
75 } text;
76 struct {
77 struct macctrl_generic generic;
78 ControlRef tbctrl;
79 ControlRef tblabel;
80 } editbox;
81 struct {
82 struct macctrl_generic generic;
83 ControlRef *tbctrls;
84 ControlRef tblabel;
85 } radio;
86 struct {
87 struct macctrl_generic generic;
88 ControlRef tbctrl;
89 } checkbox;
90 struct {
91 struct macctrl_generic generic;
92 ControlRef tbctrl;
93 } button;
94 struct {
95 struct macctrl_generic generic;
96 ControlRef tbctrl;
97 MenuRef menu;
98 int menuid;
99 unsigned int nids;
100 int *ids;
101 } popup;
102 };
103
104 struct mac_layoutstate {
105 Point pos;
106 unsigned int width;
107 unsigned int panelnum;
108 };
109
110 #define ctrlevent(mcs, mc, event) do { \
111 if ((mc)->generic.ctrl->generic.handler != NULL) \
112 (*(mc)->generic.ctrl->generic.handler)((mc)->generic.ctrl, (mcs),\
113 (mcs)->data, (event)); \
114 } while (0)
115
116 #define findbyctrl(mcs, ctrl) \
117 find234((mcs)->byctrl, (ctrl), macctrl_cmp_byctrl_find)
118
119 static void macctrl_layoutset(struct mac_layoutstate *, struct controlset *,
120 WindowPtr, struct macctrls *);
121 static void macctrl_switchtopanel(struct macctrls *, unsigned int);
122 static void macctrl_setfocus(struct macctrls *, union macctrl *);
123 static void macctrl_text(struct macctrls *, WindowPtr,
124 struct mac_layoutstate *, union control *);
125 static void macctrl_editbox(struct macctrls *, WindowPtr,
126 struct mac_layoutstate *, union control *);
127 static void macctrl_radio(struct macctrls *, WindowPtr,
128 struct mac_layoutstate *, union control *);
129 static void macctrl_checkbox(struct macctrls *, WindowPtr,
130 struct mac_layoutstate *, union control *);
131 static void macctrl_button(struct macctrls *, WindowPtr,
132 struct mac_layoutstate *, union control *);
133 static void macctrl_popup(struct macctrls *, WindowPtr,
134 struct mac_layoutstate *, union control *);
135 #if !TARGET_API_MAC_CARBON
136 static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16, ControlRef,
137 ControlDefProcMessage, SInt32);
138 static pascal SInt32 macctrl_sys7_default_cdef(SInt16, ControlRef,
139 ControlDefProcMessage, SInt32);
140 #endif
141
142 #if !TARGET_API_MAC_CARBON
143 /*
144 * This trick enables us to keep all the CDEF code in the main
145 * application, which makes life easier. For details, see
146 * <http://developer.apple.com/technotes/tn/tn2003.html#custom_code_base>.
147 */
148
149 #pragma options align=mac68k
150 typedef struct {
151 short jmpabs; /* 4EF9 */
152 ControlDefUPP theUPP;
153 } **PatchCDEF;
154 #pragma options align=reset
155 #endif
156
157 static void macctrl_init()
158 {
159 #if !TARGET_API_MAC_CARBON
160 static int inited = 0;
161 PatchCDEF cdef;
162
163 if (inited) return;
164 cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_EditBox);
165 (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_editbox_cdef);
166 cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_Default);
167 (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_default_cdef);
168 inited = 1;
169 #endif
170 }
171
172
173 static int macctrl_cmp_byctrl(void *av, void *bv)
174 {
175 union macctrl *a = (union macctrl *)av;
176 union macctrl *b = (union macctrl *)bv;
177
178 if (a->generic.ctrl < b->generic.ctrl)
179 return -1;
180 else if (a->generic.ctrl > b->generic.ctrl)
181 return +1;
182 else
183 return 0;
184 }
185
186 static int macctrl_cmp_byctrl_find(void *av, void *bv)
187 {
188 union control *a = (union control *)av;
189 union macctrl *b = (union macctrl *)bv;
190
191 if (a < b->generic.ctrl)
192 return -1;
193 else if (a > b->generic.ctrl)
194 return +1;
195 else
196 return 0;
197 }
198
199 void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
200 struct macctrls *mcs)
201 {
202 int i;
203 struct mac_layoutstate curstate;
204 ControlRef root;
205 Rect rect;
206
207 macctrl_init();
208 #if TARGET_API_MAC_CARBON
209 GetPortBounds(GetWindowPort(window), &rect);
210 #else
211 rect = window->portRect;
212 #endif
213 curstate.pos.h = rect.left + 13;
214 curstate.pos.v = rect.bottom - 33;
215 curstate.width = rect.right - rect.left - (13 * 2);
216 if (mac_gestalts.apprvers >= 0x100)
217 CreateRootControl(window, &root);
218 mcs->window = window;
219 mcs->byctrl = newtree234(macctrl_cmp_byctrl);
220 mcs->focus = NULL;
221 /* Count the number of panels */
222 mcs->npanels = 1;
223 for (i = 1; i < cb->nctrlsets; i++)
224 if (strcmp(cb->ctrlsets[i]->pathname, cb->ctrlsets[i-1]->pathname))
225 mcs->npanels++;
226 mcs->panels = snewn(mcs->npanels, union macctrl *);
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;
233 curstate.panelnum++;
234 assert(curstate.panelnum < mcs->npanels);
235 }
236 macctrl_layoutset(&curstate, cb->ctrlsets[i], window, mcs);
237 }
238 macctrl_switchtopanel(mcs, 1);
239 /* 14 = proxies, 20 = SSH bugs */
240 }
241
242 #define MAXCOLS 16
243
244 static void macctrl_layoutset(struct mac_layoutstate *curstate,
245 struct controlset *s,
246 WindowPtr window, struct macctrls *mcs)
247 {
248 unsigned int i, j, ncols, colstart;
249 struct mac_layoutstate cols[MAXCOLS];
250
251 fprintf(stderr, "--- begin set ---\n");
252 fprintf(stderr, "pathname = %s\n", s->pathname);
253 if (s->boxname && *s->boxname)
254 fprintf(stderr, "boxname = %s\n", s->boxname);
255 if (s->boxtitle)
256 fprintf(stderr, "boxtitle = %s\n", s->boxtitle);
257
258 cols[0] = *curstate;
259 ncols = 1;
260
261 for (i = 0; i < s->ncontrols; i++) {
262 union control *ctrl = s->ctrls[i];
263 char const *s;
264
265 colstart = COLUMN_START(ctrl->generic.column);
266 switch (ctrl->generic.type) {
267 case CTRL_TEXT: s = "text"; break;
268 case CTRL_EDITBOX: s = "editbox"; break;
269 case CTRL_RADIO: s = "radio"; break;
270 case CTRL_CHECKBOX: s = "checkbox"; break;
271 case CTRL_BUTTON: s = "button"; break;
272 case CTRL_LISTBOX: s = "listbox"; break;
273 case CTRL_COLUMNS: s = "columns"; break;
274 case CTRL_FILESELECT: s = "fileselect"; break;
275 case CTRL_FONTSELECT: s = "fontselect"; break;
276 case CTRL_TABDELAY: s = "tabdelay"; break;
277 default: s = "unknown"; break;
278 }
279 fprintf(stderr, " control: %s\n", s);
280 switch (ctrl->generic.type) {
281 case CTRL_COLUMNS:
282 if (ctrl->columns.ncols != 1) {
283 ncols = ctrl->columns.ncols;
284 fprintf(stderr, " split to %d\n", ncols);
285 assert(ncols <= MAXCOLS);
286 for (j = 0; j < ncols; j++) {
287 cols[j] = cols[0];
288 if (j > 0)
289 cols[j].pos.h = cols[j-1].pos.h + cols[j-1].width + 6;
290 if (j == ncols - 1)
291 cols[j].width = curstate->width -
292 (cols[j].pos.h - curstate->pos.h);
293 else
294 cols[j].width = (curstate->width + 6) *
295 ctrl->columns.percentages[j] / 100 - 6;
296 }
297 } else {
298 fprintf(stderr, " join\n");
299 for (j = 0; j < ncols; j++)
300 if (cols[j].pos.v > cols[0].pos.v)
301 cols[0].pos.v = cols[j].pos.v;
302 cols[0].width = curstate->width;
303 ncols = 1;
304 }
305 break;
306 case CTRL_TEXT:
307 macctrl_text(mcs, window, &cols[colstart], ctrl);
308 break;
309 case CTRL_EDITBOX:
310 macctrl_editbox(mcs, window, &cols[colstart], ctrl);
311 break;
312 case CTRL_RADIO:
313 macctrl_radio(mcs, window, &cols[colstart], ctrl);
314 break;
315 case CTRL_CHECKBOX:
316 macctrl_checkbox(mcs, window, &cols[colstart], ctrl);
317 break;
318 case CTRL_BUTTON:
319 macctrl_button(mcs, window, &cols[colstart], ctrl);
320 break;
321 case CTRL_LISTBOX:
322 if (ctrl->listbox.height == 0)
323 macctrl_popup(mcs, window, &cols[colstart], ctrl);
324 break;
325 }
326 }
327 for (j = 0; j < ncols; j++)
328 if (cols[j].pos.v > curstate->pos.v)
329 curstate->pos.v = cols[j].pos.v;
330 }
331
332 static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
333 {
334 unsigned int i, j;
335 union macctrl *mc;
336
337 #define hideshow(c) do { \
338 if (i == which) ShowControl(c); else HideControl(c); \
339 } while (0)
340
341 mcs->curpanel = which;
342 /* Panel 0 is special and always visible. */
343 for (i = 1; i < mcs->npanels; i++)
344 for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
345 #if !TARGET_API_MAC_CARBON
346 if (mcs->focus == mc)
347 macctrl_setfocus(mcs, NULL);
348 #endif
349 switch (mc->generic.type) {
350 case MACCTRL_TEXT:
351 hideshow(mc->text.tbctrl);
352 break;
353 case MACCTRL_EDITBOX:
354 hideshow(mc->editbox.tbctrl);
355 if (mc->editbox.tblabel != NULL)
356 hideshow(mc->editbox.tblabel);
357 break;
358 case MACCTRL_RADIO:
359 for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
360 hideshow(mc->radio.tbctrls[j]);
361 if (mc->radio.tblabel != NULL)
362 hideshow(mc->radio.tblabel);
363 break;
364 case MACCTRL_CHECKBOX:
365 hideshow(mc->checkbox.tbctrl);
366 break;
367 case MACCTRL_BUTTON:
368 hideshow(mc->button.tbctrl);
369 break;
370 case MACCTRL_POPUP:
371 hideshow(mc->popup.tbctrl);
372 break;
373 }
374 }
375 }
376
377 #if !TARGET_API_MAC_CARBON
378 /*
379 * System 7 focus manipulation
380 */
381 static void macctrl_defocus(union macctrl *mc)
382 {
383
384 assert(mac_gestalts.apprvers < 0x100);
385 switch (mc->generic.type) {
386 case MACCTRL_EDITBOX:
387 TEDeactivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
388 break;
389 }
390 }
391
392 static void macctrl_enfocus(union macctrl *mc)
393 {
394
395 assert(mac_gestalts.apprvers < 0x100);
396 switch (mc->generic.type) {
397 case MACCTRL_EDITBOX:
398 TEActivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
399 break;
400 }
401 }
402
403 static void macctrl_setfocus(struct macctrls *mcs, union macctrl *mc)
404 {
405
406 if (mcs->focus != NULL)
407 macctrl_defocus(mcs->focus);
408 mcs->focus = mc;
409 if (mc != NULL)
410 macctrl_enfocus(mc);
411 }
412 #endif
413
414 static void macctrl_text(struct macctrls *mcs, WindowPtr window,
415 struct mac_layoutstate *curstate,
416 union control *ctrl)
417 {
418 union macctrl *mc = snew(union macctrl);
419 Rect bounds;
420 SInt16 height;
421
422 assert(ctrl->text.label != NULL);
423 fprintf(stderr, " label = %s\n", ctrl->text.label);
424 mc->generic.type = MACCTRL_TEXT;
425 mc->generic.ctrl = ctrl;
426 mc->generic.privdata = NULL;
427 bounds.left = curstate->pos.h;
428 bounds.right = bounds.left + curstate->width;
429 bounds.top = curstate->pos.v;
430 bounds.bottom = bounds.top + 16;
431 if (mac_gestalts.apprvers >= 0x100) {
432 Size olen;
433
434 mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
435 kControlStaticTextProc, (long)mc);
436 SetControlData(mc->text.tbctrl, kControlEntireControl,
437 kControlStaticTextTextTag,
438 strlen(ctrl->text.label), ctrl->text.label);
439 GetControlData(mc->text.tbctrl, kControlEntireControl,
440 kControlStaticTextTextHeightTag,
441 sizeof(height), &height, &olen);
442 }
443 #if !TARGET_API_MAC_CARBON
444 else {
445 TEHandle te;
446
447 mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
448 SYS7_TEXT_PROC, (long)mc);
449 te = (TEHandle)(*mc->text.tbctrl)->contrlData;
450 TESetText(ctrl->text.label, strlen(ctrl->text.label), te);
451 height = TEGetHeight(1, (*te)->nLines, te);
452 }
453 #endif
454 fprintf(stderr, " height = %d\n", height);
455 SizeControl(mc->text.tbctrl, curstate->width, height);
456 curstate->pos.v += height + 6;
457 add234(mcs->byctrl, mc);
458 mc->generic.next = mcs->panels[curstate->panelnum];
459 mcs->panels[curstate->panelnum] = mc;
460 }
461
462 static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
463 struct mac_layoutstate *curstate,
464 union control *ctrl)
465 {
466 union macctrl *mc = snew(union macctrl);
467 Rect lbounds, bounds;
468
469 if (ctrl->editbox.label != NULL)
470 fprintf(stderr, " label = %s\n", ctrl->editbox.label);
471 fprintf(stderr, " percentwidth = %d\n", ctrl->editbox.percentwidth);
472 if (ctrl->editbox.password) fprintf(stderr, " password\n");
473 if (ctrl->editbox.has_list) fprintf(stderr, " has list\n");
474 mc->generic.type = MACCTRL_EDITBOX;
475 mc->generic.ctrl = ctrl;
476 mc->generic.privdata = NULL;
477 lbounds.left = curstate->pos.h;
478 lbounds.top = curstate->pos.v;
479 if (ctrl->editbox.percentwidth == 100) {
480 if (ctrl->editbox.label != NULL) {
481 lbounds.right = lbounds.left + curstate->width;
482 lbounds.bottom = lbounds.top + 16;
483 curstate->pos.v += 18;
484 }
485 bounds.left = curstate->pos.h;
486 bounds.right = bounds.left + curstate->width;
487 } else {
488 lbounds.right = lbounds.left +
489 curstate->width * (100 - ctrl->editbox.percentwidth) / 100;
490 lbounds.bottom = lbounds.top + 22;
491 bounds.left = lbounds.right;
492 bounds.right = lbounds.left + curstate->width;
493 }
494 bounds.top = curstate->pos.v;
495 bounds.bottom = bounds.top + 22;
496 if (mac_gestalts.apprvers >= 0x100) {
497 if (ctrl->editbox.label == NULL)
498 mc->editbox.tblabel = NULL;
499 else {
500 mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
501 0, 0, 0, kControlStaticTextProc,
502 (long)mc);
503 SetControlData(mc->editbox.tblabel, kControlEntireControl,
504 kControlStaticTextTextTag,
505 strlen(ctrl->editbox.label), ctrl->editbox.label);
506 }
507 InsetRect(&bounds, 3, 3);
508 mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
509 ctrl->editbox.password ?
510 kControlEditTextPasswordProc :
511 kControlEditTextProc, (long)mc);
512 }
513 #if !TARGET_API_MAC_CARBON
514 else {
515 if (ctrl->editbox.label == NULL)
516 mc->editbox.tblabel = NULL;
517 else {
518 mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
519 0, 0, 0, SYS7_TEXT_PROC,
520 (long)mc);
521 TESetText(ctrl->editbox.label, strlen(ctrl->editbox.label),
522 (TEHandle)(*mc->editbox.tblabel)->contrlData);
523 }
524 mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
525 SYS7_EDITBOX_PROC, (long)mc);
526 }
527 #endif
528 curstate->pos.v += 28;
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);
533 }
534
535 #if !TARGET_API_MAC_CARBON
536 static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
537 ControlRef control,
538 ControlDefProcMessage msg,
539 SInt32 param)
540 {
541 RgnHandle rgn;
542 Rect rect;
543 TEHandle te;
544 long ssfs;
545 Point mouse;
546
547 switch (msg) {
548 case initCntl:
549 rect = (*control)->contrlRect;
550 if (variant == SYS7_EDITBOX_VARIANT)
551 InsetRect(&rect, 3, 3); /* 2 if it's 20 pixels high */
552 te = TENew(&rect, &rect);
553 ssfs = GetScriptVariable(smSystemScript, smScriptSysFondSize);
554 (*te)->txSize = LoWord(ssfs);
555 (*te)->txFont = HiWord(ssfs);
556 (*control)->contrlData = (Handle)te;
557 return noErr;
558 case dispCntl:
559 TEDispose((TEHandle)(*control)->contrlData);
560 return 0;
561 case drawCntl:
562 if ((*control)->contrlVis) {
563 rect = (*control)->contrlRect;
564 if (variant == SYS7_EDITBOX_VARIANT) {
565 PenNormal();
566 FrameRect(&rect);
567 InsetRect(&rect, 3, 3);
568 }
569 (*(TEHandle)(*control)->contrlData)->viewRect = rect;
570 TEUpdate(&rect, (TEHandle)(*control)->contrlData);
571 }
572 return 0;
573 case testCntl:
574 if (variant == SYS7_TEXT_VARIANT)
575 return kControlNoPart;
576 mouse.h = LoWord(param);
577 mouse.v = HiWord(param);
578 rect = (*control)->contrlRect;
579 InsetRect(&rect, 3, 3);
580 return PtInRect(mouse, &rect) ? kControlEditTextPart : kControlNoPart;
581 case calcCRgns:
582 if (param & (1 << 31)) {
583 param &= ~(1 << 31);
584 goto calcthumbrgn;
585 }
586 /* FALLTHROUGH */
587 case calcCntlRgn:
588 rgn = (RgnHandle)param;
589 RectRgn(rgn, &(*control)->contrlRect);
590 return 0;
591 case calcThumbRgn:
592 calcthumbrgn:
593 rgn = (RgnHandle)param;
594 SetEmptyRgn(rgn);
595 return 0;
596 }
597
598 return 0;
599 }
600 #endif
601
602 static void macctrl_radio(struct macctrls *mcs, WindowPtr window,
603 struct mac_layoutstate *curstate,
604 union control *ctrl)
605 {
606 union macctrl *mc = snew(union macctrl);
607 Rect bounds;
608 Str255 title;
609 unsigned int i, colwidth;
610
611 if (ctrl->radio.label != NULL)
612 fprintf(stderr, " label = %s\n", ctrl->radio.label);
613 mc->generic.type = MACCTRL_RADIO;
614 mc->generic.ctrl = ctrl;
615 mc->generic.privdata = NULL;
616 mc->radio.tbctrls = snewn(ctrl->radio.nbuttons, ControlRef);
617 colwidth = (curstate->width + 13) / ctrl->radio.ncolumns;
618 bounds.top = curstate->pos.v;
619 bounds.bottom = bounds.top + 16;
620 bounds.left = curstate->pos.h;
621 bounds.right = bounds.left + curstate->width;
622 if (ctrl->radio.label == NULL)
623 mc->radio.tblabel = NULL;
624 else {
625 if (mac_gestalts.apprvers >= 0x100) {
626 mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
627 0, 0, 0, kControlStaticTextProc,
628 (long)mc);
629 SetControlData(mc->radio.tblabel, kControlEntireControl,
630 kControlStaticTextTextTag,
631 strlen(ctrl->radio.label), ctrl->radio.label);
632 }
633 #if !TARGET_API_MAC_CARBON
634 else {
635 mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
636 0, 0, 0, SYS7_TEXT_PROC, (long)mc);
637 TESetText(ctrl->radio.label, strlen(ctrl->radio.label),
638 (TEHandle)(*mc->radio.tblabel)->contrlData);
639 }
640 #endif
641 curstate->pos.v += 18;
642 }
643 for (i = 0; i < ctrl->radio.nbuttons; i++) {
644 fprintf(stderr, " button = %s\n", ctrl->radio.buttons[i]);
645 bounds.top = curstate->pos.v - 2;
646 bounds.bottom = bounds.top + 18;
647 bounds.left = curstate->pos.h + colwidth * (i % ctrl->radio.ncolumns);
648 if (i == ctrl->radio.nbuttons - 1 ||
649 i % ctrl->radio.ncolumns == ctrl->radio.ncolumns - 1) {
650 bounds.right = curstate->pos.h + curstate->width;
651 curstate->pos.v += 18;
652 } else
653 bounds.right = bounds.left + colwidth - 13;
654 c2pstrcpy(title, ctrl->radio.buttons[i]);
655 mc->radio.tbctrls[i] = NewControl(window, &bounds, title, TRUE,
656 0, 0, 1, radioButProc, (long)mc);
657 }
658 curstate->pos.v += 4;
659 add234(mcs->byctrl, mc);
660 mc->generic.next = mcs->panels[curstate->panelnum];
661 mcs->panels[curstate->panelnum] = mc;
662 ctrlevent(mcs, mc, EVENT_REFRESH);
663 }
664
665 static void macctrl_checkbox(struct macctrls *mcs, WindowPtr window,
666 struct mac_layoutstate *curstate,
667 union control *ctrl)
668 {
669 union macctrl *mc = snew(union macctrl);
670 Rect bounds;
671 Str255 title;
672
673 assert(ctrl->checkbox.label != NULL);
674 fprintf(stderr, " label = %s\n", ctrl->checkbox.label);
675 mc->generic.type = MACCTRL_CHECKBOX;
676 mc->generic.ctrl = ctrl;
677 mc->generic.privdata = NULL;
678 bounds.left = curstate->pos.h;
679 bounds.right = bounds.left + curstate->width;
680 bounds.top = curstate->pos.v;
681 bounds.bottom = bounds.top + 16;
682 c2pstrcpy(title, ctrl->checkbox.label);
683 mc->checkbox.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
684 checkBoxProc, (long)mc);
685 add234(mcs->byctrl, mc);
686 curstate->pos.v += 22;
687 mc->generic.next = mcs->panels[curstate->panelnum];
688 mcs->panels[curstate->panelnum] = mc;
689 ctrlevent(mcs, mc, EVENT_REFRESH);
690 }
691
692 static void macctrl_button(struct macctrls *mcs, WindowPtr window,
693 struct mac_layoutstate *curstate,
694 union control *ctrl)
695 {
696 union macctrl *mc = snew(union macctrl);
697 Rect bounds;
698 Str255 title;
699
700 assert(ctrl->button.label != NULL);
701 fprintf(stderr, " label = %s\n", ctrl->button.label);
702 if (ctrl->button.isdefault)
703 fprintf(stderr, " is default\n");
704 mc->generic.type = MACCTRL_BUTTON;
705 mc->generic.ctrl = ctrl;
706 mc->generic.privdata = NULL;
707 bounds.left = curstate->pos.h;
708 bounds.right = bounds.left + curstate->width;
709 bounds.top = curstate->pos.v;
710 bounds.bottom = bounds.top + 20;
711 c2pstrcpy(title, ctrl->button.label);
712 mc->button.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
713 pushButProc, (long)mc);
714 if (mac_gestalts.apprvers >= 0x100) {
715 Boolean isdefault = ctrl->button.isdefault;
716
717 SetControlData(mc->button.tbctrl, kControlEntireControl,
718 kControlPushButtonDefaultTag,
719 sizeof(isdefault), &isdefault);
720 } else if (ctrl->button.isdefault) {
721 InsetRect(&bounds, -4, -4);
722 NewControl(window, &bounds, title, TRUE, 0, 0, 1,
723 SYS7_DEFAULT_PROC, (long)mc);
724 }
725 if (mac_gestalts.apprvers >= 0x110) {
726 Boolean iscancel = ctrl->button.iscancel;
727
728 SetControlData(mc->button.tbctrl, kControlEntireControl,
729 kControlPushButtonCancelTag,
730 sizeof(iscancel), &iscancel);
731 }
732 add234(mcs->byctrl, mc);
733 mc->generic.next = mcs->panels[curstate->panelnum];
734 mcs->panels[curstate->panelnum] = mc;
735 curstate->pos.v += 26;
736 }
737
738 #if !TARGET_API_MAC_CARBON
739 static pascal SInt32 macctrl_sys7_default_cdef(SInt16 variant,
740 ControlRef control,
741 ControlDefProcMessage msg,
742 SInt32 param)
743 {
744 RgnHandle rgn;
745 Rect rect;
746 int oval;
747
748 switch (msg) {
749 case drawCntl:
750 if ((*control)->contrlVis) {
751 rect = (*control)->contrlRect;
752 PenNormal();
753 PenSize(3, 3);
754 oval = (rect.bottom - rect.top) / 2 + 2;
755 FrameRoundRect(&rect, oval, oval);
756 }
757 return 0;
758 case calcCRgns:
759 if (param & (1 << 31)) {
760 param &= ~(1 << 31);
761 goto calcthumbrgn;
762 }
763 /* FALLTHROUGH */
764 case calcCntlRgn:
765 rgn = (RgnHandle)param;
766 RectRgn(rgn, &(*control)->contrlRect);
767 return 0;
768 case calcThumbRgn:
769 calcthumbrgn:
770 rgn = (RgnHandle)param;
771 SetEmptyRgn(rgn);
772 return 0;
773 }
774
775 return 0;
776 }
777 #endif
778
779 static void macctrl_popup(struct macctrls *mcs, WindowPtr window,
780 struct mac_layoutstate *curstate,
781 union control *ctrl)
782 {
783 union macctrl *mc = snew(union macctrl);
784 Rect bounds;
785 Str255 title;
786 unsigned int labelwidth;
787 static int nextmenuid = MENU_MIN;
788 int menuid;
789 MenuRef menu;
790
791 /*
792 * <http://developer.apple.com/qa/tb/tb42.html> explains how to
793 * create a popup menu with dynamic content.
794 */
795 assert(ctrl->listbox.height == 0);
796 assert(!ctrl->listbox.draglist);
797 assert(!ctrl->listbox.multisel);
798
799 if (ctrl->listbox.label != NULL)
800 fprintf(stderr, " label = %s\n", ctrl->listbox.label);
801 fprintf(stderr, " percentwidth = %d\n", ctrl->listbox.percentwidth);
802
803 mc->generic.type = MACCTRL_POPUP;
804 mc->generic.ctrl = ctrl;
805 mc->generic.privdata = NULL;
806 c2pstrcpy(title, ctrl->button.label == NULL ? "" : ctrl->button.label);
807
808 /* Find a spare menu ID and create the menu */
809 while (GetMenuHandle(nextmenuid) != NULL)
810 if (++nextmenuid >= MENU_MAX) nextmenuid = MENU_MIN;
811 menuid = nextmenuid++;
812 menu = NewMenu(menuid, "\pdummy");
813 if (menu == NULL) return;
814 mc->popup.menu = menu;
815 mc->popup.menuid = menuid;
816 InsertMenu(menu, kInsertHierarchicalMenu);
817
818 /* The menu starts off empty */
819 mc->popup.nids = 0;
820 mc->popup.ids = NULL;
821
822 bounds.left = curstate->pos.h;
823 bounds.right = bounds.left + curstate->width;
824 bounds.top = curstate->pos.v;
825 bounds.bottom = bounds.top + 20;
826 /* XXX handle percentwidth == 100 */
827 labelwidth = curstate->width * (100 - ctrl->listbox.percentwidth) / 100;
828 mc->popup.tbctrl = NewControl(window, &bounds, title, TRUE,
829 popupTitleLeftJust, menuid, labelwidth,
830 popupMenuProc + popupFixedWidth, (long)mc);
831 add234(mcs->byctrl, mc);
832 curstate->pos.v += 26;
833 mc->generic.next = mcs->panels[curstate->panelnum];
834 mcs->panels[curstate->panelnum] = mc;
835 ctrlevent(mcs, mc, EVENT_REFRESH);
836 }
837
838
839 void macctrl_activate(WindowPtr window, EventRecord *event)
840 {
841 struct macctrls *mcs = mac_winctrls(window);
842 Boolean active = (event->modifiers & activeFlag) != 0;
843 GrafPtr saveport;
844 int i, j;
845 ControlPartCode state;
846 union macctrl *mc;
847
848 GetPort(&saveport);
849 SetPort((GrafPtr)GetWindowPort(window));
850 if (mac_gestalts.apprvers >= 0x100)
851 SetThemeWindowBackground(window, active ?
852 kThemeBrushModelessDialogBackgroundActive :
853 kThemeBrushModelessDialogBackgroundInactive,
854 TRUE);
855 state = active ? kControlNoPart : kControlInactivePart;
856 for (i = 0; i <= mcs->curpanel; i += mcs->curpanel)
857 for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
858 switch (mc->generic.type) {
859 case MACCTRL_TEXT:
860 HiliteControl(mc->text.tbctrl, state);
861 break;
862 case MACCTRL_EDITBOX:
863 HiliteControl(mc->editbox.tbctrl, state);
864 if (mc->editbox.tblabel != NULL)
865 HiliteControl(mc->editbox.tblabel, state);
866 break;
867 case MACCTRL_RADIO:
868 for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
869 HiliteControl(mc->radio.tbctrls[j], state);
870 if (mc->radio.tblabel != NULL)
871 HiliteControl(mc->radio.tblabel, state);
872 break;
873 case MACCTRL_CHECKBOX:
874 HiliteControl(mc->checkbox.tbctrl, state);
875 break;
876 case MACCTRL_BUTTON:
877 HiliteControl(mc->button.tbctrl, state);
878 break;
879 case MACCTRL_POPUP:
880 HiliteControl(mc->popup.tbctrl, state);
881 break;
882 }
883 #if !TARGET_API_MAC_CARBON
884 if (mcs->focus == mc) {
885 if (active)
886 macctrl_enfocus(mc);
887 else
888 macctrl_defocus(mc);
889 }
890 #endif
891 }
892 SetPort(saveport);
893 }
894
895 void macctrl_click(WindowPtr window, EventRecord *event)
896 {
897 Point mouse;
898 ControlHandle control;
899 int part, trackresult;
900 GrafPtr saveport;
901 union macctrl *mc;
902 struct macctrls *mcs = mac_winctrls(window);
903 int i;
904 UInt32 features;
905
906 GetPort(&saveport);
907 SetPort((GrafPtr)GetWindowPort(window));
908 mouse = event->where;
909 GlobalToLocal(&mouse);
910 part = FindControl(mouse, window, &control);
911 if (control != NULL) {
912 mc = (union macctrl *)GetControlReference(control);
913 if (mac_gestalts.apprvers >= 0x100) {
914 if (GetControlFeatures(control, &features) == noErr &&
915 (features & kControlSupportsFocus) &&
916 (features & kControlGetsFocusOnClick))
917 SetKeyboardFocus(window, control, part);
918 trackresult = HandleControlClick(control, mouse, event->modifiers,
919 (ControlActionUPP)-1);
920 } else {
921 #if !TARGET_API_MAC_CARBON
922 if (mc->generic.type == MACCTRL_EDITBOX &&
923 control == mc->editbox.tbctrl) {
924 TEHandle te = (TEHandle)(*control)->contrlData;
925
926 macctrl_setfocus(mcs, mc);
927 TEClick(mouse, !!(event->modifiers & shiftKey), te);
928 goto done;
929 }
930 #endif
931 trackresult = TrackControl(control, mouse, (ControlActionUPP)-1);
932 }
933 switch (mc->generic.type) {
934 case MACCTRL_RADIO:
935 if (trackresult != 0) {
936 for (i = 0; i < mc->generic.ctrl->radio.nbuttons; i++)
937 if (mc->radio.tbctrls[i] == control)
938 SetControlValue(mc->radio.tbctrls[i],
939 kControlRadioButtonCheckedValue);
940 else
941 SetControlValue(mc->radio.tbctrls[i],
942 kControlRadioButtonUncheckedValue);
943 ctrlevent(mcs, mc, EVENT_VALCHANGE);
944 }
945 break;
946 case MACCTRL_CHECKBOX:
947 if (trackresult != 0) {
948 SetControlValue(control, !GetControlValue(control));
949 ctrlevent(mcs, mc, EVENT_VALCHANGE);
950 }
951 break;
952 case MACCTRL_BUTTON:
953 if (trackresult != 0)
954 ctrlevent(mcs, mc, EVENT_ACTION);
955 break;
956 case MACCTRL_POPUP:
957 ctrlevent(mcs, mc, EVENT_SELCHANGE);
958 break;
959 }
960 }
961 done:
962 SetPort(saveport);
963 }
964
965 void macctrl_key(WindowPtr window, EventRecord *event)
966 {
967 ControlRef control;
968 struct macctrls *mcs = mac_winctrls(window);
969 union macctrl *mc;
970
971 if (mac_gestalts.apprvers >= 0x100) {
972 if (GetKeyboardFocus(window, &control) == noErr && control != NULL) {
973 HandleControlKey(control, (event->message & keyCodeMask) >> 8,
974 event->message & charCodeMask, event->modifiers);
975 mc = (union macctrl *)GetControlReference(control);
976 ctrlevent(mcs, mc, EVENT_VALCHANGE);
977 }
978 }
979 #if !TARGET_API_MAC_CARBON
980 else {
981 TEHandle te;
982
983 if (mcs->focus != NULL) {
984 mc = mcs->focus;
985 switch (mc->generic.type) {
986 case MACCTRL_EDITBOX:
987 te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
988 TEKey(event->message & charCodeMask, te);
989 ctrlevent(mcs, mc, EVENT_VALCHANGE);
990 break;
991 }
992 }
993 }
994 #endif
995 }
996
997 void macctrl_update(WindowPtr window)
998 {
999 #if TARGET_API_MAC_CARBON
1000 RgnHandle visrgn;
1001 #endif
1002 Rect rect;
1003 GrafPtr saveport;
1004
1005 BeginUpdate(window);
1006 GetPort(&saveport);
1007 SetPort((GrafPtr)GetWindowPort(window));
1008 if (mac_gestalts.apprvers >= 0x101) {
1009 #if TARGET_API_MAC_CARBON
1010 GetPortBounds(GetWindowPort(window), &rect);
1011 #else
1012 rect = window->portRect;
1013 #endif
1014 InsetRect(&rect, -1, -1);
1015 DrawThemeModelessDialogFrame(&rect, mac_frontwindow() == window ?
1016 kThemeStateActive : kThemeStateInactive);
1017 }
1018 #if TARGET_API_MAC_CARBON
1019 visrgn = NewRgn();
1020 GetPortVisibleRegion(GetWindowPort(window), visrgn);
1021 UpdateControls(window, visrgn);
1022 DisposeRgn(visrgn);
1023 #else
1024 UpdateControls(window, window->visRgn);
1025 #endif
1026 SetPort(saveport);
1027 EndUpdate(window);
1028 }
1029
1030 #if TARGET_API_MAC_CARBON
1031 #define EnableItem EnableMenuItem
1032 #define DisableItem DisableMenuItem
1033 #endif
1034 void macctrl_adjustmenus(WindowPtr window)
1035 {
1036 MenuHandle menu;
1037
1038 menu = GetMenuHandle(mFile);
1039 DisableItem(menu, iSave); /* XXX enable if modified */
1040 EnableItem(menu, iSaveAs);
1041 EnableItem(menu, iDuplicate);
1042
1043 menu = GetMenuHandle(mEdit);
1044 DisableItem(menu, 0);
1045 }
1046
1047 void macctrl_close(WindowPtr window)
1048 {
1049 struct macctrls *mcs = mac_winctrls(window);
1050 union macctrl *mc;
1051
1052 /*
1053 * Mostly, we don't bother disposing of the Toolbox controls,
1054 * since that will happen automatically when the window is
1055 * disposed of. Popup menus are an exception, because we have to
1056 * dispose of the menu ourselves, and doing that while the control
1057 * still holds a reference to it seems rude.
1058 */
1059 while ((mc = index234(mcs->byctrl, 0)) != NULL) {
1060 if (mc->generic.privdata != NULL && mc->generic.freeprivdata)
1061 sfree(mc->generic.privdata);
1062 switch (mc->generic.type) {
1063 case MACCTRL_POPUP:
1064 DisposeControl(mc->popup.tbctrl);
1065 DeleteMenu(mc->popup.menuid);
1066 DisposeMenu(mc->popup.menu);
1067 break;
1068 }
1069 del234(mcs->byctrl, mc);
1070 sfree(mc);
1071 }
1072
1073 freetree234(mcs->byctrl);
1074 mcs->byctrl = NULL;
1075 sfree(mcs->panels);
1076 mcs->panels = NULL;
1077 }
1078
1079 void dlg_update_start(union control *ctrl, void *dlg)
1080 {
1081
1082 /* No-op for now */
1083 }
1084
1085 void dlg_update_done(union control *ctrl, void *dlg)
1086 {
1087
1088 /* No-op for now */
1089 }
1090
1091 void dlg_set_focus(union control *ctrl, void *dlg)
1092 {
1093
1094 if (mac_gestalts.apprvers >= 0x100) {
1095 /* Use SetKeyboardFocus() */
1096 } else {
1097 /* Do our own mucking around */
1098 }
1099 }
1100
1101 union control *dlg_last_focused(union control *ctrl, void *dlg)
1102 {
1103
1104 return NULL;
1105 }
1106
1107 void dlg_beep(void *dlg)
1108 {
1109
1110 SysBeep(30);
1111 }
1112
1113 void dlg_error_msg(void *dlg, char *msg)
1114 {
1115 Str255 pmsg;
1116
1117 c2pstrcpy(pmsg, msg);
1118 ParamText(pmsg, NULL, NULL, NULL);
1119 StopAlert(128, NULL);
1120 }
1121
1122 void dlg_end(void *dlg, int value)
1123 {
1124 struct macctrls *mcs = dlg;
1125
1126 if (mcs->end != NULL)
1127 (*mcs->end)(mcs->window, value);
1128 };
1129
1130 void dlg_refresh(union control *ctrl, void *dlg)
1131 {
1132 struct macctrls *mcs = dlg;
1133 union macctrl *mc;
1134
1135 if (ctrl == NULL)
1136 return; /* FIXME */
1137 mc = findbyctrl(mcs, ctrl);
1138 assert(mc != NULL);
1139 ctrlevent(mcs, mc, EVENT_REFRESH);
1140 };
1141
1142 void *dlg_get_privdata(union control *ctrl, void *dlg)
1143 {
1144 struct macctrls *mcs = dlg;
1145 union macctrl *mc = findbyctrl(mcs, ctrl);
1146
1147 assert(mc != NULL);
1148 return mc->generic.privdata;
1149 }
1150
1151 void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
1152 {
1153 struct macctrls *mcs = dlg;
1154 union macctrl *mc = findbyctrl(mcs, ctrl);
1155
1156 assert(mc != NULL);
1157 mc->generic.privdata = ptr;
1158 mc->generic.freeprivdata = FALSE;
1159 }
1160
1161 void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
1162 {
1163 struct macctrls *mcs = dlg;
1164 union macctrl *mc = findbyctrl(mcs, ctrl);
1165
1166 assert(mc != NULL);
1167 mc->generic.privdata = smalloc(size);
1168 mc->generic.freeprivdata = TRUE;
1169 return mc->generic.privdata;
1170 }
1171
1172
1173 /*
1174 * Radio Button control
1175 */
1176
1177 void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton)
1178 {
1179 struct macctrls *mcs = dlg;
1180 union macctrl *mc = findbyctrl(mcs, ctrl);
1181 int i;
1182
1183 assert(mc != NULL);
1184 for (i = 0; i < ctrl->radio.nbuttons; i++) {
1185 if (i == whichbutton)
1186 SetControlValue(mc->radio.tbctrls[i],
1187 kControlRadioButtonCheckedValue);
1188 else
1189 SetControlValue(mc->radio.tbctrls[i],
1190 kControlRadioButtonUncheckedValue);
1191 }
1192
1193 };
1194
1195 int dlg_radiobutton_get(union control *ctrl, void *dlg)
1196 {
1197 struct macctrls *mcs = dlg;
1198 union macctrl *mc = findbyctrl(mcs, ctrl);
1199 int i;
1200
1201 assert(mc != NULL);
1202 for (i = 0; i < ctrl->radio.nbuttons; i++) {
1203 if (GetControlValue(mc->radio.tbctrls[i]) ==
1204 kControlRadioButtonCheckedValue)
1205 return i;
1206 }
1207 return -1;
1208 };
1209
1210
1211 /*
1212 * Check Box control
1213 */
1214
1215 void dlg_checkbox_set(union control *ctrl, void *dlg, int checked)
1216 {
1217 struct macctrls *mcs = dlg;
1218 union macctrl *mc = findbyctrl(mcs, ctrl);
1219
1220 assert(mc != NULL);
1221 SetControlValue(mc->checkbox.tbctrl,
1222 checked ? kControlCheckBoxCheckedValue :
1223 kControlCheckBoxUncheckedValue);
1224 }
1225
1226 int dlg_checkbox_get(union control *ctrl, void *dlg)
1227 {
1228 struct macctrls *mcs = dlg;
1229 union macctrl *mc = findbyctrl(mcs, ctrl);
1230
1231 assert(mc != NULL);
1232 return GetControlValue(mc->checkbox.tbctrl);
1233 }
1234
1235
1236 /*
1237 * Edit Box control
1238 */
1239
1240 void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
1241 {
1242 struct macctrls *mcs = dlg;
1243 union macctrl *mc = findbyctrl(mcs, ctrl);
1244 GrafPtr saveport;
1245
1246 assert(mc != NULL);
1247 assert(mc->generic.type == MACCTRL_EDITBOX);
1248 GetPort(&saveport);
1249 SetPort((GrafPtr)(GetWindowPort(mcs->window)));
1250 if (mac_gestalts.apprvers >= 0x100)
1251 SetControlData(mc->editbox.tbctrl, kControlEntireControl,
1252 ctrl->editbox.password ?
1253 kControlEditTextPasswordTag :
1254 kControlEditTextTextTag,
1255 strlen(text), text);
1256 #if !TARGET_API_MAC_CARBON
1257 else
1258 TESetText(text, strlen(text),
1259 (TEHandle)(*mc->editbox.tbctrl)->contrlData);
1260 #endif
1261 DrawOneControl(mc->editbox.tbctrl);
1262 SetPort(saveport);
1263 }
1264
1265 void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
1266 {
1267 struct macctrls *mcs = dlg;
1268 union macctrl *mc = findbyctrl(mcs, ctrl);
1269 Size olen;
1270
1271 assert(mc != NULL);
1272 assert(mc->generic.type == MACCTRL_EDITBOX);
1273 if (mac_gestalts.apprvers >= 0x100) {
1274 if (GetControlData(mc->editbox.tbctrl, kControlEntireControl,
1275 ctrl->editbox.password ?
1276 kControlEditTextPasswordTag :
1277 kControlEditTextTextTag,
1278 length - 1, buffer, &olen) != noErr)
1279 olen = 0;
1280 if (olen > length - 1)
1281 olen = length - 1;
1282 }
1283 #if !TARGET_API_MAC_CARBON
1284 else {
1285 TEHandle te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
1286
1287 olen = (*te)->teLength;
1288 if (olen > length - 1)
1289 olen = length - 1;
1290 memcpy(buffer, *(*te)->hText, olen);
1291 }
1292 #endif
1293 buffer[olen] = '\0';
1294 fprintf(stderr, "dlg_editbox_get: %s\n", buffer);
1295 }
1296
1297
1298 /*
1299 * List Box control
1300 */
1301
1302 static void dlg_macpopup_clear(union control *ctrl, void *dlg)
1303 {
1304 struct macctrls *mcs = dlg;
1305 union macctrl *mc = findbyctrl(mcs, ctrl);
1306 MenuRef menu = mc->popup.menu;
1307 unsigned int i, n;
1308
1309 fprintf(stderr, " popup_clear\n");
1310 n = CountMenuItems(menu);
1311 for (i = 0; i < n; i++)
1312 DeleteMenuItem(menu, n - i);
1313 mc->popup.nids = 0;
1314 sfree(mc->popup.ids);
1315 mc->popup.ids = NULL;
1316 SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1317 }
1318
1319 void dlg_listbox_clear(union control *ctrl, void *dlg)
1320 {
1321
1322 if (ctrl->listbox.height == 0)
1323 dlg_macpopup_clear(ctrl, dlg);
1324 }
1325
1326 static void dlg_macpopup_del(union control *ctrl, void *dlg, int index)
1327 {
1328 struct macctrls *mcs = dlg;
1329 union macctrl *mc = findbyctrl(mcs, ctrl);
1330 MenuRef menu = mc->popup.menu;
1331
1332 fprintf(stderr, " popup_del %d\n", index);
1333 DeleteMenuItem(menu, index + 1);
1334 if (mc->popup.ids != NULL)
1335 memcpy(mc->popup.ids + index, mc->popup.ids + index + 1,
1336 (mc->popup.nids - index - 1) * sizeof(*mc->popup.ids));
1337 SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1338 }
1339
1340 void dlg_listbox_del(union control *ctrl, void *dlg, int index)
1341 {
1342
1343 if (ctrl->listbox.height == 0)
1344 dlg_macpopup_del(ctrl, dlg, index);
1345 }
1346
1347 static void dlg_macpopup_add(union control *ctrl, void *dlg, char const *text)
1348 {
1349 struct macctrls *mcs = dlg;
1350 union macctrl *mc = findbyctrl(mcs, ctrl);
1351 MenuRef menu = mc->popup.menu;
1352 Str255 itemstring;
1353
1354 fprintf(stderr, " popup_add %s\n", text);
1355 assert(text[0] != '\0');
1356 c2pstrcpy(itemstring, text);
1357 AppendMenu(menu, "\pdummy");
1358 SetMenuItemText(menu, CountMenuItems(menu), itemstring);
1359 SetControlMaximum(mc->popup.tbctrl, CountMenuItems(menu));
1360 }
1361
1362 void dlg_listbox_add(union control *ctrl, void *dlg, char const *text)
1363 {
1364
1365 if (ctrl->listbox.height == 0)
1366 dlg_macpopup_add(ctrl, dlg, text);
1367 }
1368
1369 static void dlg_macpopup_addwithid(union control *ctrl, void *dlg,
1370 char const *text, int id)
1371 {
1372 struct macctrls *mcs = dlg;
1373 union macctrl *mc = findbyctrl(mcs, ctrl);
1374 MenuRef menu = mc->popup.menu;
1375 unsigned int index;
1376
1377 fprintf(stderr, " popup_addwthindex %s, %d\n", text, id);
1378 dlg_macpopup_add(ctrl, dlg, text);
1379 index = CountMenuItems(menu) - 1;
1380 if (mc->popup.nids <= index) {
1381 mc->popup.nids = index + 1;
1382 mc->popup.ids = sresize(mc->popup.ids, mc->popup.nids, int);
1383 }
1384 mc->popup.ids[index] = id;
1385 }
1386
1387 void dlg_listbox_addwithid(union control *ctrl, void *dlg,
1388 char const *text, int id)
1389 {
1390
1391 if (ctrl->listbox.height == 0)
1392 dlg_macpopup_addwithid(ctrl, dlg, text, id);
1393 }
1394
1395 int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
1396 {
1397 struct macctrls *mcs = dlg;
1398 union macctrl *mc = findbyctrl(mcs, ctrl);
1399
1400 if (ctrl->listbox.height == 0) {
1401 assert(mc->popup.ids != NULL && mc->popup.nids > index);
1402 return mc->popup.ids[index];
1403 }
1404 return 0;
1405 }
1406
1407 int dlg_listbox_index(union control *ctrl, void *dlg)
1408 {
1409 struct macctrls *mcs = dlg;
1410 union macctrl *mc = findbyctrl(mcs, ctrl);
1411
1412 if (ctrl->listbox.height == 0)
1413 return GetControlValue(mc->popup.tbctrl) - 1;
1414 return 0;
1415 };
1416
1417 int dlg_listbox_issel(union control *ctrl, void *dlg, int index)
1418 {
1419 struct macctrls *mcs = dlg;
1420 union macctrl *mc = findbyctrl(mcs, ctrl);
1421
1422 if (ctrl->listbox.height == 0)
1423 return GetControlValue(mc->popup.tbctrl) - 1 == index;
1424 return 0;
1425 };
1426
1427 void dlg_listbox_select(union control *ctrl, void *dlg, int index)
1428 {
1429 struct macctrls *mcs = dlg;
1430 union macctrl *mc = findbyctrl(mcs, ctrl);
1431
1432 if (ctrl->listbox.height == 0)
1433 SetControlValue(mc->popup.tbctrl, index + 1);
1434 };
1435
1436
1437 /*
1438 * Text control
1439 */
1440
1441 void dlg_text_set(union control *ctrl, void *dlg, char const *text)
1442 {
1443 struct macctrls *mcs = dlg;
1444 union macctrl *mc = findbyctrl(mcs, ctrl);
1445
1446 assert(mc != NULL);
1447 if (mac_gestalts.apprvers >= 0x100)
1448 SetControlData(mc->text.tbctrl, kControlEntireControl,
1449 kControlStaticTextTextTag, strlen(text), text);
1450 #if !TARGET_API_MAC_CARBON
1451 else
1452 TESetText(text, strlen(text),
1453 (TEHandle)(*mc->text.tbctrl)->contrlData);
1454 #endif
1455 }
1456
1457
1458 /*
1459 * File Selector control
1460 */
1461
1462 void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn)
1463 {
1464
1465 }
1466
1467 void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
1468 {
1469
1470 }
1471
1472
1473 /*
1474 * Font Selector control
1475 */
1476
1477 void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn)
1478 {
1479
1480 }
1481
1482 void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn)
1483 {
1484
1485 }
1486
1487
1488 /*
1489 * Printer enumeration
1490 */
1491
1492 printer_enum *printer_start_enum(int *nprinters)
1493 {
1494
1495 *nprinters = 0;
1496 return NULL;
1497 }
1498
1499 char *printer_get_name(printer_enum *pe, int thing)
1500 {
1501
1502 return "<none>";
1503 }
1504
1505 void printer_finish_enum(printer_enum *pe)
1506 {
1507
1508 }
1509
1510
1511 /*
1512 * Colour selection stuff
1513 */
1514
1515 void dlg_coloursel_start(union control *ctrl, void *dlg,
1516 int r, int g, int b)
1517 {
1518
1519 }
1520
1521 int dlg_coloursel_results(union control *ctrl, void *dlg,
1522 int *r, int *g, int *b)
1523 {
1524
1525 return 0;
1526 }
1527
1528 /*
1529 * Local Variables:
1530 * c-file-style: "simon"
1531 * End:
1532 */