1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <fontforge-config.h>
29 
30 #include "autotrace.h"
31 #include "cvundoes.h"
32 #include "ffglib.h"
33 #include "fontforgeui.h"
34 #include "gfile.h"
35 #include "gkeysym.h"
36 #include "lookups.h"
37 #include "print.h"
38 #include "sftextfieldP.h"
39 #include "splinesaveafm.h"
40 #include "splineutil2.h"
41 #include "tottfgpos.h"
42 #include "ustring.h"
43 #include "utype.h"
44 
45 #include <math.h>
46 #include <sys/types.h>
47 #include <time.h>
48 #include <unistd.h>
49 #if !defined(__MINGW32__)
50 #include <sys/wait.h>
51 #endif
52 
53 typedef struct printffdlg {
54     struct printinfo pi;
55     GWindow gw;
56     GWindow setup;
57     GTimer *sizechanged;
58     GTimer *dpichanged;
59     GTimer *widthchanged;
60     GTimer *resized;
61     GTextInfo *scriptlangs;
62     FontView *fv;
63     CharView *cv;
64     SplineSet *fit_to_path;
65     uint8 script_unknown;
66     uint8 insert_text;
67     uint8 ready;
68     int *done;
69 } PD;
70 
71 static PD *printwindow;
72 
73 static int lastdpi=0;
74 static unichar_t *old_bind_text = NULL;
75 
76 /* ************************************************************************** */
77 /* *********************** Code for Page Setup dialog *********************** */
78 /* ************************************************************************** */
79 
80 #define CID_lp		1001
81 #define CID_lpr		1002
82 #define	CID_ghostview	1003
83 #define CID_File	1004
84 #define CID_Other	1005
85 #define CID_OtherCmd	1006
86 #define	CID_Pagesize	1007
87 #define CID_CopiesLab	1008
88 #define CID_Copies	1009
89 #define CID_PrinterLab	1010
90 #define CID_Printer	1011
91 #define CID_PDFFile	1012
92 
PG_SetEnabled(PD * pi)93 static void PG_SetEnabled(PD *pi) {
94     int enable;
95 
96     enable = GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_lp)) ||
97 	    GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_lpr));
98 
99     GGadgetSetEnabled(GWidgetGetControl(pi->setup,CID_CopiesLab),enable);
100     GGadgetSetEnabled(GWidgetGetControl(pi->setup,CID_Copies),enable);
101     GGadgetSetEnabled(GWidgetGetControl(pi->setup,CID_PrinterLab),enable);
102     GGadgetSetEnabled(GWidgetGetControl(pi->setup,CID_Printer),enable);
103 
104     GGadgetSetEnabled(GWidgetGetControl(pi->setup,CID_OtherCmd),
105 	    GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_Other)));
106 }
107 
PG_OK(GGadget * g,GEvent * e)108 static int PG_OK(GGadget *g, GEvent *e) {
109     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
110 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
111 	const unichar_t *ret;
112 	int err=false;
113 	int copies, pgwidth, pgheight;
114 
115 	copies = GetInt8(pi->setup,CID_Copies,_("_Copies:"),&err);
116 	if ( err )
117 return(true);
118 
119 	if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_Other)) &&
120 		*_GGadgetGetTitle(GWidgetGetControl(pi->setup,CID_OtherCmd))=='\0' ) {
121 	    ff_post_error(_("No Command Specified"),_("No Command Specified"));
122 return(true);
123 	}
124 
125 	ret = _GGadgetGetTitle(GWidgetGetControl(pi->setup,CID_Pagesize));
126 	if ( uc_strstr(ret,"Letter")!=NULL ) {
127 	    pgwidth = 612; pgheight = 792;
128 	} else if ( uc_strstr(ret,"Legal")!=NULL ) {
129 	    pgwidth = 612; pgheight = 1008;
130 	} else if ( uc_strstr(ret,"A4")!=NULL ) {
131 	    pgwidth = 595; pgheight = 842;
132 	} else if ( uc_strstr(ret,"A3")!=NULL ) {
133 	    pgwidth = 842; pgheight = 1191;
134 	} else if ( uc_strstr(ret,"B4")!=NULL ) {
135 	    pgwidth = 708; pgheight = 1000;
136 	} else if ( uc_strstr(ret,"B5")!=NULL ) {
137 	    pgwidth = 516; pgheight = 728;
138 	} else {
139 	    char *cret = cu_copy(ret), *pt;
140 	    float pw,ph, scale;
141 	    if ( sscanf(cret,"%gx%g",&pw,&ph)!=2 ) {
142 		IError("Bad Pagesize must be a known name or <num>x<num><units>\nWhere <units> is one of pt (points), mm, cm, in" );
143 return( true );
144 	    }
145 	    pt = cret+strlen(cret)-1;
146 	    while ( isspace(*pt) ) --pt;
147 	    if ( strncmp(pt-2,"in",2)==0)
148 		scale = 72;
149 	    else if ( strncmp(pt-2,"cm",2)==0 )
150 		scale = 72/2.54;
151 	    else if ( strncmp(pt-2,"mm",2)==0 )
152 		scale = 72/25.4;
153 	    else if ( strncmp(pt-2,"pt",2)==0 )
154 		scale = 1;
155 	    else {
156 		IError("Bad Pagesize units are unknown\nMust be one of pt (points), mm, cm, in" );
157 return( true );
158 	    }
159 	    pgwidth = pw*scale; pgheight = ph*scale;
160 	    free(cret);
161 	}
162 
163 	ret = _GGadgetGetTitle(GWidgetGetControl(pi->setup,CID_Printer));
164 	if ( uc_strcmp(ret,"<default>")==0 || *ret=='\0' )
165 	    ret = NULL;
166 	pi->pi.printer = cu_copy(ret);
167 	pi->pi.pagewidth = pgwidth; pi->pi.pageheight = pgheight;
168 	pi->pi.copies = copies;
169 
170 	if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_lp)))
171 	    pi->pi.printtype = pt_lp;
172 	else if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_lpr)))
173 	    pi->pi.printtype = pt_lpr;
174 	else if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_ghostview)))
175 	    pi->pi.printtype = pt_ghostview;
176 	else if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_PDFFile)))
177 	    pi->pi.printtype = pt_pdf;
178 	else if ( GGadgetIsChecked(GWidgetGetControl(pi->setup,CID_Other))) {
179 	    pi->pi.printtype = pt_other;
180 	    printcommand = cu_copy(_GGadgetGetTitle(GWidgetGetControl(pi->setup,CID_OtherCmd)));
181 	} else
182 	    pi->pi.printtype = pt_file;
183 
184 	printtype = pi->pi.printtype;
185 	free(printlazyprinter); printlazyprinter = copy(pi->pi.printer);
186 	pagewidth = pgwidth; pageheight = pgheight;
187 
188 	pi->pi.done = true;
189 	SavePrefs(true);
190     }
191 return( true );
192 }
193 
PG_Cancel(GGadget * g,GEvent * e)194 static int PG_Cancel(GGadget *g, GEvent *e) {
195     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
196 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
197 	pi->pi.done = true;
198     }
199 return( true );
200 }
201 
PG_RadioSet(GGadget * g,GEvent * e)202 static int PG_RadioSet(GGadget *g, GEvent *e) {
203     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
204 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
205 	PG_SetEnabled(pi);
206     }
207 return( true );
208 }
209 
pg_e_h(GWindow gw,GEvent * event)210 static int pg_e_h(GWindow gw, GEvent *event) {
211     if ( event->type==et_close ) {
212 	PD *pi = GDrawGetUserData(gw);
213 	pi->pi.done = true;
214     } else if ( event->type==et_char ) {
215 	if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
216 	    help("ui/dialogs/display.html", NULL);
217 return( true );
218 	}
219 return( false );
220     }
221 return( true );
222 }
223 
PrinterList()224 static GTextInfo *PrinterList() {
225     char line[400];
226     FILE *printcap;
227     GTextInfo *tis=NULL;
228     int cnt;
229     char *bpt, *cpt;
230 
231     printcap = fopen("/etc/printcap","r");
232     if ( printcap==NULL ) {
233 	tis = calloc(2,sizeof(GTextInfo));
234 	tis[0].text = uc_copy("<default>");
235 return( tis );
236     }
237 
238     while ( 1 ) {
239 	cnt=1;		/* leave room for default printer */
240 	while ( fgets(line,sizeof(line),printcap)!=NULL ) {
241 	    if ( !isspace(*line) && *line!='#' ) {
242 		if ( tis!=NULL ) {
243 		    bpt = strchr(line,'|');
244 		    cpt = strchr(line,':');
245 		    if ( cpt==NULL && bpt==NULL )
246 			cpt = line+strlen(line)-1;
247 		    else if ( cpt!=NULL && bpt!=NULL && bpt<cpt )
248 			cpt = bpt;
249 		    else if ( cpt==NULL )
250 			cpt = bpt;
251 		    tis[cnt].text = uc_copyn(line,cpt-line);
252 		}
253 		++cnt;
254 	    }
255 	}
256 	if ( tis!=NULL ) {
257 	    fclose(printcap);
258 return( tis );
259 	}
260 	tis = calloc((cnt+1),sizeof(GTextInfo));
261 	tis[0].text = uc_copy("<default>");
262 	rewind(printcap);
263     }
264 }
265 
progexists(char * prog)266 static int progexists(char *prog) {
267     char buffer[1025];
268 
269 return( ProgramExists(prog,buffer)!=NULL );
270 }
271 
PageSetup(PD * pi)272 static int PageSetup(PD *pi) {
273     GRect pos;
274     GWindowAttrs wattrs;
275     GGadgetCreateData gcd[17], boxes[5], *radarray[4][5], *txtarray[3][5], *barray[9], *hvarray[5][2];
276     GTextInfo label[17];
277     char buf[10], pb[30];
278     int pt;
279     /* Don't translate these. we compare against the text */
280     static GTextInfo pagesizes[] = {
281 	{ (unichar_t *) "US Letter", NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
282 	{ (unichar_t *) "US Legal", NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
283 	{ (unichar_t *) "A3", NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
284 	{ (unichar_t *) "A4", NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
285 	{ (unichar_t *) "B4", NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
286 	GTEXTINFO_EMPTY
287     };
288 
289     memset(&wattrs,0,sizeof(wattrs));
290     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
291     wattrs.event_masks = ~(1<<et_charup);
292     wattrs.restrict_input_to_me = 1;
293     wattrs.is_dlg = 1;
294     wattrs.undercursor = 1;
295     wattrs.cursor = ct_pointer;
296     wattrs.utf8_window_title = _("Page Setup");
297     pos.x = pos.y = 0;
298     pos.width = GGadgetScale(GDrawPointsToPixels(NULL,250));
299     pos.height = GDrawPointsToPixels(NULL,174);
300     pi->setup = GDrawCreateTopWindow(NULL,&pos,pg_e_h,pi,&wattrs);
301 
302     memset(&label,0,sizeof(label));
303     memset(&gcd,0,sizeof(gcd));
304 
305 /* program names also don't get translated */
306     label[0].text = (unichar_t *) "lp";
307     label[0].text_is_1byte = true;
308     gcd[0].gd.label = &label[0];
309     gcd[0].gd.mnemonic = 'l';
310     gcd[0].gd.pos.x = 40; gcd[0].gd.pos.y = 6;
311     gcd[0].gd.flags = progexists("lp")? (gg_visible | gg_enabled):gg_visible;
312     gcd[0].gd.cid = CID_lp;
313     gcd[0].gd.handle_controlevent = PG_RadioSet;
314     gcd[0].creator = GRadioCreate;
315     radarray[0][0] = GCD_HPad10; radarray[0][1] = &gcd[0];
316 
317     label[1].text = (unichar_t *) "lpr";
318     label[1].text_is_1byte = true;
319     gcd[1].gd.label = &label[1];
320     gcd[1].gd.mnemonic = 'r';
321     gcd[1].gd.pos.x = gcd[0].gd.pos.x; gcd[1].gd.pos.y = 18+gcd[0].gd.pos.y;
322     gcd[1].gd.flags = progexists("lpr")? (gg_visible | gg_enabled):gg_visible;
323     gcd[1].gd.cid = CID_lpr;
324     gcd[1].gd.handle_controlevent = PG_RadioSet;
325     gcd[1].creator = GRadioCreate;
326     radarray[1][0] = GCD_HPad10; radarray[1][1] = &gcd[1];
327 
328     use_gv = false;
329     label[2].text = (unichar_t *) "ghostview";
330     label[2].text_is_1byte = true;
331     gcd[2].gd.label = &label[2];
332     gcd[2].gd.mnemonic = 'g';
333     gcd[2].gd.pos.x = gcd[0].gd.pos.x+50; gcd[2].gd.pos.y = gcd[0].gd.pos.y;
334     gcd[2].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
335     if ( !progexists("ghostview") ) {
336 	if ( progexists("gv") ) {
337 	    label[2].text = (unichar_t *) "gv";
338 	    use_gv = true;
339 	} else
340 	    gcd[2].gd.flags = gg_visible;
341     }
342     gcd[2].gd.cid = CID_ghostview;
343     gcd[2].gd.handle_controlevent = PG_RadioSet;
344     gcd[2].creator = GRadioCreate;
345     radarray[0][2] = &gcd[2]; radarray[0][3] = GCD_ColSpan; radarray[0][4] =NULL;
346 
347     label[3].text = (unichar_t *) _("To _File");
348     label[3].text_is_1byte = true;
349     label[3].text_in_resource = true;
350     gcd[3].gd.label = &label[3];
351     gcd[3].gd.mnemonic = 'F';
352     gcd[3].gd.pos.x = gcd[2].gd.pos.x; gcd[3].gd.pos.y = gcd[1].gd.pos.y;
353     gcd[3].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
354     gcd[3].gd.cid = CID_File;
355     gcd[3].gd.handle_controlevent = PG_RadioSet;
356     gcd[3].creator = GRadioCreate;
357     radarray[1][2] = &gcd[3];
358 
359     label[4].text = (unichar_t *) _("To P_DF File");
360     label[4].text_is_1byte = true;
361     label[4].text_in_resource = true;
362     gcd[4].gd.label = &label[4];
363     gcd[4].gd.mnemonic = 'F';
364     gcd[4].gd.pos.x = gcd[2].gd.pos.x+70; gcd[4].gd.pos.y = gcd[1].gd.pos.y;
365     gcd[4].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
366     gcd[4].gd.cid = CID_PDFFile;
367     gcd[4].gd.handle_controlevent = PG_RadioSet;
368     gcd[4].creator = GRadioCreate;
369     radarray[1][3] = &gcd[4]; radarray[1][4] =NULL;
370 
371     label[5].text = (unichar_t *) _("_Other");
372     label[5].text_is_1byte = true;
373     label[5].text_in_resource = true;
374     gcd[5].gd.label = &label[5];
375     gcd[5].gd.mnemonic = 'O';
376     gcd[5].gd.pos.x = gcd[1].gd.pos.x; gcd[5].gd.pos.y = 22+gcd[1].gd.pos.y;
377     gcd[5].gd.flags = gg_visible | gg_enabled| gg_rad_continueold;
378     gcd[5].gd.cid = CID_Other;
379     gcd[5].gd.handle_controlevent = PG_RadioSet;
380     gcd[5].gd.popup_msg = _("Any other command with all its arguments.\nThe command must expect to deal with a postscript\nfile which it will find by reading its standard input.");
381     gcd[5].creator = GRadioCreate;
382     radarray[2][0] = GCD_HPad10; radarray[2][1] = &gcd[5];
383 
384     if ( (pt=pi->pi.printtype)==pt_unknown ) pt = pt_lp;
385     if ( pt==pt_pdf ) pt = 4;		/* These two are out of order */
386     else if ( pt==pt_other ) pt = 5;
387     if ( !(gcd[pt].gd.flags&gg_enabled) ) pt = pt_file;		/* always enabled */
388     gcd[pt].gd.flags |= gg_cb_on;
389 
390     label[6].text = (unichar_t *) (printcommand?printcommand:"");
391     label[6].text_is_1byte = true;
392     gcd[6].gd.label = &label[6];
393     gcd[6].gd.mnemonic = 'O';
394     gcd[6].gd.pos.x = gcd[2].gd.pos.x; gcd[6].gd.pos.y = gcd[5].gd.pos.y-4;
395     gcd[6].gd.pos.width = 120;
396     gcd[6].gd.flags = gg_visible | gg_enabled;
397     gcd[6].gd.cid = CID_OtherCmd;
398     gcd[6].creator = GTextFieldCreate;
399     radarray[2][2] = &gcd[6]; radarray[2][3] = GCD_ColSpan; radarray[2][4] =NULL;
400     radarray[3][0] = NULL;
401 
402     label[7].text = (unichar_t *) _("Page_Size:");
403     label[7].text_is_1byte = true;
404     label[7].text_in_resource = true;
405     gcd[7].gd.label = &label[7];
406     gcd[7].gd.mnemonic = 'S';
407     gcd[7].gd.pos.x = 5; gcd[7].gd.pos.y = 24+gcd[5].gd.pos.y+6;
408     gcd[7].gd.flags = gg_visible | gg_enabled;
409     gcd[7].creator = GLabelCreate;
410     txtarray[0][0] = &gcd[7];
411 
412     if ( pi->pi.pagewidth==595 && pi->pi.pageheight==792 )
413 	strcpy(pb,"US Letter");		/* Pick a name, this is the default case */
414     else if ( pi->pi.pagewidth==612 && pi->pi.pageheight==792 )
415 	strcpy(pb,"US Letter");
416     else if ( pi->pi.pagewidth==612 && pi->pi.pageheight==1008 )
417 	strcpy(pb,"US Legal");
418     else if ( pi->pi.pagewidth==595 && pi->pi.pageheight==842 )
419 	strcpy(pb,"A4");
420     else if ( pi->pi.pagewidth==842 && pi->pi.pageheight==1191 )
421 	strcpy(pb,"A3");
422     else if ( pi->pi.pagewidth==708 && pi->pi.pageheight==1000 )
423 	strcpy(pb,"B4");
424     else
425 	sprintf(pb,"%dx%d mm", (int) (pi->pi.pagewidth*25.4/72),(int) (pi->pi.pageheight*25.4/72));
426     label[8].text = (unichar_t *) pb;
427     label[8].text_is_1byte = true;
428     gcd[8].gd.label = &label[8];
429     gcd[8].gd.mnemonic = 'S';
430     gcd[8].gd.pos.x = 60; gcd[8].gd.pos.y = gcd[7].gd.pos.y-6;
431     gcd[8].gd.pos.width = 90;
432     gcd[8].gd.flags = gg_visible | gg_enabled;
433     gcd[8].gd.cid = CID_Pagesize;
434     gcd[8].gd.u.list = pagesizes;
435     gcd[8].creator = GListFieldCreate;
436     txtarray[0][1] = &gcd[8];
437 
438 
439     label[9].text = (unichar_t *) _("_Copies:");
440     label[9].text_is_1byte = true;
441     label[9].text_in_resource = true;
442     gcd[9].gd.label = &label[9];
443     gcd[9].gd.mnemonic = 'C';
444     gcd[9].gd.pos.x = 160; gcd[9].gd.pos.y = gcd[7].gd.pos.y;
445     gcd[9].gd.flags = gg_visible | gg_enabled;
446     gcd[9].gd.cid = CID_CopiesLab;
447     gcd[9].creator = GLabelCreate;
448     txtarray[0][2] = &gcd[9];
449 
450     sprintf(buf,"%d",pi->pi.copies);
451     label[10].text = (unichar_t *) buf;
452     label[10].text_is_1byte = true;
453     gcd[10].gd.label = &label[10];
454     gcd[10].gd.mnemonic = 'C';
455     gcd[10].gd.pos.x = 200; gcd[10].gd.pos.y = gcd[8].gd.pos.y;
456     gcd[10].gd.pos.width = 40;
457     gcd[10].gd.flags = gg_visible | gg_enabled;
458     gcd[10].gd.cid = CID_Copies;
459     gcd[10].creator = GTextFieldCreate;
460     txtarray[0][3] = &gcd[10]; txtarray[0][4] = NULL;
461 
462 
463     label[11].text = (unichar_t *) _("_Printer:");
464     label[11].text_is_1byte = true;
465     label[11].text_in_resource = true;
466     gcd[11].gd.label = &label[11];
467     gcd[11].gd.mnemonic = 'P';
468     gcd[11].gd.pos.x = 5; gcd[11].gd.pos.y = 30+gcd[7].gd.pos.y+6;
469     gcd[11].gd.flags = gg_visible | gg_enabled;
470     gcd[11].gd.cid = CID_PrinterLab;
471     gcd[11].creator = GLabelCreate;
472     txtarray[1][0] = &gcd[11];
473 
474     label[12].text = (unichar_t *) pi->pi.printer;
475     label[12].text_is_1byte = true;
476     if ( pi->pi.printer!=NULL )
477 	gcd[12].gd.label = &label[12];
478     gcd[12].gd.mnemonic = 'P';
479     gcd[12].gd.pos.x = 60; gcd[12].gd.pos.y = gcd[11].gd.pos.y-6;
480     gcd[12].gd.pos.width = 90;
481     gcd[12].gd.flags = gg_visible | gg_enabled;
482     gcd[12].gd.cid = CID_Printer;
483     gcd[12].gd.u.list = PrinterList();
484     gcd[12].creator = GListFieldCreate;
485     txtarray[1][1] = &gcd[12];
486     txtarray[1][2] = GCD_ColSpan; txtarray[1][3] = GCD_Glue; txtarray[1][4] = NULL;
487     txtarray[2][0] = NULL;
488 
489 
490     gcd[13].gd.pos.x = 30-3; gcd[13].gd.pos.y = gcd[12].gd.pos.y+36;
491     gcd[13].gd.pos.width = -1; gcd[13].gd.pos.height = 0;
492     gcd[13].gd.flags = gg_visible | gg_enabled | gg_but_default;
493     label[13].text = (unichar_t *) _("_OK");
494     label[13].text_is_1byte = true;
495     label[13].text_in_resource = true;
496     gcd[13].gd.mnemonic = 'O';
497     gcd[13].gd.label = &label[13];
498     gcd[13].gd.handle_controlevent = PG_OK;
499     gcd[13].creator = GButtonCreate;
500 
501     gcd[14].gd.pos.x = -30; gcd[14].gd.pos.y = gcd[13].gd.pos.y+3;
502     gcd[14].gd.pos.width = -1; gcd[14].gd.pos.height = 0;
503     gcd[14].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
504     label[14].text = (unichar_t *) _("_Cancel");
505     label[14].text_is_1byte = true;
506     label[14].text_in_resource = true;
507     gcd[14].gd.label = &label[14];
508     gcd[14].gd.mnemonic = 'C';
509     gcd[14].gd.handle_controlevent = PG_Cancel;
510     gcd[14].creator = GButtonCreate;
511 
512     barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
513     barray[1] = &gcd[13]; barray[5] = &gcd[14];
514 
515     memset(boxes,0,sizeof(boxes));
516 
517     boxes[2].gd.flags = gg_enabled|gg_visible;
518     boxes[2].gd.u.boxelements = radarray[0];
519     boxes[2].creator = GHVBoxCreate;
520 
521     boxes[3].gd.flags = gg_enabled|gg_visible;
522     boxes[3].gd.u.boxelements = txtarray[0];
523     boxes[3].creator = GHVBoxCreate;
524 
525     boxes[4].gd.flags = gg_enabled|gg_visible;
526     boxes[4].gd.u.boxelements = barray;
527     boxes[4].creator = GHBoxCreate;
528 
529     hvarray[0][0] = &boxes[2]; hvarray[0][1] = NULL;
530     hvarray[1][0] = &boxes[3]; hvarray[1][1] = NULL;
531     hvarray[2][0] = GCD_Glue; hvarray[2][1] = NULL;
532     hvarray[3][0] = &boxes[4]; hvarray[3][1] = NULL;
533     hvarray[4][0] = NULL;
534     boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
535     boxes[0].gd.flags = gg_enabled|gg_visible;
536     boxes[0].gd.u.boxelements = hvarray[0];
537     boxes[0].creator = GHVGroupCreate;
538 
539     GGadgetsCreate(pi->setup,boxes);
540     GHVBoxSetExpandableCol(boxes[4].ret,gb_expandgluesame);
541     GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
542     GTextInfoListFree(gcd[12].gd.u.list);
543     PG_SetEnabled(pi);
544     GHVBoxFitWindow(boxes[0].ret);
545     GDrawSetVisible(pi->setup,true);
546     while ( !pi->pi.done )
547 	GDrawProcessOneEvent(NULL);
548     GDrawDestroyWindow(pi->setup);
549     pi->pi.done = false;
550 return( pi->pi.printtype!=pt_unknown );
551 }
552 
553 /* ************************************************************************** */
554 /* ************************* Code for Print dialog ************************** */
555 /* ************************************************************************** */
556 
557 /* Slightly different from one in fontview */
FVSelCount(FontView * fv)558 static int FVSelCount(FontView *fv) {
559     int i, cnt=0, gid;
560     for ( i=0; i<fv->b.map->enccount; ++i )
561 	if ( fv->b.selected[i] && (gid=fv->b.map->map[i])!=-1 &&
562 		SCWorthOutputting(fv->b.sf->glyphs[gid]))
563 	    ++cnt;
564 return( cnt);
565 }
566 
567     /* CIDs for Print */
568 #define CID_TabSet	1000
569 #define CID_Display	1001
570 #define CID_Chars	1002
571 #define	CID_MultiSize	1003
572 #define CID_PSLab	1005
573 #define	CID_PointSize	1006
574 #define CID_OK		1009
575 #define CID_Cancel	1010
576 #define CID_Setup	1010
577 
578     /* CIDs for display */
579 #define CID_Font	2001
580 #define CID_AA		2002
581 #define CID_SizeLab	2003
582 #define CID_Size	2004
583 #define CID_pfb		2005
584 #define CID_ttf		2006
585 #define CID_otf		2007
586 #define CID_nohints	2008
587 #define CID_bitmap	2009
588 #define CID_pfaedit	2010
589 #define CID_SampleText	2011
590 #define CID_ScriptLang	2022
591 #define CID_Features	2023
592 #define CID_DPI		2024
593 #define CID_TopBox	2025
594 
595     /* CIDs for Insert Text */
596 #define CID_Bind	3001
597 #define CID_Scale	3002
598 #define CID_Start	3003
599 #define CID_Center	3004
600 #define CID_End		3005
601 #define CID_TextWidth	3006
602 #define CID_YOffset	3007
603 #define CID_GlyphAsUnit	3008
604 #define CID_ActualWidth	3009
605 
PRT_SetEnabled(PD * pi)606 static void PRT_SetEnabled(PD *pi) {
607     int enable_ps;
608 
609     enable_ps = !GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Chars));
610 
611     GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_PSLab),enable_ps);
612     GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_PointSize),enable_ps);
613 }
614 
PRT_OK(GGadget * g,GEvent * e)615 static int PRT_OK(GGadget *g, GEvent *e) {
616     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
617 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
618 	int err = false;
619 	int di = pi->pi.fv!=NULL?0:pi->pi.mv!=NULL?2:1;
620 	char *ret;
621 	char *file;
622 	char buf[100];
623 
624 	if ( pi->insert_text ) {
625 	    SplineSet *ss, *end;
626 	    int bound = GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Bind));
627 	    int scale = GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Scale));
628 	    int gunit = GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_GlyphAsUnit));
629 	    int align = GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Start ))? 0 :
630 			GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Center))? 1 : 2;
631 	    int width = GetInt8(pi->gw,CID_TextWidth,_("Width"),&err);
632 	    real offset = GetReal8(pi->gw,CID_YOffset,_("Offset"),&err);
633 	    CharView *cv = pi->cv;
634 	    LayoutInfo *sample;
635 	    /* int dpi  =*/ GetInt8(pi->gw,CID_DPI,_("DPI"),&err);
636 	    /* int size =*/ GetInt8(pi->gw,CID_Size,_("Size"),&err);
637 	    if ( err )
638 return(true);
639 	    free(old_bind_text);
640 	    old_bind_text = GGadgetGetTitle(GWidgetGetControl(pi->gw,CID_SampleText));
641 	    sample = LIConvertToPrint(
642 			&((SFTextArea *) GWidgetGetControl(pi->gw,CID_SampleText))->li,
643 			width, 50000, 72 );
644 	    ss = LIConvertToSplines(sample, 72,cv->b.layerheads[cv->b.drawmode]->order2);
645 	    LayoutInfo_Destroy(sample);
646 	    free(sample);
647 	    if ( bound && pi->fit_to_path )
648 		SplineSetBindToPath(ss,scale,gunit,align,offset,pi->fit_to_path);
649 	    if ( ss ) {
650 		SplineSet *test;
651 		CVPreserveState((CharViewBase *) cv);
652 		end = NULL;
653 		for ( test=ss; test!=NULL; test=test->next ) {
654 		    SplinePoint *sp;
655 		    end = test;
656 		    for ( sp=test->first; ; ) {
657 			sp->selected = true;
658 			if ( sp->next==NULL )
659 		    break;
660 			sp = sp->next->to;
661 			if ( sp==test->first )
662 		    break;
663 		    }
664 		}
665 		end->next = cv->b.layerheads[cv->b.drawmode]->splines;
666 		cv->b.layerheads[cv->b.drawmode]->splines = ss;
667 		CVCharChangedUpdate((CharViewBase *) cv);
668 	    }
669 	} else {
670 	    pi->pi.pt = GTabSetGetSel(GWidgetGetControl(pi->gw,CID_TabSet))==0 ? pt_fontsample :
671 		       GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_Chars))? pt_chars:
672 		       GGadgetIsChecked(GWidgetGetControl(pi->gw,CID_MultiSize))? pt_multisize:
673 		       pt_fontdisplay;
674 	    if ( pi->pi.pt==pt_fontdisplay ) {
675 		pi->pi.pointsize = GetInt8(pi->gw,CID_PointSize,_("_Pointsize:"),&err);
676 		if ( err )
677 return(true);
678 		if ( pi->pi.pointsize<1 || pi->pi.pointsize>200 ) {
679 		    ff_post_error(_("Invalid point size"),_("Invalid point size"));
680 return(true);
681 		}
682 	    }
683 	    if ( pi->pi.printtype==pt_unknown )
684 		if ( !PageSetup(pi))
685 return(true);
686 
687 	    if ( pi->pi.printtype==pt_file || pi->pi.printtype==pt_pdf ) {
688 		sprintf(buf,"pr-%.90s.%s", pi->pi.mainsf->fontname,
689 			pi->pi.printtype==pt_file?"ps":"pdf");
690 		ret = gwwv_save_filename(_("Print To File..."),buf,
691 			pi->pi.printtype==pt_pdf?"*.pdf":"*.ps");
692 		if ( ret==NULL )
693 return(true);
694 		file = utf82def_copy(ret);
695 		free(ret);
696 		pi->pi.out = fopen(file,"wb");
697 		if ( pi->pi.out==NULL ) {
698 		    ff_post_error(_("Print Failed"),_("Failed to open file %s for output"), file);
699 		    free(file);
700 return(true);
701 		}
702 	    } else {
703 		file = NULL;
704 		pi->pi.out = GFileTmpfile();
705 		if ( pi->pi.out==NULL ) {
706 		    ff_post_error(_("Failed to open temporary output file"),_("Failed to open temporary output file"));
707 return(true);
708 		}
709 	    }
710 
711 	    pdefs[di].last_cs = pi->pi.mainmap->enc;
712 	    pdefs[di].pt = pi->pi.pt;
713 	    pdefs[di].pointsize = pi->pi.pointsize;
714 
715 	    if ( pi->pi.pt==pt_fontsample ) {
716 		pi->pi.sample = LIConvertToPrint(
717 			&((SFTextArea *) GWidgetGetControl(pi->gw,CID_SampleText))->li,
718 			(pagewidth-1*72)*printdpi/72,
719 			(pageheight-1*72)*printdpi/72,
720 			printdpi);
721 	    }
722 
723 	    DoPrinting(&pi->pi,file);
724 	    free(file);
725 	    if ( pi->pi.pt==pt_fontsample ) {
726 		LayoutInfo_Destroy(pi->pi.sample);
727 		free(pi->pi.sample);
728 	    }
729 	}
730 
731 	if ( pi->done!=NULL )
732 	    *(pi->done) = true;
733 	GDrawDestroyWindow(pi->gw);
734     }
735 return( true );
736 }
737 
PRT_Setup(GGadget * g,GEvent * e)738 static int PRT_Setup(GGadget *g, GEvent *e) {
739     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
740 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
741 	PageSetup(pi);
742     }
743 return( true );
744 }
745 
PRT_RadioSet(GGadget * g,GEvent * e)746 static int PRT_RadioSet(GGadget *g, GEvent *e) {
747     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
748 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
749 	PRT_SetEnabled(pi);
750     }
751 return( true );
752 }
753 
754 /* ************************************************************************** */
755 /* ************************ Code for Display dialog ************************* */
756 /* ************************************************************************** */
757 
TextInfoDataFree(GTextInfo * ti)758 static void TextInfoDataFree(GTextInfo *ti) {
759     int i;
760 
761     if ( ti==NULL )
762 return;
763     for ( i=0; ti[i].text!=NULL || ti[i].line ; ++i )
764 	free(ti[i].userdata);
765     GTextInfoListFree(ti);
766 }
767 
FontNames(SplineFont * cur_sf,int insert_text)768 static GTextInfo *FontNames(SplineFont *cur_sf, int insert_text) {
769     int cnt;
770     FontView *fv;
771     SplineFont *sf;
772     GTextInfo *ti;
773     int selected = false, any_other=-1;
774 
775     for ( fv=fv_list, cnt=0; fv!=NULL; fv=(FontView *) (fv->b.next) )
776 	if ( (FontView *) (fv->b.nextsame)==NULL )
777 	    ++cnt;
778     ti = calloc(cnt+1,sizeof(GTextInfo));
779     for ( fv=fv_list, cnt=0; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
780 	if ( (FontView *) (fv->b.nextsame)==NULL ) {
781 	    sf = fv->b.sf;
782 	    if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
783 	    ti[cnt].text = uc_copy(sf->fontname);
784 	    ti[cnt].userdata = sf;
785 	    /* In the print dlg, use the current font */
786 	    /* In the insert_text dlg, use anything other than the current */
787 	    if ( sf==cur_sf && !insert_text ) {
788 		ti[cnt].selected = true;
789 		selected = true;
790 	    } else if ( cur_sf!=sf && !selected && insert_text ) {
791 		if ( cur_sf->new )
792 		    any_other = cnt;
793 		else {
794 		    ti[cnt].selected = true;
795 		    selected = true;
796 		}
797 	    }
798 	    ++cnt;
799 	}
800     }
801     if ( !selected && any_other!=-1 )
802 	ti[any_other].selected = true;
803     else if ( !selected )
804 	ti[0].selected = true;
805 return( ti );
806 }
807 
DSP_BestMatch(SplineFont * sf,int aa,int size)808 static BDFFont *DSP_BestMatch(SplineFont *sf,int aa,int size) {
809     BDFFont *bdf, *sizem=NULL;
810     int a;
811 
812     for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
813 	if ( bdf->clut==NULL && !aa )
814 	    a = 4;
815 	else if ( bdf->clut!=NULL && aa ) {
816 	    if ( bdf->clut->clut_len==256 )
817 		a = 4;
818 	    else if ( bdf->clut->clut_len==16 )
819 		a = 3;
820 	    else
821 		a = 2;
822 	} else
823 	    a = 1;
824 	if ( bdf->pixelsize==size && a==4 )
825 return( bdf );
826 	if ( sizem==NULL )
827 	    sizem = bdf;
828 	else {
829 	    int sdnew = bdf->pixelsize-size, sdold = sizem->pixelsize-size;
830 	    if ( sdnew<0 ) sdnew = -sdnew;
831 	    if ( sdold<0 ) sdold = -sdold;
832 	    if ( sdnew<sdold )
833 		sizem = bdf;
834 	    else if ( sdnew==sdold ) {
835 		int olda;
836 		if ( sizem->clut==NULL && !aa )
837 		    olda = 4;
838 		else if ( sizem->clut!=NULL && aa ) {
839 		    if ( sizem->clut->clut_len==256 )
840 			olda = 4;
841 		    else if ( sizem->clut->clut_len==16 )
842 			olda = 3;
843 		    else
844 			olda = 2;
845 		} else
846 		    olda = 1;
847 		if ( a>olda )
848 		    sizem = bdf;
849 	    }
850 	}
851     }
852 return( sizem );
853 }
854 
DSP_BestMatchDlg(PD * di)855 static BDFFont *DSP_BestMatchDlg(PD *di) {
856     GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(di->gw,CID_Font));
857     SplineFont *sf;
858     int val;
859     unichar_t *end;
860 
861     if ( sel==NULL )
862 return( NULL );
863     sf = sel->userdata;
864     val = u_strtol(_GGadgetGetTitle(GWidgetGetControl(di->gw,CID_Size)),&end,10);
865     if ( *end!='\0' || val<4 )
866 return( NULL );
867 
868 return( DSP_BestMatch(sf,GGadgetIsChecked(GWidgetGetControl(di->gw,CID_AA)),val) );
869 }
870 
DSP_FontType(PD * di)871 static enum sftf_fonttype DSP_FontType(PD *di) {
872     int type;
873     type = GGadgetIsChecked(GWidgetGetControl(di->gw,CID_pfb))? sftf_pfb :
874 	   GGadgetIsChecked(GWidgetGetControl(di->gw,CID_ttf))? sftf_ttf :
875 	   GGadgetIsChecked(GWidgetGetControl(di->gw,CID_otf))? sftf_otf :
876 	   GGadgetIsChecked(GWidgetGetControl(di->gw,CID_nohints))? sftf_nohints :
877 	   GGadgetIsChecked(GWidgetGetControl(di->gw,CID_pfaedit))? sftf_pfaedit :
878 	   sftf_bitmap;
879 return( type );
880 }
881 
DSP_SetFont(PD * di,int doall)882 static void DSP_SetFont(PD *di,int doall) {
883     unichar_t *end;
884     int size = u_strtol(_GGadgetGetTitle(GWidgetGetControl(di->gw,CID_Size)),&end,10);
885     GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(di->gw,CID_Font));
886     SplineFont *sf;
887     int aa = GGadgetIsChecked(GWidgetGetControl(di->gw,CID_AA));
888     int type;
889     SFTextArea *g;
890     int layer;
891 
892     if ( sel==NULL || *end )
893 return;
894     sf = sel->userdata;
895 
896     type = DSP_FontType(di);
897 
898     g = (SFTextArea *) GWidgetGetControl(di->gw,CID_SampleText);
899     layer = di->fv!=NULL && di->fv->b.sf==sf ? di->fv->b.active_layer : ly_fore;
900     if ( !LI_SetFontData( &g->li, doall?0:-1,-1,
901 	    sf,layer,type,size,aa,g->g.inner.width))
902 	ff_post_error(_("Bad Font"),_("Bad Font"));
903 }
904 
DSP_ChangeFontCallback(void * context,SplineFont * sf,enum sftf_fonttype type,int size,int aa,uint32 script,uint32 lang,uint32 * feats)905 static void DSP_ChangeFontCallback(void *context,SplineFont *sf,enum sftf_fonttype type,
906 	int size, int aa, uint32 script, uint32 lang, uint32 *feats) {
907     PD *di = context;
908     char buf[16];
909     int i,j,cnt;
910     uint32 *tags;
911     GTextInfo **ti;
912 
913     GGadgetSetChecked(GWidgetGetControl(di->gw,CID_AA),aa);
914 
915     sprintf(buf,"%d",size);
916     GGadgetSetTitle8(GWidgetGetControl(di->gw,CID_Size),buf);
917 
918     {
919 	GTextInfo **ti;
920 	int i,set; int32 len;
921 	ti = GGadgetGetList(GWidgetGetControl(di->gw,CID_Font),&len);
922 	for ( i=0; i<len; ++i )
923 	    if ( ti[i]->userdata == sf )
924 	break;
925 	if ( i<len ) {
926 	    GGadgetSelectOneListItem(GWidgetGetControl(di->gw,CID_Font),i);
927 	    /*GGadgetSetTitle(GWidgetGetControl(di->gw,CID_Font),ti[i]->text);*/
928 	}
929 	set = hasFreeType() && !sf->onlybitmaps && sf->subfontcnt==0 &&
930 		!sf->strokedfont && !sf->multilayer;
931 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_pfb),set);
932 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_ttf),set);
933 	set = hasFreeType() && !sf->onlybitmaps &&
934 		!sf->strokedfont && !sf->multilayer;
935 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_otf),set);
936 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_nohints),hasFreeType());
937 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_bitmap),sf->bitmaps!=NULL);
938 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_pfaedit),!sf->onlybitmaps);
939     }
940 
941     if ( type==sftf_pfb )
942 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_pfb),true);
943     else if ( type==sftf_ttf )
944 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_ttf),true);
945     else if ( type==sftf_otf )
946 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_otf),true);
947     else if ( type==sftf_nohints )
948 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_nohints),true);
949     else if ( type==sftf_pfaedit )
950 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_pfaedit),true);
951     else
952 	GGadgetSetChecked(GWidgetGetControl(di->gw,CID_bitmap),true);
953 
954     if ( script==0 ) script = DEFAULT_SCRIPT;
955     if ( lang  ==0 ) lang   = DEFAULT_LANG;
956     buf[0] = script>>24; buf[1] = script>>16; buf[2] = script>>8; buf[3] = script;
957     buf[4] = '{';
958     buf[5] = lang>>24; buf[6] = lang>>16; buf[7] = lang>>8; buf[8] = lang;
959     buf[9] = '}';
960     buf[10] = '\0';
961     GGadgetSetTitle8(GWidgetGetControl(di->gw,CID_ScriptLang),buf);
962 
963     tags = SFFeaturesInScriptLang(sf,-2,script,lang);
964     if ( tags[0]==0 ) {
965 	free(tags);
966 	tags = SFFeaturesInScriptLang(sf,-2,script,DEFAULT_LANG);
967     }
968     for ( cnt=0; tags[cnt]!=0; ++cnt );
969     if ( feats!=NULL )
970 	for ( i=0; feats[i]!=0; ++i ) {
971 	    for ( j=0; tags[j]!=0; ++j ) {
972 		if ( feats[i]==tags[j] )
973 	    break;
974 	    }
975 	    if ( tags[j]==0 )
976 		++cnt;
977 	}
978     ti = malloc((cnt+2)*sizeof(GTextInfo *));
979     for ( i=0; tags[i]!=0; ++i ) {
980 	ti[i] = calloc( 1,sizeof(GTextInfo));
981 	ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
982 	if ( (tags[i]>>24)<' ' || (tags[i]>>24)>0x7e )
983 	    sprintf( buf, "<%d,%d>", tags[i]>>16, tags[i]&0xffff );
984 	else {
985 	    buf[0] = tags[i]>>24; buf[1] = tags[i]>>16; buf[2] = tags[i]>>8; buf[3] = tags[i]; buf[4] = 0;
986 	}
987 	ti[i]->text = uc_copy(buf);
988 	ti[i]->userdata = (void *) (intpt) tags[i];
989 	if ( feats!=NULL ) {
990 	    for ( j=0; feats[j]!=0; ++j ) {
991 		if ( feats[j] == tags[i] ) {
992 		    ti[i]->selected = true;
993 	    break;
994 		}
995 	    }
996 	}
997     }
998     cnt = i;
999     if ( feats!=NULL )
1000 	for ( i=0; feats[i]!=0; ++i ) {
1001 	    for ( j=0; tags[j]!=0; ++j ) {
1002 		if ( feats[i]==tags[j] )
1003 	    break;
1004 	    }
1005 	    if ( tags[j]==0 ) {
1006 		ti[cnt] = calloc( 1,sizeof(GTextInfo));
1007 		ti[cnt]->bg = COLOR_DEFAULT;
1008 		ti[cnt]->fg = COLOR_CREATE(0x70,0x70,0x70);
1009 		ti[cnt]->selected = true;
1010 		buf[0] = feats[i]>>24; buf[1] = feats[i]>>16; buf[2] = feats[i]>>8; buf[3] = feats[i]; buf[4] = 0;
1011 		ti[cnt]->text = uc_copy(buf);
1012 		ti[cnt++]->userdata = (void *) (intpt) feats[i];
1013 	    }
1014 	}
1015     ti[cnt] = calloc(1,sizeof(GTextInfo));
1016     /* These will become ordered because the list widget will do that */
1017     GGadgetSetList(GWidgetGetControl(di->gw,CID_Features),ti,false);
1018     free(tags);
1019 }
1020 
DSP_AAState(SplineFont * sf,BDFFont * bestbdf)1021 static int DSP_AAState(SplineFont *sf,BDFFont *bestbdf) {
1022     /* What should AntiAlias look like given the current set of bitmaps */
1023     int anyaa=0, anybit=0;
1024     BDFFont *bdf;
1025 
1026     for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next )
1027 	if ( bdf->clut==NULL )
1028 	    anybit = true;
1029 	else
1030 	    anyaa = true;
1031     if ( anybit && anyaa )
1032 return( gg_visible | gg_enabled | (bestbdf!=NULL && bestbdf->clut!=NULL ? gg_cb_on : 0) );
1033     else if ( anybit )
1034 return( gg_visible );
1035     else if ( anyaa )
1036 return( gg_visible | gg_cb_on );
1037 
1038 return( gg_visible );
1039 }
1040 
DSP_FontChanged(GGadget * g,GEvent * e)1041 static int DSP_FontChanged(GGadget *g, GEvent *e) {
1042     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1043 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1044 	GTextInfo *sel = GGadgetGetListItemSelected(g);
1045 	SplineFont *sf;
1046 	BDFFont *best;
1047 	int flags, pick = 0, i;
1048 	char size[12]; unichar_t usize[12];
1049 	uint16 cnt;
1050 
1051 	if ( sel==NULL )
1052 return( true );
1053 	sf = sel->userdata;
1054 
1055 	TextInfoDataFree(di->scriptlangs);
1056 	di->scriptlangs = SLOfFont(sf);
1057 	GGadgetSetList(GWidgetGetControl(di->gw,CID_ScriptLang),
1058 		GTextInfoArrayFromList(di->scriptlangs,&cnt),false);
1059 
1060 	if ( GGadgetIsChecked(GWidgetGetControl(di->gw,CID_bitmap)) && sf->bitmaps==NULL )
1061 	    pick = true;
1062 	GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_bitmap),sf->bitmaps!=NULL);
1063 	if ( !hasFreeType() || sf->onlybitmaps ) {
1064 	    best = DSP_BestMatchDlg(di);
1065 	    flags = DSP_AAState(sf,best);
1066 	    GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_AA),flags&gg_enabled);
1067 	    GGadgetSetChecked(GWidgetGetControl(di->gw,CID_AA),flags&gg_cb_on);
1068 	    GGadgetSetChecked(GWidgetGetControl(di->gw,CID_bitmap),true);
1069 	    for ( i=CID_pfb; i<=CID_nohints; ++i )
1070 		GGadgetSetEnabled(GWidgetGetControl(di->gw,i),false);
1071 	    if ( best!=NULL ) {
1072 		sprintf( size, "%d", best->pixelsize );
1073 		uc_strcpy(usize,size);
1074 		GGadgetSetTitle(GWidgetGetControl(di->gw,CID_Size),usize);
1075 	    }
1076 	    pick = true;
1077 	} else if ( sf->subfontcnt!=0 ) {
1078 	    for ( i=CID_pfb; i<CID_otf; ++i ) {
1079 		GGadgetSetEnabled(GWidgetGetControl(di->gw,i),false);
1080 		if ( GGadgetIsChecked(GWidgetGetControl(di->gw,i)) )
1081 		    pick = true;
1082 	    }
1083 	    GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_otf),true);
1084 	    if ( pick )
1085 		GGadgetSetChecked(GWidgetGetControl(di->gw,CID_otf),true);
1086 	} else {
1087 	    for ( i=CID_pfb; i<=CID_otf; ++i )
1088 		GGadgetSetEnabled(GWidgetGetControl(di->gw,i),true);
1089 	    if ( pick )
1090 		GGadgetSetChecked(GWidgetGetControl(di->gw,CID_pfb),true);
1091 	}
1092 	if ( pick )
1093 	    DSP_SetFont(di,false);
1094 	else
1095 	    SFTFSetFont(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,sf);
1096     }
1097 return( true );
1098 }
1099 
DSP_AAChange(GGadget * g,GEvent * e)1100 static int DSP_AAChange(GGadget *g, GEvent *e) {
1101     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1102 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1103 	if ( GGadgetIsChecked(GWidgetGetControl(di->gw,CID_bitmap)) ) {
1104 	    int val = u_strtol(_GGadgetGetTitle(GWidgetGetControl(di->gw,CID_Size)),NULL,10);
1105 	    int bestdiff = 8000, bdfdiff;
1106 	    BDFFont *bdf, *best=NULL;
1107 	    GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(di->gw,CID_Font));
1108 	    SplineFont *sf;
1109 	    int aa = GGadgetIsChecked(GWidgetGetControl(di->gw,CID_AA));
1110 	    if ( sel==NULL )
1111 return( true );
1112 	    sf = sel->userdata;
1113 	    for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
1114 		if ( (aa && bdf->clut) || (!aa && bdf->clut==NULL)) {
1115 		    if ((bdfdiff = bdf->pixelsize-val)<0 ) bdfdiff = -bdfdiff;
1116 		    if ( bdfdiff<bestdiff ) {
1117 			best = bdf;
1118 			bestdiff = bdfdiff;
1119 			if ( bdfdiff==0 )
1120 	    break;
1121 		    }
1122 		}
1123 	    }
1124 	    if ( best!=NULL ) {
1125 		char size[12]; unichar_t usize[12];
1126 		sprintf( size, "%d", best->pixelsize );
1127 		uc_strcpy(usize,size);
1128 		GGadgetSetTitle(GWidgetGetControl(di->gw,CID_Size),usize);
1129 	    }
1130 	    DSP_SetFont(di,false);
1131 	} else
1132 	    SFTFSetAntiAlias(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,
1133 		    GGadgetIsChecked(GWidgetGetControl(di->gw,CID_AA)));
1134     }
1135 return( true );
1136 }
1137 
DSP_SizeChanged(GGadget * g,GEvent * e)1138 static int DSP_SizeChanged(GGadget *g, GEvent *e) {
1139     if ( e->type==et_controlevent && e->u.control.subtype == et_textfocuschanged &&
1140 	    !e->u.control.u.tf_focus.gained_focus ) {
1141 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1142 	int err=false;
1143 	int size = GetInt8(di->gw,CID_Size,_("_Size:"),&err);
1144 	if ( err || size<4 )
1145 return( true );
1146 	if ( GWidgetGetControl(di->gw,CID_SampleText)==NULL )
1147 return( true );		/* Happens during startup */
1148 	if ( GGadgetIsChecked(GWidgetGetControl(di->gw,CID_bitmap)) ) {
1149 	    GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(di->gw,CID_Font));
1150 	    SplineFont *sf;
1151 	    BDFFont *bdf, *best=NULL;
1152 	    int aa = GGadgetIsChecked(GWidgetGetControl(di->gw,CID_AA));
1153 	    if ( sel==NULL )
1154 return( true );
1155 	    sf = sel->userdata;
1156 	    for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
1157 		if ( bdf->pixelsize==size ) {
1158 		    if (( bdf->clut && aa ) || ( bdf->clut==NULL && !aa )) {
1159 			best = bdf;
1160 	    break;
1161 		    }
1162 		    best = bdf;
1163 		}
1164 	    }
1165 	    if ( best==NULL ) {
1166 		char buf[100], *pt=buf, *end=buf+sizeof(buf)-10;
1167 		unichar_t ubuf[12];
1168 		int lastsize = 0;
1169 		for ( bdf=sf->bitmaps; bdf!=NULL && pt<end; bdf=bdf->next ) {
1170 		    if ( bdf->pixelsize!=lastsize ) {
1171 			sprintf( pt, "%d,", bdf->pixelsize );
1172 			lastsize = bdf->pixelsize;
1173 			pt += strlen(pt);
1174 		    }
1175 		}
1176 		if ( pt!=buf )
1177 		    pt[-1] = '\0';
1178 		ff_post_error(_("Bad Size"),_("Requested bitmap size not available in font. Font supports %s"),buf);
1179 		best = DSP_BestMatchDlg(di);
1180 		if ( best!=NULL ) {
1181 		    sprintf( buf, "%d", best->pixelsize);
1182 		    uc_strcpy(ubuf,buf);
1183 		    GGadgetSetTitle(GWidgetGetControl(di->gw,CID_Size),ubuf);
1184 		    size = best->pixelsize;
1185 		}
1186 	    }
1187 	    if ( best==NULL )
1188 return(true);
1189 	    GGadgetSetChecked(GWidgetGetControl(di->gw,CID_AA),best->clut!=NULL );
1190 	    DSP_SetFont(di,false);
1191 	} else
1192 	    SFTFSetSize(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,size);
1193     } else if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1194 	/* Don't change the font on each change to the text field, that might */
1195 	/*  look rather odd. But wait until we think they may have finished */
1196 	/*  typing. Either when they change the focus (above) or when they */
1197 	/*  just don't do anything for a while */
1198 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1199 	if ( di->sizechanged!=NULL )
1200 	    GDrawCancelTimer(di->sizechanged);
1201 	di->sizechanged = GDrawRequestTimer(di->gw,600,0,NULL);
1202     }
1203 return( true );
1204 }
1205 
DSP_SizeChangedTimer(PD * di)1206 static void DSP_SizeChangedTimer(PD *di) {
1207     GEvent e;
1208 
1209     di->sizechanged = NULL;
1210     memset(&e,0,sizeof(e));
1211     e.type = et_controlevent;
1212     e.u.control.g = GWidgetGetControl(di->gw,CID_Size);
1213     e.u.control.subtype = et_textfocuschanged;
1214     e.u.control.u.tf_focus.gained_focus = false;
1215     DSP_SizeChanged(e.u.control.g,&e);
1216 }
1217 
1218 
DSP_WidthChanged(GGadget * g,GEvent * e)1219 static int DSP_WidthChanged(GGadget *g, GEvent *e) {
1220     if ( e==NULL ||
1221 	    (e->type==et_controlevent && e->u.control.subtype == et_textfocuschanged &&
1222 	     !e->u.control.u.tf_focus.gained_focus )) {
1223 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1224 	int err=false;
1225 	int width = GetInt8(di->gw,CID_TextWidth,_("Width"),&err);
1226 	GGadget *sample = GWidgetGetControl(di->gw,CID_SampleText);
1227 	GRect outer;
1228 	int bp;
1229 	if ( err || width<20 || width>2000 )
1230 return( true );
1231 	if ( !di->ready )
1232 return( true );
1233 	bp = GBoxBorderWidth(di->gw,sample->box);
1234 	GGadgetGetSize(sample,&outer);
1235 	outer.width = rint(width*lastdpi/72.0)+2*bp;
1236 	GGadgetSetDesiredSize(sample,&outer,NULL);
1237 	GHVBoxFitWindow(GWidgetGetControl(di->gw,CID_TopBox));
1238     } else if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1239 	/* Don't change the font on each change to the text field, that might */
1240 	/*  look rather odd. But wait until we think they may have finished */
1241 	/*  typing. Either when they change the focus (above) or when they */
1242 	/*  just don't do anything for a while */
1243 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1244 	if ( di->widthchanged!=NULL )
1245 	    GDrawCancelTimer(di->widthchanged);
1246 	di->widthchanged = GDrawRequestTimer(di->gw,600,0,NULL);
1247     }
1248 return( true );
1249 }
1250 
DSP_WidthChangedTimer(PD * di)1251 static void DSP_WidthChangedTimer(PD *di) {
1252 
1253     di->widthchanged = NULL;
1254     DSP_WidthChanged(GWidgetGetControl(di->gw,CID_TextWidth),NULL);
1255 }
1256 
DSP_JustResized(PD * di)1257 static void DSP_JustResized(PD *di) {
1258     GGadget *sample = GWidgetGetControl(di->gw,CID_SampleText);
1259     GGadget *widthfield = GWidgetGetControl(di->gw,CID_TextWidth);
1260     char buffer[20];
1261 
1262     di->resized = NULL;
1263     if ( lastdpi!=0 && widthfield!=NULL ) {
1264 	sprintf( buffer, "%d", (int) rint( sample->inner.width*72/lastdpi ));
1265 	GGadgetSetTitle8(widthfield,buffer);
1266     }
1267 }
1268 
DSP_DpiChanged(GGadget * g,GEvent * e)1269 static int DSP_DpiChanged(GGadget *g, GEvent *e) {
1270     if ( e->type==et_controlevent && e->u.control.subtype == et_textfocuschanged &&
1271 	    !e->u.control.u.tf_focus.gained_focus ) {
1272 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1273 	int err=false;
1274 	int dpi = GetInt8(di->gw,CID_DPI,_("DPI"),&err);
1275 	GGadget *sample = GWidgetGetControl(di->gw,CID_SampleText);
1276 	GGadget *widthfield = GWidgetGetControl(di->gw,CID_TextWidth);
1277 	if ( err || dpi<20 || dpi>300 )
1278 return( true );
1279 	if ( !di->ready )
1280 return( true );		/* Happens during startup */
1281 	if ( lastdpi==dpi )
1282 return( true );
1283 	SFTFSetDPI(sample,dpi);
1284 	lastdpi = dpi;
1285 	if ( widthfield!=NULL ) {
1286 	    DSP_WidthChanged(widthfield,NULL);
1287 	} else {
1288 	    GGadgetRedraw(sample);
1289 	}
1290     } else if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1291 	/* Don't change the font on each change to the text field, that might */
1292 	/*  look rather odd. But wait until we think they may have finished */
1293 	/*  typing. Either when they change the focus (above) or when they */
1294 	/*  just don't do anything for a while */
1295 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1296 	if ( di->dpichanged!=NULL )
1297 	    GDrawCancelTimer(di->dpichanged);
1298 	di->dpichanged = GDrawRequestTimer(di->gw,600,0,NULL);
1299     }
1300 return( true );
1301 }
1302 
DSP_DpiChangedTimer(PD * di)1303 static void DSP_DpiChangedTimer(PD *di) {
1304     GEvent e;
1305 
1306     di->dpichanged = NULL;
1307     memset(&e,0,sizeof(e));
1308     e.type = et_controlevent;
1309     e.u.control.g = GWidgetGetControl(di->gw,CID_Size);
1310     e.u.control.subtype = et_textfocuschanged;
1311     e.u.control.u.tf_focus.gained_focus = false;
1312     DSP_DpiChanged(e.u.control.g,&e);
1313 }
1314 
DSP_Refresh(GGadget * g,GEvent * e)1315 static int DSP_Refresh(GGadget *g, GEvent *e) {
1316     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1317 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1318 	GGadget *sample = GWidgetGetControl(di->gw,CID_SampleText);
1319 	GGadget *fontnames = GWidgetGetControl(di->gw,CID_Font);
1320 	GTextInfo *sel = GGadgetGetListItemSelected(fontnames);
1321 	GTextInfo *fn;
1322 
1323 	SFTFRefreshFonts(sample);		/* Clear any font info and get new font maps, etc. */
1324 	SFTFProvokeCallback(sample);		/* Refresh the feature list too */
1325 
1326 	/* One thing we don't have to worry about is a font being removed */
1327 	/*  if that happens we just close this window. Too hard to fix up for */
1328 	/* But a font might be added... */
1329 	fn = FontNames(sel!=NULL? (SplineFont *) (sel->userdata) : di->pi.mainsf, di->insert_text );
1330 	GGadgetSetList(fontnames,GTextInfoArrayFromList(fn,NULL),false);
1331 	GGadgetSetEnabled(fontnames,fn[1].text!=NULL);
1332 	GTextInfoListFree(fn);
1333     }
1334 return( true );
1335 }
1336 
DSP_RadioSet(GGadget * g,GEvent * e)1337 static int DSP_RadioSet(GGadget *g, GEvent *e) {
1338     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1339 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1340 	if ( GGadgetIsChecked(GWidgetGetControl(di->gw,CID_bitmap)) ) {
1341 	    BDFFont *best = DSP_BestMatchDlg(di);
1342 	    GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(di->gw,CID_Font));
1343 	    SplineFont *sf;
1344 	    int flags;
1345 	    char size[14]; unichar_t usize[14];
1346 
1347 	    if ( sel!=NULL ) {
1348 		sf = sel->userdata;
1349 		flags = DSP_AAState(sf,best);
1350 		GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_AA),flags&gg_enabled);
1351 		GGadgetSetChecked(GWidgetGetControl(di->gw,CID_AA),flags&gg_cb_on);
1352 		if ( best!=NULL ) {
1353 		    sprintf( size, "%g",
1354 			    rint(best->pixelsize*72.0/SFTFGetDPI(GWidgetGetControl(di->gw,CID_SampleText))) );
1355 		    uc_strcpy(usize,size);
1356 		    GGadgetSetTitle(GWidgetGetControl(di->gw,CID_Size),usize);
1357 		}
1358 	    }
1359 	    DSP_SetFont(di,false);
1360 	} else {
1361 	    /*GGadgetSetEnabled(GWidgetGetControl(di->gw,CID_AA),true);*/
1362 	    SFTFSetFontType(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,
1363 		    DSP_FontType(di));
1364 	}
1365     }
1366 return( true );
1367 }
1368 
DSP_ScriptLangChanged(GGadget * g,GEvent * e)1369 static int DSP_ScriptLangChanged(GGadget *g, GEvent *e) {
1370 
1371     if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1372 	const unichar_t *sstr = _GGadgetGetTitle(g);
1373 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1374 	uint32 script, lang;
1375 
1376 	if ( e->u.control.u.tf_changed.from_pulldown!=-1 ) {
1377 	    GGadgetSetTitle8(g,di->scriptlangs[e->u.control.u.tf_changed.from_pulldown].userdata );
1378 	    sstr = _GGadgetGetTitle(g);
1379 	} else {
1380 	    if ( u_strlen(sstr)<4 || !isalpha(sstr[0]) || !isalnum(sstr[1]) /*|| !isalnum(sstr[2]) || !isalnum(sstr[3])*/ )
1381 return( true );
1382 	    if ( u_strlen(sstr)==4 )
1383 		/* No language, we'll use default */;
1384 	    else if ( u_strlen(sstr)!=10 || sstr[4]!='{' || sstr[9]!='}' ||
1385 		    !isalpha(sstr[5]) || !isalpha(sstr[6]) || !isalpha(sstr[7])  )
1386 return( true );
1387 	}
1388 	script = DEFAULT_SCRIPT;
1389 	lang = DEFAULT_LANG;
1390 	if ( u_strlen(sstr)>=4 )
1391 	    script = (sstr[0]<<24) | (sstr[1]<<16) | (sstr[2]<<8) | sstr[3];
1392 	if ( sstr[4]=='{' && u_strlen(sstr)>=9 )
1393 	    lang = (sstr[5]<<24) | (sstr[6]<<16) | (sstr[7]<<8) | sstr[8];
1394 	SFTFSetScriptLang(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,script,lang);
1395     }
1396 return( true );
1397 }
1398 
DSP_Menu(GGadget * g,GEvent * e)1399 static int DSP_Menu(GGadget *g, GEvent *e) {
1400 
1401     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonpress ) {
1402 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1403 	GGadget *st = GWidgetGetControl(di->gw,CID_SampleText);
1404 	GEvent fudge;
1405 	GPoint p;
1406 	memset(&fudge,0,sizeof(fudge));
1407 	fudge.type = et_mousedown;
1408 	fudge.w = st->base;
1409 	p.x = g->inner.x+g->inner.width/2;
1410 	p.y = g->inner.y+g->inner.height;
1411 	GDrawTranslateCoordinates(g->base,st->base,&p);
1412 	fudge.u.mouse.x = p.x; fudge.u.mouse.y = p.y;
1413 	SFTFPopupMenu((SFTextArea *) st,&fudge);
1414     }
1415 return( true );
1416 }
1417 
DSP_FeaturesChanged(GGadget * g,GEvent * e)1418 static int DSP_FeaturesChanged(GGadget *g, GEvent *e) {
1419 
1420     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1421 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1422 	uint32 *feats;
1423 	int32 len;
1424 	GTextInfo **ti = GGadgetGetList(g,&len);
1425 	int i,cnt;
1426 
1427 	for ( i=cnt=0; i<len; ++i )
1428 	    if ( ti[i]->selected ) ++cnt;
1429 	feats = malloc((cnt+1)*sizeof(uint32));
1430 	for ( i=cnt=0; i<len; ++i )
1431 	    if ( ti[i]->selected )
1432 		feats[cnt++] = (intpt) ti[i]->userdata;
1433 	feats[cnt] = 0;
1434 	/* These will be ordered because the list widget will do that */
1435 	SFTFSetFeatures(GWidgetGetControl(di->gw,CID_SampleText),-1,-1,feats);
1436     }
1437 return( true );
1438 }
1439 
PRT_Bind(GGadget * g,GEvent * e)1440 static int PRT_Bind(GGadget *g, GEvent *e) {
1441     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1442 	PD *pi = GDrawGetUserData(GGadgetGetWindow(g));
1443 	int on = GGadgetIsChecked(g);
1444 	GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_Scale),on);
1445 	GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_Start),on);
1446 	GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_Center),on);
1447 	GGadgetSetEnabled(GWidgetGetControl(pi->gw,CID_End),on);
1448     }
1449 return( true );
1450 }
1451 
DSP_TextChanged(GGadget * g,GEvent * e)1452 static int DSP_TextChanged(GGadget *g, GEvent *e) {
1453     if ( e==NULL ||
1454 	    (e->type==et_controlevent && e->u.control.subtype == et_textchanged )) {
1455 	PD *di = GDrawGetUserData(GGadgetGetWindow(g));
1456 	const unichar_t *txt = _GGadgetGetTitle(g);
1457 	const unichar_t *pt;
1458 	SFTextArea *ta = (SFTextArea *) g;
1459 	LayoutInfo *li = &ta->li;
1460 	char buffer[200];
1461 
1462 	for ( pt=txt; *pt!='\0' && ScriptFromUnicode(*pt,NULL)==DEFAULT_SCRIPT; ++pt);
1463 	if ( *pt=='\0' ) {
1464 	    if ( !di->script_unknown ) {
1465 		di->script_unknown = true;
1466 		if ( li->fontlist!=NULL ) {
1467 		    li->fontlist->script = DEFAULT_SCRIPT;
1468 		    li->fontlist->lang   = DEFAULT_LANG;
1469 		}
1470 		GGadgetSetTitle8(GWidgetGetControl(di->gw,CID_ScriptLang),"DFLT{dflt}");
1471 	    }
1472 	} else if ( di->script_unknown ) {
1473 	    uint32 script = ScriptFromUnicode(*pt,NULL);
1474 	    struct fontlist *fl;
1475 	    unichar_t buf[20];
1476 	    for ( fl=li->fontlist; fl!=NULL && ta->sel_start>fl->end; fl=fl->next );
1477 	    if ( fl!=NULL && (fl->script==DEFAULT_SCRIPT || fl->script==0 )) {
1478 		for ( fl=li->fontlist; fl!=NULL; fl=fl->next ) {
1479 		    if ( fl->script==DEFAULT_SCRIPT || fl->script == 0 ) {
1480 			fl->script = script;
1481 			fl->lang = DEFAULT_LANG;
1482 		    }
1483 		}
1484 		buf[0] = (script>>24)&0xff;
1485 		buf[1] = (script>>16)&0xff;
1486 		buf[2] = (script>>8 )&0xff;
1487 		buf[3] = (script    )&0xff;
1488 		uc_strcpy(buf+4,"{dflt}");
1489 		GGadgetSetTitle(GWidgetGetControl(di->gw,CID_ScriptLang),buf);
1490 	    }
1491 	    di->script_unknown = false;
1492 	}
1493 
1494 	if ( di->insert_text && lastdpi!=0) {
1495 	    sprintf( buffer,_("Text Width:%4d"), (int) rint(li->xmax*72.0/lastdpi));
1496 	    GGadgetSetTitle8(GWidgetGetControl(di->gw,CID_ActualWidth),buffer);
1497 	}
1498     }
1499 return( true );
1500 }
1501 
DSP_Done(GGadget * g,GEvent * e)1502 static int DSP_Done(GGadget *g, GEvent *e) {
1503     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1504 	GWindow gw = GGadgetGetWindow(g);
1505 	PD *di = GDrawGetUserData(gw);
1506 	if ( di->done!=NULL )
1507 	    *(di->done) = true;
1508 	GDrawDestroyWindow(di->gw);
1509     }
1510 return( true );
1511 }
1512 
dsp_e_h(GWindow gw,GEvent * event)1513 static int dsp_e_h(GWindow gw, GEvent *event) {
1514     if ( event->type==et_close ) {
1515 	PD *di = GDrawGetUserData(gw);
1516 	if ( di->done!=NULL )
1517 	    *(di->done) = true;
1518 	GDrawDestroyWindow(di->gw);
1519     } else if ( event->type==et_destroy ) {
1520 	PD *di = GDrawGetUserData(gw);
1521 	TextInfoDataFree(di->scriptlangs);
1522 	free(di);
1523 	if ( di==printwindow )
1524 	    printwindow = NULL;
1525     } else if ( event->type==et_char ) {
1526 	if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1527 	    help("ui/dialogs/display.html", NULL);
1528 return( true );
1529 	} else if ( GMenuIsCommand(event,H_("Quit|Ctl+Q") )) {
1530 	    MenuExit(NULL,NULL,NULL);
1531     return( false );
1532 	} else if ( GMenuIsCommand(event,H_("Close|Ctl+Shft+Q") )) {
1533 	    PD *di = GDrawGetUserData(gw);
1534 	    di->pi.done = true;
1535 	}
1536 return( false );
1537     } else if ( event->type==et_timer ) {
1538 	PD *di = GDrawGetUserData(gw);
1539 	if ( event->u.timer.timer==di->sizechanged )
1540 	    DSP_SizeChangedTimer(di);
1541 	else if ( event->u.timer.timer==di->dpichanged )
1542 	    DSP_DpiChangedTimer(di);
1543 	else if ( event->u.timer.timer==di->widthchanged )
1544 	    DSP_WidthChangedTimer(di);
1545 	else if ( event->u.timer.timer==di->resized )
1546 	    DSP_JustResized(di);
1547     } else if ( event->type==et_resize ) {
1548 	PD *di = GDrawGetUserData(gw);
1549 	if ( di->resized!=NULL )
1550 	    GDrawCancelTimer(di->resized);
1551 	di->resized = GDrawRequestTimer(di->gw,300,0,NULL);
1552     }
1553 return( true );
1554 }
1555 
_PrintFFDlg(FontView * fv,SplineChar * sc,MetricsView * mv,int isprint,CharView * cv,SplineSet * fit_to_path)1556 static void _PrintFFDlg(FontView *fv,SplineChar *sc,MetricsView *mv,
1557 	int isprint,CharView *cv,SplineSet *fit_to_path) {
1558     GRect pos;
1559     GWindowAttrs wattrs;
1560     GGadgetCreateData gcd[20], boxes[15], mgcd[5], pgcd[8], vbox, tgcd[14],
1561 	    *harray[8], *farray[8], *barray[4],
1562 	    *barray2[8], *varray[11], *varray2[9], *harray2[5],
1563 	    *varray3[4][4], *ptarray[4], *varray4[4], *varray5[4][2],
1564 	    *regenarray[9], *varray6[3], *tarray[18], *alarray[6],
1565 	    *patharray[5], *oarray[4];
1566     GTextInfo label[20], mlabel[5], plabel[8], tlabel[14];
1567     GTabInfo aspects[3];
1568     int dpi;
1569     char buf[12], dpibuf[12], sizebuf[12], widthbuf[12], pathlen[32];
1570     SplineFont *sf = fv!=NULL ? fv->b.sf : sc!=NULL ? sc->parent : mv->fv->b.sf;
1571     int hasfreetype = hasFreeType();
1572     BDFFont *bestbdf=DSP_BestMatch(sf,true,12);
1573     unichar_t *temp;
1574     int cnt;
1575     int fromwindow = fv!=NULL?0:sc!=NULL?1:2;
1576     PD *active;
1577     int done = false;
1578     int width = 300;
1579     extern int _GScrollBar_Width;
1580 
1581     if ( printwindow!=NULL && isprint ) {
1582 	GDrawSetVisible(printwindow->gw,true);
1583 	GDrawRaise(printwindow->gw);
1584 return;
1585     }
1586 
1587     if ( sf->cidmaster )
1588 	sf = sf->cidmaster;
1589 
1590     active = calloc(1,sizeof(PD));
1591     if ( isprint )
1592 	printwindow = active;
1593     active->fv = fv;
1594 
1595     if ( mv!=NULL ) {
1596 	PI_Init(&active->pi,(FontViewBase *) mv->fv,sc);
1597 	active->pi.mv = mv;
1598     } else
1599 	PI_Init(&active->pi,(FontViewBase *) fv,sc);
1600     active->cv = cv;
1601     active->fit_to_path = fit_to_path;
1602     active->insert_text = !isprint;
1603     active->done = isprint ? NULL : &done;
1604 
1605     memset(&wattrs,0,sizeof(wattrs));
1606     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1607     wattrs.event_masks = ~(1<<et_charup);
1608     wattrs.restrict_input_to_me = false;
1609     wattrs.undercursor = 1;
1610     wattrs.cursor = ct_pointer;
1611     wattrs.is_dlg = true;
1612     wattrs.utf8_window_title = isprint ? _("Print") : _("Insert Text Outlines");
1613     pos.x = pos.y = 0;
1614     pos.width = GGadgetScale(GDrawPointsToPixels(NULL,410));
1615     pos.height = GDrawPointsToPixels(NULL,330);
1616     active->gw = GDrawCreateTopWindow(NULL,&pos,dsp_e_h,active,&wattrs);
1617 
1618     memset(&vbox,0,sizeof(vbox));
1619     memset(&label,0,sizeof(label));
1620     memset(&mlabel,0,sizeof(mlabel));
1621     memset(&plabel,0,sizeof(plabel));
1622     memset(&tlabel,0,sizeof(tlabel));
1623     memset(&gcd,0,sizeof(gcd));
1624     memset(&mgcd,0,sizeof(mgcd));
1625     memset(&pgcd,0,sizeof(pgcd));
1626     memset(&tgcd,0,sizeof(tgcd));
1627     memset(&boxes,0,sizeof(boxes));
1628 
1629     label[0].text = (unichar_t *) sf->fontname;
1630     label[0].text_is_1byte = true;
1631     gcd[0].gd.label = &label[0];
1632     gcd[0].gd.popup_msg = _("Select some text, then use this list to change the\nfont in which those characters are displayed.");
1633     gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
1634     gcd[0].gd.pos.width = 150;
1635     gcd[0].gd.cid = CID_Font;
1636     gcd[0].gd.u.list = FontNames(sf,active->insert_text);
1637     gcd[0].gd.flags = (fv_list==NULL || gcd[0].gd.u.list[1].text==NULL ) ?
1638 	    (gg_visible):
1639 	    (gg_visible | gg_enabled);
1640     gcd[0].gd.handle_controlevent = DSP_FontChanged;
1641     gcd[0].creator = GListButtonCreate;
1642     varray[0] = &gcd[0]; varray[1] = NULL;
1643 
1644     label[2].text = (unichar_t *) _("_Size:");
1645     label[2].text_is_1byte = true;
1646     label[2].text_in_resource = true;
1647     gcd[2].gd.label = &label[2];
1648     gcd[2].gd.pos.x = 210; gcd[2].gd.pos.y = gcd[0].gd.pos.y+6;
1649     gcd[2].gd.flags = gg_visible | gg_enabled;
1650     if ( isprint )
1651 	gcd[2].gd.popup_msg = _("Select some text, this specifies the point\nsize of those characters");
1652     else
1653 	gcd[2].gd.popup_msg = _("Select some text, this specifies the vertical\nsize of those characters in em-units");
1654     gcd[2].gd.cid = CID_SizeLab;
1655     gcd[2].creator = GLabelCreate;
1656     harray[0] = &gcd[2];
1657 
1658     if ( bestbdf !=NULL && ( !hasfreetype || sf->onlybitmaps ))
1659 	sprintf( buf, "%d", bestbdf->pixelsize );
1660     else
1661 	strcpy(buf,"12");
1662     label[3].text = (unichar_t *) buf;
1663     label[3].text_is_1byte = true;
1664     gcd[3].gd.label = &label[3];
1665     gcd[3].gd.pos.x = 240; gcd[3].gd.pos.y = gcd[0].gd.pos.y+3;
1666     gcd[3].gd.pos.width = 40;
1667     gcd[3].gd.flags = gg_visible | gg_enabled;
1668     gcd[3].gd.cid = CID_Size;
1669     gcd[3].gd.handle_controlevent = DSP_SizeChanged;
1670     gcd[3].gd.popup_msg = _("Select some text, this specifies the pixel\nsize of those characters");
1671     gcd[3].creator = GNumericFieldCreate;
1672     harray[1] = &gcd[3]; harray[2] = GCD_HPad10;
1673 
1674     label[1].text = (unichar_t *) _("_AA");
1675     label[1].text_is_1byte = true;
1676     label[1].text_in_resource = true;
1677     gcd[1].gd.label = &label[1];
1678     gcd[1].gd.pos.x = 170; gcd[1].gd.pos.y = gcd[0].gd.pos.y+3;
1679     gcd[1].gd.flags = gg_visible | gg_enabled | gg_cb_on;
1680     if ( sf->bitmaps!=NULL && ( !hasfreetype || sf->onlybitmaps ))
1681 	gcd[1].gd.flags = DSP_AAState(sf,bestbdf);
1682     if ( !isprint )
1683 	gcd[1].gd.flags = gg_enabled | gg_cb_on;
1684     gcd[1].gd.popup_msg = _("Select some text, this controls whether those characters will be\nAntiAlias (greymap) characters, or bitmap characters");
1685     gcd[1].gd.handle_controlevent = DSP_AAChange;
1686     gcd[1].gd.cid = CID_AA;
1687     gcd[1].creator = GCheckBoxCreate;
1688     harray[3] = &gcd[1]; harray[4] = GCD_Glue; harray[5] = NULL;
1689 
1690     boxes[2].gd.flags = gg_enabled|gg_visible;
1691     boxes[2].gd.u.boxelements = harray;
1692     boxes[2].creator = GHBoxCreate;
1693     varray[2] = &boxes[2]; varray[3] = NULL;
1694 
1695     label[4].text = (unichar_t *) "pfb";
1696     label[4].text_is_1byte = true;
1697     gcd[4].gd.label = &label[4];
1698     gcd[4].gd.pos.x = gcd[0].gd.pos.x; gcd[4].gd.pos.y = 24+gcd[3].gd.pos.y;
1699     gcd[4].gd.flags = gg_visible | gg_enabled;
1700     gcd[4].gd.cid = CID_pfb;
1701     gcd[4].gd.handle_controlevent = DSP_RadioSet;
1702     gcd[4].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1703     gcd[4].creator = GRadioCreate;
1704     if ( sf->subfontcnt!=0 || !hasfreetype || sf->onlybitmaps || sf->strokedfont || sf->multilayer ) gcd[4].gd.flags = gg_visible;
1705     farray[0] = &gcd[4];
1706 
1707     label[5].text = (unichar_t *) "ttf";
1708     label[5].text_is_1byte = true;
1709     gcd[5].gd.label = &label[5];
1710     gcd[5].gd.pos.x = 46; gcd[5].gd.pos.y = gcd[4].gd.pos.y;
1711     gcd[5].gd.flags = gg_visible | gg_enabled;
1712     gcd[5].gd.cid = CID_ttf;
1713     gcd[5].gd.handle_controlevent = DSP_RadioSet;
1714     gcd[5].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1715     gcd[5].creator = GRadioCreate;
1716     if ( sf->subfontcnt!=0 || !hasfreetype || sf->onlybitmaps || sf->strokedfont || sf->multilayer ) gcd[5].gd.flags = gg_visible;
1717     else if ( sf->layers[ly_fore].order2 ) gcd[5].gd.flags |= gg_cb_on;
1718     farray[1] = &gcd[5];
1719 
1720     label[6].text = (unichar_t *) "otf";
1721     label[6].text_is_1byte = true;
1722     gcd[6].gd.label = &label[6];
1723     gcd[6].gd.pos.x = 114; gcd[6].gd.pos.y = gcd[4].gd.pos.y;
1724     gcd[6].gd.flags = gg_visible | gg_enabled;
1725     gcd[6].gd.cid = CID_otf;
1726     gcd[6].gd.handle_controlevent = DSP_RadioSet;
1727     gcd[6].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1728     gcd[6].creator = GRadioCreate;
1729     if ( !hasfreetype || sf->onlybitmaps || sf->strokedfont || sf->multilayer ) gcd[6].gd.flags = gg_visible;
1730     else if ( sf->subfontcnt!=0 || !sf->layers[ly_fore].order2 ) gcd[6].gd.flags |= gg_cb_on;
1731     farray[2] = &gcd[6];
1732 
1733     label[7].text = (unichar_t *) _("nohints");
1734     label[7].text_is_1byte = true;
1735     gcd[7].gd.label = &label[7];
1736     gcd[7].gd.pos.x = 114; gcd[7].gd.pos.y = gcd[4].gd.pos.y;
1737     gcd[7].gd.flags = gg_visible | gg_enabled;
1738     gcd[7].gd.cid = CID_nohints;
1739     gcd[7].gd.handle_controlevent = DSP_RadioSet;
1740     gcd[7].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1741     gcd[7].creator = GRadioCreate;
1742     if ( !hasfreetype || sf->onlybitmaps ) gcd[7].gd.flags = gg_visible;
1743     else if ( sf->strokedfont || sf->multilayer ) gcd[7].gd.flags |= gg_cb_on;
1744     farray[3] = &gcd[7];
1745 
1746 
1747     label[8].text = (unichar_t *) "bitmap";
1748     label[8].text_is_1byte = true;
1749     gcd[8].gd.label = &label[8];
1750     gcd[8].gd.pos.x = 148; gcd[8].gd.pos.y = gcd[4].gd.pos.y;
1751     gcd[8].gd.flags = gg_visible | gg_enabled;
1752     gcd[8].gd.cid = CID_bitmap;
1753     gcd[8].gd.handle_controlevent = DSP_RadioSet;
1754     gcd[8].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1755     gcd[8].creator = GRadioCreate;
1756     if ( sf->bitmaps==NULL ) gcd[8].gd.flags = gg_visible;
1757     else if ( sf->onlybitmaps ) gcd[8].gd.flags |= gg_cb_on;
1758     farray[4] = &gcd[8];
1759 
1760     label[9].text = (unichar_t *) "FontForge";
1761     label[9].text_is_1byte = true;
1762     gcd[9].gd.label = &label[9];
1763     gcd[9].gd.pos.x = 200; gcd[9].gd.pos.y = gcd[4].gd.pos.y;
1764     gcd[9].gd.flags = gg_visible | gg_enabled;
1765     gcd[9].gd.cid = CID_pfaedit;
1766     gcd[9].gd.handle_controlevent = DSP_RadioSet;
1767     gcd[9].gd.popup_msg = _("Specifies file format used to pass the font to freetype\n  pfb -- is the standard postscript type1\n  ttf -- is truetype\n  otf -- is opentype\n  nohints -- freetype rasterizes without hints\n  bitmap -- not passed to freetype for rendering\n    bitmap fonts must already be generated\n  FontForge -- uses FontForge's own rasterizer, not\n    freetype's. Only as last resort");
1768     gcd[9].creator = GRadioCreate;
1769     if ( sf->onlybitmaps ) gcd[9].gd.flags = gg_visible;
1770     if ( !hasfreetype && sf->bitmaps==NULL ) gcd[9].gd.flags |= gg_cb_on;
1771     else if ( sf->onlybitmaps ) gcd[9].gd.flags = gg_visible;
1772     farray[5] = &gcd[9]; farray[6] = GCD_Glue; farray[7] = NULL;
1773 
1774     boxes[3].gd.flags = gg_enabled|gg_visible;
1775     boxes[3].gd.u.boxelements = farray;
1776     boxes[3].creator = GHBoxCreate;
1777     varray[4] = &boxes[3]; varray[5] = NULL;
1778     if ( !isprint ) {
1779 	int k;
1780 	for ( k=4; k<=9; ++k )
1781 	    gcd[k].gd.flags &= ~gg_visible;
1782 	boxes[3].gd.flags = gg_enabled;
1783     }
1784 
1785     label[10].text = (unichar_t *) "DFLT{dflt}";
1786     label[10].text_is_1byte = true;
1787     gcd[10].gd.label = &label[10];
1788     gcd[10].gd.popup_msg = _("Select some text, then use this list to specify\nthe current script & language.");
1789     gcd[10].gd.pos.x = 12; gcd[10].gd.pos.y = 6;
1790     gcd[10].gd.pos.width = 150;
1791     gcd[10].gd.flags = gg_visible | gg_enabled;
1792     gcd[10].gd.cid = CID_ScriptLang;
1793     gcd[10].gd.u.list = active->scriptlangs = SLOfFont(sf);
1794     gcd[10].gd.handle_controlevent = DSP_ScriptLangChanged;
1795     gcd[10].creator = GListFieldCreate;
1796     varray[6] = GCD_Glue; varray[7] = NULL;
1797     varray[8] = &gcd[10]; varray[9] = NULL; varray[10] = NULL;
1798 
1799     boxes[4].gd.flags = gg_enabled|gg_visible;
1800     boxes[4].gd.u.boxelements = varray;
1801     boxes[4].creator = GHVBoxCreate;
1802     harray2[1] = &boxes[4];
1803 
1804     gcd[11].gd.popup_msg = _("Select some text, then use this list to specify\nactive features.");
1805     gcd[11].gd.pos.width = 50;
1806     gcd[11].gd.flags = gg_visible | gg_enabled| gg_list_alphabetic | gg_list_multiplesel;
1807     gcd[11].gd.cid = CID_Features;
1808     gcd[11].gd.handle_controlevent = DSP_FeaturesChanged;
1809     gcd[11].creator = GListCreate;
1810     harray2[0] = &gcd[11];
1811 
1812     label[12].image = &GIcon_menudelta;
1813     gcd[12].gd.label = &label[12];
1814     gcd[12].gd.popup_msg = _("Menu");
1815     gcd[12].gd.flags = gg_visible | gg_enabled;
1816     gcd[12].gd.handle_controlevent = DSP_Menu;
1817     gcd[12].creator = GButtonCreate;
1818 
1819     varray6[0] = GCD_Glue; varray6[1] = &gcd[12]; varray6[2] = NULL;
1820     vbox.gd.flags = gg_enabled|gg_visible;
1821     vbox.gd.u.boxelements = varray6;
1822     vbox.creator = GVBoxCreate;
1823 
1824     harray2[2] = &vbox; harray2[3] = GCD_Glue; harray2[4] = NULL;
1825 
1826     boxes[5].gd.flags = gg_enabled|gg_visible;
1827     boxes[5].gd.u.boxelements = harray2;
1828     boxes[5].creator = GHBoxCreate;
1829     varray2[0] = &boxes[5]; varray2[1] = NULL;
1830 
1831 
1832     gcd[13].gd.pos.x = 5; gcd[13].gd.pos.y = 20+gcd[13].gd.pos.y;
1833     gcd[13].gd.pos.width = 400; gcd[13].gd.pos.height = 236;
1834     gcd[13].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap | gg_text_xim;
1835     gcd[13].gd.handle_controlevent = DSP_TextChanged;
1836     gcd[13].gd.cid = CID_SampleText;
1837     gcd[13].creator = SFTextAreaCreate;
1838     varray2[2] = &gcd[13]; varray2[3] = NULL;
1839 
1840     gcd[14].gd.flags = gg_visible | gg_enabled ;
1841     gcd[14].creator = GLineCreate;
1842     varray2[4] = &gcd[14]; varray2[5] = NULL;
1843 
1844     label[15].text = (unichar_t *) _("DPI:");
1845     label[15].text_is_1byte = true;
1846     gcd[15].gd.label = &label[15];
1847     gcd[15].gd.flags = gg_visible | gg_enabled;
1848     gcd[15].gd.popup_msg = _("Specifies screen dots per inch");
1849     gcd[15].creator = GLabelCreate;
1850 
1851     if ( lastdpi==0 )
1852 	lastdpi = GDrawPointsToPixels(NULL,72);
1853     dpi = lastdpi;
1854     sprintf( dpibuf, "%d", dpi );
1855     label[16].text = (unichar_t *) dpibuf;
1856     label[16].text_is_1byte = true;
1857     gcd[16].gd.label = &label[16];
1858     gcd[16].gd.pos.width = 50;
1859     gcd[16].gd.flags = gg_visible | gg_enabled;
1860     gcd[16].gd.popup_msg = _("Specifies screen dots per inch");
1861     gcd[16].gd.cid = CID_DPI;
1862     gcd[16].gd.handle_controlevent = DSP_DpiChanged;
1863     gcd[16].creator = GNumericFieldCreate;
1864 
1865     regenarray[0] = &gcd[15]; regenarray[1] = &gcd[16]; regenarray[2] = GCD_Glue;
1866     if ( isprint ) {
1867 	gcd[17].gd.flags = gg_visible | gg_enabled;
1868 	gcd[17].gd.popup_msg = _("FontForge does not update this window when a change is made to the font.\nIf a font has changed press the button to force an update");
1869 	label[17].text = (unichar_t *) _("_Refresh");
1870 	label[17].text_is_1byte = true;
1871 	label[17].text_in_resource = true;
1872 	gcd[17].gd.label = &label[17];
1873 	gcd[17].gd.handle_controlevent = DSP_Refresh;
1874 	gcd[17].creator = GButtonCreate;
1875 	regenarray[3] = &gcd[17]; regenarray[4] = NULL;
1876     } else {
1877 	label[17].text = (unichar_t *) _("Text Width:    0");
1878 	label[17].text_is_1byte = true;
1879 	gcd[17].gd.label = &label[17];
1880 	gcd[17].gd.flags = gg_visible | gg_enabled;
1881 	gcd[17].gd.cid = CID_ActualWidth;
1882 	gcd[17].creator = GLabelCreate;
1883 
1884 	label[18].text = (unichar_t *) _("Wrap Pos:");
1885 	label[18].text_is_1byte = true;
1886 	gcd[18].gd.label = &label[18];
1887 	gcd[18].gd.flags = gg_visible | gg_enabled;
1888 	gcd[18].gd.popup_msg = _("The text will wrap to a new line after this many em-units");
1889 	gcd[18].creator = GLabelCreate;
1890 
1891 	sprintf( widthbuf, "%d", width );
1892 	label[19].text = (unichar_t *) widthbuf;
1893 	label[19].text_is_1byte = true;
1894 	gcd[19].gd.label = &label[19];
1895 	gcd[19].gd.pos.width = 50;
1896 	gcd[19].gd.flags = gg_visible | gg_enabled;
1897 	gcd[19].gd.popup_msg = _("The text will wrap to a new line after this many em-units");
1898 	gcd[19].gd.cid = CID_TextWidth;
1899 	gcd[19].gd.handle_controlevent = DSP_WidthChanged;
1900 	gcd[19].creator = GNumericFieldCreate;
1901 	regenarray[3] = &gcd[17]; regenarray[4] = GCD_Glue;
1902 	regenarray[5] = &gcd[18]; regenarray[6] = &gcd[19]; regenarray[7] = NULL;
1903 	gcd[13].gd.pos.width = GDrawPixelsToPoints(NULL,width*dpi/72) + _GScrollBar_Width+4;
1904     }
1905 
1906     boxes[12].gd.flags = gg_enabled|gg_visible;
1907     boxes[12].gd.u.boxelements = regenarray;
1908     boxes[12].creator = GHBoxCreate;
1909     varray2[6] = &boxes[12]; varray2[7] = NULL; varray2[8] = NULL;
1910 
1911     boxes[6].gd.flags = gg_enabled|gg_visible;
1912     boxes[6].gd.u.boxelements = varray2;
1913     boxes[6].creator = GHVBoxCreate;
1914 
1915     if ( isprint ) {
1916 	memset(aspects,0,sizeof(aspects));
1917 	aspects[0].text = (unichar_t *) _("Display");
1918 	aspects[0].text_is_1byte = true;
1919 	aspects[0].gcd = &boxes[6];
1920 
1921 	plabel[0].text = (unichar_t *) _("_Full Font Display");
1922 	plabel[0].text_is_1byte = true;
1923 	plabel[0].text_in_resource = true;
1924 	pgcd[0].gd.label = &plabel[0];
1925 	pgcd[0].gd.pos.x = 12; pgcd[0].gd.pos.y = 6;
1926 	pgcd[0].gd.flags = gg_visible | gg_enabled;
1927 	pgcd[0].gd.cid = CID_Display;
1928 	pgcd[0].gd.handle_controlevent = PRT_RadioSet;
1929 	pgcd[0].gd.popup_msg = _("Displays all the glyphs in the font on a rectangular grid at the given point size");
1930 	pgcd[0].creator = GRadioCreate;
1931 	varray3[0][0] = GCD_HPad10; varray3[0][1] = &pgcd[0]; varray3[0][2] = GCD_Glue; varray3[0][3] = NULL;
1932 
1933 	cnt = 1;
1934 	if ( fv!=NULL )
1935 	    cnt = FVSelCount(fv);
1936 	else if ( mv!=NULL )
1937 	    cnt = mv->glyphcnt;
1938 	plabel[1].text = (unichar_t *) (cnt==1?_("Full Pa_ge Glyph"):_("Full Pa_ge Glyphs"));
1939 	plabel[1].text_is_1byte = true;
1940 	plabel[1].text_in_resource = true;
1941 	pgcd[1].gd.label = &plabel[1];
1942 	pgcd[1].gd.flags = (cnt==0 ? (gg_visible): (gg_visible | gg_enabled));
1943 	pgcd[1].gd.cid = CID_Chars;
1944 	pgcd[1].gd.handle_controlevent = PRT_RadioSet;
1945 	pgcd[1].gd.popup_msg = _("Displays all the selected characters, each on its own page, at an extremely large point size");
1946 	pgcd[1].creator = GRadioCreate;
1947 	varray3[1][0] = GCD_HPad10; varray3[1][1] = &pgcd[1]; varray3[1][2] = GCD_Glue; varray3[1][3] = NULL;
1948 
1949 	plabel[2].text = (unichar_t *) (cnt==1?_("_Multi Size Glyph"):_("_Multi Size Glyphs"));
1950 	plabel[2].text_is_1byte = true;
1951 	plabel[2].text_in_resource = true;
1952 	pgcd[2].gd.label = &plabel[2];
1953 	pgcd[2].gd.flags = pgcd[1].gd.flags;
1954 	pgcd[2].gd.cid = CID_MultiSize;
1955 	pgcd[2].gd.handle_controlevent = PRT_RadioSet;
1956 	pgcd[2].gd.popup_msg = _("Displays all the selected characters, at several different point sizes");
1957 	pgcd[2].creator = GRadioCreate;
1958 
1959 	if ( pdefs[fromwindow].pt==pt_chars && cnt==0 )
1960 	    pdefs[fromwindow].pt = pt_fontdisplay;
1961 	if ( pdefs[fromwindow].pt == pt_fontsample )
1962 	    pgcd[pt_fontdisplay].gd.flags |= gg_cb_on;
1963 	else
1964 	    pgcd[pdefs[fromwindow].pt].gd.flags |= gg_cb_on;
1965 
1966 	varray3[2][0] = GCD_HPad10; varray3[2][1] = &pgcd[2]; varray3[2][2] = GCD_Glue; varray3[2][3] = NULL;
1967 	varray3[3][0] = NULL;
1968 
1969 	boxes[13].gd.flags = gg_enabled|gg_visible;
1970 	boxes[13].gd.u.boxelements = varray3[0];
1971 	boxes[13].creator = GHVBoxCreate;
1972 
1973 	plabel[3].text = (unichar_t *) _("_Pointsize:");
1974 	plabel[3].text_is_1byte = true;
1975 	plabel[3].text_in_resource = true;
1976 	pgcd[3].gd.label = &plabel[3];
1977 	pgcd[3].gd.flags = gg_visible | gg_enabled;
1978 	pgcd[3].gd.cid = CID_PSLab;
1979 	pgcd[3].creator = GLabelCreate;
1980 	ptarray[0] = &pgcd[3];
1981 
1982 	sprintf(sizebuf,"%d",active->pi.pointsize);
1983 	plabel[4].text = (unichar_t *) sizebuf;
1984 	plabel[4].text_is_1byte = true;
1985 	pgcd[4].gd.label = &plabel[4];
1986 	pgcd[4].gd.pos.width = 60;
1987 	pgcd[4].gd.flags = gg_visible | gg_enabled;
1988 	pgcd[4].gd.cid = CID_PointSize;
1989 	pgcd[4].creator = GNumericFieldCreate;
1990 	ptarray[1] = &pgcd[4]; ptarray[2] = GCD_Glue; ptarray[3] = NULL;
1991 
1992 	boxes[8].gd.flags = gg_enabled|gg_visible;
1993 	boxes[8].gd.u.boxelements = ptarray;
1994 	boxes[8].creator = GHBoxCreate;
1995 
1996 	varray4[0] = &boxes[13]; varray4[1] = &boxes[8]; varray4[2] = GCD_Glue; varray4[3] = NULL;
1997 	boxes[9].gd.flags = gg_enabled|gg_visible;
1998 	boxes[9].gd.u.boxelements = varray4;
1999 	boxes[9].creator = GVBoxCreate;
2000 
2001 	aspects[1].text = (unichar_t *) _("Print");
2002 	aspects[1].text_is_1byte = true;
2003 	aspects[1].gcd = &boxes[9];
2004 
2005 	mgcd[0].gd.pos.x = 4; mgcd[0].gd.pos.y = 6;
2006 	mgcd[0].gd.u.tabs = aspects;
2007 	mgcd[0].gd.flags = gg_visible | gg_enabled;
2008 	mgcd[0].gd.cid = CID_TabSet;
2009 	mgcd[0].creator = GTabSetCreate;
2010 
2011 	mgcd[1].gd.pos.width = -1; mgcd[1].gd.pos.height = 0;
2012 	mgcd[1].gd.flags = gg_visible | gg_enabled ;
2013 	mlabel[1].text = (unichar_t *) _("S_etup");
2014 	mlabel[1].text_is_1byte = true;
2015 	mlabel[1].text_in_resource = true;
2016 	mgcd[1].gd.label = &mlabel[1];
2017 	mgcd[1].gd.handle_controlevent = PRT_Setup;
2018 	mgcd[1].creator = GButtonCreate;
2019 	barray[0] = GCD_Glue; barray[1] = &mgcd[1]; barray[2] = GCD_Glue; barray[3] = NULL;
2020 
2021 	boxes[14].gd.flags = gg_enabled|gg_visible;
2022 	boxes[14].gd.u.boxelements = barray;
2023 	boxes[14].creator = GHBoxCreate;
2024 
2025 	mgcd[2].gd.pos.width = -1; mgcd[2].gd.pos.height = 0;
2026 	mgcd[2].gd.flags = gg_visible | gg_enabled | gg_but_default;
2027 	mlabel[2].text = (unichar_t *) _("_Print");
2028 	mlabel[2].text_is_1byte = true;
2029 	mlabel[2].text_in_resource = true;
2030 	mgcd[2].gd.mnemonic = 'O';
2031 	mgcd[2].gd.label = &mlabel[2];
2032 	mgcd[2].gd.handle_controlevent = PRT_OK;
2033 	mgcd[2].gd.cid = CID_OK;
2034 	mgcd[2].creator = GButtonCreate;
2035 
2036 	mgcd[3].gd.pos.width = -1; mgcd[3].gd.pos.height = 0;
2037 	mgcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
2038 	mlabel[3].text = (unichar_t *) _("_Done");
2039 	mlabel[3].text_is_1byte = true;
2040 	mlabel[3].text_in_resource = true;
2041 	mgcd[3].gd.label = &mlabel[3];
2042 	mgcd[3].gd.cid = CID_Cancel;
2043 	mgcd[3].gd.handle_controlevent = DSP_Done;
2044 	mgcd[3].creator = GButtonCreate;
2045 	barray2[0] = GCD_Glue; barray2[1] = &mgcd[2]; barray2[2] = GCD_Glue;
2046 	barray2[3] = GCD_Glue; barray2[4] = &mgcd[3]; barray2[5] = GCD_Glue; barray2[6] = NULL;
2047 
2048 	boxes[11].gd.flags = gg_enabled|gg_visible;
2049 	boxes[11].gd.u.boxelements = barray2;
2050 	boxes[11].creator = GHBoxCreate;
2051 
2052 	varray5[0][0] = &mgcd[0]; varray5[0][1] = NULL;
2053 	varray5[1][0] = &boxes[14]; varray5[1][1] = NULL;
2054 	varray5[2][0] = &boxes[11]; varray5[2][1] = NULL;
2055 	varray5[3][0] = NULL;
2056 
2057 	boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2058 	boxes[0].gd.flags = gg_enabled|gg_visible;
2059 	boxes[0].gd.u.boxelements = varray5[0];
2060 	boxes[0].gd.cid = CID_TopBox;
2061 	boxes[0].creator = GHVGroupCreate;
2062     } else {
2063 	tarray[0] = &boxes[6]; tarray[1] = NULL;
2064 
2065 	tgcd[0].gd.flags = fit_to_path==NULL ? gg_visible : (gg_visible | gg_enabled | gg_cb_on);
2066 	tlabel[0].text = (unichar_t *) _("Bind to Path");
2067 	tlabel[0].text_is_1byte = true;
2068 	tlabel[0].text_in_resource = true;
2069 	tgcd[0].gd.label = &tlabel[0];
2070 	tgcd[0].gd.handle_controlevent = PRT_Bind;
2071 	tgcd[0].gd.cid = CID_Bind;
2072 	tgcd[0].creator = GCheckBoxCreate;
2073 	patharray[0] = &tgcd[0]; patharray[1] = GCD_Glue;
2074 
2075 	if ( fit_to_path==NULL ) {
2076 	    tgcd[1].gd.flags = 0;
2077 	    strcpy(pathlen,"0");
2078 	} else {
2079 	    tgcd[1].gd.flags = gg_visible | gg_enabled;
2080 	    sprintf(pathlen, _("Path Length: %g"), PathLength(fit_to_path));
2081 	}
2082 	tlabel[1].text = (unichar_t *) pathlen;
2083 	tlabel[1].text_is_1byte = true;
2084 	tlabel[1].text_in_resource = true;
2085 	tgcd[1].gd.label = &tlabel[1];
2086 	tgcd[1].creator = GLabelCreate;
2087 	patharray[2] = &tgcd[1]; patharray[3] = NULL;
2088 
2089 	boxes[9].gd.flags = gg_enabled|gg_visible;
2090 	boxes[9].gd.u.boxelements = patharray;
2091 	boxes[9].creator = GHBoxCreate;
2092 	tarray[2] = &boxes[9]; tarray[3] = NULL;
2093 
2094 	tgcd[2].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled | gg_cb_on);
2095 	tlabel[2].text = (unichar_t *) _("Scale so text width matches path length");
2096 	tlabel[2].text_is_1byte = true;
2097 	tlabel[2].text_in_resource = true;
2098 	tgcd[2].gd.label = &tlabel[2];
2099 	tgcd[2].gd.cid = CID_Scale;
2100 	tgcd[2].creator = GCheckBoxCreate;
2101 	tarray[4] = &tgcd[2]; tarray[5] = NULL;
2102 
2103 	tgcd[3].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2104 	tlabel[3].text = (unichar_t *) _("Rotate each glyph as a unit");
2105 	tlabel[3].text_is_1byte = true;
2106 	tlabel[3].text_in_resource = true;
2107 	tgcd[3].gd.label = &tlabel[3];
2108 	tgcd[3].gd.cid = CID_GlyphAsUnit;
2109 	tgcd[3].creator = GCheckBoxCreate;
2110 	tarray[6] = &tgcd[3]; tarray[7] = NULL;
2111 
2112 	tgcd[4].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2113 	tlabel[4].text = (unichar_t *) _("Align:");
2114 	tlabel[4].text_is_1byte = true;
2115 	tlabel[4].text_in_resource = true;
2116 	tgcd[4].gd.label = &tlabel[4];
2117 	tgcd[4].creator = GLabelCreate;
2118 	alarray[0] = &tgcd[4];
2119 
2120 	tgcd[5].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled | gg_cb_on);
2121 	tlabel[5].text = (unichar_t *) _("At Start");
2122 	tlabel[5].text_is_1byte = true;
2123 	tlabel[5].text_in_resource = true;
2124 	tgcd[5].gd.label = &tlabel[5];
2125 	tgcd[5].gd.cid = CID_Start;
2126 	tgcd[5].creator = GRadioCreate;
2127 	alarray[1] = &tgcd[5];
2128 
2129 	tgcd[6].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2130 	tlabel[6].text = (unichar_t *) _("Centered");
2131 	tlabel[6].text_is_1byte = true;
2132 	tlabel[6].text_in_resource = true;
2133 	tgcd[6].gd.label = &tlabel[6];
2134 	tgcd[6].gd.cid = CID_Center;
2135 	tgcd[6].creator = GRadioCreate;
2136 	alarray[2] = &tgcd[6];
2137 
2138 	tgcd[7].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2139 	tlabel[7].text = (unichar_t *) _("At End");
2140 	tlabel[7].text_is_1byte = true;
2141 	tlabel[7].text_in_resource = true;
2142 	tgcd[7].gd.label = &tlabel[7];
2143 	tgcd[7].gd.cid = CID_End;
2144 	tgcd[7].creator = GRadioCreate;
2145 	alarray[3] = &tgcd[7];
2146 	alarray[4] = GCD_Glue; alarray[5] = NULL;
2147 
2148 	boxes[8].gd.flags = gg_enabled|gg_visible;
2149 	boxes[8].gd.u.boxelements = alarray;
2150 	boxes[8].creator = GHBoxCreate;
2151 	tarray[8] = &boxes[8]; tarray[9] = NULL;
2152 
2153 	tgcd[8].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2154 	tlabel[8].text = (unichar_t *) _("Offset text from path by:");
2155 	tlabel[8].text_is_1byte = true;
2156 	tlabel[8].text_in_resource = true;
2157 	tgcd[8].gd.label = &tlabel[8];
2158 	tgcd[8].creator = GLabelCreate;
2159 	oarray[0] = &tgcd[8];
2160 
2161 	tgcd[9].gd.flags = fit_to_path==NULL ? 0 : (gg_visible | gg_enabled);
2162 	tgcd[9].gd.pos.width = 60;
2163 	tlabel[9].text = (unichar_t *) "0";
2164 	tlabel[9].text_is_1byte = true;
2165 	tlabel[9].text_in_resource = true;
2166 	tgcd[9].gd.label = &tlabel[9];
2167 	tgcd[9].gd.cid = CID_YOffset;
2168 	tgcd[9].creator = GNumericFieldCreate;
2169 	oarray[1] = &tgcd[9]; oarray[2] = GCD_Glue; oarray[3] = NULL;
2170 
2171 	boxes[13].gd.flags = gg_enabled|gg_visible;
2172 	boxes[13].gd.u.boxelements = oarray;
2173 	boxes[13].creator = GHBoxCreate;
2174 	tarray[10] = &boxes[13]; tarray[11] = NULL;
2175 
2176 	tgcd[10].gd.flags = gg_visible | gg_enabled ;
2177 	tgcd[10].creator = GLineCreate;
2178 	tarray[12] = &tgcd[10]; tarray[13] = NULL;
2179 
2180 	tgcd[11].gd.pos.width = -1; tgcd[11].gd.pos.height = 0;
2181 	tgcd[11].gd.flags = gg_visible | gg_enabled | gg_but_default;
2182 	tlabel[11].text = (unichar_t *) _("_Insert");
2183 	tlabel[11].text_is_1byte = true;
2184 	tlabel[11].text_in_resource = true;
2185 	tgcd[11].gd.mnemonic = 'O';
2186 	tgcd[11].gd.label = &tlabel[11];
2187 	tgcd[11].gd.handle_controlevent = PRT_OK;
2188 	tgcd[11].gd.cid = CID_OK;
2189 	tgcd[11].creator = GButtonCreate;
2190 
2191 	tgcd[12].gd.pos.width = -1; tgcd[12].gd.pos.height = 0;
2192 	tgcd[12].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
2193 	tlabel[12].text = (unichar_t *) _("_Cancel");
2194 	tlabel[12].text_is_1byte = true;
2195 	tlabel[12].text_in_resource = true;
2196 	tgcd[12].gd.label = &tlabel[12];
2197 	tgcd[12].gd.cid = CID_Cancel;
2198 	tgcd[12].gd.handle_controlevent = DSP_Done;
2199 	tgcd[12].creator = GButtonCreate;
2200 	barray2[0] = GCD_Glue; barray2[1] = &tgcd[11]; barray2[2] = GCD_Glue;
2201 	barray2[3] = GCD_Glue; barray2[4] = &tgcd[12]; barray2[5] = GCD_Glue; barray2[6] = NULL;
2202 
2203 	boxes[11].gd.flags = gg_enabled|gg_visible;
2204 	boxes[11].gd.u.boxelements = barray2;
2205 	boxes[11].creator = GHBoxCreate;
2206 	tarray[14] = &boxes[11]; tarray[15] = NULL; tarray[16] = NULL;
2207 
2208 	boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2209 	boxes[0].gd.flags = gg_enabled|gg_visible;
2210 	boxes[0].gd.u.boxelements = tarray;
2211 	boxes[0].gd.cid = CID_TopBox;
2212 	boxes[0].creator = GHVGroupCreate;
2213     }
2214 
2215     GGadgetsCreate(active->gw,boxes);
2216     GListSetSBAlwaysVisible(gcd[11].ret,true);
2217     GListSetPopupCallback(gcd[11].ret,MV_FriendlyFeatures);
2218 
2219     GTextInfoListFree(gcd[0].gd.u.list);
2220     DSP_SetFont(active,true);
2221     if ( isprint ) {
2222 	SFTFSetDPI(gcd[13].ret,dpi);
2223 	temp = PrtBuildDef(sf,&((SFTextArea *) gcd[13].ret)->li,
2224 		(void (*)(void *, int, uint32, uint32))LayoutInfoInitLangSys);
2225 	GGadgetSetTitle(gcd[13].ret, temp);
2226 	free(temp);
2227     } else {
2228 	active->script_unknown = true;
2229 	if ( old_bind_text ) {
2230 	    SFTextAreaReplace(gcd[13].ret,old_bind_text);
2231 	    DSP_TextChanged(gcd[13].ret,NULL);
2232 	}
2233     }
2234     SFTFRegisterCallback(gcd[13].ret,active,DSP_ChangeFontCallback);
2235 
2236     GHVBoxSetExpandableRow(boxes[0].ret,0);
2237     GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
2238     GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
2239     GHVBoxSetExpandableRow(boxes[4].ret,gb_expandglue);
2240     GHVBoxSetExpandableCol(boxes[4].ret,gb_expandglue);
2241     GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue);
2242     GHVBoxSetExpandableRow(boxes[6].ret,1);
2243     GHVBoxSetExpandableCol(boxes[12].ret,gb_expandglue);
2244     GHVBoxSetExpandableCol(boxes[11].ret,gb_expandglue);
2245     GHVBoxSetExpandableRow(vbox.ret,gb_expandglue);
2246     if ( isprint ) {
2247 	GHVBoxSetExpandableCol(boxes[8].ret,gb_expandglue);
2248 	GHVBoxSetExpandableRow(boxes[9].ret,gb_expandglue);
2249 	GHVBoxSetExpandableCol(boxes[13].ret,gb_expandglue);
2250 	GHVBoxSetExpandableCol(boxes[14].ret,gb_expandglue);
2251     } else {
2252 	GHVBoxSetExpandableCol(boxes[8].ret,gb_expandglue);
2253 	GHVBoxSetExpandableRow(boxes[9].ret,gb_expandglue);
2254 	GHVBoxSetExpandableCol(boxes[13].ret,gb_expandglue);
2255     }
2256     GHVBoxFitWindow(boxes[0].ret);
2257 
2258     SFTextAreaSelect(gcd[13].ret,0,0);
2259     SFTextAreaShow(gcd[13].ret,0);
2260     SFTFProvokeCallback(gcd[13].ret);
2261     GWidgetIndicateFocusGadget(gcd[13].ret);
2262 
2263     GDrawSetVisible(active->gw,true);
2264     active->ready = true;
2265     if ( !isprint ) {
2266 	while ( !done )
2267 	    GDrawProcessOneEvent(NULL);
2268     }
2269 }
2270 
PrintFFDlg(FontView * fv,SplineChar * sc,MetricsView * mv)2271 void PrintFFDlg(FontView *fv,SplineChar *sc,MetricsView *mv) {
2272     _PrintFFDlg(fv,sc,mv,true,NULL,NULL);
2273 }
2274 
OnePathSelected(CharView * cv)2275 static SplineSet *OnePathSelected(CharView *cv) {
2276     RefChar *rf;
2277     SplineSet *ss, *sel=NULL;
2278     SplinePoint *sp;
2279 
2280     for ( ss = cv->b.layerheads[cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
2281 	for ( sp=ss->first; ; ) {
2282 	    if ( sp->selected ) {
2283 		if ( sel==NULL )
2284 		    sel = ss;
2285 		else if ( sel!=ss )
2286 return( NULL );
2287 	    }
2288 	    if ( sp->next==NULL )
2289 	break;
2290 	    sp = sp->next->to;
2291 	    if ( sp==ss->first )
2292 	break;
2293 	}
2294     }
2295     if ( sel==NULL )
2296 return( NULL );
2297 
2298     for ( rf = cv->b.layerheads[cv->b.drawmode]->refs; rf!=NULL; rf=rf->next ) {
2299 	if ( rf->selected )
2300 return( NULL );
2301     }
2302 return( sel );
2303 }
2304 
InsertTextDlg(CharView * cv)2305 void InsertTextDlg(CharView *cv) {
2306     _PrintFFDlg(NULL,cv->b.sc,NULL,false,cv,OnePathSelected(cv));
2307 }
2308 
PrintWindowClose(void)2309 void PrintWindowClose(void) {
2310     if ( printwindow!=NULL )
2311 	GDrawDestroyWindow(printwindow->gw);
2312 }
2313