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 "encoding.h"
32 #include "fontforgeui.h"
33 #include "gfile.h"
34 #include "gicons.h"
35 #include "gio.h"
36 #include "gkeysym.h"
37 #include "gresource.h"
38 #include "macbinary.h"
39 #include "mm.h"
40 #include "namelist.h"
41 #include "psfont.h"
42 #include "savefont.h"
43 #include "splinefill.h"
44 #include "splinesaveafm.h"
45 #include "splineutil.h"
46 #include "tottf.h"
47 #include "ustring.h"
48 #include "utype.h"
49 #include "woff.h"
50 
51 #include <locale.h>
52 #include <math.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <time.h>
56 #include <unistd.h>
57 
58 int ask_user_for_resolution = true;
59 int old_fontlog=false;
60 
61 static int nfnt_warned = false, post_warned = false;
62 
63 #define CID_MergeTables	100
64 #define CID_TTC_CFF	101
65 #define CID_Family	2000
66 
67 #define CID_AppendFontLog	400
68 #define CID_FontLogBit		401
69 #define CID_Layers		402
70 #define CID_PrependTimestamp    403
71 
72 #define CID_OK		        1001
73 #define CID_PS_AFM		1002
74 #define CID_PS_PFM		1003
75 #define CID_PS_TFM		1004
76 #define CID_PS_HintSubs		1005
77 #define CID_PS_Flex		1006
78 #define CID_PS_Hints		1007
79 #define CID_PS_Restrict256	1008
80 #define CID_PS_Round		1009
81 #define CID_PS_OFM		1010
82 #define CID_PS_AFMmarks		1011
83 #define CID_TTF_Hints		1101
84 #define CID_TTF_FullPS		1102
85 #define CID_TTF_AppleMode	1103
86 #define CID_TTF_PfEdComments	1104
87 #define CID_TTF_PfEdColors	1105
88 #define CID_TTF_PfEd		1106
89 #define CID_TTF_TeXTable	1107
90 #define CID_TTF_OpenTypeMode	1108
91 #define CID_TTF_OldKern		1109
92 #define CID_TTF_GlyphMap	1110
93 #define CID_TTF_OFM		1111
94 #define CID_TTF_NoMacNames	1112
95 #define CID_TTF_PfEdLookups	1113
96 #define CID_TTF_PfEdGuides	1114
97 #define CID_TTF_PfEdLayers	1115
98 #define CID_FontLog		1116
99 #define CID_TTF_DummyDSIG	1117
100 #define CID_NativeKern		1118
101 #define CID_TTF_OldKernMappedOnly 1119
102 #define CID_TTF_FFTMTable	1120
103 
104 struct gfc_data {
105     int done;
106     int sod_done;
107     int sod_which;
108     int sod_invoked;
109     int ret;
110     int family, familycnt;
111     GWindow gw;
112     GGadget *gfc;
113     GGadget *pstype;
114     GGadget *bmptype;
115     GGadget *bmpsizes;
116     GGadget *options;
117     GGadget *rename;
118     GGadget *validate;
119     int ps_flags;		/* The ordering of these flags fields is */
120     int sfnt_flags;		/*  important. We index into them */
121   /* WAS otf_flags */
122     int psotb_flags;		/*  don't reorder or put junk in between */
123     uint8 optset[3];
124     SplineFont *sf;
125     EncMap *map;
126     int layer;
127 };
128 
129 static GTextInfo formattypes[] = {
130     { (unichar_t *) N_("PS Type 1 (Ascii)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
131     { (unichar_t *) N_("PS Type 1 (Binary)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
132 #if __Mac
133     { (unichar_t *) N_("PS Type 1 (Resource)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
134 #else
135     { (unichar_t *) N_("PS Type 1 (MacBin)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
136 #endif
137     { (unichar_t *) N_("PS Type 1 (Multiple)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
138     { (unichar_t *) N_("PS Multiple Master(A)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
139     { (unichar_t *) N_("PS Multiple Master(B)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
140     { (unichar_t *) N_("PS Type 3"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
141     { (unichar_t *) N_("PS Type 0"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
142     { (unichar_t *) N_("PS CID"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
143 /* GT: "CFF (Bare)" means a CFF font without the normal OpenType wrapper */
144 /* GT: CFF is a font format that normally lives inside an OpenType font */
145 /* GT: but it is perfectly meaningful to remove all the OpenType complexity */
146 /* GT: and just leave a bare CFF font */
147     { (unichar_t *) N_("CFF (Bare)"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
148     { (unichar_t *) N_("CFF CID (Bare)"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
149     { (unichar_t *) N_("Type42"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
150     { (unichar_t *) N_("Type11 (CID 2)"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
151     { (unichar_t *) N_("TrueType"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
152     { (unichar_t *) N_("TrueType (Symbol)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
153 #if __Mac
154     { (unichar_t *) N_("TrueType (Resource)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
155 #else
156     { (unichar_t *) N_("TrueType (MacBin)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
157 #endif
158     { (unichar_t *) N_("TrueType (TTC)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
159     { (unichar_t *) N_("TrueType (Mac dfont)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
160     { (unichar_t *) N_("OpenType (CFF)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
161     { (unichar_t *) N_("OpenType (Mac dfont)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
162     { (unichar_t *) N_("OpenType CID"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
163     { (unichar_t *) N_("OpenType CID (dfont)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
164     { (unichar_t *) N_("SVG font"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
165     { (unichar_t *) N_("Unified Font Object (UFO3)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
166     { (unichar_t *) N_("Unified Font Object 2"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
167     { (unichar_t *) N_("Unified Font Object 3"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
168     { (unichar_t *) N_("Web Open Font (WOFF)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
169     { (unichar_t *) N_("Web Open Font (WOFF2)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
170     { (unichar_t *) N_("No Outline Font"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
171     GTEXTINFO_EMPTY
172 };
173 static GTextInfo bitmaptypes[] = {
174     { (unichar_t *) N_("BDF"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
175     { (unichar_t *) N_("In TTF/OTF"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
176     { (unichar_t *) N_("Apple bitmap only sfnt (dfont)"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
177     { (unichar_t *) N_("(faked) MS bitmap only sfnt (ttf)"), NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
178     { (unichar_t *) N_("X11 bitmap only sfnt (otb)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
179 #if __Mac
180     { (unichar_t *) N_("NFNT (Resource)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
181 #else
182     { (unichar_t *) N_("NFNT (MacBin)"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
183 #endif
184 /* OS/X doesn't seem to support NFNTs, so there's no point in putting them in a dfont */
185 /*  { (unichar_t *) "NFNT (dfont)", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },*/
186     { (unichar_t *) N_("Win FON"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
187     { (unichar_t *) N_("Win FNT"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
188     { (unichar_t *) N_("Palm OS Bitmap"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
189     { (unichar_t *) N_("PS Type3 Bitmap"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
190     { (unichar_t *) N_("No Bitmap Fonts"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
191     GTEXTINFO_EMPTY
192 };
193 
194 int old_validate = true;
195 
196 extern int old_sfnt_flags;
197 extern int old_ps_flags;
198 extern int old_psotb_flags;
199 
200 extern int oldformatstate;
201 extern int oldbitmapstate;
202 
203 static const char *pfaeditflag = "SplineFontDB:";
204 
ParseBitmapSizes(GGadget * g,char * msg,int * err)205 int32 *ParseBitmapSizes(GGadget *g,char *msg,int *err) {
206     const unichar_t *val = _GGadgetGetTitle(g), *pt; unichar_t *end, *end2;
207     int i;
208     int32 *sizes;
209 
210     locale_t tmplocale; locale_t oldlocale; // Declare temporary locale storage.
211     switch_to_c_locale(&tmplocale, &oldlocale); // Switch to the C locale temporarily and cache the old locale.
212 
213     *err = false;
214     end2 = NULL;
215     for ( i=1, pt = val; (end = u_strchr(pt,',')) || (end2=u_strchr(pt,' ')); ++i ) {
216 	if ( end!=NULL && end2!=NULL ) {
217 	    if ( end2<end ) end = end2;
218 	} else if ( end2!=NULL )
219 	    end = end2;
220 	pt = end+1;
221 	end2 = NULL;
222     }
223     sizes = malloc((i+1)*sizeof(int32));
224 
225     for ( i=0, pt = val; *pt!='\0' ; ) {
226 	sizes[i]=rint(u_strtod(pt,&end));
227 	if ( msg!=_("Pixel List") )
228 	    /* No bit depth allowed */;
229 	else if ( *end!='@' )
230 	    sizes[i] |= 0x10000;
231 	else
232 	    sizes[i] |= (u_strtol(end+1,&end,10)<<16);
233 	if ( sizes[i]>0 ) ++i;
234 	if ( *end!=' ' && *end!=',' && *end!='\0' ) {
235 	    free(sizes);
236 	    GGadgetProtest8(msg);
237 	    *err = true;
238     break;
239 	}
240 	while ( *end==' ' || *end==',' ) ++end;
241 	pt = end;
242     }
243     switch_to_old_locale(&tmplocale, &oldlocale); // Switch to the cached locale.
244     if ( *err )
245 return( NULL );
246     sizes[i] = 0;
247 return( sizes );
248 }
249 
OPT_PSHints(GGadget * g,GEvent * e)250 static int OPT_PSHints(GGadget *g, GEvent *e) {
251     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
252 	GWindow gw = GGadgetGetWindow(g);
253 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
254 	if ( GGadgetIsChecked(g)) {
255 	    int which = d->sod_which>1? d->sod_which-1 : d->sod_which;
256 	    int flags = (&d->ps_flags)[which];
257 	    /*GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_HintSubs),true);*/
258 	    GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Flex),true);
259 	    /*GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_HintSubs),!(flags&ps_flag_nohintsubs));*/
260 	    GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Flex),!(flags&ps_flag_noflex));
261 	} else {
262 	    /*GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_HintSubs),false);*/
263 	    GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Flex),false);
264 	    /*GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_HintSubs),false);*/
265 	    GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Flex),false);
266 	}
267     }
268 return( true );
269 }
270 
OPT_Applemode(GGadget * g,GEvent * e)271 static int OPT_Applemode(GGadget *g, GEvent *e) {
272     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
273 	GWindow gw = GGadgetGetWindow(g);
274 	if ( GGadgetIsChecked(g))
275 	    GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OldKern),false);
276     }
277 return( true );
278 }
279 
OPT_OldKern(GGadget * g,GEvent * e)280 static int OPT_OldKern(GGadget *g, GEvent *e) {
281     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
282 	GWindow gw = GGadgetGetWindow(g);
283 	if ( GGadgetIsChecked(g))
284 	    GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_AppleMode),false);
285     }
286 return( true );
287 }
288 
sod_e_h(GWindow gw,GEvent * event)289 static int sod_e_h(GWindow gw, GEvent *event) {
290     if ( event->type==et_close ) {
291 	struct gfc_data *d = GDrawGetUserData(gw);
292 	d->sod_done = true;
293     } else if ( event->type == et_char ) {
294 	if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
295 	    help("ui/dialogs/generate.html", "#generate-options");
296 return( true );
297 	}
298 return( false );
299     } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
300 	struct gfc_data *d = GDrawGetUserData(gw);
301 	if ( GGadgetGetCid(event->u.control.g)==CID_OK ) {
302 	    if ( d->sod_which==0 ) {		/* PostScript */
303 		d->ps_flags = 0;
304 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_AFM)) )
305 		    d->ps_flags |= ps_flag_afm;
306 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_AFMmarks)) )
307 		    d->ps_flags |= ps_flag_afmwithmarks;
308 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_PFM)) )
309 		    d->ps_flags |= ps_flag_pfm;
310 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_TFM)) )
311 		    d->ps_flags |= ps_flag_tfm;
312 		/*if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_HintSubs)) )*/
313 		    /*d->ps_flags |= ps_flag_nohintsubs;*/
314 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Flex)) )
315 		    d->ps_flags |= ps_flag_noflex;
316 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Hints)) )
317 		    d->ps_flags |= ps_flag_nohints;
318 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Round)) )
319 		    d->ps_flags |= ps_flag_round;
320 		/*if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Restrict256)) )*/
321 		    /*d->ps_flags |= ps_flag_restrict256;*/
322 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_FontLog)) )
323 		    d->ps_flags |= ps_flag_outputfontlog;
324 	    } else if ( d->sod_which==1 || d->sod_which==2 ) {	/* Open/TrueType */
325 		d->sfnt_flags = 0;
326 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_Hints)) )
327 		    d->sfnt_flags |= ttf_flag_nohints;
328 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_FullPS)) )
329 		    d->sfnt_flags |= ttf_flag_shortps;
330 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_AppleMode)) )
331 		    d->sfnt_flags |= ttf_flag_applemode;
332 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_OpenTypeMode)) )
333 		    d->sfnt_flags |= ttf_flag_otmode;
334 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_OldKern)) &&
335 			!(d->sfnt_flags&ttf_flag_applemode) )
336 		    d->sfnt_flags |= ttf_flag_oldkern;
337 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_DummyDSIG)) )
338 		    d->sfnt_flags |= ttf_flag_dummyDSIG;
339 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdComments)) )
340 		    d->sfnt_flags |= ttf_flag_pfed_comments;
341 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdColors)) )
342 		    d->sfnt_flags |= ttf_flag_pfed_colors;
343 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdLookups)) )
344 		    d->sfnt_flags |= ttf_flag_pfed_lookupnames;
345 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdGuides)) )
346 		    d->sfnt_flags |= ttf_flag_pfed_guides;
347 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdLayers)) )
348 		    d->sfnt_flags |= ttf_flag_pfed_layers;
349 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_FFTMTable)) )
350 		    d->sfnt_flags |= ttf_flag_noFFTMtable;
351 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_TeXTable)) )
352 		    d->sfnt_flags |= ttf_flag_TeXtable;
353 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_GlyphMap)) )
354 		    d->sfnt_flags |= ttf_flag_glyphmap;
355 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_OFM)) )
356 		    d->sfnt_flags |= ttf_flag_ofm;
357 
358 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_AFM)) )
359 		    d->sfnt_flags |= ps_flag_afm;
360 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_AFMmarks)) )
361 		    d->sfnt_flags |= ps_flag_afmwithmarks;
362 		/*if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_HintSubs)) )*/
363 		    /*d->sfnt_flags |= ps_flag_nohintsubs;*/
364 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Flex)) )
365 		    d->sfnt_flags |= ps_flag_noflex;
366 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Hints)) )
367 		    d->sfnt_flags |= ps_flag_nohints;
368 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Round)) )
369 		    d->sfnt_flags |= ps_flag_round;
370 
371 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_FontLog)) )
372 		    d->sfnt_flags |= ps_flag_outputfontlog;
373 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_NativeKern)) )
374 		    d->sfnt_flags |= ttf_native_kern; // This applies mostly to U. F. O. right now.
375 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_OldKernMappedOnly)) )
376 		    d->sfnt_flags |= ttf_flag_oldkernmappedonly;
377 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_NoMacNames)) )
378 		    d->sfnt_flags |= ttf_flag_nomacnames;
379 	    } else {				/* PS + OpenType Bitmap */
380 		d->ps_flags = d->psotb_flags = 0;
381 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_AFMmarks)) )
382 		     d->psotb_flags = d->ps_flags |= ps_flag_afmwithmarks;
383 		/*if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_HintSubs)) )*/
384 		     /*d->psotb_flags = d->ps_flags |= ps_flag_nohintsubs;*/
385 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Flex)) )
386 		     d->psotb_flags = d->ps_flags |= ps_flag_noflex;
387 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Hints)) )
388 		     d->psotb_flags = d->ps_flags |= ps_flag_nohints;
389 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_Round)) )
390 		     d->psotb_flags = d->ps_flags |= ps_flag_round;
391 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_PFM)) )
392 		     d->psotb_flags = d->ps_flags |= ps_flag_pfm;
393 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_PS_TFM)) )
394 		     d->psotb_flags = d->ps_flags |= ps_flag_tfm;
395 
396 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_FullPS)) )
397 		    d->psotb_flags |= ttf_flag_shortps;
398 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdComments)) )
399 		    d->psotb_flags |= ttf_flag_pfed_comments;
400 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdColors)) )
401 		    d->psotb_flags |= ttf_flag_pfed_colors;
402 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdLookups)) )
403 		    d->psotb_flags |= ttf_flag_pfed_lookupnames;
404 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdGuides)) )
405 		    d->psotb_flags |= ttf_flag_pfed_guides;
406 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_PfEdLayers)) )
407 		    d->psotb_flags |= ttf_flag_pfed_layers;
408 		if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_FFTMTable)) )
409 		    d->psotb_flags |= ttf_flag_noFFTMtable;
410 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_TeXTable)) )
411 		    d->psotb_flags |= ttf_flag_TeXtable;
412 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_GlyphMap)) )
413 		    d->psotb_flags |= ttf_flag_glyphmap;
414 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_OFM)) )
415 		    d->psotb_flags |= ttf_flag_ofm;
416 		if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_NoMacNames)) )
417 		    d->psotb_flags |= ttf_flag_nomacnames;
418 	    }
419 	    d->sod_invoked = true;
420 	}
421 	d->sod_done = true;
422     }
423 return( true );
424 }
425 
OptSetDefaults(GWindow gw,struct gfc_data * d,int which,int iscid)426 static void OptSetDefaults(GWindow gw,struct gfc_data *d,int which,int iscid) {
427     int w = which>1 ? which-1 : which;
428     int flags = (&d->ps_flags)[w];
429     int fs = GGadgetGetFirstListSelectedItem(d->pstype);
430     int bf = GGadgetGetFirstListSelectedItem(d->bmptype);
431     /* which==0 => pure postscript */
432     /* which==1 => truetype or bitmap in sfnt wrapper */
433     /* which==2 => opentype (ps) */
434     /* which==3 => generating an sfnt based bitmap only font with a postscript outline font */
435 
436     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Hints),!(flags&ps_flag_nohints));
437     /*GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_HintSubs),!(flags&ps_flag_nohintsubs));*/
438     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Flex),!(flags&ps_flag_noflex));
439     /*GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Restrict256),flags&ps_flag_restrict256);*/
440     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Round),flags&ps_flag_round);
441 
442     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_AFM),flags&ps_flag_afm);
443     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_AFMmarks),flags&ps_flag_afmwithmarks);
444     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_PFM),(flags&ps_flag_pfm) && !iscid);
445     GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_TFM),flags&ps_flag_tfm);
446 
447     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_Hints),!(flags&ttf_flag_nohints));
448     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_FullPS),!(flags&ttf_flag_shortps));
449     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OFM),flags&ttf_flag_ofm);
450     if ( d->optset[which] )
451 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_AppleMode),flags&ttf_flag_applemode);
452     else if ( which==0 || which==3 )	/* PostScript */
453 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_AppleMode),false);
454     else
455 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_AppleMode),(flags&ttf_flag_applemode));
456     if ( d->optset[which] )
457 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OpenTypeMode),flags&ttf_flag_otmode);
458     else if ( which==0 )	/* PostScript */
459 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OpenTypeMode),false);
460     else if ( (fs==ff_ttfmacbin || fs==ff_ttfdfont || fs==ff_otfdfont ||
461 	     fs==ff_otfciddfont || d->family==gf_macfamily || (fs==ff_none && bf==bf_sfnt_dfont)))
462 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OpenTypeMode),false);
463     else
464 	GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OpenTypeMode),(flags&ttf_flag_otmode));
465 
466     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_PfEdComments),flags&ttf_flag_pfed_comments);
467     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_PfEdColors),flags&ttf_flag_pfed_colors);
468     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_PfEdLookups),flags&ttf_flag_pfed_lookupnames);
469     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_PfEdGuides),flags&ttf_flag_pfed_guides);
470     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_PfEdLayers),flags&ttf_flag_pfed_layers);
471     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_FFTMTable),
472 	    which!=0 && !(flags&ttf_flag_noFFTMtable));
473     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_TeXTable),flags&ttf_flag_TeXtable);
474     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_GlyphMap),flags&ttf_flag_glyphmap);
475     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OldKern),
476 	    (flags&ttf_flag_oldkern) && !GGadgetIsChecked(GWidgetGetControl(gw,CID_TTF_AppleMode)));
477     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_DummyDSIG),flags&ttf_flag_dummyDSIG);
478     GGadgetSetChecked(GWidgetGetControl(gw,CID_FontLog),flags&ps_flag_outputfontlog);
479     GGadgetSetChecked(GWidgetGetControl(gw,CID_NativeKern),flags&ttf_native_kern);
480     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_OldKernMappedOnly),flags&ttf_flag_oldkernmappedonly);
481     GGadgetSetChecked(GWidgetGetControl(gw,CID_TTF_NoMacNames),flags&ttf_flag_nomacnames);
482 
483     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Hints),which!=1);
484     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Flex),which!=1);
485     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Round),which!=1);
486     if ( which!=1 && (flags&ps_flag_nohints)) {
487 	GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_Flex),false);
488 	GGadgetSetChecked(GWidgetGetControl(gw,CID_PS_Flex),false);
489     }
490 
491     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_AFM),which!=1);
492     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_AFMmarks),which!=1);
493     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_PFM),which==0 || which==3);
494     GGadgetSetEnabled(GWidgetGetControl(gw,CID_PS_TFM),which==0 || which==3);
495 
496     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_Hints),which==1);
497     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_FullPS),which!=0);
498     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_AppleMode),which!=0 && which!=3);
499     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_OpenTypeMode),which!=0 && which!=3);
500     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_OldKern),which!=0 );
501     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_DummyDSIG),which!=0 );
502 
503     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEd),which!=0);
504     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdComments),which!=0);
505     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdColors),which!=0);
506     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdLookups),which!=0);
507     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdGuides),which!=0);
508     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdColors),which!=0);
509     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_PfEdLayers),which!=0);
510     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_FFTMTable), which!=0);
511     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_TeXTable),which!=0);
512     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_GlyphMap),which!=0);
513     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_OFM),which!=0);
514 
515     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_OldKernMappedOnly),which!=0 );
516     GGadgetSetEnabled(GWidgetGetControl(gw,CID_TTF_NoMacNames),which!=0 );
517 
518     d->optset[which] = true;
519 }
520 
521 #define OPT_Width	230
522 #define OPT_Height	233
523 
SaveOptionsDlg(struct gfc_data * d,int which,int iscid)524 static void SaveOptionsDlg(struct gfc_data *d,int which,int iscid) {
525     int k,fontlog_k,group,group2;
526     GWindow gw;
527     GWindowAttrs wattrs;
528     GGadgetCreateData gcd[36];
529     GTextInfo label[36];
530     GRect pos;
531     GGadgetCreateData *hvarray1[21], *hvarray2[44], *hvarray3[8], *harray[7], *varray[11];
532     GGadgetCreateData boxes[6];
533 
534     d->sod_done = false;
535     d->sod_which = which;
536 
537     memset(&wattrs,0,sizeof(wattrs));
538     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
539     wattrs.event_masks = ~(1<<et_charup);
540     wattrs.restrict_input_to_me = 1;
541     wattrs.undercursor = 1;
542     wattrs.cursor = ct_pointer;
543     wattrs.utf8_window_title = _("Options");
544     wattrs.is_dlg = true;
545     pos.x = pos.y = 0;
546     pos.width = GGadgetScale(GDrawPointsToPixels(NULL,OPT_Width));
547     pos.height = GDrawPointsToPixels(NULL,OPT_Height);
548     gw = GDrawCreateTopWindow(NULL,&pos,sod_e_h,d,&wattrs);
549 
550     memset(&label,0,sizeof(label));
551     memset(&gcd,0,sizeof(gcd));
552     memset(boxes,0,sizeof(boxes));
553 
554     k = 0;
555     gcd[k].gd.pos.x = 2; gcd[k].gd.pos.y = 2;
556     gcd[k].gd.pos.width = pos.width-4; gcd[k].gd.pos.height = pos.height-4;
557     gcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
558     gcd[k++].creator = GGroupCreate;
559 
560     label[k].text = (unichar_t *) U_("PostScript®");
561     label[k].text_is_1byte = true;
562     gcd[k].gd.label = &label[k];
563     gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = 5;
564     gcd[k].gd.flags = gg_enabled | gg_visible;
565     gcd[k++].creator = GLabelCreate;
566 
567     group = k;
568     gcd[k].gd.pos.x = 4; gcd[k].gd.pos.y = 9;
569     gcd[k].gd.pos.width = OPT_Width-8; gcd[k].gd.pos.height = 72;
570     gcd[k].gd.flags = gg_enabled | gg_visible ;
571     gcd[k++].creator = GGroupCreate;
572 
573     gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = 16;
574     gcd[k].gd.flags = gg_visible;
575     label[k].text = (unichar_t *) _("Round");
576     label[k].text_is_1byte = true;
577     gcd[k].gd.popup_msg = _("Do you want to round coordinates to integers (this saves space)?");
578     gcd[k].gd.label = &label[k];
579     gcd[k].gd.cid = CID_PS_Round;
580     gcd[k++].creator = GCheckBoxCreate;
581     hvarray1[0] = &gcd[k-1]; hvarray1[1] = GCD_ColSpan;
582 
583     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
584     gcd[k].gd.flags = gg_visible;
585     label[k].text = (unichar_t *) _("Hints");
586     label[k].text_is_1byte = true;
587     gcd[k].gd.popup_msg = _("Do you want the font file to contain PostScript hints?");
588     gcd[k].gd.label = &label[k];
589     gcd[k].gd.handle_controlevent = OPT_PSHints;
590     gcd[k].gd.cid = CID_PS_Hints;
591     gcd[k++].creator = GCheckBoxCreate;
592     hvarray1[5] = &gcd[k-1]; hvarray1[6] = GCD_ColSpan;
593 
594     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+4; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
595     gcd[k].gd.flags = gg_visible;
596     label[k].text = (unichar_t *) _("Flex Hints");
597     label[k].text_is_1byte = true;
598     gcd[k].gd.popup_msg = _("Do you want the font file to contain PostScript flex hints?");
599     gcd[k].gd.label = &label[k];
600     gcd[k].gd.cid = CID_PS_Flex;
601     gcd[k++].creator = GCheckBoxCreate;
602     hvarray1[10] = GCD_HPad10; hvarray1[11] = &gcd[k-1];
603     hvarray1[15] = GCD_Glue; hvarray1[16] = GCD_Glue;
604 
605     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
606     gcd[k].gd.flags = 0;
607     label[k].text = (unichar_t *) _("Hint Substitution");
608     label[k].text_is_1byte = true;
609     gcd[k].gd.popup_msg = _("Do you want the font file to do hint substitution?");
610     gcd[k].gd.label = &label[k];
611     gcd[k].gd.cid = CID_PS_HintSubs;
612     gcd[k++].creator = GCheckBoxCreate;
613 
614     gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
615     gcd[k].gd.flags = 0;
616     label[k].text = (unichar_t *) _("First 256");
617     label[k].text_is_1byte = true;
618     gcd[k].gd.popup_msg = _("Limit the font so that only the glyphs referenced in the first 256 encodings\nwill be included in the file");
619     gcd[k].gd.label = &label[k];
620     gcd[k].gd.cid = CID_PS_Restrict256;
621     gcd[k++].creator = GCheckBoxCreate;
622 
623     gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
624     gcd[k].gd.flags = gg_visible;
625     label[k].text = (unichar_t *) _("Output AFM");
626     label[k].text_is_1byte = true;
627     gcd[k].gd.popup_msg = U_("The AFM file contains metrics information that many word-processors will read when using a PostScript® font.");
628     gcd[k].gd.label = &label[k];
629     gcd[k].gd.cid = CID_PS_AFM;
630     gcd[k++].creator = GCheckBoxCreate;
631     hvarray1[2] = &gcd[k-1]; hvarray1[3] = GCD_ColSpan; hvarray1[4] = NULL;
632 
633     gcd[k].gd.pos.x = 112; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
634     gcd[k].gd.flags = gg_visible;
635     label[k].text = (unichar_t *) _("Composites in AFM");
636     label[k].text_is_1byte = true;
637     gcd[k].gd.popup_msg = U_("The AFM format allows some information about composites\n(roughly the same as mark to base anchor classes) to be\nincluded. However it tends to make AFM files huge as it\nis not stored in an efficient manner.");
638     gcd[k].gd.label = &label[k];
639     gcd[k].gd.cid = CID_PS_AFMmarks;
640     gcd[k++].creator = GCheckBoxCreate;
641     hvarray1[7] = GCD_HPad10; hvarray1[8] = &gcd[k-1]; hvarray1[9] = NULL;
642 
643     gcd[k].gd.pos.x = gcd[k-2].gd.pos.x; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
644     gcd[k].gd.flags = gg_visible;
645     label[k].text = (unichar_t *) _("Output PFM");
646     label[k].text_is_1byte = true;
647     gcd[k].gd.popup_msg = U_("The PFM file contains information Windows needs to install a PostScript® font.");
648     gcd[k].gd.label = &label[k];
649     gcd[k].gd.cid = CID_PS_PFM;
650     gcd[k++].creator = GCheckBoxCreate;
651     hvarray1[12] = &gcd[k-1]; hvarray1[13] = GCD_ColSpan; hvarray1[14] = NULL;
652 
653     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
654     gcd[k].gd.flags = gg_visible;
655     label[k].text = (unichar_t *) _("Output TFM & ENC");
656     label[k].text_is_1byte = true;
657     gcd[k].gd.popup_msg = U_("The tfm and enc files contain information TeX needs to install a PostScript® font.");
658     gcd[k].gd.label = &label[k];
659     gcd[k].gd.cid = CID_PS_TFM;
660     gcd[k++].creator = GCheckBoxCreate;
661     hvarray1[17] = &gcd[k-1]; hvarray1[18] = GCD_ColSpan; hvarray1[19] = NULL;
662     hvarray1[20] = NULL;
663 
664     boxes[2].gd.flags = gg_enabled|gg_visible;
665     boxes[2].gd.u.boxelements = hvarray1;
666     boxes[2].gd.label = (GTextInfo *) &gcd[1];
667     boxes[2].creator = GHVGroupCreate;
668 
669 
670     label[k].text = (unichar_t *) _("SFNT");
671     label[k].text_is_1byte = true;
672     gcd[k].gd.label = &label[k];
673     gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[group].gd.pos.y+gcd[group].gd.pos.height+6;
674     gcd[k].gd.flags = gg_enabled | gg_visible;
675     gcd[k++].creator = GLabelCreate;
676 
677     group2 = k;
678     gcd[k].gd.pos.x = 4; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+4;
679     gcd[k].gd.pos.width = OPT_Width-8; gcd[k].gd.pos.height = 100;
680     gcd[k].gd.flags = gg_enabled | gg_visible ;
681     gcd[k++].creator = GGroupCreate;
682 
683     gcd[k].gd.pos.x = gcd[group+1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+8;
684     gcd[k].gd.flags = gg_visible;
685     label[k].text = (unichar_t *) _("TrueType Hints");
686     label[k].text_is_1byte = true;
687     gcd[k].gd.popup_msg = _("Do you want the font file to contain truetype hints? This will not\ngenerate new instructions, it will just make use of whatever is associated\nwith each character.");
688     gcd[k].gd.label = &label[k];
689     gcd[k].gd.cid = CID_TTF_Hints;
690     gcd[k++].creator = GCheckBoxCreate;
691     hvarray2[0] = &gcd[k-1]; hvarray2[1] = GCD_ColSpan;
692 
693     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
694     gcd[k].gd.flags = gg_visible;
695     label[k].text = (unichar_t *) _("PS Glyph Names");
696     label[k].text_is_1byte = true;
697     gcd[k].gd.popup_msg = _("Do you want the font file to contain the names of each glyph in the font?");
698     gcd[k].gd.label = &label[k];
699     gcd[k].gd.cid = CID_TTF_FullPS;
700     gcd[k++].creator = GCheckBoxCreate;
701     hvarray2[5] = &gcd[k-1]; hvarray2[6] = GCD_ColSpan;
702 
703     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
704     gcd[k].gd.flags = gg_visible;
705     label[k].text = (unichar_t *) _("Apple");
706     label[k].text_is_1byte = true;
707     gcd[k].gd.popup_msg = _("Apple and MS/Adobe differ about the format of truetype and opentype files\nThis allows you to select which standard to follow for your font.\nThe main differences are:\n The requirements for the 'postscript' name in the name table conflict\n Bitmap data are stored in different tables\n Scaled composite characters are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop");
708     gcd[k].gd.label = &label[k];
709     gcd[k].gd.cid = CID_TTF_AppleMode;
710     gcd[k].gd.handle_controlevent = OPT_Applemode;
711     gcd[k++].creator = GCheckBoxCreate;
712     hvarray2[10] = &gcd[k-1]; hvarray2[11] = GCD_ColSpan;
713 
714     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
715     gcd[k].gd.flags = gg_visible;
716     label[k].text = (unichar_t *) _("OpenType");
717     label[k].text_is_1byte = true;
718     gcd[k].gd.popup_msg = _("Apple and MS/Adobe differ about the format of truetype and opentype files\nThis allows you to select which standard to follow for your font.\nThe main differences are:\n The requirements for the 'postscript' name in the name table conflict\n Bitmap data are stored in different tables\n Scaled composite glyphs are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop");
719     gcd[k].gd.label = &label[k];
720     gcd[k].gd.cid = CID_TTF_OpenTypeMode;
721     gcd[k++].creator = GCheckBoxCreate;
722     hvarray2[15] = &gcd[k-1]; hvarray2[16] = GCD_ColSpan;
723 
724     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+4; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
725     gcd[k].gd.flags = gg_visible;
726     label[k].text = (unichar_t *) _("Old style 'kern'");
727     label[k].text_is_1byte = true;
728     gcd[k].gd.popup_msg = _("Many applications still don't support 'GPOS' kerning.\nIf you want to include both 'GPOS' and old-style 'kern'\ntables set this check box.\nIt may not be set in conjunction with the Apple checkbox.\nThis may confuse other applications though.");
729     gcd[k].gd.label = &label[k];
730     gcd[k].gd.cid = CID_TTF_OldKern;
731     gcd[k].gd.handle_controlevent = OPT_OldKern;
732     gcd[k++].creator = GCheckBoxCreate;
733     hvarray2[20] = GCD_HPad10; hvarray2[21] = &gcd[k-1];
734 
735     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+4; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
736     gcd[k].gd.flags = gg_visible;
737     label[k].text = (unichar_t *) _("Dummy 'DSIG'");
738     label[k].text_is_1byte = true;
739     gcd[k].gd.popup_msg = _(
740 	"MS uses the presence of a 'DSIG' table to determine whether to use an OpenType\n"
741 	"icon for the tt font. FontForge can't generate a useful 'DSIG' table, but it can\n"
742 	"generate an empty one with no signature info. A pointless table.");
743     gcd[k].gd.label = &label[k];
744     gcd[k].gd.cid = CID_TTF_DummyDSIG;
745     gcd[k++].creator = GCheckBoxCreate;
746     hvarray2[25] = GCD_HPad10; hvarray2[26] = &gcd[k-1];
747 
748     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
749     gcd[k].gd.flags = gg_visible;
750     label[k].text = (unichar_t *) _("Output Glyph Map");
751     label[k].text_is_1byte = true;
752     gcd[k].gd.popup_msg = _("When generating a truetype or opentype font it is occasionally\nuseful to know the mapping between truetype glyph ids and\nglyph names. Setting this option will cause FontForge to\nproduce a file (with extension .g2n) containing those data.");
753     gcd[k].gd.label = &label[k];
754     gcd[k].gd.cid = CID_TTF_GlyphMap;
755     gcd[k++].creator = GCheckBoxCreate;
756     hvarray2[30] = &gcd[k-1]; hvarray2[31] = GCD_ColSpan;
757 
758     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
759     gcd[k].gd.flags = gg_visible;
760     label[k].text = (unichar_t *) _("Output OFM & CFG");
761     label[k].text_is_1byte = true;
762     gcd[k].gd.popup_msg = _("The ofm and cfg files contain information Omega needs to process a font.");
763     gcd[k].gd.label = &label[k];
764     gcd[k].gd.cid = CID_TTF_OFM;
765     gcd[k++].creator = GCheckBoxCreate;
766     hvarray2[35] = &gcd[k-1]; hvarray2[36] = GCD_ColSpan;
767 
768     gcd[k].gd.pos.x = gcd[group+6].gd.pos.x; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
769     gcd[k].gd.flags = gg_visible;
770     label[k].text = (unichar_t *) _("PfaEdit Table");
771     label[k].text_is_1byte = true;
772     gcd[k].gd.popup_msg = _("The PfaEdit table is an extension to the TrueType format\nand contains various data used by FontForge\n(It should be called the FontForge table,\nbut isn't for historical reasons)");
773     gcd[k].gd.label = &label[k];
774     gcd[k].gd.cid = CID_TTF_PfEd;
775     gcd[k++].creator = GLabelCreate;
776     hvarray2[2] = &gcd[k-1]; hvarray2[3] = GCD_ColSpan; hvarray2[4] = NULL;
777 
778     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+2; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y-4;
779     gcd[k].gd.flags = gg_visible;
780     label[k].text = (unichar_t *) _("Save Comments");
781     label[k].text_is_1byte = true;
782     gcd[k].gd.popup_msg = _("Save glyph comments in the PfEd table");
783     gcd[k].gd.label = &label[k];
784     gcd[k].gd.cid = CID_TTF_PfEdComments;
785     gcd[k++].creator = GCheckBoxCreate;
786     hvarray2[7] = GCD_HPad10; hvarray2[8] = &gcd[k-1]; hvarray2[9] = NULL;
787 
788     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y-4;
789     gcd[k].gd.flags = gg_visible;
790     label[k].text = (unichar_t *) _("Save Colors");
791     label[k].text_is_1byte = true;
792     gcd[k].gd.popup_msg = _("Save glyph colors in the PfEd table");
793     gcd[k].gd.label = &label[k];
794     gcd[k].gd.cid = CID_TTF_PfEdColors;
795     gcd[k++].creator = GCheckBoxCreate;
796     hvarray2[12] = GCD_HPad10; hvarray2[13] = &gcd[k-1]; hvarray2[14] = NULL;
797 
798     gcd[k].gd.pos.x = gcd[k-3].gd.pos.x; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
799     gcd[k].gd.flags = gg_visible;
800     label[k].text = (unichar_t *) _("Lookup Names");
801     label[k].text_is_1byte = true;
802     gcd[k].gd.popup_msg = _("Preserve the names of the GPOS/GSUB lookups and subtables");
803     gcd[k].gd.label = &label[k];
804     gcd[k].gd.cid = CID_TTF_PfEdLookups;
805     gcd[k++].creator = GCheckBoxCreate;
806     hvarray2[17] = GCD_HPad10; hvarray2[18] = &gcd[k-1]; hvarray2[19] = NULL;
807 
808     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
809     gcd[k].gd.flags = gg_visible;
810     label[k].text = (unichar_t *) _("Save Guides");
811     label[k].text_is_1byte = true;
812     gcd[k].gd.popup_msg = _("Save the guidelines in the Guide layer.");
813     gcd[k].gd.label = &label[k];
814     gcd[k].gd.cid = CID_TTF_PfEdGuides;
815     gcd[k++].creator = GCheckBoxCreate;
816     hvarray2[22] = GCD_HPad10; hvarray2[23] = &gcd[k-1]; hvarray2[24] = NULL;
817 
818     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
819     gcd[k].gd.flags = gg_visible;
820     label[k].text = (unichar_t *) _("Save Layers");
821     label[k].text_is_1byte = true;
822     gcd[k].gd.popup_msg = _(
823 	    "Preserve any background and spiro layers.\n"
824 	    "Also if we output a truetype font from a\n"
825 	    "cubic database, save the cubic splines.");
826     gcd[k].gd.label = &label[k];
827     gcd[k].gd.cid = CID_TTF_PfEdLayers;
828     gcd[k++].creator = GCheckBoxCreate;
829     hvarray2[27] = GCD_HPad10; hvarray2[28] = &gcd[k-1]; hvarray2[29] = NULL;
830 
831     gcd[k].gd.pos.x = gcd[k-3].gd.pos.x; gcd[k].gd.pos.y = gcd[k-5].gd.pos.y;
832     gcd[k].gd.flags = gg_visible;
833     label[k].text = (unichar_t *) _("FFTM Table");
834     label[k].text_is_1byte = true;
835     gcd[k].gd.popup_msg = _("The FFTM table is an extension to the TrueType format\nand contains a series of timestamps defined by FontForge\n");
836     gcd[k].gd.label = &label[k];
837     gcd[k].gd.cid = CID_TTF_FFTMTable;
838     gcd[k++].creator = GCheckBoxCreate;
839     hvarray2[32] = &gcd[k-1]; hvarray2[33] = GCD_ColSpan; hvarray2[34] = NULL;
840 
841     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
842     gcd[k].gd.flags = gg_visible;
843     label[k].text = (unichar_t *) _("TeX Table");
844     label[k].text_is_1byte = true;
845     gcd[k].gd.popup_msg = _("The TeX table is an extension to the TrueType format\nand the various data you would expect to find in\na tfm file (that isn't already stored elsewhere\nin the ttf file)\n");
846     gcd[k].gd.label = &label[k];
847     gcd[k].gd.cid = CID_TTF_TeXTable;
848     gcd[k++].creator = GCheckBoxCreate;
849     hvarray2[37] = &gcd[k-1]; hvarray2[38] = GCD_ColSpan; hvarray2[39] = NULL;
850     hvarray2[40] = GCD_Glue; hvarray2[41] = GCD_Glue; hvarray2[42] = NULL;
851     hvarray2[43] = NULL;
852 
853     boxes[3].gd.flags = gg_enabled|gg_visible;
854     boxes[3].gd.u.boxelements = hvarray2;
855     boxes[3].gd.label = (GTextInfo *) &gcd[group2-1];
856     boxes[3].creator = GHVGroupCreate;
857 
858     fontlog_k = k;
859     gcd[k].gd.flags = gg_visible | gg_enabled;
860     label[k].text = (unichar_t *) _("Output FONTLOG.txt");
861     label[k].text_is_1byte = true;
862     gcd[k].gd.popup_msg = _(
863 	"The FONTLOG is a text file containing relevant information\n"
864 	"about the font including such things as its changelog.\n"
865 	"(A general template is available in the OFL FAQ on http://scripts.sil.org/OFL-FAQ_web)\n"
866 	"Usage within an open font project is highly recommended but not required.\n"
867 	"If your font already contains a fontlog table (see the Element->Font Info)\n"
868 	"and you check this box, then the internal fontlog information will be\n"
869 	"appended to the file \"FONTLOG.txt\" in the same directory\n"
870 	"as the font itself.");
871     gcd[k].gd.label = &label[k];
872     gcd[k].gd.cid = CID_FontLog;
873     gcd[k++].creator = GCheckBoxCreate;
874     hvarray3[0] = &gcd[k-1];
875 
876     gcd[k].gd.pos.y = gcd[k-1].gd.pos.y; gcd[k].gd.pos.x = gcd[k-2].gd.pos.x;
877     gcd[k].gd.flags = gg_visible | gg_enabled;
878     label[k].text = (unichar_t *) _("Prefer native kerning");
879     label[k].text_is_1byte = true;
880     gcd[k].gd.popup_msg = _(
881 	"Use native kerning structures (instead of a feature file) even when this might lose information.\n");
882     gcd[k].gd.label = &label[k];
883     gcd[k].gd.cid = CID_NativeKern;
884     gcd[k++].creator = GCheckBoxCreate;
885     hvarray3[1] = &gcd[k-1]; hvarray3[2]=NULL;
886 
887     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
888     gcd[k].gd.flags = gg_visible | gg_enabled;
889     label[k].text = (unichar_t *) _("Windows-compatible \'kern\'");
890     label[k].text_is_1byte = true;
891     gcd[k].gd.popup_msg = _("If the old-style \'kern\' table contains unencoded glyphs\n(or glyphs encoded outside of the BMP), many Windows applications\nwon't have any kerning at all. This option excludes such\nproblematic glyphs from the old-style \'kern\' table.");
892     gcd[k].gd.label = &label[k];
893     gcd[k].gd.cid = CID_TTF_OldKernMappedOnly;
894     gcd[k++].creator = GCheckBoxCreate;
895     hvarray3[3] = &gcd[k-1]; hvarray3[4] = NULL;
896 
897     gcd[k].gd.pos.x = gcd[k-1].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
898     gcd[k].gd.flags = gg_visible | gg_enabled;
899     label[k].text = (unichar_t *) _("No Mac Names");
900     label[k].text_is_1byte = true;
901     gcd[k].gd.popup_msg = _("Do not add duplicated name entries for legacy Mac platform. These name entries are only needed for some legacy Mac applications.");
902     gcd[k].gd.label = &label[k];
903     gcd[k].gd.cid = CID_TTF_NoMacNames;
904     gcd[k++].creator = GCheckBoxCreate;
905     hvarray3[5] = &gcd[k-1];
906 
907     hvarray3[6] = NULL; hvarray3[7] = NULL;
908 
909     boxes[4].gd.flags = gg_enabled|gg_visible;
910     boxes[4].gd.u.boxelements = hvarray3;
911     boxes[4].gd.label = NULL;
912     boxes[4].creator = GHVGroupCreate;
913 
914     gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = gcd[group2].gd.pos.y+gcd[group2].gd.pos.height+10-3;
915     gcd[k].gd.pos.width = -1;
916     gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
917     label[k].text = (unichar_t *) _("_OK");
918     label[k].text_is_1byte = true;
919     label[k].text_in_resource = true;
920     gcd[k].gd.label = &label[k];
921     gcd[k].gd.cid = CID_OK;
922     gcd[k++].creator = GButtonCreate;
923     harray[0] = GCD_Glue; harray[1] = &gcd[k-1]; harray[2] = GCD_Glue;
924 
925     gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
926     gcd[k].gd.pos.width = -1;
927     gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
928     label[k].text = (unichar_t *) _("_Cancel");
929     label[k].text_is_1byte = true;
930     label[k].text_in_resource = true;
931     gcd[k].gd.label = &label[k];
932     gcd[k++].creator = GButtonCreate;
933     harray[3] = GCD_Glue; harray[4] = &gcd[k-1]; harray[5] = GCD_Glue;
934     harray[6] = NULL;
935 
936     boxes[5].gd.flags = gg_enabled|gg_visible;
937     boxes[5].gd.u.boxelements = harray;
938     boxes[5].creator = GHBoxCreate;
939 
940     varray[0] = &boxes[2]; varray[1] = NULL;
941     varray[2] = &boxes[3]; varray[3] = NULL;
942     varray[4] = &boxes[4]; varray[5] = NULL;
943     varray[6] = GCD_Glue; varray[7] = NULL;
944     varray[8] = &boxes[5]; varray[9] = NULL;
945     varray[10] = NULL;
946 
947     boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
948     boxes[0].gd.flags = gg_enabled|gg_visible;
949     boxes[0].gd.u.boxelements = varray;
950     boxes[0].creator = GHVGroupCreate;
951 
952     GGadgetsCreate(gw,boxes);
953     GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
954     GHVBoxSetExpandableCol(boxes[4].ret,gb_expandgluesame);
955     GHVBoxFitWindow(boxes[0].ret);
956 
957     OptSetDefaults(gw,d,which,iscid);
958 
959     GDrawSetVisible(gw,true);
960     while ( !d->sod_done )
961 	GDrawProcessOneEvent(NULL);
962     GDrawDestroyWindow(gw);
963 }
964 
br_e_h(GWindow gw,GEvent * event)965 static int br_e_h(GWindow gw, GEvent *event) {
966     if ( event->type==et_close ) {
967 	int *done = GDrawGetUserData(gw);
968 	*done = -1;
969     } else if ( event->type == et_char ) {
970 return( false );
971     } else if ( event->type == et_map ) {
972 	/* Above palettes */
973 	GDrawRaise(gw);
974     } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
975 	int *done = GDrawGetUserData(gw);
976 	if ( GGadgetGetCid(event->u.control.g)==1001 )
977 	    *done = true;
978 	else
979 	    *done = -1;
980     } else if ( event->type==et_controlevent && event->u.control.subtype == et_textchanged &&
981 	    GGadgetGetCid(event->u.control.g)==1003 ) {
982 	GGadgetSetChecked(GWidgetGetControl(gw,1004),true);
983     }
984 return( true );
985 }
986 
AskResolution(int bf,BDFFont * bdf)987 static int AskResolution(int bf,BDFFont *bdf) {
988     GRect pos;
989     static GWindow bdf_gw, fon_gw;
990     GWindow gw;
991     GWindowAttrs wattrs;
992     GGadgetCreateData gcd[10], *varray[22], *harray[7], *harray2[4], boxes[4];
993     GTextInfo label[10];
994     int done=-3;
995     int def_res = -1;
996     char buf[20];
997 
998     if ( bdf!=NULL )
999 	def_res = bdf->res;
1000 
1001     if ( no_windowing_ui )
1002 return( -1 );
1003 
1004     gw = bf==bf_bdf ? bdf_gw : fon_gw;
1005     if ( gw==NULL ) {
1006 	memset(&wattrs,0,sizeof(wattrs));
1007 	wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1008 	wattrs.event_masks = ~(1<<et_charup);
1009 	wattrs.restrict_input_to_me = 1;
1010 	wattrs.undercursor = 1;
1011 	wattrs.cursor = ct_pointer;
1012 	wattrs.utf8_window_title = _("BDF Resolution");
1013 	wattrs.is_dlg = true;
1014 	pos.x = pos.y = 0;
1015 	pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
1016 	pos.height = GDrawPointsToPixels(NULL,130);
1017 	gw = GDrawCreateTopWindow(NULL,&pos,br_e_h,&done,&wattrs);
1018 	if ( bf==bf_bdf )
1019 	    bdf_gw = gw;
1020 	else
1021 	    fon_gw = gw;
1022 
1023 	memset(&label,0,sizeof(label));
1024 	memset(&gcd,0,sizeof(gcd));
1025 	memset(&boxes,0,sizeof(boxes));
1026 
1027 	label[0].text = (unichar_t *) _("BDF Resolution");
1028 	label[0].text_is_1byte = true;
1029 	gcd[0].gd.label = &label[0];
1030 	gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 7;
1031 	gcd[0].gd.flags = gg_enabled|gg_visible;
1032 	gcd[0].creator = GLabelCreate;
1033 	harray2[0] = GCD_Glue; harray2[1] = &gcd[0]; harray2[2] = GCD_Glue; harray2[3] = NULL;
1034 
1035 	boxes[3].gd.flags = gg_enabled|gg_visible;
1036 	boxes[3].gd.u.boxelements = harray2;
1037 	boxes[3].creator = GHBoxCreate;
1038 	varray[0] = &boxes[3]; varray[1] = GCD_ColSpan; varray[2] = NULL;
1039 
1040 	label[1].text = (unichar_t *) (bf==bf_bdf ? "75" : "96");
1041 	label[1].text_is_1byte = true;
1042 	gcd[1].gd.label = &label[1];
1043 	gcd[1].gd.mnemonic = (bf==bf_bdf ? '7' : '9');
1044 	gcd[1].gd.pos.x = 20; gcd[1].gd.pos.y = 13+7;
1045 	gcd[1].gd.flags = gg_enabled|gg_visible;
1046 	if ( (bf==bf_bdf ? 75 : 96)==def_res )
1047 	    gcd[1].gd.flags |= gg_cb_on;
1048 	gcd[1].gd.cid = 75;
1049 	gcd[1].creator = GRadioCreate;
1050 	varray[3] = &gcd[1]; varray[4] = GCD_Glue; varray[5] = NULL;
1051 
1052 	label[2].text = (unichar_t *) (bf==bf_bdf ? "100" : "120");
1053 	label[2].text_is_1byte = true;
1054 	gcd[2].gd.label = &label[2];
1055 	gcd[2].gd.mnemonic = '1';
1056 	gcd[2].gd.pos.x = 20; gcd[2].gd.pos.y = gcd[1].gd.pos.y+17;
1057 	gcd[2].gd.flags = gg_enabled|gg_visible;
1058 	if ( (bf==bf_bdf ? 100 : 120)==def_res )
1059 	    gcd[2].gd.flags |= gg_cb_on;
1060 	gcd[2].gd.cid = 100;
1061 	gcd[2].creator = GRadioCreate;
1062 	varray[6] = &gcd[2]; varray[7] = GCD_Glue; varray[8] = NULL;
1063 
1064 	label[3].text = (unichar_t *) _("_Guess");
1065 	label[3].text_is_1byte = true;
1066 	label[3].text_in_resource = true;
1067 	gcd[3].gd.label = &label[3];
1068 	gcd[3].gd.pos.x = 20; gcd[3].gd.pos.y = gcd[2].gd.pos.y+17;
1069 	gcd[3].gd.flags = gg_enabled|gg_visible;
1070 	if ( !((gcd[1].gd.flags|gcd[2].gd.flags)&gg_cb_on) )
1071 	    gcd[3].gd.flags |= gg_cb_on;
1072 	gcd[3].gd.cid = -1;
1073 	gcd[3].gd.popup_msg = _("Guess each font's resolution based on its pixel size");
1074 	gcd[3].creator = GRadioCreate;
1075 	varray[9] = &gcd[3]; varray[10] = GCD_Glue; varray[11] = NULL;
1076 
1077 	label[4].text = (unichar_t *) _("_Other");
1078 	label[4].text_is_1byte = true;
1079 	label[4].text_in_resource = true;
1080 	gcd[4].gd.label = &label[4];
1081 	gcd[4].gd.pos.x = 20; gcd[4].gd.pos.y = gcd[3].gd.pos.y+17;
1082 	gcd[4].gd.flags = gg_enabled|gg_visible;
1083 	gcd[4].gd.cid = 1004;
1084 	gcd[4].creator = GRadioCreate;
1085 
1086 	label[5].text = (unichar_t *) (bf == bf_bdf ? "96" : "72");
1087 	if ( def_res>0 ) {
1088 	    sprintf( buf, "%d", def_res );
1089 	    label[5].text = (unichar_t *) buf;
1090 	}
1091 	label[5].text_is_1byte = true;
1092 	gcd[5].gd.label = &label[5];
1093 	gcd[5].gd.pos.x = 70; gcd[5].gd.pos.y = gcd[4].gd.pos.y-3; gcd[5].gd.pos.width = 40;
1094 	gcd[5].gd.flags = gg_enabled|gg_visible;
1095 	gcd[5].gd.cid = 1003;
1096 	gcd[5].creator = GTextFieldCreate;
1097 	varray[12] = &gcd[4]; varray[13] = &gcd[5]; varray[14] = NULL;
1098 	varray[15] = GCD_Glue; varray[16] = GCD_Glue; varray[17] = NULL;
1099 
1100 	gcd[6].gd.pos.x = 15-3; gcd[6].gd.pos.y = gcd[4].gd.pos.y+24;
1101 	gcd[6].gd.pos.width = -1; gcd[6].gd.pos.height = 0;
1102 	gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_default;
1103 	label[6].text = (unichar_t *) _("_OK");
1104 	label[6].text_is_1byte = true;
1105 	label[6].text_in_resource = true;
1106 	gcd[6].gd.mnemonic = 'O';
1107 	gcd[6].gd.label = &label[6];
1108 	gcd[6].gd.cid = 1001;
1109 	gcd[6].creator = GButtonCreate;
1110 	harray[0] = GCD_Glue; harray[1] = &gcd[6]; harray[2] = GCD_Glue;
1111 
1112 	gcd[7].gd.pos.x = -15; gcd[7].gd.pos.y = gcd[6].gd.pos.y+3;
1113 	gcd[7].gd.pos.width = -1; gcd[7].gd.pos.height = 0;
1114 	gcd[7].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1115 	label[7].text = (unichar_t *) _("_Cancel");
1116 	label[7].text_is_1byte = true;
1117 	label[7].text_in_resource = true;
1118 	gcd[7].gd.label = &label[7];
1119 	gcd[7].gd.mnemonic = 'C';
1120 	/*gcd[7].gd.handle_controlevent = CH_Cancel;*/
1121 	gcd[7].gd.cid = 1002;
1122 	gcd[7].creator = GButtonCreate;
1123 	harray[3] = GCD_Glue; harray[4] = &gcd[7]; harray[5] = GCD_Glue;
1124 	harray[6] = NULL;
1125 
1126 	boxes[2].gd.flags = gg_enabled|gg_visible;
1127 	boxes[2].gd.u.boxelements = harray;
1128 	boxes[2].creator = GHBoxCreate;
1129 	varray[18] = &boxes[2]; varray[19] = GCD_ColSpan; varray[20] = NULL;
1130 	varray[21] = NULL;
1131 
1132 	boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
1133 	boxes[0].gd.flags = gg_enabled|gg_visible;
1134 	boxes[0].gd.u.boxelements = varray;
1135 	boxes[0].creator = GHVGroupCreate;
1136 
1137 	gcd[8].gd.pos.x = 2; gcd[8].gd.pos.y = 2;
1138 	gcd[8].gd.pos.width = pos.width-4; gcd[8].gd.pos.height = pos.height-2;
1139 	gcd[8].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
1140 	gcd[8].creator = GGroupCreate;
1141 
1142 	GGadgetsCreate(gw,boxes);
1143 	GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
1144 	GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
1145     } else
1146 	GDrawSetUserData(gw,&done);
1147 
1148     GWidgetHidePalettes();
1149     GDrawSetVisible(gw,true);
1150     while ( true ) {
1151 	done = 0;
1152 	while ( !done )
1153 	    GDrawProcessOneEvent(NULL);
1154 	if ( GGadgetIsChecked(GWidgetGetControl(gw,1004)) ) {
1155 	    int err = false;
1156 	    int res = GetInt8(gw,1003,_("Other ..."),&err);
1157 	    if ( res<10 )
1158 		GGadgetProtest8( _("_Other"));
1159 	    else if ( !err ) {
1160 		GDrawSetVisible(gw,false);
1161 return( res );
1162 	    }
1163     continue;
1164 	}
1165 	GDrawSetVisible(gw,false);
1166 	if ( done==-1 )
1167 return( -2 );
1168 	if ( GGadgetIsChecked(GWidgetGetControl(gw,75)) )
1169 return( bf == bf_bdf ? 75 : 96 );
1170 	if ( GGadgetIsChecked(GWidgetGetControl(gw,100)) )
1171 return( bf == bf_bdf ? 100 : 120 );
1172 	/*if ( GGadgetIsChecked(GWidgetGetControl(gw,-1)) )*/
1173 return( -1 );
1174     }
1175 }
1176 
SearchDirForWernerFile(char * dir,char * filename)1177 static char *SearchDirForWernerFile(char *dir,char *filename) {
1178     char buffer[1025], buf2[200];
1179     FILE *file;
1180     int good = 0;
1181 
1182     if ( dir==NULL || filename==NULL || \
1183 	 strlen(dir)+strlen(filename)>sizeof(buffer)-2 )
1184 	return( NULL );
1185 
1186     strcpy(buffer,dir);
1187     strcat(buffer,"/");
1188     strcat(buffer,filename);
1189     if ( (file=fopen(buffer,"r"))==NULL )
1190 	return( NULL );
1191     if ( fgets(buf2,sizeof(buf2),file)!=NULL && \
1192 	  strncmp(buf2,pfaeditflag,strlen(pfaeditflag))==0 )
1193 	good = 1;
1194     fclose( file );
1195     if ( good )
1196 	return( copy(buffer) );
1197 
1198     return( NULL );
1199 }
1200 
GFileChooserFilterWernerSFDs(GGadget * g,GDirEntry * ent,const unichar_t * dir)1201 static enum fchooserret GFileChooserFilterWernerSFDs(GGadget *g,GDirEntry *ent,
1202 	const unichar_t *dir) {
1203     enum fchooserret ret = GFileChooserDefFilter(g,ent,dir);
1204     char buf2[200];
1205     FILE *file;
1206 
1207     if ( ret==fc_show && !ent->isdir ) {
1208 	char *filename = malloc(u_strlen(dir)+u_strlen(ent->name)+5);
1209 	cu_strcpy(filename,dir);
1210 	strcat(filename,"/");
1211 	cu_strcat(filename,ent->name);
1212 	file = fopen(filename,"r");
1213 	if ( file==NULL )
1214 	    ret = fc_hide;
1215 	else {
1216 	    if ( fgets(buf2,sizeof(buf2),file)==NULL ||
1217 		    strncmp(buf2,pfaeditflag,strlen(pfaeditflag))==0 )
1218 		ret = fc_hide;
1219 	    fclose(file);
1220 	}
1221 	free(filename);
1222     }
1223 return( ret );
1224 }
1225 
GetWernerSFDFile(SplineFont * sf,EncMap * map)1226 static char *GetWernerSFDFile(SplineFont *sf,EncMap *map) {
1227     char *def=NULL, *ret;
1228     char buffer[100];
1229     int supl = sf->supplement;
1230 
1231     for ( supl = sf->supplement; supl<sf->supplement+10 ; ++supl ) {
1232 	if ( no_windowing_ui ) {
1233 	    if ( sf->subfontcnt!=0 ) {
1234 		sprintf(buffer,"%.40s-%.40s-%d.sfd", sf->cidregistry,sf->ordering,supl);
1235 		def = buffer;
1236 	    } else if ( strstrmatch(map->enc->enc_name,"big")!=NULL &&
1237 		    strchr(map->enc->enc_name,'5')!=NULL ) {
1238 		if (strstrmatch(map->enc->enc_name,"hkscs")!=NULL )
1239 		    def = "Big5HKSCS.sfd";
1240 		else
1241 		    def = "Big5.sfd";
1242 	    } else if ( strstrmatch(map->enc->enc_name,"sjis")!=NULL )
1243 		def = "Sjis.sfd";
1244 	    else if ( strstrmatch(map->enc->enc_name,"Wansung")!=NULL ||
1245 		    strstrmatch(map->enc->enc_name,"EUC-KR")!=NULL )
1246 		def = "Wansung.sfd";
1247 	    else if ( strstrmatch(map->enc->enc_name,"johab")!=NULL )
1248 		def = "Johab.sfd";
1249 	    else if ( map->enc->is_unicodebmp || map->enc->is_unicodefull )
1250 		def = "Unicode.sfd";
1251 	}
1252 	if ( def!=NULL ) {
1253 	    ret = SearchDirForWernerFile(".",def);
1254 	    if ( ret==NULL )
1255 		ret = SearchDirForWernerFile(getFontForgeShareDir(),def);
1256 	    if ( ret!=NULL )
1257 return( ret );
1258 	}
1259 	if ( sf->subfontcnt!=0 )
1260     break;
1261     }
1262 
1263     if ( no_windowing_ui )
1264 return( NULL );
1265 
1266     /*if ( def==NULL )*/
1267 	def = "*.sfd";
1268     ret = gwwv_open_filename(_("Find Sub Font Definition file"),NULL,"*.sfd",GFileChooserFilterWernerSFDs);
1269 return( ret );
1270 }
1271 
AnyRefs(RefChar * refs)1272 static int AnyRefs(RefChar *refs) {
1273     int j;
1274     while ( refs!=NULL ) {
1275 	for ( j=0; j<refs->layer_cnt; ++j )
1276 	    if ( refs->layers[j].splines!=NULL )
1277 return( true );
1278 	refs = refs->next;
1279     }
1280 return( false );
1281 }
1282 
1283 int will_prepend_timestamp = false;
1284 
prepend_timestamp(struct gfc_data * d)1285 static void prepend_timestamp(struct gfc_data *d){
1286 
1287   if (d->sf->familyname_with_timestamp)
1288     free(d->sf->familyname_with_timestamp);
1289   d->sf->familyname_with_timestamp = NULL;
1290 
1291   if (will_prepend_timestamp){
1292     //prepend "YYMMDDHHMM-"
1293 
1294     time_t rawtime;
1295     struct tm * timeinfo;
1296     time(&rawtime);
1297     timeinfo = localtime(&rawtime);
1298     char timestamp[11];
1299     strftime(timestamp, 11, "%y%m%d%H%M", timeinfo);
1300 
1301     char* new_name;
1302     char* original_name = (d->sf->familyname) ? d->sf->familyname : d->sf->fontname;
1303     int i;
1304 
1305     if (original_name!=NULL){
1306     //if we already have a timestamp prepended, we should remove it before appending a new one
1307       int timestamp_found = (original_name[10]=='-');
1308       for (i=0;i<10;i++)
1309         if (original_name[i]<'0' || original_name[i]>'9')
1310           timestamp_found = false;
1311 
1312       if (timestamp_found)
1313         original_name = original_name + 11; //skip previous timestamp
1314 
1315       new_name = malloc (sizeof(char) * (strlen(original_name) + 12));
1316       sprintf(new_name, "%s-%s", timestamp, original_name);
1317 
1318       d->sf->familyname_with_timestamp = new_name;
1319     }
1320   }
1321 }
1322 
DoSave(struct gfc_data * d,unichar_t * path)1323 static void DoSave(struct gfc_data *d,unichar_t *path) {
1324     int err=false;
1325     char *temp;
1326     int32 *sizes=NULL;
1327     int iscid, i;
1328     struct sflist *sfs=NULL, *cur, *last=NULL;
1329     static int psscalewarned=0, ttfscalewarned=0, psfnlenwarned=0;
1330     int flags;
1331     struct sflist *sfl;
1332     char **former;
1333     NameList *rename_to;
1334     GTextInfo *ti = GGadgetGetListItemSelected(d->rename);
1335     char *nlname = u2utf8_copy(ti->text);
1336     extern NameList *force_names_when_saving;
1337     int notdef_pos = SFFindNotdef(d->sf,-1);
1338     int layer = ly_fore;
1339     int likecff;
1340     char *buts[3];
1341 
1342     prepend_timestamp(d);
1343 
1344     buts[0] = _("_Yes");
1345     buts[1] = _("_No");
1346     buts[2] = NULL;
1347 
1348     rename_to = NameListByName(nlname);
1349     free(nlname);
1350     if ( rename_to!=NULL && rename_to->uses_unicode ) {
1351 	/* I'll let someone generate a font with utf8 names, but I won't let */
1352 	/*  them take a font and force it to unicode here. */
1353 	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."));
1354 return;
1355     }
1356 
1357     for ( i=d->sf->glyphcnt-1; i>=1; --i ) if ( i!=notdef_pos )
1358 	if ( d->sf->glyphs[i]!=NULL && strcmp(d->sf->glyphs[i]->name,".notdef")==0 &&
1359 		(d->sf->glyphs[i]->layers[ly_fore].splines!=NULL || AnyRefs(d->sf->glyphs[i]->layers[ly_fore].refs )))
1360     break;
1361     if ( i>0 ) {
1362 	if ( gwwv_ask(_("Notdef name"),(const char **) buts,0,1,_("The glyph at encoding %d is named \".notdef\" but contains an outline. Because it is called \".notdef\" it will not be included in the generated font. You may give it a new name using Element->Glyph Info. Do you wish to continue font generation (and omit this character)?"),d->map->backmap[i])==1 )
1363 return;
1364     }
1365 
1366     if ( d->family==gf_none )
1367 	layer = (intpt) GGadgetGetListItemSelected(GWidgetGetControl(d->gw,CID_Layers))->userdata;
1368 
1369     temp = u2def_copy(path);
1370     oldformatstate = GGadgetGetFirstListSelectedItem(d->pstype);
1371     iscid = oldformatstate==ff_cid || oldformatstate==ff_cffcid ||
1372 	    oldformatstate==ff_otfcid || oldformatstate==ff_otfciddfont;
1373     if ( !iscid && (d->sf->cidmaster!=NULL || d->sf->subfontcnt>1)) {
1374 	if ( gwwv_ask(_("Not a CID format"),(const char **) buts,0,1,_("You are attempting to save a CID font in a non-CID format. This is ok, but it means that only the current sub-font will be saved.\nIs that what you want?"))==1 )
1375 return;
1376     }
1377     if ( oldformatstate == ff_ttf || oldformatstate==ff_ttfsym ||
1378 	    oldformatstate==ff_ttfmacbin || oldformatstate==ff_ttfdfont ) {
1379 	SplineChar *sc; RefChar *ref;
1380 	for ( i=0; i<d->sf->glyphcnt; ++i ) if ( (sc = d->sf->glyphs[i])!=NULL ) {
1381 	    if ( sc->ttf_instrs_len!=0 && sc->instructions_out_of_date ) {
1382 		if ( gwwv_ask(_("Instructions out of date"),(const char **) buts,0,1,_("The truetype instructions on glyph %s are out of date.\nDo you want to proceed anyway?"), sc->name)==1 ) {
1383 		    CharViewCreate(sc,(FontView *) d->sf->fv,-1);
1384 return;
1385 		} else
1386 	break;
1387 	    }
1388 	    for ( ref=sc->layers[ly_fore].refs; ref!=NULL ; ref=ref->next )
1389 		if ( ref->point_match_out_of_date && ref->point_match ) {
1390 		    if ( gwwv_ask(_("Reference point match out of date"),(const char **) buts,0,1,_("In glyph %s the reference to %s is positioned by point matching, and the point numbers may no longer reflect the original intent.\nDo you want to proceed anyway?"), sc->name, ref->sc->name)==1 ) {
1391 			CharViewCreate(sc,(FontView *) d->sf->fv,-1);
1392 return;
1393 		    } else
1394 	goto end_of_loop;
1395 		}
1396 	}
1397 	end_of_loop:;
1398     }
1399 
1400     if ( d->sf->os2_version==1 && (oldformatstate>=ff_otf && oldformatstate<=ff_otfciddfont)) {
1401 	ff_post_error(_("Bad OS/2 version"), _("OpenType fonts must have a version greater than 1\nUse Element->Font Info->OS/2->Misc to change this."));
1402 return;
1403     }
1404 
1405     likecff = 0;
1406     if ( oldformatstate==ff_ttc ) {
1407 	likecff = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TTC_CFF));
1408     }
1409 
1410     if ( likecff || oldformatstate<=ff_cffcid ||
1411 	    (oldformatstate>=ff_otf && oldformatstate<=ff_otfciddfont)) {
1412 	if ( d->sf->ascent+d->sf->descent!=1000 && !psscalewarned ) {
1413 	    if ( gwwv_ask(_("Non-standard Em-Size"),(const char **) buts,0,1,_("The convention is that PostScript fonts should have an Em-Size of 1000. But this font has a size of %d. This is not an error, but you might consider altering the Em-Size with the Element->Font Info->General dialog.\nDo you wish to continue to generate your font in spite of this?"),
1414 		    d->sf->ascent+d->sf->descent)==1 )
1415 return;
1416 	    psscalewarned = true;
1417 	}
1418 	if ( (strlen(d->sf->fontname)>31 || (d->sf->familyname!=NULL && strlen(d->sf->familyname)>31)) && !psfnlenwarned ) {
1419 	    if ( gwwv_ask(_("Bad Font Name"),(const char **) buts,0,1,_("Some versions of Windows will refuse to install postscript fonts if the fontname is longer than 31 characters. Do you want to continue anyway?"))==1 )
1420 return;
1421 	    psfnlenwarned = true;
1422 	}
1423     } else if ( oldformatstate!=ff_none && oldformatstate!=ff_svg &&
1424 	    oldformatstate!=ff_ufo && oldformatstate!=ff_ufo2 && oldformatstate!=ff_ufo3 ) {
1425 	int val = d->sf->ascent+d->sf->descent;
1426 	int bit;
1427 	for ( bit=0x800000; bit!=0; bit>>=1 )
1428 	    if ( bit==val )
1429 	break;
1430 	if ( bit==0 && !ttfscalewarned ) {
1431 	    if ( gwwv_ask(_("Non-standard Em-Size"),(const char **) buts,0,1,_("The convention is that TrueType fonts should have an Em-Size which is a power of 2. But this font has a size of %d. This is not an error, but you might consider altering the Em-Size with the Element->Font Info->General dialog.\nDo you wish to continue to generate your font in spite of this?"),val)==1 )
1432 return;
1433 	    ttfscalewarned = true;
1434 	}
1435     }
1436 
1437     if ( oldformatstate==ff_ttfsym && AlreadyMSSymbolArea(d->sf,d->map))
1438 	/* Don't complain */;
1439     else if ( ((oldformatstate<ff_ptype0 && oldformatstate!=ff_multiple) ||
1440 		oldformatstate==ff_ttfsym || oldformatstate==ff_cff ) &&
1441 		d->map->enc->has_2byte ) {
1442 	char *buts[3];
1443 	buts[0] = _("_Yes");
1444 	buts[1] = _("_Cancel");
1445 	buts[2] = NULL;
1446 	if ( gwwv_ask(_("Encoding Too Large"),(const char **) buts,0,1,_("Your font has a 2 byte encoding, but you are attempting to save it in a format that only supports one byte encodings. This means that you won't be able to access anything after the first 256 characters without reencoding the font.\n\nDo you want to proceed anyway?"))==1 )
1447 return;
1448     }
1449 
1450     oldbitmapstate = GGadgetGetFirstListSelectedItem(d->bmptype);
1451     if ( oldbitmapstate!=bf_none )
1452 	sizes = ParseBitmapSizes(d->bmpsizes,_("Pixel List"),&err);
1453     if ( err )
1454 return;
1455     if ( oldbitmapstate==bf_nfntmacbin && oldformatstate!=ff_pfbmacbin && !nfnt_warned ) {
1456 	nfnt_warned = true;
1457 	ff_post_notice(_("The 'NFNT' bitmap format is obsolete"),_("The 'NFNT' bitmap format is not used under OS/X (though you still need to create a (useless) bitmap font if you are saving a type1 PostScript resource)"));
1458     } else if ( oldformatstate==ff_pfbmacbin &&
1459 	    (oldbitmapstate!=bf_nfntmacbin || sizes[0]==0)) {
1460 	ff_post_error(_("Needs bitmap font"),_("When generating a Mac Type1 resource font, you MUST generate at least one NFNT bitmap font to go with it. If you have not created any bitmaps for this font, cancel this dlg and use the Element->Bitmaps Available command to create one"));
1461 return;
1462     } else if ( oldformatstate==ff_pfbmacbin && !post_warned) {
1463 	post_warned = true;
1464 	ff_post_notice(_("The 'POST' type1 format is probably deprecated"),_("The 'POST' type1 format is probably deprecated and may not work in future version of the mac."));
1465     }
1466 
1467     if ( d->family ) {
1468 	cur = chunkalloc(sizeof(struct sflist));
1469 	cur->next = NULL;
1470 	sfs = last = cur;
1471 	cur->sf = d->sf;
1472 	cur->map = EncMapCopy(d->map);
1473 	cur->sizes = sizes;
1474 	for ( i=0; i<d->familycnt; ++i ) {
1475 	    if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_Family+10*i)) ) {
1476 		cur = chunkalloc(sizeof(struct sflist));
1477 		last->next = cur;
1478 		last = cur;
1479 		cur->sf = GGadgetGetUserData(GWidgetGetControl(d->gw,CID_Family+10*i));
1480 		if ( oldbitmapstate!=bf_none )
1481 		    cur->sizes = ParseBitmapSizes(GWidgetGetControl(d->gw,CID_Family+10*i+1),_("Pixel List"),&err);
1482 		if ( err ) {
1483 		    SfListFree(sfs);
1484 return;
1485 		}
1486 		cur->map = EncMapFromEncoding(cur->sf,d->map->enc);
1487 	    }
1488 	}
1489     } else if ( !d->sf->multilayer && !d->sf->strokedfont && !d->sf->onlybitmaps ) {
1490 	if ( oldformatstate == ff_ptype3 || oldformatstate == ff_none )
1491 	    /* No point in validating type3 fonts */;
1492 	else if ( (old_validate = GGadgetIsChecked(d->validate))) {
1493 	    int vs = SFValidate(d->sf,layer,false);
1494 	    int mask = VSMaskFromFormat(d->sf,layer,oldformatstate);
1495 	    int blues = ValidatePrivate(d->sf)& ~pds_missingblue;
1496 	    if ( (vs&mask) || blues!=0 ) {
1497 		const char *rsb[3];
1498 		char *errs;
1499 		int ret;
1500 
1501 		rsb[0] =  _("_Review");
1502 		rsb[1] =  _("_Generate");
1503 		rsb[2]=NULL;
1504 		errs = VSErrorsFromMask(vs&mask,blues);
1505 		ret = gwwv_ask(_("Errors detected"),rsb,0,0,_("The font contains errors.\n%sWould you like to review the errors or save the font anyway?"),errs);
1506 		free(errs);
1507 		if ( ret==0 ) {
1508 		    d->done = true;
1509 		    d->ret = false;
1510 		    SFValidationWindow(d->sf,layer,oldformatstate);
1511 return;
1512 		}
1513 		/* Ok... they want to proceed */
1514 	    }
1515 	}
1516     }
1517 
1518     switch ( d->sod_which ) {
1519       case 0:	/* PostScript */
1520 	flags = old_ps_flags = d->ps_flags;
1521       break;
1522       case 1:	/* TrueType */
1523 	flags = old_sfnt_flags = d->sfnt_flags;
1524       break;
1525       case 2:	/* OpenType */
1526 	flags = old_sfnt_flags = d->sfnt_flags;
1527       break;
1528       case 3:	/* PostScript & OpenType bitmaps */
1529 	old_ps_flags = d->ps_flags;
1530 	flags = old_psotb_flags = d->psotb_flags;
1531       break;
1532     }
1533 
1534     former = NULL;
1535     if ( d->family && sfs!=NULL ) {
1536 	for ( sfl=sfs; sfl!=NULL; sfl=sfl->next ) {
1537 	    PrepareUnlinkRmOvrlp(sfl->sf,temp,layer);
1538 	    if ( rename_to!=NULL && !iscid )
1539 		sfl->former_names = SFTemporaryRenameGlyphsToNamelist(sfl->sf,rename_to);
1540 	}
1541     } else {
1542 	PrepareUnlinkRmOvrlp(d->sf,temp,layer);
1543 	if ( rename_to!=NULL && !iscid )
1544 	    former = SFTemporaryRenameGlyphsToNamelist(d->sf,rename_to);
1545     }
1546 
1547     if ( d->family==gf_none ) {
1548 	char *wernersfdname = NULL;
1549 	char *old_fontlog_contents;
1550 	int res = -1;
1551 	if ( oldformatstate == ff_multiple )
1552 	    wernersfdname = GetWernerSFDFile(d->sf,d->map);
1553 	if (( oldbitmapstate==bf_bdf || oldbitmapstate==bf_fnt ||
1554 		oldbitmapstate==bf_fon ) && ask_user_for_resolution ) {
1555 	    ff_progress_pause_timer();
1556 	    res = AskResolution(oldbitmapstate,d->sf->bitmaps);
1557 	    ff_progress_resume_timer();
1558 	}
1559 	old_fontlog = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_AppendFontLog));
1560 	old_fontlog_contents = NULL;
1561 	if ( old_fontlog ) {
1562 	    char *new = GGadgetGetTitle8(GWidgetGetControl(d->gw,CID_FontLogBit));
1563 	    if ( new!=NULL && *new!='\0' ) {
1564 		old_fontlog_contents=d->sf->fontlog;
1565 		if ( d->sf->fontlog==NULL )
1566 		    d->sf->fontlog = new;
1567 		else {
1568 		    d->sf->fontlog = strconcat3(d->sf->fontlog,"\n\n",new);
1569 		    free(new);
1570 		}
1571 		d->sf->changed = true;
1572 	    }
1573 	}
1574 	if ( res!=-2 )
1575 	    err = _DoSave(d->sf,temp,sizes,res,d->map, wernersfdname, layer );
1576 	if ( err && old_fontlog ) {
1577 	    free(d->sf->fontlog);
1578 	    d->sf->fontlog = old_fontlog_contents;
1579 	} else
1580 	    free( old_fontlog_contents );
1581 	free(wernersfdname);
1582     } else if ( d->family == gf_macfamily )
1583 	err = !WriteMacFamily(temp,sfs,oldformatstate,oldbitmapstate,flags,layer);
1584     else {
1585 	int ttcflags =
1586 	    (GGadgetIsChecked(GWidgetGetControl(d->gw,CID_MergeTables))?ttc_flag_trymerge:0) |
1587 	    (GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TTC_CFF))?ttc_flag_cff:0);
1588 	err = !WriteTTC(temp,sfs,oldformatstate,oldbitmapstate,flags,layer,ttcflags);
1589     }
1590 
1591     if ( d->family && sfs!=NULL ) {
1592 	for ( sfl=sfs; sfl!=NULL; sfl=sfl->next ) {
1593 	    RestoreUnlinkRmOvrlp(sfl->sf,temp,layer);
1594 	    if ( rename_to!=NULL && !iscid )
1595 		SFTemporaryRestoreGlyphNames(sfl->sf,sfl->former_names);
1596 	}
1597     } else {
1598 	RestoreUnlinkRmOvrlp(d->sf,temp,layer);
1599 	if ( rename_to!=NULL && !iscid )
1600 	    SFTemporaryRestoreGlyphNames(d->sf,former);
1601     }
1602     if ( !iscid )
1603 	force_names_when_saving = rename_to;
1604 
1605     free(temp);
1606     d->done = !err;
1607     d->ret = !err;
1608 }
1609 
GFD_doesnt(GIOControl * gio)1610 static void GFD_doesnt(GIOControl *gio) {
1611     /* The filename the user chose doesn't exist, so everything is happy */
1612     struct gfc_data *d = gio->userdata;
1613     DoSave(d,gio->path);
1614     GFileChooserReplaceIO(d->gfc,NULL);
1615 }
1616 
GFD_exists(GIOControl * gio)1617 static void GFD_exists(GIOControl *gio) {
1618     /* The filename the user chose exists, ask user if s/he wants to overwrite */
1619     struct gfc_data *d = gio->userdata;
1620     char *temp;
1621     const char *rcb[3];
1622 
1623     rcb[2]=NULL;
1624     rcb[0] =  _("_Replace");
1625     rcb[1] =  _("_Cancel");
1626 
1627     if ( gwwv_ask(_("File Exists"),rcb,0,1,_("File, %s, exists. Replace it?"),
1628 	    temp = u2utf8_copy(u_GFileNameTail(gio->path)))==0 ) {
1629 	DoSave(d,gio->path);
1630     }
1631     free(temp);
1632     GFileChooserReplaceIO(d->gfc,NULL);
1633 }
1634 
_GFD_SaveOk(struct gfc_data * d)1635 static void _GFD_SaveOk(struct gfc_data *d) {
1636     GGadget *tf;
1637     unichar_t *ret;
1638     int formatstate = GGadgetGetFirstListSelectedItem(d->pstype);
1639 
1640     GFileChooserGetChildren(d->gfc,NULL,NULL,&tf);
1641     if ( *_GGadgetGetTitle(tf)!='\0' ) {
1642 	ret = GGadgetGetTitle(d->gfc);
1643 	if ( formatstate!=ff_none )	/* are we actually generating an outline font? */
1644 	    GIOfileExists(GFileChooserReplaceIO(d->gfc,
1645 		    GIOCreate(ret,d,GFD_exists,GFD_doesnt)));
1646 	else
1647 	    GFD_doesnt(GIOCreate(ret,d,GFD_exists,GFD_doesnt));	/* No point in bugging the user if we aren't doing anything */
1648 	free(ret);
1649     }
1650 }
1651 
GFD_SaveOk(GGadget * g,GEvent * e)1652 static int GFD_SaveOk(GGadget *g, GEvent *e) {
1653     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1654 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1655 	_GFD_SaveOk(d);
1656     }
1657 return( true );
1658 }
1659 
GFD_Cancel(GGadget * g,GEvent * e)1660 static int GFD_Cancel(GGadget *g, GEvent *e) {
1661     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1662 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1663 	d->done = true;
1664 	d->ret = false;
1665     }
1666 return( true );
1667 }
1668 
GFD_FigureWhich(struct gfc_data * d)1669 static void GFD_FigureWhich(struct gfc_data *d) {
1670     int fs = GGadgetGetFirstListSelectedItem(d->pstype);
1671     int bf = GGadgetGetFirstListSelectedItem(d->bmptype);
1672     int which;
1673     if ( fs==ff_none )
1674 	which = 1;		/* Some bitmaps get stuffed int ttf files */
1675     else if ( fs<=ff_cffcid )
1676 	which = 0;		/* PostScript options */
1677     else if ( fs<=ff_ttfdfont )
1678 	which = 1;		/* truetype options */ /* type42 also */
1679     else
1680 	which = 2;		/* opentype options */
1681     if ( fs==ff_woff || fs==ff_woff2 ) {
1682 	SplineFont *sf = d->sf;
1683 	int layer = d->layer;
1684 	if ( sf->layers[layer].order2 )
1685 	    which = 1;			/* truetype */
1686 	else
1687 	    which = 2;			/* opentype */
1688     }
1689     if ( bf == bf_otb && which==0 )
1690 	which = 3;		/* postscript options with opentype bitmap options */
1691     d->sod_which = which;
1692 }
1693 
GFD_Options(GGadget * g,GEvent * e)1694 static int GFD_Options(GGadget *g, GEvent *e) {
1695     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1696 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1697 	int fs = GGadgetGetFirstListSelectedItem(d->pstype);
1698 	int iscid = fs==ff_cid || fs==ff_cffcid || fs==ff_otfcid ||
1699 		fs==ff_otfciddfont || fs==ff_type42cid;
1700 	GFD_FigureWhich(d);
1701 	SaveOptionsDlg(d,d->sod_which,iscid);
1702     }
1703 return( true );
1704 }
1705 
GFD_dircreated(GIOControl * gio)1706 static void GFD_dircreated(GIOControl *gio) {
1707     struct gfc_data *d = gio->userdata;
1708     unichar_t *dir = u_copy(gio->path);
1709 
1710     GFileChooserReplaceIO(d->gfc,NULL);
1711     GFileChooserSetDir(d->gfc,dir);
1712     free(dir);
1713 }
1714 
GFD_dircreatefailed(GIOControl * gio)1715 static void GFD_dircreatefailed(GIOControl *gio) {
1716     /* We couldn't create the directory */
1717     struct gfc_data *d = gio->userdata;
1718     char *temp;
1719 
1720     ff_post_notice(_("Couldn't create directory"),_("Couldn't create directory: %s"),
1721 		temp = u2utf8_copy(u_GFileNameTail(gio->path)));
1722     free(temp);
1723     GFileChooserReplaceIO(d->gfc,NULL);
1724 }
1725 
GFD_NewDir(GGadget * g,GEvent * e)1726 static int GFD_NewDir(GGadget *g, GEvent *e) {
1727     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1728 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1729 	char *newdir;
1730 	unichar_t *temp;
1731 	newdir = gwwv_ask_string(_("Create directory..."),NULL,_("Directory name?"));
1732 	if ( newdir==NULL )
1733 return( true );
1734 	if ( !GFileIsAbsolute(newdir)) {
1735 	    char *olddir = u2utf8_copy(GFileChooserGetDir(d->gfc));
1736 	    char *temp = GFileAppendFile(olddir,newdir,false);
1737 	    free(newdir); free(olddir);
1738 	    newdir = temp;
1739 	}
1740 	temp = utf82u_copy(newdir);
1741 	GIOmkDir(GFileChooserReplaceIO(d->gfc,
1742 		GIOCreate(temp,d,GFD_dircreated,GFD_dircreatefailed)));
1743 	free(newdir); free(temp);
1744     }
1745 return( true );
1746 }
1747 
BitmapName(struct gfc_data * d)1748 static void BitmapName(struct gfc_data *d) {
1749     int bf = GGadgetGetFirstListSelectedItem(d->bmptype);
1750     int format = GGadgetGetFirstListSelectedItem(d->pstype);
1751 
1752     if ( bf<0 || format<0 || format!=ff_none )
1753 return;
1754 
1755     unichar_t *ret = GGadgetGetTitle(d->gfc);
1756     unichar_t *dup, *pt, *tpt;
1757 
1758     dup = malloc((u_strlen(ret)+30)*sizeof(unichar_t));
1759     u_strcpy(dup,ret);
1760     free(ret);
1761     pt = u_strrchr(dup,'.');
1762     tpt = u_strrchr(dup,'/');
1763     if ( pt<tpt )
1764 	pt = NULL;
1765     if ( pt==NULL ) pt = dup+u_strlen(dup);
1766     if ( uc_strcmp(pt-5, ".bmap.bin" )==0 ) pt -= 5;
1767     if ( uc_strcmp(pt-4, ".ttf.bin" )==0 ) pt -= 4;
1768     if ( uc_strcmp(pt-4, ".otf.dfont" )==0 ) pt -= 4;
1769     if ( uc_strncmp(pt-2, "%s", 2 )==0 ) pt -= 2;
1770     if ( uc_strncmp(pt-2, "-*", 2 )==0 ) pt -= 2;
1771     uc_strcpy(pt,bitmapextensions[bf]);
1772     GGadgetSetTitle(d->gfc,dup);
1773     free(dup);
1774 }
1775 
GFD_Format(GGadget * g,GEvent * e)1776 static int GFD_Format(GGadget *g, GEvent *e) {
1777     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1778 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1779 	unichar_t *pt, *dup, *tpt, *ret;
1780 	int format = GGadgetGetFirstListSelectedItem(d->pstype);
1781 	int32 len; int bf;
1782 	static unichar_t nullstr[] = { 0 };
1783 	GTextInfo **list;
1784 	SplineFont *temp;
1785 
1786 	list = GGadgetGetList(d->bmptype,&len);
1787 	temp = d->sf->cidmaster ? d->sf->cidmaster : d->sf;
1788 	if ( format==ff_none ) {
1789 	    if ( temp->bitmaps!=NULL ) {
1790 		list[bf_sfnt_dfont]->disabled = false;
1791 		list[bf_sfnt_ms]->disabled = false;
1792 		list[bf_otb]->disabled = false;
1793 		list[bf_ttf]->disabled = true;
1794 	    }
1795 	    BitmapName(d);
1796 return( true );
1797 	}
1798 
1799 	ret = GGadgetGetTitle(d->gfc);
1800 	dup = malloc((u_strlen(ret)+30)*sizeof(unichar_t));
1801 	u_strcpy(dup,ret);
1802 	free(ret);
1803 	pt = u_strrchr(dup,'.');
1804 	tpt = u_strrchr(dup,'/');
1805 	if ( pt<tpt )
1806 	    pt = NULL;
1807 	if ( pt==NULL ) pt = dup+u_strlen(dup);
1808 	if ( uc_strcmp(pt-5, ".bmap.bin" )==0 ) pt -= 5;
1809 	if ( uc_strcmp(pt-4, ".ttf.bin" )==0 ) pt -= 4;
1810 	if ( uc_strcmp(pt-4, ".otf.dfont" )==0 ) pt -= 4;
1811 	if ( uc_strcmp(pt-4, ".cid.t42" )==0 ) pt -= 4;
1812 	if ( uc_strncmp(pt-2, "%s", 2 )==0 ) pt -= 2;
1813 	if ( uc_strncmp(pt-2, "-*", 2 )==0 ) pt -= 2;
1814 	uc_strcpy(pt,savefont_extensions[format]);
1815 	GGadgetSetTitle(d->gfc,dup);
1816 	free(dup);
1817 
1818 	if ( d->sf->cidmaster!=NULL ) {
1819 	    if ( format!=ff_none && format != ff_cid && format != ff_cffcid &&
1820 		    format != ff_otfcid && format!=ff_otfciddfont ) {
1821 		GGadgetSetTitle(d->bmpsizes,nullstr);
1822 	    }
1823 	}
1824 
1825 	bf = GGadgetGetFirstListSelectedItem(d->bmptype);
1826 	list[bf_sfnt_dfont]->disabled = true;
1827 	if ( temp->bitmaps==NULL )
1828 	    /* Don't worry about what formats are possible, they're disabled */;
1829 	else if ( format!=ff_ttf && format!=ff_ttfsym && format!=ff_otf &&
1830 		format!=ff_ttfdfont && format!=ff_otfdfont && format!=ff_otfciddfont &&
1831 		format!=ff_otfcid && format!=ff_ttfmacbin && format!=ff_none ) {
1832 	    /* If we're not in a ttf format then we can't output ttf bitmaps */
1833 	    list[bf_ttf]->disabled = true;
1834 	    list[bf_sfnt_dfont]->disabled = false;
1835 	    list[bf_sfnt_ms]->disabled = false;
1836 	    list[bf_otb]->disabled = false;
1837 	    if ( bf==bf_ttf )
1838 		GGadgetSelectOneListItem(d->bmptype,bf_otb);
1839 	    if ( format==ff_pfbmacbin )
1840 		GGadgetSelectOneListItem(d->bmptype,bf_nfntmacbin);
1841 	    bf = GGadgetGetFirstListSelectedItem(d->bmptype);
1842 	    GGadgetSetEnabled(d->bmpsizes, format!=ff_multiple && bf!=bf_none );	/* We know there are bitmaps */
1843 	} else {
1844 	    list[bf_ttf]->disabled = false;
1845 	    list[bf_sfnt_dfont]->disabled = true;
1846 	    list[bf_sfnt_ms]->disabled = true;
1847 	    list[bf_otb]->disabled = true;
1848 	    if ( bf==bf_none )
1849 		/* Do nothing, always appropriate */;
1850 	    else if ( format==ff_ttf || format==ff_ttfsym || format==ff_otf ||
1851 		    format==ff_otfcid ||
1852 		    bf==bf_sfnt_dfont || bf == bf_sfnt_ms || bf == bf_otb )
1853 		GGadgetSelectOneListItem(d->bmptype,bf_ttf);
1854 	}
1855 #if __Mac
1856 	{ GGadget *pulldown, *list, *tf;
1857 	    /* The name of the postscript file is fixed and depends solely on */
1858 	    /*  the font name. If the user tried to change it, the font would */
1859 	    /*  not be found */
1860 	    /* See MakeMacPSName for a full description */
1861 	    GFileChooserGetChildren(d->gfc,&pulldown,&list,&tf);
1862 	    GGadgetSetVisible(tf,format!=ff_pfbmacbin);
1863 	}
1864 #endif
1865 	GGadgetSetEnabled(d->bmptype, format!=ff_multiple );
1866     }
1867 return( true );
1868 }
1869 
GFD_BitmapFormat(GGadget * g,GEvent * e)1870 static int GFD_BitmapFormat(GGadget *g, GEvent *e) {
1871     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1872 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1873 	/*int format = GGadgetGetFirstListSelectedItem(d->pstype);*/
1874 	int bf = GGadgetGetFirstListSelectedItem(d->bmptype);
1875 	int i;
1876 
1877 	GGadgetSetEnabled(d->bmpsizes,bf!=bf_none);
1878 	if ( d->family ) {
1879 	    for ( i=0; i<d->familycnt; ++i )
1880 		GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Family+10*i+1),
1881 			bf!=bf_none);
1882 	}
1883 	BitmapName(d);
1884     }
1885 return( true );
1886 }
1887 
GFD_TogglePrependTimestamp(GGadget * g,GEvent * e)1888 static int GFD_TogglePrependTimestamp(GGadget *g, GEvent *e) {
1889   if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1890     will_prepend_timestamp = GGadgetIsChecked(g);
1891   }
1892   return( true );
1893 }
1894 
GFD_ToggleFontLog(GGadget * g,GEvent * e)1895 static int GFD_ToggleFontLog(GGadget *g, GEvent *e) {
1896     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1897 	struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
1898 	static int cids[] = {
1899 	    CID_FontLogBit,
1900 	    0 };
1901 	int i, visible = GGadgetIsChecked(g);
1902 
1903 	for ( i=0; cids[i]!=0; ++i )
1904 	    GGadgetSetVisible(GWidgetGetControl(d->gw,cids[i]),visible);
1905 
1906 	GWidgetToDesiredSize(d->gw);
1907     }
1908 return( true );
1909 }
1910 
e_h(GWindow gw,GEvent * event)1911 static int e_h(GWindow gw, GEvent *event) {
1912     if ( event->type==et_close ) {
1913 	struct gfc_data *d = GDrawGetUserData(gw);
1914 	d->done = true;
1915 	d->ret = false;
1916     } else if ( event->type == et_char ) {
1917 	if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1918 	    help("ui/dialogs/generate.html", NULL);
1919 return( true );
1920 	} else if ( (event->u.chr.keysym=='s' || event->u.chr.keysym=='g' ||
1921 		event->u.chr.keysym=='G' ) &&
1922 		(event->u.chr.state&ksm_control) ) {
1923 	    _GFD_SaveOk(GDrawGetUserData(gw));
1924 return( true );
1925 	}
1926 return( false );
1927     } else if ( event->type == et_mousemove ||
1928 	    (event->type==et_mousedown && event->u.mouse.button==3 )) {
1929 	struct gfc_data *d = GDrawGetUserData(gw);
1930 	if ( !GGadgetWithin(d->gfc,event->u.mouse.x,event->u.mouse.y))
1931 return( false );
1932 	GFileChooserPopupCheck(d->gfc,event);
1933     } else if (( event->type==et_mouseup || event->type==et_mousedown ) &&
1934 	    (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
1935 	struct gfc_data *d = GDrawGetUserData(gw);
1936 return( GGadgetDispatchEvent((GGadget *) (d->gfc),event));
1937     }
1938 return( true );
1939 }
1940 
BitmapList(SplineFont * sf)1941 static unichar_t *BitmapList(SplineFont *sf) {
1942     BDFFont *bdf;
1943     int i;
1944     char *cret, *pt;
1945     unichar_t *uret;
1946 
1947     for ( bdf=sf->bitmaps, i=0; bdf!=NULL; bdf=bdf->next, ++i );
1948     pt = cret = malloc((i+1)*20);
1949     for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
1950 	if ( pt!=cret ) *pt++ = ',';
1951 	if ( bdf->clut==NULL )
1952 	    sprintf( pt, "%d", bdf->pixelsize );
1953 	else
1954 	    sprintf( pt, "%d@%d", bdf->pixelsize, BDFDepth(bdf) );
1955 	pt += strlen(pt);
1956     }
1957     *pt = '\0';
1958     uret = uc_copy(cret);
1959     free(cret);
1960 return( uret );
1961 }
1962 
styleName(SplineFont * sf)1963 static const char *styleName(SplineFont *sf) {
1964     int stylecode = MacStyleCode(sf,NULL);
1965 
1966     if ( stylecode&sf_bold )
1967         return " Bold";
1968     if ( stylecode&sf_italic )
1969         return " Italic";
1970     if ( stylecode&sf_outline )
1971         return " Outline";
1972     if ( stylecode&sf_shadow )
1973         return " Shadow";
1974     if ( stylecode&sf_condense )
1975         return " Condensed";
1976     if ( stylecode&sf_extend )
1977         return " Extended";
1978     return " Plain";
1979 }
1980 
SFUsableLayerNames(SplineFont * sf,int def_layer)1981 static GTextInfo *SFUsableLayerNames(SplineFont *sf,int def_layer) {
1982     int gid, layer, cnt = 1, k, known;
1983     SplineFont *_sf;
1984     SplineChar *sc;
1985     GTextInfo *ti;
1986 
1987     for ( layer=0; layer<sf->layer_cnt; ++layer )
1988 	sf->layers[layer].ticked = false;
1989     sf->layers[ly_fore].ticked = true;
1990     for ( layer=0; layer<sf->layer_cnt; ++layer ) if ( !sf->layers[layer].background ) {
1991 	known = -1;
1992 	k = 0;
1993 	do {
1994 	    _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
1995 	    for ( gid = 0; gid<_sf->glyphcnt; ++gid ) if ( (sc=_sf->glyphs[gid])!=NULL ) {
1996 		if ( sc->layers[layer].images!=NULL ) {
1997 		    known = 0;
1998 	    break;
1999 		}
2000 		if ( sc->layers[layer].splines!=NULL )
2001 		    known = 1;
2002 	    }
2003 	    ++k;
2004 	} while ( known!=0 && k<sf->subfontcnt );
2005 	if ( known == 1 ) {
2006 	    sf->layers[layer].ticked = true;
2007 	    ++cnt;
2008 	} else if ( layer==def_layer )
2009 	    def_layer = ly_fore;
2010     }
2011 
2012     ti = calloc(cnt+1,sizeof(GTextInfo));
2013     cnt=0;
2014     for ( layer=0; layer<sf->layer_cnt; ++layer ) if ( sf->layers[layer].ticked ) {
2015 	ti[cnt].text = (unichar_t *) sf->layers[layer].name;
2016 	ti[cnt].text_is_1byte = true;
2017 	ti[cnt].selected = layer==def_layer;
2018 	ti[cnt++].userdata = (void *) (intpt) layer;
2019     }
2020 return( ti );
2021 }
2022 
2023 typedef SplineFont *SFArray[48];
2024 
SFGenerateFont(SplineFont * sf,int layer,int family,EncMap * map)2025 int SFGenerateFont(SplineFont *sf,int layer,int family,EncMap *map) {
2026     GRect pos;
2027     GWindow gw;
2028     GWindowAttrs wattrs;
2029     GGadgetCreateData gcd[20+2*48+5+1], *varray[13], *hvarray[33], *famarray[3*52+1],
2030 	    *harray[10], boxes[7];
2031     GTextInfo label[20+2*48+4+1];
2032     struct gfc_data d;
2033     GGadget *pulldown, *files, *tf;
2034     int hvi, i, j, k, f, old, ofs, y, fc, dupfc, dupstyle, rk, vk;
2035     int bs = GIntGetResource(_NUM_Buttonsize), bsbigger, totwid, spacing;
2036     SplineFont *temp;
2037     int familycnt=0;
2038     int fondcnt = 0, fondmax = 10;
2039     SFArray *familysfs=NULL;
2040     uint16 psstyle;
2041     static int done=false;
2042     extern NameList *force_names_when_saving;
2043     char **nlnames;
2044     int cnt, any;
2045     GTextInfo *namelistnames, *lynames=NULL;
2046 
2047     memset(&d,'\0',sizeof(d));
2048     d.sf = sf;
2049     d.layer = layer;
2050 
2051     if ( !done ) {
2052 	done = true;
2053 	for ( i=0; formattypes[i].text; ++i )
2054 	    formattypes[i].text = (unichar_t *) _((char *) formattypes[i].text);
2055 	for ( i=0; bitmaptypes[i].text; ++i )
2056 	    bitmaptypes[i].text = (unichar_t *) _((char *) bitmaptypes[i].text);
2057     }
2058 
2059     if ( family==gf_macfamily ) {
2060 	old_sfnt_flags |=  ttf_flag_applemode;
2061 	old_sfnt_flags &= ~ttf_flag_otmode;
2062     }
2063 
2064     if ( family ) {
2065 	/* I could just disable the menu item, but I think it's a bit confusing*/
2066 	/*  and I want people to know why they can't generate a family */
2067 	FontView *fv;
2068 	SplineFont *dup=NULL/*, *badenc=NULL*/;
2069 	familysfs = malloc((fondmax=10)*sizeof(SFArray));
2070 	memset(familysfs[0],0,sizeof(familysfs[0]));
2071 	familysfs[0][0] = sf;
2072 	fondcnt = 1;
2073 	for ( fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
2074 	    if ( fv->b.sf==sf )
2075 	continue;
2076 	    if ( family==gf_ttc ) {
2077 		fc = fondcnt;
2078 		psstyle = 0;
2079 	    } else if ( family==gf_macfamily && sf->familyname && fv->b.sf->familyname && strcmp(fv->b.sf->familyname,sf->familyname)==0 ) {
2080 		MacStyleCode(fv->b.sf,&psstyle);
2081 		if ( fv->b.sf->fondname==NULL ) {
2082 		    fc = 0;
2083 		    if ( familysfs[0][0]->fondname==NULL &&
2084 			    (familysfs[0][psstyle]==NULL || familysfs[0][psstyle]==fv->b.sf))
2085 			familysfs[0][psstyle] = fv->b.sf;
2086 		    else {
2087 			for ( fc=0; fc<fondcnt; ++fc ) {
2088 			    for ( i=0; i<48; ++i )
2089 				if ( familysfs[fc][i]!=NULL )
2090 			    break;
2091 			    if ( i<48 && familysfs[fc][i]->fondname==NULL &&
2092 				    familysfs[fc][psstyle]==fv->b.sf )
2093 			break;
2094 			}
2095 		    }
2096 		} else {
2097 		    for ( fc=0; fc<fondcnt; ++fc ) {
2098 			for ( i=0; i<48; ++i )
2099 			    if ( familysfs[fc][i]!=NULL )
2100 			break;
2101 			if ( i<48 && familysfs[fc][i]->fondname!=NULL &&
2102 				strcmp(familysfs[fc][i]->fondname,fv->b.sf->fondname)==0 ) {
2103 			    if ( familysfs[fc][psstyle]==fv->b.sf )
2104 				/* several windows may point to same font */;
2105 			    else if ( familysfs[fc][psstyle]!=NULL ) {
2106 				dup = fv->b.sf;
2107 			        dupstyle = psstyle;
2108 			        dupfc = fc;
2109 			    } else
2110 				familysfs[fc][psstyle] = fv->b.sf;
2111 		    break;
2112 			}
2113 		    }
2114 		}
2115 	    }
2116 	    if ( fc==fondcnt ) {
2117 		/* Create a new fond containing just this font */
2118 		if ( fondcnt>=fondmax )
2119 		    familysfs = realloc(familysfs,(fondmax+=10)*sizeof(SFArray));
2120 		memset(familysfs[fondcnt],0,sizeof(SFArray));
2121 		familysfs[fondcnt++][psstyle] = fv->b.sf;
2122 	    }
2123 	}
2124 	if ( family==gf_macfamily ) {
2125 	    for ( fc=0; fc<fondcnt; ++fc ) for ( i=0; i<48; ++i ) {
2126 		if ( familysfs[fc][i]!=NULL ) {
2127 		    ++familycnt;
2128 		}
2129 	    }
2130 	    if ( MacStyleCode(sf,NULL)!=0 || familycnt<=1 || sf->multilayer ) {
2131 		ff_post_error(_("Bad Mac Family"),_("To generate a Mac family file, the current font must have plain (Normal, Regular, etc.) style, and there must be other open fonts with the same family name."));
2132 return( 0 );
2133 	    } else if ( dup ) {
2134 		MacStyleCode(dup,&psstyle);
2135 		ff_post_error(_("Bad Mac Family"),_("There are two open fonts with the current family name and the same style. %.30s and %.30s"),
2136 		    dup->fontname, familysfs[dupfc][dupstyle]->fontname);
2137     return( 0 );
2138 	    }
2139 	} else {
2140 	    familycnt = fondcnt;
2141 	}
2142     }
2143 
2144     memset(&wattrs,0,sizeof(wattrs));
2145     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2146     wattrs.event_masks = ~(1<<et_charup);
2147     wattrs.is_dlg = true;
2148     wattrs.restrict_input_to_me = 1;
2149     wattrs.undercursor = 1;
2150     wattrs.cursor = ct_pointer;
2151     {
2152         const char *label = _("Generate Fonts");
2153         switch (family) {
2154         case gf_ttc:
2155             label = _("Generate TTC");
2156             break;
2157         case gf_macfamily:
2158             label = _("Generate Mac Family");
2159             break;
2160         }
2161         wattrs.utf8_window_title = label;
2162     }
2163     pos.x = pos.y = 0;
2164     totwid = GGadgetScale(295);
2165     bsbigger = 4*bs+4*14>totwid; totwid = bsbigger?4*bs+4*12:totwid;
2166     spacing = (totwid-4*bs-2*12)/3;
2167     pos.width = GDrawPointsToPixels(NULL,totwid);
2168     if ( family )
2169 	pos.height = GDrawPointsToPixels(NULL,310+13+26*(familycnt-1));
2170     else
2171 	pos.height = GDrawPointsToPixels(NULL,310);
2172     gw = GDrawCreateTopWindow(NULL,&pos,e_h,&d,&wattrs);
2173 
2174     memset(&label,0,sizeof(label));
2175     memset(&gcd,0,sizeof(gcd));
2176     memset(&boxes,0,sizeof(boxes));
2177     gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6; gcd[0].gd.pos.width = 100*totwid/GIntGetResource(_NUM_ScaleFactor)-24; gcd[0].gd.pos.height = 182;
2178     gcd[0].gd.flags = gg_visible | gg_enabled;
2179     gcd[0].creator = GFileChooserCreate;
2180     varray[0] = &gcd[0]; varray[1] = NULL;
2181 
2182     y = 276;
2183     if ( family )
2184 	y += 13 + 26*(familycnt-1);
2185 
2186     gcd[1].gd.pos.x = 12; gcd[1].gd.pos.y = y-3;
2187     gcd[1].gd.pos.width = -1;
2188     gcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
2189     label[1].text = (unichar_t *) _("_Generate");
2190     label[1].text_is_1byte = true;
2191     label[1].text_in_resource = true;
2192     gcd[1].gd.mnemonic = 'S';
2193     gcd[1].gd.label = &label[1];
2194     gcd[1].gd.handle_controlevent = GFD_SaveOk;
2195     gcd[1].creator = GButtonCreate;
2196     harray[0] = GCD_Glue; harray[1] = &gcd[1];
2197 
2198     gcd[2].gd.pos.x = -(spacing+bs)*100/GIntGetResource(_NUM_ScaleFactor)-12; gcd[2].gd.pos.y = y;
2199     gcd[2].gd.pos.width = -1;
2200     gcd[2].gd.flags = gg_visible | gg_enabled;
2201     label[2].text = (unichar_t *) _("_Filter");
2202     label[2].text_is_1byte = true;
2203     label[2].text_in_resource = true;
2204     gcd[2].gd.mnemonic = 'F';
2205     gcd[2].gd.label = &label[2];
2206     gcd[2].gd.handle_controlevent = GFileChooserFilterEh;
2207     gcd[2].creator = GButtonCreate;
2208     harray[2] = GCD_Glue; harray[3] = &gcd[2];
2209 
2210     gcd[3].gd.pos.x = -12; gcd[3].gd.pos.y = y; gcd[3].gd.pos.width = -1; gcd[3].gd.pos.height = 0;
2211     gcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
2212     label[3].text = (unichar_t *) _("_Cancel");
2213     label[3].text_is_1byte = true;
2214     label[3].text_in_resource = true;
2215     gcd[3].gd.label = &label[3];
2216     gcd[3].gd.mnemonic = 'C';
2217     gcd[3].gd.handle_controlevent = GFD_Cancel;
2218     gcd[3].creator = GButtonCreate;
2219     harray[6] = GCD_Glue; harray[7] = &gcd[3]; harray[8] = GCD_Glue; harray[9] = NULL;
2220 
2221     gcd[4].gd.pos.x = (spacing+bs)*100/GIntGetResource(_NUM_ScaleFactor)+12; gcd[4].gd.pos.y = y; gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
2222     gcd[4].gd.flags = gg_visible | gg_enabled;
2223     label[4].text = (unichar_t *) S_("Directory|_New");
2224     label[4].text_is_1byte = true;
2225     label[4].text_in_resource = true;
2226     label[4].image = &_GIcon_dir;
2227     label[4].image_precedes = false;
2228     gcd[4].gd.mnemonic = 'N';
2229     gcd[4].gd.label = &label[4];
2230     gcd[4].gd.handle_controlevent = GFD_NewDir;
2231     gcd[4].creator = GButtonCreate;
2232     harray[4] = GCD_Glue; harray[5] = &gcd[4];
2233 
2234     boxes[2].gd.flags = gg_enabled|gg_visible;
2235     boxes[2].gd.u.boxelements = harray;
2236     boxes[2].creator = GHBoxCreate;
2237 
2238     gcd[5].gd.pos.x = 12; gcd[5].gd.pos.y = 218; gcd[5].gd.pos.width = 0; gcd[5].gd.pos.height = 0;
2239     gcd[5].gd.flags = gg_visible | gg_enabled;
2240     label[5].text = (unichar_t *) _("Options");
2241     label[5].text_is_1byte = true;
2242     gcd[5].gd.popup_msg = _("Allows you to select optional behavior when generating the font");
2243     gcd[5].gd.label = &label[5];
2244     gcd[5].gd.handle_controlevent = GFD_Options;
2245     gcd[5].creator = GButtonCreate;
2246     hvarray[4] = &gcd[5]; hvarray[5] = GCD_Glue;
2247 
2248     gcd[6].gd.pos.x = 12; gcd[6].gd.pos.y = 190; gcd[6].gd.pos.width = 0; gcd[6].gd.pos.height = 0;
2249     gcd[6].gd.flags = gg_visible | gg_enabled ;
2250     gcd[6].gd.u.list = formattypes;
2251     gcd[6].creator = GListButtonCreate;
2252     hvarray[0] = &gcd[6]; hvarray[1] = GCD_ColSpan;
2253 
2254     any = false;
2255     for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i])) {
2256 	any = true;
2257     break;
2258     }
2259     for ( i=0; i<sizeof(formattypes)/sizeof(formattypes[0])-1; ++i )
2260 	formattypes[i].disabled = !any;
2261     formattypes[ff_ptype0].disabled = sf->onlybitmaps || map->enc->only_1byte;
2262     formattypes[ff_mma].disabled = formattypes[ff_mmb].disabled =
2263 	     sf->mm==NULL || sf->mm->apple || !MMValid(sf->mm,false);
2264     formattypes[ff_cffcid].disabled = sf->cidmaster==NULL;
2265     formattypes[ff_cid].disabled = sf->cidmaster==NULL;
2266     formattypes[ff_otfcid].disabled = sf->cidmaster==NULL;
2267     formattypes[ff_otfciddfont].disabled = sf->cidmaster==NULL;
2268     if ( map->enc->is_unicodefull )
2269 	formattypes[ff_type42cid].disabled = true;	/* Identity CMap only handles BMP */
2270     ofs = oldformatstate;
2271     if (( ofs==ff_ptype0 && formattypes[ff_ptype0].disabled ) ||
2272 	    ((ofs==ff_mma || ofs==ff_mmb) && sf->mm==NULL) ||
2273 	    ((ofs==ff_cid || ofs==ff_cffcid || ofs==ff_otfcid || ofs==ff_otfciddfont) && formattypes[ff_cid].disabled))
2274 	ofs = ff_pfb;
2275     else if ( (ofs!=ff_cid && ofs!=ff_cffcid && ofs!=ff_otfcid && ofs!=ff_otfciddfont) && sf->cidmaster!=NULL )
2276 	ofs = ff_otfcid;
2277     else if ( !formattypes[ff_mmb].disabled && ofs!=ff_mma )
2278 	ofs = ff_mmb;
2279     if ( ofs==ff_ttc )
2280 	ofs = ff_ttf;
2281     if ( sf->onlybitmaps )
2282 	ofs = ff_none;
2283     if ( sf->multilayer ) {
2284 	formattypes[ff_pfa].disabled = true;
2285 	formattypes[ff_pfb].disabled = true;
2286 	formattypes[ff_pfbmacbin].disabled = true;
2287 	formattypes[ff_mma].disabled = true;
2288 	formattypes[ff_mmb].disabled = true;
2289 	formattypes[ff_multiple].disabled = true;
2290 	formattypes[ff_ptype0].disabled = true;
2291 	formattypes[ff_cff].disabled = true;
2292 	formattypes[ff_cffcid].disabled = true;
2293 	formattypes[ff_cid].disabled = true;
2294 	formattypes[ff_ttf].disabled = true;
2295 	formattypes[ff_type42].disabled = true;
2296 	formattypes[ff_type42cid].disabled = true;
2297 	formattypes[ff_ttfsym].disabled = true;
2298 	formattypes[ff_ttfmacbin].disabled = true;
2299 	formattypes[ff_ttfdfont].disabled = true;
2300 	formattypes[ff_otfdfont].disabled = true;
2301 	formattypes[ff_otf].disabled = true;
2302 	formattypes[ff_otfcid].disabled = true;
2303 	formattypes[ff_cffcid].disabled = true;
2304 	formattypes[ff_ufo].disabled = true;
2305 	formattypes[ff_ufo2].disabled = true;
2306 	formattypes[ff_ufo3].disabled = true;
2307 	if ( ofs!=ff_svg )
2308 	    ofs = ff_ptype3;
2309     } else if ( sf->strokedfont ) {
2310 	formattypes[ff_ttf].disabled = true;
2311 	formattypes[ff_ttfsym].disabled = true;
2312 	formattypes[ff_ttfmacbin].disabled = true;
2313 	formattypes[ff_ttfdfont].disabled = true;
2314 	formattypes[ff_ufo].disabled = true;
2315 	formattypes[ff_ufo2].disabled = true;
2316 	formattypes[ff_ufo3].disabled = true;
2317 	if ( ofs==ff_ttf || ofs==ff_ttfsym || ofs==ff_ttfmacbin || ofs==ff_ttfdfont )
2318 	    ofs = ff_otf;
2319     }
2320     formattypes[ff_ttc].disabled = true;
2321     if ( family == gf_macfamily ) {
2322 	if ( ofs==ff_pfa || ofs==ff_pfb || ofs==ff_multiple || ofs==ff_ptype3 ||
2323 		ofs==ff_ptype0 || ofs==ff_mma || ofs==ff_mmb )
2324 	    ofs = ff_pfbmacbin;
2325 	else if ( ofs==ff_cid || ofs==ff_otfcid || ofs==ff_cffcid )
2326 	    ofs = ff_otfciddfont;
2327 	else if ( ofs==ff_ttf || ofs==ff_ttfsym )
2328 	    ofs = ff_ttfmacbin;
2329 	else if ( ofs==ff_otf || ofs==ff_cff )
2330 	    ofs = ff_otfdfont;
2331 	else if ( ofs==ff_ufo || ofs==ff_ufo2 || ofs==ff_ufo3 || ofs==ff_ttc )
2332 	    ofs = ff_ttfdfont;
2333 	formattypes[ff_pfa].disabled = true;
2334 	formattypes[ff_pfb].disabled = true;
2335 	formattypes[ff_mma].disabled = true;
2336 	formattypes[ff_mmb].disabled = true;
2337 	formattypes[ff_multiple].disabled = true;
2338 	formattypes[ff_ptype3].disabled = true;
2339 	formattypes[ff_ptype0].disabled = true;
2340 	formattypes[ff_type42].disabled = true;
2341 	formattypes[ff_type42cid].disabled = true;
2342 	formattypes[ff_ttf].disabled = true;
2343 	formattypes[ff_ttfsym].disabled = true;
2344 	formattypes[ff_otf].disabled = true;
2345 	formattypes[ff_otfcid].disabled = true;
2346 	formattypes[ff_cff].disabled = true;
2347 	formattypes[ff_cffcid].disabled = true;
2348 	formattypes[ff_svg].disabled = true;
2349 	formattypes[ff_ufo].disabled = true;
2350 	formattypes[ff_ufo2].disabled = true;
2351 	formattypes[ff_ufo3].disabled = true;
2352     } else if ( family == gf_ttc ) {
2353 	for ( i=0; i<=ff_none; ++i )
2354 	    formattypes[i].disabled = true;
2355 	formattypes[ff_ttc].disabled = false;
2356 	ofs = ff_ttc;
2357     }
2358 #ifndef FONTFORGE_CAN_USE_WOFF2
2359 	formattypes[ff_woff2].disabled = true;
2360 #endif
2361 
2362     for ( i=0; i<sizeof(formattypes)/sizeof(formattypes[0]); ++i )
2363 	formattypes[i].selected = false;
2364     formattypes[ofs].selected = true;
2365     gcd[6].gd.handle_controlevent = GFD_Format;
2366     gcd[6].gd.label = &formattypes[ofs];
2367 
2368     gcd[7].gd.pos.x = 2; gcd[7].gd.pos.y = 2;
2369     gcd[7].gd.pos.width = pos.width-4; gcd[7].gd.pos.height = pos.height-4;
2370     gcd[7].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
2371     gcd[7].creator = GGroupCreate;
2372 
2373     gcd[8].gd.pos.x = 155; gcd[8].gd.pos.y = 190; gcd[8].gd.pos.width = 126;
2374     gcd[8].gd.flags = gg_visible | gg_enabled;
2375     gcd[8].gd.u.list = bitmaptypes;
2376     gcd[8].creator = GListButtonCreate;
2377     for ( i=0; i<sizeof(bitmaptypes)/sizeof(bitmaptypes[0]); ++i ) {
2378 	bitmaptypes[i].selected = false;
2379 	bitmaptypes[i].disabled = false;
2380     }
2381     hvarray[2] = &gcd[8]; hvarray[3] = NULL;
2382     old = oldbitmapstate;
2383     if ( family==gf_macfamily ) {
2384 	if ( old==bf_bdf || old==bf_fon || old==bf_fnt || old==bf_sfnt_ms ||
2385 		old==bf_otb || old==bf_palm || old==bf_ptype3 ) {
2386 	    if ( ofs==ff_otfdfont || ofs==ff_otfciddfont || ofs==ff_ttfdfont )
2387 		old = bf_ttf;
2388 	    else
2389 		old = bf_sfnt_dfont;
2390 	} else if ( old==bf_nfntmacbin &&
2391 		    ( ofs==ff_otfdfont || ofs==ff_otfciddfont || ofs==ff_ttfdfont ))
2392 	    old = bf_ttf;
2393 	bitmaptypes[bf_bdf].disabled = true;
2394 	bitmaptypes[bf_fon].disabled = true;
2395 	bitmaptypes[bf_fnt].disabled = true;
2396     } else if ( family==gf_ttc ) {
2397 	for ( i=0; i<bf_none; ++i )
2398 	    bitmaptypes[i].disabled = true;
2399 	bitmaptypes[bf_ttf].disabled = false;
2400 	if ( old!=bf_none )
2401 	    old = bf_ttf;
2402     }
2403     temp = sf->cidmaster ? sf->cidmaster : sf;
2404     if ( temp->bitmaps==NULL ) {
2405 	old = bf_none;
2406 	bitmaptypes[bf_bdf].disabled = true;
2407 	bitmaptypes[bf_ttf].disabled = true;
2408 	bitmaptypes[bf_sfnt_dfont].disabled = true;
2409 	bitmaptypes[bf_sfnt_ms].disabled = true;
2410 	bitmaptypes[bf_otb].disabled = true;
2411 	bitmaptypes[bf_nfntmacbin].disabled = true;
2412 	bitmaptypes[bf_fon].disabled = true;
2413 	bitmaptypes[bf_fnt].disabled = true;
2414 	bitmaptypes[bf_palm].disabled = true;
2415 	bitmaptypes[bf_ptype3].disabled = true;
2416     } else if ( ofs==ff_ttf || ofs==ff_ttfsym || ofs==ff_ttfmacbin ||
2417 	    ofs==ff_ttfdfont || ofs==ff_otf || ofs==ff_otfdfont || ofs==ff_otfcid ||
2418 	    ofs==ff_otfciddfont ) {
2419 	bitmaptypes[bf_ttf].disabled = false;
2420 	bitmaptypes[bf_sfnt_dfont].disabled = true;
2421 	bitmaptypes[bf_sfnt_ms].disabled = true;
2422 	bitmaptypes[bf_otb].disabled = true;
2423     } else {
2424 	bitmaptypes[bf_ttf].disabled = true;
2425 	bitmaptypes[bf_sfnt_dfont].disabled = false;
2426 	bitmaptypes[bf_sfnt_ms].disabled = false;
2427 	bitmaptypes[bf_otb].disabled = false;
2428     }
2429     bitmaptypes[old].selected = true;
2430     gcd[8].gd.label = &bitmaptypes[old];
2431     gcd[8].gd.handle_controlevent = GFD_BitmapFormat;
2432 
2433     gcd[9].gd.pos.x = gcd[8].gd.pos.x; gcd[9].gd.pos.y = 219; gcd[9].gd.pos.width = gcd[8].gd.pos.width;
2434     gcd[9].gd.flags = gg_visible | gg_enabled;
2435     if ( old==bf_none )
2436 	gcd[9].gd.flags &= ~gg_enabled;
2437     gcd[9].creator = GTextFieldCreate;
2438     label[9].text = BitmapList(temp);
2439     gcd[9].gd.label = &label[9];
2440     hvarray[6] = &gcd[9]; hvarray[7] = NULL;
2441 
2442     k = 10;
2443     label[k].text = (unichar_t *) _("Force glyph names to:");
2444     label[k].text_is_1byte = true;
2445     gcd[k].gd.label = &label[k];
2446     gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24+6;
2447     gcd[k].gd.flags = gg_enabled | gg_visible;
2448     gcd[k].gd.popup_msg = _("In the saved font, force all glyph names to match those in the specified namelist");
2449     gcd[k++].creator = GLabelCreate;
2450     hvarray[8] = &gcd[k-1]; hvarray[9] = GCD_ColSpan;
2451 
2452     rk = k;
2453     gcd[k].gd.pos.x = gcd[k-2].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
2454     gcd[k].gd.pos.width = gcd[k-2].gd.pos.width;
2455     gcd[k].gd.flags = gg_visible | gg_enabled;
2456     gcd[k].gd.popup_msg = _("In the saved font, force all glyph names to match those in the specified namelist");
2457     gcd[k].creator = GListButtonCreate;
2458     nlnames = AllNamelistNames();
2459     for ( cnt=0; nlnames[cnt]!=NULL; ++cnt);
2460     namelistnames = calloc(cnt+3,sizeof(GTextInfo));
2461     namelistnames[0].text = (unichar_t *) _("No Rename");
2462     namelistnames[0].text_is_1byte = true;
2463     if ( force_names_when_saving==NULL ) {
2464 	namelistnames[0].selected = true;
2465 	gcd[k].gd.label = &namelistnames[0];
2466     }
2467     namelistnames[1].line = true;
2468     for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
2469 	namelistnames[cnt+2].text = (unichar_t *) nlnames[cnt];
2470 	namelistnames[cnt+2].text_is_1byte = true;
2471 	if ( force_names_when_saving!=NULL &&
2472 		strcmp(_(force_names_when_saving->title),nlnames[cnt])==0 ) {
2473 	    namelistnames[cnt+2].selected = true;
2474 	    gcd[k].gd.label = &namelistnames[cnt+2];
2475 	}
2476     }
2477     gcd[k++].gd.u.list = namelistnames;
2478     free(nlnames);
2479     hvarray[10] = &gcd[k-1]; hvarray[11] = NULL;
2480 
2481     if ( !family ) {
2482 	/* Too annoying to check if all fonts in a family have the same set of*/
2483 	/*  useful layers. So only do this if not family */
2484 	label[k].text = (unichar_t *) _("Layer:");
2485 	label[k].text_is_1byte = true;
2486 	gcd[k].gd.label = &label[k];
2487 	gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24+6;
2488 	gcd[k].gd.flags = gg_enabled | gg_visible;
2489 	gcd[k].gd.popup_msg = _("In the saved font, force all glyph names to match those in the specified namelist");
2490 	gcd[k++].creator = GLabelCreate;
2491 
2492 	gcd[k].gd.pos.x = gcd[k-2].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
2493 	gcd[k].gd.pos.width = gcd[k-2].gd.pos.width;
2494 	gcd[k].gd.flags = gg_visible | gg_enabled;
2495 	gcd[k].gd.popup_msg = _("Save a font based on the specified layer");
2496 	gcd[k].creator = GListButtonCreate;
2497 	gcd[k].gd.cid = CID_Layers;
2498 	gcd[k++].gd.u.list = lynames = SFUsableLayerNames(sf,layer);
2499 	if ( lynames[1].text==NULL ) {
2500 	    gcd[k-2].gd.flags &= ~gg_visible;
2501 	    gcd[k-1].gd.flags &= ~gg_visible;
2502 	}
2503 	hvi=12;
2504 	hvarray[hvi++] = &gcd[k-2]; hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = &gcd[k-1];
2505 	hvarray[hvi++] = NULL;
2506 
2507 	/* Too time consuming to validate lots of fonts, and what UI would I use? */
2508 	/*  so only do this if not family */
2509 	vk = k;
2510 	label[k].text = (unichar_t *) _("Validate Before Saving");
2511 	label[k].text_is_1byte = true;
2512 	gcd[k].gd.label = &label[k];
2513 	gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24+6;
2514 	if ( sf->multilayer || sf->strokedfont || sf->onlybitmaps )
2515 	    gcd[k].gd.flags = gg_visible;
2516 	else if ( old_validate )
2517 	    gcd[k].gd.flags = (gg_enabled | gg_visible | gg_cb_on);
2518 	else
2519 	    gcd[k].gd.flags = (gg_enabled | gg_visible);
2520 	gcd[k].gd.popup_msg = _("Check the glyph outlines for standard errors before saving\nThis can be slow.");
2521 	gcd[k++].creator = GCheckBoxCreate;
2522 	hvarray[hvi++] = &gcd[k-1]; hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = GCD_ColSpan;
2523 	hvarray[hvi++] = NULL;
2524 
2525 	label[k].text = (unichar_t *) _("Append a FONTLOG entry");
2526 	label[k].text_is_1byte = true;
2527 	gcd[k].gd.label = &label[k];
2528 	gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24+6;
2529 	gcd[k].gd.flags = (gg_enabled | gg_visible);
2530 	if ( old_fontlog )
2531 	    gcd[k].gd.flags |= gg_cb_on;
2532 	gcd[k].gd.popup_msg = _("The FONTLOG allows you to keep a log of changes made to your font.");
2533 	gcd[k].gd.cid = CID_AppendFontLog;
2534 	gcd[k].gd.handle_controlevent = GFD_ToggleFontLog;
2535 	gcd[k++].creator = GCheckBoxCreate;
2536 	hvarray[hvi++] = &gcd[k-1]; hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = GCD_ColSpan;
2537 	hvarray[hvi++] = NULL;
2538 
2539 	gcd[k].gd.flags = old_fontlog ? (gg_visible | gg_enabled | gg_textarea_wrap) : (gg_enabled|gg_textarea_wrap);
2540 	gcd[k].gd.cid = CID_FontLogBit;
2541 	gcd[k++].creator = GTextAreaCreate;
2542 	hvarray[hvi++] = &gcd[k-1];
2543 	hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = NULL;
2544 
2545 	label[k].text = (unichar_t *) _("Prepend timestamp");
2546 	label[k].text_is_1byte = true;
2547 	gcd[k].gd.label = &label[k];
2548 	gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24+6;
2549 	gcd[k].gd.flags = (gg_enabled | gg_visible);
2550 	gcd[k].gd.popup_msg = _("This option prepends a timestamp in the format YYMMDDHHMM to the filename and font-family name metadata.");
2551 	gcd[k].gd.cid = CID_PrependTimestamp;
2552 	gcd[k].gd.handle_controlevent = GFD_TogglePrependTimestamp;
2553 	gcd[k++].creator = GCheckBoxCreate; //???
2554 	hvarray[hvi++] = &gcd[k-1]; hvarray[hvi++] = GCD_ColSpan; hvarray[hvi++] = GCD_ColSpan;
2555 	hvarray[hvi++] = NULL; hvarray[hvi++] = NULL;
2556     } else {
2557 	hvarray[12] = NULL;
2558     }
2559 
2560     boxes[3].gd.flags = gg_enabled|gg_visible;
2561     boxes[3].gd.u.boxelements = hvarray;
2562     boxes[3].creator = GHVBoxCreate;
2563     varray[2] = GCD_Glue; varray[3] = NULL;
2564     varray[4] = &boxes[3]; varray[5] = NULL;
2565     varray[6] = GCD_Glue; varray[7] = NULL;
2566     varray[8] = GCD_Glue; varray[9] = NULL;
2567     varray[10] = &boxes[2]; varray[11] = NULL;
2568     varray[12] = NULL;
2569 
2570     if ( family ) {
2571 	y = 276;
2572 
2573 	f = 0;
2574 	gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
2575 	gcd[k].gd.pos.width = totwid-5-5;
2576 	gcd[k].gd.flags = gg_visible | gg_enabled ;
2577 	gcd[k++].creator = GLineCreate;
2578 	famarray[f++] = &gcd[k-1]; famarray[f++] = GCD_ColSpan; famarray[f++] = NULL;
2579 	y += 7;
2580 
2581 	for ( i=0, fc=0, j=1; i<familycnt && j<48 ; ++i ) {
2582 	    while ( fc<fondcnt ) {
2583 		while ( j<48 && familysfs[fc][j]==NULL ) ++j;
2584 		if ( j!=48 )
2585 	    break;
2586 		++fc;
2587 		j=0;
2588 	    }
2589 	    if ( fc==fondcnt )
2590 	break;
2591 	    gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = y;
2592 	    gcd[k].gd.pos.width = gcd[8].gd.pos.x-gcd[k].gd.pos.x-5;
2593 	    gcd[k].gd.flags = gg_visible | gg_enabled | gg_cb_on ;
2594 	    label[k].text = (unichar_t *) (familysfs[fc][j]->fontname);
2595 	    label[k].text_is_1byte = true;
2596 	    gcd[k].gd.label = &label[k];
2597 	    gcd[k].gd.cid = CID_Family+i*10;
2598 	    gcd[k].data = familysfs[fc][j];
2599 	    gcd[k].gd.popup_msg = styleName(familysfs[fc][j]);
2600 	    gcd[k++].creator = GCheckBoxCreate;
2601 	    famarray[f++] = &gcd[k-1];
2602 
2603 	    gcd[k].gd.pos.x = gcd[8].gd.pos.x; gcd[k].gd.pos.y = y; gcd[k].gd.pos.width = gcd[8].gd.pos.width;
2604 	    gcd[k].gd.flags = gg_visible | gg_enabled;
2605 	    if ( old==bf_none )
2606 		gcd[k].gd.flags &= ~gg_enabled;
2607 	    temp = familysfs[fc][j]->cidmaster ? familysfs[fc][j]->cidmaster : familysfs[fc][j];
2608 	    label[k].text = BitmapList(temp);
2609 	    gcd[k].gd.label = &label[k];
2610 	    gcd[k].gd.cid = CID_Family+i*10+1;
2611 	    gcd[k].data = familysfs[fc][j];
2612 	    gcd[k++].creator = GTextFieldCreate;
2613 	    famarray[f++] = &gcd[k-1]; famarray[f++] = NULL;
2614 	    y+=26;
2615 	    ++j;
2616 	}
2617 
2618 	gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
2619 	gcd[k].gd.pos.width = totwid-5-5;
2620 	gcd[k].gd.flags = gg_visible | gg_enabled ;
2621 	gcd[k++].creator = GLineCreate;
2622 	famarray[f++] = &gcd[k-1]; famarray[f++] = GCD_ColSpan; famarray[f++] = NULL;
2623 	if ( family == gf_ttc ) {
2624 	    gcd[k].gd.flags = gg_visible | gg_enabled | gg_cb_on;
2625 	    label[k].text = (unichar_t *) _("Merge tables across fonts");
2626 	    label[k].text_is_1byte = true;
2627 	    gcd[k].gd.label = &label[k];
2628 	    gcd[k].gd.cid = CID_MergeTables;
2629 	    gcd[k].gd.popup_msg = _(
2630 		"FontForge can generate two styles of ttc file.\n"
2631 		"In the first each font is a separate entity\n"
2632 		"with no connection to other fonts. In the second\n"
2633 		"FontForge will attempt to use the same glyph table\n"
2634 		"for all fonts, merging duplicate glyphs. It will\n"
2635 		"also attempt to use the same space for tables in\n"
2636 		"different fonts which are bit by bit the same.\n\n"
2637 		"FontForge isn't always able to perform a merge, in\n"
2638 		"which case it falls back on generating independent\n"
2639 		"fonts within the ttc.\n"
2640 		" FontForge cannot merge if:\n"
2641 		"  * The fonts have different em-sizes\n"
2642 		"  * Bitmaps are involved\n"
2643 		"  * The merged glyf table has more than 65534 glyphs\n\n"
2644 		"(Merging will take longer)" );
2645 	    gcd[k++].creator = GCheckBoxCreate;
2646 	    famarray[f++] = &gcd[k-1]; famarray[f++] = GCD_ColSpan; famarray[f++] = NULL;
2647 
2648 	    gcd[k].gd.flags = gg_visible | gg_enabled;
2649 	    label[k].text = (unichar_t *) _("As CFF fonts");
2650 	    label[k].text_is_1byte = true;
2651 	    gcd[k].gd.label = &label[k];
2652 	    gcd[k].gd.cid = CID_TTC_CFF;
2653 	    gcd[k].gd.popup_msg = _(
2654 		"Put CFF fonts into the ttc rather than TTF.\n These seem to work on the mac and linux\n but are documented not to work on Windows." );
2655 	    gcd[k++].creator = GCheckBoxCreate;
2656 	    famarray[f++] = &gcd[k-1]; famarray[f++] = GCD_ColSpan; famarray[f++] = NULL;
2657 	}
2658 	famarray[f++] = NULL;
2659 
2660 	free(familysfs);
2661 
2662 	boxes[4].gd.flags = gg_enabled|gg_visible;
2663 	boxes[4].gd.u.boxelements = famarray;
2664 	boxes[4].creator = GHVBoxCreate;
2665 	varray[6] = &boxes[4];
2666     }
2667 
2668     boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2669     boxes[0].gd.flags = gg_enabled|gg_visible;
2670     boxes[0].gd.u.boxelements = varray;
2671     boxes[0].creator = GHVGroupCreate;
2672 
2673     GGadgetsCreate(gw,boxes);
2674     GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2675     GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
2676     GHVBoxFitWindow(boxes[0].ret);
2677 
2678     GGadgetSetUserData(gcd[2].ret,gcd[0].ret);
2679     free(namelistnames);
2680     free(lynames);
2681     free(label[9].text);
2682     GFileChooserConnectButtons(gcd[0].ret,gcd[1].ret,gcd[2].ret);
2683     {
2684 	SplineFont *master = sf->cidmaster ? sf->cidmaster : sf;
2685 	char *fn = master->defbasefilename!=NULL ? master->defbasefilename :
2686 		master->fontname;
2687 	unichar_t *temp = malloc(sizeof(unichar_t)*(strlen(fn)+30));
2688 	uc_strcpy(temp,fn);
2689 	if ( ofs==ff_none )
2690 	    uc_strcat(temp,bitmapextensions[old]);
2691 	else
2692 	    uc_strcat(temp,savefont_extensions[ofs]);
2693 	GGadgetSetTitle(gcd[0].ret,temp);
2694 	free(temp);
2695     }
2696     GFileChooserGetChildren(gcd[0].ret,&pulldown,&files,&tf);
2697     GWidgetIndicateFocusGadget(tf);
2698 #if __Mac
2699 	/* The name of the postscript file is fixed and depends solely on */
2700 	/*  the font name. If the user tried to change it, the font would */
2701 	/*  not be found */
2702 	GGadgetSetVisible(tf,ofs!=ff_pfbmacbin);
2703 #endif
2704 
2705     d.sf = sf;
2706     d.map = map;
2707     d.family = family;
2708     d.familycnt = familycnt-1;		/* Don't include the "normal" instance */
2709     d.gfc = gcd[0].ret;
2710     d.pstype = gcd[6].ret;
2711     d.bmptype = gcd[8].ret;
2712     d.bmpsizes = gcd[9].ret;
2713     d.rename = gcd[rk].ret;
2714     d.validate = family ? NULL : gcd[vk].ret;
2715     d.gw = gw;
2716 
2717     d.ps_flags = old_ps_flags;
2718     d.sfnt_flags = old_sfnt_flags;
2719     d.psotb_flags = old_ps_flags | (old_psotb_flags&~ps_flag_mask);
2720 
2721     GFD_FigureWhich(&d);
2722 
2723     GWidgetHidePalettes();
2724     GDrawSetVisible(gw,true);
2725     while ( !d.done )
2726         GDrawProcessOneEvent(NULL);
2727     GDrawDestroyWindow(gw);
2728 return(d.ret);
2729 }
2730