Subversion Repositories filter_foundry

Rev

Rev 199 | Rev 268 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 199 Rev 259
Line 1... Line 1...
1
/*
1
/*
2
        This file is part of a common library
2
        This file is part of a common library
3
    Copyright (C) 2002-6 Toby Thain, toby@telegraphics.com.au
3
    Copyright (C) 2002-6 Toby Thain, toby@telegraphics.com.au
4
 
4
 
5
    This program is free software; you can redistribute it and/or modify
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
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
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
8
    (at your option) any later version.
9
 
9
 
10
    This program is distributed in the hope that it will be useful,
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
13
    GNU General Public License for more details.
14
 
14
 
15
    You should have received a copy of the GNU General Public License
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
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
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
18
*/
19
 
19
 
20
/* Choose file dialog using Navigation Services
20
/* Choose file dialog using Navigation Services
21
   (C) 2002-6 Toby Thain <toby@telegraphics.com.au> */
21
   (C) 2002-6 Toby Thain <toby@telegraphics.com.au> */
22
 
22
 
23
#include <memory.h>
23
#include <memory.h>
24
#include <script.h>
24
#include <script.h>
25
#include <plstringfuncs.h>
25
#include <plstringfuncs.h>
26
#include <stringcompare.h>
26
#include <stringcompare.h>
27
#include <aedatamodel.h>
27
#include <aedatamodel.h>
28
 
28
 
29
#include <string.h>
29
#include <string.h>
30
#include <ctype.h>
30
#include <ctype.h>
31
#include <stdio.h>
31
#include <stdio.h>
32
 
32
 
33
#include "choosefile.h"
33
#include "choosefile.h"
34
#include "dbg.h"
34
#include "dbg.h"
35
#include "str.h"
35
#include "str.h"
36
 
36
 
37
#if ! OPAQUE_TOOLBOX_STRUCTS
37
#if ! OPAQUE_TOOLBOX_STRUCTS
38
        #define AEGetDescData BlockMove
38
        #define AEGetDescData BlockMove
39
#endif
39
#endif
40
 
40
 
41
struct exts_types{
41
struct exts_types{
42
        char *filter;
42
        char *filter;
43
        int numtypes;
43
        int numtypes;
44
        OSType *typelist;
44
        OSType *typelist;
45
};
45
};
46
 
46
 
47
Boolean matchext(StringPtr name,char *ext);
47
Boolean matchext(StringPtr name,char *ext);
48
Boolean matchextfilter(StringPtr name,struct exts_types *ud);
48
Boolean matchextfilter(StringPtr name,struct exts_types *ud);
49
Boolean matchtypelist(NavFileOrFolderInfo* info,struct exts_types *ud);
49
Boolean matchtypelist(NavFileOrFolderInfo* info,struct exts_types *ud);
50
pascal Boolean myFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
50
pascal Boolean myFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
51
 
51
 
52
int strincmp(char *s1, char *s2, int n) {
52
int strincmp(char *s1, char *s2, int n) {
53
        /* case insensitive comparison */
53
        /* case insensitive comparison */
54
        int d;
54
        int d;
55
        while (--n >= 0) {
55
        while (--n >= 0) {
56
                d = tolower(*s1) - tolower(*s2);
56
                d = tolower(*s1) - tolower(*s2);
57
                if (d != 0 || *s1 == '\0' || *s2 == '\0') return d;
57
                if (d != 0 || *s1 == '\0' || *s2 == '\0') return d;
58
                ++s1;
58
                ++s1;
59
                ++s2;
59
                ++s2;
60
        }
60
        }
61
        return 0;
61
        return 0;
62
}
62
}
63
 
63
 
64
Boolean matchext(StringPtr name,char *ext){
64
Boolean matchext(StringPtr name,char *ext){
65
        Ptr pos = PLstrrchr(name,'.');
65
        Ptr pos = PLstrrchr(name,'.');
66
        int len = strlen(ext);
66
        int len = strlen(ext);
67
        return pos && (name[0] - (pos-(Ptr)name) == len) && !strincmp(pos+1,ext,len);
67
        return pos && (name[0] - (pos-(Ptr)name) == len) && !strincmp(pos+1,ext,len);
68
}
68
}
69
 
69
 
70
/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/CommonDialogBoxLibrary/CommonDialogBoxReference/CommonDialogBoxStructures/OPENFILENAME.asp
70
/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/CommonDialogBoxLibrary/CommonDialogBoxReference/CommonDialogBoxStructures/OPENFILENAME.asp
71
lpstrFilter
71
lpstrFilter
72
Pointer to a buffer containing pairs of null-terminated filter strings.
72
Pointer to a buffer containing pairs of null-terminated filter strings.
73
The last string in the buffer must be terminated by two NULL characters.
73
The last string in the buffer must be terminated by two NULL characters.
74
The first string in each pair is a display string that describes the filter
74
The first string in each pair is a display string that describes the filter
75
(for example, "Text Files"), and the second string specifies the filter pattern
75
(for example, "Text Files"), and the second string specifies the filter pattern
76
(for example, "*.TXT"). To specify multiple filter patterns for a single display string,
76
(for example, "*.TXT"). To specify multiple filter patterns for a single display string,
77
use a semicolon to separate the patterns (for example, "*.TXT;*.DOC;*.BAK").
77
use a semicolon to separate the patterns (for example, "*.TXT;*.DOC;*.BAK").
78
A pattern string can be a combination of valid file name characters
78
A pattern string can be a combination of valid file name characters
79
and the asterisk (*) wildcard character. Do not include spaces in the pattern string.
79
and the asterisk (*) wildcard character. Do not include spaces in the pattern string.
80
*/
80
*/
81
// example:
81
// example:
82
// "All supported files (.AFS, .8BF, .TXT)\0*.AFS;*.8BF;*.TXT\0All files (*.*)\0*.*\0\0"
82
// "All supported files (.AFS, .8BF, .TXT)\0*.AFS;*.8BF;*.TXT\0All files (*.*)\0*.*\0\0"
83
 
83
 
84
Boolean matchextfilter(StringPtr name,struct exts_types *ud){
84
Boolean matchextfilter(StringPtr name,struct exts_types *ud){
85
        Ptr pos = PLstrrchr(name,'.');
85
        Ptr pos = PLstrrchr(name,'.');
86
        char *p = ud->filter,*q;
86
        char *p = ud->filter,*q;
87
        int len;
87
        int len;
88
 
88
 
89
        if(p){
89
        if(p){
90
                // process only the FIRST string pair (in Windows GetFile box,
90
                // process only the FIRST string pair (in Windows GetFile box,
91
                // the user gets to choose which filter string to apply)
91
                // the user gets to choose which filter string to apply)
92
 
92
 
93
                // skip over display string
93
                // skip over display string
94
                while(*p++)
94
                while(*p++)
95
                        ;
95
                        ;
96
 
96
 
97
                // keep going until second string ends
97
                // keep going until second string ends
98
                while(*p){
98
                while(*p){
99
 
99
 
100
                        if(p[0] == '*' && p[1] == '.'){ // only match entries of '*.XXX' form
100
                        if(p[0] == '*' && p[1] == '.'){ // only match entries of '*.XXX' form
101
 
101
 
102
                                if(p[2] == '*')
102
                                if(p[2] == '*')
103
                                        return true; // looks like it's "*.*"
103
                                        return true; // looks like it's "*.*"
104
 
104
 
105
                                p += 2;
105
                                p += 2;
106
 
106
 
107
                                if(pos){ // file name does have an extension
107
                                if(pos){ // file name does have an extension
108
                                        q = pos+1; // point to first char of extension
108
                                        q = pos+1; // point to first char of extension
109
                                        len = name[0] - (pos-(Ptr)name);
109
                                        len = name[0] - (pos-(Ptr)name);
110
 
110
 
111
                                        // match characters until filename ends, pattern ends (NUL or ';') or mismatch
111
                                        // match characters until filename ends, pattern ends (NUL or ';') or mismatch
112
                                        while( len && *p && *p != ';' && toupper(*q++) == toupper(*p++) )
112
                                        while( len && *p && *p != ';' && toupper(*q++) == toupper(*p++) )
113
                                                --len;
113
                                                --len;
114
 
114
 
115
                                        // check if whole pattern matched
115
                                        // check if whole pattern matched
116
                                        if( len == 0 && (!*p || *p == ';') )
116
                                        if( len == 0 && (!*p || *p == ';') )
117
                                                return true;
117
                                                return true;
118
                                }
118
                                }
119
                        }
119
                        }
120
 
120
 
121
                        // skip to next item (after ';')
121
                        // skip to next item (after ';')
122
                        while( *p && *p != ';' )
122
                        while( *p && *p != ';' )
123
                                ++p;
123
                                ++p;
124
                        if(*p) ++p; // skip over semicolon
124
                        if(*p) ++p; // skip over semicolon
125
 
125
 
126
                }
126
                }
127
 
127
 
128
        }
128
        }
129
        return false;
129
        return false;
130
}
130
}
131
 
131
 
132
Boolean matchtypelist(NavFileOrFolderInfo* info,struct exts_types *ud){
132
Boolean matchtypelist(NavFileOrFolderInfo* info,struct exts_types *ud){
133
        int i;
133
        int i;
134
 
134
 
135
        if(ud->typelist)
135
        if(ud->typelist)
136
                for(i=0;i<ud->numtypes;++i)
136
                for(i=0;i<ud->numtypes;++i)
137
                        if(info->fileAndFolder.fileInfo.finderInfo.fdType == ud->typelist[i])
137
                        if(info->fileAndFolder.fileInfo.finderInfo.fdType == ud->typelist[i])
138
                                return true;
138
                                return true;
139
        return false;
139
        return false;
140
}
140
}
141
 
141
 
142
pascal Boolean myFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
142
pascal Boolean myFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
143
{
143
{
144
        NavFileOrFolderInfo *theInfo = (NavFileOrFolderInfo*)info;
144
        NavFileOrFolderInfo *theInfo = (NavFileOrFolderInfo*)info;
145
        OSStatus e = noErr;
145
        OSStatus e = noErr;
146
        AEDesc theDesc;
146
        AEDesc theDesc;
147
        FSSpec fss;
147
        FSSpec fss;
148
 
148
 
149
        if( !(e = AECoerceDesc(theItem,typeFSS,&theDesc)) ){
149
        if( !(e = AECoerceDesc(theItem,typeFSS,&theDesc)) ){
150
                AEGetDescData(&theDesc,&fss,sizeof(FSSpec));
150
                AEGetDescData(&theDesc,&fss,sizeof(FSSpec));
151
                AEDisposeDesc(&theDesc);
151
                AEDisposeDesc(&theDesc);
152
                return e || theItem->descriptorType != typeFSS || theInfo->isFolder
152
                return e || theItem->descriptorType != typeFSS || theInfo->isFolder
153
                        || matchextfilter(fss.name,(struct exts_types*)callBackUD)
153
                        || matchextfilter(fss.name,(struct exts_types*)callBackUD)
154
                        || matchtypelist(theInfo,(struct exts_types*)callBackUD);
154
                        || matchtypelist(theInfo,(struct exts_types*)callBackUD);
155
  }
155
  }
156
  return true;
156
  return true;
157
}
157
}
158
 
158
 
159
Boolean choosefiletypes(StringPtr prompt,StandardFileReply *sfr,NavReplyRecord *reply,
159
Boolean choosefiletypes(StringPtr prompt,StandardFileReply *sfr,NavReplyRecord *reply,
160
                                                OSType types[],int ntypes,const char *lpstrFilter)
160
                                                OSType types[],int ntypes,const char *lpstrFilter)
161
{
161
{
162
        //NavTypeListHandle tl = (NavTypeListHandle)NewHandle(sizeof(NavTypeList) + ntypes*sizeof(OSType));
162
        //NavTypeListHandle tl = (NavTypeListHandle)NewHandle(sizeof(NavTypeList) + ntypes*sizeof(OSType));
163
        OSErr e;
163
        OSErr e;
164
        long count;
164
        long count;
165
        AEKeyword theKeyword;
165
        AEKeyword theKeyword;
166
        DescType actualType;
166
        DescType actualType;
167
        Size actualSize;
167
        Size actualSize;
168
        NavDialogOptions dopts;
168
        NavDialogOptions dopts;
169
        NavObjectFilterUPP filter_upp = NewNavObjectFilterUPP(myFilterProc);
169
        NavObjectFilterUPP filter_upp = NewNavObjectFilterUPP(myFilterProc);
170
        struct exts_types ud;
170
        struct exts_types ud;
171
 
171
 
172
        sfr->sfGood = false;
172
        sfr->sfGood = false;
173
 
173
 
174
        if(!(e = NavGetDefaultDialogOptions(&dopts))){
174
        if(!(e = NavGetDefaultDialogOptions(&dopts))){
175
                PLstrcpy(dopts.message,prompt);
175
                PLstrcpy(dopts.message,prompt);
176
                ud.filter = lpstrFilter;
176
                ud.filter = lpstrFilter;
177
                ud.numtypes = ntypes;
177
                ud.numtypes = ntypes;
178
                ud.typelist = types;
178
                ud.typelist = types;
179
                e = NavChooseFile(NULL,reply,&dopts,NULL,NULL,filter_upp,NULL/*tl*/,&ud);
179
                e = NavChooseFile(NULL,reply,&dopts,NULL,NULL,filter_upp,NULL/*tl*/,&ud);
180
        }
180
        }
181
 
181
 
182
        if(!e && reply->validRecord ){
182
        if(!e && reply->validRecord ){
183
                if ( !(e = AECountItems(&reply->selection, &count))
183
                if ( !(e = AECountItems(&reply->selection, &count))
184
                         && count==1
184
                         && count==1
185
                         && !(e = AEGetNthPtr(&reply->selection,1,typeFSS,&theKeyword,&actualType,
185
                         && !(e = AEGetNthPtr(&reply->selection,1,typeFSS,&theKeyword,&actualType,
186
                                                                  &sfr->sfFile,sizeof(FSSpec),&actualSize)) ){
186
                                                                  &sfr->sfFile,sizeof(FSSpec),&actualSize)) ){
187
                        sfr->sfScript = reply->keyScript;
187
                        sfr->sfScript = reply->keyScript;
188
                        sfr->sfGood = true;
188
                        sfr->sfGood = true;
189
                }
189
                }
190
//        NavDisposeReply(&reply); // caller must dispose
190
//        NavDisposeReply(&reply); // caller must dispose
191
        }
191
        }
192
 
192
 
193
        DisposeNavObjectFilterUPP(filter_upp);
193
        DisposeNavObjectFilterUPP(filter_upp);
194
        return sfr->sfGood;
194
        return sfr->sfGood;
195
}
195
}
196
 
196
 
197
Boolean choosefile(StringPtr prompt,StandardFileReply *sfr,
197
Boolean choosefile(StringPtr prompt,StandardFileReply *sfr,
198
                                   NavReplyRecord *reply,OSType type,const char *lpstrFilter)
198
                                   NavReplyRecord *reply,OSType type,const char *lpstrFilter)
199
{
199
{
200
        return choosefiletypes(prompt,sfr,reply,&type,1,lpstrFilter);
200
        return choosefiletypes(prompt,sfr,reply,&type,1,lpstrFilter);
201
}
201
}
202
 
202
 
203
Boolean putfile(StringPtr prompt,StringPtr fname,OSType fileType,OSType fileCreator,
203
Boolean putfile(StringPtr prompt,StringPtr fname,OSType fileType,OSType fileCreator,
204
                NavReplyRecord *reply,StandardFileReply *sfr,
204
                NavReplyRecord *reply,StandardFileReply *sfr,
205
                char *lpstrDefExt,const char *lpstrFilter,int nFilterIndex){
205
                char *lpstrDefExt,const char *lpstrFilter,int nFilterIndex){
206
//      NavReplyRecord reply;
206
//      NavReplyRecord reply;
207
        NavDialogOptions dopts;
207
        NavDialogOptions dopts;
208
//      AEDesc defaultLocation;
208
//      AEDesc defaultLocation;
209
        AEKeyword theKeyword;
209
        AEKeyword theKeyword;
210
        DescType actualType;
210
        DescType actualType;
211
        Size actualSize;
211
        Size actualSize;
212
        OSErr e;
212
        OSErr e;
213
 
213
 
214
        sfr->sfGood = false;
214
        sfr->sfGood = false;
215
 
215
 
216
        NavGetDefaultDialogOptions(&dopts);
216
        NavGetDefaultDialogOptions(&dopts);
217
        dopts.dialogOptionFlags |= kNavNoTypePopup;
217
        dopts.dialogOptionFlags |= kNavNoTypePopup;
218
        dopts.dialogOptionFlags &= ~kNavAllowStationery;
218
        dopts.dialogOptionFlags &= ~kNavAllowStationery;
219
        PLstrcpy(dopts.savedFileName,fname);          /* default name for text box in NavPutFile (or null string for default) */
219
        PLstrcpy(dopts.savedFileName,fname);          /* default name for text box in NavPutFile (or null string for default) */
220
/* in two minds whether to append default extension or not, on Mac; skip for now.
220
/* in two minds whether to append default extension or not, on Mac; skip for now.
221
        if(lpstrDefExt && fname[0]){
221
        if(lpstrDefExt && fname[0]){
222
                dopts.savedFileName[++*dopts.savedFileName] = '.';
222
                dopts.savedFileName[++*dopts.savedFileName] = '.';
223
                memcpy(dopts.savedFileName+1+*dopts.savedFileName,lpstrDefExt,strlen(lpstrDefExt));
223
                memcpy(dopts.savedFileName+1+*dopts.savedFileName,lpstrDefExt,strlen(lpstrDefExt));
224
                *dopts.savedFileName += strlen(lpstrDefExt);
224
                *dopts.savedFileName += strlen(lpstrDefExt);
225
        }
225
        }
226
*/
226
*/
227
        PLstrcpy(dopts.message,prompt);                /* custom message prompt (or null string for default) */
227
        PLstrcpy(dopts.message,prompt);                /* custom message prompt (or null string for default) */
228
 
228
 
229
        if( !(e = NavPutFile(NULL,reply,&dopts,NULL,fileType,fileCreator,NULL)) && reply->validRecord ){
229
        if( !(e = NavPutFile(NULL,reply,&dopts,NULL,fileType,fileCreator,NULL)) && reply->validRecord ){
230
                if( !(e = AEGetNthPtr(&(reply->selection), 1, typeFSS,
230
                if( !(e = AEGetNthPtr(&(reply->selection), 1, typeFSS,
231
                                                          &theKeyword, &actualType, &sfr->sfFile, sizeof(FSSpec), &actualSize)) ){
231
                                                          &theKeyword, &actualType, &sfr->sfFile, sizeof(FSSpec), &actualSize)) ){
232
                        sfr->sfScript = reply->keyScript;
232
                        sfr->sfScript = reply->keyScript;
233
                        sfr->sfGood = true;
233
                        sfr->sfGood = true;
234
                }
234
                }
235
        }
235
        }
236
 
236
 
237
        return sfr->sfGood;
237
        return sfr->sfGood;
238
}
238
}
239
 
239
 
240
OSErr completesave(NavReplyRecord *reply){
240
OSErr completesave(NavReplyRecord *reply){
241
        OSErr e = NavCompleteSave(reply,kNavTranslateInPlace);
241
        OSErr e = NavCompleteSave(reply,kNavTranslateInPlace);
242
        NavDisposeReply(reply);
242
        NavDisposeReply(reply);
243
        return e;
243
        return e;
244
}
244
}