Subversion Repositories filter_foundry

Rev

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

Rev Author Line No. Line
2 toby 1
/*
18 toby 2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
98 toby 3
    Copyright (C) 2003-7 Toby Thain, toby@telegraphics.com.au
2 toby 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 <plstringfuncs.h>
21
#include <ASRegistry.h>
13 toby 22
#include <ctype.h>
2 toby 23
 
24
#include "ff.h"
25
 
26
#include "file_compat.h"
27
 
28
// MoreFiles headers
29
#include "FileCopy.h" 
30
#include "MoreFilesExtras.h"
31
 
32
OSErr wrstr(FILEREF rn,char *s);
33
OSErr dopkginfo(FILEREF rn);
34
OSErr make_bundle(StandardFileReply *sfr, short plugvol,long plugdir,StringPtr plugname);
11 toby 35
OSErr doresources(FSSpec *srcplug, FSSpec *rsrccopyfss);
2 toby 36
OSErr make_singlefile(StandardFileReply *sfr, short plugvol,long plugdir,StringPtr plugname);
11 toby 37
OSErr copyplist(FSSpec *fss, short dstvol,long dstdir);
13 toby 38
int copyletters(char *dst,StringPtr src);
2 toby 39
 
13 toby 40
// prototype for a function included in Carbon's stdlib and declared in /usr/include/string.h
41
// but missing from MPW Universal header string.h
42
#ifndef _STRING_H_
43
        char    *strnstr(const char *, const char *, size_t);
44
#endif
45
 
2 toby 46
OSErr wrstr(FILEREF rn,char *s){
47
        long count = strlen(s);
48
        return FSWrite(rn,&count,s);
49
}
50
 
11 toby 51
OSErr doresources(FSSpec *srcplug, FSSpec *rsrccopy){
2 toby 52
        short srcrn,dstrn;
53
        Handle hpipl,h;
85 toby 54
        long origsize,newsize,parm_type,parm_id;
2 toby 55
        OSErr e = noErr;
56
        Str255 title;
57
 
11 toby 58
#ifdef MACMACHO
62 toby 59
        FSRef inref,outref;
60
        // work with resources in data fork
61
        if( !(e = FSpMakeFSRef(srcplug,&inref))
62
         && !(e = FSOpenResourceFile(&inref,0/*forkNameLength*/,NULL/*forkName*/,fsRdPerm,&srcrn))
63
         && !(e = FSpMakeFSRef(rsrccopy,&outref))
64
         &&  (e = FSOpenResourceFile(&outref,0/*forkNameLength*/,NULL/*forkName*/,fsWrPerm,&dstrn)) )
65
                CloseResFile(srcrn);
11 toby 66
#else
62 toby 67
        // ordinary resource fork files
68
        srcrn = FSpOpenResFile(srcplug,fsRdPerm);
69
        if(srcrn != -1){
70
                dstrn = FSpOpenResFile(rsrccopy,fsWrPerm);
71
                if(dstrn == -1){
72
                        e = ResError();
73
                        CloseResFile(srcrn);
74
                }
75
        }else e = ResError();
11 toby 76
#endif
2 toby 77
 
11 toby 78
        if(!e){
79
                /* create a new PiPL resource for the standalone plugin,
80
                   with updated title and category strings */
81
 
57 toby 82
                if( (hpipl = Get1Resource('DATA',16000))
83
                 && (h = Get1Resource('PiPL',16000)) )
84
                {
11 toby 85
                        RemoveResource(h);
86
 
87
                        DetachResource(hpipl);
2 toby 88
 
11 toby 89
                        PLstrcpy(title,gdata->parm.title);
90
                        if(gdata->parm.popDialog)
91
                                PLstrcat(title,"\pÉ");
2 toby 92
 
11 toby 93
                        origsize = GetHandleSize(hpipl);
94
                        SetHandleSize(hpipl,origsize+0x300); /* some slop for fixup to work with */
95
                        HLock(hpipl);
96
                        newsize = fixpipl((PIPropertyList*) *hpipl,origsize,title);
97
                        HUnlock(hpipl);
98
                        SetHandleSize(hpipl,newsize);
99
 
100
                        AddResource(hpipl,'PiPL',16000,"\p");
101
 
57 toby 102
                        if( !(e = ResError()) ){
103
                                /* do a similar trick with the terminology resource,
104
                                   so the scripting system can distinguish the standalone plugin */
11 toby 105
 
57 toby 106
                                if( (h = Get1Resource(typeAETE,AETE_ID)) ){
107
                                        origsize = GetHandleSize(h);
108
                                        SetHandleSize(h,origsize+0x100); /* slop for fixup to work with */
109
                                        HLock(h);
110
                                        newsize = fixaete((unsigned char*)*h,origsize,gdata->parm.title);
111
                                        HUnlock(h);
112
                                        SetHandleSize(h,newsize);
113
 
114
                                        ChangedResource(h);
115
 
116
                                        if( !(e = ResError()) ){
117
                                                /* add PARM resource */
85 toby 118
                                                if( !(e = PtrToHand(&gdata->parm,&h,sizeof(PARM_T))) ){
119
                                                        if(gdata->obfusc){
120
                                                                HLock(h);
121
                                                                obfusc((unsigned char*)*h,sizeof(PARM_T));
122
                                                                HUnlock(h);
123
                                                                parm_type = 'DATA';
124
                                                                parm_id = OBFUSCDATA_ID;
125
                                                        }else{
126
                                                                parm_type = 'PARM';
127
                                                                parm_id = PARM_ID;
128
                                                        }
129
                                                        AddResource(h,parm_type,parm_id,"\p");
130
                                                }
57 toby 131
                                        }
132
                                }
133
 
134
                        }
2 toby 135
 
11 toby 136
                }
57 toby 137
                if(!e)
138
                        e = ResError();
139
 
11 toby 140
                CloseResFile(dstrn);
2 toby 141
                CloseResFile(srcrn);
11 toby 142
        }
2 toby 143
 
144
        return e;
145
}
146
 
11 toby 147
int copyletters(char *dst,StringPtr src){
98 toby 148
        int i, n;
62 toby 149
 
98 toby 150
        for(i = src[0], n = 0; i--;)
62 toby 151
                if(isalpha(*++src)){
152
                        *dst++ = *src;
153
                        ++n;
154
                }
155
        return n;
11 toby 156
}
8 toby 157
 
98 toby 158
// Info.plist in new standalone copy needs to be edited -
11 toby 159
// at least the CFBundleIdentifier property must be unique
160
 
57 toby 161
OSErr copyplist(FSSpec *fss, short dstvol, long dstdir){
62 toby 162
        static char *key = "com.telegraphics.FilterFoundry";
163
        static unsigned char *fname="\pInfo.plist";
164
        char *buf,*save,*p;
165
        short rn,dstrn,i,n,m;
166
        long eof,count;
167
        OSErr e;
168
 
169
        if( !(e = HCreate(dstvol,dstdir,fname,'pled','TEXT')) ){
170
                if( !(e = HOpenDF(dstvol,dstdir,fname,fsWrPerm,&dstrn)) ){
171
                        if( !(e = FSpOpenDF(fss,fsRdPerm,&rn)) ){
172
                                if( !(e = GetEOF(rn,&eof)) && (buf = malloc(eof+1024)) ){
173
                                        if( !(e = FSRead(rn,&eof,buf)) ){
174
                                                buf[eof] = 0;
175
                                                if( (p = strnstr(buf,key,eof)) && (save = malloc(eof-(p-buf)+1)) ){
176
                                                        p += strlen(key);
177
                                                        // store text after matched string
178
                                                        strcpy(save,p);
179
 
180
                                                        *p++ = '.';
181
                                                        n = copyletters(p,gdata->parm.category);
182
                                                        p += n;
183
                                                        if(n) *p++ = '.';
184
                                                        m = copyletters(p,gdata->parm.title);
185
                                                        p += m;
186
                                                        if(!m){
187
                                                                // generate a random ASCII identifier
188
                                                                srand(TICKCOUNT());
98 toby 189
                                                                for(i = 8; i--;)
190
                                                                        *p++ = 'a' + (rand() % 26);
62 toby 191
                                                        }
192
                                                        strcpy(p,save);
193
 
194
                                                        count = strlen(buf);
195
                                                        e = FSWrite(dstrn,&count,buf);
196
 
197
                                                        free(save);
198
                                                }else e = paramErr; // not found?? shouldn't happen
199
                                        }
200
                                        free(buf);
201
                                }
202
                                FSClose(rn);
203
                        }
204
                        FSClose(dstrn);
205
                }
206
                if(e) HDelete(dstvol,dstdir,fname);
207
        }
208
        return e;
11 toby 209
}
210
 
57 toby 211
OSErr make_bundle(StandardFileReply *sfr, short plugvol, long plugdir, StringPtr plugname){
2 toby 212
        short dstvol = sfr->sfFile.vRefNum;
11 toby 213
        long bundledir,contentsdir,macosdir,rsrcdir;
2 toby 214
        DInfo fndrInfo;
215
        OSErr e;
11 toby 216
        FSSpec fss,macosfss,rsrcfss,rsrccopyfss;
2 toby 217
 
218
        if( !(e = FSpDirCreate(&sfr->sfFile,sfr->sfScript,&bundledir)) ){
219
                if(!(e = FSpGetDInfo(&sfr->sfFile,&fndrInfo)) ){
220
                        fndrInfo.frFlags |= kHasBundle;
221
                        FSpSetDInfo(&sfr->sfFile,&fndrInfo);
222
                }
223
                if( !(e = DirCreate(dstvol,bundledir,"\pContents",&contentsdir)) ){
224
                        if( !(e = DirCreate(dstvol,contentsdir,"\pMacOS",&macosdir)) ){
11 toby 225
                                if( !(e = DirCreate(dstvol,contentsdir,"\pResources",&rsrcdir)) ){
2 toby 226
 
98 toby 227
                                        /* directories created; copy the Info.plist file, resource file, and executable */
2 toby 228
 
11 toby 229
                                        if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::MacOS:FilterFoundry",&macosfss))
63 toby 230
                                         && !(e = FileCopy(macosfss.vRefNum,macosfss.parID,macosfss.name, dstvol,macosdir,NULL, NULL,NULL,0,false)) )
231
                                        {
98 toby 232
                                                /* add PARM resources to each binary, and edit PiPLs */
63 toby 233
                                                if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Resources:FilterFoundry.rsrc",&rsrcfss))
234
                                                 && !(e = FileCopy(rsrcfss.vRefNum,rsrcfss.parID,rsrcfss.name, dstvol,rsrcdir,NULL, NULL,NULL,0,false))
235
                                                 && !(e = FSMakeFSSpec(dstvol,rsrcdir,"\pFilterFoundry.rsrc",&rsrccopyfss)) )
236
                                                {
237
                                                        if( !(e = doresources(&rsrcfss, &rsrccopyfss))
238
                                                         && !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Info.plist",&fss)) )
62 toby 239
                                                        {
63 toby 240
                                                                e = copyplist(&fss,dstvol,contentsdir);
62 toby 241
 
242
                                                                if(e) FSpDelete(&rsrccopyfss);
243
                                                        }
244
                                                        if(e) HDelete(dstvol,macosdir,"\pFilterFoundry");
11 toby 245
                                                }
246
                                                if(e) HDelete(dstvol,rsrcdir,plugname);
247
                                        }
248
                                        if(e) HDelete(dstvol,contentsdir,"\pResources");
2 toby 249
                                }
11 toby 250
                                if(e) HDelete(dstvol,contentsdir,"\pMacOS");
2 toby 251
                        }
11 toby 252
                        if(e) HDelete(dstvol,bundledir,"\pContents");
2 toby 253
                }
254
                if(e) FSpDelete(&sfr->sfFile);
255
        }
256
 
257
        return e;
258
}
259
 
98 toby 260
OSErr make_singlefile(StandardFileReply *sfr, short plugvol, long plugdir, StringPtr plugname){
2 toby 261
        OSErr e;
262
        FSSpec origfss;
263
 
264
        e = FSpDelete(&sfr->sfFile);
265
        if(e && e != fnfErr){
11 toby 266
                alertuser("Can't replace the existing file. Try a different name or location.","");
2 toby 267
                return userCanceledErr;
268
        }
269
 
270
        if( !(e = FileCopy(plugvol,plugdir,plugname, sfr->sfFile.vRefNum,sfr->sfFile.parID,NULL, sfr->sfFile.name,NULL,0,false))
62 toby 271
         && !(e = FSMakeFSSpec(plugvol,plugdir,plugname,&origfss)) )
98 toby 272
                /* add PARM resources, and edit PiPL */
11 toby 273
                e = doresources(&origfss, &sfr->sfFile);
2 toby 274
 
275
        return e;
276
}
277
 
278
OSErr make_standalone(StandardFileReply *sfr){
279
        OSErr e;
280
        short plugvol;
281
        long plugdir;
282
        Str255 plugname;
283
 
98 toby 284
        if(!(e = GetFileLocation(CurResFile(),&plugvol,&plugdir,plugname))){
11 toby 285
#ifdef MACMACHO
98 toby 286
                e = make_bundle(sfr,plugvol,plugdir,plugname);
11 toby 287
#else
98 toby 288
                e = make_singlefile(sfr,plugvol,plugdir,plugname);
11 toby 289
#endif
98 toby 290
        }
2 toby 291
 
292
        if(e && e != userCanceledErr)
293
                alertuser("Could not create standalone plugin.","");
294
 
295
        return e;
296
}