Subversion Repositories filter_foundry

Rev

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