Subversion Repositories filter_foundry

Rev

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

Rev 433 Rev 444
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-2021 Daniel Marschall, ViaThinkSoft
4
    Copyright (C) 2018-2021 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
/* This is PLATFORM INDEPENDENT user interface code - mainly dialog logic */
21
/* This is PLATFORM INDEPENDENT user interface code - mainly dialog logic */
22
 
22
 
23
#include "ff.h"
23
#include "ff.h"
24
 
24
 
25
#include "node.h"
25
#include "node.h"
26
#include "funcs.h"
26
#include "funcs.h"
27
#include "y.tab.h"
27
#include "y.tab.h"
28
#include "choosefile.h"
28
#include "choosefile.h"
29
#include "sprintf_tiny.h"
29
#include "sprintf_tiny.h"
30
#include "compat_string.h"
30
#include "compat_string.h"
31
 
31
 
32
#ifdef MAC_ENV
32
#ifdef MAC_ENV
33
        #include <plstringfuncs.h>
33
        #include <plstringfuncs.h>
34
#endif
34
#endif
35
 
35
 
36
Boolean doupdates = true;
36
Boolean doupdates = true;
37
 
37
 
38
void updateglobals(DIALOGREF dp);
38
void updateglobals(DIALOGREF dp);
39
struct node *updateexpr(DIALOGREF dp,int i);
39
struct node *updateexpr(DIALOGREF dp,int i);
40
void updatedialog(DIALOGREF dp);
40
void updatedialog(DIALOGREF dp);
41
void slidertextchanged(DIALOGREF dp,int item);
41
void slidertextchanged(DIALOGREF dp,int item);
42
void updatezoom(DIALOGREF dp);
42
void updatezoom(DIALOGREF dp);
43
 
43
 
44
void updatedialog(DIALOGREF dp){
44
void updatedialog(DIALOGREF dp){
45
        int i;
45
        int i;
46
 
46
 
47
        doupdates = false;
47
        doupdates = false;
48
 
48
 
49
        for(i = 0; i < 8; ++i){
49
        for(i = 0; i < 8; ++i){
50
                SETSLIDERVALUE(dp,FIRSTCTLITEM+i,slider[i]);
50
                SETSLIDERVALUE(dp,FIRSTCTLITEM+i,slider[i]);
51
                SETCTLTEXTINT(dp,FIRSTCTLTEXTITEM+i,slider[i],false);
51
                SETCTLTEXTINT(dp,FIRSTCTLTEXTITEM+i,slider[i],false);
52
        }
52
        }
53
 
53
 
54
        for(i = 0; i < 4; ++i){
54
        for(i = 0; i < 4; ++i){
55
                if(!gdata->standalone)
55
                if(!gdata->standalone)
56
                        SETCTLTEXT(dp,FIRSTEXPRITEM+i,expr[i] ? expr[i] : "");
56
                        SETCTLTEXT(dp,FIRSTEXPRITEM+i,expr[i] ? expr[i] : "");
57
                if(i < nplanes)
57
                if(i < nplanes)
58
                        updateexpr(dp,FIRSTEXPRITEM+i);
58
                        updateexpr(dp,FIRSTEXPRITEM+i);
59
        }
59
        }
60
 
60
 
61
        if(!gdata->standalone)
61
        if(!gdata->standalone)
62
                SELECTCTLTEXT(dp,FIRSTEXPRITEM,0,-1);
62
                SELECTCTLTEXT(dp,FIRSTEXPRITEM,0,-1);
63
 
63
 
64
        doupdates = true;
64
        doupdates = true;
65
}
65
}
66
 
66
 
67
/* copy dialog settings to global variables (sliders, expressions) */
67
/* copy dialog settings to global variables (sliders, expressions) */
68
 
68
 
69
void updateglobals(DIALOGREF dp){
69
void updateglobals(DIALOGREF dp){
70
 
70
 
71
        UNREFERENCED_PARAMETER(dp);
71
        UNREFERENCED_PARAMETER(dp);
72
 
72
 
73
        // DM 28 Nov 2021: Removed this function. It makes no sense! The internal state is in the memory
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!
74
        // and the dialog is only the view!
75
 
75
 
76
        /*
76
        /*
77
        int i;
77
        int i;
78
        char s[MAXEXPR+1];
78
        char s[MAXEXPR+1];
79
 
79
 
80
        for(i = 0; i < 8; ++i)
80
        for(i = 0; i < 8; ++i)
81
                slider[i] = (value_type)(GETSLIDERVALUE(dp,FIRSTCTLITEM+i));
81
                slider[i] = (value_type)(GETSLIDERVALUE(dp,FIRSTCTLITEM+i));
82
 
82
 
83
        if(!gdata->standalone)
83
        if(!gdata->standalone)
84
                for(i = 0; i < 4; ++i){
84
                for(i = 0; i < 4; ++i){
85
                        // stash expression strings
85
                        // stash expression strings
86
                        if(GETCTLTEXT(dp,FIRSTEXPRITEM+i,s,MAXEXPR)){
86
                        if(GETCTLTEXT(dp,FIRSTEXPRITEM+i,s,MAXEXPR)){
87
                                if(expr[i])
87
                                if(expr[i])
88
                                        free(expr[i]);
88
                                        free(expr[i]);
89
                                expr[i] = _strdup(s);
89
                                expr[i] = _strdup(s);
90
                        }
90
                        }
91
                        if(!expr[i])
91
                        if(!expr[i])
92
                                expr[i] = _strdup("c");
92
                                expr[i] = _strdup("c");
93
                }
93
                }
94
        */
94
        */
95
}
95
}
96
 
96
 
97
struct node *updateexpr(DIALOGREF dp,int item){
97
struct node *updateexpr(DIALOGREF dp,int item){
98
        char s[MAXEXPR+1];
98
        char s[MAXEXPR+1];
99
        int i;
99
        int i;
100
 
100
 
101
        i = item - FIRSTEXPRITEM;
101
        i = item - FIRSTEXPRITEM;
102
 
102
 
103
        freetree(tree[i]);
103
        freetree(tree[i]);
104
 
104
 
105
        if(!gdata->standalone){
105
        if(!gdata->standalone){
106
                GETCTLTEXT(dp,item,s,MAXEXPR);
106
                GETCTLTEXT(dp,item,s,MAXEXPR);
107
 
107
 
108
                if(expr[i])
108
                if(expr[i])
109
                        free(expr[i]);
109
                        free(expr[i]);
110
                expr[i] = _strdup(s);
110
                expr[i] = _strdup(s);
111
        }
111
        }
112
 
112
 
113
        tree[i] = parseexpr(expr[i]);
113
        tree[i] = parseexpr(expr[i]);
114
 
114
 
115
        if(!gdata->standalone){
115
        if(!gdata->standalone){
116
                if(tree[i])
116
                if(tree[i])
117
                        HideDialogItem(dp,FIRSTICONITEM+i);
117
                        HideDialogItem(dp,FIRSTICONITEM+i);
118
                else{
118
                else{
119
                        err[i] = errstr;
119
                        err[i] = errstr;
120
                        errstart[i] = tokstart;
120
                        errstart[i] = tokstart;
121
                        errpos[i] = tokpos;
121
                        errpos[i] = tokpos;
122
                        ShowDialogItem(dp,FIRSTICONITEM+i);
122
                        ShowDialogItem(dp,FIRSTICONITEM+i);
123
                }
123
                }
124
        }
124
        }
125
        return tree[i];
125
        return tree[i];
126
}
126
}
127
 
127
 
128
void updatezoom(DIALOGREF dp){
128
void updatezoom(DIALOGREF dp){
129
        char s[10];
129
        char s[10];
130
        sprintf(s, "%d%%", (int)(100./zoomfactor));
130
        sprintf(s, "%d%%", (int)(100./zoomfactor));
131
        SETCTLTEXT(dp,ZOOMLEVELITEM,s);
131
        SETCTLTEXT(dp,ZOOMLEVELITEM,s);
132
        if (zoomfactor > 1.)
132
        if (zoomfactor > 1.)
133
                ENABLEDLGITEM(dp, ZOOMINITEM);   // ShowDialogItem(dp,ZOOMINITEM);
133
                ENABLEDLGITEM(dp, ZOOMINITEM);   // ShowDialogItem(dp,ZOOMINITEM);
134
        else
134
        else
135
                DISABLEDLGITEM(dp, ZOOMINITEM);  // HideDialogItem(dp, ZOOMINITEM);
135
                DISABLEDLGITEM(dp, ZOOMINITEM);  // HideDialogItem(dp, ZOOMINITEM);
136
        if(zoomfactor < fitzoom)
136
        if(zoomfactor < fitzoom)
137
                ENABLEDLGITEM(dp, ZOOMOUTITEM);  // ShowDialogItem(dp,ZOOMOUTITEM);
137
                ENABLEDLGITEM(dp, ZOOMOUTITEM);  // ShowDialogItem(dp,ZOOMOUTITEM);
138
        else
138
        else
139
                DISABLEDLGITEM(dp, ZOOMOUTITEM); // HideDialogItem(dp,ZOOMOUTITEM);
139
                DISABLEDLGITEM(dp, ZOOMOUTITEM); // HideDialogItem(dp,ZOOMOUTITEM);
140
}
140
}
141
 
141
 
142
/* traverse expression tree, looking for constant references to sliders/maps */
142
/* traverse expression tree, looking for constant references to sliders/maps */
143
 
143
 
144
static int _checksl(struct node*p,int ctlflags[],int mapflags[]){
144
static int _checksl(struct node*p,int ctlflags[],int mapflags[]){
145
        int s, i, result;
145
        int s, i, result;
146
 
146
 
147
        result = 0;
147
        result = 0;
148
        if(p){
148
        if(p){
149
                if( (p->kind==TOK_FN1 && p->v.sym->fn == (pfunc_type)ff_ctl)
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) ){
150
                 || (p->kind==TOK_FN3 && p->v.sym->fn == (pfunc_type)ff_val) ){
151
                        if(p->child[0]->kind == TOK_NUM){
151
                        if(p->child[0]->kind == TOK_NUM){
152
                                s = p->child[0]->v.value;
152
                                s = p->child[0]->v.value;
153
                                if(s>=0 && s<=7)
153
                                if(s>=0 && s<=7)
154
                                        ctlflags[s] = 1;
154
                                        ctlflags[s] = 1;
155
                        }else
155
                        }else
156
                                result |= CHECKSLIDERS_CTL_AMBIGUOUS; /* can't determine which ctl() */
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){
157
                }else if(p->kind==TOK_FN2 && p->v.sym->fn == (pfunc_type)ff_map){
158
                        if(p->child[0]->kind == TOK_NUM){
158
                        if(p->child[0]->kind == TOK_NUM){
159
                                s = p->child[0]->v.value;
159
                                s = p->child[0]->v.value;
160
                                if(s>=0 && s<=3){
160
                                if(s>=0 && s<=3){
161
                                        mapflags[s] = 1;
161
                                        mapflags[s] = 1;
162
                                        ctlflags[s*2] = ctlflags[s*2+1] = 1;
162
                                        ctlflags[s*2] = ctlflags[s*2+1] = 1;
163
                                }
163
                                }
164
                        }else
164
                        }else
165
                                result |= CHECKSLIDERS_MAP_AMBIGUOUS; /* can't determine which map() */
165
                                result |= CHECKSLIDERS_MAP_AMBIGUOUS; /* can't determine which map() */
166
                 }
166
                 }
167
 
167
 
168
                for( i = 0 ; i < MAXCHILDREN ; ++i )
168
                for( i = 0 ; i < MAXCHILDREN ; ++i )
169
                        result |= _checksl(p->child[i],ctlflags,mapflags);
169
                        result |= _checksl(p->child[i],ctlflags,mapflags);
170
        }
170
        }
171
 
171
 
172
        return result;
172
        return result;
173
}
173
}
174
 
174
 
175
int checksliders(int exprs,int ctlflags[],int mapflags[]){
175
int checksliders(int exprs,int ctlflags[],int mapflags[]){
176
        int i, result;
176
        int i, result;
177
 
177
 
178
        result = 0;
178
        result = 0;
179
 
179
 
180
        for(i = 4; i--;)
180
        for(i = 4; i--;)
181
                mapflags[i] = 0;
181
                mapflags[i] = 0;
182
        for(i = 8; i--;)
182
        for(i = 8; i--;)
183
                ctlflags[i] = 0;
183
                ctlflags[i] = 0;
184
 
184
 
185
        for(i = 0; i < exprs; i++)
185
        for(i = 0; i < exprs; i++)
186
                result |= _checksl(tree[i],ctlflags,mapflags);
186
                result |= _checksl(tree[i],ctlflags,mapflags);
187
 
187
 
188
        return result;
188
        return result;
189
}
189
}
190
 
190
 
191
void slidermoved(DIALOGREF dp,int i){
191
void slidermoved(DIALOGREF dp,int i){
192
        int v = GETSLIDERVALUE(dp,i);
192
        int v = GETSLIDERVALUE(dp,i);
193
        i -= FIRSTCTLITEM;
193
        i -= FIRSTCTLITEM;
194
        slider[i] = v;
194
        slider[i] = v;
195
        SETCTLTEXTINT(dp,i+FIRSTCTLTEXTITEM,v,false);
195
        SETCTLTEXTINT(dp,i+FIRSTCTLTEXTITEM,v,false);
196
}
196
}
197
 
197
 
198
void slidertextchanged(DIALOGREF dp,int i){
198
void slidertextchanged(DIALOGREF dp,int i){
199
        int v = GETCTLTEXTINT(dp,i,NULL,false);
199
        int v = GETCTLTEXTINT(dp,i,NULL,false);
200
        i -= FIRSTCTLTEXTITEM;
200
        i -= FIRSTCTLTEXTITEM;
201
        SETSLIDERVALUE(dp,i+FIRSTCTLITEM,v);
201
        SETSLIDERVALUE(dp,i+FIRSTCTLITEM,v);
202
        slider[i] = v;
202
        slider[i] = v;
203
}
203
}
204
 
204
 
205
void maindlgupdate(DIALOGREF dp){
205
void maindlgupdate(DIALOGREF dp){
206
        int i,unknown,ctls[8],maps[4];
206
        int i,unknown,ctls[8],maps[4];
207
 
207
 
208
        unknown = checksliders(nplanes,ctls,maps);
208
        unknown = checksliders(nplanes,ctls,maps);
209
 
209
 
210
        for(i = 0; i < 8; i++)
210
        for(i = 0; i < 8; i++)
211
                if(unknown || ctls[i]){
211
                if(unknown || ctls[i]){
212
                        ENABLEDLGITEM(dp,FIRSTCTLITEM+i); // TODO: slider is still shown as disabled
212
                        ENABLEDLGITEM(dp,FIRSTCTLITEM+i); // TODO: slider is still shown as disabled
213
                        REPAINTCTL(dp, FIRSTCTLITEM + i); // required for PLUGIN.DLL sliders
213
                        REPAINTCTL(dp, FIRSTCTLITEM + i); // required for PLUGIN.DLL sliders
214
                        ENABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
214
                        ENABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
215
                        ShowDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
215
                        ShowDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
216
                }else{
216
                }else{
217
                        DISABLEDLGITEM(dp,FIRSTCTLITEM+i);
217
                        DISABLEDLGITEM(dp,FIRSTCTLITEM+i);
218
                        REPAINTCTL(dp,FIRSTCTLITEM+i); // required for PLUGIN.DLL sliders
218
                        REPAINTCTL(dp,FIRSTCTLITEM+i); // required for PLUGIN.DLL sliders
219
                        DISABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
219
                        DISABLEDLGITEM(dp,FIRSTCTLLABELITEM+i);
220
                        HideDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
220
                        HideDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
221
                }
221
                }
222
 
222
 
223
        for(i = 0; i < nplanes; i++)
223
        for(i = 0; i < nplanes; i++)
224
                if(!tree[i]){
224
                if(!tree[i]){
225
                        /* uh oh, couldn't parse one of the saved expressions...this is fatal */
225
                        /* uh oh, couldn't parse one of the saved expressions...this is fatal */
226
                        DISABLEDLGITEM(dp,IDOK);
226
                        DISABLEDLGITEM(dp,IDOK);
227
                        if(gdata->standalone){
227
                        if(gdata->standalone){
228
                                alertuser(_strdup("Can't run this filter (there is a problem with the saved expressions)."),_strdup(""));
228
                                alertuser((TCHAR*)TEXT("Can't run this filter (there is a problem with the saved expressions)."), (TCHAR*)TEXT(""));
229
                        }else{
229
                        }else{
230
                                DISABLEDLGITEM(dp,SAVEITEM);
230
                                DISABLEDLGITEM(dp,SAVEITEM);
231
                                DISABLEDLGITEM(dp,MAKEITEM);
231
                                DISABLEDLGITEM(dp,MAKEITEM);
232
                        }
232
                        }
233
                        return;
233
                        return;
234
                }
234
                }
235
 
235
 
236
        /* we have valid expression trees in all slots...proceed! */
236
        /* we have valid expression trees in all slots...proceed! */
237
        updateglobals(dp);
237
        updateglobals(dp);
238
        if(setup(gpb))
238
        if(setup(gpb))
239
                recalc_preview(gpb,dp);
239
                recalc_preview(gpb,dp);
240
 
240
 
241
        ENABLEDLGITEM(dp,IDOK);
241
        ENABLEDLGITEM(dp,IDOK);
242
        if(!gdata->standalone){
242
        if(!gdata->standalone){
243
                ENABLEDLGITEM(dp,SAVEITEM);
243
                ENABLEDLGITEM(dp,SAVEITEM);
244
                ENABLEDLGITEM(dp,MAKEITEM);
244
                ENABLEDLGITEM(dp,MAKEITEM);
245
                ENABLEDLGITEM(dp,HELPITEM);
245
                ENABLEDLGITEM(dp,HELPITEM);
246
        }
246
        }
247
}
247
}
248
 
248
 
249
/* one-time initialisation of dialog box */
249
/* one-time initialisation of dialog box */
250
 
250
 
251
void maindlginit(DIALOGREF dp){
251
void maindlginit(DIALOGREF dp){
252
        char s[0x100];
252
        char s[0x100];
253
        int i;
253
        int i;
254
        const char *channelsuffixes[] = {
254
        const char *channelsuffixes[] = {
255
                "", "KA", "I", "RGBA",
255
                "", "KA", "I", "RGBA",
256
                "CMYK", "HSL", "HSB", "1234",
256
                "CMYK", "HSL", "HSB", "1234",
257
                "DA", "LabA"
257
                "DA", "LabA"
258
        };
258
        };
259
 
259
 
260
        /* hide unused expression items */
260
        /* hide unused expression items */
261
        if(gdata->standalone){
261
        if(gdata->standalone){
262
                SetDlgItemText(dp,PARAMAUTHORITEM,gdata->parm.szAuthor);
262
                SetDlgItemTextA(dp,PARAMAUTHORITEM,gdata->parm.szAuthor);
263
                SetDlgItemText(dp,PARAMCOPYITEM,gdata->parm.szCopyright);
263
                SetDlgItemTextA(dp,PARAMCOPYITEM,gdata->parm.szCopyright);
264
 
264
 
265
                // update labels for map() or ctl() sliders
265
                // update labels for map() or ctl() sliders
266
                for(i = 0; i < 8; ++i){
266
                for(i = 0; i < 8; ++i){
267
                        if(gdata->parm.map_used[i/2]){
267
                        if(gdata->parm.map_used[i/2]){
268
                                if((i&1) == 0){
268
                                if((i&1) == 0){
269
                                        // even (0, 2, 4, 6)
269
                                        // even (0, 2, 4, 6)
270
                                        strcpy(s,gdata->parm.szMap[i/2]);
270
                                        strcpy(s,gdata->parm.szMap[i/2]);
271
                                        SetDlgItemText(dp, FIRSTMAPLABELITEM+(i/2),s);
271
                                        SetDlgItemTextA(dp, FIRSTMAPLABELITEM+(i/2),s);
272
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i);
272
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i);
273
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i + 1);
273
                                        HideDialogItem(dp, FIRSTCTLLABELITEM + i + 1);
274
                                }
274
                                }
275
                        } else if(gdata->parm.ctl_used[i]){
275
                        } else if(gdata->parm.ctl_used[i]){
276
                                strcpy(s,gdata->parm.szCtl[i]);
276
                                strcpy(s,gdata->parm.szCtl[i]);
277
                                SetDlgItemText(dp, FIRSTCTLLABELITEM+i,s);
277
                                SetDlgItemTextA(dp, FIRSTCTLLABELITEM+i,s);
278
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
278
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
279
                        }else{
279
                        }else{
280
                                HideDialogItem(dp, FIRSTCTLITEM+i);
280
                                HideDialogItem(dp, FIRSTCTLITEM+i);
281
                                HideDialogItem(dp, FIRSTCTLTEXTITEM+i);
281
                                HideDialogItem(dp, FIRSTCTLTEXTITEM+i);
282
                                HideDialogItem(dp, FIRSTCTLLABELITEM + i);
282
                                HideDialogItem(dp, FIRSTCTLLABELITEM + i);
283
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
283
                                HideDialogItem(dp, FIRSTMAPLABELITEM + i/2);
284
                        }
284
                        }
285
                }
285
                }
286
        }
286
        }
287
 
287
 
288
        strcpy(s,"X =");
288
        strcpy(s,"X =");
289
        for(i = 0; i < 4; ++i){
289
        for(i = 0; i < 4; ++i){
290
                if(i >= nplanes){
290
                if(i >= nplanes){
291
                        HideDialogItem(dp,FIRSTICONITEM+i);
291
                        HideDialogItem(dp,FIRSTICONITEM+i);
292
                        HideDialogItem(dp,FIRSTEXPRITEM+i);
292
                        HideDialogItem(dp,FIRSTEXPRITEM+i);
293
                        HideDialogItem(dp,FIRSTLABELITEM+i);
293
                        HideDialogItem(dp,FIRSTLABELITEM+i);
294
                }else{
294
                }else{
295
                        s[0] = channelsuffixes[gpb->imageMode][i];
295
                        s[0] = channelsuffixes[gpb->imageMode][i];
296
                        SetDlgItemText(dp,FIRSTLABELITEM+i,s);
296
                        SetDlgItemTextA(dp,FIRSTLABELITEM+i,s);
297
                }
297
                }
298
        }
298
        }
299
 
299
 
300
        if(setup_preview(gpb,nplanes)){
300
        if(setup_preview(gpb,nplanes)){
301
                // On very large images, processing a fully zoomed out preview (the initial default)
301
                // On very large images, processing a fully zoomed out preview (the initial default)
302
                // can cause out of memory errors, because Photoshop can't page in all data
302
                // can cause out of memory errors, because Photoshop can't page in all data
303
                // during advanceState. To prevent this problem, zoom in until we aren't
303
                // during advanceState. To prevent this problem, zoom in until we aren't
304
                // previewing more than say 10% of Photoshop's indicated maxSpace.
304
                // previewing more than say 10% of Photoshop's indicated maxSpace.
305
                // (e.g., on a 1GB WinXP system, PS CS2 reports 520MB maxSpace, so this will let us
305
                // (e.g., on a 1GB WinXP system, PS CS2 reports 520MB maxSpace, so this will let us
306
                // preview about 50MB of image data.)
306
                // preview about 50MB of image data.)
307
 
307
 
308
                /* Workaround: GIMP/PSPI sets maxSpace to 100 MB hardcoded, so the zoom is not adjusted correctly. */
308
                /* Workaround: GIMP/PSPI sets maxSpace to 100 MB hardcoded, so the zoom is not adjusted correctly. */
309
                int disable_zoom_memory_check;
309
                int disable_zoom_memory_check;
310
                disable_zoom_memory_check = !maxspace_available();
310
                disable_zoom_memory_check = !maxspace_available();
311
 
311
 
312
                if (!disable_zoom_memory_check) {
312
                if (!disable_zoom_memory_check) {
313
                        zoomfactor = sqrt(maxspace()/(10.*preview_w*preview_h*nplanes));
313
                        zoomfactor = sqrt(maxspace()/(10.*preview_w*preview_h*nplanes));
314
                        if(zoomfactor > fitzoom)
314
                        if(zoomfactor > fitzoom)
315
                                zoomfactor = fitzoom;
315
                                zoomfactor = fitzoom;
316
                        if(zoomfactor < 1.)
316
                        if(zoomfactor < 1.)
317
                                zoomfactor = 1.;
317
                                zoomfactor = 1.;
318
                } else {
318
                } else {
319
                        zoomfactor = fitzoom;
319
                        zoomfactor = fitzoom;
320
                }
320
                }
321
 
321
 
322
                updatezoom(dp);
322
                updatezoom(dp);
323
        }else{
323
        }else{
324
                DISABLEDLGITEM(dp, ZOOMINITEM);    // HideDialogItem(dp,ZOOMINITEM);
324
                DISABLEDLGITEM(dp, ZOOMINITEM);    // HideDialogItem(dp,ZOOMINITEM);
325
                DISABLEDLGITEM(dp, ZOOMOUTITEM);   // HideDialogItem(dp,ZOOMOUTITEM);
325
                DISABLEDLGITEM(dp, ZOOMOUTITEM);   // HideDialogItem(dp,ZOOMOUTITEM);
326
                DISABLEDLGITEM(dp, ZOOMLEVELITEM); // HideDialogItem(dp,ZOOMLEVELITEM);
326
                DISABLEDLGITEM(dp, ZOOMLEVELITEM); // HideDialogItem(dp,ZOOMLEVELITEM);
327
        }
327
        }
328
 
328
 
329
        updatedialog(dp);
329
        updatedialog(dp);
330
        maindlgupdate(dp);
330
        maindlgupdate(dp);
331
}
331
}
332
 
332
 
333
 
333
 
334
/* process an item hit. return false if the dialog is finished; otherwise return true. */
334
/* process an item hit. return false if the dialog is finished; otherwise return true. */
335
 
335
 
336
Boolean maindlgitem(DIALOGREF dp,int item){
336
Boolean maindlgitem(DIALOGREF dp,int item){
337
        extern int previewerr;
337
        extern int previewerr;
338
 
338
 
339
        StandardFileReply sfr;
339
        StandardFileReply sfr;
340
        NavReplyRecord reply;
340
        NavReplyRecord reply;
341
        static OSType types[] = {TEXT_FILETYPE,PS_FILTER_FILETYPE};
341
        static OSType types[] = {TEXT_FILETYPE,PS_FILTER_FILETYPE};
342
        char *reason;
342
        char *reason;
343
        HINSTANCE hShellRes;
343
        HINSTANCE hShellRes;
344
        InternalState bakState;
344
        InternalState bakState;
345
 
345
 
346
        switch(item){
346
        switch(item){
347
#ifdef MAC_ENV
347
#ifdef MAC_ENV
348
        case ok:
348
        case ok:
349
        case cancel:
349
        case cancel:
350
#else
350
#else
351
        case IDOK:
351
        case IDOK:
352
        case IDCANCEL:
352
        case IDCANCEL:
353
#endif
353
#endif
354
                dispose_preview();
354
                dispose_preview();
355
                return false; // end dialog
355
                return false; // end dialog
356
        case OPENITEM:
356
        case OPENITEM:
357
                if(!gdata->standalone && choosefiletypes(
357
                if(!gdata->standalone && choosefiletypes(
358
                        #ifdef MAC_ENV
358
                        #ifdef MAC_ENV
359
                        (StringPtr)_strdup("\pChoose filter settings"), // "\p" means "Pascal string"
359
                        (StringPtr)_strdup("\pChoose filter settings"), // "\p" means "Pascal string"
360
                        #else
-
 
361
                        (StringPtr)_strdup("\026Choose filter settings"),
-
 
362
                        #endif
-
 
363
                        &sfr,&reply,types,2,
360
                        & sfr, & reply, types, 2,
364
                        "All supported files (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx)\0*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx\0Filter Factory Settings (*.afs, *.txt)\0*.afs;*.txt\0PluginCommander or FFDecomp TXT file (*.txt)\0*.txt\0Filter Factory for Windows, Standalone Filter (*.8bf)\0*.8bf\0Premiere TF/FF Settings (*.pff)\0*.pff\0Premiere TT/FF for Windows, Standalone Filter (*.prm)\0*.prm\0FilterFactory for MacOS, Standalone Filter (*.bin, *.rsrc)\0*.bin\0\"Filters Unlimited\" filter (*.ffx)\0*.ffx\0All files (*.*)\0*.*\0\0"
361
                        "All supported files (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx)\0*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx\0Filter Factory Settings (*.afs, *.txt)\0*.afs;*.txt\0PluginCommander or FFDecomp TXT file (*.txt)\0*.txt\0Filter Factory for Windows, Standalone Filter (*.8bf)\0*.8bf\0Premiere TF/FF Settings (*.pff)\0*.pff\0Premiere TT/FF for Windows, Standalone Filter (*.prm)\0*.prm\0FilterFactory for MacOS, Standalone Filter (*.bin, *.rsrc)\0*.bin\0\"Filters Unlimited\" filter (*.ffx)\0*.ffx\0All files (*.*)\0*.*\0\0"
-
 
362
                        #else
-
 
363
                        TEXT("Choose filter settings"),
-
 
364
                        & sfr, & reply, types, 2,
365
                        #ifdef _WIN32
365
                        TEXT("All supported files (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx)\0*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx\0Filter Factory Settings (*.afs, *.txt)\0*.afs;*.txt\0PluginCommander or FFDecomp TXT file (*.txt)\0*.txt\0Filter Factory for Windows, Standalone Filter (*.8bf)\0*.8bf\0Premiere TF/FF Settings (*.pff)\0*.pff\0Premiere TT/FF for Windows, Standalone Filter (*.prm)\0*.prm\0FilterFactory for MacOS, Standalone Filter (*.bin, *.rsrc)\0*.bin\0\"Filters Unlimited\" filter (*.ffx)\0*.ffx\0All files (*.*)\0*.*\0\0")
366
                        ,gdata->hWndMainDlg
366
                        ,gdata->hWndMainDlg
367
                        #endif /* _WIN32 */
367
                        #endif
368
                )){
368
                )){
369
                        // Backup everything, otherwise we might lose parameter data if the loading fails
369
                        // Backup everything, otherwise we might lose parameter data if the loading fails
370
                        bakState = saveInternalState();
370
                        bakState = saveInternalState();
371
 
371
 
372
                        if (loadfile(&sfr,&reason)) {
372
                        if (loadfile(&sfr,&reason)) {
373
                                updatedialog(dp);
373
                                updatedialog(dp);
374
                                maindlgupdate(dp);
374
                                maindlgupdate(dp);
375
                        }
375
                        }
376
                        else {
376
                        else {
-
 
377
                                #ifdef UNICODE
-
 
378
                                TCHAR reasonW[0x300];
-
 
379
                                mbstowcs(reasonW, reason, 0x300);
-
 
380
                                alertuser((TCHAR*)TEXT("Could not load settings."), reasonW);
-
 
381
                                #else
377
                                alertuser(_strdup("Cannot load settings."), reason);
382
                                alertuser((TCHAR*)TEXT("Could not load settings."), reason);
-
 
383
                                #endif
378
 
384
 
379
                                // Restore
385
                                // Restore
380
                                restoreInternalState(bakState);
386
                                restoreInternalState(bakState);
381
                        }
387
                        }
382
                }
388
                }
383
                break;
389
                break;
384
        case SAVEITEM:
390
        case SAVEITEM:
385
                if(!gdata->standalone && putfile(
391
                if(!gdata->standalone && putfile(
386
                        #ifdef MAC_ENV
392
                        #ifdef MAC_ENV
387
                        (StringPtr)_strdup("\pSave filter settings"), // "\p" means "Pascal string"
393
                        (StringPtr)_strdup("\pSave filter settings"), // "\p" means "Pascal string"
388
                        #else
-
 
389
                        (StringPtr)_strdup("\024Save filter settings"),
-
 
390
                        #endif
-
 
391
                        (StringPtr)_strdup("\0"),
394
                        (StringPtr)_strdup("\0"),
392
                        TEXT_FILETYPE,SIG_SIMPLETEXT,&reply,&sfr,
395
                        TEXT_FILETYPE, SIG_SIMPLETEXT, & reply, & sfr,
-
 
396
                        "afs",
393
                        "afs","All supported files (.afs, *.pff, .txt)\0*.afs;*.pff;*.txt\0Filter Factory Settings (*.afs)\0*.afs\0Premiere TF/FF Settings (*.pff)\0*.pff\0PluginCommander TXT file (*.txt)\0*.txt\0All files (*.*)\0*.*\0\0",1
397
                        "All supported files (.afs, *.pff, .txt)\0*.afs;*.pff;*.txt\0Filter Factory Settings (*.afs)\0*.afs\0Premiere TF/FF Settings (*.pff)\0*.pff\0PluginCommander TXT file (*.txt)\0*.txt\0All files (*.*)\0*.*\0\0", 1
-
 
398
                        #else
-
 
399
                        TEXT("Save filter settings"),
-
 
400
                        TEXT("\0"),
-
 
401
                        TEXT_FILETYPE, SIG_SIMPLETEXT, & reply, & sfr,
394
                        #ifdef _WIN32
402
                        TEXT("afs"),
-
 
403
                        TEXT("All supported files (.afs, *.pff, .txt)\0*.afs;*.pff;*.txt\0Filter Factory Settings (*.afs)\0*.afs\0Premiere TF/FF Settings (*.pff)\0*.pff\0PluginCommander TXT file (*.txt)\0*.txt\0All files (*.*)\0*.*\0\0"), 1
395
                        ,gdata->hWndMainDlg
404
                        ,gdata->hWndMainDlg
396
                        #endif /* _WIN32 */
405
                        #endif
397
                )){
406
                )){
398
                        if(savefile_afs_pff_picotxt(&sfr)) {
407
                        if(savefile_afs_pff_picotxt(&sfr)) {
399
                                completesave(&reply);
408
                                completesave(&reply);
400
 
409
 
401
                                if (fileHasExtension(&sfr, ".txt")) {
410
                                if (fileHasExtension(&sfr, TEXT(".txt"))) {
402
                                        char filename[MAX_PATH];
-
 
403
 
-
 
404
                                        showmessage(_strdup("The file was successfully saved in the \"PluginCommander\" TXT format. The file will now be opened in a text editor, so that you can fill in the missing data: Category, Title, Copyright, Author, Filename, Slider/Map names."));
411
                                        showmessage((TCHAR*)TEXT("The file was successfully saved in the \"PluginCommander\" TXT format. The file will now be opened in a text editor, so that you can fill in the missing data: Category, Title, Copyright, Author, Filename, Slider/Map names."));
405
 
412
 
406
                                        #ifdef MAC_ENV
413
                                        #ifdef MAC_ENV
407
                                        // TODO: Open text file instead
414
                                        // TODO: Open text file instead
408
                                        showmessage(_strdup("Please edit the file manually to enter the title, category, authorname, copyright, slidernames etc."));
415
                                        showmessage((TCHAR*)TEXT("Please edit the file manually to enter the title, category, authorname, copyright, slidernames etc."));
409
                                        #else
416
                                        #else
410
                                        myp2cstrcpy(filename, sfr.sfFile.name);
-
 
411
                                        hShellRes = ShellExecuteA(
417
                                        hShellRes = ShellExecute(
412
                                                gdata->hWndMainDlg,
418
                                                gdata->hWndMainDlg,
413
                                                "open",
419
                                                TEXT("open"),
414
                                                filename,
420
                                                &sfr.sfFile.szName[0],
415
                                                NULL,
421
                                                NULL,
416
                                                NULL,
422
                                                NULL,
417
                                                SW_SHOWNORMAL
423
                                                SW_SHOWNORMAL
418
                                        );
424
                                        );
419
                                        if (hShellRes <= (HINSTANCE)32) {
425
                                        if (hShellRes <= (HINSTANCE)32) {
420
                                                // MSDN states: "If the function succeeds, it returns a value greater than 32."
426
                                                // MSDN states: "If the function succeeds, it returns a value greater than 32."
421
 
427
 
422
                                                char s[100];
428
                                                TCHAR s[0x300];
423
                                                strcpy(s, "ShellExecuteA failed: ");
429
                                                xstrcpy(s, (TCHAR*)TEXT("ShellExecuteA failed: "));
424
                                                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
430
                                                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - xstrlen(s), NULL);
425
                                                dbg(s);
431
                                                dbg(&s[0]);
426
 
432
 
427
                                                showmessage(_strdup("Please edit the file manually to enter the title, category, author, copyright, filename, slidernames etc."));
433
                                                showmessage((TCHAR*)TEXT("Please edit the file manually to enter the title, category, author, copyright, filename, slidernames etc."));
428
                                        }
434
                                        }
429
                                        #endif
435
                                        #endif
430
                                }
436
                                }
431
 
437
 
432
                        }
438
                        }
433
                }
439
                }
434
                break;
440
                break;
435
        case MAKEITEM:
441
        case MAKEITEM:
436
                if (gdata->standalone) return true; // should not happen since the button should be grayed out
442
                if (gdata->standalone) return true; // should not happen since the button should be grayed out
437
 
443
 
438
                builddialog(gpb);
444
                builddialog(gpb);
439
 
445
 
440
                break;
446
                break;
441
        case HELPITEM:
447
        case HELPITEM:
442
                #ifdef MAC_ENV
448
                #ifdef MAC_ENV
443
                // TODO: Open web-browser instead
449
                // TODO: Open web-browser instead
444
                showmessage(_strdup("You can find the documentation here: https://github.com/danielmarschall/filter_foundry/tree/master/doc"));
450
                showmessage((TCHAR*)TEXT("You can find the documentation here: https://github.com/danielmarschall/filter_foundry/tree/master/doc"));
445
                #else
451
                #else
446
                hShellRes = ShellExecuteA(
452
                hShellRes = ShellExecute(
447
                        gdata->hWndMainDlg,
453
                        gdata->hWndMainDlg,
448
                        "open",
454
                        TEXT("open"),
449
                        "https://github.com/danielmarschall/filter_foundry/blob/master/doc/The%20Filter%20Foundry.pdf",
455
                        TEXT("https://github.com/danielmarschall/filter_foundry/blob/master/doc/The%20Filter%20Foundry.pdf"),
450
                        NULL,
456
                        NULL,
451
                        NULL,
457
                        NULL,
452
                        SW_SHOWNORMAL
458
                        SW_SHOWNORMAL
453
                );
459
                );
454
                if (hShellRes == (HINSTANCE)ERROR_FILE_NOT_FOUND) {
460
                if (hShellRes == (HINSTANCE)ERROR_FILE_NOT_FOUND) {
455
                        // On Win98 we get ERROR_FILE_NOT_FOUND, but the browser still opens!
461
                        // On Win98 we get ERROR_FILE_NOT_FOUND, but the browser still opens!
456
                        // So we ignore it for now...
462
                        // So we ignore it for now...
457
                }
463
                }
458
                else if (hShellRes <= (HINSTANCE)32) {
464
                else if (hShellRes <= (HINSTANCE)32) {
459
                        // MSDN states: "If the function succeeds, it returns a value greater than 32."
465
                        // MSDN states: "If the function succeeds, it returns a value greater than 32."
460
 
466
 
461
                        char s[100];
467
                        TCHAR s[0x300];
462
                        strcpy(s, "ShellExecuteA failed: ");
468
                        xstrcpy(s, (TCHAR*)TEXT("ShellExecute failed: "));
463
                        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
469
                        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - xstrlen(s), NULL);
464
                        dbg(s);
470
                        dbg(&s[0]);
465
 
471
 
466
                        showmessage(_strdup("You can find the documentation here: https://github.com/danielmarschall/filter_foundry/tree/master/doc"));
472
                        showmessage((TCHAR*)TEXT("You can find the documentation here: https://github.com/danielmarschall/filter_foundry/tree/master/doc"));
467
                }
473
                }
468
                #endif
474
                #endif
469
                break;
475
                break;
470
        case ZOOMINITEM:
476
        case ZOOMINITEM:
471
                zoomfactor = zoomfactor > 2. ? zoomfactor/2. : 1.;
477
                zoomfactor = zoomfactor > 2. ? zoomfactor/2. : 1.;
472
                updatezoom(dp);
478
                updatezoom(dp);
473
                previewerr = false;
479
                previewerr = false;
474
                recalc_preview(gpb,dp);
480
                recalc_preview(gpb,dp);
475
                break;
481
                break;
476
        case ZOOMOUTITEM:
482
        case ZOOMOUTITEM:
477
                zoomfactor *= 2.;
483
                zoomfactor *= 2.;
478
                if(zoomfactor > fitzoom)
484
                if(zoomfactor > fitzoom)
479
                        zoomfactor = fitzoom;
485
                        zoomfactor = fitzoom;
480
                updatezoom(dp);
486
                updatezoom(dp);
481
                previewerr = false;
487
                previewerr = false;
482
                recalc_preview(gpb,dp);
488
                recalc_preview(gpb,dp);
483
                break;
489
                break;
484
        case ZOOMLEVELITEM:
490
        case ZOOMLEVELITEM:
485
                zoomfactor = zoomfactor > 1. ? 1. : (fitzoom < 1. ? 1. : fitzoom);
491
                zoomfactor = zoomfactor > 1. ? 1. : (fitzoom < 1. ? 1. : fitzoom);
486
                updatezoom(dp);
492
                updatezoom(dp);
487
                previewerr = false;
493
                previewerr = false;
488
                recalc_preview(gpb,dp);
494
                recalc_preview(gpb,dp);
489
                break;
495
                break;
490
        case FIRSTCTLITEM:
496
        case FIRSTCTLITEM:
491
        case FIRSTCTLITEM+1:
497
        case FIRSTCTLITEM+1:
492
        case FIRSTCTLITEM+2:
498
        case FIRSTCTLITEM+2:
493
        case FIRSTCTLITEM+3:
499
        case FIRSTCTLITEM+3:
494
        case FIRSTCTLITEM+4:
500
        case FIRSTCTLITEM+4:
495
        case FIRSTCTLITEM+5:
501
        case FIRSTCTLITEM+5:
496
        case FIRSTCTLITEM+6:
502
        case FIRSTCTLITEM+6:
497
        case FIRSTCTLITEM+7:
503
        case FIRSTCTLITEM+7:
498
                slidermoved(dp,item);
504
                slidermoved(dp,item);
499
                recalc_preview(gpb,dp);
505
                recalc_preview(gpb,dp);
500
                break;
506
                break;
501
        case FIRSTCTLTEXTITEM:
507
        case FIRSTCTLTEXTITEM:
502
        case FIRSTCTLTEXTITEM+1:
508
        case FIRSTCTLTEXTITEM+1:
503
        case FIRSTCTLTEXTITEM+2:
509
        case FIRSTCTLTEXTITEM+2:
504
        case FIRSTCTLTEXTITEM+3:
510
        case FIRSTCTLTEXTITEM+3:
505
        case FIRSTCTLTEXTITEM+4:
511
        case FIRSTCTLTEXTITEM+4:
506
        case FIRSTCTLTEXTITEM+5:
512
        case FIRSTCTLTEXTITEM+5:
507
        case FIRSTCTLTEXTITEM+6:
513
        case FIRSTCTLTEXTITEM+6:
508
        case FIRSTCTLTEXTITEM+7:
514
        case FIRSTCTLTEXTITEM+7:
509
                slidertextchanged(dp,item);
515
                slidertextchanged(dp,item);
510
                recalc_preview(gpb,dp);
516
                recalc_preview(gpb,dp);
511
                break;
517
                break;
512
        case FIRSTICONITEM:
518
        case FIRSTICONITEM:
513
        case FIRSTICONITEM+1:
519
        case FIRSTICONITEM+1:
514
        case FIRSTICONITEM+2:
520
        case FIRSTICONITEM+2:
515
        case FIRSTICONITEM+3:
521
        case FIRSTICONITEM+3:
516
                item -= FIRSTICONITEM;
522
                item -= FIRSTICONITEM;
-
 
523
                {
-
 
524
                        #ifdef UNICODE
-
 
525
                        TCHAR errW[0x300];
-
 
526
                        mbstowcs(errW, err[item], 0x300);
-
 
527
                        alertuser(errW, (TCHAR*)TEXT(""));
-
 
528
                        #else
517
                alertuser(err[item],_strdup(""));
529
                        alertuser(err[item], (TCHAR*)TEXT(""));
-
 
530
                        #endif
-
 
531
                }
518
                SELECTCTLTEXT(dp,FIRSTEXPRITEM+item,errstart[item],errpos[item]);
532
                SELECTCTLTEXT(dp,FIRSTEXPRITEM+item,errstart[item],errpos[item]);
519
                break;
533
                break;
520
        case FIRSTEXPRITEM:
534
        case FIRSTEXPRITEM:
521
        case FIRSTEXPRITEM+1:
535
        case FIRSTEXPRITEM+1:
522
        case FIRSTEXPRITEM+2:
536
        case FIRSTEXPRITEM+2:
523
        case FIRSTEXPRITEM+3:
537
        case FIRSTEXPRITEM+3:
524
                if((item-FIRSTEXPRITEM) < nplanes){
538
                if((item-FIRSTEXPRITEM) < nplanes){
525
                        updateexpr(dp,item);
539
                        updateexpr(dp,item);
526
                        maindlgupdate(dp);
540
                        maindlgupdate(dp);
527
                }
541
                }
528
                break;
542
                break;
529
        }
543
        }
530
 
544
 
531
        return true; // keep going
545
        return true; // keep going
532
}
546
}
533
 
547
 
534
Boolean alertuser(char *err,char *more){
548
Boolean alertuser(TCHAR *err,TCHAR *more){
535
        char *s = (char*)malloc(strlen(err)+strlen(more)+2),*q;
549
        TCHAR *s = (TCHAR*)malloc((xstrlen(err)+xstrlen(more)+2)*sizeof(TCHAR)), *q;
536
        Boolean res;
550
        Boolean res;
537
 
551
 
538
        q = cat(s,err);
552
        q = xstrcat(s,err);
539
        *q++ = LF;
553
        *q++ = LF;
540
        q = cat(q,more);
554
        q = xstrcat(q,more);
541
        *q = 0;
555
        *q = 0;
542
        res = simplealert(s);
556
        res = simplealert(s);
543
        free(s);
557
        free(s);
544
        return res;
558
        return res;
545
}
559
}
546
 
560