Subversion Repositories filter_foundry

Rev

Rev 555 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
259 daniel-mar 1
/*
2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
536 daniel-mar 3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
550 daniel-mar 4
    Copyright (C) 2018-2023 Daniel Marschall, ViaThinkSoft
259 daniel-mar 5
 
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
20
 
21
/* This is PLATFORM INDEPENDENT user interface code - mainly dialog logic */
22
 
23
#include "ff.h"
24
 
25
#include "node.h"
26
#include "funcs.h"
27
#include "y.tab.h"
28
#include "choosefile.h"
29
#include "sprintf_tiny.h"
30
#include "compat_string.h"
31
 
32
#ifdef MAC_ENV
33
        #include <plstringfuncs.h>
34
#endif
35
 
36
Boolean doupdates = true;
37
 
38
void updateglobals(DIALOGREF dp);
39
struct node *updateexpr(DIALOGREF dp,int i);
40
void updatedialog(DIALOGREF dp);
41
void slidertextchanged(DIALOGREF dp,int item);
42
void updatezoom(DIALOGREF dp);
43
 
44
void updatedialog(DIALOGREF dp){
45
        int i;
46
 
47
        doupdates = false;
48
 
49
        for(i = 0; i < 8; ++i){
550 daniel-mar 50
                SETSLIDERVALUE(dp,FIRSTCTLITEM+i, gdata->parm.val[i]);
51
                SETCTLTEXTINT(dp,FIRSTCTLTEXTITEM+i, gdata->parm.val[i],false);
259 daniel-mar 52
        }
53
 
54
        for(i = 0; i < 4; ++i){
550 daniel-mar 55
                if(!gdata->parm.standalone)
56
                        SETCTLTEXT(dp,FIRSTEXPRITEM+i, gdata->parm.szFormula[i]);
259 daniel-mar 57
                if(i < nplanes)
58
                        updateexpr(dp,FIRSTEXPRITEM+i);
59
        }
60
 
550 daniel-mar 61
        if(!gdata->parm.standalone)
259 daniel-mar 62
                SELECTCTLTEXT(dp,FIRSTEXPRITEM,0,-1);
63
 
64
        doupdates = true;
65
}
66
 
67
/* copy dialog settings to global variables (sliders, expressions) */
68
 
69
void updateglobals(DIALOGREF dp){
422 daniel-mar 70
 
433 daniel-mar 71
        UNREFERENCED_PARAMETER(dp);
72
 
259 daniel-mar 73
}
74
 
75
struct node *updateexpr(DIALOGREF dp,int item){
544 daniel-mar 76
        char s[MAXEXPR];
259 daniel-mar 77
        int i;
78
 
79
        i = item - FIRSTEXPRITEM;
80
 
81
        freetree(tree[i]);
82
 
550 daniel-mar 83
        if(!gdata->parm.standalone){
544 daniel-mar 84
                GETCTLTEXT(dp,item,s,MAXEXPR); // cchMax: NULL is included, so MAXEXPR is correct
550 daniel-mar 85
                strcpy(gdata->parm.szFormula[i], s);
259 daniel-mar 86
        }
87
 
550 daniel-mar 88
        tree[i] = parseexpr(gdata->parm.szFormula[i]);
259 daniel-mar 89
 
550 daniel-mar 90
        if(!gdata->parm.standalone){
259 daniel-mar 91
                if(tree[i])
92
                        HideDialogItem(dp,FIRSTICONITEM+i);
93
                else{
94
                        err[i] = errstr;
95
                        errstart[i] = tokstart;
96
                        errpos[i] = tokpos;
97
                        ShowDialogItem(dp,FIRSTICONITEM+i);
98
                }
99
        }
100
        return tree[i];
101
}
102
 
103
void updatezoom(DIALOGREF dp){
104
        char s[10];
105
        sprintf(s, "%d%%", (int)(100./zoomfactor));
106
        SETCTLTEXT(dp,ZOOMLEVELITEM,s);
419 daniel-mar 107
        if (zoomfactor > 1.)
108
                ENABLEDLGITEM(dp, ZOOMINITEM);   // ShowDialogItem(dp,ZOOMINITEM);
259 daniel-mar 109
        else
419 daniel-mar 110
                DISABLEDLGITEM(dp, ZOOMINITEM);  // HideDialogItem(dp, ZOOMINITEM);
259 daniel-mar 111
        if(zoomfactor < fitzoom)
419 daniel-mar 112
                ENABLEDLGITEM(dp, ZOOMOUTITEM);  // ShowDialogItem(dp,ZOOMOUTITEM);
259 daniel-mar 113
        else
419 daniel-mar 114
                DISABLEDLGITEM(dp, ZOOMOUTITEM); // HideDialogItem(dp,ZOOMOUTITEM);
259 daniel-mar 115
}
116
 
117
/* traverse expression tree, looking for constant references to sliders/maps */
118
 
557 daniel-mar 119
static int _checksl(struct node*p,bool32_t ctlflags[], bool32_t mapflags[]){
259 daniel-mar 120
        int s, i, result;
121
 
122
        result = 0;
123
        if(p){
124
                if( (p->kind==TOK_FN1 && p->v.sym->fn == (pfunc_type)ff_ctl)
125
                 || (p->kind==TOK_FN3 && p->v.sym->fn == (pfunc_type)ff_val) ){
126
                        if(p->child[0]->kind == TOK_NUM){
127
                                s = p->child[0]->v.value;
128
                                if(s>=0 && s<=7)
129
                                        ctlflags[s] = 1;
130
                        }else
131
                                result |= CHECKSLIDERS_CTL_AMBIGUOUS; /* can't determine which ctl() */
132
                }else if(p->kind==TOK_FN2 && p->v.sym->fn == (pfunc_type)ff_map){
133
                        if(p->child[0]->kind == TOK_NUM){
134
                                s = p->child[0]->v.value;
135
                                if(s>=0 && s<=3){
136
                                        mapflags[s] = 1;
137
                                        ctlflags[s*2] = ctlflags[s*2+1] = 1;
138
                                }
139
                        }else
140
                                result |= CHECKSLIDERS_MAP_AMBIGUOUS; /* can't determine which map() */
141
                 }
142
 
143
                for( i = 0 ; i < MAXCHILDREN ; ++i )
144
                        result |= _checksl(p->child[i],ctlflags,mapflags);
145
        }
146
 
147
        return result;
148
}
149
 
550 daniel-mar 150
int checksliders(int exprs){
259 daniel-mar 151
        int i, result;
152
 
153
        result = 0;
154
 
155
        for(i = 4; i--;)
550 daniel-mar 156
                gdata->parm.map_used[i] = 0;
259 daniel-mar 157
        for(i = 8; i--;)
550 daniel-mar 158
                gdata->parm.ctl_used[i] = 0;
259 daniel-mar 159
 
160
        for(i = 0; i < exprs; i++)
550 daniel-mar 161
                result |= _checksl(tree[i], gdata->parm.ctl_used, gdata->parm.map_used);
259 daniel-mar 162
 
163
        return result;
164
}
165
 
166
void slidermoved(DIALOGREF dp,int i){
167
        int v = GETSLIDERVALUE(dp,i);
453 daniel-mar 168
        if (v < 0) v = 0;
456 daniel-mar 169
        else if (v > 255) v = 255;
259 daniel-mar 170
        i -= FIRSTCTLITEM;
550 daniel-mar 171
        gdata->parm.val[i] = (uint8_t)v;
259 daniel-mar 172
        SETCTLTEXTINT(dp,i+FIRSTCTLTEXTITEM,v,false);
173
}
174
 
175
void slidertextchanged(DIALOGREF dp,int i){
176
        int v = GETCTLTEXTINT(dp,i,NULL,false);
453 daniel-mar 177
        if (v < 0) v = 0;
456 daniel-mar 178
        else if (v > 255) v = 255;
259 daniel-mar 179
        i -= FIRSTCTLTEXTITEM;
180
        SETSLIDERVALUE(dp,i+FIRSTCTLITEM,v);
550 daniel-mar 181
        gdata->parm.val[i] = (uint8_t)v;
259 daniel-mar 182
}
183
 
184
void maindlgupdate(DIALOGREF dp){
550 daniel-mar 185
        int i,unknown;
259 daniel-mar 186
 
550 daniel-mar 187
        unknown = checksliders(nplanes);
259 daniel-mar 188
 
189
        for(i = 0; i < 8; i++)
550 daniel-mar 190
                if(unknown || gdata->parm.ctl_used[i]){
422 daniel-mar 191
                        ENABLEDLGITEM(dp,FIRSTCTLITEM+i); // TODO: slider is still shown as disabled
499 daniel-mar 192
                        REPAINTCTL(dp, FIRSTCTLITEM+i); // required for PLUGIN.DLL sliders
259 daniel-mar 193
                        ENABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
194
                        ShowDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
195
                }else{
196
                        DISABLEDLGITEM(dp,FIRSTCTLITEM+i);
422 daniel-mar 197
                        REPAINTCTL(dp,FIRSTCTLITEM+i); // required for PLUGIN.DLL sliders
259 daniel-mar 198
                        DISABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
199
                        HideDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
200
                }
201
 
202
        for(i = 0; i < nplanes; i++)
203
                if(!tree[i]){
204
                        /* uh oh, couldn't parse one of the saved expressions...this is fatal */
205
                        DISABLEDLGITEM(dp,IDOK);
550 daniel-mar 206
                        if(gdata->parm.standalone){
510 daniel-mar 207
                                // TODO: But before this happens, we get filterBadParameters in filterSelectorStart, since setup() failed
208
                                //       so, do we need this message here at all?
492 daniel-mar 209
                                simplealert_id(MSG_SAVED_EXPR_ERR_ID);
259 daniel-mar 210
                        }else{
211
                                DISABLEDLGITEM(dp,SAVEITEM);
212
                                DISABLEDLGITEM(dp,MAKEITEM);
213
                        }
214
                        return;
215
                }
216
 
217
        /* we have valid expression trees in all slots...proceed! */
218
        updateglobals(dp);
219
        if(setup(gpb))
220
                recalc_preview(gpb,dp);
221
 
222
        ENABLEDLGITEM(dp,IDOK);
550 daniel-mar 223
        if(!gdata->parm.standalone){
259 daniel-mar 224
                ENABLEDLGITEM(dp,SAVEITEM);
225
                ENABLEDLGITEM(dp,MAKEITEM);
305 daniel-mar 226
                ENABLEDLGITEM(dp,HELPITEM);
259 daniel-mar 227
        }
228
}
229
 
230
/* one-time initialisation of dialog box */
231
 
232
void maindlginit(DIALOGREF dp){
233
        char s[0x100];
234
        int i;
235
        const char *channelsuffixes[] = {
236
                "", "KA", "I", "RGBA",
237
                "CMYK", "HSL", "HSB", "1234",
238
                "DA", "LabA"
239
        };
240
 
241
        /* hide unused expression items */
550 daniel-mar 242
        if(gdata->parm.standalone){
511 daniel-mar 243
                strcpy_win_replace_ampersand(&s[0], &gdata->parm.szAuthor[0]);
244
                SETCTLTEXT(dp,PARAMAUTHORITEM,s);
245
                strcpy_win_replace_ampersand(&s[0], &gdata->parm.szCopyright[0]);
246
                SETCTLTEXT(dp,PARAMCOPYITEM,s);
259 daniel-mar 247
 
248
                // update labels for map() or ctl() sliders
249
                for(i = 0; i < 8; ++i){
511 daniel-mar 250
                        if(gdata->parm.map_used[i/2]) {
259 daniel-mar 251
                                if((i&1) == 0){
252
                                        // even (0, 2, 4, 6)
511 daniel-mar 253
                                        strcpy_win_replace_ampersand(&s[0], &gdata->parm.szMap[i/2][0]);
254
                                        SETCTLTEXT(dp, FIRSTMAPLABELITEM + (i/2),s);
259 daniel-mar 255
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i);
256
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i + 1);
257
                                }
511 daniel-mar 258
                        } else if(gdata->parm.ctl_used[i]) {
259
                                strcpy_win_replace_ampersand(&s[0], &gdata->parm.szCtl[i][0]);
260
                                SETCTLTEXT(dp, FIRSTCTLLABELITEM+i,s);
259 daniel-mar 261
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
511 daniel-mar 262
                        } else {
263
                                HideDialogItem(dp, FIRSTCTLITEM + i);
264
                                HideDialogItem(dp, FIRSTCTLTEXTITEM + i);
259 daniel-mar 265
                                HideDialogItem(dp, FIRSTCTLLABELITEM + i);
266
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
267
                        }
268
                }
269
        }
270
 
271
        strcpy(s,"X =");
272
        for(i = 0; i < 4; ++i){
273
                if(i >= nplanes){
274
                        HideDialogItem(dp,FIRSTICONITEM+i);
275
                        HideDialogItem(dp,FIRSTEXPRITEM+i);
276
                        HideDialogItem(dp,FIRSTLABELITEM+i);
277
                }else{
278
                        s[0] = channelsuffixes[gpb->imageMode][i];
511 daniel-mar 279
                        SETCTLTEXT(dp,FIRSTLABELITEM+i,s);
259 daniel-mar 280
                }
281
        }
282
 
283
        if(setup_preview(gpb,nplanes)){
284
                // On very large images, processing a fully zoomed out preview (the initial default)
285
                // can cause out of memory errors, because Photoshop can't page in all data
286
                // during advanceState. To prevent this problem, zoom in until we aren't
287
                // previewing more than say 10% of Photoshop's indicated maxSpace.
288
                // (e.g., on a 1GB WinXP system, PS CS2 reports 520MB maxSpace, so this will let us
289
                // preview about 50MB of image data.)
290
 
291
                /* Workaround: GIMP/PSPI sets maxSpace to 100 MB hardcoded, so the zoom is not adjusted correctly. */
292
                int disable_zoom_memory_check;
293
                disable_zoom_memory_check = !maxspace_available();
294
 
295
                if (!disable_zoom_memory_check) {
296
                        zoomfactor = sqrt(maxspace()/(10.*preview_w*preview_h*nplanes));
297
                        if(zoomfactor > fitzoom)
298
                                zoomfactor = fitzoom;
299
                        if(zoomfactor < 1.)
300
                                zoomfactor = 1.;
301
                } else {
302
                        zoomfactor = fitzoom;
303
                }
304
 
305
                updatezoom(dp);
306
        }else{
419 daniel-mar 307
                DISABLEDLGITEM(dp, ZOOMINITEM);    // HideDialogItem(dp,ZOOMINITEM);
308
                DISABLEDLGITEM(dp, ZOOMOUTITEM);   // HideDialogItem(dp,ZOOMOUTITEM);
309
                DISABLEDLGITEM(dp, ZOOMLEVELITEM); // HideDialogItem(dp,ZOOMLEVELITEM);
259 daniel-mar 310
        }
311
 
312
        updatedialog(dp);
313
        maindlgupdate(dp);
314
}
315
 
316
 
317
/* process an item hit. return false if the dialog is finished; otherwise return true. */
318
 
319
Boolean maindlgitem(DIALOGREF dp,int item){
320
        extern int previewerr;
321
 
322
        StandardFileReply sfr;
323
        NavReplyRecord reply;
324
        static OSType types[] = {TEXT_FILETYPE,PS_FILTER_FILETYPE};
323 daniel-mar 325
        HINSTANCE hShellRes;
430 daniel-mar 326
        InternalState bakState;
259 daniel-mar 327
 
328
        switch(item){
363 daniel-mar 329
#ifdef MAC_ENV
330
        case ok:
331
        case cancel:
332
#else
259 daniel-mar 333
        case IDOK:
334
        case IDCANCEL:
363 daniel-mar 335
#endif
259 daniel-mar 336
                dispose_preview();
337
                return false; // end dialog
338
        case OPENITEM:
493 daniel-mar 339
        {
495 daniel-mar 340
                TCHAR* tmp1;
496 daniel-mar 341
                TCHAR* filters, *title;
342
                Boolean loadDlgRet;
343
 
553 daniel-mar 344
                showDialogAgain:
345
 
496 daniel-mar 346
                title = (TCHAR*)malloc(1024);
347
                if (title == NULL) return false;
348
 
349
                filters = (TCHAR*)malloc(4096);
495 daniel-mar 350
                if (filters == NULL) return false;
351
                memset(filters, 0, 4096);
352
                tmp1 = filters;
493 daniel-mar 353
 
496 daniel-mar 354
                FF_GetMsg(title, MSG_LOAD_FILTER_SETTINGS_TITLE_ID);
355
 
495 daniel-mar 356
                strcpy_advance_id(&tmp1, MSG_ALL_SUPPORTED_FILES_ID);
544 daniel-mar 357
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx, *.ffl, *.guf)")); tmp1++;
358
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx;*.ffl;*.guf")); tmp1++;
493 daniel-mar 359
 
495 daniel-mar 360
                strcpy_advance_id(&tmp1, MSG_OPEN_AFS_ID);
361
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs)")); tmp1++;
362
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs")); tmp1++;
493 daniel-mar 363
 
495 daniel-mar 364
                strcpy_advance_id(&tmp1, MSG_OPEN_TXT_ID);
365
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.txt)")); tmp1++;
366
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.txt")); tmp1++;
493 daniel-mar 367
 
495 daniel-mar 368
                strcpy_advance_id(&tmp1, MSG_OPEN_8BF_ID);
369
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.8bf)")); tmp1++;
370
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.8bf")); tmp1++;
493 daniel-mar 371
 
495 daniel-mar 372
                strcpy_advance_id(&tmp1, MSG_OPEN_PFF_ID);
373
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.pff)")); tmp1++;
374
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.pff")); tmp1++;
493 daniel-mar 375
 
495 daniel-mar 376
                strcpy_advance_id(&tmp1, MSG_OPEN_PRM_ID);
377
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.prm)")); tmp1++;
378
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.prm")); tmp1++;
493 daniel-mar 379
 
495 daniel-mar 380
                strcpy_advance_id(&tmp1, MSG_OPEN_RSRC_ID);
381
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.bin, *.rsrc)")); tmp1++;
382
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.bin;*.rsrc")); tmp1++;
493 daniel-mar 383
 
495 daniel-mar 384
                strcpy_advance_id(&tmp1, MSG_OPEN_FFX_ID);
385
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.ffx)")); tmp1++;
386
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.ffx")); tmp1++;
493 daniel-mar 387
 
544 daniel-mar 388
                strcpy_advance_id(&tmp1, MSG_OPEN_FFL_ID);
389
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.ffl)")); tmp1++;
390
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.ffl")); tmp1++;
391
 
537 daniel-mar 392
                strcpy_advance_id(&tmp1, MSG_OPEN_GUF_ID);
393
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.guf)")); tmp1++;
394
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.guf")); tmp1++;
395
 
495 daniel-mar 396
                strcpy_advance_id(&tmp1, MSG_ALL_FILES_ID);
397
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.*)")); tmp1++;
398
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.*")); tmp1++;
493 daniel-mar 399
 
550 daniel-mar 400
                loadDlgRet = !gdata->parm.standalone && choosefiletypes(
496 daniel-mar 401
#ifdef MAC_ENV
498 daniel-mar 402
                        "\pChoose filter settings", // "\p" means "Pascal string" // TODO (Not important yet): TRANSLATE
493 daniel-mar 403
                        &sfr, &reply, types, 2,
495 daniel-mar 404
                        filters
496 daniel-mar 405
#else
406
                        title, &sfr, &reply, types, 2,
495 daniel-mar 407
                        filters, gdata->hWndMainDlg
496 daniel-mar 408
#endif
409
                );
536 daniel-mar 410
 
496 daniel-mar 411
                free(filters);
412
                free(title);
413
 
414
                if (loadDlgRet) {
552 daniel-mar 415
                        FFLoadingResult res;
416
 
408 daniel-mar 417
                        // Backup everything, otherwise we might lose parameter data if the loading fails
379 daniel-mar 418
                        bakState = saveInternalState();
292 daniel-mar 419
 
557 daniel-mar 420
                        if (LOADING_OK == (res = loadfile(&sfr))) {
259 daniel-mar 421
                                updatedialog(dp);
422
                                maindlgupdate(dp);
292 daniel-mar 423
                        }
424
                        else {
377 daniel-mar 425
                                // Restore
379 daniel-mar 426
                                restoreInternalState(bakState);
552 daniel-mar 427
 
428
                                if (res == MSG_FFL_CONVERTED_ID) {
429
                                        showmessage_id(res);
553 daniel-mar 430
                                        //return maindlgitem(dp, item); // call open Dialog again
431
                                        goto showDialogAgain;
552 daniel-mar 432
                                }
433
                                else {
434
                                        TCHAR* reason = FF_GetMsg_Cpy(res);
435
                                        alertuser_id(MSG_CANNOT_LOAD_SETTINGS_ID, reason);
436
                                        FF_GetMsg_Free(reason);
437
                                }
292 daniel-mar 438
                        }
259 daniel-mar 439
                }
440
                break;
493 daniel-mar 441
        }
259 daniel-mar 442
        case SAVEITEM:
493 daniel-mar 443
        {
495 daniel-mar 444
                TCHAR* tmp1;
496 daniel-mar 445
                TCHAR* filters, *title;
446
                Boolean saveDlgRet;
447
 
448
                title = (TCHAR*)malloc(1024);
449
                if (title == NULL) return false;
450
 
451
                filters = (TCHAR*)malloc(4096);
495 daniel-mar 452
                if (filters == NULL) return false;
453
                memset(filters, 0, 4096);
454
                tmp1 = filters;
493 daniel-mar 455
 
496 daniel-mar 456
                FF_GetMsg(title, MSG_SAVE_FILTER_SETTINGS_TITLE_ID);
457
 
495 daniel-mar 458
                strcpy_advance_id(&tmp1, MSG_ALL_SUPPORTED_FILES_ID);
537 daniel-mar 459
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.pff, *.txt, *.guf)")); tmp1++;
460
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.pff;*.txt;*.guf")); tmp1++;
493 daniel-mar 461
 
495 daniel-mar 462
                strcpy_advance_id(&tmp1, MSG_SAVE_AFS_ID);
463
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs)")); tmp1++;
464
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs")); tmp1++;
493 daniel-mar 465
 
495 daniel-mar 466
                strcpy_advance_id(&tmp1, MSG_SAVE_PFF_ID);
467
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.pff)")); tmp1++;
468
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.pff")); tmp1++;
493 daniel-mar 469
 
495 daniel-mar 470
                strcpy_advance_id(&tmp1, MSG_SAVE_TXT_ID);
471
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.txt)")); tmp1++;
472
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.txt")); tmp1++;
493 daniel-mar 473
 
537 daniel-mar 474
                strcpy_advance_id(&tmp1, MSG_SAVE_GUF_ID);
475
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.guf)")); tmp1++;
476
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.guf")); tmp1++;
477
 
495 daniel-mar 478
                strcpy_advance_id(&tmp1, MSG_ALL_FILES_ID);
479
                strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.*)")); tmp1++;
480
                strcpy_advance(&tmp1, (TCHAR*)TEXT("*.*")); tmp1++;
493 daniel-mar 481
 
550 daniel-mar 482
                saveDlgRet = !gdata->parm.standalone && putfile(
496 daniel-mar 483
#ifdef MAC_ENV
498 daniel-mar 484
                        "\pSave filter settings", // "\p" means "Pascal string" // TODO (Not important yet): TRANSLATE
485
                        "\0",
493 daniel-mar 486
                        TEXT_FILETYPE, SIG_SIMPLETEXT, &reply, &sfr,
444 daniel-mar 487
                        "afs",
495 daniel-mar 488
                        filters, 1
496 daniel-mar 489
#else
490
                        title,
444 daniel-mar 491
                        TEXT("\0"),
493 daniel-mar 492
                        TEXT_FILETYPE, SIG_SIMPLETEXT, &reply, &sfr,
444 daniel-mar 493
                        TEXT("afs"),
495 daniel-mar 494
                        filters, 1, gdata->hWndMainDlg
496 daniel-mar 495
#endif
496
                );
536 daniel-mar 497
 
496 daniel-mar 498
                free(filters);
499
                free(title);
500
 
501
                if (saveDlgRet) {
555 daniel-mar 502
                        FFSavingResult saveres = savefile_afs_pff_picotxt_guf(&sfr);
557 daniel-mar 503
                        if (saveres != SAVING_OK) {
555 daniel-mar 504
                                TCHAR* reason = FF_GetMsg_Cpy(saveres);
505
                                alertuser_id(MSG_CANNOT_SAVE_SETTINGS_ID, reason);
506
                                FF_GetMsg_Free(reason);
507
                        }
508
                        else {
259 daniel-mar 509
                                completesave(&reply);
389 daniel-mar 510
 
444 daniel-mar 511
                                if (fileHasExtension(&sfr, TEXT(".txt"))) {
492 daniel-mar 512
                                        showmessage_id(MSG_PICO_SAVED_ID);
389 daniel-mar 513
 
514
                                        #ifdef MAC_ENV
515
                                        // TODO: Open text file instead
492 daniel-mar 516
                                        showmessage_id(MSG_PLEASE_EDIT_MANUALLY_ID);
389 daniel-mar 517
                                        #else
444 daniel-mar 518
                                        hShellRes = ShellExecute(
389 daniel-mar 519
                                                gdata->hWndMainDlg,
444 daniel-mar 520
                                                TEXT("open"),
521
                                                &sfr.sfFile.szName[0],
389 daniel-mar 522
                                                NULL,
523
                                                NULL,
524
                                                SW_SHOWNORMAL
525
                                        );
526
                                        if (hShellRes <= (HINSTANCE)32) {
527
                                                // MSDN states: "If the function succeeds, it returns a value greater than 32."
528
 
444 daniel-mar 529
                                                TCHAR s[0x300];
492 daniel-mar 530
                                                xstrcpy(s, (TCHAR*)TEXT("ShellExecute failed: ")); // TODO (Not so important): TRANSLATE
454 daniel-mar 531
                                                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
482 daniel-mar 532
                                                simplealert(&s[0]);
389 daniel-mar 533
 
492 daniel-mar 534
                                                showmessage_id(MSG_PLEASE_EDIT_MANUALLY_ID);
389 daniel-mar 535
                                        }
536
                                        #endif
537
                                }
538
 
539
                        }
259 daniel-mar 540
                }
496 daniel-mar 541
 
259 daniel-mar 542
                break;
493 daniel-mar 543
        }
259 daniel-mar 544
        case MAKEITEM:
550 daniel-mar 545
                if (gdata->parm.standalone) return true; // should not happen since the button should be grayed out
365 daniel-mar 546
 
547
                builddialog(gpb);
259 daniel-mar 548
 
549
                break;
305 daniel-mar 550
        case HELPITEM:
551
                #ifdef MAC_ENV
552
                // TODO: Open web-browser instead
492 daniel-mar 553
                showmessage_id(MSG_FIND_DOKU_HERE_ID);
305 daniel-mar 554
                #else
444 daniel-mar 555
                hShellRes = ShellExecute(
305 daniel-mar 556
                        gdata->hWndMainDlg,
444 daniel-mar 557
                        TEXT("open"),
558
                        TEXT("https://github.com/danielmarschall/filter_foundry/blob/master/doc/The%20Filter%20Foundry.pdf"),
312 daniel-mar 559
                        NULL,
560
                        NULL,
561
                        SW_SHOWNORMAL
322 daniel-mar 562
                );
323 daniel-mar 563
                if (hShellRes == (HINSTANCE)ERROR_FILE_NOT_FOUND) {
322 daniel-mar 564
                        // On Win98 we get ERROR_FILE_NOT_FOUND, but the browser still opens!
565
                        // So we ignore it for now...
566
                }
323 daniel-mar 567
                else if (hShellRes <= (HINSTANCE)32) {
312 daniel-mar 568
                        // MSDN states: "If the function succeeds, it returns a value greater than 32."
322 daniel-mar 569
 
444 daniel-mar 570
                        TCHAR s[0x300];
492 daniel-mar 571
                        xstrcpy(s, (TCHAR*)TEXT("ShellExecute failed: ")); // TODO (Not so important): TRANSLATE
454 daniel-mar 572
                        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
482 daniel-mar 573
                        simplealert(&s[0]);
322 daniel-mar 574
 
492 daniel-mar 575
                        showmessage_id(MSG_FIND_DOKU_HERE_ID);
312 daniel-mar 576
                }
305 daniel-mar 577
                #endif
578
                break;
259 daniel-mar 579
        case ZOOMINITEM:
580
                zoomfactor = zoomfactor > 2. ? zoomfactor/2. : 1.;
581
                updatezoom(dp);
582
                previewerr = false;
583
                recalc_preview(gpb,dp);
584
                break;
585
        case ZOOMOUTITEM:
586
                zoomfactor *= 2.;
587
                if(zoomfactor > fitzoom)
588
                        zoomfactor = fitzoom;
589
                updatezoom(dp);
590
                previewerr = false;
591
                recalc_preview(gpb,dp);
592
                break;
593
        case ZOOMLEVELITEM:
594
                zoomfactor = zoomfactor > 1. ? 1. : (fitzoom < 1. ? 1. : fitzoom);
595
                updatezoom(dp);
596
                previewerr = false;
597
                recalc_preview(gpb,dp);
598
                break;
599
        case FIRSTCTLITEM:
600
        case FIRSTCTLITEM+1:
601
        case FIRSTCTLITEM+2:
602
        case FIRSTCTLITEM+3:
603
        case FIRSTCTLITEM+4:
604
        case FIRSTCTLITEM+5:
605
        case FIRSTCTLITEM+6:
606
        case FIRSTCTLITEM+7:
607
                slidermoved(dp,item);
608
                recalc_preview(gpb,dp);
609
                break;
610
        case FIRSTCTLTEXTITEM:
611
        case FIRSTCTLTEXTITEM+1:
612
        case FIRSTCTLTEXTITEM+2:
613
        case FIRSTCTLTEXTITEM+3:
614
        case FIRSTCTLTEXTITEM+4:
615
        case FIRSTCTLTEXTITEM+5:
616
        case FIRSTCTLTEXTITEM+6:
617
        case FIRSTCTLTEXTITEM+7:
618
                slidertextchanged(dp,item);
619
                recalc_preview(gpb,dp);
620
                break;
621
        case FIRSTICONITEM:
622
        case FIRSTICONITEM+1:
623
        case FIRSTICONITEM+2:
624
        case FIRSTICONITEM+3:
625
                item -= FIRSTICONITEM;
444 daniel-mar 626
                {
445 daniel-mar 627
                        simplealert(err[item]);
444 daniel-mar 628
                }
259 daniel-mar 629
                SELECTCTLTEXT(dp,FIRSTEXPRITEM+item,errstart[item],errpos[item]);
630
                break;
631
        case FIRSTEXPRITEM:
632
        case FIRSTEXPRITEM+1:
633
        case FIRSTEXPRITEM+2:
634
        case FIRSTEXPRITEM+3:
635
                if((item-FIRSTEXPRITEM) < nplanes){
636
                        updateexpr(dp,item);
637
                        maindlgupdate(dp);
638
                }
639
                break;
640
        }
641
 
642
        return true; // keep going
643
}
644
 
444 daniel-mar 645
Boolean alertuser(TCHAR *err,TCHAR *more){
448 daniel-mar 646
        TCHAR *s, *q;
259 daniel-mar 647
        Boolean res;
448 daniel-mar 648
        size_t i;
259 daniel-mar 649
 
492 daniel-mar 650
        if (more == NULL) {
651
                return simplealert(err);
652
        }
653
 
448 daniel-mar 654
        s = (TCHAR*)malloc((xstrlen(err) + xstrlen(more) + 3) * sizeof(TCHAR)); // 3=CR+LF+NUL
447 daniel-mar 655
        if (s == NULL) return false;
536 daniel-mar 656
 
447 daniel-mar 657
        q = s;
658
 
659
        for (i = 0; i < xstrlen(err); i++) {
660
                *q++ = err[i];
661
        }
662
 
663
        #ifdef WIN_ENV
664
        *q++ = CR;
665
        #endif
387 daniel-mar 666
        *q++ = LF;
447 daniel-mar 667
 
668
        for (i = 0; i < xstrlen(more); i++) {
669
                *q++ = more[i];
670
        }
671
 
672
        *q++ = 0;
673
 
259 daniel-mar 674
        res = simplealert(s);
675
        free(s);
676
        return res;
677
}
492 daniel-mar 678
 
679
Boolean alertuser_id(int MsgId, TCHAR* more) {
680
        TCHAR msg[1000];
681
        FF_GetMsg(&msg[0], MsgId);
682
        return alertuser(&msg[0], more);
683
}
684
 
685
Boolean simplealert_id(int MsgId) {
686
        TCHAR msg[1000];
687
        FF_GetMsg(&msg[0], MsgId);
688
        return simplealert(&msg[0]);
689
}
690
 
691
Boolean simplewarning_id(int MsgId) {
692
        TCHAR msg[1000];
693
        FF_GetMsg(&msg[0], MsgId);
694
        return simplewarning(&msg[0]);
695
}
696
 
697
Boolean showmessage_id(int MsgId) {
698
        TCHAR msg[1000];
699
        FF_GetMsg(&msg[0], MsgId);
700
        return showmessage(&msg[0]);
701
}