Subversion Repositories filter_foundry

Rev

Rev 505 | Rev 536 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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