Subversion Repositories filter_foundry

Rev

Rev 389 | Rev 393 | 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
3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
4
    Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
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
 
36
enum{
37
        BUFSIZE = 4L<<10,
38
        MAXLINE = 0x200,
39
};
40
 
389 daniel-mar 41
Boolean readparams_afs_pff(Handle h,Boolean alerts,char **reason){
256 daniel-mar 42
        Boolean res = false;
43
        char linebuf[MAXLINE+1],curexpr[MAXEXPR+1],*p,*dataend,*q;
44
        char c;
45
        int linecnt, lineptr, exprcnt;
46
 
47
        if(!h){
48
                *reason = _strdup("readparams: Null parameter handle.");
49
                return false;
50
        }
51
 
52
        p = PILOCKHANDLE(h,false);
53
        dataend = p + PIGETHANDLESIZE(h);
54
 
55
        q = curexpr;
56
        linecnt = exprcnt = lineptr = 0;
57
 
58
        *reason = _strdup("File was too short.");
59
        while(p < dataend){
60
 
61
                c = *p++;
62
 
63
                if(c==CR || c==LF){ /* detected end of line */
64
 
65
                        /* look ahead to see if we need to skip a line feed (DOS EOL convention) */
66
                        if(c == CR && *p == LF && p < dataend)
67
                                ++p;
68
 
69
                        linebuf[lineptr] = 0; /* add terminating NUL to line buffer */
70
 
71
                        /* process complete line */
72
                        if(linecnt==0){
73
                                if(strcmp(linebuf,"%RGB-1.0")){
74
                                        if(alerts)
75
                                                *reason = _strdup("This doesn't look like a Filter Factory file (first line is not \"%RGB-1.0\").");
76
                                        break;
77
                                }
78
                        }else if(linecnt<=8){
79
                                slider[linecnt-1] = atoi(linebuf);
80
                        }else{
81
                                if(lineptr){
82
                                        /* it's not an empty line; append it to current expr string */
83
                                        if( q+lineptr > curexpr+MAXEXPR ){
84
                                                *reason = _strdup("Found an expression longer than 1024 characters.");
85
                                                break;
86
                                        }
87
                                        q = cat(q,linebuf);
88
                                }else{
89
                                        /* it's an empty line: we've completed the expr string */
90
                                        if(expr[exprcnt])
91
                                                free(expr[exprcnt]);
92
                                        *q = 0;
93
                                        if(!(expr[exprcnt] = my_strdup(curexpr))){
94
                                                *reason = _strdup("Could not get memory for expression.");
95
                                                break;
96
                                        }
97
 
98
                                        if(++exprcnt == 4){
99
                                                res = true;
100
                                                break; /* got everything we want */
101
                                        }
102
 
103
                                        q = curexpr; /* empty current expr, ready for next one */
104
                                }
105
                        }
106
 
107
                        ++linecnt;
108
                        lineptr = 0;
109
                }else{
110
                        /* store character */
111
                        if(c=='\\'){ /* escape sequence */
112
                                if(p < dataend){
113
                                        c = *p++;
114
                                        switch(c){
115
                                        case 'r':
268 daniel-mar 116
                                                #if WIN_ENV
117
                                                c = CR;
118
                                                if (lineptr < MAXLINE)
274 daniel-mar 119
                                                        linebuf[lineptr++] = c;
268 daniel-mar 120
                                                c = LF;
121
                                                #else
122
                                                c = CR;
123
                                                #endif
124
                                                break;
256 daniel-mar 125
                                        case '\\': break;
126
                                        default:
127
                                                if(alerts) alertuser(_strdup("Warning:"),_strdup("Unknown escape sequence in input."));
128
                                        }
129
                                }//else if(alerts) alertuser(_strdup("Warning:"),_strdup("truncated escape sequence ends input"));
130
                        }
131
 
132
                        if(lineptr < MAXLINE)
133
                                linebuf[lineptr++] = c;
134
                }
135
        }
136
 
137
        PIUNLOCKHANDLE(h);
138
 
139
        if (res) *reason = NULL; // no error
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];
256 daniel-mar 158
        sprintf((char*)photoshop->category, "Filter Factory"); // Premiere plugins do not have a category attribute
159
        photoshop->iProtected = 0; // Premiere plugins do not have a protect flag
160
        memcpy((void*)photoshop->title, (void*)premiere->title, sizeof(photoshop->title));
161
        memcpy((void*)photoshop->copyright, (void*)premiere->copyright, sizeof(photoshop->copyright));
162
        memcpy((void*)photoshop->author, (void*)premiere->author, sizeof(photoshop->author));
163
        for (i=0;i<4;++i)
272 daniel-mar 164
                memcpy((void*)photoshop->map[i], (void*)premiere->map[i], sizeof(photoshop->map[i]));
256 daniel-mar 165
        for (i=0;i<8;++i)
272 daniel-mar 166
                memcpy((void*)photoshop->ctl[i], (void*)premiere->ctl[i], sizeof(photoshop->ctl[i]));
256 daniel-mar 167
 
168
        if (premiere->singleExpression) {
169
                memcpy((void*)photoshop->formula[0], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
170
                memcpy((void*)photoshop->formula[1], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
171
                memcpy((void*)photoshop->formula[2], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
172
                memcpy((void*)photoshop->formula[3], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
173
        } else {
174
                memcpy((void*)photoshop->formula[0], (void*)premiere->formula[2], sizeof(photoshop->formula[2]));
175
                memcpy((void*)photoshop->formula[1], (void*)premiere->formula[1], sizeof(photoshop->formula[1]));
176
                memcpy((void*)photoshop->formula[2], (void*)premiere->formula[0], sizeof(photoshop->formula[0]));
177
                memcpy((void*)photoshop->formula[3], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
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);
187
        val = (char*)malloc(len + 1);
188
        if (val != NULL) {
189
                memcpy(val, (char*)*q, len);
190
                val[len] = 0;
191
        }
192
        *q += len;
193
        return val;
194
}
195
 
196
Boolean readfile_ffx(StandardFileReply* sfr, char** reason) {
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
 
205
        if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
206
                if ((h = readfileintohandle(refnum))) {
207
                        char* q = (char*)PILOCKHANDLE(h, false);
208
 
209
                        len = *((uint32_t*)q);
210
                        if (len == 6) {
211
                                val = _ffx_read_str(&q);
367 daniel-mar 212
                                if (strcmp(val, "FFX1.0") == 0) format_version = 10;
213
                                else if (strcmp(val, "FFX1.1") == 0) format_version = 11;
214
                                else if (strcmp(val, "FFX1.2") == 0) format_version = 12;
366 daniel-mar 215
                                free(val);
367 daniel-mar 216
                                if (format_version > 0) {
368 daniel-mar 217
                                        simplewarning(_strdup("Attention! You are loading a \"Filters Unlimited\" file. Please note that Filter Foundry only implements the basic Filter Factory functions. Therefore, most \"Filters Unlimited\" filters won't work with Filter Foundry."));
218
 
366 daniel-mar 219
                                        val = _ffx_read_str(&q);
220
                                        myc2pstrcpy(gdata->parm.title, val);
221
                                        free(val);
222
 
223
                                        val = _ffx_read_str(&q);
224
                                        myc2pstrcpy(gdata->parm.category, val);
225
                                        free(val);
226
 
227
                                        val = _ffx_read_str(&q);
228
                                        myc2pstrcpy(gdata->parm.author, val);
229
                                        free(val);
230
 
231
                                        val = _ffx_read_str(&q);
232
                                        myc2pstrcpy(gdata->parm.copyright, val);
233
                                        free(val);
234
 
235
                                        // Channels I, R, G, B, A
236
                                        for (i = 0; i < 4; i++) {
237
                                                val = _ffx_read_str(&q);
238
                                                if (i == 0) {
370 daniel-mar 239
                                                        char* val2 = _ffx_read_str(&q);
366 daniel-mar 240
                                                        if (strcmp(val, "0") != 0) {
241
                                                                // "Intro channel" existing
370 daniel-mar 242
                                                                // C++ wrong warning: Using uninitialized memory "val2" (C6001)
243
                                                                #pragma warning(suppress : 6001)
244
                                                                char* combined = (char*)malloc(strlen(val) + strlen(",") + strlen(val2) + 1);
245
                                                                if (combined != NULL) {
246
                                                                        sprintf(combined, "%s,%s", val, val2);
247
                                                                        free(val);
248
                                                                        free(val2);
249
                                                                        val = combined;
250
                                                                }
366 daniel-mar 251
                                                        }
252
                                                        else {
253
                                                                free(val);
370 daniel-mar 254
                                                                val = val2;
366 daniel-mar 255
                                                        }
256
                                                }
368 daniel-mar 257
                                                if (strlen(val) >= sizeof(gdata->parm.formula[i])) {
258
                                                        if (i == 0) {
381 daniel-mar 259
                                                                simplealert(_strdup("Attention! The formula for channel I/R was too long (longer than 1023 characters) and was truncated."));
368 daniel-mar 260
                                                        }
261
                                                        else if (i == 1) {
381 daniel-mar 262
                                                                simplealert(_strdup("Attention! The formula for channel G was too long (longer than 1023 characters) and was truncated."));
368 daniel-mar 263
                                                        }
264
                                                        else if (i == 2) {
381 daniel-mar 265
                                                                simplealert(_strdup("Attention! The formula for channel B was too long (longer than 1023 characters) and was truncated."));
368 daniel-mar 266
                                                        }
267
                                                        else if (i == 3) {
381 daniel-mar 268
                                                                simplealert(_strdup("Attention! The formula for channel A was too long (longer than 1023 characters) and was truncated."));
368 daniel-mar 269
                                                        }
370 daniel-mar 270
                                                        // C++ wrong warning: Buffer overflow (C6386)
271
                                                        #pragma warning(suppress : 6386)
368 daniel-mar 272
                                                        val[sizeof(gdata->parm.formula[i]) - 1] = '\0';
273
                                                }
366 daniel-mar 274
                                                expr[i] = my_strdup(val);
368 daniel-mar 275
                                                strcpy((char*)gdata->parm.formula[i], val); // Attention! This is not a Pascal string!
366 daniel-mar 276
                                                free(val);
277
                                        }
278
 
279
                                        // Sliders
280
                                        for (i = 0; i < 8; i++) {
367 daniel-mar 281
                                                char* sliderName;
366 daniel-mar 282
                                                val = _ffx_read_str(&q);
367 daniel-mar 283
                                                sliderName = val;
284
                                                if (format_version >= 12) {
285
                                                        // Format FFX1.2 has prefixes {S} = Slider, {C} = Checkbox, none = Slider
286
                                                        if ((sliderName[0] == '{') && (sliderName[1] == 'S') && (sliderName[2] == '}')) sliderName += 3;
287
                                                        else if ((sliderName[0] == '{') && (sliderName[1] == 'C') && (sliderName[2] == '}')) sliderName += 3;
288
                                                }
289
                                                myc2pstrcpy(gdata->parm.ctl[i], sliderName);
366 daniel-mar 290
                                                free(val);
367 daniel-mar 291
                                                gdata->parm.ctl_used[i] = (bool32_t)*((byte*)q);
366 daniel-mar 292
                                                q += sizeof(byte);
293
                                                gdata->parm.val[i] = *((uint32_t*)q);
294
                                                slider[i] = *((uint32_t*)q);
295
                                                q += sizeof(uint32_t);
296
                                        }
297
 
390 daniel-mar 298
                                        // Maps (are not part of the format!)
299
                                        strcpy((char*)gdata->parm.map[0], "\006Map 0:");
300
                                        strcpy((char*)gdata->parm.map[1], "\006Map 1:");
301
                                        strcpy((char*)gdata->parm.map[2], "\006Map 2:");
302
                                        strcpy((char*)gdata->parm.map[3], "\006Map 3:");
303
 
366 daniel-mar 304
                                        res = true;
305
                                }
306
                        }
307
                        PIDISPOSEHANDLE(h);
308
                }
309
                FSClose(refnum);
310
        }
311
 
312
        if (res) gdata->obfusc = false;
313
        return res;
314
}
315
 
373 daniel-mar 316
Boolean readfile_8bf(StandardFileReply *sfr,char **reason){
256 daniel-mar 317
        unsigned char magic[2];
318
        FILECOUNT count;
319
        Handle h;
320
        Boolean res = false;
321
        FILEREF refnum;
322
 
323
        if(FSpOpenDF(&sfr->sfFile,fsRdPerm,&refnum) == noErr){
324
                // check DOS EXE magic number
325
                count = 2;
326
                if(FSRead(refnum,&count,magic) == noErr /*&& magic[0]=='M' && magic[1]=='Z'*/){
309 daniel-mar 327
                        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 328
                                if( (h = readfileintohandle(refnum)) ){
329
                                        long *q = (long*)PILOCKHANDLE(h,false);
330
 
331
                                        // look for signature at start of valid PARM resource
332
                                        // This signature is observed in Filter Factory standalones.
333
                                        for( count /= 4 ; count >= PARM_SIZE/4 ; --count, ++q )
334
                                        {
335
 
268 daniel-mar 336
                                                #ifdef MAC_ENV
256 daniel-mar 337
                                                // Case #1: Mac is reading Windows (Win16/32/64) plugin
338
                                                if( ((EndianS32_LtoN(q[0]) == PARM_SIZE) ||
339
                                                     (EndianS32_LtoN(q[0]) == PARM_SIZE_PREMIERE) ||
340
                                                     (EndianS32_LtoN(q[0]) == PARM_SIG_MAC)) && EndianS32_LtoN(q[1]) == 1
341
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 1 /*Windows format resource*/)) )
342
                                                {
343
                                                        // these are the only numeric fields we *have* to swap
344
                                                        // all the rest are flags which (if we're careful) will work in either ordering
345
                                                        for(i = 0; i < 8; ++i)
346
                                                                slider[i] = EndianS32_LtoN(slider[i]);
347
                                                }
268 daniel-mar 348
                                                #else
256 daniel-mar 349
                                                // Case #2: Windows is reading a Windows plugin (if Resource API failed, e.g. Win64 tries to open NE file, Win32 tries to open 64bit file)
350
                                                if( ((q[0] == PARM_SIZE) ||
351
                                                     (q[0] == PARM_SIZE_PREMIERE) ||
352
                                                     (q[0] == PARM_SIG_MAC)) && q[1] == 1
308 daniel-mar 353
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 1/*fromwin*/)))
256 daniel-mar 354
                                                {
355
                                                }
356
 
339 daniel-mar 357
                                                // Case #3: Windows is reading an old FilterFactory Mac file
358
                                                // Note: You must read the ".rsrc" resource fork, not the standalone binary!
256 daniel-mar 359
                                                else if( ((EndianS32_LtoN(q[0]) == PARM_SIZE) ||
360
                                                     (EndianS32_LtoN(q[0]) == PARM_SIZE_PREMIERE) ||
361
                                                     (EndianS32_LtoN(q[0]) == PARM_SIG_MAC)) && EndianS32_LtoN(q[1]) == 1
362
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 0 /*Strings are already PStrings*/)) )
363
                                                {
339 daniel-mar 364
                                                        // Note: slider[i] = EndianS32_LtoN(slider[i]); will be done in readPARM()
365
                                                        // All the rest are flags which (if we're careful) will work in either ordering
366
 
387 daniel-mar 367
                                                        // Convert CR in the copyright field to CRLF.
341 daniel-mar 368
                                                        int i, j;
339 daniel-mar 369
                                                        for (i = 1; i < gdata->parm.copyright[0]; i++) {
387 daniel-mar 370
                                                                if (gdata->parm.copyright[i] == CR) {
341 daniel-mar 371
                                                                        for (j = gdata->parm.copyright[0]; j>i; j--) {
372
                                                                                gdata->parm.copyright[j+1] = gdata->parm.copyright[j];
373
                                                                        }
374
                                                                        gdata->parm.copyright[0]++;
387 daniel-mar 375
                                                                        gdata->parm.copyright[i+1] = LF;
339 daniel-mar 376
                                                                }
377
                                                        }
256 daniel-mar 378
                                                }
268 daniel-mar 379
                                                #endif
256 daniel-mar 380
 
381
                                                if (res) break;
382
                                        }
341 daniel-mar 383
 
256 daniel-mar 384
                                        PIDISPOSEHANDLE(h);
385
                                }
386
                        }
387
                } // else no point in proceeding
388
                FSClose(refnum);
389
        }else
390
                *reason = _strdup("Could not open file.");
391
 
392
        if (res) gdata->obfusc = false;
393
        return res;
394
}
395
 
396
Boolean readPARM(Ptr p,PARM_T *pparm,char **reasonstr,int fromwin){
397
        int i;
398
 
399
        if (*((unsigned int*)p) == PARM_SIZE_PREMIERE) {
400
                convert_premiere_to_photoshop(pparm, (PARM_T_PREMIERE*)p);
401
        } else {
402
                // Assume it is Photoshop. Signature either PARM_SIZE (0x2068) or 0x1C68
403
                memcpy(pparm,p,sizeof(PARM_T));
404
        }
405
 
406
        if(fromwin){
407
                /* Windows PARM resource stores C strings - convert to Pascal strings  */
408
                myc2pstr((char*)pparm->category);
409
                myc2pstr((char*)pparm->title);
410
                myc2pstr((char*)pparm->copyright);
411
                myc2pstr((char*)pparm->author);
412
                for(i = 0; i < 4; ++i)
413
                        myc2pstr((char*)pparm->map[i]);
414
                for(i = 0; i < 8; ++i)
415
                        myc2pstr((char*)pparm->ctl[i]);
416
        }
417
 
418
        for(i = 0; i < 4; ++i){
419
                if(expr[i]) free(expr[i]);
366 daniel-mar 420
                expr[i] = my_strdup((char*)pparm->formula[i]);
256 daniel-mar 421
        }
422
 
339 daniel-mar 423
        for (i = 0; i < 8; ++i) {
424
                if (pparm->val[i] > 0xFF) {
425
                        // Wrong endianess (e.g. reading a Mac rsrc on Windows)
426
                        slider[i] = (uint8_t)EndianS32_LtoN(pparm->val[i]);
427
                }
428
                else {
429
                        slider[i] = (uint8_t)pparm->val[i];
430
                }
431
        }
256 daniel-mar 432
 
433
        return true;
434
}
435
 
436
Handle readfileintohandle(FILEREF r){
437
        FILEPOS n;
438
        Handle h;
439
        Ptr p;
440
 
441
        if( GetEOF(r,&n) == noErr && (h = PINEWHANDLE(n)) ){
442
                p = PILOCKHANDLE(h,false);
443
                if(SetFPos(r,fsFromStart,0) == noErr && FSRead(r,(FILECOUNT*)&n,p) == noErr){
444
                        PIUNLOCKHANDLE(h);
445
                        return h;
446
                }
447
                PIDISPOSEHANDLE(h);
448
        }
449
        return NULL;
450
}
451
 
385 daniel-mar 452
Boolean _picoLineContainsKey(char* line, char** content, const char* searchkey/*=NULL*/) {
386 daniel-mar 453
        size_t i;
454
        for (i = 0; i < strlen(line); i++) {
388 daniel-mar 455
                if (line[i] == '?') break; // avoid that "a?b:c" is detected as key
385 daniel-mar 456
                if (line[i] == ':') {
386 daniel-mar 457
                        // Note: We are ignoring whitespaces, i.e. " A :" != "A:" (TODO: should we change this?)
458
                        if ((searchkey == NULL) || ((i == strlen(searchkey)) && (memcmp(line, searchkey, i) == 0))) {
459
                                i++; // jump over ':' char
387 daniel-mar 460
                                //while ((line[i] == ' ') || (line[i] == TAB)) i++; // Trim value left
385 daniel-mar 461
                                *content = line + i;
462
                                return true;
463
                        }
464
                }
465
        }
466
        *content = line;
467
        return false;
468
}
469
 
388 daniel-mar 470
void _ffdcomp_removebrackets(char* x, char* maxptr) {
471
        char* closingBracketPos = NULL;
472
        Boolean openingBracketFound = false;
473
        if (x[0] == '[') {
474
                openingBracketFound = true;
475
        }
476
        x[0] = ':';
477
        x++;
478
        while (x < maxptr) {
479
                if ((!openingBracketFound) && (x[0] == '[')) {
480
                        openingBracketFound = true;
481
                        x[0] = ' ';
482
                }
483
                else if (openingBracketFound) {
484
                        if (x[0] == ']') {
485
                                closingBracketPos = x;
486
                        }
487
                        else if ((x[0] == CR) || (x[0] == LF)) {
488
                                if (closingBracketPos) closingBracketPos[0] = ' '; // last closing pos before CR/LF
489
                                break;
490
                        }
491
                }
492
                x++;
493
        }
494
}
495
 
386 daniel-mar 496
// isFormula=false => outputFile is Pascal string. TXT linebreaks become spaces.
497
// isFormula=true  => outputFile is C string. TXT line breaks become CRLF line breaks
498
Boolean _picoReadProperty(char* inputFile, int maxInput, const char* property, char* outputFile, size_t maxOutput, Boolean isFormula) {
499
        int i;
500
        char* outputwork;
501
        char* sline;
502
        char* svalue;
503
        char* inputwork;
504
        char* inputworkinitial;
505
        outputwork = outputFile;
506
        sline = NULL;
507
        svalue = NULL;
385 daniel-mar 508
        // Check parameters
386 daniel-mar 509
        if (maxOutput == 0) return false;
385 daniel-mar 510
        if (inputFile == 0) return false;
511
        // Let input memory be read-only, +1 for terminal zero
512
        //char* inputwork = inputFile;
386 daniel-mar 513
        inputwork = (char*)malloc(maxInput + 1);
514
        inputworkinitial = inputwork;
385 daniel-mar 515
        if (inputwork == 0) return false;
516
        memcpy(inputwork, inputFile, maxInput);
388 daniel-mar 517
        inputwork[maxInput] = 0; // otherwise strstr() will crash
518
 
519
        // Transform "FFDecomp" TXT file into the similar "PluginCommander" TXT file
520
        if (strstr(inputwork, "Filter Factory Plugin Information:")) {
521
                char* x;
522
                char* k1;
523
                char* k2;
524
                // Metadata:
525
                x = strstr(inputwork, "CATEGORY:");
389 daniel-mar 526
                if (x) memcpy(x, "Category:", strlen("Category:"));
388 daniel-mar 527
                x = strstr(inputwork, "TITLE:");
389 daniel-mar 528
                if (x) memcpy(x, "Title:", strlen("Title:"));
388 daniel-mar 529
                x = strstr(inputwork, "COPYRIGHT:");
389 daniel-mar 530
                if (x) memcpy(x, "Copyright:", strlen("Copyright:"));
388 daniel-mar 531
                x = strstr(inputwork, "AUTHOR:");
389 daniel-mar 532
                if (x) memcpy(x, "Author:", strlen("Author:"));
388 daniel-mar 533
                // Controls:
534
                for (i = 0; i < 8; i++) {
535
                        k1 = (char*)malloc(strlen("Control X:") + 1);
536
                        sprintf(k1, "Control %d:", i);
537
                        x = strstr(inputwork, k1);
538
                        if (x) {
539
                                k2 = (char*)malloc(strlen("ctl[X]:   ") + 1);
540
                                sprintf(k2, "ctl[%d]:   ", i);
389 daniel-mar 541
                                memcpy(x, k2, strlen(k2));
388 daniel-mar 542
                                x += strlen("ctl[X]");
543
                                _ffdcomp_removebrackets(x, inputwork + maxInput - 1);
544
                                free(k2);
545
                        }
546
                        free(k1);
547
                }
548
                // Maps:
549
                for (i = 0; i < 4; i++) {
550
                        k1 = (char*)malloc(strlen("Map X:") + 1);
551
                        sprintf(k1, "Map %d:", i);
552
                        x = strstr(inputwork, k1);
553
                        if (x) {
554
                                k2 = (char*)malloc(strlen("map[X]:") + 1);
555
                                sprintf(k2, "map[%d]:", i);
389 daniel-mar 556
                                memcpy(x, k2, strlen(k2));
388 daniel-mar 557
                                x += strlen("map[X]");
558
                                _ffdcomp_removebrackets(x, inputwork + maxInput - 1);
559
                                free(k2);
560
                        }
561
                        free(k1);
562
                }
563
                // Convert all '\r' to '\n' for the next step to be easier
564
                for (i = 0; i < maxInput; i++) {
565
                        if (inputworkinitial[i] == CR) inputworkinitial[i] = LF;
566
                }
567
                x = strstr(inputwork, "\nR=\n");
389 daniel-mar 568
                if (x) memcpy(x, "\nR:\n", strlen("\nR:\n"));
388 daniel-mar 569
                x = strstr(inputwork, "\nG=\n");
389 daniel-mar 570
                if (x) memcpy(x, "\nG:\n", strlen("\nG:\n"));
388 daniel-mar 571
                x = strstr(inputwork, "\nB=\n");
389 daniel-mar 572
                if (x) memcpy(x, "\nB:\n", strlen("\nB:\n"));
388 daniel-mar 573
                x = strstr(inputwork, "\nA=\n");
389 daniel-mar 574
                if (x) memcpy(x, "\nA:\n", strlen("\nA:\n"));
388 daniel-mar 575
        }
385 daniel-mar 576
        // Replace all \r and \n with \0, so that we can parse easier
386 daniel-mar 577
        for (i = 0; i < maxInput; i++) {
388 daniel-mar 578
                if (inputworkinitial[i] == 0) break;
579
                if (inputworkinitial[i] == CR) inputworkinitial[i] = 0;
580
                if (inputworkinitial[i] == LF) inputworkinitial[i] = 0;
385 daniel-mar 581
        }
388 daniel-mar 582
 
385 daniel-mar 583
        // Find line that contains out key
388 daniel-mar 584
        inputwork = inputworkinitial;
385 daniel-mar 585
        do {
586
                if (inputwork > inputworkinitial + maxInput) {
587
                        // Key not found. Set output to empty string
588
                        outputwork[0] = 0;
589
                        free(inputworkinitial);
386 daniel-mar 590
                        if (!isFormula) myc2pstr(outputFile);
385 daniel-mar 591
                        return false;
592
                }
593
                sline = inputwork;
594
                inputwork += strlen(sline) + 1;
595
                if (inputwork - 1 > inputworkinitial + maxInput) {
596
                        // Key not found. Set output to empty string
597
                        // TODO: will that be ever called?
598
                        outputwork[0] = 0;
599
                        free(inputworkinitial);
386 daniel-mar 600
                        if (!isFormula) myc2pstr(outputFile);
385 daniel-mar 601
                        return false;
602
                }
603
        } while (!_picoLineContainsKey(sline, &svalue, property));
388 daniel-mar 604
 
385 daniel-mar 605
        // Read line(s) until we find a line with another key, or the line end
606
        do {
387 daniel-mar 607
                while ((svalue[0] == ' ') || (svalue[0] == TAB)) svalue++; // Trim left
608
                while ((svalue[strlen(svalue) - 1] == ' ') || (svalue[strlen(svalue) - 1] == TAB)) svalue[strlen(svalue) - 1] = 0; // Trim right
386 daniel-mar 609
 
385 daniel-mar 610
                if (strlen(svalue) > 0) {
386 daniel-mar 611
                        if (outputwork + strlen(svalue) + (isFormula ? 3 : 2) > outputFile + maxOutput) {
385 daniel-mar 612
                                int remaining = maxOutput - (outputwork - outputFile) - 1;
613
                                //printf("BUFFER FULL (remaining = %d)\n", remaining);
614
                                memcpy(outputwork, svalue, remaining);
615
                                outputwork += remaining;
616
                                outputwork[0] = 0;
617
                                free(inputworkinitial);
386 daniel-mar 618
                                if (!isFormula) myc2pstr(outputFile);
385 daniel-mar 619
                                return true;
620
                        }
621
                        else {
622
                                memcpy(outputwork, svalue, strlen(svalue));
623
                                outputwork += strlen(svalue);
386 daniel-mar 624
                                if (isFormula) {
625
                                        // Formulas: TXT line break stays line break (important if you have comments!)
388 daniel-mar 626
                                        outputwork[0] = CR;
627
                                        outputwork[1] = LF;
387 daniel-mar 628
                                        outputwork += 2;
386 daniel-mar 629
                                }
630
                                else {
631
                                        // Everything else: TXT line breaks becomes single whitespace
632
                                        outputwork[0] = ' ';
633
                                        outputwork++;
634
                                }
385 daniel-mar 635
                        }
636
                }
637
                outputwork[0] = 0;
638
 
639
                // Process next line
640
                if (inputwork > inputworkinitial + maxInput) break;
641
                sline = inputwork;
642
                inputwork += strlen(sline) + 1;
386 daniel-mar 643
                if (inputwork - 1 > inputworkinitial + maxInput) break; // TODO: will that be ever called?
385 daniel-mar 644
        } while (!_picoLineContainsKey(sline, &svalue, NULL));
388 daniel-mar 645
 
385 daniel-mar 646
        // Remove trailing whitespace
647
        if (outputwork > outputFile) {
648
                outputwork -= 1;
649
                outputwork[0] = 0;
650
        }
651
        free(inputworkinitial);
386 daniel-mar 652
        if (!isFormula) myc2pstr(outputFile);
385 daniel-mar 653
        return true;
654
}
655
 
656
Boolean readfile_picotxt(StandardFileReply* sfr, char** reason) {
389 daniel-mar 657
        extern int ctls[], maps[];
658
 
385 daniel-mar 659
        Handle h;
660
        Boolean res = false;
661
        FILEREF refnum;
662
 
663
        if (!fileHasExtension(sfr, ".txt")) return false;
664
 
665
        if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
666
                if ((h = readfileintohandle(refnum))) {
667
                        FILECOUNT count = PIGETHANDLESIZE(h);
668
                        char* q = PILOCKHANDLE(h, false);
669
 
670
                        char out[256];
671
                        if (_picoReadProperty(q, count, "Title", out, sizeof(out), false)) {
386 daniel-mar 672
                                int i;
385 daniel-mar 673
 
674
                                // Plugin infos
386 daniel-mar 675
                                _picoReadProperty(q, count, "Title", (char*)gdata->parm.title, sizeof(gdata->parm.title)-1, false);
676
                                _picoReadProperty(q, count, "Category", (char*)gdata->parm.category, sizeof(gdata->parm.category)-1, false);
677
                                _picoReadProperty(q, count, "Author", (char*)gdata->parm.author, sizeof(gdata->parm.author)-1, false);
678
                                _picoReadProperty(q, count, "Copyright", (char*)gdata->parm.copyright, sizeof(gdata->parm.copyright)-1, false);
679
                                //_picoReadProperty(q, count, "Filename", (char*)gdata->parm.xxx, sizeof(gdata->parm.xxx), false);
385 daniel-mar 680
 
681
                                // Expressions
386 daniel-mar 682
                                if (!_picoReadProperty(q, count, "R", (char*)gdata->parm.formula[0], sizeof(gdata->parm.formula[0]), true))
683
                                        strcpy((char*)gdata->parm.formula[0], "r");
684
                                if (!_picoReadProperty(q, count, "G", (char*)gdata->parm.formula[1], sizeof(gdata->parm.formula[1]), true))
685
                                        strcpy((char*)gdata->parm.formula[1], "g");
686
                                if (!_picoReadProperty(q, count, "B", (char*)gdata->parm.formula[2], sizeof(gdata->parm.formula[2]), true))
687
                                        strcpy((char*)gdata->parm.formula[2], "b");
688
                                if (!_picoReadProperty(q, count, "A", (char*)gdata->parm.formula[3], sizeof(gdata->parm.formula[3]), true))
689
                                        strcpy((char*)gdata->parm.formula[3], "a");
690
                                for (i = 0; i < 4; i++) {
385 daniel-mar 691
                                        if (expr[i]) free(expr[i]);
386 daniel-mar 692
                                        expr[i] = my_strdup((char*)gdata->parm.formula[i]);
385 daniel-mar 693
                                }
694
 
695
                                // Slider names
386 daniel-mar 696
                                for (i = 0; i < 8; i++) {
385 daniel-mar 697
                                        char keyname[7];
698
                                        sprintf(keyname, "ctl[%d]", i);
386 daniel-mar 699
                                        _picoReadProperty(q, count, keyname, (char*)gdata->parm.ctl[i], sizeof(gdata->parm.ctl[i]), false);
385 daniel-mar 700
                                }
701
 
702
                                // Slider values
386 daniel-mar 703
                                for (i = 0; i < 8; i++) {
704
                                        char keyname[7], tmp[5];
385 daniel-mar 705
                                        sprintf(keyname, "val[%d]", i);
706
                                        if (!_picoReadProperty(q, count, keyname, tmp, sizeof(tmp), false)) {
707
                                                sprintf(keyname, "def[%d]", i);
708
                                                if (!_picoReadProperty(q, count, keyname, tmp, sizeof(tmp), false)) {
386 daniel-mar 709
                                                        tmp[0] = 1;
710
                                                        tmp[1] = '0';
711
                                                        tmp[2] = 0;
385 daniel-mar 712
                                                }
713
                                        }
386 daniel-mar 714
                                        myp2cstr((unsigned char*)tmp);
385 daniel-mar 715
                                        gdata->parm.val[i] = slider[i] = atoi(tmp);
716
                                }
717
 
718
                                // Map names
386 daniel-mar 719
                                for (i = 0; i < 4; i++) {
385 daniel-mar 720
                                        char keyname[7];
721
                                        sprintf(keyname, "map[%d]", i);
386 daniel-mar 722
                                        _picoReadProperty(q, count, keyname, (char*)gdata->parm.map[i], sizeof(gdata->parm.map[i]), false);
385 daniel-mar 723
                                }
724
 
389 daniel-mar 725
                                //These will be set when the expressions are evaluated anyway. So this part is optional:
726
                                checksliders(4, ctls, maps);
727
                                for (i = 0; i < 8; i++) gdata->parm.ctl_used[i] = ctls[i];
728
                                for (i = 0; i < 4; i++) gdata->parm.map_used[i] = maps[i];
385 daniel-mar 729
 
730
                                res = true;
731
                        }
732
 
733
                        PIUNLOCKHANDLE(h);
734
                        PIDISPOSEHANDLE(h);
735
                }
736
                FSClose(refnum);
737
        }
738
 
739
        return res;
740
}
741
 
366 daniel-mar 742
Boolean readfile_afs_pff(StandardFileReply *sfr,char **reason){
256 daniel-mar 743
        FILEREF r;
744
        Handle h;
745
        Boolean res = false;
746
 
747
        if(FSpOpenDF(&sfr->sfFile,fsRdPerm,&r) == noErr){
748
                if( (h = readfileintohandle(r)) ){
389 daniel-mar 749
                        if( (res = readparams_afs_pff(h,true,reason)) ) {
256 daniel-mar 750
                                gdata->standalone = false; // so metadata fields will default, if user chooses Make...
751
 
752
                                if (fileHasExtension(sfr, ".pff")) {
753
                                        // If it is a Premiere settings file, we need to swap the channels red and blue
263 daniel-mar 754
                                        // We just swap the pointers!
256 daniel-mar 755
                                        char* tmp;
263 daniel-mar 756
                                        tmp = expr[0];
757
                                        expr[0] = expr[2];
758
                                        expr[2] = tmp;
256 daniel-mar 759
                                }
760
                        }
761
 
762
                        PIDISPOSEHANDLE(h);
763
                }
764
                FSClose(r);
765
        }else
766
                *reason = _strdup("Could not open the file.");
767
 
768
        return res;
769
}