Subversion Repositories filter_foundry

Rev

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