Subversion Repositories filter_foundry

Rev

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

Rev Author Line No. Line
256 daniel-mar 1
/*
2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
536 daniel-mar 3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
541 daniel-mar 4
    Copyright (C) 2018-2023 Daniel Marschall, ViaThinkSoft
256 daniel-mar 5
 
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
20
 
21
#include "ff.h"
22
 
23
#include "file_compat.h"
24
 
25
#ifdef MAC_ENV
26
#include <Endian.h>
27
#else
28
int EndianS32_LtoN(int num) {
272 daniel-mar 29
        return ((num>>24)&0xff) +      // move byte 3 to byte 0
30
               ((num<<8)&0xff0000) +   // move byte 1 to byte 2
31
               ((num>>8)&0xff00) +     // move byte 2 to byte 1
256 daniel-mar 32
               ((num<<24)&0xff000000); // byte 0 to byte 3
33
}
34
#endif
35
 
518 daniel-mar 36
#define BUFSIZE 4L<<10
37
#define MAXLINE 0x200
256 daniel-mar 38
 
492 daniel-mar 39
Boolean readparams_afs_pff(Handle h, TCHAR**reason){
256 daniel-mar 40
        Boolean res = false;
454 daniel-mar 41
        char linebuf[MAXLINE + 1] = { 0 };
42
        char curexpr[MAXEXPR + 1] = { 0 };
43
        char *p, *dataend, *q;
256 daniel-mar 44
        char c;
45
        int linecnt, lineptr, exprcnt;
46
 
482 daniel-mar 47
        if (!h) return false;
256 daniel-mar 48
 
49
        p = PILOCKHANDLE(h,false);
50
        dataend = p + PIGETHANDLESIZE(h);
51
 
52
        q = curexpr;
53
        linecnt = exprcnt = lineptr = 0;
54
 
55
        while(p < dataend){
56
 
57
                c = *p++;
58
 
59
                if(c==CR || c==LF){ /* detected end of line */
60
 
421 daniel-mar 61
                        /* look ahead to see if we need to skip a line feed (DOS CRLF EOL convention) */
62
                        if(p < dataend && c == CR && *p == LF)
256 daniel-mar 63
                                ++p;
64
 
539 daniel-mar 65
                        linebuf[lineptr] = '\0'; /* add terminating NUL to line buffer */
256 daniel-mar 66
 
67
                        /* process complete line */
68
                        if(linecnt==0){
539 daniel-mar 69
                                if(strcmp(linebuf,"%RGB-1.0") != 0){
498 daniel-mar 70
                                        // Note: We don't set *reason, because we cannot be sure if it is a valid file in regards to a different data type
71
                                        // We only set *Reason, if we are sure that it is an AFS file which is indeed wrong.
256 daniel-mar 72
                                        break;
73
                                }
74
                        }else if(linecnt<=8){
453 daniel-mar 75
                                int v;
76
                                v = atoi(linebuf);
77
                                if (v < 0) v = 0;
456 daniel-mar 78
                                else if (v > 255) v = 255;
79
                                slider[linecnt-1] = (uint8_t)v;
256 daniel-mar 80
                        }else{
81
                                if(lineptr){
82
                                        /* it's not an empty line; append it to current expr string */
83
                                        if( q+lineptr > curexpr+MAXEXPR ){
492 daniel-mar 84
                                                // TODO: isn't the limit 1024?! (because we need to have the NUL too?)
498 daniel-mar 85
                                                if (reason) *reason = FF_GetMsg_Cpy(MSG_EXPRESSION1024_FOUND_ID);
256 daniel-mar 86
                                                break;
87
                                        }
88
                                        q = cat(q,linebuf);
89
                                }else{
90
                                        /* it's an empty line: we've completed the expr string */
91
                                        if(expr[exprcnt])
92
                                                free(expr[exprcnt]);
539 daniel-mar 93
                                        *q = '\0';
256 daniel-mar 94
                                        if(!(expr[exprcnt] = my_strdup(curexpr))){
498 daniel-mar 95
                                                if (reason) *reason = FF_GetMsg_Cpy(MSG_EXPRESSION_OOM_ID);
256 daniel-mar 96
                                                break;
97
                                        }
98
 
99
                                        if(++exprcnt == 4){
100
                                                res = true;
101
                                                break; /* got everything we want */
102
                                        }
103
 
104
                                        q = curexpr; /* empty current expr, ready for next one */
105
                                }
106
                        }
107
 
108
                        ++linecnt;
109
                        lineptr = 0;
110
                }else{
111
                        /* store character */
112
                        if(c=='\\'){ /* escape sequence */
113
                                if(p < dataend){
114
                                        c = *p++;
115
                                        switch(c){
116
                                        case 'r':
268 daniel-mar 117
                                                #if WIN_ENV
118
                                                c = CR;
119
                                                if (lineptr < MAXLINE)
274 daniel-mar 120
                                                        linebuf[lineptr++] = c;
268 daniel-mar 121
                                                c = LF;
122
                                                #else
123
                                                c = CR;
124
                                                #endif
125
                                                break;
256 daniel-mar 126
                                        case '\\': break;
408 daniel-mar 127
                                        //default:
492 daniel-mar 128
                                        //      if(alerts) alertuser((TCHAR*)TEXT("Warning:"),TEXT("Unknown escape sequence in input.")); // TODO (Not so important): TRANSLATE
256 daniel-mar 129
                                        }
492 daniel-mar 130
                                }//else if(alerts) alertuser((TCHAR*)TEXT("Warning:"),TEXT("truncated escape sequence ends input")); // TODO (Not so important): TRANSLATE
256 daniel-mar 131
                        }
132
 
133
                        if(lineptr < MAXLINE)
134
                                linebuf[lineptr++] = c;
135
                }
136
        }
137
 
138
        PIUNLOCKHANDLE(h);
139
 
140
        return res;
141
}
142
 
143
void convert_premiere_to_photoshop(PARM_T* photoshop, PARM_T_PREMIERE* premiere) {
144
        int i;
145
 
146
        photoshop->cbSize = sizeof(PARM_T);
147
        photoshop->standalone = premiere->standalone;
148
        for (i=0;i<8;++i)
272 daniel-mar 149
                photoshop->val[i] = premiere->val[i];
256 daniel-mar 150
        photoshop->popDialog = premiere->popDialog;
151
        photoshop->unknown1 = premiere->unknown1;
152
        photoshop->unknown2 = premiere->unknown2;
153
        photoshop->unknown3 = premiere->unknown3;
154
        for (i=0;i<4;++i)
272 daniel-mar 155
                photoshop->map_used[i] = premiere->map_used[i];
256 daniel-mar 156
        for (i=0;i<8;++i)
272 daniel-mar 157
                photoshop->ctl_used[i] = premiere->ctl_used[i];
393 daniel-mar 158
        sprintf(photoshop->szCategory, "Filter Factory"); // Premiere plugins do not have a category attribute
256 daniel-mar 159
        photoshop->iProtected = 0; // Premiere plugins do not have a protect flag
393 daniel-mar 160
        memcpy((void*)photoshop->szTitle, (void*)premiere->szTitle, sizeof(photoshop->szTitle));
161
        memcpy((void*)photoshop->szCopyright, (void*)premiere->szCopyright, sizeof(photoshop->szCopyright));
162
        memcpy((void*)photoshop->szAuthor, (void*)premiere->szAuthor, sizeof(photoshop->szAuthor));
256 daniel-mar 163
        for (i=0;i<4;++i)
393 daniel-mar 164
                memcpy((void*)photoshop->szMap[i], (void*)premiere->szMap[i], sizeof(photoshop->szMap[i]));
256 daniel-mar 165
        for (i=0;i<8;++i)
393 daniel-mar 166
                memcpy((void*)photoshop->szCtl[i], (void*)premiere->szCtl[i], sizeof(photoshop->szCtl[i]));
256 daniel-mar 167
 
168
        if (premiere->singleExpression) {
393 daniel-mar 169
                memcpy((void*)photoshop->szFormula[0], (void*)premiere->szFormula[3], sizeof(photoshop->szFormula[3]));
170
                memcpy((void*)photoshop->szFormula[1], (void*)premiere->szFormula[3], sizeof(photoshop->szFormula[3]));
171
                memcpy((void*)photoshop->szFormula[2], (void*)premiere->szFormula[3], sizeof(photoshop->szFormula[3]));
172
                memcpy((void*)photoshop->szFormula[3], (void*)premiere->szFormula[3], sizeof(photoshop->szFormula[3]));
256 daniel-mar 173
        } else {
393 daniel-mar 174
                memcpy((void*)photoshop->szFormula[0], (void*)premiere->szFormula[2], sizeof(photoshop->szFormula[2]));
175
                memcpy((void*)photoshop->szFormula[1], (void*)premiere->szFormula[1], sizeof(photoshop->szFormula[1]));
176
                memcpy((void*)photoshop->szFormula[2], (void*)premiere->szFormula[0], sizeof(photoshop->szFormula[0]));
177
                memcpy((void*)photoshop->szFormula[3], (void*)premiere->szFormula[3], sizeof(photoshop->szFormula[3]));
256 daniel-mar 178
        }
179
}
180
 
366 daniel-mar 181
char* _ffx_read_str(char** q) {
182
        uint32_t len;
183
        char* val;
184
 
185
        len = *((uint32_t*)*q);
186
        *q += sizeof(uint32_t);
454 daniel-mar 187
        val = (char*)malloc((size_t)len + 1);
366 daniel-mar 188
        if (val != NULL) {
189
                memcpy(val, (char*)*q, len);
539 daniel-mar 190
                val[len] = '\0';
366 daniel-mar 191
        }
192
        *q += len;
193
        return val;
194
}
195
 
492 daniel-mar 196
Boolean readfile_ffx(StandardFileReply* sfr, TCHAR** reason) {
366 daniel-mar 197
        Handle h;
198
        Boolean res = false;
199
        FILEREF refnum;
200
        uint32_t len;
201
        char* val;
367 daniel-mar 202
        int format_version = -1;
366 daniel-mar 203
        int i;
204
 
433 daniel-mar 205
        UNREFERENCED_PARAMETER(reason);
206
 
366 daniel-mar 207
        if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
208
                if ((h = readfileintohandle(refnum))) {
209
                        char* q = (char*)PILOCKHANDLE(h, false);
210
 
211
                        len = *((uint32_t*)q);
212
                        if (len == 6) {
213
                                val = _ffx_read_str(&q);
367 daniel-mar 214
                                if (strcmp(val, "FFX1.0") == 0) format_version = 10;
215
                                else if (strcmp(val, "FFX1.1") == 0) format_version = 11;
216
                                else if (strcmp(val, "FFX1.2") == 0) format_version = 12;
366 daniel-mar 217
                                free(val);
367 daniel-mar 218
                                if (format_version > 0) {
492 daniel-mar 219
                                        simplewarning_id(MSG_FILTERS_UNLIMITED_WARNING_ID);
368 daniel-mar 220
 
366 daniel-mar 221
                                        val = _ffx_read_str(&q);
541 daniel-mar 222
                                        if (strlen(val) >= sizeof(gdata->parm.szTitle)) {
223
                                                val[sizeof(gdata->parm.szTitle) - 1] = '\0';
224
                                        }
393 daniel-mar 225
                                        strcpy(gdata->parm.szTitle, val);
366 daniel-mar 226
                                        free(val);
227
 
228
                                        val = _ffx_read_str(&q);
541 daniel-mar 229
                                        if (strlen(val) >= sizeof(gdata->parm.szCategory)) {
230
                                                val[sizeof(gdata->parm.szCategory) - 1] = '\0';
231
                                        }
393 daniel-mar 232
                                        strcpy(gdata->parm.szCategory, val);
366 daniel-mar 233
                                        free(val);
234
 
235
                                        val = _ffx_read_str(&q);
541 daniel-mar 236
                                        if (strlen(val) >= sizeof(gdata->parm.szAuthor)) {
237
                                                val[sizeof(gdata->parm.szAuthor) - 1] = '\0';
238
                                        }
393 daniel-mar 239
                                        strcpy(gdata->parm.szAuthor, val);
366 daniel-mar 240
                                        free(val);
241
 
242
                                        val = _ffx_read_str(&q);
541 daniel-mar 243
                                        if (strlen(val) >= sizeof(gdata->parm.szCopyright)) {
244
                                                val[sizeof(gdata->parm.szCopyright) - 1] = '\0';
245
                                        }
393 daniel-mar 246
                                        strcpy(gdata->parm.szCopyright, val);
366 daniel-mar 247
                                        free(val);
248
 
249
                                        // Channels I, R, G, B, A
250
                                        for (i = 0; i < 4; i++) {
251
                                                val = _ffx_read_str(&q);
252
                                                if (i == 0) {
370 daniel-mar 253
                                                        char* val2 = _ffx_read_str(&q);
366 daniel-mar 254
                                                        if (strcmp(val, "0") != 0) {
255
                                                                // "Intro channel" existing
370 daniel-mar 256
                                                                // C++ wrong warning: Using uninitialized memory "val2" (C6001)
257
                                                                #pragma warning(suppress : 6001)
541 daniel-mar 258
                                                                char* combined = (char*)malloc(strlen(val) + strlen(",") + strlen(val2) + 1/*NUL byte*/);
370 daniel-mar 259
                                                                if (combined != NULL) {
260
                                                                        sprintf(combined, "%s,%s", val, val2);
261
                                                                        free(val);
262
                                                                        free(val2);
263
                                                                        val = combined;
264
                                                                }
366 daniel-mar 265
                                                        }
266
                                                        else {
267
                                                                free(val);
370 daniel-mar 268
                                                                val = val2;
366 daniel-mar 269
                                                        }
270
                                                }
393 daniel-mar 271
                                                if (strlen(val) >= sizeof(gdata->parm.szFormula[i])) {
368 daniel-mar 272
                                                        if (i == 0) {
492 daniel-mar 273
                                                                simplealert_id(MSG_FORMULA_IR_1023_TRUNCATED_ID);
368 daniel-mar 274
                                                        }
275
                                                        else if (i == 1) {
492 daniel-mar 276
                                                                simplealert_id(MSG_FORMULA_G_1023_TRUNCATED_ID);
368 daniel-mar 277
                                                        }
278
                                                        else if (i == 2) {
492 daniel-mar 279
                                                                simplealert_id(MSG_FORMULA_B_1023_TRUNCATED_ID);
368 daniel-mar 280
                                                        }
281
                                                        else if (i == 3) {
492 daniel-mar 282
                                                                simplealert_id(MSG_FORMULA_A_1023_TRUNCATED_ID);
368 daniel-mar 283
                                                        }
370 daniel-mar 284
                                                        // C++ wrong warning: Buffer overflow (C6386)
285
                                                        #pragma warning(suppress : 6386)
393 daniel-mar 286
                                                        val[sizeof(gdata->parm.szFormula[i]) - 1] = '\0';
368 daniel-mar 287
                                                }
395 daniel-mar 288
                                                if (expr[i]) free(expr[i]);
366 daniel-mar 289
                                                expr[i] = my_strdup(val);
393 daniel-mar 290
                                                strcpy(gdata->parm.szFormula[i], val);
366 daniel-mar 291
                                                free(val);
292
                                        }
293
 
294
                                        // Sliders
295
                                        for (i = 0; i < 8; i++) {
367 daniel-mar 296
                                                char* sliderName;
453 daniel-mar 297
                                                int v;
366 daniel-mar 298
                                                val = _ffx_read_str(&q);
367 daniel-mar 299
                                                sliderName = val;
300
                                                if (format_version >= 12) {
301
                                                        // Format FFX1.2 has prefixes {S} = Slider, {C} = Checkbox, none = Slider
302
                                                        if ((sliderName[0] == '{') && (sliderName[1] == 'S') && (sliderName[2] == '}')) sliderName += 3;
303
                                                        else if ((sliderName[0] == '{') && (sliderName[1] == 'C') && (sliderName[2] == '}')) sliderName += 3;
304
                                                }
541 daniel-mar 305
                                                if (strlen(val) >= sizeof(gdata->parm.szCtl[i])) {
306
                                                        val[sizeof(gdata->parm.szCtl[i]) - 1] = '\0';
307
                                                }
393 daniel-mar 308
                                                strcpy(gdata->parm.szCtl[i], sliderName);
366 daniel-mar 309
                                                free(val);
367 daniel-mar 310
                                                gdata->parm.ctl_used[i] = (bool32_t)*((byte*)q);
366 daniel-mar 311
                                                q += sizeof(byte);
312
                                                gdata->parm.val[i] = *((uint32_t*)q);
453 daniel-mar 313
                                                v = *((uint32_t*)q);
314
                                                if (v < 0) v = 0;
456 daniel-mar 315
                                                else if (v > 255) v = 255;
316
                                                slider[i] = (uint8_t)v;
366 daniel-mar 317
                                                q += sizeof(uint32_t);
318
                                        }
319
 
390 daniel-mar 320
                                        // Maps (are not part of the format!)
393 daniel-mar 321
                                        strcpy(gdata->parm.szMap[0], "Map 0:");
322
                                        strcpy(gdata->parm.szMap[1], "Map 1:");
323
                                        strcpy(gdata->parm.szMap[2], "Map 2:");
324
                                        strcpy(gdata->parm.szMap[3], "Map 3:");
390 daniel-mar 325
 
366 daniel-mar 326
                                        res = true;
327
                                }
328
                        }
329
                        PIDISPOSEHANDLE(h);
330
                }
331
                FSClose(refnum);
332
        }
333
 
334
        if (res) gdata->obfusc = false;
335
        return res;
336
}
337
 
492 daniel-mar 338
Boolean readfile_8bf(StandardFileReply *sfr, TCHAR**reason){
256 daniel-mar 339
        unsigned char magic[2];
340
        FILECOUNT count;
341
        Handle h;
342
        Boolean res = false;
343
        FILEREF refnum;
344
 
345
        if(FSpOpenDF(&sfr->sfFile,fsRdPerm,&refnum) == noErr){
346
                // check DOS EXE magic number
347
                count = 2;
348
                if(FSRead(refnum,&count,magic) == noErr /*&& magic[0]=='M' && magic[1]=='Z'*/){
309 daniel-mar 349
                        if(GetEOF(refnum,(FILEPOS*)&count) == noErr && count < 4096L<<10){ // sanity check file size < 4MiB (note that "Debug" builds can have approx 700 KiB while "Release" builds have approx 300 KiB)
256 daniel-mar 350
                                if( (h = readfileintohandle(refnum)) ){
351
                                        long *q = (long*)PILOCKHANDLE(h,false);
352
 
353
                                        // look for signature at start of valid PARM resource
354
                                        // This signature is observed in Filter Factory standalones.
355
                                        for( count /= 4 ; count >= PARM_SIZE/4 ; --count, ++q )
356
                                        {
394 daniel-mar 357
                                                res = readPARM(&gdata->parm, (Ptr)q);
256 daniel-mar 358
                                                if (res) break;
359
                                        }
341 daniel-mar 360
 
256 daniel-mar 361
                                        PIDISPOSEHANDLE(h);
362
                                }
363
                        }
364
                } // else no point in proceeding
365
                FSClose(refnum);
366
        }else
498 daniel-mar 367
                if (reason) *reason = FF_GetMsg_Cpy(MSG_CANNOT_OPEN_FILE_ID);
256 daniel-mar 368
 
369
        if (res) gdata->obfusc = false;
370
        return res;
371
}
372
 
394 daniel-mar 373
Boolean readPARM(PARM_T* pparm, Ptr p){
374
        Boolean towin, tomac, fromwin, frommac;
375
        unsigned int signature = *((unsigned int*)p);
376
        unsigned int standalone = *((unsigned int*)p+1);
256 daniel-mar 377
 
394 daniel-mar 378
        // Find out our OS ("reader") the OS of the plugin ("source")
379
        #ifdef MAC_ENV
380
        towin = false;
381
        tomac = true;
382
        fromwin = ((EndianS32_LtoN(signature) == PARM_SIZE) ||
383
                (EndianS32_LtoN(signature) == PARM_SIZE_PREMIERE) ||
384
                (EndianS32_LtoN(signature) == PARM_SIG_MAC)) && EndianS32_LtoN(standalone) == 1;
385
        frommac = ((signature == PARM_SIZE) ||
386
                (signature == PARM_SIZE_PREMIERE) ||
387
                (signature == PARM_SIG_MAC)) && standalone == 1;
388
        #else
389
        towin = true;
390
        tomac = false;
391
        fromwin = ((signature == PARM_SIZE) ||
392
                (signature == PARM_SIZE_PREMIERE) ||
393
                (signature == PARM_SIG_MAC)) && standalone == 1;
394
        frommac = ((EndianS32_LtoN(signature) == PARM_SIZE) ||
395
                (EndianS32_LtoN(signature) == PARM_SIZE_PREMIERE) ||
396
                (EndianS32_LtoN(signature) == PARM_SIG_MAC)) && EndianS32_LtoN(standalone) == 1;
397
        #endif
398
 
399
        // Is it a valid signature?
400
        if (!fromwin && !frommac) {
401
                // No valid signature found
402
                return false;
403
        }
404
 
405
        // Does it come from Premiere or Photoshop?
406
        // Initialize pparm
407
        if ((signature == PARM_SIZE_PREMIERE) || (EndianS32_LtoN(signature) == PARM_SIZE_PREMIERE)) {
408
                // It comes from Premiere. Swap R and B channel and convert to a Photoshop PARM_T
256 daniel-mar 409
                convert_premiere_to_photoshop(pparm, (PARM_T_PREMIERE*)p);
410
        } else {
394 daniel-mar 411
                // It is already Photoshop. Just copy to pparm.
412
                memcpy(pparm, p, sizeof(PARM_T));
256 daniel-mar 413
        }
414
 
394 daniel-mar 415
        // Do we need to do string conversion?
416
        if (frommac) {
456 daniel-mar 417
                int i;
418
 
394 daniel-mar 419
                /* Mac PARM resource stores Pascal strings - convert to C strings, since this is what we work internally with (regardles of OS) */
393 daniel-mar 420
                myp2cstr((unsigned char*)pparm->szCategory);
421
                myp2cstr((unsigned char*)pparm->szTitle);
422
                myp2cstr((unsigned char*)pparm->szCopyright);
423
                myp2cstr((unsigned char*)pparm->szAuthor);
394 daniel-mar 424
                for (i = 0; i < 4; ++i)
393 daniel-mar 425
                        myp2cstr((unsigned char*)pparm->szMap[i]);
394 daniel-mar 426
                for (i = 0; i < 8; ++i)
393 daniel-mar 427
                        myp2cstr((unsigned char*)pparm->szCtl[i]);
256 daniel-mar 428
        }
429
 
394 daniel-mar 430
        // Case #1: Mac is reading Windows (Win16/32/64) plugin
431
        if (fromwin && tomac) {
432
                size_t i;
433
 
434
                // Convert copyright CRLF to CR (actually, just removing LF)
454 daniel-mar 435
                char copyrightCRLF[256] = { 0 };
456 daniel-mar 436
                char* pCopyright = &copyrightCRLF[0];
394 daniel-mar 437
                for (i = 0; i < strlen(pparm->szCopyright); i++) {
438
                        if (pparm->szCopyright[i] != LF) {
456 daniel-mar 439
                                *pCopyright++ = pparm->szCopyright[i];
394 daniel-mar 440
                        }
441
                }
456 daniel-mar 442
                *pCopyright++ = '\0';
394 daniel-mar 443
                strcpy(pparm->szCopyright, copyrightCRLF);
444
 
445
                // these are the only numeric fields we *have* to swap
446
                // all the rest are bool_t flags which (if we're careful) will work in either ordering
447
                for (i = 0; i < 8; ++i)
448
                        pparm->val[i] = EndianS32_LtoN(pparm->val[i]);
449
        }
450
 
451
        // Case #2: Mac is reading Mac (in case the normal resource extraction didn't work)
452
        // Nothing to do
453
 
454
        // Case #3: Windows is reading a Windows plugin (if Resource API failed, e.g. Win64 tries to open Win16 NE file or Win32 tries to open Win64 file)
455
        // Nothing to do
456
 
457
        // Case #4: Windows is reading an old FilterFactory Mac file
458
        // Note: You must read the ".rsrc" resource fork, not the standalone binary!
459
        if (frommac && towin) {
460
                size_t i;
461
 
462
                // Convert CR in the copyright field to CRLF.
454 daniel-mar 463
                char copyrightCRLF[256] = { 0 };
456 daniel-mar 464
                char* pCopyright = &copyrightCRLF[0];
394 daniel-mar 465
                for (i = 0; i < strlen(pparm->szCopyright); i++) {
456 daniel-mar 466
                        *pCopyright++ = pparm->szCopyright[i];
394 daniel-mar 467
                        if (pparm->szCopyright[i] == CR) {
456 daniel-mar 468
                                *pCopyright++ = LF;
394 daniel-mar 469
                        }
470
                }
456 daniel-mar 471
                *pCopyright++ = '\0';
394 daniel-mar 472
                strcpy(pparm->szCopyright, copyrightCRLF);
473
 
474
                // these are the only numeric fields we *have* to swap
475
                // all the rest are bool_t flags which (if we're careful) will work in either ordering
476
                for (i = 0; i < 8; ++i)
477
                        pparm->val[i] = EndianS32_LtoN(pparm->val[i]);
478
        }
479
 
480
        // Now set the values in pparm into the working variables expr[] and slider[], so that they are visible in the GUI
456 daniel-mar 481
        {
482
                int i;
483
                for (i = 0; i < 4; ++i) {
484
                        if (expr[i]) free(expr[i]);
485
                        expr[i] = my_strdup(pparm->szFormula[i]);
486
                }
394 daniel-mar 487
 
456 daniel-mar 488
                for (i = 0; i < 8; ++i) {
489
                        slider[i] = (uint8_t)pparm->val[i];
490
                        /*
491
                        if (slider[i] > 0xFF) {
492
                                // Wrong endianess (e.g. reading a Mac rsrc on Windows)
493
                                // Should not happen since we did the stuff above
494
                                slider[i] = (uint8_t)EndianS32_LtoN(slider[i]);
495
                        }
496
                        */
339 daniel-mar 497
                }
498
        }
256 daniel-mar 499
 
500
        return true;
501
}
502
 
503
Handle readfileintohandle(FILEREF r){
504
        FILEPOS n;
505
        Handle h;
506
        Ptr p;
507
 
508
        if( GetEOF(r,&n) == noErr && (h = PINEWHANDLE(n)) ){
509
                p = PILOCKHANDLE(h,false);
510
                if(SetFPos(r,fsFromStart,0) == noErr && FSRead(r,(FILECOUNT*)&n,p) == noErr){
511
                        PIUNLOCKHANDLE(h);
512
                        return h;
513
                }
514
                PIDISPOSEHANDLE(h);
515
        }
516
        return NULL;
517
}
518
 
385 daniel-mar 519
Boolean _picoLineContainsKey(char* line, char** content, const char* searchkey/*=NULL*/) {
386 daniel-mar 520
        size_t i;
521
        for (i = 0; i < strlen(line); i++) {
388 daniel-mar 522
                if (line[i] == '?') break; // avoid that "a?b:c" is detected as key
385 daniel-mar 523
                if (line[i] == ':') {
386 daniel-mar 524
                        // Note: We are ignoring whitespaces, i.e. " A :" != "A:" (TODO: should we change this?)
525
                        if ((searchkey == NULL) || ((i == strlen(searchkey)) && (memcmp(line, searchkey, i) == 0))) {
526
                                i++; // jump over ':' char
387 daniel-mar 527
                                //while ((line[i] == ' ') || (line[i] == TAB)) i++; // Trim value left
385 daniel-mar 528
                                *content = line + i;
529
                                return true;
530
                        }
531
                }
532
        }
533
        *content = line;
534
        return false;
535
}
536
 
388 daniel-mar 537
void _ffdcomp_removebrackets(char* x, char* maxptr) {
538
        char* closingBracketPos = NULL;
539
        Boolean openingBracketFound = false;
540
        if (x[0] == '[') {
541
                openingBracketFound = true;
542
        }
543
        x[0] = ':';
544
        x++;
545
        while (x < maxptr) {
546
                if ((!openingBracketFound) && (x[0] == '[')) {
547
                        openingBracketFound = true;
548
                        x[0] = ' ';
549
                }
550
                else if (openingBracketFound) {
551
                        if (x[0] == ']') {
552
                                closingBracketPos = x;
553
                        }
554
                        else if ((x[0] == CR) || (x[0] == LF)) {
555
                                if (closingBracketPos) closingBracketPos[0] = ' '; // last closing pos before CR/LF
556
                                break;
557
                        }
558
                }
559
                x++;
560
        }
561
}
562
 
393 daniel-mar 563
// isFormula=false => outputFile is C string. TXT linebreaks become spaces.
386 daniel-mar 564
// isFormula=true  => outputFile is C string. TXT line breaks become CRLF line breaks
505 daniel-mar 565
Boolean _picoReadProperty(char* inputFile, size_t maxInput, const char* property, char* outputFile, size_t maxOutput, Boolean isFormula) {
566
        size_t i;
386 daniel-mar 567
        char* outputwork;
568
        char* sline;
569
        char* svalue;
570
        char* inputwork;
571
        char* inputworkinitial;
572
        outputwork = outputFile;
573
        sline = NULL;
574
        svalue = NULL;
385 daniel-mar 575
        // Check parameters
386 daniel-mar 576
        if (maxOutput == 0) return false;
539 daniel-mar 577
        if (inputFile == NULL) return false;
385 daniel-mar 578
        // Let input memory be read-only, +1 for terminal zero
579
        //char* inputwork = inputFile;
541 daniel-mar 580
        inputwork = (char*)malloc((size_t)maxInput + 1/*NUL byte*/);
386 daniel-mar 581
        inputworkinitial = inputwork;
539 daniel-mar 582
        if (inputwork == NULL) return false;
385 daniel-mar 583
        memcpy(inputwork, inputFile, maxInput);
539 daniel-mar 584
        inputwork[maxInput] = '\0'; // otherwise strstr() will crash
388 daniel-mar 585
 
586
        // Transform "FFDecomp" TXT file into the similar "PluginCommander" TXT file
587
        if (strstr(inputwork, "Filter Factory Plugin Information:")) {
588
                char* x;
589
                char* k1;
590
                char* k2;
591
                // Metadata:
592
                x = strstr(inputwork, "CATEGORY:");
389 daniel-mar 593
                if (x) memcpy(x, "Category:", strlen("Category:"));
388 daniel-mar 594
                x = strstr(inputwork, "TITLE:");
389 daniel-mar 595
                if (x) memcpy(x, "Title:", strlen("Title:"));
388 daniel-mar 596
                x = strstr(inputwork, "COPYRIGHT:");
389 daniel-mar 597
                if (x) memcpy(x, "Copyright:", strlen("Copyright:"));
388 daniel-mar 598
                x = strstr(inputwork, "AUTHOR:");
389 daniel-mar 599
                if (x) memcpy(x, "Author:", strlen("Author:"));
388 daniel-mar 600
                // Controls:
601
                for (i = 0; i < 8; i++) {
541 daniel-mar 602
                        k1 = (char*)malloc(strlen("Control X:") + 1/*NUL byte*/);
505 daniel-mar 603
                        sprintf(k1, "Control %d:", (int)i);
388 daniel-mar 604
                        x = strstr(inputwork, k1);
605
                        if (x) {
541 daniel-mar 606
                                k2 = (char*)malloc(strlen("ctl[X]:   ") + 1/*NUL byte*/);
505 daniel-mar 607
                                sprintf(k2, "ctl[%d]:   ", (int)i);
389 daniel-mar 608
                                memcpy(x, k2, strlen(k2));
388 daniel-mar 609
                                x += strlen("ctl[X]");
610
                                _ffdcomp_removebrackets(x, inputwork + maxInput - 1);
611
                                free(k2);
612
                        }
613
                        free(k1);
614
                }
615
                // Maps:
616
                for (i = 0; i < 4; i++) {
541 daniel-mar 617
                        k1 = (char*)malloc(strlen("Map X:") + 1/*NUL byte*/);
505 daniel-mar 618
                        sprintf(k1, "Map %d:", (int)i);
388 daniel-mar 619
                        x = strstr(inputwork, k1);
620
                        if (x) {
541 daniel-mar 621
                                k2 = (char*)malloc(strlen("map[X]:") + 1/*NUL byte*/);
505 daniel-mar 622
                                sprintf(k2, "map[%d]:", (int)i);
389 daniel-mar 623
                                memcpy(x, k2, strlen(k2));
388 daniel-mar 624
                                x += strlen("map[X]");
625
                                _ffdcomp_removebrackets(x, inputwork + maxInput - 1);
626
                                free(k2);
627
                        }
628
                        free(k1);
629
                }
630
                // Convert all '\r' to '\n' for the next step to be easier
631
                for (i = 0; i < maxInput; i++) {
632
                        if (inputworkinitial[i] == CR) inputworkinitial[i] = LF;
633
                }
634
                x = strstr(inputwork, "\nR=\n");
389 daniel-mar 635
                if (x) memcpy(x, "\nR:\n", strlen("\nR:\n"));
388 daniel-mar 636
                x = strstr(inputwork, "\nG=\n");
389 daniel-mar 637
                if (x) memcpy(x, "\nG:\n", strlen("\nG:\n"));
388 daniel-mar 638
                x = strstr(inputwork, "\nB=\n");
389 daniel-mar 639
                if (x) memcpy(x, "\nB:\n", strlen("\nB:\n"));
388 daniel-mar 640
                x = strstr(inputwork, "\nA=\n");
389 daniel-mar 641
                if (x) memcpy(x, "\nA:\n", strlen("\nA:\n"));
388 daniel-mar 642
        }
385 daniel-mar 643
        // Replace all \r and \n with \0, so that we can parse easier
386 daniel-mar 644
        for (i = 0; i < maxInput; i++) {
539 daniel-mar 645
                if (inputworkinitial[i] == CR) inputworkinitial[i] = '\0';
646
                else if (inputworkinitial[i] == LF) inputworkinitial[i] = '\0';
385 daniel-mar 647
        }
388 daniel-mar 648
 
385 daniel-mar 649
        // Find line that contains out key
388 daniel-mar 650
        inputwork = inputworkinitial;
385 daniel-mar 651
        do {
652
                if (inputwork > inputworkinitial + maxInput) {
653
                        // Key not found. Set output to empty string
539 daniel-mar 654
                        outputwork[0] = '\0';
385 daniel-mar 655
                        free(inputworkinitial);
656
                        return false;
657
                }
658
                sline = inputwork;
659
                inputwork += strlen(sline) + 1;
660
                if (inputwork - 1 > inputworkinitial + maxInput) {
661
                        // Key not found. Set output to empty string
662
                        // TODO: will that be ever called?
539 daniel-mar 663
                        outputwork[0] = '\0';
385 daniel-mar 664
                        free(inputworkinitial);
665
                        return false;
666
                }
667
        } while (!_picoLineContainsKey(sline, &svalue, property));
388 daniel-mar 668
 
385 daniel-mar 669
        // Read line(s) until we find a line with another key, or the line end
670
        do {
387 daniel-mar 671
                while ((svalue[0] == ' ') || (svalue[0] == TAB)) svalue++; // Trim left
539 daniel-mar 672
                while ((svalue[strlen(svalue) - 1] == ' ') || (svalue[strlen(svalue) - 1] == TAB)) svalue[strlen(svalue) - 1] = '\0'; // Trim right
386 daniel-mar 673
 
385 daniel-mar 674
                if (strlen(svalue) > 0) {
393 daniel-mar 675
                        if (outputwork + strlen(svalue) + (isFormula ? 3/*CRLF+NUL*/ : 2/*space+NUL*/) > outputFile + maxOutput) {
444 daniel-mar 676
                                size_t remaining = maxOutput - (outputwork - outputFile) - 1;
385 daniel-mar 677
                                //printf("BUFFER FULL (remaining = %d)\n", remaining);
678
                                memcpy(outputwork, svalue, remaining);
679
                                outputwork += remaining;
539 daniel-mar 680
                                outputwork[0] = '\0';
385 daniel-mar 681
                                free(inputworkinitial);
682
                                return true;
683
                        }
684
                        else {
685
                                memcpy(outputwork, svalue, strlen(svalue));
686
                                outputwork += strlen(svalue);
386 daniel-mar 687
                                if (isFormula) {
688
                                        // Formulas: TXT line break stays line break (important if you have comments!)
388 daniel-mar 689
                                        outputwork[0] = CR;
690
                                        outputwork[1] = LF;
387 daniel-mar 691
                                        outputwork += 2;
386 daniel-mar 692
                                }
693
                                else {
694
                                        // Everything else: TXT line breaks becomes single whitespace
695
                                        outputwork[0] = ' ';
696
                                        outputwork++;
697
                                }
385 daniel-mar 698
                        }
699
                }
539 daniel-mar 700
                outputwork[0] = '\0';
385 daniel-mar 701
 
702
                // Process next line
703
                if (inputwork > inputworkinitial + maxInput) break;
704
                sline = inputwork;
705
                inputwork += strlen(sline) + 1;
386 daniel-mar 706
                if (inputwork - 1 > inputworkinitial + maxInput) break; // TODO: will that be ever called?
385 daniel-mar 707
        } while (!_picoLineContainsKey(sline, &svalue, NULL));
388 daniel-mar 708
 
385 daniel-mar 709
        // Remove trailing whitespace
710
        if (outputwork > outputFile) {
711
                outputwork -= 1;
539 daniel-mar 712
                outputwork[0] = '\0';
385 daniel-mar 713
        }
714
        free(inputworkinitial);
715
        return true;
716
}
717
 
537 daniel-mar 718
Boolean readfile_picotxt_or_ffdecomp(StandardFileReply* sfr, TCHAR** reason) {
389 daniel-mar 719
        extern int ctls[], maps[];
720
 
385 daniel-mar 721
        Handle h;
722
        Boolean res = false;
723
        FILEREF refnum;
724
 
433 daniel-mar 725
        UNREFERENCED_PARAMETER(reason);
726
 
444 daniel-mar 727
        if (!fileHasExtension(sfr, TEXT(".txt"))) return false;
385 daniel-mar 728
 
729
        if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
730
                if ((h = readfileintohandle(refnum))) {
505 daniel-mar 731
                        FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h);
385 daniel-mar 732
                        char* q = PILOCKHANDLE(h, false);
733
 
541 daniel-mar 734
                        char dummy[256];
735
                        if (_picoReadProperty(q, count, "Title", dummy, sizeof(dummy), false)) {
386 daniel-mar 736
                                int i;
385 daniel-mar 737
 
738
                                // Plugin infos
393 daniel-mar 739
                                _picoReadProperty(q, count, "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle), false);
740
                                _picoReadProperty(q, count, "Category", gdata->parm.szCategory, sizeof(gdata->parm.szCategory), false);
741
                                _picoReadProperty(q, count, "Author", gdata->parm.szAuthor, sizeof(gdata->parm.szAuthor), false);
742
                                _picoReadProperty(q, count, "Copyright", gdata->parm.szCopyright, sizeof(gdata->parm.szCopyright), false);
743
                                //_picoReadProperty(q, count, "Filename", gdata->parm.xxx, sizeof(gdata->parm.xxx), false);
385 daniel-mar 744
 
745
                                // Expressions
393 daniel-mar 746
                                if (!_picoReadProperty(q, count, "R", gdata->parm.szFormula[0], sizeof(gdata->parm.szFormula[0]), true))
747
                                        strcpy(gdata->parm.szFormula[0], "r");
748
                                if (!_picoReadProperty(q, count, "G", gdata->parm.szFormula[1], sizeof(gdata->parm.szFormula[1]), true))
749
                                        strcpy(gdata->parm.szFormula[1], "g");
750
                                if (!_picoReadProperty(q, count, "B", gdata->parm.szFormula[2], sizeof(gdata->parm.szFormula[2]), true))
751
                                        strcpy(gdata->parm.szFormula[2], "b");
752
                                if (!_picoReadProperty(q, count, "A", gdata->parm.szFormula[3], sizeof(gdata->parm.szFormula[3]), true))
753
                                        strcpy(gdata->parm.szFormula[3], "a");
386 daniel-mar 754
                                for (i = 0; i < 4; i++) {
385 daniel-mar 755
                                        if (expr[i]) free(expr[i]);
393 daniel-mar 756
                                        expr[i] = my_strdup(gdata->parm.szFormula[i]);
385 daniel-mar 757
                                }
758
 
386 daniel-mar 759
                                for (i = 0; i < 8; i++) {
537 daniel-mar 760
                                        int v;
541 daniel-mar 761
                                        char keyname[6/*strlen("ctl[X]")*/ + 1/*strlen("\0")*/], tmp[5];
537 daniel-mar 762
 
763
                                        // Slider names
385 daniel-mar 764
                                        sprintf(keyname, "ctl[%d]", i);
393 daniel-mar 765
                                        _picoReadProperty(q, count, keyname, gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]), false);
385 daniel-mar 766
 
537 daniel-mar 767
                                        // Slider values
385 daniel-mar 768
                                        sprintf(keyname, "val[%d]", i);
769
                                        if (!_picoReadProperty(q, count, keyname, tmp, sizeof(tmp), false)) {
770
                                                sprintf(keyname, "def[%d]", i);
771
                                                if (!_picoReadProperty(q, count, keyname, tmp, sizeof(tmp), false)) {
393 daniel-mar 772
                                                        strcpy(tmp,"0");
385 daniel-mar 773
                                                }
774
                                        }
453 daniel-mar 775
                                        v = atoi(tmp);
776
                                        if (v < 0) v = 0;
456 daniel-mar 777
                                        else if (v > 255) v = 255;
778
                                        gdata->parm.val[i] = slider[i] = (uint8_t)v;
385 daniel-mar 779
                                }
780
 
781
                                // Map names
386 daniel-mar 782
                                for (i = 0; i < 4; i++) {
541 daniel-mar 783
                                        char keyname[6/*strlen("map[X]")*/ + 1/*strlen("\0")*/];
385 daniel-mar 784
                                        sprintf(keyname, "map[%d]", i);
393 daniel-mar 785
                                        _picoReadProperty(q, count, keyname, gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]), false);
385 daniel-mar 786
                                }
787
 
389 daniel-mar 788
                                //These will be set when the expressions are evaluated anyway. So this part is optional:
789
                                checksliders(4, ctls, maps);
790
                                for (i = 0; i < 8; i++) gdata->parm.ctl_used[i] = ctls[i];
791
                                for (i = 0; i < 4; i++) gdata->parm.map_used[i] = maps[i];
385 daniel-mar 792
 
793
                                res = true;
794
                        }
795
 
796
                        PIUNLOCKHANDLE(h);
797
                        PIDISPOSEHANDLE(h);
798
                }
799
                FSClose(refnum);
800
        }
801
 
802
        return res;
803
}
804
 
539 daniel-mar 805
Boolean _gufReadProperty(char* fileContents, size_t argMaxInputLength, const char* section, const char* keyname, char* argOutput, size_t argMaxOutLength) {
806
        size_t iTmp;
807
        char* tmpFileContents, * tmpSection, * tmpStart, * tmpStart2, * tmpEnd, * tmpKeyname, * tmpStart3, * tmpStart4, * inputwork;
808
 
809
        // Check parameters
810
        if (argMaxOutLength == 0) return false;
811
        if (fileContents == NULL) return false;
812
 
813
        // Handle argMaxInputLength
814
        //char* inputwork = fileContents;
541 daniel-mar 815
        inputwork = (char*)malloc((size_t)argMaxInputLength + 1/*NUL byte*/);
539 daniel-mar 816
        if (inputwork == NULL) return false;
817
        memcpy(inputwork, fileContents, argMaxInputLength);
818
        inputwork[argMaxInputLength] = '\0';
819
 
820
        // Prepare the input file contents to make it easier parse-able
821
        iTmp = strlen(inputwork) + strlen("\n\n[");
541 daniel-mar 822
        tmpFileContents = (char*)malloc(iTmp + 1/*NUL byte*/);
539 daniel-mar 823
        if (tmpFileContents == NULL) return false;
824
        sprintf(tmpFileContents, "\n%s\n[", inputwork);
825
        for (iTmp = 0; iTmp < strlen(tmpFileContents); iTmp++) {
826
                if (tmpFileContents[iTmp] == '\r') tmpFileContents[iTmp] = '\n';
827
        }
828
 
829
        // Find the section begin
830
        iTmp = strlen(section) + strlen("\n[]\n");
541 daniel-mar 831
        tmpSection = (char*)malloc(iTmp + 1/*NUL byte*/);
539 daniel-mar 832
        if (tmpSection == NULL) return false;
833
        sprintf(tmpSection, "\n[%s]\n", section);
834
        tmpStart = strstr(tmpFileContents, tmpSection);
835
        if (tmpStart == NULL) return false;
836
        tmpStart += iTmp;
837
 
838
        // Find the end of the section and set a NULL terminator to it
839
        iTmp = strlen(tmpStart) + strlen("\n");
840
        tmpStart2 = (char*)malloc(iTmp + 1/*NUL byte*/);
841
        if (tmpStart2 == NULL) return false;
842
        sprintf(tmpStart2, "\n%s", tmpStart);
843
        tmpEnd = strstr(tmpStart2, "\n[");
844
        if (tmpEnd == NULL) return false;
845
        tmpEnd[0] = '\0';
846
 
847
        // Find the start of the value
848
        iTmp = strlen(keyname) + strlen("\n=");
849
        tmpKeyname = (char*)malloc(iTmp + 1/*NUL byte*/);
850
        if (tmpKeyname == NULL) return false;
851
        sprintf(tmpKeyname, "\n%s=", keyname);
852
        tmpStart3 = strstr(tmpStart2, tmpKeyname);
853
        if (tmpStart3 == NULL) return false;
854
        tmpStart3 += strlen("\n");
855
        tmpStart4 = strstr(tmpStart3, "=");
856
        if (tmpStart4 == NULL) return false;
857
        tmpStart4 += strlen("=");
858
 
859
        // Find the end of the value
860
        tmpEnd = strstr(tmpStart4, "\n");
861
        if (tmpEnd == NULL) return false;
862
        tmpEnd[0] = '\0';
863
 
864
        // Copy to output
865
        if (strlen(tmpStart4) < argMaxOutLength + 1) argMaxOutLength = strlen(tmpStart4) + 1;
866
        memcpy(argOutput, tmpStart4, argMaxOutLength);
867
        argOutput[argMaxOutLength - 1] = '\0';
868
 
869
        // Free all temporary stuff
870
        //for (iTmp = 0; iTmp < strlen(tmpFileContents); iTmp++) tmpFileContents[iTmp] = '\0';
871
        free(tmpFileContents);
872
        //for (iTmp = 0; iTmp < strlen(tmpSection); iTmp++) tmpSection[iTmp] = '\0';
873
        free(tmpSection);
874
        //for (iTmp = 0; iTmp < strlen(tmpKeyname); iTmp++) tmpKeyname[iTmp] = '\0';
875
        free(tmpKeyname);
876
        //for (iTmp = 0; iTmp < strlen(tmpStart2); iTmp++) tmpStart2[iTmp] = '\0';
877
        free(tmpStart2);
878
 
879
        // Return success
880
        return true;
537 daniel-mar 881
}
882
 
883
Boolean readfile_guf(StandardFileReply* sfr, TCHAR** reason) {
884
        extern int ctls[], maps[];
885
 
886
        Handle h;
887
        Boolean res = false;
888
        FILEREF refnum;
889
 
541 daniel-mar 890
        // TODO: Decode UTF-8 to ANSI (or "?" for unknown characters)
891
 
537 daniel-mar 892
        if (!fileHasExtension(sfr, TEXT(".guf"))) return false;
893
 
894
        if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
895
                if ((h = readfileintohandle(refnum))) {
896
                        FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h);
897
                        char* q = PILOCKHANDLE(h, false);
898
 
899
                        char out[256];
900
                        if (_gufReadProperty(q, count, "GUF", "Protocol", out, sizeof(out))) {
539 daniel-mar 901
                                if (strcmp(out, "1") != 0) {
537 daniel-mar 902
                                        if (reason) *reason = FF_GetMsg_Cpy(MSG_INCOMPATIBLE_GUF_FILE_ID);
539 daniel-mar 903
                                        PIUNLOCKHANDLE(h);
904
                                        PIDISPOSEHANDLE(h);
905
                                        FSClose(refnum);
537 daniel-mar 906
                                        return false;
907
                                }
908
                        }
909
                        else {
910
                                if (reason) *reason = FF_GetMsg_Cpy(MSG_INCOMPATIBLE_GUF_FILE_ID);
539 daniel-mar 911
                                PIUNLOCKHANDLE(h);
912
                                PIDISPOSEHANDLE(h);
913
                                FSClose(refnum);
537 daniel-mar 914
                                return false;
915
                        }
916
                        if (_gufReadProperty(q, count, "Info", "Title", out, sizeof(out))) {
917
                                int i;
541 daniel-mar 918
                                char tmp[256];
919
                                char* tmp2;
537 daniel-mar 920
 
921
                                // Plugin infos
922
                                _gufReadProperty(q, count, "Info", "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle));
541 daniel-mar 923
                                _gufReadProperty(q, count, "Info", "Category", tmp, sizeof(tmp));
924
                                tmp2 = strrchr(tmp, '/');
925
                                if (tmp2 == NULL) {
926
                                        strcpy(gdata->parm.szCategory, tmp);
927
                                } else {
928
                                        strcpy(gdata->parm.szCategory, tmp2+1);
929
                                }
537 daniel-mar 930
                                _gufReadProperty(q, count, "Info", "Author", gdata->parm.szAuthor, sizeof(gdata->parm.szAuthor));
931
                                _gufReadProperty(q, count, "Info", "Copyright", gdata->parm.szCopyright, sizeof(gdata->parm.szCopyright));
932
                                //_gufReadProperty(q, count, "Filter Factory", "8bf", gdata->parm.xxx, sizeof(gdata->parm.xxx));
933
 
934
                                // Expressions
935
                                if (!_gufReadProperty(q, count, "Code", "R", gdata->parm.szFormula[0], sizeof(gdata->parm.szFormula[0])))
936
                                        strcpy(gdata->parm.szFormula[0], "r");
937
                                if (!_gufReadProperty(q, count, "Code", "G", gdata->parm.szFormula[1], sizeof(gdata->parm.szFormula[1])))
938
                                        strcpy(gdata->parm.szFormula[1], "g");
939
                                if (!_gufReadProperty(q, count, "Code", "B", gdata->parm.szFormula[2], sizeof(gdata->parm.szFormula[2])))
940
                                        strcpy(gdata->parm.szFormula[2], "b");
941
                                if (!_gufReadProperty(q, count, "Code", "A", gdata->parm.szFormula[3], sizeof(gdata->parm.szFormula[3])))
942
                                        strcpy(gdata->parm.szFormula[3], "a");
943
                                for (i = 0; i < 4; i++) {
944
                                        if (expr[i]) free(expr[i]);
945
                                        expr[i] = my_strdup(gdata->parm.szFormula[i]);
946
                                }
947
 
948
                                for (i = 0; i < 8; i++) {
949
                                        int v;
541 daniel-mar 950
                                        char keyname[9/*strlen("Control X")*/ + 1/*strlen("\0")*/], tmp[5];
537 daniel-mar 951
                                        sprintf(keyname, "Control %d", i);
952
 
953
                                        // Slider names
954
                                        _gufReadProperty(q, count, keyname, "Label", gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]));
955
 
956
                                        // Slider values
957
                                        if (!_gufReadProperty(q, count, keyname, "Preset", tmp, sizeof(tmp))) {
958
                                                strcpy(tmp, "0");
959
                                        }
960
                                        v = atoi(tmp);
961
                                        if (v < 0) v = 0;
962
                                        else if (v > 255) v = 255;
963
                                        gdata->parm.val[i] = slider[i] = (uint8_t)v;
964
                                }
965
 
966
                                // Map names
967
                                for (i = 0; i < 4; i++) {
541 daniel-mar 968
                                        char keyname[5/*strlen("Map X")*/ + 1/*strlen("\0")*/];
537 daniel-mar 969
                                        sprintf(keyname, "Map %d", i);
970
                                        _gufReadProperty(q, count, keyname, "Label", gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]));
971
                                }
972
 
973
                                //These will be set when the expressions are evaluated anyway. So this part is optional:
974
                                checksliders(4, ctls, maps);
975
                                for (i = 0; i < 8; i++) gdata->parm.ctl_used[i] = ctls[i];
976
                                for (i = 0; i < 4; i++) gdata->parm.map_used[i] = maps[i];
977
 
978
                                res = true;
979
                        }
980
 
981
                        PIUNLOCKHANDLE(h);
982
                        PIDISPOSEHANDLE(h);
983
                }
984
                FSClose(refnum);
985
        }
986
 
987
        return res;
988
}
989
 
492 daniel-mar 990
Boolean readfile_afs_pff(StandardFileReply *sfr, TCHAR**reason){
256 daniel-mar 991
        FILEREF r;
992
        Handle h;
993
        Boolean res = false;
994
 
995
        if(FSpOpenDF(&sfr->sfFile,fsRdPerm,&r) == noErr){
996
                if( (h = readfileintohandle(r)) ){
408 daniel-mar 997
                        if( (res = readparams_afs_pff(h,reason)) ) {
256 daniel-mar 998
                                gdata->standalone = false; // so metadata fields will default, if user chooses Make...
999
 
444 daniel-mar 1000
                                if (fileHasExtension(sfr, TEXT(".pff"))) {
256 daniel-mar 1001
                                        // If it is a Premiere settings file, we need to swap the channels red and blue
263 daniel-mar 1002
                                        // We just swap the pointers!
256 daniel-mar 1003
                                        char* tmp;
263 daniel-mar 1004
                                        tmp = expr[0];
1005
                                        expr[0] = expr[2];
1006
                                        expr[2] = tmp;
256 daniel-mar 1007
                                }
1008
                        }
1009
 
1010
                        PIDISPOSEHANDLE(h);
1011
                }
1012
                FSClose(r);
492 daniel-mar 1013
        }
1014
        else
498 daniel-mar 1015
                if (reason) *reason = FF_GetMsg_Cpy(MSG_CANNOT_OPEN_FILE_ID);
256 daniel-mar 1016
 
1017
        return res;
1018
}