1 /* -*- coding: utf-8 -*- */
2 /* Copyright (C) 2000-2012 by George Williams */
3 /*
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13
14 * The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <fontforge-config.h>
30
31 #include "fontforgeui.h"
32 #include "namelist.h"
33 #include "scripting.h"
34
35 #include "gdraw.h"
36 #include "ggadget.h"
37 #include "gwidget.h"
38 #include "ustring.h"
39
40 #include <stdlib.h>
41 #include <string.h>
42
43 extern NameList *force_names_when_opening;
44 int default_font_filter_index=0;
45 struct openfilefilters *user_font_filters = NULL;
46
47 #ifdef FONTFORGE_CAN_USE_WOFF2
48 /* GGadgetWildMatch is buggy... it must be woff2 then woff */
49 # define WOFF_EXT ",woff2,woff"
50 #else
51 # define WOFF_EXT ",woff"
52 #endif
53
54 struct openfilefilters def_font_filters[] = {
55 {
56 N_("All Fonts"),
57 /* any these files... */
58 "*.{"
59 "pfa,"
60 "pfb,"
61 "pt3,"
62 "t42,"
63 "sfd,"
64 "ufo,"
65 "ttf,"
66 "bdf,"
67 "otf,"
68 "otb,"
69 "cff,"
70 "cef,"
71 "gai,"
72 "svg,"
73 "ufo,"
74 "pf3,"
75 "ttc,"
76 "gsf,"
77 "cid,"
78 "bin,"
79 "hqx,"
80 "dfont,"
81 "mf,"
82 "ik,"
83 "fon,"
84 "fnt,"
85 "pcf,"
86 "pmf,"
87 "[0-9]*pk,"
88 /* I used to say "*gf" but that also matched xgf (xgridfit) files -- which ff can't open */
89 "[0-9]*gf,"
90 "pdb"
91 WOFF_EXT
92 "}"
93 /* With any of these methods of compression */
94 "{.gz,.Z,.bz2,.lzma,}"
95 },
96 {
97 N_("Outline Fonts"),
98 "*.{"
99 "pfa,"
100 "pfb,"
101 "pt3,"
102 "t42,"
103 "sfd,"
104 "ufo,"
105 "ttf,"
106 "otf,"
107 "cff,"
108 "cef,"
109 "gai,"
110 "svg,"
111 "ufo,"
112 "pf3,"
113 "ttc,"
114 "gsf,"
115 "cid,"
116 "bin,"
117 "hqx,"
118 "dfont,"
119 "mf,"
120 "ik"
121 WOFF_EXT
122 "}"
123 "{.gz,.Z,.bz2,.lzma,}"
124 },
125 {
126 N_("Bitmap Fonts"),
127 "*.{"
128 "bdf,"
129 "otb,"
130 "bin,"
131 "hqx,"
132 "fon,"
133 "fnt,"
134 "pcf,"
135 "pmf,"
136 "*pk,"
137 "*gf,"
138 "pdb"
139 "}"
140 "{.gz,.Z,.bz2,.lzma,}"
141 },
142 { NU_("ΤεΧ Bitmap Fonts"), "*{pk,gf}" },
143 { N_("PostScript"), "*.{pfa,pfb,t42,otf,cef,cff,gai,pf3,pt3,gsf,cid}{.gz,.Z,.bz,.bz2,.lzma,}" },
144 { N_("TrueType"), "*.{ttf,t42,ttc}{.gz,.Z,.bz,.bz2,.lzma,}" },
145 { N_("OpenType"), "*.{ttf,otf" WOFF_EXT "}{.gz,.Z,.bz,.bz2,.lzma,}" },
146 { N_("Type1"), "*.{pfa,pfb,gsf,cid}{.gz,.Z,.bz2,.lzma,}" },
147 { N_("Type2"), "*.{otf,cef,cff,gai}{.gz,.Z,.bz2,.lzma,}" },
148 { N_("Type3"), "*.{pf3,pt3}{.gz,.Z,.bz2,.lzma,}" },
149 { N_("SVG"), "*.svg{.gz,.Z,.bz2,.lzma,}" },
150 { N_("Unified Font Object"), "*.ufo" },
151 { N_("FontForge's SFD"), "*.sfd{.gz,.Z,.bz2,.lzma,}" },
152 { N_("Backup SFD"), "*.sfd~" },
153 { N_("Extract from PDF"), "*.pdf{.gz,.Z,.bz2,.lzma,}" },
154 { "-", NULL },
155 { N_("Archives"), "*.{zip,tgz,tbz,tbz2,tar.gz,tar.bz,tar.bz2,tar}" },
156 { N_("All Files"), "*" },
157 { NULL, NULL }
158 };
159
StandardFilters(void)160 static GTextInfo **StandardFilters(void) {
161 int k, cnt, i;
162 GTextInfo **ti;
163
164 /* Make two passes thru outer loop. The first pass determines the
165 * interim count of how many entries will be generated and then
166 * allocates an array with 3 entries more than that. The second
167 * pass ( if(k) ) accumulates the data values, then adds a trailer,
168 * to return in the GTextInfo** structure 'ti'.
169 */
170 for ( k=0; k<2; ++k ) {
171 cnt = 0;
172 for ( i=0; def_font_filters[i].name!=NULL; ++i ) {
173 if ( k ) {
174 ti[cnt] = calloc(1,sizeof(GTextInfo));
175 ti[cnt]->userdata = def_font_filters[i].filter;
176 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
177 if ( *(char *) def_font_filters[i].name == '-' )
178 ti[cnt]->line = true;
179 else
180 ti[cnt]->text = utf82u_copy(_(def_font_filters[i].name));
181 }
182 ++cnt;
183 }
184 if ( user_font_filters!=NULL ) {
185 if ( k ) {
186 ti[cnt] = calloc(1,sizeof(GTextInfo));
187 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
188 /* Don't translate this name */
189 ti[cnt]->line = true;
190 }
191 ++cnt;
192 for ( i=0; user_font_filters[i].name!=NULL; ++i ) {
193 if ( k ) {
194 ti[cnt] = calloc(1,sizeof(GTextInfo));
195 ti[cnt]->userdata = user_font_filters[i].filter;
196 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
197 /* Don't translate this name */
198 if ( *(char *) user_font_filters[i].name == '-' )
199 ti[cnt]->line = true;
200 else
201 ti[cnt]->text = utf82u_copy(user_font_filters[i].name);
202 }
203 ++cnt;
204 }
205 }
206 if ( k ) {
207 ti[cnt] = calloc(1,sizeof(GTextInfo));
208 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
209 ti[cnt++]->line = true;
210 ti[cnt] = calloc(1,sizeof(GTextInfo));
211 ti[cnt]->userdata = (void *) -1;
212 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
213 ti[cnt++]->text = utf82u_copy(_("Edit Filter List"));
214 ti[cnt] = calloc(1,sizeof(GTextInfo));
215 } else
216 ti = malloc((cnt+3)*sizeof(GTextInfo *));
217 }
218 ti[default_font_filter_index]->selected = true;
219 return( ti );
220 }
221
222 struct filter_d {
223 int done;
224 GGadget *gme;
225 };
226
Filter_Cancel(GGadget * g,GEvent * e)227 static int Filter_Cancel(GGadget *g, GEvent *e) {
228 GWindow gw;
229 struct filter_d *d;
230
231 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
232 gw = GGadgetGetWindow(g);
233 d = GDrawGetUserData(gw);
234 d->done = true;
235 }
236 return( true );
237 }
238
Filter_OK(GGadget * g,GEvent * e)239 static int Filter_OK(GGadget *g, GEvent *e) {
240 struct filter_d *d;
241 struct matrix_data *md;
242 int rows,i,cnt;
243
244 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
245 if ( user_font_filters!=NULL ) {
246 for ( i=0; user_font_filters[i].name!=NULL; ++i ) {
247 free(user_font_filters[i].name);
248 free(user_font_filters[i].filter);
249 }
250 free(user_font_filters);
251 user_font_filters = NULL;
252 }
253 d = GDrawGetUserData(GGadgetGetWindow(g));
254 md = GMatrixEditGet(d->gme,&rows);
255 for ( i=cnt=0; i<rows; ++i )
256 if ( !md[2*i].frozen )
257 ++cnt;
258 if ( cnt!=0 ) {
259 user_font_filters = malloc((cnt+1)*sizeof(struct openfilefilters));
260 for ( i=cnt=0; i<rows; ++i ) if ( !md[2*i].frozen ) {
261 user_font_filters[cnt].name = copy(md[2*i].u.md_str);
262 user_font_filters[cnt].filter = copy(md[2*i+1].u.md_str);
263 ++cnt;
264 }
265 user_font_filters[cnt].name = user_font_filters[cnt].filter = NULL;
266 }
267 SavePrefs(true);
268 d->done = true;
269 }
270 return( true );
271 }
272
filter_e_h(GWindow gw,GEvent * event)273 static int filter_e_h(GWindow gw, GEvent *event) {
274 if ( event->type==et_close ) {
275 struct filter_d *d = GDrawGetUserData(gw);
276 d->done = true;
277 } else if ( event->type == et_char ) {
278 return( false );
279 }
280 return( true );
281 }
282
filter_candelete(GGadget * g,int r)283 static int filter_candelete(GGadget *g, int r) {
284 struct matrix_data *md;
285 int rows;
286
287 md = GMatrixEditGet(g,&rows);
288 if ( r>=rows )
289 return( false );
290
291 return( !md[2*r].frozen );
292 }
293
FilterDlg(void)294 static void FilterDlg(void) {
295 static struct col_init cols[] = {
296 { me_string, NULL, NULL, NULL, N_("Name") },
297 { me_string, NULL, NULL, NULL, N_("Filter") }
298 };
299 static int inited = false;
300 static struct matrixinit mi = {
301 2, cols,
302 0, NULL,
303 NULL,
304 filter_candelete,
305 NULL,
306 NULL,
307 NULL,
308 NULL
309 };
310 struct matrix_data *md;
311 int k, cnt, i, ptwidth;
312 GGadgetCreateData gcd[3], boxes[3], *varray[7], *harray[7];
313 GTextInfo label[3];
314 GRect pos;
315 GWindow gw;
316 GWindowAttrs wattrs;
317 struct filter_d d;
318
319 if ( !inited ) {
320 inited = true;
321 cols[0].title = _(cols[0].title);
322 cols[1].title = _(cols[1].title);
323 }
324
325 for ( k=0; k<2; ++k ) {
326 cnt = 0;
327 for ( i=0; def_font_filters[i].name!=NULL; ++i ) {
328 if ( *(char *) def_font_filters[i].name != '-' ) {
329 if ( k ) {
330 md[2*cnt].u.md_str = copy(_(def_font_filters[i].name));
331 md[2*cnt].frozen = true;
332 md[2*cnt+1].u.md_str = copy(def_font_filters[i].filter);
333 md[2*cnt+1].frozen = true;
334 }
335 ++cnt;
336 }
337 }
338 if ( user_font_filters!=NULL ) {
339 for ( i=0; user_font_filters[i].name!=NULL; ++i ) {
340 if ( *(char *) user_font_filters[i].name != '-' ) {
341 if ( k ) {
342 md[2*cnt].u.md_str = copy(user_font_filters[i].name);
343 md[2*cnt].frozen = false;
344 md[2*cnt+1].u.md_str = copy(user_font_filters[i].filter);
345 md[2*cnt+1].frozen = false;
346 }
347 ++cnt;
348 }
349 }
350 }
351 if ( !k )
352 md = calloc(2*cnt,sizeof(struct matrix_data));
353 }
354 mi.initial_row_cnt = cnt;
355 mi.matrix_data = md;
356
357
358 memset(&d,'\0',sizeof(d));
359
360 memset(&wattrs,0,sizeof(wattrs));
361 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
362 wattrs.event_masks = ~(1<<et_charup);
363 wattrs.restrict_input_to_me = 1;
364 wattrs.is_dlg = true;
365 wattrs.undercursor = 1;
366 wattrs.cursor = ct_pointer;
367 wattrs.utf8_window_title = _("Edit Font Filters");
368 pos.x = pos.y = 0;
369 ptwidth = 2*GIntGetResource(_NUM_Buttonsize)+GGadgetScale(60);
370 pos.width =GDrawPointsToPixels(NULL,ptwidth);
371 pos.height = GDrawPointsToPixels(NULL,90);
372 gw = GDrawCreateTopWindow(NULL,&pos,filter_e_h,&d,&wattrs);
373
374
375 memset(&label,0,sizeof(label));
376 memset(&gcd,0,sizeof(gcd));
377 memset(&boxes,0,sizeof(boxes));
378
379 gcd[0].gd.pos.x = 10; gcd[0].gd.pos.y = 6;
380 gcd[0].gd.pos.width = 300; gcd[0].gd.pos.height = 200;
381 gcd[0].gd.flags = gg_visible | gg_enabled;
382 gcd[0].creator = GMatrixEditCreate;
383 gcd[0].gd.u.matrix = &mi;
384 varray[0] = &gcd[0]; varray[1] = NULL;
385
386 gcd[1].gd.pos.x = 20-3; gcd[1].gd.pos.y = 90-35-3;
387 gcd[1].gd.pos.width = -1; gcd[1].gd.pos.height = 0;
388 gcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
389 label[1].text = (unichar_t *) _("_OK");
390 label[1].text_is_1byte = true;
391 label[1].text_in_resource = true;
392 gcd[1].gd.label = &label[1];
393 gcd[1].gd.handle_controlevent = Filter_OK;
394 gcd[1].creator = GButtonCreate;
395 harray[0] = GCD_Glue; harray[1] = &gcd[1]; harray[2] = GCD_Glue;
396
397 gcd[2].gd.pos.x = -20; gcd[2].gd.pos.y = 90-35;
398 gcd[2].gd.pos.width = -1; gcd[2].gd.pos.height = 0;
399 gcd[2].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
400 label[2].text = (unichar_t *) _("_Cancel");
401 label[2].text_is_1byte = true;
402 label[2].text_in_resource = true;
403 gcd[2].gd.label = &label[2];
404 gcd[2].gd.handle_controlevent = Filter_Cancel;
405 gcd[2].creator = GButtonCreate;
406 harray[3] = GCD_Glue; harray[4] = &gcd[2]; harray[5] = GCD_Glue;
407 harray[6] = NULL;
408 varray[2] = &boxes[2]; varray[3] = NULL;
409 varray[4] = NULL;
410
411 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
412 boxes[0].gd.flags = gg_enabled|gg_visible;
413 boxes[0].gd.u.boxelements = varray;
414 boxes[0].creator = GHVGroupCreate;
415
416 boxes[2].gd.flags = gg_enabled|gg_visible;
417 boxes[2].gd.u.boxelements = harray;
418 boxes[2].creator = GHBoxCreate;
419
420
421 GGadgetsCreate(gw,boxes);
422 GHVBoxSetExpandableRow(boxes[0].ret,0);
423 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
424 GHVBoxFitWindow(boxes[0].ret);
425 GMatrixEditSetNewText(gcd[0].ret,S_("Filter|New"));
426 d.gme = gcd[0].ret;
427
428 GDrawSetVisible(gw,true);
429 while ( !d.done )
430 GDrawProcessOneEvent(NULL);
431 GDrawDestroyWindow(gw);
432
433 for ( i=0; i<cnt; ++i ) {
434 free(md[2*i].u.md_str);
435 free(md[2*i+1].u.md_str);
436 }
437 free(md);
438 }
439
440 struct gfc_data {
441 int done;
442 unichar_t *ret;
443 GGadget *gfc;
444 GGadget *rename;
445 int filename_popup_pos;
446 unichar_t *lastpopupfontname;
447 };
448
GFD_Ok(GGadget * g,GEvent * e)449 static int GFD_Ok(GGadget *g, GEvent *e) {
450 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
451 struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
452 GGadget *tf;
453 GFileChooserGetChildren(d->gfc,NULL,NULL,&tf);
454 if ( *_GGadgetGetTitle(tf)!='\0' ) {
455 extern int allow_utf8_glyphnames;
456 GTextInfo *ti = GGadgetGetListItemSelected(d->rename);
457 char *nlname = u2utf8_copy(ti->text);
458 force_names_when_opening = NameListByName(nlname);
459 free(nlname);
460 if ( force_names_when_opening!=NULL && force_names_when_opening->uses_unicode &&
461 !allow_utf8_glyphnames) {
462 ff_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
463 return(true);
464 }
465 d->done = true;
466 d->ret = GGadgetGetTitle(d->gfc);
467
468 // Trim trailing '/' if its there and put that string back as
469 // the d->gfc string.
470 int tmplen = u_strlen( d->ret );
471 if( tmplen > 0 ) {
472 if( d->ret[ tmplen-1 ] == '/' ) {
473 unichar_t* tmp = u_copy( d->ret );
474 tmp[ tmplen-1 ] = '\0';
475 GGadgetSetTitle(d->gfc, tmp);
476 free(tmp);
477 d->ret = GGadgetGetTitle(d->gfc);
478 }
479 }
480 }
481 }
482 return( true );
483 }
484
GFD_New(GGadget * g,GEvent * e)485 static int GFD_New(GGadget *g, GEvent *e) {
486 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
487 struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
488 d->done = true;
489 GDrawSetVisible(GGadgetGetWindow(g),false);
490 FontNew();
491 }
492 return( true );
493 }
494
GFD_Cancel(GGadget * g,GEvent * e)495 static int GFD_Cancel(GGadget *g, GEvent *e) {
496 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
497 struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
498 d->done = true;
499 }
500 return( true );
501 }
502
GFD_FilterSelected(GGadget * g,GEvent * e)503 static int GFD_FilterSelected(GGadget *g, GEvent *e) {
504 if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
505 struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
506 GTextInfo *ti = GGadgetGetListItemSelected(g);
507 if ( ti->userdata==NULL )
508 /* They selected a line. Dull */;
509 else if ( ti->userdata == (void *) -1 ) {
510 FilterDlg();
511 GGadgetSetList(g,StandardFilters(),true);
512 } else {
513 unichar_t *temp = utf82u_copy(ti->userdata);
514 GFileChooserSetFilterText(d->gfc,temp);
515 free(temp);
516 temp = GFileChooserGetDir(d->gfc);
517 GFileChooserSetDir(d->gfc,temp);
518 free(temp);
519 default_font_filter_index = GGadgetGetFirstListSelectedItem(g);
520 SavePrefs(true);
521 }
522 }
523 return( true );
524 }
525
WithinList(struct gfc_data * d,GEvent * event)526 static int WithinList(struct gfc_data *d,GEvent *event) {
527 GRect size;
528 GGadget *list;
529 int32 pos;
530 unichar_t *ufile;
531 char *file, **fontnames;
532 int cnt, len;
533 unichar_t *msg;
534
535 if ( event->type!=et_mousemove )
536 return( false );
537
538 GFileChooserGetChildren(d->gfc,NULL, &list, NULL);
539 if ( list==NULL )
540 return( false );
541 if ( !GGadgetWithin(list,event->u.mouse.x,event->u.mouse.y) )
542 return( false );
543 pos = GListIndexFromY(list,event->u.mouse.y);
544 if ( pos == d->filename_popup_pos )
545 return( pos!=-1 );
546 if ( pos==-1 || GFileChooserPosIsDir(d->gfc,pos)) {
547 d->filename_popup_pos = -1;
548 return( pos!=-1 );
549 }
550 ufile = GFileChooserFileNameOfPos(d->gfc,pos);
551 if ( ufile==NULL )
552 return( true );
553 file = u2def_copy(ufile);
554 free(ufile);
555
556 fontnames = GetFontNames(file, 0);
557 if ( fontnames==NULL || fontnames[0]==NULL )
558 msg = uc_copy( "???" );
559 else {
560 len = 0;
561 for ( cnt=0; fontnames[cnt]!=NULL; ++cnt )
562 len += strlen(fontnames[cnt])+1;
563 msg = malloc((len+2)*sizeof(unichar_t));
564 len = 0;
565 for ( cnt=0; fontnames[cnt]!=NULL; ++cnt ) {
566 uc_strcpy(msg+len,fontnames[cnt]);
567 len += strlen(fontnames[cnt]);
568 msg[len++] = '\n';
569 }
570 msg[len-1] = '\0';
571 }
572 GGadgetPreparePopup(GGadgetGetWindow(d->gfc),msg);
573 if ( fontnames!=NULL ) {
574 for ( cnt=0; fontnames[cnt]!=NULL; ++cnt ) {
575 free(fontnames[cnt]);
576 }
577 free(fontnames);
578 }
579 free(file);
580 free(d->lastpopupfontname);
581 d->lastpopupfontname = msg;
582 return( true );
583 }
584
e_h(GWindow gw,GEvent * event)585 static int e_h(GWindow gw, GEvent *event) {
586 if ( event->type==et_close ) {
587 struct gfc_data *d = GDrawGetUserData(gw);
588 d->done = true;
589 } else if ( event->type == et_map ) {
590 /* Above palettes */
591 GDrawRaise(gw);
592 } else if ( event->type == et_char ) {
593 return( false );
594 } else if ( event->type == et_mousemove ||
595 (event->type==et_mousedown && event->u.mouse.button==3 )) {
596 struct gfc_data *d = GDrawGetUserData(gw);
597 if ( !WithinList(d,event) )
598 GFileChooserPopupCheck(d->gfc,event);
599 } else if (( event->type==et_mouseup || event->type==et_mousedown ) &&
600 (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
601 struct gfc_data *d = GDrawGetUserData(gw);
602 return( GGadgetDispatchEvent((GGadget *) (d->gfc),event));
603 } else if ( event->type == et_resize ) {
604 GRect r, size;
605 struct gfc_data *d = GDrawGetUserData(gw);
606 if ( d->gfc!=NULL ) {
607 GDrawGetSize(gw,&size);
608 GGadgetGetSize(d->gfc,&r);
609 GGadgetResize(d->gfc,size.width-2*r.x,r.height);
610 }
611 }
612 return( event->type!=et_char );
613 }
614
FVOpenFont(char * title,const char * defaultfile,bool mult,bool modal)615 static unichar_t *FVOpenFont(char *title, const char *defaultfile, bool mult, bool modal) {
616 GRect pos;
617 int i, filter, renamei;
618 GWindow gw;
619 GWindowAttrs wattrs;
620 GGadgetCreateData gcd[11], boxes[5], *varray[9], *harray1[7], *harray2[4], *harray3[9];
621 GTextInfo label[10];
622 struct gfc_data d;
623 int bs = GIntGetResource(_NUM_Buttonsize), bsbigger, totwid, spacing;
624 GGadget *tf;
625 unichar_t *temp;
626 char **nlnames;
627 GTextInfo *namelistnames, **filts;
628 int cnt;
629
630 memset(&d,'\0',sizeof(d));
631
632 memset(&wattrs,0,sizeof(wattrs));
633 if (modal) {
634 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
635 wattrs.restrict_input_to_me = 1;
636 wattrs.is_dlg = true;
637 wattrs.undercursor = 1;
638 } else {
639 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
640 }
641 wattrs.event_masks = ~(1<<et_charup);
642 wattrs.cursor = ct_pointer;
643 wattrs.utf8_window_title = title;
644
645 pos.x = pos.y = 0;
646
647 totwid = GGadgetScale(295);
648 bsbigger = 4*bs+4*14>totwid; totwid = bsbigger?4*bs+4*12:totwid;
649 spacing = (totwid-4*bs-2*12)/3;
650
651 pos.width = GDrawPointsToPixels(NULL,totwid);
652 pos.height = GDrawPointsToPixels(NULL,247);
653 gw = GDrawCreateTopWindow(NULL,&pos,e_h,&d,&wattrs);
654
655 memset(&label,0,sizeof(label));
656 memset(&gcd,0,sizeof(gcd));
657 memset(&boxes,0,sizeof(boxes));
658 i=0;
659 gcd[i].gd.pos.x = 12; gcd[i].gd.pos.y = 6; gcd[i].gd.pos.width = totwid*100/GIntGetResource(_NUM_ScaleFactor)-24; gcd[i].gd.pos.height = 180;
660 gcd[i].gd.flags = gg_visible | gg_enabled;
661 if ( RecentFiles[0]!=NULL )
662 gcd[i].gd.flags = gg_visible | gg_enabled | gg_file_pulldown;
663 if ( mult )
664 gcd[i].gd.flags |= gg_file_multiple;
665 varray[0] = &gcd[i]; varray[1] = NULL;
666 gcd[i++].creator = GFileChooserCreate;
667
668 label[i].text = (unichar_t *) _("Filter:");
669 label[i].text_is_1byte = true;
670 gcd[i].gd.label = &label[i];
671 gcd[i].gd.pos.x = 8; gcd[i].gd.pos.y = 188+6;
672 gcd[i].gd.flags = gg_visible | gg_enabled;
673 gcd[i].gd.popup_msg = _("Display files of this type" );
674 harray1[0] = GCD_Glue; harray1[1] = &gcd[i];
675 gcd[i++].creator = GLabelCreate;
676
677 gcd[i].gd.pos.x = 0; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y-6;
678 gcd[i].gd.flags = gg_visible | gg_enabled;
679 gcd[i].gd.popup_msg = _("Display files of this type");
680 gcd[i].gd.handle_controlevent = GFD_FilterSelected;
681 harray1[2] = &gcd[i]; harray1[3] = GCD_Glue; harray1[4] = GCD_Glue; harray1[5] = GCD_Glue; harray1[6] = NULL;
682 gcd[i++].creator = GListButtonCreate;
683
684 boxes[2].gd.flags = gg_visible | gg_enabled;
685 boxes[2].gd.u.boxelements = harray1;
686 boxes[2].creator = GHBoxCreate;
687 varray[2] = &boxes[2]; varray[3] = NULL;
688
689 label[i].text = (unichar_t *) _("Force glyph names to:");
690 label[i].text_is_1byte = true;
691 gcd[i].gd.label = &label[i];
692 gcd[i].gd.pos.x = 8; gcd[i].gd.pos.y = 188+6;
693 gcd[i].gd.flags = gg_visible | gg_enabled;
694 gcd[i].gd.popup_msg = _("In the saved font, force all glyph names to match those in the specified namelist");
695 harray2[0] = &gcd[i];
696 gcd[i++].creator = GLabelCreate;
697
698 renamei = i;
699 gcd[i].gd.pos.x = 0; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y-6;
700 gcd[i].gd.flags = gg_visible | gg_enabled;
701 gcd[i].gd.popup_msg = _("In the saved font, force all glyph names to match those in the specified namelist");
702 gcd[i].creator = GListButtonCreate;
703 nlnames = AllNamelistNames();
704 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt);
705 namelistnames = calloc(cnt+3,sizeof(GTextInfo));
706 namelistnames[0].text = (unichar_t *) _("No Rename");
707 namelistnames[0].text_is_1byte = true;
708 if ( force_names_when_opening==NULL ) {
709 namelistnames[0].selected = true;
710 gcd[i].gd.label = &namelistnames[0];
711 }
712 namelistnames[1].line = true;
713 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
714 namelistnames[cnt+2].text = (unichar_t *) nlnames[cnt];
715 namelistnames[cnt+2].text_is_1byte = true;
716 if ( force_names_when_opening!=NULL &&
717 strcmp(_(force_names_when_opening->title),nlnames[cnt])==0 ) {
718 namelistnames[cnt+2].selected = true;
719 gcd[i].gd.label = &namelistnames[cnt+2];
720 }
721 }
722 harray2[1] = &gcd[i]; harray2[2] = GCD_Glue; harray2[3] = NULL;
723 gcd[i++].gd.u.list = namelistnames;
724
725 boxes[3].gd.flags = gg_visible | gg_enabled;
726 boxes[3].gd.u.boxelements = harray2;
727 boxes[3].creator = GHBoxCreate;
728 varray[4] = &boxes[3]; varray[5] = NULL;
729
730 gcd[i].gd.pos.x = 12; gcd[i].gd.pos.y = 216-3;
731 gcd[i].gd.pos.width = -1;
732 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
733 label[i].text = (unichar_t *) _("_OK");
734 label[i].text_is_1byte = true;
735 label[i].text_in_resource = true;
736 gcd[i].gd.mnemonic = 'O';
737 gcd[i].gd.label = &label[i];
738 gcd[i].gd.handle_controlevent = GFD_Ok;
739 harray3[0] = GCD_Glue; harray3[1] = &gcd[i];
740 gcd[i++].creator = GButtonCreate;
741
742 gcd[i].gd.pos.x = -(spacing+bs)*100/GIntGetResource(_NUM_ScaleFactor)-12; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
743 gcd[i].gd.pos.width = -1;
744 gcd[i].gd.flags = gg_visible | gg_enabled;
745 label[i].text = (unichar_t *) S_("Font|_New");
746 label[i].text_is_1byte = true;
747 label[i].text_in_resource = true;
748 gcd[i].gd.mnemonic = 'N';
749 gcd[i].gd.label = &label[i];
750 gcd[i].gd.handle_controlevent = GFD_New;
751 harray3[2] = GCD_Glue; harray3[3] = &gcd[i];
752 gcd[i++].creator = GButtonCreate;
753
754 filter = i;
755 gcd[i].gd.pos.x = (spacing+bs)*100/GIntGetResource(_NUM_ScaleFactor)+12; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y;
756 gcd[i].gd.pos.width = -1;
757 gcd[i].gd.flags = /* gg_visible |*/ gg_enabled;
758 label[i].text = (unichar_t *) _("_Filter");
759 label[i].text_is_1byte = true;
760 label[i].text_in_resource = true;
761 gcd[i].gd.mnemonic = 'F';
762 gcd[i].gd.label = &label[i];
763 gcd[i].gd.handle_controlevent = GFileChooserFilterEh;
764 harray3[4] = &gcd[i];
765 gcd[i++].creator = GButtonCreate;
766
767 gcd[i].gd.pos.x = -12; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y;
768 gcd[i].gd.pos.width = -1;
769 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
770 label[i].text = (unichar_t *) _("_Cancel");
771 label[i].text_is_1byte = true;
772 label[i].text_in_resource = true;
773 gcd[i].gd.label = &label[i];
774 gcd[i].gd.mnemonic = 'C';
775 gcd[i].gd.handle_controlevent = GFD_Cancel;
776 harray3[5] = GCD_Glue; harray3[6] = &gcd[i]; harray3[7] = GCD_Glue; harray3[8] = NULL;
777 gcd[i++].creator = GButtonCreate;
778
779 boxes[4].gd.flags = gg_visible | gg_enabled;
780 boxes[4].gd.u.boxelements = harray3;
781 boxes[4].creator = GHBoxCreate;
782 varray[6] = &boxes[4]; varray[7] = NULL;
783 varray[8] = NULL;
784
785 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
786 boxes[0].gd.flags = gg_visible | gg_enabled;
787 boxes[0].gd.u.boxelements = varray;
788 boxes[0].creator = GHVGroupCreate;
789
790 gcd[i].gd.pos.x = 2; gcd[i].gd.pos.y = 2;
791 gcd[i].gd.pos.width = pos.width-4; gcd[i].gd.pos.height = pos.height-4;
792 gcd[i].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
793 gcd[i++].creator = GGroupCreate;
794
795 GGadgetsCreate(gw,boxes);
796
797 d.gfc = gcd[0].ret;
798 d.rename = gcd[renamei].ret;
799
800 filts = StandardFilters();
801 GGadgetSetList(harray1[2]->ret,filts,true);
802 GHVBoxSetExpandableRow(boxes[0].ret,0);
803 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
804 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
805 GHVBoxSetExpandableCol(boxes[4].ret,gb_expandgluesame);
806 GHVBoxFitWindow(boxes[0].ret);
807 free(namelistnames);
808 GGadgetSetUserData(gcd[filter].ret,gcd[0].ret);
809
810 GFileChooserConnectButtons(gcd[0].ret,harray3[1]->ret,gcd[filter].ret);
811 temp = utf82u_copy(filts[default_font_filter_index]->userdata);
812 GFileChooserSetFilterText(gcd[0].ret,temp);
813 free(temp);
814 GFileChooserGetChildren(gcd[0].ret,NULL, NULL, &tf);
815 if ( RecentFiles[0]!=NULL ) {
816 GGadgetSetList(tf,GTextInfoFromChars(RecentFiles,RECENT_MAX),false);
817 }
818 GGadgetSetTitle8(gcd[0].ret,defaultfile);
819
820 GWidgetHidePalettes();
821 GDrawSetVisible(gw,true);
822 while ( !d.done )
823 GDrawProcessOneEvent(NULL);
824 GDrawDestroyWindow(gw);
825 GDrawProcessPendingEvents(NULL); /* Give the window a chance to vanish... */
826 GDrawSync(NULL);
827 GDrawProcessPendingEvents(NULL); /* Give the window a chance to vanish... */
828 free( d.lastpopupfontname );
829 GTextInfoArrayFree(filts);
830 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
831 free(nlnames[cnt]);
832 }
833 free(nlnames);
834 return(d.ret);
835 }
836
GetPostScriptFontName(char * dir,bool mult,bool modal)837 char *GetPostScriptFontName(char *dir, bool mult, bool modal) {
838 unichar_t *ret;
839 char *u_dir;
840 char *temp;
841
842 u_dir = def2utf8_copy(dir);
843 ret = FVOpenFont(_("Open Font"), u_dir, mult, modal);
844 temp = u2def_copy(ret);
845
846 free(ret);
847 return( temp );
848 }
849
850