Subversion Repositories filter_foundry

Rev

Rev 193 | Rev 268 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
259 daniel-mar 1
/*
2
        This file is part of a common library
3
    Copyright (C) 1990-2006 Toby Thain, toby@telegraphics.com.au
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by  
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
 
15
    You should have received a copy of the GNU General Public License  
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
 
68
Handle item_handle(DialogPtr d,short i){
69
        short kind;
70
        Handle item;
71
        Rect box;
72
 
73
        GetDialogItem(d,i,&kind,&item,&box);
74
        return item;
75
}
76
 
77
void get_item_rect(DialogPtr d,short i,Rect*r){
78
        short kind;
79
        Handle item;
80
 
81
        GetDialogItem(d,i,&kind,&item,r);
82
}
83
 
84
void inval_item(DialogPtr d,short i){
85
        Rect r;
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;
188
 
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);
196
 
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)
212
 
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
{
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) == '.'));
277
}
278
 
279
Boolean WasCancelSystem6or7(EventRecord *theEvent)
280
{
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) == '.'));
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.
360
 
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
}