Subversion Repositories filter_foundry

Rev

Rev 268 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
259 daniel-mar 1
/*
268 daniel-mar 2
    This file is part of a common library
536 daniel-mar 3
    Copyright (C) 1990-2006 Toby Thain, toby@telegraphics.net
259 daniel-mar 4
 
5
    This program is free software; you can redistribute it and/or modify
268 daniel-mar 6
    it under the terms of the GNU General Public License as published by
259 daniel-mar 7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
268 daniel-mar 15
    You should have received a copy of the GNU General Public License
259 daniel-mar 16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19
 
20
#include "carbonstuff.h"
21
 
22
#include <quickdraw.h>
23
#include <controls.h>
24
#include <dialogs.h>
25
#include <events.h>
26
#include <osutils.h> // Delay
27
#include <palettes.h> // GetGray
28
#include <resources.h>
29
#include <textutils.h> // NumToString
30
#include <ctype.h>
31
#include <gestalt.h>
32
 
33
#include "dlg.h"
34
#include "qd.h"
35
#include "wind.h"
36
#include "misc-mac.h"
37
 
38
#if 0 //TARGET_API_MAC_CARBON /* FIXME:KLUDGE */
39
#define DisposeRoutineDescriptor
40
#define NewRoutineDescriptor( theProc, theProcInfo, theISA) (theProc)
41
#define NewDeviceLoopDrawingProc
42
#endif
43
 
44
pascal void grey_item_dldp(short depth, short deviceFlags, GDHandle targetDevice, long userData);
45
 
46
DialogPtr get_centred_dialog(short id){ DialogRef d;
47
        // assume the dialog is initially invisible; otherwise the centring process would be ugly
48
        /*centre_window*/(d = GetNewDialog(id,0,(WindowPtr)-1));
49
        ShowWindow(GetDialogWindow(d));
50
        return d;
51
}
52
 
53
void centre_alert(short id){
54
        AlertTHndl a = (AlertTHndl)GetResource('ALRT',id);
55
        centre_rect(&(*a)->boundsRect);
56
}
57
 
58
Point centred(short id){ DialogTHndl t; Rect s;
59
        t = (DialogTHndl)GetResource('DLOG',id);
60
        s = (*t)->boundsRect;
61
        ReleaseResource((Handle)t);
62
        centre_rect(&s);
63
        return TOPLEFT(s);
64
}
65
 
66
/* dialog utilities */
67
 
268 daniel-mar 68
Handle item_handle(DialogPtr d,short i){
259 daniel-mar 69
        short kind;
70
        Handle item;
71
        Rect box;
72
 
73
        GetDialogItem(d,i,&kind,&item,&box);
74
        return item;
75
}
76
 
268 daniel-mar 77
void get_item_rect(DialogPtr d,short i,Rect*r){
259 daniel-mar 78
        short kind;
79
        Handle item;
80
 
81
        GetDialogItem(d,i,&kind,&item,r);
82
}
83
 
268 daniel-mar 84
void inval_item(DialogPtr d,short i){
85
        Rect r;
259 daniel-mar 86
        //GrafPtr gp;
87
        get_item_rect(d,i,&r);
88
        //GetPort(&gp);         SetPort(d);
89
        InvalWindowRect(GetDialogWindow(d),&r);
90
        //SetPort(gp);
91
}
92
 
93
void hide_items(DialogPtr d,long v){ int i;
94
        for(i=1;v>>=1;i++)
95
                if(v&1)
96
                        HideDialogItem(d,i);
97
}
98
void show_items(DialogPtr d,long v){ int i;
99
        for(i=1;v>>=1;i++)
100
                if(v&1)
101
                        ShowDialogItem(d,i);
102
}
103
 
104
void set_user_item(DialogPtr d,short i,UserItemUPP p){
105
        short kind;
106
        Handle item;
107
        Rect box;
108
 
109
        GetDialogItem(d,i,&kind,&item,&box);
110
        SetDialogItem(d,i,kind,(void*)p,&box);
111
}
112
 
113
void set_item_value(DialogPtr d,short i,short v){
114
        SetControlValue((ControlHandle)item_handle(d,i),v);
115
}
116
 
117
void get_item_text(DialogPtr d,short i,Str255 s){
118
        GetDialogItemText(item_handle(d,i),s);
119
}
120
 
121
void set_item_text(DialogPtr d,short i,Str255 s){
122
        SetDialogItemText(item_handle(d,i),s);
123
}
124
 
125
void set_num_item(DialogPtr d,short i,long n){
126
        Str255 s;
127
 
128
        NumToString(n,s);
129
        SetDialogItemText(item_handle(d,i),s);
130
}
131
 
132
long get_num_item(DialogPtr d,short i){
133
        Str255 s;
134
        long n;
135
 
136
        GetDialogItemText(item_handle(d,i),s);
137
        StringToNum(s,&n);
138
        return n;
139
}
140
 
141
USER_ITEM(dimmed_item){ PenState ps; Rect r; Pattern pat;
142
        get_item_rect(theDialog,itemNo,&r);
143
        GetPenState(&ps);
144
        GetQDGlobalsGray(&pat);
145
        PenPat(&pat);
146
        PenMode(patBic);
147
        PaintRect(&r);
148
        SetPenState(&ps);
149
}
150
 
151
#if 0
152
USER_ITEM(grey_item){ PenState ps; Rect r;
153
        get_item_rect(theDialog,itemNo,&r);
154
        GetPenState(&ps);
155
        PenPat(&SAFE_QD(gray));
156
        FrameRect(&r);
157
        SetPenState(&ps);
158
}
159
 
160
#else
161
 
162
pascal void grey_item_dldp(short depth, short deviceFlags, GDHandle targetDevice, long userData){
163
        RGBColor save,fg,bg;
164
        PenState ps;
165
        int f;
166
        Pattern pat;
167
 
168
        GetBackColor(&bg);
169
        GetForeColor(&fg);
170
        save = fg;
171
 
172
        if( f = GetGray(targetDevice, &bg, &fg) ){
173
                RGBForeColor(&fg);
174
        }else{
175
                GetPenState(&ps);
176
                GetQDGlobalsGray(&pat);
177
                PenPat(&pat);
178
        }
179
        FrameRect((Rect*)userData);
180
        f ? RGBForeColor(&save) : SetPenState(&ps);
181
}
182
 
183
USER_ITEM(grey_item){
184
        Rect r;
185
        RgnHandle rgn;
186
        DeviceLoopDrawingUPP proc = NewDeviceLoopDrawingUPP(grey_item_dldp);
187
        GrafPtr gp;
268 daniel-mar 188
 
259 daniel-mar 189
        GetPort(&gp);
190
        SetPort((GrafPtr)GetWindowPort(GetDialogWindow(theDialog)));
191
 
192
        get_item_rect(theDialog,itemNo,&r);
193
        RectRgn(rgn = NewRgn(),&r);
194
        DeviceLoop(rgn, proc, (long)&r, 0);
195
        DisposeRgn(rgn);
268 daniel-mar 196
 
259 daniel-mar 197
        SetPort(gp);
198
 
199
        DisposeDeviceLoopDrawingUPP(proc);
200
}
201
#endif
202
 
203
USER_ITEM(framed_item){ Rect r;
204
        get_item_rect(theDialog,itemNo,&r);
205
        FrameRect(&r);
206
}
207
 
208
USER_ITEM(label_frame_item){ Rect r; RgnHandle rgn,rgn2;
209
        // draws a single-pixel frame around the item,
210
        // leaving out the rectangle of the previous item
211
        // (which is usually the label for the frame)
268 daniel-mar 212
 
259 daniel-mar 213
        GetClip(rgn = NewRgn());
214
 
215
        get_item_rect(theDialog,itemNo-1,&r);
216
        RectRgn(rgn2 = NewRgn(),&r);
217
        DiffRgn(rgn,rgn2,rgn2);
218
        SetClip(rgn2);
219
 
220
        grey_item(theDialog, itemNo);
221
 
222
        SetClip(rgn);
223
 
224
        DisposeRgn(rgn);
225
        DisposeRgn(rgn2);
226
}
227
 
228
USER_ITEM(outlined_item){ PenState ps; Rect r; int k; Pattern pat;
229
        get_item_rect(theDialog,itemNo,&r);
230
        GetPenState(&ps);
231
        PenSize(3,3);
232
        if( GetControlHilite( (ControlHandle)item_handle(theDialog,GetDialogDefaultItem(theDialog)) ) ){
233
                GetQDGlobalsGray(&pat);
234
                PenPat(&pat);
235
        }
236
        k = (r.bottom-r.top)/2 + 2; // ???
237
        FrameRoundRect(&r,k,k);
238
        SetPenState(&ps);
239
}
240
 
241
#if 0
242
// determine what character a keypress would be had it not been modified by the command key
243
// this code is absolutely useless
244
 
245
char unmodified_key(EventRecord*e){ short keycode; long state=0,c; char c1; void *transData;
246
        if(transData = (void*)GetEnvirons(smKCHRCache)){
247
                keycode = (e->modifiers & (0xff00 & ~cmdKey)) | ((e->message & keyCodeMask) >> 8);
248
                c = KeyTrans(transData,keycode,&state);
249
                return (c1 = c>>16) ? c1 : c;
250
        }else
251
                return e->message;
252
}
253
 
254
/*
255
You're wrong Phil. Command does in fact disable the shift modifier. See
256
the tech note on International Cancelling. To properly handle the command
257
key in your application, you should always strip the command-key bit out
258
of the modifiers field and re-pass the keystroke through KeyTrans. Here's
259
some source code for doing it with the cancel key, but you should use
260
similar code for any command-key combination (like in MenuKey):
261
*/
262
/* These both use Universal Headers. The second is for System 6 too. */
263
 
264
Boolean WasCancel(EventRecord *theEvent)
265
{
268 daniel-mar 266
        short keyCode;
267
        long state = 0L, test;
268
        unsigned long keys;
269
 
270
        if(!(theEvent->modifiers & cmdKey))
271
                return(false);
272
        keyCode = (theEvent->modifiers & 0xFE00) |
273
                  ((theEvent->message & keyCodeMask) >> 8);
274
        keys = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache),
275
                            keyCode, &state);
276
        return(((Byte)keys == '.') || ((Byte)(keys >>= 16) == '.'));
259 daniel-mar 277
}
278
 
279
Boolean WasCancelSystem6or7(EventRecord *theEvent)
280
{
268 daniel-mar 281
        short keyCode, rsrcID, scriptID;
282
        Ptr kchrPtr;
283
        Handle kchrRsrc = nil;
284
        long state = 0L;
285
        unsigned long keys;
286
 
287
        if(!(theEvent->modifiers & cmdKey))
288
                return(false);
289
        keyCode = (theEvent->modifiers & 0xFE00) |
290
                  ((theEvent->message & keyCodeMask) >> 8);
291
        if((kchrPtr = (Ptr)GetScriptManagerVariable(smKCHRCache)) == nil) {
292
                scriptID = GetScriptManagerVariable(smKeyScript);
293
                rsrcID = GetScriptVariable(scriptID, smScriptKeys);
294
                kchrRsrc = GetResource('KCHR', rsrcID);
295
                if(kchrRsrc != nil)
296
                        kchrPtr = *kchrRsrc;
297
        }
298
        if(kchrPtr != nil)
299
                keys = KeyTranslate(kchrPtr, keyCode, &state);
300
        if(kchrRsrc != nil)
301
                ReleaseResource(kchrRsrc);
302
        return(((Byte)keys == '.') || ((Byte)(keys >>= 16) == '.'));
259 daniel-mar 303
}
304
// Pete Resnick    (...so what is a mojo, and why would one be rising?)
305
#endif
306
 
307
Boolean is_a_button(DialogPtr d,int i){ KIND_ITEM_BOX
308
        GetDialogItem(d,i,&kind,&item,&box);
309
        return kind==ctrlItem|btnCtrl && !GetControlHilite((ControlHandle)item);
310
}
311
 
312
// TO DO: modify is_cancel to use IsCmdChar (scripts.h)
313
 
314
Boolean is_cancel(EventRecord*e){ char c = e->message;
315
        return e->what==keyDown && ((e->modifiers&cmdKey && c=='.') || c==27);
316
}
317
FILTER(filter_buttons){ int i=0,j; char c; Str255 s; WindowPtr w; Boolean f = false;
318
        switch(theEvent->what){
319
        case mouseDown:
320
                if(theEvent->modifiers & cmdKey && FindWindow(theEvent->where,&w) == inDrag){
321
                        BitMap bm;
322
                        GetQDGlobalsScreenBits(&bm);
323
                        DragWindow(w,theEvent->where,&bm.bounds);
324
                        theEvent->what = nullEvent;
325
                }
326
                break;
327
        case keyDown:
328
                c = theEvent->message;
329
                if( (c==3 || c==13) && is_a_button(theDialog,GetDialogDefaultItem(theDialog)) )
330
                        i = GetDialogDefaultItem(theDialog);
331
                else if(is_cancel(theEvent) && is_a_button(theDialog,cancel))
332
                        i = cancel;
333
                else if(GetDialogKeyboardFocusItem(theDialog) == -1 /*|| theEvent->modifiers & cmdKey*/
334
                                && gestalt_attr(gestaltDITLExtAttr,gestaltDITLExtPresent)){
335
                        c = tolower(c);
336
                        for(j=CountDITL(theDialog);j;j--){ KIND_ITEM_BOX
337
                                GetDialogItem(theDialog,j,&kind,&item,&box);
338
                                if( (kind&(itemDisable|ctrlItem))==ctrlItem && !GetControlHilite((ControlHandle)item) ){
339
                                        GetControlTitle((ControlHandle)item,s);
340
                                        if(*s && tolower(s[1])==c)
341
                                                if(i){ // two buttons' titles begin with the same character
342
                                                        i = 0;
343
                                                        break;
344
                                                }else
345
                                                        i = j;
346
                                }
347
                        }
348
                }
349
                if(i){
350
                        flash_button(theDialog,*itemHit = i);
351
                        f = true;
352
                }
353
        }
354
        return f;
355
}
356
 
357
/*      It would be nice to highlight the button until the user releases the key,
358
        but if the key was released before the event mask is set to include key-up events,
359
        the event won't be posted, and the button stays highlighted until a key is next released.
268 daniel-mar 360
 
259 daniel-mar 361
        The easy solution is to enable key-up events when the application starts up;
362
        however, I'm not sure that the extra code to do this
363
                *(short*)SysEvtMask |= keyUpMask
364
        and wait for the event
365
                while(!EventAvail(keyUpMask,&e)) ;
366
        is justified.
367
        (There's also the overhead of an extra event per keypress.)
368
        We should only un-highlight the button if the SAME key was released as was pressed.
369
*/
370
void flash_button(DialogPtr d,short i){
371
#if 0 // I'm temporarily taking this code out, because "inButton" has disappeared from headers???
372
        ControlHandle c; unsigned long t; int h;
373
        c = (ControlHandle)item_handle(d,i);
374
        h = (*c)->contrlHilite;
375
        HiliteControl(c,inButton);
376
        Delay(8,&t);
377
        HiliteControl(c,h);
378
#endif
379
}