Line data Source code
1 : /* Copyright (C) 2002-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
29 :
30 : #include "cvundoes.h"
31 : #include "fontforgeui.h"
32 : #include <gresource.h>
33 : #include <utype.h>
34 : #include <ustring.h>
35 : #include <gkeysym.h>
36 : #include "scripting.h"
37 : #include "scriptfuncs.h"
38 :
39 : struct sd_data {
40 : int done;
41 : FontView *fv;
42 : SplineChar *sc;
43 : int layer;
44 : GWindow gw;
45 : int oldh;
46 : };
47 :
48 : #define SD_Width 250
49 : #define SD_Height 270
50 : #define CID_Script 1001
51 : #define CID_Box 1002
52 : #define CID_OK 1003
53 : #define CID_Call 1004
54 : #define CID_Cancel 1005
55 : #define CID_Python 1006
56 : #define CID_FF 1007
57 :
58 0 : static int SD_Call(GGadget *g, GEvent *e) {
59 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
60 : char *fn;
61 : unichar_t *insert;
62 :
63 0 : fn = gwwv_open_filename(_("Call Script"), NULL, "*",NULL);
64 0 : if ( fn==NULL )
65 0 : return(true);
66 0 : insert = malloc((strlen(fn)+10)*sizeof(unichar_t));
67 0 : *insert = '"';
68 0 : utf82u_strcpy(insert+1,fn);
69 0 : uc_strcat(insert,"\"()");
70 0 : GTextFieldReplace(GWidgetGetControl(GGadgetGetWindow(g),CID_Script),insert);
71 0 : free(insert);
72 0 : free(fn);
73 : }
74 0 : return( true );
75 : }
76 :
77 : #if !defined(_NO_FFSCRIPT)
78 0 : static void ExecNative(GGadget *g, GEvent *e) {
79 0 : struct sd_data *sd = GDrawGetUserData(GGadgetGetWindow(g));
80 : Context c;
81 : Val args[1];
82 : Array *dontfree[1];
83 : jmp_buf env;
84 :
85 0 : memset( &c,0,sizeof(c));
86 0 : memset( args,0,sizeof(args));
87 0 : memset( dontfree,0,sizeof(dontfree));
88 0 : running_script = true;
89 0 : c.a.argc = 1;
90 0 : c.a.vals = args;
91 0 : c.dontfree = dontfree;
92 0 : c.filename = args[0].u.sval = "ScriptDlg";
93 0 : args[0].type = v_str;
94 0 : c.return_val.type = v_void;
95 0 : c.err_env = &env;
96 0 : c.curfv = (FontViewBase *) sd->fv;
97 0 : if ( setjmp(env)!=0 ) {
98 0 : running_script = false;
99 0 : return; /* Error return */
100 : }
101 :
102 0 : c.script = tmpfile();
103 0 : if ( c.script==NULL )
104 0 : ScriptError(&c, "Can't create temporary file");
105 : else {
106 0 : const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(sd->gw,CID_Script));
107 0 : while ( *ret ) {
108 : /* There's a bug here. Filenames need to be converted to the local charset !!!! */
109 0 : putc(*ret,c.script);
110 0 : ++ret;
111 : }
112 0 : rewind(c.script);
113 0 : ff_VerboseCheck();
114 0 : c.lineno = 1;
115 0 : while ( !c.returned && !c.broken && ff_NextToken(&c)!=tt_eof ) {
116 0 : ff_backuptok(&c);
117 0 : ff_statement(&c);
118 : }
119 0 : fclose(c.script);
120 0 : sd->done = true;
121 : }
122 0 : running_script = false;
123 : }
124 : #endif
125 :
126 : #if !defined(_NO_PYTHON)
127 0 : static void ExecPython(GGadget *g, GEvent *e) {
128 0 : struct sd_data *sd = GDrawGetUserData(GGadgetGetWindow(g));
129 : char *str;
130 :
131 0 : running_script = true;
132 :
133 0 : str = GGadgetGetTitle8(GWidgetGetControl(sd->gw,CID_Script));
134 0 : PyFF_ScriptString((FontViewBase *) sd->fv,sd->sc,sd->layer,str);
135 0 : free(str);
136 0 : running_script = false;
137 0 : }
138 : #endif
139 :
140 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
141 0 : static void _SD_LangChanged(struct sd_data *sd) {
142 0 : GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_Call),
143 0 : !GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_Python)));
144 0 : }
145 :
146 0 : static int SD_LangChanged(GGadget *g, GEvent *e) {
147 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
148 0 : struct sd_data *sd = GDrawGetUserData(GGadgetGetWindow(g));
149 0 : _SD_LangChanged(sd);
150 : }
151 0 : return( true );
152 : }
153 : #endif
154 :
155 0 : static int SD_OK(GGadget *g, GEvent *e) {
156 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
157 0 : struct sd_data *sd = GDrawGetUserData(GGadgetGetWindow(g));
158 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
159 0 : if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_Python)) )
160 0 : ExecPython(g,e);
161 : else
162 0 : ExecNative(g,e);
163 : #elif !defined(_NO_PYTHON)
164 : ExecPython(g,e);
165 : #elif !defined(_NO_FFSCRIPT)
166 : ExecNative(g,e);
167 : #endif
168 0 : sd->done = true;
169 : }
170 0 : return( true );
171 : }
172 :
173 0 : static void SD_DoCancel(struct sd_data *sd) {
174 0 : sd->done = true;
175 0 : }
176 :
177 0 : static int SD_Cancel(GGadget *g, GEvent *e) {
178 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
179 0 : SD_DoCancel( GDrawGetUserData(GGadgetGetWindow(g)));
180 : }
181 0 : return( true );
182 : }
183 :
184 0 : static int sd_e_h(GWindow gw, GEvent *event) {
185 0 : struct sd_data *sd = GDrawGetUserData(gw);
186 :
187 0 : if ( sd==NULL )
188 0 : return( true );
189 :
190 0 : if ( event->type==et_close ) {
191 0 : SD_DoCancel( sd );
192 0 : } else if ( event->type==et_char ) {
193 0 : if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
194 0 : help("scripting.html");
195 0 : return( true );
196 : }
197 0 : return( false );
198 0 : } else if ( event->type == et_map ) /* Above palettes */
199 0 : GDrawRaise(gw);
200 0 : else if ( event->type == et_resize )
201 0 : GDrawRequestExpose(gw,NULL,false);
202 0 : return( true );
203 : }
204 :
205 0 : void ScriptDlg(FontView *fv,CharView *cv) {
206 : GRect pos;
207 : static GWindow gw;
208 : GWindowAttrs wattrs;
209 : GGadgetCreateData gcd[12], boxes[5], *barray[4][8], *hvarray[4][2];
210 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
211 : GGadgetCreateData *rarray[4];
212 : #endif
213 : GTextInfo label[12];
214 : struct sd_data sd;
215 : FontView *list;
216 : int i,l;
217 :
218 0 : memset(&sd,0,sizeof(sd));
219 0 : sd.fv = fv;
220 0 : sd.sc = cv==NULL ? NULL : cv->b.sc;
221 0 : sd.layer = cv==NULL ? ly_fore : CVLayer((CharViewBase *) cv);
222 0 : sd.oldh = pos.height = GDrawPointsToPixels(NULL,SD_Height);
223 :
224 0 : if ( gw==NULL ) {
225 0 : memset(&wattrs,0,sizeof(wattrs));
226 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
227 0 : wattrs.event_masks = ~(1<<et_charup);
228 0 : wattrs.restrict_input_to_me = 1;
229 0 : wattrs.undercursor = 1;
230 0 : wattrs.cursor = ct_pointer;
231 0 : wattrs.utf8_window_title = _("Execute Script");
232 0 : wattrs.is_dlg = true;
233 0 : pos.x = pos.y = 0;
234 0 : pos.width = GDrawPointsToPixels(NULL,GGadgetScale(SD_Width));
235 0 : gw = GDrawCreateTopWindow(NULL,&pos,sd_e_h,&sd,&wattrs);
236 :
237 0 : memset(&boxes,0,sizeof(boxes));
238 0 : memset(&gcd,0,sizeof(gcd));
239 0 : memset(&label,0,sizeof(label));
240 :
241 0 : i = l = 0;
242 0 : gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = 10;
243 0 : gcd[i].gd.pos.width = SD_Width-20; gcd[i].gd.pos.height = SD_Height-54;
244 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
245 0 : gcd[i].gd.cid = CID_Script;
246 0 : gcd[i++].creator = GTextAreaCreate;
247 0 : hvarray[l][0] = &gcd[i-1]; hvarray[l++][1] = NULL;
248 :
249 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
250 0 : gcd[i-1].gd.pos.height -= 24;
251 :
252 0 : gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+gcd[i-1].gd.pos.height+1;
253 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_cb_on;
254 0 : gcd[i].gd.cid = CID_Python;
255 0 : label[i].text = (unichar_t *) _("_Python");
256 0 : label[i].text_is_1byte = true;
257 0 : label[i].text_in_resource = true;
258 0 : gcd[i].gd.label = &label[i];
259 0 : gcd[i].gd.handle_controlevent = SD_LangChanged;
260 0 : gcd[i++].creator = GRadioCreate;
261 0 : rarray[0] = &gcd[i-1];
262 :
263 0 : gcd[i].gd.pos.x = 70; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y;
264 0 : gcd[i].gd.flags = gg_visible | gg_enabled; /* disabled if cv!=NULL later */
265 0 : gcd[i].gd.cid = CID_FF;
266 0 : label[i].text = (unichar_t *) _("_FF");
267 0 : label[i].text_is_1byte = true;
268 0 : label[i].text_in_resource = true;
269 0 : gcd[i].gd.label = &label[i];
270 0 : gcd[i].gd.handle_controlevent = SD_LangChanged;
271 0 : gcd[i++].creator = GRadioCreate;
272 0 : rarray[1] = &gcd[i-1]; rarray[2] = GCD_Glue; rarray[3] = NULL;
273 :
274 0 : boxes[2].gd.flags = gg_enabled | gg_visible;
275 0 : boxes[2].gd.u.boxelements = rarray;
276 0 : boxes[2].creator = GHBoxCreate;
277 0 : hvarray[l][0] = &boxes[2]; hvarray[l++][1] = NULL;
278 : #endif
279 :
280 0 : barray[0][0] = barray[1][0] = barray[0][6] = barray[1][6] = GCD_Glue;
281 0 : barray[0][2] = barray[1][2] = barray[0][4] = barray[1][4] = GCD_Glue;
282 0 : barray[0][1] = barray[0][5] = GCD_RowSpan;
283 0 : barray[0][7] = barray[1][7] = barray[2][0] = NULL;
284 0 : gcd[i].gd.pos.x = 25-3; gcd[i].gd.pos.y = SD_Height-32-3;
285 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
286 0 : label[i].text = (unichar_t *) _("_OK");
287 0 : label[i].text_is_1byte = true;
288 0 : label[i].text_in_resource = true;
289 0 : gcd[i].gd.mnemonic = 'O';
290 0 : gcd[i].gd.label = &label[i];
291 0 : gcd[i].gd.handle_controlevent = SD_OK;
292 0 : gcd[i].gd.cid = CID_OK;
293 0 : gcd[i++].creator = GButtonCreate;
294 0 : barray[1][1] = &gcd[i-1];
295 :
296 0 : gcd[i].gd.pos.x = -25; gcd[i].gd.pos.y = SD_Height-32;
297 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
298 0 : label[i].text = (unichar_t *) _("_Cancel");
299 0 : label[i].text_is_1byte = true;
300 0 : label[i].text_in_resource = true;
301 0 : gcd[i].gd.label = &label[i];
302 0 : gcd[i].gd.mnemonic = 'C';
303 0 : gcd[i].gd.handle_controlevent = SD_Cancel;
304 0 : gcd[i].gd.cid = CID_Cancel;
305 0 : gcd[i++].creator = GButtonCreate;
306 0 : barray[1][5] = &gcd[i-1];
307 :
308 0 : gcd[i].gd.pos.x = (SD_Width-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor))/2; gcd[i].gd.pos.y = SD_Height-40;
309 0 : gcd[i].gd.flags = gg_visible | gg_enabled;
310 0 : label[i].text = (unichar_t *) _("C_all...");
311 0 : label[i].text_is_1byte = true;
312 0 : label[i].text_in_resource = true;
313 0 : gcd[i].gd.label = &label[i];
314 0 : gcd[i].gd.mnemonic = 'a';
315 0 : gcd[i].gd.handle_controlevent = SD_Call;
316 0 : gcd[i].gd.cid = CID_Call;
317 0 : gcd[i++].creator = GButtonCreate;
318 0 : barray[0][3] = &gcd[i-1];
319 :
320 : #if !defined(_NO_FFSCRIPT)
321 0 : gcd[i].gd.pos.width = gcd[i].gd.pos.height = 5;
322 0 : gcd[i].gd.flags = gg_visible | gg_enabled;
323 0 : gcd[i++].creator = GSpacerCreate;
324 0 : barray[1][3] = &gcd[i-1];
325 : #else
326 : barray[1][3] = GCD_RowSpan;
327 : #endif
328 :
329 0 : barray[3][0] = NULL;
330 :
331 0 : boxes[3].gd.flags = gg_enabled | gg_visible;
332 0 : boxes[3].gd.u.boxelements = barray[0];
333 0 : boxes[3].creator = GHVBoxCreate;
334 0 : hvarray[l][0] = &boxes[3]; hvarray[l++][1] = NULL;
335 0 : hvarray[l][0] = NULL;
336 :
337 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
338 0 : boxes[0].gd.flags = gg_enabled | gg_visible;
339 0 : boxes[0].gd.u.boxelements = hvarray[0];
340 0 : boxes[0].creator = GHVGroupCreate;
341 :
342 0 : GGadgetsCreate(gw,boxes);
343 0 : if ( boxes[2].ret!=NULL )
344 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
345 0 : GHVBoxSetExpandableCol(boxes[3].ret,gb_expandgluesame);
346 0 : GHVBoxSetExpandableRow(boxes[0].ret,0);
347 0 : GHVBoxFitWindow(boxes[0].ret);
348 : }
349 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
350 0 : GGadgetSetEnabled(GWidgetGetControl(gw,CID_FF),cv==NULL);
351 : #endif
352 0 : sd.gw = gw;
353 0 : GDrawSetUserData(gw,&sd);
354 0 : GWidgetIndicateFocusGadget(GWidgetGetControl(gw,CID_Script));
355 : #if !defined(_NO_FFSCRIPT) && !defined(_NO_PYTHON)
356 0 : _SD_LangChanged(&sd);
357 : #endif
358 0 : GDrawSetVisible(gw,true);
359 0 : while ( !sd.done )
360 0 : GDrawProcessOneEvent(NULL);
361 0 : GDrawSetVisible(gw,false);
362 :
363 : /* Selection may be out of date, force a refresh */
364 0 : for ( list = fv_list; list!=NULL; list=(FontView *) list->b.next )
365 0 : GDrawRequestExpose(list->v,NULL,false);
366 0 : GDrawSync(NULL);
367 0 : GDrawProcessPendingEvents(NULL);
368 0 : GDrawSetUserData(gw,NULL);
369 0 : }
370 : #endif /* No scripting */
|