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 "autosave.h"
31 #include "autotrace.h"
32 #include "autowidth.h"
33 #include "autowidth2.h"
34 #include "bitmapchar.h"
35 #include "bvedit.h"
36 #include "chardata.h"
37 #include "cvundoes.h"
38 #include "dumppfa.h"
39 #include "encoding.h"
40 #include "ffglib.h"
41 #include "fontforgeui.h"
42 #include "fvcomposite.h"
43 #include "fvfonts.h"
44 #include "gfile.h"
45 #include "gio.h"
46 #include "gkeysym.h"
47 #include "gresedit.h"
48 #include "gresource.h"
49 #include "groups.h"
50 #include "mm.h"
51 #include "namelist.h"
52 #include "nonlineartrans.h"
53 #include "psfont.h"
54 #include "pua.h"
55 #include "scripting.h"
56 #include "search.h"
57 #include "sfd.h"
58 #include "sfundo.h"
59 #include "splinefill.h"
60 #include "splinesaveafm.h"
61 #include "splineutil.h"
62 #include "splineutil2.h"
63 #include "tottfgpos.h"
64 #include "unicodelibinfo.h"
65 #include "ustring.h"
66 #include "utype.h"
67
68 #include <math.h>
69 #include <unistd.h>
70
71 #if defined (__MINGW32__)
72 #include <windows.h>
73 #endif
74
75 int OpenCharsInNewWindow = 0;
76 char *RecentFiles[RECENT_MAX] = { NULL };
77 int save_to_dir = 0; /* use sfdir rather than sfd */
78 unichar_t *script_menu_names[SCRIPT_MENU_MAX];
79 char *script_filenames[SCRIPT_MENU_MAX];
80 extern int onlycopydisplayed, copymetadata, copyttfinstr, add_char_to_name_list;
81 int home_char='A';
82 int compact_font_on_open=0;
83 int warn_script_unsaved = 0;
84 int navigation_mask = 0; /* Initialized in startui.c */
85
86 static char *fv_fontnames = MONO_UI_FAMILIES;
87 extern void python_call_onClosingFunctions();
88
89 #define FV_LAB_HEIGHT 15
90
91 #ifdef BIGICONS
92 #define fontview_width 32
93 #define fontview_height 32
94 static unsigned char fontview_bits[] = {
95 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00,
96 0x82, 0x20, 0x86, 0x08, 0x42, 0x21, 0x8a, 0x14, 0xc2, 0x21, 0x86, 0x04,
97 0x42, 0x21, 0x8a, 0x14, 0x42, 0x21, 0x86, 0x08, 0x02, 0x20, 0x80, 0x00,
98 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00, 0x82, 0xa0, 0x8f, 0x18,
99 0x82, 0x20, 0x91, 0x24, 0x42, 0x21, 0x91, 0x02, 0x42, 0x21, 0x91, 0x02,
100 0x22, 0x21, 0x8f, 0x02, 0xe2, 0x23, 0x91, 0x02, 0x12, 0x22, 0x91, 0x02,
101 0x3a, 0x27, 0x91, 0x24, 0x02, 0xa0, 0x8f, 0x18, 0x02, 0x20, 0x80, 0x00,
102 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00, 0x42, 0x20, 0x86, 0x18,
103 0xa2, 0x20, 0x8a, 0x04, 0xa2, 0x20, 0x86, 0x08, 0xa2, 0x20, 0x8a, 0x10,
104 0x42, 0x20, 0x8a, 0x0c, 0x82, 0x20, 0x80, 0x00, 0x02, 0x20, 0x80, 0x00,
105 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00};
106 #else
107 #define fontview2_width 16
108 #define fontview2_height 16
109 static unsigned char fontview2_bits[] = {
110 0x00, 0x07, 0x80, 0x08, 0x40, 0x17, 0x40, 0x15, 0x60, 0x09, 0x10, 0x02,
111 0xa0, 0x01, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x50, 0x00, 0x52, 0x00,
112 0x55, 0x00, 0x5d, 0x00, 0x22, 0x00, 0x1c, 0x00};
113 #endif
114
115 extern int _GScrollBar_Width;
116
117 static int fv_fontsize = 11, fv_fs_init=0;
118 static Color fvselcol = 0xffff00, fvselfgcol=0x000000;
119 Color view_bgcol;
120 static Color fvglyphinfocol = 0xff0000;
121 static Color fvemtpyslotfgcol = 0xd08080;
122 static Color fvchangedcol = 0x000060;
123 static Color fvhintingneededcol = 0x0000ff;
124
125 enum glyphlable { gl_glyph, gl_name, gl_unicode, gl_encoding };
126 int default_fv_showhmetrics=false, default_fv_showvmetrics=false,
127 default_fv_glyphlabel = gl_glyph;
128 #define METRICS_BASELINE 0x0000c0
129 #define METRICS_ORIGIN 0xc00000
130 #define METRICS_ADVANCE 0x008000
131 FontView *fv_list=NULL;
132
133
FV_ToggleCharChanged(SplineChar * sc)134 static void FV_ToggleCharChanged(SplineChar *sc) {
135 int i, j;
136 int pos;
137 FontView *fv;
138
139 for ( fv = (FontView *) (sc->parent->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
140 if ( fv->b.sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
141 continue;
142 if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
143 continue;
144 for ( pos=0; pos<fv->b.map->enccount; ++pos ) if ( fv->b.map->map[pos]==sc->orig_pos ) {
145 i = pos / fv->colcnt;
146 j = pos - i*fv->colcnt;
147 i -= fv->rowoff;
148 /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
149 /* but every now and then the WM forces us to use a window size which doesn't */
150 /* fit our expectations (maximized view) and we must be prepared for half */
151 /* lines */
152 if ( i>=0 && i<=fv->rowcnt ) {
153 GRect r;
154 r.x = j*fv->cbw+1; r.width = fv->cbw-1;
155 r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
156 GDrawRequestExpose(fv->v,&r,false);
157 }
158 }
159 }
160 }
161
FVMarkHintsOutOfDate(SplineChar * sc)162 void FVMarkHintsOutOfDate(SplineChar *sc) {
163 int i, j;
164 int pos;
165 FontView *fv;
166
167 if ( sc->parent->onlybitmaps || sc->parent->multilayer || sc->parent->strokedfont )
168 return;
169 for ( fv = (FontView *) (sc->parent->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
170 if ( fv->b.sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
171 continue;
172 if ( sc->layers[fv->b.active_layer].order2 )
173 continue;
174 if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
175 continue;
176 for ( pos=0; pos<fv->b.map->enccount; ++pos ) if ( fv->b.map->map[pos]==sc->orig_pos ) {
177 i = pos / fv->colcnt;
178 j = pos - i*fv->colcnt;
179 i -= fv->rowoff;
180 /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
181 /* but every now and then the WM forces us to use a window size which doesn't */
182 /* fit our expectations (maximized view) and we must be prepared for half */
183 /* lines */
184 if ( i>=0 && i<=fv->rowcnt ) {
185 GRect r;
186 r.x = j*fv->cbw+1; r.width = fv->cbw-1;
187 r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
188 GDrawDrawLine(fv->v,r.x,r.y,r.x,r.y+r.height-1,fvhintingneededcol);
189 GDrawDrawLine(fv->v,r.x+1,r.y,r.x+1,r.y+r.height-1,fvhintingneededcol);
190 GDrawDrawLine(fv->v,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,fvhintingneededcol);
191 GDrawDrawLine(fv->v,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,fvhintingneededcol);
192 }
193 }
194 }
195 }
196
FeatureTrans(FontView * fv,int enc)197 static int FeatureTrans(FontView *fv, int enc) {
198 SplineChar *sc;
199 PST *pst;
200 char *pt;
201 int gid;
202
203 if ( enc<0 || enc>=fv->b.map->enccount || (gid = fv->b.map->map[enc])==-1 )
204 return( -1 );
205 if ( fv->cur_subtable==NULL )
206 return( gid );
207
208 sc = fv->b.sf->glyphs[gid];
209 if ( sc==NULL )
210 return( -1 );
211 for ( pst = sc->possub; pst!=NULL; pst=pst->next ) {
212 if (( pst->type == pst_substitution || pst->type == pst_alternate ) &&
213 pst->subtable == fv->cur_subtable )
214 break;
215 }
216 if ( pst==NULL )
217 return( -1 );
218 pt = strchr(pst->u.subs.variant,' ');
219 if ( pt!=NULL )
220 *pt = '\0';
221 gid = SFFindExistingSlot(fv->b.sf, -1, pst->u.subs.variant );
222 if ( pt!=NULL )
223 *pt = ' ';
224 return( gid );
225 }
226
FVDrawGlyph(GWindow pixmap,FontView * fv,int index,int forcebg)227 static void FVDrawGlyph(GWindow pixmap, FontView *fv, int index, int forcebg ) {
228 GRect box, old2;
229 int feat_gid;
230 SplineChar *sc;
231 struct _GImage base;
232 GImage gi;
233 GClut clut;
234 int i,j;
235 int em = fv->b.sf->ascent+fv->b.sf->descent;
236 int yorg = fv->magnify*(fv->show->ascent);
237
238 i = index / fv->colcnt;
239 j = index - i*fv->colcnt;
240 i -= fv->rowoff;
241
242 if ( index<fv->b.map->enccount && (fv->b.selected[index] || forcebg)) {
243 box.x = j*fv->cbw+1; box.width = fv->cbw-1;
244 box.y = i*fv->cbh+fv->lab_height+1; box.height = fv->cbw;
245 GDrawFillRect(pixmap,&box,fv->b.selected[index] ? fvselcol : view_bgcol );
246 }
247 feat_gid = FeatureTrans(fv,index);
248 sc = feat_gid!=-1 ? fv->b.sf->glyphs[feat_gid]: NULL;
249 if ( !SCWorthOutputting(sc) ) {
250 int x = j*fv->cbw+1, xend = x+fv->cbw-2;
251 int y = i*fv->cbh+fv->lab_height+1, yend = y+fv->cbw-1;
252 GDrawDrawLine(pixmap,x,y,xend,yend,fvemtpyslotfgcol);
253 GDrawDrawLine(pixmap,x,yend,xend,y,fvemtpyslotfgcol);
254 }
255 if ( sc!=NULL ) {
256 BDFChar *bdfc;
257
258 if ( fv->show!=NULL && fv->show->piecemeal &&
259 feat_gid!=-1 &&
260 (feat_gid>=fv->show->glyphcnt || fv->show->glyphs[feat_gid]==NULL) &&
261 fv->b.sf->glyphs[feat_gid]!=NULL )
262 BDFPieceMeal(fv->show,feat_gid);
263
264 if ( fv->show!=NULL && feat_gid!=-1 &&
265 feat_gid < fv->show->glyphcnt &&
266 fv->show->glyphs[feat_gid]==NULL &&
267 SCWorthOutputting(fv->b.sf->glyphs[feat_gid]) ) {
268 /* If we have an outline but no bitmap for this slot */
269 box.x = j*fv->cbw+1; box.width = fv->cbw-2;
270 box.y = i*fv->cbh+fv->lab_height+2; box.height = box.width+1;
271 GDrawDrawRect(pixmap,&box,0xff0000);
272 ++box.x; ++box.y; box.width -= 2; box.height -= 2;
273 GDrawDrawRect(pixmap,&box,0xff0000);
274 /* When reencoding a font we can find times where index>=show->charcnt */
275 } else if ( fv->show!=NULL && feat_gid<fv->show->glyphcnt && feat_gid!=-1 &&
276 fv->show->glyphs[feat_gid]!=NULL ) {
277 /* If fontview is set to display an embedded bitmap font (not a temporary font, */
278 /* rasterized specially for this purpose), then we can't use it directly, as bitmap */
279 /* glyphs may contain selections and references. So create a temporary copy of */
280 /* the glyph merging all such elements into a single bitmap */
281 bdfc = fv->show->piecemeal ?
282 fv->show->glyphs[feat_gid] : BDFGetMergedChar( fv->show->glyphs[feat_gid] );
283
284 memset(&gi,'\0',sizeof(gi));
285 memset(&base,'\0',sizeof(base));
286 if ( bdfc->byte_data ) {
287 gi.u.image = &base;
288 base.image_type = it_index;
289 if ( !fv->b.selected[index] )
290 base.clut = fv->show->clut;
291 else {
292 int bgr=((fvselcol>>16)&0xff), bgg=((fvselcol>>8)&0xff), bgb= (fvselcol&0xff);
293 int fgr=((fvselfgcol>>16)&0xff), fgg=((fvselfgcol>>8)&0xff), fgb= (fvselfgcol&0xff);
294 int i;
295 memset(&clut,'\0',sizeof(clut));
296 base.clut = &clut;
297 clut.clut_len = fv->show->clut->clut_len;
298 for ( i=0; i<clut.clut_len; ++i ) {
299 clut.clut[i] =
300 COLOR_CREATE( bgr + (i*(fgr-bgr))/(clut.clut_len-1),
301 bgg + (i*(fgg-bgg))/(clut.clut_len-1),
302 bgb + (i*(fgb-bgb))/(clut.clut_len-1));
303 }
304 }
305 GDrawSetDither(NULL, false); /* on 8 bit displays we don't want any dithering */
306 } else {
307 memset(&clut,'\0',sizeof(clut));
308 gi.u.image = &base;
309 base.image_type = it_mono;
310 base.clut = &clut;
311 clut.clut_len = 2;
312 clut.clut[0] = fv->b.selected[index] ? fvselcol : view_bgcol ;
313 clut.clut[1] = fv->b.selected[index] ? fvselfgcol : 0 ;
314 }
315 base.trans = 0;
316 base.clut->trans_index = 0;
317
318 base.data = bdfc->bitmap;
319 base.bytes_per_line = bdfc->bytes_per_line;
320 base.width = bdfc->xmax-bdfc->xmin+1;
321 base.height = bdfc->ymax-bdfc->ymin+1;
322 box.x = j*fv->cbw; box.width = fv->cbw;
323 box.y = i*fv->cbh+fv->lab_height+1; box.height = box.width+1;
324 GDrawPushClip(pixmap,&box,&old2);
325 if ( !fv->b.sf->onlybitmaps && fv->show!=fv->filled &&
326 sc->layers[fv->b.active_layer].splines==NULL && sc->layers[fv->b.active_layer].refs==NULL &&
327 !sc->widthset &&
328 !(bdfc->xmax<=0 && bdfc->xmin==0 && bdfc->ymax<=0 && bdfc->ymax==0) ) {
329 /* If we have a bitmap but no outline character... */
330 GRect b;
331 b.x = box.x+1; b.y = box.y+1; b.width = box.width-2; b.height = box.height-2;
332 GDrawDrawRect(pixmap,&b,0x008000);
333 ++b.x; ++b.y; b.width -= 2; b.height -= 2;
334 GDrawDrawRect(pixmap,&b,0x008000);
335 }
336
337 // Keep centering consistent to bdfc->width. If base.width!=bdfc->width,
338 // the bitmap has likely been run through BCCompressBitmap. In this
339 // case, bdfc->xmin should represent the true offset from the origin
340 // to the first used column.
341 int xwidth = (bdfc->width != base.width) ? bdfc->width - bdfc->xmin*2 : base.width;
342
343 /* I assume that the bitmap image matches the bounding*/
344 /* box. In some bitmap fonts the bitmap has white space on the*/
345 /* right. This can throw off the centering algorithem */
346 if ( fv->magnify>1 ) {
347 GDrawDrawImageMagnified(pixmap,&gi,NULL,
348 j*fv->cbw+(fv->cbw-1-fv->magnify*xwidth)/2,
349 i*fv->cbh+fv->lab_height+1+fv->magnify*(fv->show->ascent-bdfc->ymax),
350 fv->magnify*base.width,fv->magnify*base.height);
351 } else if ( (GDrawHasCairo(pixmap)&gc_alpha) && base.image_type==it_index ) {
352 GDrawDrawGlyph(pixmap,&gi,NULL,
353 j*fv->cbw+(fv->cbw-1-xwidth)/2,
354 i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
355 } else
356 GDrawDrawImage(pixmap,&gi,NULL,
357 j*fv->cbw+(fv->cbw-1-xwidth)/2,
358 i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
359 if ( fv->showhmetrics ) {
360 int x1, x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*xwidth)/2- bdfc->xmin*fv->magnify;
361 /* Draw advance width & horizontal origin */
362 if ( fv->showhmetrics&fvm_origin )
363 GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+yorg-3,x0,
364 i*fv->cbh+fv->lab_height+yorg+2,METRICS_ORIGIN);
365 x1 = x0 + fv->magnify*bdfc->width;
366 if ( fv->showhmetrics&fvm_advanceat )
367 GDrawDrawLine(pixmap,x1,i*fv->cbh+fv->lab_height+1,x1,
368 (i+1)*fv->cbh-1,METRICS_ADVANCE);
369 if ( fv->showhmetrics&fvm_advanceto )
370 GDrawDrawLine(pixmap,x0,(i+1)*fv->cbh-2,x1,
371 (i+1)*fv->cbh-2,METRICS_ADVANCE);
372 }
373 if ( fv->showvmetrics ) {
374 int x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*xwidth)/2- bdfc->xmin*fv->magnify
375 + fv->magnify*fv->show->pixelsize/2;
376 int y0 = i*fv->cbh+fv->lab_height+yorg;
377 int yvw = y0 + fv->magnify*sc->vwidth*fv->show->pixelsize/em;
378 if ( fv->showvmetrics&fvm_baseline )
379 GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+1,x0,
380 (i+1)*fv->cbh-1,METRICS_BASELINE);
381 if ( fv->showvmetrics&fvm_advanceat )
382 GDrawDrawLine(pixmap,j*fv->cbw,yvw,(j+1)*fv->cbw,
383 yvw,METRICS_ADVANCE);
384 if ( fv->showvmetrics&fvm_advanceto )
385 GDrawDrawLine(pixmap,j*fv->cbw+2,y0,j*fv->cbw+2,
386 yvw,METRICS_ADVANCE);
387 if ( fv->showvmetrics&fvm_origin )
388 GDrawDrawLine(pixmap,x0-3,i*fv->cbh+fv->lab_height+yorg,x0+2,i*fv->cbh+fv->lab_height+yorg,METRICS_ORIGIN);
389 }
390 GDrawPopClip(pixmap,&old2);
391 if ( !fv->show->piecemeal ) BDFCharFree( bdfc );
392 }
393 }
394 }
395
FVToggleCharSelected(FontView * fv,int enc)396 static void FVToggleCharSelected(FontView *fv,int enc) {
397 int i, j;
398
399 if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
400 return;
401
402 i = enc / fv->colcnt;
403 j = enc - i*fv->colcnt;
404 i -= fv->rowoff;
405 /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
406 /* but every now and then the WM forces us to use a window size which doesn't */
407 /* fit our expectations (maximized view) and we must be prepared for half */
408 /* lines */
409 if ( i>=0 && i<=fv->rowcnt )
410 FVDrawGlyph(fv->v,fv,enc,true);
411 }
412
FontViewRefreshAll(SplineFont * sf)413 static void FontViewRefreshAll(SplineFont *sf) {
414 FontView *fv;
415 for ( fv = (FontView *) (sf->fv); fv!=NULL; fv = (FontView *) (fv->b.nextsame) )
416 if ( fv->v!=NULL )
417 GDrawRequestExpose(fv->v,NULL,false);
418 }
419
FVDeselectAll(FontView * fv)420 void FVDeselectAll(FontView *fv) {
421 int i;
422
423 for ( i=0; i<fv->b.map->enccount; ++i ) {
424 if ( fv->b.selected[i] ) {
425 fv->b.selected[i] = false;
426 FVToggleCharSelected(fv,i);
427 }
428 }
429 fv->sel_index = 0;
430 }
431
FVInvertSelection(FontView * fv)432 static void FVInvertSelection(FontView *fv) {
433 int i;
434
435 for ( i=0; i<fv->b.map->enccount; ++i ) {
436 fv->b.selected[i] = !fv->b.selected[i];
437 FVToggleCharSelected(fv,i);
438 }
439 fv->sel_index = 1;
440 }
441
FVSelectAll(FontView * fv)442 static void FVSelectAll(FontView *fv) {
443 int i;
444
445 for ( i=0; i<fv->b.map->enccount; ++i ) {
446 if ( !fv->b.selected[i] ) {
447 fv->b.selected[i] = true;
448 FVToggleCharSelected(fv,i);
449 }
450 }
451 fv->sel_index = 1;
452 }
453
FVReselect(FontView * fv,int newpos)454 static void FVReselect(FontView *fv, int newpos) {
455 int i;
456
457 if ( newpos<0 ) newpos = 0;
458 else if ( newpos>=fv->b.map->enccount ) newpos = fv->b.map->enccount-1;
459
460 if ( fv->pressed_pos<fv->end_pos ) {
461 if ( newpos>fv->end_pos ) {
462 for ( i=fv->end_pos+1; i<=newpos; ++i ) if ( !fv->b.selected[i] ) {
463 fv->b.selected[i] = fv->sel_index;
464 FVToggleCharSelected(fv,i);
465 }
466 } else if ( newpos<fv->pressed_pos ) {
467 for ( i=fv->end_pos; i>fv->pressed_pos; --i ) if ( fv->b.selected[i] ) {
468 fv->b.selected[i] = false;
469 FVToggleCharSelected(fv,i);
470 }
471 for ( i=fv->pressed_pos-1; i>=newpos; --i ) if ( !fv->b.selected[i] ) {
472 fv->b.selected[i] = fv->sel_index;
473 FVToggleCharSelected(fv,i);
474 }
475 } else {
476 for ( i=fv->end_pos; i>newpos; --i ) if ( fv->b.selected[i] ) {
477 fv->b.selected[i] = false;
478 FVToggleCharSelected(fv,i);
479 }
480 }
481 } else {
482 if ( newpos<fv->end_pos ) {
483 for ( i=fv->end_pos-1; i>=newpos; --i ) if ( !fv->b.selected[i] ) {
484 fv->b.selected[i] = fv->sel_index;
485 FVToggleCharSelected(fv,i);
486 }
487 } else if ( newpos>fv->pressed_pos ) {
488 for ( i=fv->end_pos; i<fv->pressed_pos; ++i ) if ( fv->b.selected[i] ) {
489 fv->b.selected[i] = false;
490 FVToggleCharSelected(fv,i);
491 }
492 for ( i=fv->pressed_pos+1; i<=newpos; ++i ) if ( !fv->b.selected[i] ) {
493 fv->b.selected[i] = fv->sel_index;
494 FVToggleCharSelected(fv,i);
495 }
496 } else {
497 for ( i=fv->end_pos; i<newpos; ++i ) if ( fv->b.selected[i] ) {
498 fv->b.selected[i] = false;
499 FVToggleCharSelected(fv,i);
500 }
501 }
502 }
503 fv->end_pos = newpos;
504 if ( newpos>=0 && newpos<fv->b.map->enccount && (i = fv->b.map->map[newpos])!=-1 &&
505 fv->b.sf->glyphs[i]!=NULL &&
506 fv->b.sf->glyphs[i]->unicodeenc>=0 && fv->b.sf->glyphs[i]->unicodeenc<0x10000 )
507 GInsCharSetChar(fv->b.sf->glyphs[i]->unicodeenc);
508 }
509
FVFlattenAllBitmapSelections(FontView * fv)510 static void FVFlattenAllBitmapSelections(FontView *fv) {
511 BDFFont *bdf;
512 int i;
513
514 for ( bdf = fv->b.sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
515 for ( i=0; i<bdf->glyphcnt; ++i )
516 if ( bdf->glyphs[i]!=NULL && bdf->glyphs[i]->selection!=NULL )
517 BCFlattenFloat(bdf->glyphs[i]);
518 }
519 }
520
AskChanged(SplineFont * sf)521 static int AskChanged(SplineFont *sf) {
522 int ret;
523 char *buts[4];
524 char *filename, *fontname;
525
526 if ( sf->cidmaster!=NULL )
527 sf = sf->cidmaster;
528
529 filename = sf->filename;
530 fontname = sf->fontname;
531
532 if ( filename==NULL && sf->origname!=NULL &&
533 sf->onlybitmaps && sf->bitmaps!=NULL && sf->bitmaps->next==NULL )
534 filename = sf->origname;
535 if ( filename==NULL ) filename = "untitled.sfd";
536 filename = GFileNameTail(filename);
537 buts[0] = _("_Save");
538 buts[1] = _("_Don't Save");
539 buts[2] = _("_Cancel");
540 buts[3] = NULL;
541 ret = gwwv_ask( _("Font changed"),(const char **) buts,0,2,_("Font %1$.40s in file %2$.40s has been changed.\nDo you want to save it?"),fontname,filename);
542 return( ret );
543 }
544
AskScriptChanged()545 static int AskScriptChanged() {
546 int ret;
547 char *buts[4];
548
549 buts[0] = _("_Yes");
550 buts[1] = _("Yes, and don't _remind me again");
551 buts[2] = _("_No");
552 buts[3] = NULL;
553 ret = gwwv_ask( _("Unsaved script"),(const char **) buts,0,2,_("You have an unsaved script in the «Execute Script» dialog. Do you intend to discard it?"));
554 if (ret == 1) {
555 warn_script_unsaved = 0;
556 SavePrefs(true);
557 }
558 return( ret );
559 }
560
_FVMenuGenerate(FontView * fv,int family)561 int _FVMenuGenerate(FontView *fv,int family) {
562 FVFlattenAllBitmapSelections(fv);
563 return( SFGenerateFont(fv->b.sf,fv->b.active_layer,family,fv->b.normal==NULL?fv->b.map:fv->b.normal) );
564 }
565
FVMenuGenerate(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))566 static void FVMenuGenerate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
567 FontView *fv = (FontView *) GDrawGetUserData(gw);
568
569 _FVMenuGenerate(fv,gf_none);
570 }
571
FVMenuGenerateFamily(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))572 static void FVMenuGenerateFamily(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
573 FontView *fv = (FontView *) GDrawGetUserData(gw);
574
575 _FVMenuGenerate(fv,gf_macfamily);
576 }
577
FVMenuGenerateTTC(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))578 static void FVMenuGenerateTTC(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
579 FontView *fv = (FontView *) GDrawGetUserData(gw);
580
581 _FVMenuGenerate(fv,gf_ttc);
582 }
583
584 extern int save_to_dir;
585
SaveAs_FormatChange(GGadget * g,GEvent * e)586 static int SaveAs_FormatChange(GGadget *g, GEvent *e) {
587 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
588 GGadget *fc = GWidgetGetControl(GGadgetGetWindow(g),1000);
589 char *oldname = GGadgetGetTitle8(fc);
590 int *_s2d = GGadgetGetUserData(g);
591 int s2d = GGadgetIsChecked(g);
592 char *pt, *newname = malloc(strlen(oldname)+8);
593 strcpy(newname,oldname);
594 pt = strrchr(newname,'.');
595 if ( pt==NULL )
596 pt = newname+strlen(newname);
597 strcpy(pt,s2d ? ".sfdir" : ".sfd" );
598 GGadgetSetTitle8(fc,newname);
599 save_to_dir = *_s2d = s2d;
600 SavePrefs(true);
601 }
602 return( true );
603 }
604
605
_FVSaveAsFilterFunc(GGadget * g,struct gdirentry * ent,const unichar_t * dir)606 static enum fchooserret _FVSaveAsFilterFunc(GGadget *g,struct gdirentry *ent, const unichar_t *dir)
607 {
608 char* n = u_to_c(ent->name);
609 int ew = endswithi( n, "sfd" ) || endswithi( n, "sfdir" );
610 if( ew )
611 return fc_show;
612 if( ent->isdir )
613 return fc_show;
614 return fc_hide;
615 }
616
617
_FVMenuSaveAs(FontView * fv)618 int _FVMenuSaveAs(FontView *fv) {
619 char *temp;
620 char *ret;
621 char *filename;
622 int ok;
623 int s2d = fv->b.cidmaster!=NULL ? fv->b.cidmaster->save_to_dir :
624 fv->b.sf->mm!=NULL ? fv->b.sf->mm->normal->save_to_dir :
625 fv->b.sf->save_to_dir;
626 GGadgetCreateData gcd;
627 GTextInfo label;
628
629 if ( fv->b.cidmaster!=NULL && fv->b.cidmaster->filename!=NULL )
630 temp=def2utf8_copy(fv->b.cidmaster->filename);
631 else if ( fv->b.sf->mm!=NULL && fv->b.sf->mm->normal->filename!=NULL )
632 temp=def2utf8_copy(fv->b.sf->mm->normal->filename);
633 else if ( fv->b.sf->filename!=NULL )
634 temp=def2utf8_copy(fv->b.sf->filename);
635 else {
636 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:
637 fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:fv->b.sf;
638 char *fn = sf->defbasefilename ? sf->defbasefilename : sf->fontname;
639 temp = malloc((strlen(fn)+10));
640 strcpy(temp,fn);
641 if ( sf->defbasefilename!=NULL )
642 /* Don't add a default suffix, they've already told us what name to use */;
643 else if ( fv->b.cidmaster!=NULL )
644 strcat(temp,"CID");
645 else if ( sf->mm==NULL )
646 ;
647 else if ( sf->mm->apple )
648 strcat(temp,"Var");
649 else
650 strcat(temp,"MM");
651 strcat(temp,save_to_dir ? ".sfdir" : ".sfd");
652 s2d = save_to_dir;
653 }
654
655 memset(&gcd,0,sizeof(gcd));
656 memset(&label,0,sizeof(label));
657 gcd.gd.flags = s2d ? (gg_visible | gg_enabled | gg_cb_on) : (gg_visible | gg_enabled);
658 label.text = (unichar_t *) _("Save as _Directory");
659 label.text_is_1byte = true;
660 label.text_in_resource = true;
661 gcd.gd.label = &label;
662 gcd.gd.handle_controlevent = SaveAs_FormatChange;
663 gcd.data = &s2d;
664 gcd.creator = GCheckBoxCreate;
665
666 GFileChooserInputFilenameFuncType FilenameFunc = GFileChooserDefInputFilenameFunc;
667
668 #if defined(__MINGW32__)
669 //
670 // If they are "saving as" but there is no path, lets help
671 // the poor user by starting someplace sane rather than in `pwd`
672 //
673 if( !GFileIsAbsolute(temp) )
674 {
675 char* defaultSaveDir = GFileGetHomeDocumentsDir();
676 // printf("save-as:%s\n", temp );
677 char* temp2 = GFileAppendFile( defaultSaveDir, temp, 0 );
678 free(temp);
679 temp = temp2;
680 }
681 #endif
682
683 ret = GWidgetSaveAsFileWithGadget8(_("Save as..."),temp,0,NULL,
684 _FVSaveAsFilterFunc, FilenameFunc,
685 &gcd );
686 free(temp);
687 if ( ret==NULL )
688 return( 0 );
689 filename = utf82def_copy(ret);
690 free(ret);
691
692 if(!(endswithi( filename, ".sfdir") || endswithi( filename, ".sfd")))
693 {
694 // they forgot the extension, so we force the default of .sfd
695 // and alert them to the fact that we have done this and we
696 // are not saving to a OTF, TTF, UFO formatted file
697
698 char* extension = ".sfd";
699 char* newpath = copyn( filename, strlen(filename) + strlen(".sfd") + 1 );
700 strcat( newpath, ".sfd" );
701
702 char* oldfn = GFileNameTail( filename );
703 char* newfn = GFileNameTail( newpath );
704
705 LogError( _("You tried to save with the filename %s but it was saved as %s. "),
706 oldfn, newfn );
707 LogError( _("Please choose File/Generate Fonts to save to other formats."));
708
709 free(filename);
710 filename = newpath;
711 }
712
713 FVFlattenAllBitmapSelections(fv);
714 fv->b.sf->compression = 0;
715 ok = SFDWrite(filename,fv->b.sf,fv->b.map,fv->b.normal,s2d);
716 if ( ok ) {
717 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:fv->b.sf;
718 free(sf->filename);
719 sf->filename = filename;
720 sf->save_to_dir = s2d;
721 free(sf->origname);
722 sf->origname = copy(filename);
723 sf->new = false;
724 if ( sf->mm!=NULL ) {
725 int i;
726 for ( i=0; i<sf->mm->instance_count; ++i ) {
727 free(sf->mm->instances[i]->filename);
728 sf->mm->instances[i]->filename = filename;
729 free(sf->mm->instances[i]->origname);
730 sf->mm->instances[i]->origname = copy(filename);
731 sf->mm->instances[i]->new = false;
732 }
733 }
734 SplineFontSetUnChanged(sf);
735 FVSetTitles(fv->b.sf);
736 } else {
737 ff_post_error(_("Save Failed"),_("Save Failed"));
738 free(filename);
739 }
740 return( ok );
741 }
742
FVMenuSaveAs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))743 static void FVMenuSaveAs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
744 FontView *fv = (FontView *) GDrawGetUserData(gw);
745
746 _FVMenuSaveAs(fv);
747 }
748
IsBackupName(char * filename)749 static int IsBackupName(char *filename) {
750
751 if ( filename==NULL )
752 return( false );
753 return( filename[strlen(filename)-1]=='~' );
754 }
755
_FVMenuSave(FontView * fv)756 int _FVMenuSave(FontView *fv) {
757 int ret = 0;
758 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:
759 fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:
760 fv->b.sf;
761
762 if ( sf->filename==NULL || IsBackupName(sf->filename))
763 ret = _FVMenuSaveAs(fv);
764 else {
765 FVFlattenAllBitmapSelections(fv);
766 if ( !SFDWriteBak(sf->filename,sf,fv->b.map,fv->b.normal) )
767 ff_post_error(_("Save Failed"),_("Save Failed"));
768 else {
769 SplineFontSetUnChanged(sf);
770 ret = true;
771 }
772 }
773 return( ret );
774 }
775
FVMenuSave(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))776 static void FVMenuSave(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
777 FontView *fv = (FontView *) GDrawGetUserData(gw);
778 _FVMenuSave(fv);
779 }
780
_FVCloseWindows(FontView * fv)781 void _FVCloseWindows(FontView *fv) {
782 int i, j;
783 BDFFont *bdf;
784 MetricsView *mv, *mnext;
785 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf->mm!=NULL?fv->b.sf->mm->normal : fv->b.sf;
786
787 PrintWindowClose();
788 if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b && fv->b.sf->kcld!=NULL )
789 KCLD_End(fv->b.sf->kcld);
790 if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b && fv->b.sf->vkcld!=NULL )
791 KCLD_End(fv->b.sf->vkcld);
792
793 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
794 CharView *cv, *next;
795 for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
796 next = (CharView *) (cv->b.next);
797 GDrawDestroyWindow(cv->gw);
798 }
799 if ( sf->glyphs[i]->charinfo )
800 CharInfoDestroy(sf->glyphs[i]->charinfo);
801 }
802 if ( sf->mm!=NULL ) {
803 MMSet *mm = sf->mm;
804 for ( j=0; j<mm->instance_count; ++j ) {
805 SplineFont *sf = mm->instances[j];
806 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
807 CharView *cv, *next;
808 for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
809 next = (CharView *) (cv->b.next);
810 GDrawDestroyWindow(cv->gw);
811 }
812 if ( sf->glyphs[i]->charinfo )
813 CharInfoDestroy(sf->glyphs[i]->charinfo);
814 }
815 for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
816 mnext = mv->next;
817 GDrawDestroyWindow(mv->gw);
818 }
819 }
820 } else if ( sf->subfontcnt!=0 ) {
821 for ( j=0; j<sf->subfontcnt; ++j ) {
822 for ( i=0; i<sf->subfonts[j]->glyphcnt; ++i ) if ( sf->subfonts[j]->glyphs[i]!=NULL ) {
823 CharView *cv, *next;
824 for ( cv = (CharView *) (sf->subfonts[j]->glyphs[i]->views); cv!=NULL; cv = next ) {
825 next = (CharView *) (cv->b.next);
826 GDrawDestroyWindow(cv->gw);
827 if ( sf->subfonts[j]->glyphs[i]->charinfo )
828 CharInfoDestroy(sf->subfonts[j]->glyphs[i]->charinfo);
829 }
830 }
831 for ( mv=sf->subfonts[j]->metrics; mv!=NULL; mv = mnext ) {
832 mnext = mv->next;
833 GDrawDestroyWindow(mv->gw);
834 }
835 }
836 } else {
837 for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
838 mnext = mv->next;
839 GDrawDestroyWindow(mv->gw);
840 }
841 }
842 for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
843 for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
844 BitmapView *bv, *next;
845 for ( bv = bdf->glyphs[i]->views; bv!=NULL; bv = next ) {
846 next = bv->next;
847 GDrawDestroyWindow(bv->gw);
848 }
849 }
850 }
851 if ( fv->b.sf->fontinfo!=NULL )
852 FontInfoDestroy(fv->b.sf);
853 if ( fv->b.sf->valwin!=NULL )
854 ValidationDestroy(fv->b.sf);
855 SVDetachFV(fv);
856 }
857
SFAnyChanged(SplineFont * sf)858 static int SFAnyChanged(SplineFont *sf) {
859 if ( sf->mm!=NULL ) {
860 MMSet *mm = sf->mm;
861 int i;
862 if ( mm->changed )
863 return( true );
864 for ( i=0; i<mm->instance_count; ++i )
865 if ( sf->mm->instances[i]->changed )
866 return( true );
867 /* Changes to the blended font aren't real (for adobe fonts) */
868 if ( mm->apple && mm->normal->changed )
869 return( true );
870
871 return( false );
872 } else
873 return( sf->changed );
874 }
875
_FVMenuClose(FontView * fv)876 static int _FVMenuClose(FontView *fv) {
877 int i;
878 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf;
879
880 if ( !SFCloseAllInstrs(fv->b.sf) )
881 return( false );
882
883 if ( fv->b.nextsame!=NULL || fv->b.sf->fv!=&fv->b ) {
884 /* There's another view, can close this one with no problems */
885 } else if ( warn_script_unsaved && fv->script_unsaved &&
886 AskScriptChanged()==2 ) {
887 return false;
888 } else if ( SFAnyChanged(sf) ) {
889 i = AskChanged(fv->b.sf);
890 if ( i==2 ) /* Cancel */
891 return( false );
892 if ( i==0 && !_FVMenuSave(fv)) /* Save */
893 return(false);
894 else
895 SFClearAutoSave(sf); /* if they didn't save it, remove change record */
896 }
897 _FVCloseWindows(fv);
898 if ( sf->filename!=NULL )
899 RecentFilesRemember(sf->filename);
900 else if ( sf->origname!=NULL )
901 RecentFilesRemember(sf->origname);
902 GDrawDestroyWindow(fv->gw);
903 return( true );
904 }
905
MenuNew(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))906 void MenuNew(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
907 FontNew();
908 }
909
FVMenuClose(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))910 static void FVMenuClose(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
911 FontView *fv = (FontView *) GDrawGetUserData(gw);
912
913 if ( fv->b.container )
914 (fv->b.container->funcs->doClose)(fv->b.container);
915 else
916 _FVMenuClose(fv);
917 }
918
FV_ReattachCVs(SplineFont * old,SplineFont * new)919 static void FV_ReattachCVs(SplineFont *old,SplineFont *new) {
920 int i, j, pos;
921 CharView *cv, *cvnext;
922 SplineFont *sub;
923
924 for ( i=0; i<old->glyphcnt; ++i ) {
925 if ( old->glyphs[i]!=NULL && old->glyphs[i]->views!=NULL ) {
926 if ( new->subfontcnt==0 ) {
927 pos = SFFindExistingSlot(new,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
928 sub = new;
929 } else {
930 pos = -1;
931 for ( j=0; j<new->subfontcnt && pos==-1 ; ++j ) {
932 sub = new->subfonts[j];
933 pos = SFFindExistingSlot(sub,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
934 }
935 }
936 if ( pos==-1 ) {
937 for ( cv=(CharView *) (old->glyphs[i]->views); cv!=NULL; cv = cvnext ) {
938 cvnext = (CharView *) (cv->b.next);
939 GDrawDestroyWindow(cv->gw);
940 }
941 } else {
942 for ( cv=(CharView *) (old->glyphs[i]->views); cv!=NULL; cv = cvnext ) {
943 cvnext = (CharView *) (cv->b.next);
944 CVChangeSC(cv,sub->glyphs[pos]);
945 cv->b.layerheads[dm_grid] = &new->grid;
946 }
947 }
948 GDrawProcessPendingEvents(NULL); /* Don't want to many destroy_notify events clogging up the queue */
949 }
950 }
951 }
952
FVMenuRevert(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))953 static void FVMenuRevert(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
954 FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
955 FVRevert(fv);
956 }
957
FVMenuRevertBackup(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))958 static void FVMenuRevertBackup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
959 FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
960 FVRevertBackup(fv);
961 }
962
FVMenuRevertGlyph(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))963 static void FVMenuRevertGlyph(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
964 FontView *fv = (FontView *) GDrawGetUserData(gw);
965 FVRevertGlyph((FontViewBase *) fv);
966 }
967
FVMenuClearSpecialData(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))968 static void FVMenuClearSpecialData(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
969 FontView *fv = (FontView *) GDrawGetUserData(gw);
970 FVClearSpecialData((FontViewBase *) fv);
971 }
972
MenuPrefs(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))973 void MenuPrefs(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
974 DoPrefs();
975 }
976
MenuXRes(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))977 void MenuXRes(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
978 DoXRes();
979 }
980
MenuSaveAll(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))981 void MenuSaveAll(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
982 FontView *fv;
983
984 for ( fv = fv_list; fv!=NULL; fv = (FontView *) (fv->b.next) ) {
985 if ( SFAnyChanged(fv->b.sf) && !_FVMenuSave(fv))
986 return;
987 }
988 }
989
_MenuExit(void * UNUSED (junk))990 static void _MenuExit(void *UNUSED(junk)) {
991
992 FontView *fv, *next;
993
994 #ifndef _NO_PYTHON
995 python_call_onClosingFunctions();
996 #endif
997
998 LastFonts_Save();
999 for ( fv = fv_list; fv!=NULL; fv = next )
1000 {
1001 next = (FontView *) (fv->b.next);
1002 if ( !_FVMenuClose(fv))
1003 return;
1004 if ( fv->b.nextsame!=NULL || fv->b.sf->fv!=&fv->b )
1005 {
1006 GDrawSync(NULL);
1007 GDrawProcessPendingEvents(NULL);
1008 }
1009 }
1010 GDrawSync(NULL);
1011 GDrawProcessPendingEvents(NULL);
1012 exit(0);
1013 }
1014
FVMenuExit(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1015 static void FVMenuExit(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1016 _MenuExit(NULL);
1017 }
1018
MenuExit(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * e)1019 void MenuExit(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *e) {
1020 if ( e==NULL ) /* Not from the menu directly, but a shortcut */
1021 _MenuExit(NULL);
1022 else
1023 DelayEvent(_MenuExit,NULL);
1024 }
1025
MergeKernInfo(SplineFont * sf,EncMap * map)1026 void MergeKernInfo(SplineFont *sf,EncMap *map) {
1027 #ifndef __Mac
1028 static char wild[] = "*.{afm,tfm,ofm,pfm,bin,hqx,dfont,feature,feat,fea}";
1029 static char wild2[] = "*.{afm,amfm,tfm,ofm,pfm,bin,hqx,dfont,feature,feat,fea}";
1030 #else
1031 static char wild[] = "*"; /* Mac resource files generally don't have extensions */
1032 static char wild2[] = "*";
1033 #endif
1034 char *ret = gwwv_open_filename(_("Merge Feature Info"),NULL,
1035 sf->mm!=NULL?wild2:wild,NULL);
1036 char *temp;
1037
1038 if ( ret==NULL )
1039 return; /* Cancelled */
1040 temp = utf82def_copy(ret);
1041
1042 if ( !LoadKerningDataFromMetricsFile(sf,temp,map))
1043 ff_post_error(_("Load of Kerning Metrics Failed"),_("Failed to load kern data from %s"), temp);
1044 free(ret); free(temp);
1045 }
1046
FVMenuMergeKern(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1047 static void FVMenuMergeKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1048 FontView *fv = (FontView *) GDrawGetUserData(gw);
1049 MergeKernInfo(fv->b.sf,fv->b.map);
1050 }
1051
_FVMenuOpen(FontView * fv)1052 void _FVMenuOpen(FontView *fv) {
1053 char *temp;
1054 char *eod, *fpt, *file, *full;
1055 FontView *test; int fvcnt, fvtest;
1056
1057 char* OpenDir = NULL, *DefaultDir = NULL, *NewDir = NULL;
1058 #if defined(__MINGW32__)
1059 DefaultDir = copy(GFileGetHomeDocumentsDir()); //Default value
1060 if (fv && fv->b.sf && fv->b.sf->filename) {
1061 free(DefaultDir);
1062 DefaultDir = GFileDirNameEx(fv->b.sf->filename, true);
1063 }
1064 #endif
1065
1066 for ( fvcnt=0, test=fv_list; test!=NULL; ++fvcnt, test=(FontView *) (test->b.next) );
1067 do {
1068 if (NewDir != NULL) {
1069 if (OpenDir != DefaultDir) {
1070 free(OpenDir);
1071 }
1072
1073 OpenDir = NewDir;
1074 NewDir = NULL;
1075 } else if (OpenDir != DefaultDir) {
1076 free(OpenDir);
1077 OpenDir = DefaultDir;
1078 }
1079
1080 temp = GetPostScriptFontName(OpenDir,true,fv != NULL);
1081 if ( temp==NULL )
1082 return;
1083
1084 //Make a copy of the folder; may be needed later if opening fails.
1085 NewDir = GFileDirName(temp);
1086 if (!GFileExists(NewDir)) {
1087 free(NewDir);
1088 NewDir = NULL;
1089 }
1090
1091 eod = strrchr(temp,'/');
1092 if (eod != NULL) {
1093 *eod = '\0';
1094 file = eod+1;
1095
1096 if (*file) {
1097 do {
1098 fpt = strstr(file,"; ");
1099 if ( fpt!=NULL ) *fpt = '\0';
1100 full = malloc(strlen(temp)+1+strlen(file)+1);
1101 strcpy(full,temp); strcat(full,"/"); strcat(full,file);
1102 ViewPostScriptFont(full,0);
1103 file = fpt+2;
1104 free(full);
1105 } while ( fpt!=NULL );
1106 }
1107 }
1108 free(temp);
1109 for ( fvtest=0, test=fv_list; test!=NULL; ++fvtest, test=(FontView *) (test->b.next) );
1110 } while ( fvtest==fvcnt ); /* did the load fail for some reason? try again */
1111
1112 free( NewDir );
1113 free( OpenDir );
1114 if (OpenDir != DefaultDir) {
1115 free( DefaultDir );
1116 }
1117 }
1118
FVMenuOpen(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1119 static void FVMenuOpen(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1120 FontView *fv = (FontView*) GDrawGetUserData(gw);
1121 _FVMenuOpen(fv);
1122 }
1123
FVMenuContextualHelp(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1124 static void FVMenuContextualHelp(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1125 help("ui/mainviews/fontview.html", NULL);
1126 }
1127
MenuHelp(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1128 void MenuHelp(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1129 help("index.html", NULL);
1130 }
1131
MenuIndex(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1132 void MenuIndex(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1133 help("index.html", NULL);
1134 }
1135
MenuLicense(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1136 void MenuLicense(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1137 help("https://github.com/fontforge/fontforge/blob/master/LICENSE", NULL);
1138 }
1139
MenuAbout(GWindow UNUSED (base),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1140 void MenuAbout(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1141 ShowAboutScreen();
1142 }
1143
FVMenuImport(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1144 static void FVMenuImport(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1145 FontView *fv = (FontView *) GDrawGetUserData(gw);
1146 int empty = fv->b.sf->onlybitmaps && fv->b.sf->bitmaps==NULL;
1147 BDFFont *bdf;
1148 FVImport(fv);
1149 if ( empty && fv->b.sf->bitmaps!=NULL ) {
1150 for ( bdf= fv->b.sf->bitmaps; bdf->next!=NULL; bdf = bdf->next );
1151 FVChangeDisplayBitmap((FontViewBase *) fv,bdf);
1152 }
1153 }
1154
FVSelCount(FontView * fv)1155 static int FVSelCount(FontView *fv) {
1156 int i, cnt=0;
1157
1158 for ( i=0; i<fv->b.map->enccount; ++i )
1159 if ( fv->b.selected[i] ) ++cnt;
1160 if ( cnt>10 ) {
1161 char *buts[3];
1162 buts[0] = _("_OK");
1163 buts[1] = _("_Cancel");
1164 buts[2] = NULL;
1165 if ( gwwv_ask(_("Many Windows"),(const char **) buts,0,1,_("This involves opening more than 10 windows.\nIs that really what you want?"))==1 )
1166 return( false );
1167 }
1168 return( true );
1169 }
1170
FVMenuOpenOutline(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1171 static void FVMenuOpenOutline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1172 FontView *fv = (FontView *) GDrawGetUserData(gw);
1173 int i;
1174 SplineChar *sc;
1175
1176 if ( !FVSelCount(fv))
1177 return;
1178 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1179 return;
1180
1181 for ( i=0; i<fv->b.map->enccount; ++i )
1182 if ( fv->b.selected[i] ) {
1183 sc = FVMakeChar(fv,i);
1184 CharViewCreate(sc,fv,i);
1185 }
1186 }
1187
FVMenuOpenBitmap(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1188 static void FVMenuOpenBitmap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1189 FontView *fv = (FontView *) GDrawGetUserData(gw);
1190 int i;
1191 SplineChar *sc;
1192
1193 if ( fv->b.cidmaster==NULL ? (fv->b.sf->bitmaps==NULL) : (fv->b.cidmaster->bitmaps==NULL) )
1194 return;
1195 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1196 return;
1197 if ( !FVSelCount(fv))
1198 return;
1199 for ( i=0; i<fv->b.map->enccount; ++i )
1200 if ( fv->b.selected[i] ) {
1201 sc = FVMakeChar(fv,i);
1202 if ( sc!=NULL )
1203 BitmapViewCreatePick(i,fv);
1204 }
1205 }
1206
_MenuWarnings(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1207 void _MenuWarnings(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1208 ShowErrorWindow();
1209 }
1210
FVMenuOpenMetrics(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1211 static void FVMenuOpenMetrics(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1212 FontView *fv = (FontView *) GDrawGetUserData(gw);
1213 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1214 return;
1215 MetricsViewCreate(fv,NULL,fv->filled==fv->show?NULL:fv->show);
1216 }
1217
FVMenuPrint(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1218 static void FVMenuPrint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1219 FontView *fv = (FontView *) GDrawGetUserData(gw);
1220
1221 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1222 return;
1223 PrintFFDlg(fv,NULL,NULL);
1224 }
1225
1226 #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
FVMenuExecute(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1227 static void FVMenuExecute(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1228 FontView *fv = (FontView *) GDrawGetUserData(gw);
1229
1230 ScriptDlg(fv,NULL);
1231 }
1232 #endif
1233
FVMenuFontInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1234 static void FVMenuFontInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1235 FontView *fv = (FontView *) GDrawGetUserData(gw);
1236 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1237 return;
1238 FontMenuFontInfo(fv);
1239 }
1240
FVMenuMATHInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1241 static void FVMenuMATHInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1242 FontView *fv = (FontView *) GDrawGetUserData(gw);
1243 SFMathDlg(fv->b.sf,fv->b.active_layer);
1244 }
1245
FVMenuFindProblems(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1246 static void FVMenuFindProblems(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1247 FontView *fv = (FontView *) GDrawGetUserData(gw);
1248 FindProblems(fv,NULL,NULL);
1249 }
1250
FVMenuValidate(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1251 static void FVMenuValidate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1252 FontView *fv = (FontView *) GDrawGetUserData(gw);
1253 SFValidationWindow(fv->b.sf,fv->b.active_layer,ff_none);
1254 }
1255
FVMenuSetExtremumBound(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1256 static void FVMenuSetExtremumBound(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1257 FontView *fv = (FontView *) GDrawGetUserData(gw);
1258 char buffer[40], *end, *ret;
1259 int val;
1260
1261 sprintf( buffer, "%d", fv->b.sf->extrema_bound<=0 ?
1262 (int) rint((fv->b.sf->ascent+fv->b.sf->descent)/100.0) :
1263 fv->b.sf->extrema_bound );
1264 ret = gwwv_ask_string(_("Extremum bound..."),buffer,_("Adobe says that \"big\" splines should not have extrema.\nBut they don't define what big means.\nIf the distance between the spline's end-points is bigger than this value, then the spline is \"big\" to fontforge."));
1265 if ( ret==NULL )
1266 return;
1267 val = (int) rint(strtod(ret,&end));
1268 if ( *end!='\0' )
1269 ff_post_error( _("Bad Number"),_("Bad Number") );
1270 else {
1271 fv->b.sf->extrema_bound = val;
1272 if ( !fv->b.sf->changed ) {
1273 fv->b.sf->changed = true;
1274 FVSetTitles(fv->b.sf);
1275 }
1276 }
1277 free(ret);
1278 }
1279
FVMenuEmbolden(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1280 static void FVMenuEmbolden(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1281 FontView *fv = (FontView *) GDrawGetUserData(gw);
1282 EmboldenDlg(fv,NULL);
1283 }
1284
FVMenuItalic(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1285 static void FVMenuItalic(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1286 FontView *fv = (FontView *) GDrawGetUserData(gw);
1287 ItalicDlg(fv,NULL);
1288 }
1289
FVMenuSmallCaps(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1290 static void FVMenuSmallCaps(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1291 FontView *fv = (FontView *) GDrawGetUserData(gw);
1292 GlyphChangeDlg(fv,NULL,gc_smallcaps);
1293 }
1294
FVMenuChangeXHeight(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1295 static void FVMenuChangeXHeight(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1296 FontView *fv = (FontView *) GDrawGetUserData(gw);
1297 ChangeXHeightDlg(fv,NULL);
1298 }
1299
FVMenuChangeGlyph(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1300 static void FVMenuChangeGlyph(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1301 FontView *fv = (FontView *) GDrawGetUserData(gw);
1302 GlyphChangeDlg(fv,NULL,gc_generic);
1303 }
1304
FVMenuSubSup(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1305 static void FVMenuSubSup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1306 FontView *fv = (FontView *) GDrawGetUserData(gw);
1307 GlyphChangeDlg(fv,NULL,gc_subsuper);
1308 }
1309
FVMenuOblique(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1310 static void FVMenuOblique(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1311 FontView *fv = (FontView *) GDrawGetUserData(gw);
1312 ObliqueDlg(fv,NULL);
1313 }
1314
FVMenuCondense(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1315 static void FVMenuCondense(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1316 FontView *fv = (FontView *) GDrawGetUserData(gw);
1317 CondenseExtendDlg(fv,NULL);
1318 }
1319
1320 #define MID_24 2001
1321 #define MID_36 2002
1322 #define MID_48 2004
1323 #define MID_72 2014
1324 #define MID_96 2015
1325 #define MID_128 2018
1326 #define MID_AntiAlias 2005
1327 #define MID_Next 2006
1328 #define MID_Prev 2007
1329 #define MID_NextDef 2012
1330 #define MID_PrevDef 2013
1331 #define MID_ShowHMetrics 2016
1332 #define MID_ShowVMetrics 2017
1333 #define MID_Ligatures 2020
1334 #define MID_KernPairs 2021
1335 #define MID_AnchorPairs 2022
1336 #define MID_FitToBbox 2023
1337 #define MID_DisplaySubs 2024
1338 #define MID_32x8 2025
1339 #define MID_16x4 2026
1340 #define MID_8x2 2027
1341 #define MID_BitmapMag 2028
1342 #define MID_Layers 2029
1343 #define MID_FontInfo 2200
1344 #define MID_CharInfo 2201
1345 #define MID_Transform 2202
1346 #define MID_Stroke 2203
1347 #define MID_RmOverlap 2204
1348 #define MID_Simplify 2205
1349 #define MID_Correct 2206
1350 #define MID_BuildAccent 2208
1351 #define MID_AvailBitmaps 2210
1352 #define MID_RegenBitmaps 2211
1353 #define MID_Autotrace 2212
1354 #define MID_Round 2213
1355 #define MID_MergeFonts 2214
1356 #define MID_InterpolateFonts 2215
1357 #define MID_FindProblems 2216
1358 #define MID_Embolden 2217
1359 #define MID_Condense 2218
1360 #define MID_ShowDependentRefs 2222
1361 #define MID_AddExtrema 2224
1362 #define MID_CleanupGlyph 2225
1363 #define MID_TilePath 2226
1364 #define MID_BuildComposite 2227
1365 #define MID_NLTransform 2228
1366 #define MID_Intersection 2229
1367 #define MID_FindInter 2230
1368 #define MID_Styles 2231
1369 #define MID_SimplifyMore 2233
1370 #define MID_ShowDependentSubs 2234
1371 #define MID_DefaultATT 2235
1372 #define MID_POV 2236
1373 #define MID_BuildDuplicates 2237
1374 #define MID_StrikeInfo 2238
1375 #define MID_FontCompare 2239
1376 #define MID_CanonicalStart 2242
1377 #define MID_CanonicalContours 2243
1378 #define MID_RemoveBitmaps 2244
1379 #define MID_Validate 2245
1380 #define MID_MassRename 2246
1381 #define MID_Italic 2247
1382 #define MID_SmallCaps 2248
1383 #define MID_SubSup 2249
1384 #define MID_ChangeXHeight 2250
1385 #define MID_ChangeGlyph 2251
1386 #define MID_SetColor 2252
1387 #define MID_SetExtremumBound 2253
1388 #define MID_Center 2600
1389 #define MID_Thirds 2601
1390 #define MID_SetWidth 2602
1391 #define MID_SetLBearing 2603
1392 #define MID_SetRBearing 2604
1393 #define MID_SetVWidth 2605
1394 #define MID_RmHKern 2606
1395 #define MID_RmVKern 2607
1396 #define MID_VKernByClass 2608
1397 #define MID_VKernFromH 2609
1398 #define MID_SetBearings 2610
1399 #define MID_AutoHint 2501
1400 #define MID_ClearHints 2502
1401 #define MID_ClearWidthMD 2503
1402 #define MID_AutoInstr 2504
1403 #define MID_EditInstructions 2505
1404 #define MID_Editfpgm 2506
1405 #define MID_Editprep 2507
1406 #define MID_ClearInstrs 2508
1407 #define MID_HStemHist 2509
1408 #define MID_VStemHist 2510
1409 #define MID_BlueValuesHist 2511
1410 #define MID_Editcvt 2512
1411 #define MID_HintSubsPt 2513
1412 #define MID_AutoCounter 2514
1413 #define MID_DontAutoHint 2515
1414 #define MID_RmInstrTables 2516
1415 #define MID_Editmaxp 2517
1416 #define MID_Deltas 2518
1417 #define MID_OpenBitmap 2700
1418 #define MID_OpenOutline 2701
1419 #define MID_Revert 2702
1420 #define MID_Recent 2703
1421 #define MID_Print 2704
1422 #define MID_ScriptMenu 2705
1423 #define MID_RevertGlyph 2707
1424 #define MID_RevertToBackup 2708
1425 #define MID_GenerateTTC 2709
1426 #define MID_OpenMetrics 2710
1427 #define MID_ClearSpecialData 2711
1428 #define MID_Cut 2101
1429 #define MID_Copy 2102
1430 #define MID_Paste 2103
1431 #define MID_Clear 2104
1432 #define MID_SelAll 2106
1433 #define MID_CopyRef 2107
1434 #define MID_UnlinkRef 2108
1435 #define MID_Undo 2109
1436 #define MID_Redo 2110
1437 #define MID_CopyWidth 2111
1438 #define MID_UndoFontLevel 2112
1439 #define MID_AllFonts 2122
1440 #define MID_DisplayedFont 2123
1441 #define MID_CharName 2124
1442 #define MID_RemoveUndoes 2114
1443 #define MID_CopyFgToBg 2115
1444 #define MID_ClearBackground 2116
1445 #define MID_CopyLBearing 2125
1446 #define MID_CopyRBearing 2126
1447 #define MID_CopyVWidth 2127
1448 #define MID_Join 2128
1449 #define MID_PasteInto 2129
1450 #define MID_SameGlyphAs 2130
1451 #define MID_RplRef 2131
1452 #define MID_PasteAfter 2132
1453 #define MID_TTFInstr 2134
1454 #define MID_CopyLookupData 2135
1455 #define MID_CopyL2L 2136
1456 #define MID_CorrectRefs 2137
1457 #define MID_Convert2CID 2800
1458 #define MID_Flatten 2801
1459 #define MID_InsertFont 2802
1460 #define MID_InsertBlank 2803
1461 #define MID_CIDFontInfo 2804
1462 #define MID_RemoveFromCID 2805
1463 #define MID_ConvertByCMap 2806
1464 #define MID_FlattenByCMap 2807
1465 #define MID_ChangeSupplement 2808
1466 #define MID_Reencode 2830
1467 #define MID_ForceReencode 2831
1468 #define MID_AddUnencoded 2832
1469 #define MID_RemoveUnused 2833
1470 #define MID_DetachGlyphs 2834
1471 #define MID_DetachAndRemoveGlyphs 2835
1472 #define MID_LoadEncoding 2836
1473 #define MID_MakeFromFont 2837
1474 #define MID_RemoveEncoding 2838
1475 #define MID_DisplayByGroups 2839
1476 #define MID_Compact 2840
1477 #define MID_SaveNamelist 2841
1478 #define MID_RenameGlyphs 2842
1479 #define MID_NameGlyphs 2843
1480 #define MID_HideNoGlyphSlots 2844
1481 #define MID_CreateMM 2900
1482 #define MID_MMInfo 2901
1483 #define MID_MMValid 2902
1484 #define MID_ChangeMMBlend 2903
1485 #define MID_BlendToNew 2904
1486 #define MID_ModifyComposition 20902
1487 #define MID_BuildSyllables 20903
1488
1489
1490 #define MID_Warnings 3000
1491
1492
1493 /* returns -1 if nothing selected, if exactly one char return it, -2 if more than one */
FVAnyCharSelected(FontView * fv)1494 static int FVAnyCharSelected(FontView *fv) {
1495 int i, val=-1;
1496
1497 for ( i=0; i<fv->b.map->enccount; ++i ) {
1498 if ( fv->b.selected[i]) {
1499 if ( val==-1 )
1500 val = i;
1501 else
1502 return( -2 );
1503 }
1504 }
1505 return( val );
1506 }
1507
FVAllSelected(FontView * fv)1508 static int FVAllSelected(FontView *fv) {
1509 int i, any = false;
1510 /* Is everything real selected? */
1511
1512 for ( i=0; i<fv->b.sf->glyphcnt; ++i ) if ( SCWorthOutputting(fv->b.sf->glyphs[i])) {
1513 if ( !fv->b.selected[fv->b.map->backmap[i]] )
1514 return( false );
1515 any = true;
1516 }
1517 return( any );
1518 }
1519
FVMenuCopyFrom(GWindow UNUSED (gw),struct gmenuitem * mi,GEvent * UNUSED (e))1520 static void FVMenuCopyFrom(GWindow UNUSED(gw), struct gmenuitem *mi, GEvent *UNUSED(e)) {
1521 /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
1522
1523 if ( mi->mid==MID_CharName )
1524 copymetadata = !copymetadata;
1525 else if ( mi->mid==MID_TTFInstr )
1526 copyttfinstr = !copyttfinstr;
1527 else
1528 onlycopydisplayed = (mi->mid==MID_DisplayedFont);
1529 SavePrefs(true);
1530 }
1531
FVMenuCopy(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1532 static void FVMenuCopy(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1533 FontView *fv = (FontView *) GDrawGetUserData(gw);
1534 if ( FVAnyCharSelected(fv)==-1 )
1535 return;
1536 FVCopy((FontViewBase *) fv,ct_fullcopy);
1537 }
1538
FVMenuCopyLookupData(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1539 static void FVMenuCopyLookupData(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1540 FontView *fv = (FontView *) GDrawGetUserData(gw);
1541 if ( FVAnyCharSelected(fv)==-1 )
1542 return;
1543 FVCopy((FontViewBase *) fv,ct_lookups);
1544 }
1545
FVMenuCopyRef(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1546 static void FVMenuCopyRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1547 FontView *fv = (FontView *) GDrawGetUserData(gw);
1548 if ( FVAnyCharSelected(fv)==-1 )
1549 return;
1550 FVCopy((FontViewBase *) fv,ct_reference);
1551 }
1552
FVMenuCopyWidth(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))1553 static void FVMenuCopyWidth(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
1554 FontView *fv = (FontView *) GDrawGetUserData(gw);
1555
1556 if ( FVAnyCharSelected(fv)==-1 )
1557 return;
1558 if ( mi->mid==MID_CopyVWidth && !fv->b.sf->hasvmetrics )
1559 return;
1560 FVCopyWidth((FontViewBase *) fv,
1561 mi->mid==MID_CopyWidth?ut_width:
1562 mi->mid==MID_CopyVWidth?ut_vwidth:
1563 mi->mid==MID_CopyLBearing?ut_lbearing:
1564 ut_rbearing);
1565 }
1566
FVMenuPaste(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1567 static void FVMenuPaste(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1568 FontView *fv = (FontView *) GDrawGetUserData(gw);
1569 if ( FVAnyCharSelected(fv)==-1 )
1570 return;
1571 PasteIntoFV((FontViewBase *) fv,false,NULL);
1572 }
1573
FVMenuPasteInto(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1574 static void FVMenuPasteInto(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1575 FontView *fv = (FontView *) GDrawGetUserData(gw);
1576 if ( FVAnyCharSelected(fv)==-1 )
1577 return;
1578 PasteIntoFV((FontViewBase *) fv,true,NULL);
1579 }
1580
FVMenuPasteAfter(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1581 static void FVMenuPasteAfter(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1582 FontView *fv = (FontView *) GDrawGetUserData(gw);
1583 int pos = FVAnyCharSelected(fv);
1584 if ( pos<0 )
1585 return;
1586 PasteIntoFV(&fv->b,2,NULL);
1587 }
1588
FVMenuSameGlyphAs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1589 static void FVMenuSameGlyphAs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1590 FontView *fv = (FontView *) GDrawGetUserData(gw);
1591 FVSameGlyphAs((FontViewBase *) fv);
1592 GDrawRequestExpose(fv->v,NULL,false);
1593 }
1594
FVMenuCopyFgBg(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1595 static void FVMenuCopyFgBg(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1596 FontView *fv = (FontView *) GDrawGetUserData(gw);
1597 FVCopyFgtoBg( (FontViewBase *) fv );
1598 }
1599
FVMenuCopyL2L(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1600 static void FVMenuCopyL2L(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1601 FontView *fv = (FontView *) GDrawGetUserData(gw);
1602 FVCopyLayerToLayer( fv );
1603 }
1604
FVMenuCompareL2L(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1605 static void FVMenuCompareL2L(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1606 FontView *fv = (FontView *) GDrawGetUserData(gw);
1607 FVCompareLayerToLayer( fv );
1608 }
1609
FVMenuClear(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1610 static void FVMenuClear(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1611 FontView *fv = (FontView *) GDrawGetUserData(gw);
1612 FVClear( (FontViewBase *) fv );
1613 }
1614
FVMenuClearBackground(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1615 static void FVMenuClearBackground(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1616 FontView *fv = (FontView *) GDrawGetUserData(gw);
1617 FVClearBackground( (FontViewBase *) fv );
1618 }
1619
FVMenuJoin(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1620 static void FVMenuJoin(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1621 FontView *fv = (FontView *) GDrawGetUserData(gw);
1622 FVJoin( (FontViewBase *) fv );
1623 }
1624
FVMenuUnlinkRef(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1625 static void FVMenuUnlinkRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1626 FontView *fv = (FontView *) GDrawGetUserData(gw);
1627 FVUnlinkRef( (FontViewBase *) fv );
1628 }
1629
FVMenuRemoveUndoes(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1630 static void FVMenuRemoveUndoes(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1631 FontView *fv = (FontView *) GDrawGetUserData(gw);
1632 SFRemoveUndoes(fv->b.sf,fv->b.selected,fv->b.map);
1633 }
1634
FVMenuUndo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1635 static void FVMenuUndo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1636 FontView *fv = (FontView *) GDrawGetUserData(gw);
1637 FVUndo((FontViewBase *) fv);
1638 }
1639
FVMenuRedo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1640 static void FVMenuRedo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1641 FontView *fv = (FontView *) GDrawGetUserData(gw);
1642 FVRedo((FontViewBase *) fv);
1643 }
1644
FVMenuUndoFontLevel(GWindow gw,struct gmenuitem * mi,GEvent * e)1645 static void FVMenuUndoFontLevel(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1646 FontView *fv = (FontView *) GDrawGetUserData(gw);
1647 FontViewBase * fvb = (FontViewBase *) fv;
1648 SplineFont *sf = fvb->sf;
1649
1650 if( !sf->undoes )
1651 return;
1652
1653 struct sfundoes *undo = sf->undoes;
1654 // printf("font level undo msg:%s\n", undo->msg );
1655 SFUndoPerform( undo, sf );
1656 SFUndoRemoveAndFree( sf, undo );
1657 }
1658
FVMenuCut(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1659 static void FVMenuCut(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1660 FontView *fv = (FontView *) GDrawGetUserData(gw);
1661 FVCopy(&fv->b,ct_fullcopy);
1662 FVClear(&fv->b);
1663 }
1664
FVMenuSelectAll(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1665 static void FVMenuSelectAll(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1666 FontView *fv = (FontView *) GDrawGetUserData(gw);
1667
1668 FVSelectAll(fv);
1669 }
1670
FVMenuInvertSelection(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1671 static void FVMenuInvertSelection(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1672 FontView *fv = (FontView *) GDrawGetUserData(gw);
1673
1674 FVInvertSelection(fv);
1675 }
1676
FVMenuDeselectAll(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))1677 static void FVMenuDeselectAll(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1678 FontView *fv = (FontView *) GDrawGetUserData(gw);
1679
1680 FVDeselectAll(fv);
1681 }
1682
1683 enum merge_type { mt_set=0, mt_merge=4, mt_or=mt_merge, mt_restrict=8, mt_and=12 };
1684 /* Index array by merge_type(*4) + selection*2 + doit */
1685 const uint8 mergefunc[] = {
1686 /* mt_set */
1687 0, 1,
1688 0, 1,
1689 /* mt_merge */
1690 0, 1,
1691 1, 1,
1692 /* mt_restrict */
1693 0, 0,
1694 1, 0,
1695 /* mt_and */
1696 0, 0,
1697 0, 1,
1698 };
1699
SelMergeType(GEvent * e)1700 static enum merge_type SelMergeType(GEvent *e) {
1701 if ( e->type!=et_mouseup )
1702 return( mt_set );
1703
1704 return( ((e->u.mouse.state&ksm_shift)?mt_merge:0) |
1705 ((e->u.mouse.state&ksm_control)?mt_restrict:0) );
1706 }
1707
SubMatch(char * pattern,char * eop,char * name,int ignorecase)1708 static char *SubMatch(char *pattern, char *eop, char *name,int ignorecase) {
1709 char ch, *ppt, *npt, *ept, *eon;
1710
1711 while ( pattern<eop && ( ch = *pattern)!='\0' ) {
1712 if ( ch=='*' ) {
1713 if ( pattern[1]=='\0' )
1714 return( name+strlen(name));
1715 for ( npt=name; ; ++npt ) {
1716 if ( (eon = SubMatch(pattern+1,eop,npt,ignorecase))!= NULL )
1717 return( eon );
1718 if ( *npt=='\0' )
1719 return( NULL );
1720 }
1721 } else if ( ch=='?' ) {
1722 if ( *name=='\0' )
1723 return( NULL );
1724 ++name;
1725 } else if ( ch=='[' ) {
1726 /* [<char>...] matches the chars
1727 * [<char>-<char>...] matches any char within the range (inclusive)
1728 * the above may be concattenated and the resultant pattern matches
1729 * anything thing which matches any of them.
1730 * [^<char>...] matches any char which does not match the rest of
1731 * the pattern
1732 * []...] as a special case a ']' immediately after the '[' matches
1733 * itself and does not end the pattern
1734 */
1735 int found = 0, not=0;
1736 ++pattern;
1737 if ( pattern[0]=='^' ) { not = 1; ++pattern; }
1738 for ( ppt = pattern; (ppt!=pattern || *ppt!=']') && *ppt!='\0' ; ++ppt ) {
1739 ch = *ppt;
1740 if ( ppt[1]=='-' && ppt[2]!=']' && ppt[2]!='\0' ) {
1741 char ch2 = ppt[2];
1742 if ( (*name>=ch && *name<=ch2) ||
1743 (ignorecase && islower(ch) && islower(ch2) &&
1744 *name>=toupper(ch) && *name<=toupper(ch2)) ||
1745 (ignorecase && isupper(ch) && isupper(ch2) &&
1746 *name>=tolower(ch) && *name<=tolower(ch2))) {
1747 if ( !not ) {
1748 found = 1;
1749 break;
1750 }
1751 } else {
1752 if ( not ) {
1753 found = 1;
1754 break;
1755 }
1756 }
1757 ppt += 2;
1758 } else if ( ch==*name || (ignorecase && tolower(ch)==tolower(*name)) ) {
1759 if ( !not ) {
1760 found = 1;
1761 break;
1762 }
1763 } else {
1764 if ( not ) {
1765 found = 1;
1766 break;
1767 }
1768 }
1769 }
1770 if ( !found )
1771 return( NULL );
1772 while ( *ppt!=']' && *ppt!='\0' ) ++ppt;
1773 pattern = ppt;
1774 ++name;
1775 } else if ( ch=='{' ) {
1776 /* matches any of a comma separated list of substrings */
1777 for ( ppt = pattern+1; *ppt!='\0' ; ppt = ept ) {
1778 for ( ept=ppt; *ept!='}' && *ept!=',' && *ept!='\0'; ++ept );
1779 npt = SubMatch(ppt,ept,name,ignorecase);
1780 if ( npt!=NULL ) {
1781 char *ecurly = ept;
1782 while ( *ecurly!='}' && ecurly<eop && *ecurly!='\0' ) ++ecurly;
1783 if ( (eon=SubMatch(ecurly+1,eop,npt,ignorecase))!=NULL )
1784 return( eon );
1785 }
1786 if ( *ept=='}' )
1787 return( NULL );
1788 if ( *ept==',' ) ++ept;
1789 }
1790 } else if ( ch==*name ) {
1791 ++name;
1792 } else if ( ignorecase && tolower(ch)==tolower(*name)) {
1793 ++name;
1794 } else
1795 return( NULL );
1796 ++pattern;
1797 }
1798 return( name );
1799 }
1800
1801 /* Handles *?{}[] wildcards */
WildMatch(char * pattern,char * name,int ignorecase)1802 static int WildMatch(char *pattern, char *name,int ignorecase) {
1803 char *eop = pattern + strlen(pattern);
1804
1805 if ( pattern==NULL )
1806 return( true );
1807
1808 name = SubMatch(pattern,eop,name,ignorecase);
1809 if ( name==NULL )
1810 return( false );
1811 if ( *name=='\0' )
1812 return( true );
1813
1814 return( false );
1815 }
1816
SS_ScriptChanged(GGadget * g,GEvent * e)1817 static int SS_ScriptChanged(GGadget *g, GEvent *e) {
1818
1819 if ( e->type==et_controlevent && e->u.control.subtype != et_textfocuschanged ) {
1820 char *txt = GGadgetGetTitle8(g);
1821 char buf[8];
1822 int i;
1823 extern GTextInfo scripts[];
1824
1825 for ( i=0; scripts[i].text!=NULL; ++i ) {
1826 if ( strcmp((char *) scripts[i].text,txt)==0 )
1827 break;
1828 }
1829 free(txt);
1830 if ( scripts[i].text==NULL )
1831 return( true );
1832 buf[0] = ((intpt) scripts[i].userdata)>>24;
1833 buf[1] = ((intpt) scripts[i].userdata)>>16;
1834 buf[2] = ((intpt) scripts[i].userdata)>>8 ;
1835 buf[3] = ((intpt) scripts[i].userdata) ;
1836 buf[4] = 0;
1837 GGadgetSetTitle8(g,buf);
1838 }
1839 return( true );
1840 }
1841
SS_OK(GGadget * g,GEvent * e)1842 static int SS_OK(GGadget *g, GEvent *e) {
1843
1844 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1845 int *done = GDrawGetUserData(GGadgetGetWindow(g));
1846 *done = 2;
1847 }
1848 return( true );
1849 }
1850
SS_Cancel(GGadget * g,GEvent * e)1851 static int SS_Cancel(GGadget *g, GEvent *e) {
1852
1853 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1854 int *done = GDrawGetUserData(GGadgetGetWindow(g));
1855 *done = true;
1856 }
1857 return( true );
1858 }
1859
ss_e_h(GWindow gw,GEvent * event)1860 static int ss_e_h(GWindow gw, GEvent *event) {
1861 int *done = GDrawGetUserData(gw);
1862
1863 switch ( event->type ) {
1864 case et_char:
1865 return( false );
1866 case et_close:
1867 *done = true;
1868 break;
1869 }
1870 return( true );
1871 }
1872
FVSelectByScript(FontView * fv,int merge)1873 static void FVSelectByScript(FontView *fv,int merge) {
1874 int j, gid;
1875 SplineChar *sc;
1876 EncMap *map = fv->b.map;
1877 SplineFont *sf = fv->b.sf;
1878 extern GTextInfo scripts[];
1879 GRect pos;
1880 GWindow gw;
1881 GWindowAttrs wattrs;
1882 GGadgetCreateData gcd[10], *hvarray[21][2], *barray[8], boxes[3];
1883 GTextInfo label[10];
1884 int i,k;
1885 int done = 0, doit;
1886 char tagbuf[4];
1887 uint32 tag;
1888 const unichar_t *ret;
1889 int lc_k, uc_k, select_k;
1890 int only_uc=0, only_lc=0;
1891
1892 LookupUIInit();
1893
1894 memset(&wattrs,0,sizeof(wattrs));
1895 memset(&gcd,0,sizeof(gcd));
1896 memset(&label,0,sizeof(label));
1897 memset(&boxes,0,sizeof(boxes));
1898
1899 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1900 wattrs.event_masks = ~(1<<et_charup);
1901 wattrs.restrict_input_to_me = false;
1902 wattrs.is_dlg = 1;
1903 wattrs.undercursor = 1;
1904 wattrs.cursor = ct_pointer;
1905 wattrs.utf8_window_title = _("Select by Script");
1906 wattrs.is_dlg = true;
1907 pos.x = pos.y = 0;
1908 pos.width = 100;
1909 pos.height = 100;
1910 gw = GDrawCreateTopWindow(NULL,&pos,ss_e_h,&done,&wattrs);
1911
1912 k = i = 0;
1913
1914 gcd[k].gd.flags = gg_visible|gg_enabled ;
1915 gcd[k].gd.u.list = scripts;
1916 gcd[k].gd.handle_controlevent = SS_ScriptChanged;
1917 gcd[k++].creator = GListFieldCreate;
1918 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1919
1920 label[k].text = (unichar_t *) _("All glyphs");
1921 label[k].text_is_1byte = true;
1922 gcd[k].gd.label = &label[k];
1923 gcd[k].gd.flags = gg_enabled|gg_visible|gg_cb_on;
1924 gcd[k].gd.popup_msg = _("Set the selection of the font view to all glyphs in the script.");
1925 gcd[k++].creator = GRadioCreate;
1926 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1927 hvarray[i][0] = GCD_HPad10; hvarray[i++][1] = NULL;
1928
1929 uc_k = k;
1930 label[k].text = (unichar_t *) _("Only upper case");
1931 label[k].text_is_1byte = true;
1932 gcd[k].gd.label = &label[k];
1933 gcd[k].gd.flags = gg_enabled|gg_visible;
1934 gcd[k].gd.popup_msg = _("Set the selection of the font view to any upper case glyphs in the script.");
1935 gcd[k++].creator = GRadioCreate;
1936 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1937
1938 lc_k = k;
1939 label[k].text = (unichar_t *) _("Only lower case");
1940 label[k].text_is_1byte = true;
1941 gcd[k].gd.label = &label[k];
1942 gcd[k].gd.flags = gg_enabled|gg_visible;
1943 gcd[k].gd.popup_msg = _("Set the selection of the font view to any lower case glyphs in the script.");
1944 gcd[k++].creator = GRadioCreate;
1945 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1946 hvarray[i][0] = GCD_HPad10; hvarray[i++][1] = NULL;
1947
1948 select_k = k;
1949 label[k].text = (unichar_t *) _("Select Results");
1950 label[k].text_is_1byte = true;
1951 gcd[k].gd.label = &label[k];
1952 gcd[k].gd.flags = gg_enabled|gg_visible|gg_rad_startnew;
1953 gcd[k].gd.popup_msg = _("Set the selection of the font view to the glyphs\nwhich match");
1954 gcd[k++].creator = GRadioCreate;
1955 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1956
1957 label[k].text = (unichar_t *) _("Merge Results");
1958 label[k].text_is_1byte = true;
1959 gcd[k].gd.label = &label[k];
1960 gcd[k].gd.flags = gg_enabled|gg_visible;
1961 gcd[k].gd.popup_msg = _("Expand the selection of the font view to include\nall the glyphs which match");
1962 gcd[k++].creator = GRadioCreate;
1963 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1964
1965 label[k].text = (unichar_t *) _("Restrict Selection");
1966 label[k].text_is_1byte = true;
1967 gcd[k].gd.label = &label[k];
1968 gcd[k].gd.flags = gg_enabled|gg_visible;
1969 gcd[k].gd.popup_msg = _("Remove matching glyphs from the selection." );
1970 gcd[k++].creator = GRadioCreate;
1971 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1972
1973 label[k].text = (unichar_t *) _("Logical And with Selection");
1974 label[k].text_is_1byte = true;
1975 gcd[k].gd.label = &label[k];
1976 gcd[k].gd.flags = gg_enabled|gg_visible;
1977 gcd[k].gd.popup_msg = _("Remove glyphs which do not match from the selection." );
1978 gcd[k++].creator = GRadioCreate;
1979 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1980 gcd[k-4 + merge/4].gd.flags |= gg_cb_on;
1981
1982 hvarray[i][0] = GCD_Glue; hvarray[i++][1] = NULL;
1983
1984 label[k].text = (unichar_t *) _("_OK");
1985 label[k].text_is_1byte = true;
1986 label[k].text_in_resource = true;
1987 gcd[k].gd.label = &label[k];
1988 gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_default;
1989 gcd[k].gd.handle_controlevent = SS_OK;
1990 gcd[k++].creator = GButtonCreate;
1991
1992 label[k].text = (unichar_t *) _("_Cancel");
1993 label[k].text_is_1byte = true;
1994 label[k].text_in_resource = true;
1995 gcd[k].gd.label = &label[k];
1996 gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_cancel;
1997 gcd[k].gd.handle_controlevent = SS_Cancel;
1998 gcd[k++].creator = GButtonCreate;
1999
2000 barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
2001 barray[1] = &gcd[k-2]; barray[5] = &gcd[k-1];
2002 hvarray[i][0] = &boxes[2]; hvarray[i++][1] = NULL;
2003 hvarray[i][0] = NULL;
2004
2005 memset(boxes,0,sizeof(boxes));
2006 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2007 boxes[0].gd.flags = gg_enabled|gg_visible;
2008 boxes[0].gd.u.boxelements = hvarray[0];
2009 boxes[0].creator = GHVGroupCreate;
2010
2011 boxes[2].gd.flags = gg_enabled|gg_visible;
2012 boxes[2].gd.u.boxelements = barray;
2013 boxes[2].creator = GHBoxCreate;
2014
2015 GGadgetsCreate(gw,boxes);
2016 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
2017 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2018
2019
2020 GHVBoxFitWindow(boxes[0].ret);
2021
2022 GDrawSetVisible(gw,true);
2023 ret = NULL;
2024 while ( !done ) {
2025 GDrawProcessOneEvent(NULL);
2026 if ( done==2 ) {
2027 ret = _GGadgetGetTitle(gcd[0].ret);
2028 if ( *ret=='\0' ) {
2029 ff_post_error(_("No Script"),_("Please specify a script"));
2030 done = 0;
2031 } else if ( u_strlen(ret)>4 ) {
2032 ff_post_error(_("Bad Script"),_("Scripts are 4 letter tags"));
2033 done = 0;
2034 }
2035 }
2036 }
2037 memset(tagbuf,' ',4);
2038 if ( done==2 && ret!=NULL ) {
2039 tagbuf[0] = *ret;
2040 if ( ret[1]!='\0' ) {
2041 tagbuf[1] = ret[1];
2042 if ( ret[2]!='\0' ) {
2043 tagbuf[2] = ret[2];
2044 if ( ret[3]!='\0' )
2045 tagbuf[3] = ret[3];
2046 }
2047 }
2048 }
2049 merge = GGadgetIsChecked(gcd[select_k+0].ret) ? mt_set :
2050 GGadgetIsChecked(gcd[select_k+1].ret) ? mt_merge :
2051 GGadgetIsChecked(gcd[select_k+2].ret) ? mt_restrict :
2052 mt_and;
2053 only_uc = GGadgetIsChecked(gcd[uc_k+0].ret);
2054 only_lc = GGadgetIsChecked(gcd[lc_k+0].ret);
2055
2056 GDrawDestroyWindow(gw);
2057 if ( done==1 )
2058 return;
2059 tag = (tagbuf[0]<<24) | (tagbuf[1]<<16) | (tagbuf[2]<<8) | tagbuf[3];
2060
2061 for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2062 doit = ( SCScriptFromUnicode(sc)==tag );
2063 if ( doit ) {
2064 if ( only_uc && (sc->unicodeenc==-1 || sc->unicodeenc>0xffff ||
2065 !isupper(sc->unicodeenc)) )
2066 doit = false;
2067 else if ( only_lc && (sc->unicodeenc==-1 || sc->unicodeenc>0xffff ||
2068 !islower(sc->unicodeenc)) )
2069 doit = false;
2070 }
2071 fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2072 } else if ( merge==mt_set )
2073 fv->b.selected[j] = false;
2074
2075 GDrawRequestExpose(fv->v,NULL,false);
2076 }
2077
FVMenuSelectByScript(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2078 static void FVMenuSelectByScript(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2079 FontView *fv = (FontView *) GDrawGetUserData(gw);
2080
2081 FVSelectByScript(fv,SelMergeType(e));
2082 }
2083
FVSelectColor(FontView * fv,uint32 col,int merge)2084 static void FVSelectColor(FontView *fv, uint32 col, int merge) {
2085 int i, doit;
2086 uint32 sccol;
2087 SplineChar **glyphs = fv->b.sf->glyphs;
2088
2089 for ( i=0; i<fv->b.map->enccount; ++i ) {
2090 int gid = fv->b.map->map[i];
2091 sccol = ( gid==-1 || glyphs[gid]==NULL ) ? COLOR_DEFAULT : glyphs[gid]->color;
2092 doit = sccol==col;
2093 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2094 }
2095 GDrawRequestExpose(fv->v,NULL,false);
2096 }
2097
FVMenuSelectColor(GWindow gw,struct gmenuitem * mi,GEvent * e)2098 static void FVMenuSelectColor(GWindow gw, struct gmenuitem *mi, GEvent *e) {
2099 FontView *fv = (FontView *) GDrawGetUserData(gw);
2100 Color col = (Color) (intpt) (mi->ti.userdata);
2101 if ( (intpt) mi->ti.userdata == (intpt) -10 ) {
2102 struct hslrgb retcol, font_cols[6];
2103 retcol = GWidgetColor(_("Pick a color"),NULL,SFFontCols(fv->b.sf,font_cols));
2104 if ( !retcol.rgb )
2105 return;
2106 col = (((int) rint(255.*retcol.r))<<16 ) |
2107 (((int) rint(255.*retcol.g))<<8 ) |
2108 (((int) rint(255.*retcol.b)) );
2109 }
2110 FVSelectColor(fv,col,SelMergeType(e));
2111 }
2112
FVSelectByName(FontView * fv,char * ret,int merge)2113 static int FVSelectByName(FontView *fv, char *ret, int merge) {
2114 int j, gid, doit;
2115 char *end;
2116 SplineChar *sc;
2117 EncMap *map = fv->b.map;
2118 SplineFont *sf = fv->b.sf;
2119 struct altuni *alt;
2120
2121 if ( !merge )
2122 FVDeselectAll(fv);
2123 if (( *ret=='0' && ( ret[1]=='x' || ret[1]=='X' )) ||
2124 ((*ret=='u' || *ret=='U') && ret[1]=='+' )) {
2125 int uni = (int) strtol(ret+2,&end,16);
2126 int vs= -2;
2127 if ( *end=='.' ) {
2128 ++end;
2129 if (( *end=='0' && ( end[1]=='x' || end[1]=='X' )) ||
2130 ((*end=='u' || *end=='U') && end[1]=='+' ))
2131 end += 2;
2132 vs = (int) strtoul(end,&end,16);
2133 }
2134 if ( *end!='\0' || uni<0 || uni>=0x110000 ) {
2135 ff_post_error( _("Bad Number"),_("Bad Number") );
2136 return( false );
2137 }
2138 for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2139 if ( vs==-2 ) {
2140 for ( alt=sc->altuni; alt!=NULL && (alt->unienc!=uni || alt->fid!=0); alt=alt->next );
2141 } else {
2142 for ( alt=sc->altuni; alt!=NULL && (alt->unienc!=uni || alt->vs!=vs || alt->fid!=0); alt=alt->next );
2143 }
2144 doit = (sc->unicodeenc == uni && vs<0) || alt!=NULL;
2145 fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2146 } else if ( merge==mt_set )
2147 fv->b.selected[j] = false;
2148 } else {
2149 for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2150 doit = WildMatch(ret,sc->name,false);
2151 fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2152 } else if ( merge==mt_set )
2153 fv->b.selected[j] = false;
2154 }
2155 GDrawRequestExpose(fv->v,NULL,false);
2156 fv->sel_index = 1;
2157 return( true );
2158 }
2159
FVMenuSelectByName(GWindow _gw,struct gmenuitem * UNUSED (mi),GEvent * e)2160 static void FVMenuSelectByName(GWindow _gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2161 FontView *fv = (FontView *) GDrawGetUserData(_gw);
2162 GRect pos;
2163 GWindow gw;
2164 GWindowAttrs wattrs;
2165 GGadgetCreateData gcd[8], *hvarray[12][2], *barray[8], boxes[3];
2166 GTextInfo label[8];
2167 int merge = SelMergeType(e);
2168 int done=0,k,i;
2169
2170 memset(&wattrs,0,sizeof(wattrs));
2171 memset(&gcd,0,sizeof(gcd));
2172 memset(&label,0,sizeof(label));
2173 memset(&boxes,0,sizeof(boxes));
2174
2175 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2176 wattrs.event_masks = ~(1<<et_charup);
2177 wattrs.restrict_input_to_me = false;
2178 wattrs.undercursor = 1;
2179 wattrs.cursor = ct_pointer;
2180 wattrs.utf8_window_title = _("Select by Name");
2181 wattrs.is_dlg = false;
2182 pos.x = pos.y = 0;
2183 pos.width = 100;
2184 pos.height = 100;
2185 gw = GDrawCreateTopWindow(NULL,&pos,ss_e_h,&done,&wattrs);
2186
2187 k = i = 0;
2188
2189 label[k].text = (unichar_t *) _("Enter either a wildcard pattern (to match glyph names)\n or a unicode encoding like \"U+0065\".");
2190 label[k].text_is_1byte = true;
2191 gcd[k].gd.label = &label[k];
2192 gcd[k].gd.flags = gg_visible | gg_enabled;
2193 gcd[k].gd.popup_msg = _(
2194 "Unix style wildcarding is accepted:\n"
2195 "Most characters match themselves\n"
2196 "A \"?\" will match any single character\n"
2197 "A \"*\" will match an arbitrary number of characters (including none)\n"
2198 "An \"[abd]\" set of characters within square brackets will match any (single) character\n"
2199 "A \"{scmp,c2sc}\" set of strings within curly brackets will match any string\n"
2200 "So \"a.*\" would match \"a.\" or \"a.sc\" or \"a.swash\"\n"
2201 "While \"a.{scmp,c2sc}\" would match \"a.scmp\" or \"a.c2sc\"\n"
2202 "And \"a.[abd]\" would match \"a.a\" or \"a.b\" or \"a.d\"");
2203 gcd[k++].creator = GLabelCreate;
2204 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2205
2206 gcd[k].gd.flags = gg_visible | gg_enabled;
2207 gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg;
2208 gcd[k++].creator = GTextFieldCreate;
2209 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2210
2211 label[k].text = (unichar_t *) _("Select Results");
2212 label[k].text_is_1byte = true;
2213 gcd[k].gd.label = &label[k];
2214 gcd[k].gd.flags = gg_enabled|gg_visible;
2215 gcd[k].gd.popup_msg = _("Set the selection of the font view to the glyphs\nwhich match");
2216 gcd[k++].creator = GRadioCreate;
2217 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2218
2219 label[k].text = (unichar_t *) _("Merge Results");
2220 label[k].text_is_1byte = true;
2221 gcd[k].gd.label = &label[k];
2222 gcd[k].gd.flags = gg_enabled|gg_visible;
2223 gcd[k].gd.popup_msg = _("Expand the selection of the font view to include\nall the glyphs which match");
2224 gcd[k++].creator = GRadioCreate;
2225 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2226
2227 label[k].text = (unichar_t *) _("Restrict Selection");
2228 label[k].text_is_1byte = true;
2229 gcd[k].gd.label = &label[k];
2230 gcd[k].gd.flags = gg_enabled|gg_visible;
2231 gcd[k].gd.popup_msg = _("Remove matching glyphs from the selection." );
2232 gcd[k++].creator = GRadioCreate;
2233 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2234
2235 label[k].text = (unichar_t *) _("Logical And with Selection");
2236 label[k].text_is_1byte = true;
2237 gcd[k].gd.label = &label[k];
2238 gcd[k].gd.flags = gg_enabled|gg_visible;
2239 gcd[k].gd.popup_msg = _("Remove glyphs which do not match from the selection." );
2240 gcd[k++].creator = GRadioCreate;
2241 hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2242 gcd[k-4 + merge/4].gd.flags |= gg_cb_on;
2243
2244 hvarray[i][0] = GCD_Glue; hvarray[i++][1] = NULL;
2245
2246 label[k].text = (unichar_t *) _("_OK");
2247 label[k].text_is_1byte = true;
2248 label[k].text_in_resource = true;
2249 gcd[k].gd.label = &label[k];
2250 gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_default;
2251 gcd[k].gd.handle_controlevent = SS_OK;
2252 gcd[k++].creator = GButtonCreate;
2253
2254 label[k].text = (unichar_t *) _("_Cancel");
2255 label[k].text_is_1byte = true;
2256 label[k].text_in_resource = true;
2257 gcd[k].gd.label = &label[k];
2258 gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_cancel;
2259 gcd[k].gd.handle_controlevent = SS_Cancel;
2260 gcd[k++].creator = GButtonCreate;
2261
2262 barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
2263 barray[1] = &gcd[k-2]; barray[5] = &gcd[k-1];
2264 hvarray[i][0] = &boxes[2]; hvarray[i++][1] = NULL;
2265 hvarray[i][0] = NULL;
2266
2267 memset(boxes,0,sizeof(boxes));
2268 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2269 boxes[0].gd.flags = gg_enabled|gg_visible;
2270 boxes[0].gd.u.boxelements = hvarray[0];
2271 boxes[0].creator = GHVGroupCreate;
2272
2273 boxes[2].gd.flags = gg_enabled|gg_visible;
2274 boxes[2].gd.u.boxelements = barray;
2275 boxes[2].creator = GHBoxCreate;
2276
2277 GGadgetsCreate(gw,boxes);
2278 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
2279 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2280
2281
2282 GHVBoxFitWindow(boxes[0].ret);
2283
2284 GDrawSetVisible(gw,true);
2285 while ( !done ) {
2286 GDrawProcessOneEvent(NULL);
2287 if ( done==2 ) {
2288 char *str = GGadgetGetTitle8(gcd[1].ret);
2289 int merge = GGadgetIsChecked(gcd[2].ret) ? mt_set :
2290 GGadgetIsChecked(gcd[3].ret) ? mt_merge :
2291 GGadgetIsChecked(gcd[4].ret) ? mt_restrict :
2292 mt_and;
2293 int ret = FVSelectByName(fv,str,merge);
2294 free(str);
2295 if ( !ret )
2296 done = 0;
2297 }
2298 }
2299 GDrawDestroyWindow(gw);
2300 }
2301
FVMenuSelectWorthOutputting(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2302 static void FVMenuSelectWorthOutputting(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2303 FontView *fv = (FontView *) GDrawGetUserData(gw);
2304 int i, gid, doit;
2305 EncMap *map = fv->b.map;
2306 SplineFont *sf = fv->b.sf;
2307 int merge = SelMergeType(e);
2308
2309 for ( i=0; i< map->enccount; ++i ) {
2310 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2311 SCWorthOutputting(sf->glyphs[gid]) );
2312 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2313 }
2314 GDrawRequestExpose(fv->v,NULL,false);
2315 }
2316
FVMenuGlyphsRefs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2317 static void FVMenuGlyphsRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2318 FontView *fv = (FontView *) GDrawGetUserData(gw);
2319 int i, gid, doit;
2320 EncMap *map = fv->b.map;
2321 SplineFont *sf = fv->b.sf;
2322 int merge = SelMergeType(e);
2323 int layer = fv->b.active_layer;
2324
2325 for ( i=0; i< map->enccount; ++i ) {
2326 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2327 sf->glyphs[gid]->layers[layer].refs!=NULL &&
2328 sf->glyphs[gid]->layers[layer].splines==NULL );
2329 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2330 }
2331 GDrawRequestExpose(fv->v,NULL,false);
2332 }
2333
FVMenuGlyphsSplines(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2334 static void FVMenuGlyphsSplines(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2335 FontView *fv = (FontView *) GDrawGetUserData(gw);
2336 int i, gid, doit;
2337 EncMap *map = fv->b.map;
2338 SplineFont *sf = fv->b.sf;
2339 int merge = SelMergeType(e);
2340 int layer = fv->b.active_layer;
2341
2342 for ( i=0; i< map->enccount; ++i ) {
2343 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2344 sf->glyphs[gid]->layers[layer].refs==NULL &&
2345 sf->glyphs[gid]->layers[layer].splines!=NULL );
2346 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2347 }
2348 GDrawRequestExpose(fv->v,NULL,false);
2349 }
2350
FVMenuGlyphsBoth(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2351 static void FVMenuGlyphsBoth(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2352 FontView *fv = (FontView *) GDrawGetUserData(gw);
2353 int i, gid, doit;
2354 EncMap *map = fv->b.map;
2355 SplineFont *sf = fv->b.sf;
2356 int merge = SelMergeType(e);
2357 int layer = fv->b.active_layer;
2358
2359 for ( i=0; i< map->enccount; ++i ) {
2360 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2361 sf->glyphs[gid]->layers[layer].refs!=NULL &&
2362 sf->glyphs[gid]->layers[layer].splines!=NULL );
2363 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2364 }
2365 GDrawRequestExpose(fv->v,NULL,false);
2366 }
2367
FVMenuGlyphsWhite(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2368 static void FVMenuGlyphsWhite(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2369 FontView *fv = (FontView *) GDrawGetUserData(gw);
2370 int i, gid, doit;
2371 EncMap *map = fv->b.map;
2372 SplineFont *sf = fv->b.sf;
2373 int merge = SelMergeType(e);
2374 int layer = fv->b.active_layer;
2375
2376 for ( i=0; i< map->enccount; ++i ) {
2377 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2378 sf->glyphs[gid]->layers[layer].refs==NULL &&
2379 sf->glyphs[gid]->layers[layer].splines==NULL );
2380 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2381 }
2382 GDrawRequestExpose(fv->v,NULL,false);
2383 }
2384
FVMenuSelectChanged(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2385 static void FVMenuSelectChanged(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2386 FontView *fv = (FontView *) GDrawGetUserData(gw);
2387 int i, gid, doit;
2388 EncMap *map = fv->b.map;
2389 SplineFont *sf = fv->b.sf;
2390 int merge = SelMergeType(e);
2391
2392 for ( i=0; i< map->enccount; ++i ) {
2393 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->changed );
2394 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2395 }
2396
2397 GDrawRequestExpose(fv->v,NULL,false);
2398 }
2399
FVMenuSelectHintingNeeded(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2400 static void FVMenuSelectHintingNeeded(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2401 FontView *fv = (FontView *) GDrawGetUserData(gw);
2402 int i, gid, doit;
2403 EncMap *map = fv->b.map;
2404 SplineFont *sf = fv->b.sf;
2405 int order2 = sf->layers[fv->b.active_layer].order2;
2406 int merge = SelMergeType(e);
2407
2408 for ( i=0; i< map->enccount; ++i ) {
2409 doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2410 ((!order2 && sf->glyphs[gid]->changedsincelasthinted ) ||
2411 ( order2 && sf->glyphs[gid]->layers[fv->b.active_layer].splines!=NULL &&
2412 sf->glyphs[gid]->ttf_instrs_len<=0 ) ||
2413 ( order2 && sf->glyphs[gid]->instructions_out_of_date )) );
2414 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2415 }
2416 GDrawRequestExpose(fv->v,NULL,false);
2417 }
2418
FVMenuSelectAutohintable(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2419 static void FVMenuSelectAutohintable(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2420 FontView *fv = (FontView *) GDrawGetUserData(gw);
2421 int i, gid, doit;
2422 EncMap *map = fv->b.map;
2423 SplineFont *sf = fv->b.sf;
2424 int merge = SelMergeType(e);
2425
2426 for ( i=0; i< map->enccount; ++i ) {
2427 doit = (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2428 !sf->glyphs[gid]->manualhints;
2429 fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2430 }
2431 GDrawRequestExpose(fv->v,NULL,false);
2432 }
2433
FVMenuSelectByPST(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2434 static void FVMenuSelectByPST(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2435 FontView *fv = (FontView *) GDrawGetUserData(gw);
2436
2437 FVSelectByPST(fv);
2438 }
2439
FVMenuFindRpl(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2440 static void FVMenuFindRpl(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2441 FontView *fv = (FontView *) GDrawGetUserData(gw);
2442
2443 SVCreate(fv);
2444 }
2445
FVMenuReplaceWithRef(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2446 static void FVMenuReplaceWithRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2447 FontView *fv = (FontView *) GDrawGetUserData(gw);
2448
2449 FVReplaceOutlineWithReference(fv,.001);
2450 }
2451
FVMenuCorrectRefs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2452 static void FVMenuCorrectRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2453 FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
2454
2455 FVCorrectReferences(fv);
2456 }
2457
FVMenuCharInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2458 static void FVMenuCharInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2459 FontView *fv = (FontView *) GDrawGetUserData(gw);
2460 int pos = FVAnyCharSelected(fv);
2461 if ( pos<0 )
2462 return;
2463 if ( fv->b.cidmaster!=NULL &&
2464 (fv->b.map->map[pos]==-1 || fv->b.sf->glyphs[fv->b.map->map[pos]]==NULL ))
2465 return;
2466 SCCharInfo(SFMakeChar(fv->b.sf,fv->b.map,pos),fv->b.active_layer,fv->b.map,pos);
2467 }
2468
FVMenuBDFInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2469 static void FVMenuBDFInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2470 FontView *fv = (FontView *) GDrawGetUserData(gw);
2471 if ( fv->b.sf->bitmaps==NULL )
2472 return;
2473 if ( fv->show!=fv->filled )
2474 SFBdfProperties(fv->b.sf,fv->b.map,fv->show);
2475 else
2476 SFBdfProperties(fv->b.sf,fv->b.map,NULL);
2477 }
2478
FVMenuBaseHoriz(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2479 static void FVMenuBaseHoriz(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2480 FontView *fv = (FontView *) GDrawGetUserData(gw);
2481 SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2482 sf->horiz_base = SFBaselines(sf,sf->horiz_base,false);
2483 SFBaseSort(sf);
2484 }
2485
FVMenuBaseVert(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2486 static void FVMenuBaseVert(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2487 FontView *fv = (FontView *) GDrawGetUserData(gw);
2488 SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2489 sf->vert_base = SFBaselines(sf,sf->vert_base,true);
2490 SFBaseSort(sf);
2491 }
2492
FVMenuJustify(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2493 static void FVMenuJustify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2494 FontView *fv = (FontView *) GDrawGetUserData(gw);
2495 SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2496 JustifyDlg(sf);
2497 }
2498
FVMenuMassRename(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2499 static void FVMenuMassRename(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2500 FontView *fv = (FontView *) GDrawGetUserData(gw);
2501 FVMassGlyphRename(fv);
2502 }
2503
FVSetColor(FontView * fv,uint32 col)2504 static void FVSetColor(FontView *fv, uint32 col) {
2505 int i;
2506
2507 for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
2508 SplineChar *sc = SFMakeChar(fv->b.sf,fv->b.map,i);
2509 sc->color = col;
2510 }
2511 GDrawRequestExpose(fv->v,NULL,false);
2512 }
2513
FVMenuSetColor(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))2514 static void FVMenuSetColor(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2515 FontView *fv = (FontView *) GDrawGetUserData(gw);
2516 Color col = (Color) (intpt) (mi->ti.userdata);
2517 if ( (intpt) mi->ti.userdata == (intpt) -10 ) {
2518 struct hslrgb retcol, font_cols[6];
2519 retcol = GWidgetColor(_("Pick a color"),NULL,SFFontCols(fv->b.sf,font_cols));
2520 if ( !retcol.rgb )
2521 return;
2522 col = (((int) rint(255.*retcol.r))<<16 ) |
2523 (((int) rint(255.*retcol.g))<<8 ) |
2524 (((int) rint(255.*retcol.b)) );
2525 }
2526 FVSetColor(fv,col);
2527 }
2528
FVMenuShowDependentRefs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2529 static void FVMenuShowDependentRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2530 FontView *fv = (FontView *) GDrawGetUserData(gw);
2531 int pos = FVAnyCharSelected(fv);
2532 SplineChar *sc;
2533
2534 if ( pos<0 || fv->b.map->map[pos]==-1 )
2535 return;
2536 sc = fv->b.sf->glyphs[fv->b.map->map[pos]];
2537 if ( sc==NULL || sc->dependents==NULL )
2538 return;
2539 SCRefBy(sc);
2540 }
2541
FVMenuShowDependentSubs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2542 static void FVMenuShowDependentSubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2543 FontView *fv = (FontView *) GDrawGetUserData(gw);
2544 int pos = FVAnyCharSelected(fv);
2545 SplineChar *sc;
2546
2547 if ( pos<0 || fv->b.map->map[pos]==-1 )
2548 return;
2549 sc = fv->b.sf->glyphs[fv->b.map->map[pos]];
2550 if ( sc==NULL )
2551 return;
2552 SCSubBy(sc);
2553 }
2554
getorigin(void * UNUSED (d),BasePoint * base,int index)2555 static int getorigin(void *UNUSED(d), BasePoint *base, int index) {
2556 /*FontView *fv = (FontView *) d;*/
2557
2558 base->x = base->y = 0;
2559 switch ( index ) {
2560 case 0: /* Character origin */
2561 /* all done */
2562 break;
2563 case 1: /* Center of selection */
2564 /*CVFindCenter(cv,base,!CVAnySel(cv,NULL,NULL,NULL,NULL));*/
2565 break;
2566 default:
2567 return( false );
2568 }
2569 return( true );
2570 }
2571
FVDoTransform(FontView * fv)2572 static void FVDoTransform(FontView *fv) {
2573 enum transdlg_flags flags=tdf_enableback|tdf_enablekerns;
2574 if ( FVAnyCharSelected(fv)==-1 )
2575 return;
2576 if ( FVAllSelected(fv))
2577 flags=tdf_enableback|tdf_enablekerns|tdf_defaultkerns;
2578 TransformDlgCreate(fv,FVTransFunc,getorigin,flags,cvt_none);
2579 }
2580
FVMenuTransform(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2581 static void FVMenuTransform(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2582 FontView *fv = (FontView *) GDrawGetUserData(gw);
2583 FVDoTransform(fv);
2584 }
2585
FVMenuPOV(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2586 static void FVMenuPOV(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2587 FontView *fv = (FontView *) GDrawGetUserData(gw);
2588 struct pov_data pov_data;
2589 if ( FVAnyCharSelected(fv)==-1 || fv->b.sf->onlybitmaps )
2590 return;
2591 if ( PointOfViewDlg(&pov_data,fv->b.sf,false)==-1 )
2592 return;
2593 FVPointOfView((FontViewBase *) fv,&pov_data);
2594 }
2595
FVMenuNLTransform(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2596 static void FVMenuNLTransform(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2597 FontView *fv = (FontView *) GDrawGetUserData(gw);
2598 if ( FVAnyCharSelected(fv)==-1 )
2599 return;
2600 NonLinearDlg(fv,NULL);
2601 }
2602
FVMenuBitmaps(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))2603 static void FVMenuBitmaps(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2604 FontView *fv = (FontView *) GDrawGetUserData(gw);
2605 BitmapDlg(fv,NULL,mi->mid==MID_RemoveBitmaps?-1:(mi->mid==MID_AvailBitmaps) );
2606 }
2607
FVMenuStroke(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2608 static void FVMenuStroke(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2609 FontView *fv = (FontView *) GDrawGetUserData(gw);
2610 FVStroke(fv);
2611 }
2612
2613 # ifdef FONTFORGE_CONFIG_TILEPATH
FVMenuTilePath(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2614 static void FVMenuTilePath(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2615 FontView *fv = (FontView *) GDrawGetUserData(gw);
2616 FVTile(fv);
2617 }
2618
FVMenuPatternTile(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2619 static void FVMenuPatternTile(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2620 FontView *fv = (FontView *) GDrawGetUserData(gw);
2621 FVPatternTile(fv);
2622 }
2623 #endif
2624
FVMenuOverlap(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))2625 static void FVMenuOverlap(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2626 FontView *fv = (FontView *) GDrawGetUserData(gw);
2627
2628 if ( fv->b.sf->onlybitmaps )
2629 return;
2630
2631 /* We know it's more likely that we'll find a problem in the overlap code */
2632 /* than anywhere else, so let's save the current state against a crash */
2633 DoAutoSaves();
2634
2635 FVOverlap(&fv->b,mi->mid==MID_RmOverlap ? over_remove :
2636 mi->mid==MID_Intersection ? over_intersect :
2637 over_findinter);
2638 }
2639
FVMenuInline(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2640 static void FVMenuInline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2641 FontView *fv = (FontView *) GDrawGetUserData(gw);
2642
2643 OutlineDlg(fv,NULL,NULL,true);
2644 }
2645
FVMenuOutline(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2646 static void FVMenuOutline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2647 FontView *fv = (FontView *) GDrawGetUserData(gw);
2648
2649 OutlineDlg(fv,NULL,NULL,false);
2650 }
2651
FVMenuShadow(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2652 static void FVMenuShadow(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2653 FontView *fv = (FontView *) GDrawGetUserData(gw);
2654
2655 ShadowDlg(fv,NULL,NULL,false);
2656 }
2657
FVMenuWireframe(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2658 static void FVMenuWireframe(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2659 FontView *fv = (FontView *) GDrawGetUserData(gw);
2660
2661 ShadowDlg(fv,NULL,NULL,true);
2662 }
2663
FVSimplify(FontView * fv,int type)2664 static void FVSimplify(FontView *fv,int type) {
2665 static struct simplifyinfo smpls[] = {
2666 { sf_normal, 0, 0, 0, 0, 0, 0 },
2667 { sf_normal,.75,.05,0,-1, 0, 0 },
2668 { sf_normal,.75,.05,0,-1, 0, 0 }};
2669 struct simplifyinfo *smpl = &smpls[type+1];
2670
2671 if ( smpl->linelenmax==-1 || (type==0 && !smpl->set_as_default)) {
2672 smpl->err = (fv->b.sf->ascent+fv->b.sf->descent)/1000.;
2673 smpl->linelenmax = (fv->b.sf->ascent+fv->b.sf->descent)/100.;
2674 }
2675
2676 if ( type==1 ) {
2677 if ( !SimplifyDlg(fv->b.sf,smpl))
2678 return;
2679 if ( smpl->set_as_default )
2680 smpls[1] = *smpl;
2681 }
2682 _FVSimplify((FontViewBase *) fv,smpl);
2683 }
2684
FVMenuSimplify(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2685 static void FVMenuSimplify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2686 FVSimplify( (FontView *) GDrawGetUserData(gw),false );
2687 }
2688
FVMenuSimplifyMore(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2689 static void FVMenuSimplifyMore(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2690 FVSimplify( (FontView *) GDrawGetUserData(gw),true );
2691 }
2692
FVMenuCleanup(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2693 static void FVMenuCleanup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2694 FVSimplify( (FontView *) GDrawGetUserData(gw),-1 );
2695 }
2696
FVMenuCanonicalStart(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2697 static void FVMenuCanonicalStart(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2698 FVCanonicalStart( (FontViewBase *) GDrawGetUserData(gw) );
2699 }
2700
FVMenuCanonicalContours(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2701 static void FVMenuCanonicalContours(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2702 FVCanonicalContours( (FontViewBase *) GDrawGetUserData(gw) );
2703 }
2704
FVMenuAddExtrema(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2705 static void FVMenuAddExtrema(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2706 FVAddExtrema( (FontViewBase *) GDrawGetUserData(gw) , false);
2707 }
2708
FVMenuCorrectDir(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2709 static void FVMenuCorrectDir(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2710 FontView *fv = (FontView *) GDrawGetUserData(gw);
2711 FVCorrectDir((FontViewBase *) fv);
2712 }
2713
FVMenuRound2Int(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2714 static void FVMenuRound2Int(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2715 FVRound2Int( (FontViewBase *) GDrawGetUserData(gw), 1.0 );
2716 }
2717
FVMenuRound2Hundredths(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2718 static void FVMenuRound2Hundredths(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2719 FVRound2Int( (FontViewBase *) GDrawGetUserData(gw),100.0 );
2720 }
2721
FVMenuCluster(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2722 static void FVMenuCluster(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2723 FVCluster( (FontViewBase *) GDrawGetUserData(gw));
2724 }
2725
FVMenuAutotrace(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * e)2726 static void FVMenuAutotrace(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2727 FontView *fv = (FontView *) GDrawGetUserData(gw);
2728 GCursor ct=0;
2729
2730 if ( fv->v!=NULL ) {
2731 ct = GDrawGetCursor(fv->v);
2732 GDrawSetCursor(fv->v,ct_watch);
2733 GDrawSync(NULL);
2734 GDrawProcessPendingEvents(NULL);
2735 }
2736 FVAutoTrace(&fv->b,e!=NULL && (e->u.mouse.state&ksm_shift));
2737 if ( fv->v!=NULL )
2738 GDrawSetCursor(fv->v,ct);
2739 }
2740
FVMenuBuildAccent(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2741 static void FVMenuBuildAccent(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2742 FVBuildAccent( (FontViewBase *) GDrawGetUserData(gw), true );
2743 }
2744
FVMenuBuildComposite(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2745 static void FVMenuBuildComposite(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2746 FVBuildAccent( (FontViewBase *) GDrawGetUserData(gw), false );
2747 }
2748
FVMenuBuildDuplicate(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2749 static void FVMenuBuildDuplicate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2750 FVBuildDuplicate( (FontViewBase *) GDrawGetUserData(gw));
2751 }
2752
2753 #ifdef KOREAN
FVMenuShowGroup(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2754 static void FVMenuShowGroup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2755 ShowGroup( ((FontView *) GDrawGetUserData(gw))->sf );
2756 }
2757 #endif
2758
2759 #if HANYANG
FVMenuModifyComposition(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2760 static void FVMenuModifyComposition(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2761 FontView *fv = (FontView *) GDrawGetUserData(gw);
2762 if ( fv->b.sf->rules!=NULL )
2763 SFModifyComposition(fv->b.sf);
2764 }
2765
FVMenuBuildSyllables(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2766 static void FVMenuBuildSyllables(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2767 FontView *fv = (FontView *) GDrawGetUserData(gw);
2768 if ( fv->b.sf->rules!=NULL )
2769 SFBuildSyllables(fv->b.sf);
2770 }
2771 #endif
2772
FVMenuCompareFonts(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2773 static void FVMenuCompareFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2774 FontView *fv = (FontView *) GDrawGetUserData(gw);
2775 FontCompareDlg(fv);
2776 }
2777
FVMenuMergeFonts(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2778 static void FVMenuMergeFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2779 FontView *fv = (FontView *) GDrawGetUserData(gw);
2780 FVMergeFonts(fv);
2781 }
2782
FVMenuInterpFonts(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2783 static void FVMenuInterpFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2784 FontView *fv = (FontView *) GDrawGetUserData(gw);
2785 FVInterpolateFonts(fv);
2786 }
2787
2788 static void FVShowInfo(FontView *fv);
2789
FVChangeChar(FontView * fv,int i)2790 void FVChangeChar(FontView *fv,int i) {
2791
2792 if ( i!=-1 ) {
2793 FVDeselectAll(fv);
2794 fv->b.selected[i] = true;
2795 fv->sel_index = 1;
2796 fv->end_pos = fv->pressed_pos = i;
2797 FVToggleCharSelected(fv,i);
2798 FVScrollToChar(fv,i);
2799 FVShowInfo(fv);
2800 }
2801 }
2802
FVScrollToChar(FontView * fv,int i)2803 void FVScrollToChar(FontView *fv,int i) {
2804
2805 if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
2806 return;
2807
2808 if ( i!=-1 ) {
2809 if ( i/fv->colcnt<fv->rowoff || i/fv->colcnt >= fv->rowoff+fv->rowcnt ) {
2810 fv->rowoff = i/fv->colcnt;
2811 if ( fv->rowcnt>= 3 )
2812 --fv->rowoff;
2813 if ( fv->rowoff+fv->rowcnt>=fv->rowltot )
2814 fv->rowoff = fv->rowltot-fv->rowcnt;
2815 if ( fv->rowoff<0 ) fv->rowoff = 0;
2816 GScrollBarSetPos(fv->vsb,fv->rowoff);
2817 GDrawRequestExpose(fv->v,NULL,false);
2818 }
2819 }
2820 }
2821
FVScrollToGID(FontView * fv,int gid)2822 static void FVScrollToGID(FontView *fv,int gid) {
2823 FVScrollToChar(fv,fv->b.map->backmap[gid]);
2824 }
2825
FV_ChangeGID(FontView * fv,int gid)2826 static void FV_ChangeGID(FontView *fv,int gid) {
2827 FVChangeChar(fv,fv->b.map->backmap[gid]);
2828 }
2829
_FVMenuChangeChar(FontView * fv,int mid)2830 static void _FVMenuChangeChar(FontView *fv,int mid ) {
2831 SplineFont *sf = fv->b.sf;
2832 EncMap *map = fv->b.map;
2833 int pos = FVAnyCharSelected(fv);
2834
2835 if ( pos>=0 ) {
2836 if ( mid==MID_Next )
2837 ++pos;
2838 else if ( mid==MID_Prev )
2839 --pos;
2840 else if ( mid==MID_NextDef ) {
2841 for ( ++pos; pos<map->enccount &&
2842 (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
2843 (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
2844 ++pos );
2845 if ( pos>=map->enccount ) {
2846 int selpos = FVAnyCharSelected(fv);
2847 char *iconv_name = map->enc->iconv_name ? map->enc->iconv_name :
2848 map->enc->enc_name;
2849 if ( strstr(iconv_name,"2022")!=NULL && selpos<0x2121 )
2850 pos = 0x2121;
2851 else if ( strstr(iconv_name,"EUC")!=NULL && selpos<0xa1a1 )
2852 pos = 0xa1a1;
2853 else if ( map->enc->is_tradchinese ) {
2854 if ( strstrmatch(map->enc->enc_name,"HK")!=NULL &&
2855 selpos<0x8140 )
2856 pos = 0x8140;
2857 else
2858 pos = 0xa140;
2859 } else if ( map->enc->is_japanese ) {
2860 if ( strstrmatch(iconv_name,"SJIS")!=NULL ||
2861 (strstrmatch(iconv_name,"JIS")!=NULL && strstrmatch(iconv_name,"SHIFT")!=NULL )) {
2862 if ( selpos<0x8100 )
2863 pos = 0x8100;
2864 else if ( selpos<0xb000 )
2865 pos = 0xb000;
2866 }
2867 } else if ( map->enc->is_korean ) {
2868 if ( strstrmatch(iconv_name,"JOHAB")!=NULL ) {
2869 if ( selpos<0x8431 )
2870 pos = 0x8431;
2871 } else { /* Wansung, EUC-KR */
2872 if ( selpos<0xa1a1 )
2873 pos = 0xa1a1;
2874 }
2875 } else if ( map->enc->is_simplechinese ) {
2876 if ( strmatch(iconv_name,"EUC-CN")==0 && selpos<0xa1a1 )
2877 pos = 0xa1a1;
2878 }
2879 if ( pos>=map->enccount )
2880 return;
2881 }
2882 } else if ( mid==MID_PrevDef ) {
2883 for ( --pos; pos>=0 &&
2884 (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
2885 (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
2886 --pos );
2887 if ( pos<0 )
2888 return;
2889 }
2890 }
2891 if ( pos<0 ) pos = map->enccount-1;
2892 else if ( pos>= map->enccount ) pos = 0;
2893 if ( pos>=0 && pos<map->enccount )
2894 FVChangeChar(fv,pos);
2895 }
2896
FVMenuChangeChar(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))2897 static void FVMenuChangeChar(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2898 FontView *fv = (FontView *) GDrawGetUserData(gw);
2899 _FVMenuChangeChar(fv,mi->mid);
2900 }
2901
FVShowSubFont(FontView * fv,SplineFont * new)2902 static void FVShowSubFont(FontView *fv,SplineFont *new) {
2903 MetricsView *mv, *mvnext;
2904 BDFFont *newbdf;
2905 int wascompact = fv->b.normal!=NULL;
2906 extern int use_freetype_to_rasterize_fv;
2907
2908 for ( mv=fv->b.sf->metrics; mv!=NULL; mv = mvnext ) {
2909 /* Don't bother trying to fix up metrics views, just not worth it */
2910 mvnext = mv->next;
2911 GDrawDestroyWindow(mv->gw);
2912 }
2913 if ( wascompact ) {
2914 EncMapFree(fv->b.map);
2915 if (fv->b.map == fv->b.sf->map) { fv->b.sf->map = fv->b.normal; }
2916 fv->b.map = fv->b.normal;
2917 fv->b.normal = NULL;
2918 fv->b.selected = realloc(fv->b.selected,fv->b.map->enccount);
2919 memset(fv->b.selected,0,fv->b.map->enccount);
2920 }
2921 CIDSetEncMap((FontViewBase *) fv,new);
2922 if ( wascompact ) {
2923 fv->b.normal = EncMapCopy(fv->b.map);
2924 CompactEncMap(fv->b.map,fv->b.sf);
2925 FontViewReformatOne(&fv->b);
2926 FVSetTitle(&fv->b);
2927 }
2928 newbdf = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
2929 (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
2930 (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
2931 NULL);
2932 BDFFontFree(fv->filled);
2933 if ( fv->filled == fv->show )
2934 fv->show = newbdf;
2935 fv->filled = newbdf;
2936 GDrawRequestExpose(fv->v,NULL,true);
2937 }
2938
FVMenuGotoChar(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2939 static void FVMenuGotoChar(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2940 FontView *fv = (FontView *) GDrawGetUserData(gw);
2941 int merge_with_selection = false;
2942 int pos = GotoChar(fv->b.sf,fv->b.map,&merge_with_selection);
2943 if ( fv->b.cidmaster!=NULL && pos!=-1 && !fv->b.map->enc->is_compact ) {
2944 SplineFont *cidmaster = fv->b.cidmaster;
2945 int k, hadk= cidmaster->subfontcnt;
2946 for ( k=0; k<cidmaster->subfontcnt; ++k ) {
2947 SplineFont *sf = cidmaster->subfonts[k];
2948 if ( pos<sf->glyphcnt && sf->glyphs[pos]!=NULL )
2949 break;
2950 if ( pos<sf->glyphcnt )
2951 hadk = k;
2952 }
2953 if ( k==cidmaster->subfontcnt && pos>=fv->b.sf->glyphcnt )
2954 k = hadk;
2955 if ( k!=cidmaster->subfontcnt && cidmaster->subfonts[k] != fv->b.sf )
2956 FVShowSubFont(fv,cidmaster->subfonts[k]);
2957 if ( pos>=fv->b.sf->glyphcnt )
2958 pos = -1;
2959 }
2960 if ( !merge_with_selection )
2961 FVChangeChar(fv,pos);
2962 else {
2963 if ( !fv->b.selected[pos] ) {
2964 fv->b.selected[pos] = ++fv->sel_index;
2965 FVToggleCharSelected(fv,pos);
2966 }
2967 fv->end_pos = fv->pressed_pos = pos;
2968 FVScrollToChar(fv,pos);
2969 FVShowInfo(fv);
2970 }
2971 }
2972
FVMenuLigatures(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2973 static void FVMenuLigatures(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2974 FontView *fv = (FontView *) GDrawGetUserData(gw);
2975 SFShowLigatures(fv->b.sf,NULL);
2976 }
2977
FVMenuKernPairs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2978 static void FVMenuKernPairs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2979 FontView *fv = (FontView *) GDrawGetUserData(gw);
2980 SFKernClassTempDecompose(fv->b.sf,false);
2981 SFShowKernPairs(fv->b.sf,NULL,NULL,fv->b.active_layer);
2982 SFKernCleanup(fv->b.sf,false);
2983 }
2984
FVMenuAnchorPairs(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))2985 static void FVMenuAnchorPairs(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2986 FontView *fv = (FontView *) GDrawGetUserData(gw);
2987 SFShowKernPairs(fv->b.sf,NULL,mi->ti.userdata,fv->b.active_layer);
2988 }
2989
FVMenuShowAtt(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2990 static void FVMenuShowAtt(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2991 FontView *fv = (FontView *) GDrawGetUserData(gw);
2992 ShowAtt(fv->b.sf,fv->b.active_layer);
2993 }
2994
FVMenuDisplaySubs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))2995 static void FVMenuDisplaySubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2996 FontView *fv = (FontView *) GDrawGetUserData(gw);
2997
2998 if ( fv->cur_subtable!=0 ) {
2999 fv->cur_subtable = NULL;
3000 } else {
3001 SplineFont *sf = fv->b.sf;
3002 OTLookup *otf;
3003 struct lookup_subtable *sub;
3004 int cnt, k;
3005 char **names = NULL;
3006 if ( sf->cidmaster ) sf=sf->cidmaster;
3007 for ( k=0; k<2; ++k ) {
3008 cnt = 0;
3009 for ( otf = sf->gsub_lookups; otf!=NULL; otf=otf->next ) {
3010 if ( otf->lookup_type==gsub_single ) {
3011 for ( sub=otf->subtables; sub!=NULL; sub=sub->next ) {
3012 if ( names )
3013 names[cnt] = sub->subtable_name;
3014 ++cnt;
3015 }
3016 }
3017 }
3018 if ( cnt==0 )
3019 break;
3020 if ( names==NULL )
3021 names = malloc((cnt+3) * sizeof(char *));
3022 else {
3023 names[cnt++] = "-";
3024 names[cnt++] = _("New Lookup Subtable...");
3025 names[cnt] = NULL;
3026 }
3027 }
3028 sub = NULL;
3029 if ( names!=NULL ) {
3030 int ret = gwwv_choose(_("Display Substitution..."), (const char **) names, cnt, 0,
3031 _("Pick a substitution to display in the window."));
3032 if ( ret!=-1 )
3033 sub = SFFindLookupSubtable(sf,names[ret]);
3034 free(names);
3035 if ( ret==-1 )
3036 return;
3037 }
3038 if ( sub==NULL )
3039 sub = SFNewLookupSubtableOfType(sf,gsub_single,NULL,fv->b.active_layer);
3040 if ( sub!=NULL )
3041 fv->cur_subtable = sub;
3042 }
3043 GDrawRequestExpose(fv->v,NULL,false);
3044 }
3045
FVChangeDisplayFont(FontView * fv,BDFFont * bdf)3046 static void FVChangeDisplayFont(FontView *fv,BDFFont *bdf) {
3047 int samesize=0;
3048 int rcnt, ccnt;
3049 int oldr, oldc;
3050 int first_time = fv->show==NULL;
3051
3052 if ( fv->v==NULL ) /* Can happen in scripts */
3053 return;
3054
3055 if ( fv->show!=bdf ) {
3056 oldc = fv->cbw*fv->colcnt;
3057 oldr = fv->cbh*fv->rowcnt;
3058
3059 fv->show = bdf;
3060 fv->b.active_bitmap = bdf==fv->filled ? NULL : bdf;
3061 if ( fv->user_requested_magnify!=-1 )
3062 fv->magnify=fv->user_requested_magnify;
3063 else if ( bdf->pixelsize<20 ) {
3064 if ( bdf->pixelsize<=9 )
3065 fv->magnify = 3;
3066 else
3067 fv->magnify = 2;
3068 samesize = ( fv->show && fv->cbw == (bdf->pixelsize*fv->magnify)+1 );
3069 } else
3070 fv->magnify = 1;
3071 if ( !first_time && fv->cbw == fv->magnify*bdf->pixelsize+1 )
3072 samesize = true;
3073 fv->cbw = (bdf->pixelsize*fv->magnify)+1;
3074 fv->cbh = (bdf->pixelsize*fv->magnify)+1+fv->lab_height+1;
3075 fv->resize_expected = !samesize;
3076 ccnt = fv->b.sf->desired_col_cnt;
3077 rcnt = fv->b.sf->desired_row_cnt;
3078 if ((( bdf->pixelsize<=fv->b.sf->display_size || bdf->pixelsize<=-fv->b.sf->display_size ) &&
3079 fv->b.sf->top_enc!=-1 /* Not defaulting */ ) ||
3080 bdf->pixelsize<=48 ) {
3081 /* use the desired sizes */
3082 } else {
3083 if ( bdf->pixelsize>48 ) {
3084 ccnt = 8;
3085 rcnt = 2;
3086 } else if ( bdf->pixelsize>=96 ) {
3087 ccnt = 4;
3088 rcnt = 1;
3089 }
3090 if ( !first_time ) {
3091 if ( ccnt < oldc/fv->cbw )
3092 ccnt = oldc/fv->cbw;
3093 if ( rcnt < oldr/fv->cbh )
3094 rcnt = oldr/fv->cbh;
3095 }
3096 }
3097 if ( samesize ) {
3098 GDrawRequestExpose(fv->v,NULL,false);
3099 } else if ( fv->b.container!=NULL && fv->b.container->funcs->doResize!=NULL ) {
3100 (fv->b.container->funcs->doResize)(fv->b.container,&fv->b,
3101 ccnt*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3102 rcnt*fv->cbh+1+fv->mbh+fv->infoh);
3103 } else {
3104 GDrawResize(fv->gw,
3105 ccnt*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3106 rcnt*fv->cbh+1+fv->mbh+fv->infoh);
3107 }
3108 }
3109 }
3110
3111 struct md_data {
3112 int done;
3113 int ish;
3114 FontView *fv;
3115 };
3116
md_e_h(GWindow gw,GEvent * e)3117 static int md_e_h(GWindow gw, GEvent *e) {
3118 if ( e->type==et_close ) {
3119 struct md_data *d = GDrawGetUserData(gw);
3120 d->done = true;
3121 } else if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
3122 struct md_data *d = GDrawGetUserData(gw);
3123 static int masks[] = { fvm_baseline, fvm_origin, fvm_advanceat, fvm_advanceto, -1 };
3124 int i, metrics;
3125 if ( GGadgetGetCid(e->u.control.g)==10 ) {
3126 metrics = 0;
3127 for ( i=0; masks[i]!=-1 ; ++i )
3128 if ( GGadgetIsChecked(GWidgetGetControl(gw,masks[i])))
3129 metrics |= masks[i];
3130 if ( d->ish )
3131 default_fv_showhmetrics = d->fv->showhmetrics = metrics;
3132 else
3133 default_fv_showvmetrics = d->fv->showvmetrics = metrics;
3134 }
3135 d->done = true;
3136 } else if ( e->type==et_char ) {
3137 return( false );
3138 }
3139 return( true );
3140 }
3141
FVMenuShowMetrics(GWindow fvgw,struct gmenuitem * mi,GEvent * UNUSED (e))3142 static void FVMenuShowMetrics(GWindow fvgw,struct gmenuitem *mi, GEvent *UNUSED(e)) {
3143 FontView *fv = (FontView *) GDrawGetUserData(fvgw);
3144 GRect pos;
3145 GWindow gw;
3146 GWindowAttrs wattrs;
3147 struct md_data d;
3148 GGadgetCreateData gcd[7];
3149 GTextInfo label[6];
3150 int metrics = mi->mid==MID_ShowHMetrics ? fv->showhmetrics : fv->showvmetrics;
3151
3152 d.fv = fv;
3153 d.done = 0;
3154 d.ish = mi->mid==MID_ShowHMetrics;
3155
3156 memset(&wattrs,0,sizeof(wattrs));
3157 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
3158 wattrs.event_masks = ~(1<<et_charup);
3159 wattrs.restrict_input_to_me = 1;
3160 wattrs.undercursor = 1;
3161 wattrs.cursor = ct_pointer;
3162 wattrs.utf8_window_title = d.ish?_("Show H. Metrics"):_("Show V. Metrics");
3163 pos.x = pos.y = 0;
3164 pos.width =GDrawPointsToPixels(NULL,GGadgetScale(170));
3165 pos.height = GDrawPointsToPixels(NULL,130);
3166 gw = GDrawCreateTopWindow(NULL,&pos,md_e_h,&d,&wattrs);
3167
3168 memset(&label,0,sizeof(label));
3169 memset(&gcd,0,sizeof(gcd));
3170
3171 label[0].text = (unichar_t *) _("Baseline");
3172 label[0].text_is_1byte = true;
3173 gcd[0].gd.label = &label[0];
3174 gcd[0].gd.pos.x = 8; gcd[0].gd.pos.y = 8;
3175 gcd[0].gd.flags = gg_enabled|gg_visible|(metrics&fvm_baseline?gg_cb_on:0);
3176 gcd[0].gd.cid = fvm_baseline;
3177 gcd[0].creator = GCheckBoxCreate;
3178
3179 label[1].text = (unichar_t *) _("Origin");
3180 label[1].text_is_1byte = true;
3181 gcd[1].gd.label = &label[1];
3182 gcd[1].gd.pos.x = 8; gcd[1].gd.pos.y = gcd[0].gd.pos.y+16;
3183 gcd[1].gd.flags = gg_enabled|gg_visible|(metrics&fvm_origin?gg_cb_on:0);
3184 gcd[1].gd.cid = fvm_origin;
3185 gcd[1].creator = GCheckBoxCreate;
3186
3187 label[2].text = (unichar_t *) _("Advance Width as a Line");
3188 label[2].text_is_1byte = true;
3189 gcd[2].gd.label = &label[2];
3190 gcd[2].gd.pos.x = 8; gcd[2].gd.pos.y = gcd[1].gd.pos.y+16;
3191 gcd[2].gd.flags = gg_enabled|gg_visible|(metrics&fvm_advanceat?gg_cb_on:0);
3192 gcd[2].gd.cid = fvm_advanceat;
3193 gcd[2].gd.popup_msg = _("Display the advance width as a line\nperpendicular to the advance direction");
3194 gcd[2].creator = GCheckBoxCreate;
3195
3196 label[3].text = (unichar_t *) _("Advance Width as a Bar");
3197 label[3].text_is_1byte = true;
3198 gcd[3].gd.label = &label[3];
3199 gcd[3].gd.pos.x = 8; gcd[3].gd.pos.y = gcd[2].gd.pos.y+16;
3200 gcd[3].gd.flags = gg_enabled|gg_visible|(metrics&fvm_advanceto?gg_cb_on:0);
3201 gcd[3].gd.cid = fvm_advanceto;
3202 gcd[3].gd.popup_msg = _("Display the advance width as a bar under the glyph\nshowing the extent of the advance");
3203 gcd[3].creator = GCheckBoxCreate;
3204
3205 label[4].text = (unichar_t *) _("_OK");
3206 label[4].text_is_1byte = true;
3207 label[4].text_in_resource = true;
3208 gcd[4].gd.label = &label[4];
3209 gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
3210 gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
3211 gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
3212 gcd[4].gd.cid = 10;
3213 gcd[4].creator = GButtonCreate;
3214
3215 label[5].text = (unichar_t *) _("_Cancel");
3216 label[5].text_is_1byte = true;
3217 label[5].text_in_resource = true;
3218 gcd[5].gd.label = &label[5];
3219 gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = gcd[4].gd.pos.y+3;
3220 gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
3221 gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3222 gcd[5].creator = GButtonCreate;
3223
3224 GGadgetsCreate(gw,gcd);
3225
3226 GDrawSetVisible(gw,true);
3227 while ( !d.done )
3228 GDrawProcessOneEvent(NULL);
3229 GDrawDestroyWindow(gw);
3230
3231 SavePrefs(true);
3232 GDrawRequestExpose(fv->v,NULL,false);
3233 }
3234
FV_ChangeDisplayBitmap(FontView * fv,BDFFont * bdf)3235 static void FV_ChangeDisplayBitmap(FontView *fv,BDFFont *bdf) {
3236 FVChangeDisplayFont(fv,bdf);
3237 if (fv->show != NULL) {
3238 fv->b.sf->display_size = fv->show->pixelsize;
3239 } else {
3240 fv->b.sf->display_size = 1;
3241 }
3242 }
3243
FVMenuSize(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3244 static void FVMenuSize(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3245 FontView *fv = (FontView *) GDrawGetUserData(gw);
3246 int dspsize = fv->filled->pixelsize;
3247 int changedmodifier = false;
3248 extern int use_freetype_to_rasterize_fv;
3249
3250 fv->magnify = 1;
3251 fv->user_requested_magnify = -1;
3252 if ( mi->mid == MID_24 )
3253 default_fv_font_size = dspsize = 24;
3254 else if ( mi->mid == MID_36 )
3255 default_fv_font_size = dspsize = 36;
3256 else if ( mi->mid == MID_48 )
3257 default_fv_font_size = dspsize = 48;
3258 else if ( mi->mid == MID_72 )
3259 default_fv_font_size = dspsize = 72;
3260 else if ( mi->mid == MID_96 )
3261 default_fv_font_size = dspsize = 96;
3262 else if ( mi->mid == MID_128 )
3263 default_fv_font_size = dspsize = 128;
3264 else if ( mi->mid == MID_FitToBbox ) {
3265 default_fv_bbsized = fv->bbsized = !fv->bbsized;
3266 fv->b.sf->display_bbsized = fv->bbsized;
3267 changedmodifier = true;
3268 } else {
3269 default_fv_antialias = fv->antialias = !fv->antialias;
3270 fv->b.sf->display_antialias = fv->antialias;
3271 changedmodifier = true;
3272 }
3273
3274 SavePrefs(true);
3275 if ( fv->filled!=fv->show || fv->filled->pixelsize != dspsize || changedmodifier ) {
3276 BDFFont *new, *old;
3277 old = fv->filled;
3278 new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,dspsize,72,
3279 (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
3280 (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
3281 NULL);
3282 fv->filled = new;
3283 FVChangeDisplayFont(fv,new);
3284 BDFFontFree(old);
3285 fv->b.sf->display_size = -dspsize;
3286 if ( fv->b.cidmaster!=NULL ) {
3287 int i;
3288 for ( i=0; i<fv->b.cidmaster->subfontcnt; ++i )
3289 fv->b.cidmaster->subfonts[i]->display_size = -dspsize;
3290 }
3291 }
3292 }
3293
FVSetUIToMatch(FontView * destfv,FontView * srcfv)3294 void FVSetUIToMatch(FontView *destfv,FontView *srcfv) {
3295 extern int use_freetype_to_rasterize_fv;
3296
3297 if ( destfv->filled==NULL || srcfv->filled==NULL )
3298 return;
3299 if ( destfv->magnify!=srcfv->magnify ||
3300 destfv->user_requested_magnify!=srcfv->user_requested_magnify ||
3301 destfv->bbsized!=srcfv->bbsized ||
3302 destfv->antialias!=srcfv->antialias ||
3303 destfv->filled->pixelsize != srcfv->filled->pixelsize ) {
3304 BDFFont *new, *old;
3305 destfv->magnify = srcfv->magnify;
3306 destfv->user_requested_magnify = srcfv->user_requested_magnify;
3307 destfv->bbsized = srcfv->bbsized;
3308 destfv->antialias = srcfv->antialias;
3309 old = destfv->filled;
3310 new = SplineFontPieceMeal(destfv->b.sf,destfv->b.active_layer,srcfv->filled->pixelsize,72,
3311 (destfv->antialias?pf_antialias:0)|(destfv->bbsized?pf_bbsized:0)|
3312 (use_freetype_to_rasterize_fv && !destfv->b.sf->strokedfont && !destfv->b.sf->multilayer?pf_ft_nohints:0),
3313 NULL);
3314 destfv->filled = new;
3315 FVChangeDisplayFont(destfv,new);
3316 BDFFontFree(old);
3317 }
3318 }
3319
FV_LayerChanged(FontView * fv)3320 static void FV_LayerChanged( FontView *fv ) {
3321 extern int use_freetype_to_rasterize_fv;
3322 BDFFont *new, *old;
3323
3324 fv->magnify = 1;
3325 fv->user_requested_magnify = -1;
3326
3327 old = fv->filled;
3328 new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
3329 (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
3330 (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
3331 NULL);
3332 fv->filled = new;
3333 FVChangeDisplayFont(fv,new);
3334 fv->b.sf->display_size = -fv->filled->pixelsize;
3335 BDFFontFree(old);
3336 }
3337
FVMenuChangeLayer(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3338 static void FVMenuChangeLayer(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3339 FontView *fv = (FontView *) GDrawGetUserData(gw);
3340
3341 fv->b.active_layer = mi->mid;
3342 fv->b.sf->display_layer = mi->mid;
3343 FV_LayerChanged(fv);
3344 }
3345
FVMenuMagnify(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3346 static void FVMenuMagnify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3347 FontView *fv = (FontView *) GDrawGetUserData(gw);
3348 int magnify = fv->user_requested_magnify!=-1 ? fv->user_requested_magnify : fv->magnify;
3349 char def[20], *end, *ret;
3350 int val;
3351 BDFFont *show = fv->show;
3352
3353 sprintf( def, "%d", magnify );
3354 ret = gwwv_ask_string(_("Bitmap Magnification..."),def,_("Please specify a bitmap magnification factor."));
3355 if ( ret==NULL )
3356 return;
3357 val = strtol(ret,&end,10);
3358 if ( val<1 || val>5 || *end!='\0' )
3359 ff_post_error( _("Bad Number"),_("Bad Number") );
3360 else {
3361 fv->user_requested_magnify = val;
3362 fv->show = fv->filled;
3363 fv->b.active_bitmap = NULL;
3364 FVChangeDisplayFont(fv,show);
3365 }
3366 free(ret);
3367 }
3368
FVMenuWSize(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3369 static void FVMenuWSize(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3370 FontView *fv = (FontView *) GDrawGetUserData(gw);
3371 int h,v;
3372 extern int default_fv_col_count, default_fv_row_count;
3373
3374 if ( mi->mid == MID_32x8 ) {
3375 h = 32; v=8;
3376 } else if ( mi->mid == MID_16x4 ) {
3377 h = 16; v=4;
3378 } else {
3379 h = 8; v=2;
3380 }
3381 GDrawResize(fv->gw,
3382 h*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3383 v*fv->cbh+1+fv->mbh+fv->infoh);
3384 fv->b.sf->desired_col_cnt = default_fv_col_count = h;
3385 fv->b.sf->desired_row_cnt = default_fv_row_count = v;
3386
3387 SavePrefs(true);
3388 }
3389
FVMenuGlyphLabel(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3390 static void FVMenuGlyphLabel(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3391 FontView *fv = (FontView *) GDrawGetUserData(gw);
3392
3393 default_fv_glyphlabel = fv->glyphlabel = mi->mid;
3394
3395 GDrawRequestExpose(fv->v,NULL,false);
3396
3397 SavePrefs(true);
3398 }
3399
FVMenuShowBitmap(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3400 static void FVMenuShowBitmap(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3401 FontView *fv = (FontView *) GDrawGetUserData(gw);
3402 BDFFont *bdf = mi->ti.userdata;
3403
3404 FV_ChangeDisplayBitmap(fv,bdf); /* Let's not change any of the others */
3405 }
3406
FV_ShowFilled(FontView * fv)3407 static void FV_ShowFilled(FontView *fv) {
3408
3409 fv->magnify = 1;
3410 fv->user_requested_magnify = 1;
3411 if ( fv->show!=fv->filled )
3412 FVChangeDisplayFont(fv,fv->filled);
3413 fv->b.sf->display_size = -fv->filled->pixelsize;
3414 fv->b.active_bitmap = NULL;
3415 }
3416
FVMenuCenter(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3417 static void FVMenuCenter(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3418 FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
3419 FVMetricsCenter(fv,mi->mid==MID_Center);
3420 }
3421
FVMenuSetWidth(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3422 static void FVMenuSetWidth(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3423 FontView *fv = (FontView *) GDrawGetUserData(gw);
3424
3425 if ( FVAnyCharSelected(fv)==-1 )
3426 return;
3427 if ( mi->mid == MID_SetVWidth && !fv->b.sf->hasvmetrics )
3428 return;
3429 FVSetWidth(fv,mi->mid==MID_SetWidth ?wt_width:
3430 mi->mid==MID_SetLBearing?wt_lbearing:
3431 mi->mid==MID_SetRBearing?wt_rbearing:
3432 mi->mid==MID_SetBearings?wt_bearings:
3433 wt_vwidth);
3434 }
3435
FVMenuAutoWidth(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3436 static void FVMenuAutoWidth(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3437 FontView *fv = (FontView *) GDrawGetUserData(gw);
3438
3439 FVAutoWidth2(fv);
3440 }
3441
FVMenuKernByClasses(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3442 static void FVMenuKernByClasses(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3443 FontView *fv = (FontView *) GDrawGetUserData(gw);
3444
3445 ShowKernClasses(fv->b.sf,NULL,fv->b.active_layer,false);
3446 }
3447
FVMenuVKernByClasses(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3448 static void FVMenuVKernByClasses(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3449 FontView *fv = (FontView *) GDrawGetUserData(gw);
3450
3451 ShowKernClasses(fv->b.sf,NULL,fv->b.active_layer,true);
3452 }
3453
FVMenuRemoveKern(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3454 static void FVMenuRemoveKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3455 FontView *fv = (FontView *) GDrawGetUserData(gw);
3456
3457 FVRemoveKerns(&fv->b);
3458 }
3459
FVMenuRemoveVKern(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3460 static void FVMenuRemoveVKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3461 FontView *fv = (FontView *) GDrawGetUserData(gw);
3462
3463 FVRemoveVKerns(&fv->b);
3464 }
3465
FVMenuKPCloseup(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3466 static void FVMenuKPCloseup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3467 FontView *fv = (FontView *) GDrawGetUserData(gw);
3468 int i;
3469
3470 for ( i=0; i<fv->b.map->enccount; ++i )
3471 if ( fv->b.selected[i] )
3472 break;
3473 KernPairD(fv->b.sf,i==fv->b.map->enccount?NULL:
3474 fv->b.map->map[i]==-1?NULL:
3475 fv->b.sf->glyphs[fv->b.map->map[i]],NULL,fv->b.active_layer,
3476 false);
3477 }
3478
FVMenuVKernFromHKern(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3479 static void FVMenuVKernFromHKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3480 FontView *fv = (FontView *) GDrawGetUserData(gw);
3481
3482 FVVKernFromHKern(&fv->b);
3483 }
3484
FVMenuAutoHint(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3485 static void FVMenuAutoHint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3486 FontView *fv = (FontView *) GDrawGetUserData(gw);
3487 FVAutoHint( &fv->b );
3488 }
3489
FVMenuAutoHintSubs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3490 static void FVMenuAutoHintSubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3491 FontView *fv = (FontView *) GDrawGetUserData(gw);
3492 FVAutoHintSubs( &fv->b );
3493 }
3494
FVMenuAutoCounter(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3495 static void FVMenuAutoCounter(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3496 FontView *fv = (FontView *) GDrawGetUserData(gw);
3497 FVAutoCounter( &fv->b );
3498 }
3499
FVMenuDontAutoHint(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3500 static void FVMenuDontAutoHint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3501 FontView *fv = (FontView *) GDrawGetUserData(gw);
3502 FVDontAutoHint( &fv->b );
3503 }
3504
FVMenuDeltas(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3505 static void FVMenuDeltas(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3506 FontView *fv = (FontView *) GDrawGetUserData(gw);
3507
3508 if ( !hasFreeTypeDebugger())
3509 return;
3510 DeltaSuggestionDlg(fv,NULL);
3511 }
3512
FVMenuAutoInstr(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3513 static void FVMenuAutoInstr(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3514 FontView *fv = (FontView *) GDrawGetUserData(gw);
3515 FVAutoInstr( &fv->b );
3516 }
3517
FVMenuEditInstrs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3518 static void FVMenuEditInstrs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3519 FontView *fv = (FontView *) GDrawGetUserData(gw);
3520 int index = FVAnyCharSelected(fv);
3521 SplineChar *sc;
3522 if ( index<0 )
3523 return;
3524 sc = SFMakeChar(fv->b.sf,fv->b.map,index);
3525 SCEditInstructions(sc);
3526 }
3527
FVMenuEditTable(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3528 static void FVMenuEditTable(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3529 FontView *fv = (FontView *) GDrawGetUserData(gw);
3530 SFEditTable(fv->b.sf,
3531 mi->mid==MID_Editprep?CHR('p','r','e','p'):
3532 mi->mid==MID_Editfpgm?CHR('f','p','g','m'):
3533 mi->mid==MID_Editmaxp?CHR('m','a','x','p'):
3534 CHR('c','v','t',' '));
3535 }
3536
FVMenuRmInstrTables(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3537 static void FVMenuRmInstrTables(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3538 FontView *fv = (FontView *) GDrawGetUserData(gw);
3539 TtfTablesFree(fv->b.sf->ttf_tables);
3540 fv->b.sf->ttf_tables = NULL;
3541 if ( !fv->b.sf->changed ) {
3542 fv->b.sf->changed = true;
3543 FVSetTitles(fv->b.sf);
3544 }
3545 }
3546
FVMenuClearInstrs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3547 static void FVMenuClearInstrs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3548 FontView *fv = (FontView *) GDrawGetUserData(gw);
3549 FVClearInstrs(&fv->b);
3550 }
3551
FVMenuClearHints(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3552 static void FVMenuClearHints(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3553 FontView *fv = (FontView *) GDrawGetUserData(gw);
3554 FVClearHints(&fv->b);
3555 }
3556
FVMenuHistograms(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3557 static void FVMenuHistograms(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3558 FontView *fv = (FontView *) GDrawGetUserData(gw);
3559 SFHistogram(fv->b.sf, fv->b.active_layer, NULL,
3560 FVAnyCharSelected(fv)!=-1?fv->b.selected:NULL,
3561 fv->b.map,
3562 mi->mid==MID_HStemHist ? hist_hstem :
3563 mi->mid==MID_VStemHist ? hist_vstem :
3564 hist_blues);
3565 }
3566
3567
FontViewSetTitle(FontView * fv)3568 static void FontViewSetTitle(FontView *fv) {
3569 unichar_t *title, *ititle, *temp;
3570 char *file=NULL;
3571 char *enc;
3572 int len;
3573
3574 if ( fv->gw==NULL ) /* In scripting */
3575 return;
3576
3577 enc = SFEncodingName(fv->b.sf,fv->b.normal?fv->b.normal:fv->b.map);
3578 len = strlen(fv->b.sf->fontname)+1 + strlen(enc)+6;
3579 if ( fv->b.normal ) len += strlen(_("Compact"))+1;
3580 if ( fv->b.cidmaster!=NULL ) {
3581 if ( (file = fv->b.cidmaster->filename)==NULL )
3582 file = fv->b.cidmaster->origname;
3583 } else {
3584 if ( (file = fv->b.sf->filename)==NULL )
3585 file = fv->b.sf->origname;
3586 }
3587 if ( file!=NULL )
3588 len += 2+strlen(file);
3589 title = malloc((len+1)*sizeof(unichar_t));
3590 uc_strcpy(title,"");
3591 uc_strcat(title,fv->b.sf->fontname);
3592 if ( fv->b.sf->changed )
3593 uc_strcat(title,"*");
3594 if ( file!=NULL ) {
3595 uc_strcat(title," ");
3596 temp = def2u_copy(GFileNameTail(file));
3597 u_strcat(title,temp);
3598 free(temp);
3599 }
3600 uc_strcat(title, " (" );
3601 if ( fv->b.normal ) { utf82u_strcat(title,_("Compact")); uc_strcat(title," "); }
3602 uc_strcat(title,enc);
3603 uc_strcat(title, ")" );
3604 free(enc);
3605
3606 ititle = uc_copy(fv->b.sf->fontname);
3607 GDrawSetWindowTitles(fv->gw,title,ititle);
3608 free(title);
3609 free(ititle);
3610 }
3611
FVTitleUpdate(FontViewBase * fv)3612 void FVTitleUpdate(FontViewBase *fv)
3613 {
3614 FontViewSetTitle( (FontView*)fv );
3615 }
3616
FontViewSetTitles(SplineFont * sf)3617 static void FontViewSetTitles(SplineFont *sf) {
3618 FontView *fv;
3619
3620 for ( fv = (FontView *) (sf->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame))
3621 FontViewSetTitle(fv);
3622 }
3623
FVMenuShowSubFont(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3624 static void FVMenuShowSubFont(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3625 FontView *fv = (FontView *) GDrawGetUserData(gw);
3626 SplineFont *new = mi->ti.userdata;
3627 FVShowSubFont(fv,new);
3628 }
3629
FVMenuConvert2CID(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3630 static void FVMenuConvert2CID(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3631 FontView *fv = (FontView *) GDrawGetUserData(gw);
3632 SplineFont *cidmaster = fv->b.cidmaster;
3633 struct cidmap *cidmap;
3634
3635 if ( cidmaster!=NULL )
3636 return;
3637 SFFindNearTop(fv->b.sf);
3638 cidmap = AskUserForCIDMap();
3639 if ( cidmap==NULL )
3640 return;
3641 MakeCIDMaster(fv->b.sf,fv->b.map,false,NULL,cidmap);
3642 SFRestoreNearTop(fv->b.sf);
3643 }
3644
CMapFilter(GGadget * g,GDirEntry * ent,const unichar_t * dir)3645 static enum fchooserret CMapFilter(GGadget *g,GDirEntry *ent,
3646 const unichar_t *dir) {
3647 enum fchooserret ret = GFileChooserDefFilter(g,ent,dir);
3648 char buf2[256];
3649 FILE *file;
3650 static char *cmapflag = "%!PS-Adobe-3.0 Resource-CMap";
3651
3652 if ( ret==fc_show && !ent->isdir ) {
3653 int len = 3*(u_strlen(dir)+u_strlen(ent->name)+5);
3654 char *filename = malloc(len);
3655 u2def_strncpy(filename,dir,len);
3656 strcat(filename,"/");
3657 u2def_strncpy(buf2,ent->name,sizeof(buf2));
3658 strcat(filename,buf2);
3659 file = fopen(filename,"r");
3660 if ( file==NULL )
3661 ret = fc_hide;
3662 else {
3663 if ( fgets(buf2,sizeof(buf2),file)==NULL ||
3664 strncmp(buf2,cmapflag,strlen(cmapflag))!=0 )
3665 ret = fc_hide;
3666 fclose(file);
3667 }
3668 free(filename);
3669 }
3670 return( ret );
3671 }
3672
FVMenuConvertByCMap(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3673 static void FVMenuConvertByCMap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3674 FontView *fv = (FontView *) GDrawGetUserData(gw);
3675 SplineFont *cidmaster = fv->b.cidmaster;
3676 char *cmapfilename;
3677
3678 if ( cidmaster!=NULL )
3679 return;
3680 cmapfilename = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
3681 if ( cmapfilename==NULL )
3682 return;
3683 MakeCIDMaster(fv->b.sf,fv->b.map,true,cmapfilename,NULL);
3684 free(cmapfilename);
3685 }
3686
FVMenuFlatten(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3687 static void FVMenuFlatten(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3688 FontView *fv = (FontView *) GDrawGetUserData(gw);
3689 SplineFont *cidmaster = fv->b.cidmaster;
3690
3691 if ( cidmaster==NULL )
3692 return;
3693 SFFlatten(&cidmaster);
3694 }
3695
FVMenuFlattenByCMap(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3696 static void FVMenuFlattenByCMap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3697 FontView *fv = (FontView *) GDrawGetUserData(gw);
3698 SplineFont *cidmaster = fv->b.cidmaster;
3699 char *cmapname;
3700
3701 if ( cidmaster==NULL )
3702 return;
3703 cmapname = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
3704 if ( cmapname==NULL )
3705 return;
3706 SFFindNearTop(fv->b.sf);
3707 SFFlattenByCMap(&cidmaster,cmapname);
3708 SFRestoreNearTop(fv->b.sf);
3709 free(cmapname);
3710 }
3711
FVMenuInsertFont(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3712 static void FVMenuInsertFont(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3713 FontView *fv = (FontView *) GDrawGetUserData(gw);
3714 SplineFont *cidmaster = fv->b.cidmaster;
3715 SplineFont *new;
3716 struct cidmap *map;
3717 char *filename;
3718 extern NameList *force_names_when_opening;
3719
3720 if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
3721 return;
3722
3723 filename = GetPostScriptFontName(NULL,false,true);
3724 if ( filename==NULL )
3725 return;
3726 new = LoadSplineFont(filename,0);
3727 free(filename);
3728 if ( new==NULL )
3729 return;
3730 if ( new->fv == &fv->b ) /* Already part of us */
3731 return;
3732 if ( new->fv != NULL ) {
3733 if ( ((FontView *) (new->fv))->gw!=NULL )
3734 GDrawRaise( ((FontView *) (new->fv))->gw);
3735 ff_post_error(_("Please close font"),_("Please close %s before inserting it into a CID font"),new->origname);
3736 return;
3737 }
3738 EncMapFree(new->map);
3739 if ( force_names_when_opening!=NULL )
3740 SFRenameGlyphsToNamelist(new,force_names_when_opening );
3741
3742 map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
3743 SFEncodeToMap(new,map);
3744 if ( !PSDictHasEntry(new->private,"lenIV"))
3745 PSDictChangeEntry(new->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
3746 new->display_antialias = fv->b.sf->display_antialias;
3747 new->display_bbsized = fv->b.sf->display_bbsized;
3748 new->display_size = fv->b.sf->display_size;
3749 FVInsertInCID((FontViewBase *) fv,new);
3750 CIDMasterAsDes(new);
3751 }
3752
FVMenuInsertBlank(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3753 static void FVMenuInsertBlank(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3754 FontView *fv = (FontView *) GDrawGetUserData(gw);
3755 SplineFont *cidmaster = fv->b.cidmaster, *sf;
3756 struct cidmap *map;
3757
3758 if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
3759 return;
3760 map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
3761 sf = SplineFontBlank(MaxCID(map));
3762 sf->glyphcnt = sf->glyphmax;
3763 sf->cidmaster = cidmaster;
3764 sf->display_antialias = fv->b.sf->display_antialias;
3765 sf->display_bbsized = fv->b.sf->display_bbsized;
3766 sf->display_size = fv->b.sf->display_size;
3767 sf->private = calloc(1,sizeof(struct psdict));
3768 PSDictChangeEntry(sf->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
3769 FVInsertInCID((FontViewBase *) fv,sf);
3770 }
3771
FVMenuRemoveFontFromCID(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3772 static void FVMenuRemoveFontFromCID(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3773 FontView *fv = (FontView *) GDrawGetUserData(gw);
3774 char *buts[3];
3775 SplineFont *cidmaster = fv->b.cidmaster, *sf = fv->b.sf, *replace;
3776 int i;
3777 MetricsView *mv, *mnext;
3778 FontView *fvs;
3779
3780 if ( cidmaster==NULL || cidmaster->subfontcnt<=1 ) /* Can't remove last font */
3781 return;
3782 buts[0] = _("_Remove"); buts[1] = _("_Cancel"); buts[2] = NULL;
3783 if ( gwwv_ask(_("_Remove Font"),(const char **) buts,0,1,_("Are you sure you wish to remove sub-font %1$.40s from the CID font %2$.40s"),
3784 sf->fontname,cidmaster->fontname)==1 )
3785 return;
3786
3787 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
3788 CharView *cv, *next;
3789 for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
3790 next = (CharView *) (cv->b.next);
3791 GDrawDestroyWindow(cv->gw);
3792 }
3793 }
3794 GDrawProcessPendingEvents(NULL);
3795 for ( mv=fv->b.sf->metrics; mv!=NULL; mv = mnext ) {
3796 mnext = mv->next;
3797 GDrawDestroyWindow(mv->gw);
3798 }
3799 GDrawSync(NULL);
3800 GDrawProcessPendingEvents(NULL);
3801 /* Just in case... */
3802 GDrawSync(NULL);
3803 GDrawProcessPendingEvents(NULL);
3804
3805 for ( i=0; i<cidmaster->subfontcnt; ++i )
3806 if ( cidmaster->subfonts[i]==sf )
3807 break;
3808 replace = i==0?cidmaster->subfonts[1]:cidmaster->subfonts[i-1];
3809 while ( i<cidmaster->subfontcnt-1 ) {
3810 cidmaster->subfonts[i] = cidmaster->subfonts[i+1];
3811 ++i;
3812 }
3813 --cidmaster->subfontcnt;
3814
3815 for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) ) {
3816 if ( fvs->b.sf==sf )
3817 CIDSetEncMap((FontViewBase *) fvs,replace);
3818 }
3819 FontViewReformatAll(fv->b.sf);
3820 SplineFontFree(sf);
3821 }
3822
FVMenuCIDFontInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3823 static void FVMenuCIDFontInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3824 FontView *fv = (FontView *) GDrawGetUserData(gw);
3825 SplineFont *cidmaster = fv->b.cidmaster;
3826
3827 if ( cidmaster==NULL )
3828 return;
3829 FontInfo(cidmaster,fv->b.active_layer,-1,false);
3830 }
3831
FVMenuChangeSupplement(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3832 static void FVMenuChangeSupplement(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3833 FontView *fv = (FontView *) GDrawGetUserData(gw);
3834 SplineFont *cidmaster = fv->b.cidmaster;
3835 struct cidmap *cidmap;
3836 char buffer[20];
3837 char *ret, *end;
3838 int supple;
3839
3840 if ( cidmaster==NULL )
3841 return;
3842 sprintf(buffer,"%d",cidmaster->supplement);
3843 ret = gwwv_ask_string(_("Change Supplement..."),buffer,_("Please specify a new supplement for %.20s-%.20s"),
3844 cidmaster->cidregistry,cidmaster->ordering);
3845 if ( ret==NULL )
3846 return;
3847 supple = strtol(ret,&end,10);
3848 if ( *end!='\0' || supple<=0 ) {
3849 free(ret);
3850 ff_post_error( _("Bad Number"),_("Bad Number") );
3851 return;
3852 }
3853 free(ret);
3854 if ( supple!=cidmaster->supplement ) {
3855 /* this will make noises if it can't find an appropriate cidmap */
3856 cidmap = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,supple,cidmaster);
3857 cidmaster->supplement = supple;
3858 FontViewSetTitle(fv);
3859 }
3860 }
3861
FVFindACharInDisplay(FontView * fv)3862 static SplineChar *FVFindACharInDisplay(FontView *fv) {
3863 int start, end, enc, gid;
3864 EncMap *map = fv->b.map;
3865 SplineFont *sf = fv->b.sf;
3866 SplineChar *sc;
3867
3868 start = fv->rowoff*fv->colcnt;
3869 end = start + fv->rowcnt*fv->colcnt;
3870 for ( enc = start; enc<end && enc<map->enccount; ++enc ) {
3871 if ( (gid=map->map[enc])!=-1 && (sc=sf->glyphs[gid])!=NULL )
3872 return( sc );
3873 }
3874 return( NULL );
3875 }
3876
FVMenuReencode(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3877 static void FVMenuReencode(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3878 FontView *fv = (FontView *) GDrawGetUserData(gw);
3879 Encoding *enc = NULL;
3880 SplineChar *sc;
3881
3882 sc = FVFindACharInDisplay(fv);
3883 enc = FindOrMakeEncoding(mi->ti.userdata);
3884 if ( enc==NULL ) {
3885 IError("Known encoding could not be found");
3886 return;
3887 }
3888 FVReencode((FontViewBase *) fv,enc);
3889 if ( sc!=NULL ) {
3890 int enc = fv->b.map->backmap[sc->orig_pos];
3891 if ( enc!=-1 )
3892 FVScrollToChar(fv,enc);
3893 }
3894 }
3895
FVMenuForceEncode(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3896 static void FVMenuForceEncode(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3897 FontView *fv = (FontView *) GDrawGetUserData(gw);
3898 Encoding *enc = NULL;
3899 int oldcnt = fv->b.map->enccount;
3900
3901 enc = FindOrMakeEncoding(mi->ti.userdata);
3902 if ( enc==NULL ) {
3903 IError("Known encoding could not be found");
3904 return;
3905 }
3906 SFForceEncoding(fv->b.sf,fv->b.map,enc);
3907 if ( oldcnt < fv->b.map->enccount ) {
3908 fv->b.selected = realloc(fv->b.selected,fv->b.map->enccount);
3909 memset(fv->b.selected+oldcnt,0,fv->b.map->enccount-oldcnt);
3910 }
3911 if ( fv->b.normal!=NULL ) {
3912 EncMapFree(fv->b.normal);
3913 if (fv->b.normal == fv->b.sf->map) { fv->b.sf->map = NULL; }
3914 fv->b.normal = NULL;
3915 }
3916 SFReplaceEncodingBDFProps(fv->b.sf,fv->b.map);
3917 FontViewSetTitle(fv);
3918 FontViewReformatOne(&fv->b);
3919 }
3920
FVMenuDisplayByGroups(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3921 static void FVMenuDisplayByGroups(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3922 FontView *fv = (FontView *) GDrawGetUserData(gw);
3923
3924 DisplayGroups(fv);
3925 }
3926
FVMenuDefineGroups(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3927 static void FVMenuDefineGroups(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3928 FontView *fv = (FontView *) GDrawGetUserData(gw);
3929
3930 DefineGroups(fv);
3931 }
3932
FVMenuMMValid(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3933 static void FVMenuMMValid(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3934 FontView *fv = (FontView *) GDrawGetUserData(gw);
3935 MMSet *mm = fv->b.sf->mm;
3936
3937 if ( mm==NULL )
3938 return;
3939 MMValid(mm,true);
3940 }
3941
FVMenuCreateMM(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3942 static void FVMenuCreateMM(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3943 MMWizard(NULL);
3944 }
3945
FVMenuMMInfo(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3946 static void FVMenuMMInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3947 FontView *fv = (FontView *) GDrawGetUserData(gw);
3948 MMSet *mm = fv->b.sf->mm;
3949
3950 if ( mm==NULL )
3951 return;
3952 MMWizard(mm);
3953 }
3954
FVMenuChangeMMBlend(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3955 static void FVMenuChangeMMBlend(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3956 FontView *fv = (FontView *) GDrawGetUserData(gw);
3957 MMSet *mm = fv->b.sf->mm;
3958
3959 if ( mm==NULL || mm->apple )
3960 return;
3961 MMChangeBlend(mm,fv,false);
3962 }
3963
FVMenuBlendToNew(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3964 static void FVMenuBlendToNew(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3965 FontView *fv = (FontView *) GDrawGetUserData(gw);
3966 MMSet *mm = fv->b.sf->mm;
3967
3968 if ( mm==NULL )
3969 return;
3970 MMChangeBlend(mm,fv,true);
3971 }
3972
cflistcheck(GWindow UNUSED (gw),struct gmenuitem * mi,GEvent * UNUSED (e))3973 static void cflistcheck(GWindow UNUSED(gw), struct gmenuitem *mi, GEvent *UNUSED(e)) {
3974 /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
3975
3976 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
3977 switch ( mi->mid ) {
3978 case MID_AllFonts:
3979 mi->ti.checked = !onlycopydisplayed;
3980 break;
3981 case MID_DisplayedFont:
3982 mi->ti.checked = onlycopydisplayed;
3983 break;
3984 case MID_CharName:
3985 mi->ti.checked = copymetadata;
3986 break;
3987 case MID_TTFInstr:
3988 mi->ti.checked = copyttfinstr;
3989 break;
3990 }
3991 }
3992 }
3993
sllistcheck(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))3994 static void sllistcheck(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3995 FontView *fv = (FontView *) GDrawGetUserData(gw);
3996 fv = fv;
3997 }
3998
htlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))3999 static void htlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4000 FontView *fv = (FontView *) GDrawGetUserData(gw);
4001 int anychars = FVAnyCharSelected(fv);
4002 int multilayer = fv->b.sf->multilayer;
4003
4004 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4005 switch ( mi->mid ) {
4006 case MID_AutoHint:
4007 mi->ti.disabled = anychars==-1 || multilayer;
4008 break;
4009 case MID_HintSubsPt:
4010 mi->ti.disabled = fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4011 if ( fv->b.sf->mm!=NULL && fv->b.sf->mm->apple )
4012 mi->ti.disabled = true;
4013 break;
4014 case MID_AutoCounter: case MID_DontAutoHint:
4015 mi->ti.disabled = fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4016 break;
4017 case MID_AutoInstr: case MID_EditInstructions: case MID_Deltas:
4018 mi->ti.disabled = !fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4019 break;
4020 case MID_RmInstrTables:
4021 mi->ti.disabled = fv->b.sf->ttf_tables==NULL;
4022 break;
4023 case MID_Editfpgm: case MID_Editprep: case MID_Editcvt: case MID_Editmaxp:
4024 mi->ti.disabled = !fv->b.sf->layers[fv->b.active_layer].order2 || multilayer;
4025 break;
4026 case MID_ClearHints: case MID_ClearWidthMD: case MID_ClearInstrs:
4027 mi->ti.disabled = anychars==-1;
4028 break;
4029 }
4030 }
4031 }
4032
fllistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4033 static void fllistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4034 FontView *fv = (FontView *) GDrawGetUserData(gw);
4035 int anychars = FVAnyCharSelected(fv);
4036 FontView *fvs;
4037 int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
4038
4039 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4040 switch ( mi->mid ) {
4041 case MID_GenerateTTC:
4042 for ( fvs=fv_list; fvs!=NULL; fvs=(FontView *) (fvs->b.next) ) {
4043 if ( fvs!=fv )
4044 break;
4045 }
4046 mi->ti.disabled = fvs==NULL;
4047 break;
4048 case MID_Revert:
4049 mi->ti.disabled = fv->b.sf->origname==NULL || fv->b.sf->new;
4050 break;
4051 case MID_RevertToBackup:
4052 /* We really do want to use filename here and origname above */
4053 mi->ti.disabled = true;
4054 if ( fv->b.sf->filename!=NULL ) {
4055 if ( fv->b.sf->backedup == bs_dontknow ) {
4056 char *buf = malloc(strlen(fv->b.sf->filename)+20);
4057 strcpy(buf,fv->b.sf->filename);
4058 if ( fv->b.sf->compression!=0 )
4059 strcat(buf,compressors[fv->b.sf->compression-1].ext);
4060 strcat(buf,"~");
4061 if ( access(buf,F_OK)==0 )
4062 fv->b.sf->backedup = bs_backedup;
4063 else
4064 fv->b.sf->backedup = bs_not;
4065 free(buf);
4066 }
4067 if ( fv->b.sf->backedup == bs_backedup )
4068 mi->ti.disabled = false;
4069 }
4070 break;
4071 case MID_RevertGlyph:
4072 mi->ti.disabled = fv->b.sf->origname==NULL || fv->b.sf->sfd_version<2 || anychars==-1 || fv->b.sf->compression!=0;
4073 break;
4074 case MID_Recent:
4075 mi->ti.disabled = !RecentFilesAny();
4076 break;
4077 case MID_ScriptMenu:
4078 mi->ti.disabled = script_menu_names[0]==NULL;
4079 break;
4080 case MID_Print:
4081 mi->ti.disabled = fv->b.sf->onlybitmaps || in_modal;
4082 break;
4083 }
4084 }
4085 }
4086
edlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4087 static void edlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4088 FontView *fv = (FontView *) GDrawGetUserData(gw);
4089 int pos = FVAnyCharSelected(fv), i, gid;
4090 int not_pasteable = pos==-1 ||
4091 (!CopyContainsSomething() && !SCClipboardHasPasteableContents());
4092 RefChar *base = CopyContainsRef(fv->b.sf);
4093 int base_enc = base!=NULL ? fv->b.map->backmap[base->orig_pos] : -1;
4094
4095
4096 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4097 switch ( mi->mid ) {
4098 case MID_Paste: case MID_PasteInto:
4099 mi->ti.disabled = not_pasteable;
4100 break;
4101 case MID_PasteAfter:
4102 mi->ti.disabled = not_pasteable || pos<0;
4103 break;
4104 case MID_SameGlyphAs:
4105 mi->ti.disabled = not_pasteable || base==NULL || fv->b.cidmaster!=NULL ||
4106 base_enc==-1 ||
4107 fv->b.selected[base_enc]; /* Can't be self-referential */
4108 break;
4109 case MID_Join:
4110 case MID_Cut: case MID_Copy: case MID_Clear:
4111 case MID_CopyWidth: case MID_CopyLBearing: case MID_CopyRBearing:
4112 case MID_CopyRef: case MID_UnlinkRef:
4113 case MID_RemoveUndoes: case MID_CopyFgToBg: case MID_CopyL2L:
4114 mi->ti.disabled = pos==-1;
4115 break;
4116 case MID_RplRef:
4117 case MID_CorrectRefs:
4118 mi->ti.disabled = pos==-1 || fv->b.cidmaster!=NULL || fv->b.sf->multilayer;
4119 break;
4120 case MID_CopyLookupData:
4121 mi->ti.disabled = pos==-1 || (fv->b.sf->gpos_lookups==NULL && fv->b.sf->gsub_lookups==NULL);
4122 break;
4123 case MID_CopyVWidth:
4124 mi->ti.disabled = pos==-1 || !fv->b.sf->hasvmetrics;
4125 break;
4126 case MID_ClearBackground:
4127 mi->ti.disabled = true;
4128 if ( pos!=-1 && !( onlycopydisplayed && fv->filled!=fv->show )) {
4129 for ( i=0; i<fv->b.map->enccount; ++i )
4130 if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4131 fv->b.sf->glyphs[gid]!=NULL )
4132 if ( fv->b.sf->glyphs[gid]->layers[ly_back].images!=NULL ||
4133 fv->b.sf->glyphs[gid]->layers[ly_back].splines!=NULL ) {
4134 mi->ti.disabled = false;
4135 break;
4136 }
4137 }
4138 break;
4139 case MID_Undo:
4140 for ( i=0; i<fv->b.map->enccount; ++i )
4141 if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4142 fv->b.sf->glyphs[gid]!=NULL )
4143 if ( fv->b.sf->glyphs[gid]->layers[fv->b.active_layer].undoes!=NULL )
4144 break;
4145 mi->ti.disabled = i==fv->b.map->enccount;
4146 break;
4147 case MID_Redo:
4148 for ( i=0; i<fv->b.map->enccount; ++i )
4149 if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4150 fv->b.sf->glyphs[gid]!=NULL )
4151 if ( fv->b.sf->glyphs[gid]->layers[fv->b.active_layer].redoes!=NULL )
4152 break;
4153 mi->ti.disabled = i==fv->b.map->enccount;
4154 break;
4155 case MID_UndoFontLevel:
4156 mi->ti.disabled = dlist_isempty( (struct dlistnode **)&fv->b.sf->undoes );
4157 break;
4158 }
4159 }
4160 }
4161
trlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4162 static void trlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4163 FontView *fv = (FontView *) GDrawGetUserData(gw);
4164 int anychars = FVAnyCharSelected(fv);
4165
4166 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4167 switch ( mi->mid ) {
4168 case MID_Transform:
4169 mi->ti.disabled = anychars==-1;
4170 break;
4171 case MID_NLTransform: case MID_POV:
4172 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4173 break;
4174 }
4175 }
4176 }
4177
validlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4178 static void validlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4179 FontView *fv = (FontView *) GDrawGetUserData(gw);
4180 int anychars = FVAnyCharSelected(fv);
4181
4182 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4183 switch ( mi->mid ) {
4184 case MID_FindProblems:
4185 mi->ti.disabled = anychars==-1;
4186 break;
4187 case MID_Validate:
4188 mi->ti.disabled = fv->b.sf->strokedfont || fv->b.sf->multilayer;
4189 break;
4190 }
4191 }
4192 }
4193
ellistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4194 static void ellistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4195 FontView *fv = (FontView *) GDrawGetUserData(gw);
4196 int anychars = FVAnyCharSelected(fv), gid;
4197 int anybuildable, anytraceable;
4198 int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
4199
4200 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4201 switch ( mi->mid ) {
4202 case MID_FontInfo:
4203 mi->ti.disabled = in_modal;
4204 break;
4205 case MID_CharInfo:
4206 mi->ti.disabled = anychars<0 || in_modal;
4207 break;
4208 case MID_Transform:
4209 mi->ti.disabled = anychars==-1;
4210 /* some Transformations make sense on bitmaps now */
4211 break;
4212 case MID_AddExtrema:
4213 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4214 break;
4215 case MID_Simplify:
4216 case MID_Stroke: case MID_RmOverlap:
4217 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4218 break;
4219 case MID_Styles:
4220 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4221 break;
4222 case MID_Round: case MID_Correct:
4223 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4224 break;
4225 #ifdef FONTFORGE_CONFIG_TILEPATH
4226 case MID_TilePath:
4227 mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4228 break;
4229 #endif
4230 case MID_AvailBitmaps:
4231 mi->ti.disabled = fv->b.sf->mm!=NULL;
4232 break;
4233 case MID_RegenBitmaps: case MID_RemoveBitmaps:
4234 mi->ti.disabled = fv->b.sf->bitmaps==NULL || fv->b.sf->onlybitmaps ||
4235 fv->b.sf->mm!=NULL;
4236 break;
4237 case MID_BuildAccent:
4238 anybuildable = false;
4239 if ( anychars!=-1 ) {
4240 int i;
4241 for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4242 SplineChar *sc=NULL, dummy;
4243 gid = fv->b.map->map[i];
4244 if ( gid!=-1 )
4245 sc = fv->b.sf->glyphs[gid];
4246 if ( sc==NULL )
4247 sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4248 if ( SFIsSomethingBuildable(fv->b.sf,sc,fv->b.active_layer,false) ||
4249 SFIsDuplicatable(fv->b.sf,sc)) {
4250 anybuildable = true;
4251 break;
4252 }
4253 }
4254 }
4255 mi->ti.disabled = !anybuildable;
4256 break;
4257 case MID_Autotrace:
4258 anytraceable = false;
4259 if ( FindAutoTraceName()!=NULL && anychars!=-1 ) {
4260 int i;
4261 for ( i=0; i<fv->b.map->enccount; ++i )
4262 if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4263 fv->b.sf->glyphs[gid]!=NULL &&
4264 fv->b.sf->glyphs[gid]->layers[ly_back].images!=NULL ) {
4265 anytraceable = true;
4266 break;
4267 }
4268 }
4269 mi->ti.disabled = !anytraceable;
4270 break;
4271 case MID_MergeFonts:
4272 mi->ti.disabled = fv->b.sf->bitmaps!=NULL && fv->b.sf->onlybitmaps;
4273 break;
4274 case MID_FontCompare:
4275 mi->ti.disabled = fv_list->b.next==NULL;
4276 break;
4277 case MID_InterpolateFonts:
4278 mi->ti.disabled = fv->b.sf->onlybitmaps;
4279 break;
4280 }
4281 }
4282 }
4283
mtlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4284 static void mtlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4285 FontView *fv = (FontView *) GDrawGetUserData(gw);
4286 int anychars = FVAnyCharSelected(fv);
4287
4288 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4289 switch ( mi->mid ) {
4290 case MID_Center: case MID_Thirds: case MID_SetWidth:
4291 case MID_SetLBearing: case MID_SetRBearing: case MID_SetBearings:
4292 mi->ti.disabled = anychars==-1;
4293 break;
4294 case MID_SetVWidth:
4295 mi->ti.disabled = anychars==-1 || !fv->b.sf->hasvmetrics;
4296 break;
4297 case MID_VKernByClass:
4298 case MID_VKernFromH:
4299 case MID_RmVKern:
4300 mi->ti.disabled = !fv->b.sf->hasvmetrics;
4301 break;
4302 }
4303 }
4304 }
4305
4306 #if HANYANG
hglistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4307 static void hglistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4308 FontView *fv = (FontView *) GDrawGetUserData(gw);
4309
4310 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4311 if ( mi->mid==MID_BuildSyllables || mi->mid==MID_ModifyComposition )
4312 mi->ti.disabled = fv->b.sf->rules==NULL;
4313 }
4314 }
4315
4316 static GMenuItem2 hglist[] = {
4317 { { (unichar_t *) N_("_New Composition..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New Composition...|No Shortcut"), NULL, NULL, MenuNewComposition },
4318 { { (unichar_t *) N_("_Modify Composition..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Modify Composition...|No Shortcut"), NULL, NULL, FVMenuModifyComposition, MID_ModifyComposition },
4319 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, }},
4320 { { (unichar_t *) N_("_Build Syllables"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Syllables|No Shortcut"), NULL, NULL, FVMenuBuildSyllables, MID_BuildSyllables },
4321 { NULL }
4322 };
4323 #endif
4324
balistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4325 static void balistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4326 FontView *fv = (FontView *) GDrawGetUserData(gw);
4327
4328 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4329 if ( mi->mid==MID_BuildAccent || mi->mid==MID_BuildComposite ) {
4330 int anybuildable = false;
4331 int onlyaccents = mi->mid==MID_BuildAccent;
4332 int i, gid;
4333 for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4334 SplineChar *sc=NULL, dummy;
4335 if ( (gid=fv->b.map->map[i])!=-1 )
4336 sc = fv->b.sf->glyphs[gid];
4337 if ( sc==NULL )
4338 sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4339 if ( SFIsSomethingBuildable(fv->b.sf,sc,fv->b.active_layer,onlyaccents)) {
4340 anybuildable = true;
4341 break;
4342 }
4343 }
4344 mi->ti.disabled = !anybuildable;
4345 } else if ( mi->mid==MID_BuildDuplicates ) {
4346 int anybuildable = false;
4347 int i, gid;
4348 for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4349 SplineChar *sc=NULL, dummy;
4350 if ( (gid=fv->b.map->map[i])!=-1 )
4351 sc = fv->b.sf->glyphs[gid];
4352 if ( sc==NULL )
4353 sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4354 if ( SFIsDuplicatable(fv->b.sf,sc)) {
4355 anybuildable = true;
4356 break;
4357 }
4358 }
4359 mi->ti.disabled = !anybuildable;
4360 }
4361 }
4362 }
4363
delistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4364 static void delistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4365 FontView *fv = (FontView *) GDrawGetUserData(gw);
4366 int i = FVAnyCharSelected(fv);
4367 int gid = i<0 ? -1 : fv->b.map->map[i];
4368
4369 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4370 switch ( mi->mid ) {
4371 case MID_ShowDependentRefs:
4372 mi->ti.disabled = gid<0 || fv->b.sf->glyphs[gid]==NULL ||
4373 fv->b.sf->glyphs[gid]->dependents == NULL;
4374 break;
4375 case MID_ShowDependentSubs:
4376 mi->ti.disabled = gid<0 || fv->b.sf->glyphs[gid]==NULL ||
4377 !SCUsedBySubs(fv->b.sf->glyphs[gid]);
4378 break;
4379 }
4380 }
4381 }
4382
infolistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4383 static void infolistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4384 FontView *fv = (FontView *) GDrawGetUserData(gw);
4385 int anychars = FVAnyCharSelected(fv);
4386
4387 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4388 switch ( mi->mid ) {
4389 case MID_StrikeInfo:
4390 mi->ti.disabled = fv->b.sf->bitmaps==NULL;
4391 break;
4392 case MID_MassRename:
4393 mi->ti.disabled = anychars==-1;
4394 break;
4395 case MID_SetColor:
4396 mi->ti.disabled = anychars==-1;
4397 break;
4398 }
4399 }
4400 }
4401
4402 static GMenuItem2 dummyitem[] = {
4403 { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, NULL, NULL, NULL, NULL, 0 },
4404 GMENUITEM2_EMPTY
4405 };
4406
4407 static GMenuItem2 fllist[] = {
4408 { { (unichar_t *) N_("Font|_New"), (GImage *) "filenew.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New|No Shortcut"), NULL, NULL, MenuNew, 0 },
4409 #if HANYANG
4410 { { (unichar_t *) N_("_Hangul"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Hangul|No Shortcut"), hglist, hglistcheck, NULL, 0 },
4411 #endif
4412 { { (unichar_t *) N_("_Open"), (GImage *) "fileopen.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Open|No Shortcut"), NULL, NULL, FVMenuOpen, 0 },
4413 { { (unichar_t *) N_("Recen_t"), (GImage *) "filerecent.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Recent|No Shortcut"), dummyitem, MenuRecentBuild, NULL, MID_Recent },
4414 { { (unichar_t *) N_("_Close"), (GImage *) "fileclose.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Close|No Shortcut"), NULL, NULL, FVMenuClose, 0 },
4415 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4416 { { (unichar_t *) N_("_Save"), (GImage *) "filesave.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Save|No Shortcut"), NULL, NULL, FVMenuSave, 0 },
4417 { { (unichar_t *) N_("S_ave as..."), (GImage *) "filesaveas.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Save as...|No Shortcut"), NULL, NULL, FVMenuSaveAs, 0 },
4418 { { (unichar_t *) N_("Save A_ll"), (GImage *) "filesaveall.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Save All|No Shortcut"), NULL, NULL, MenuSaveAll, 0 },
4419 { { (unichar_t *) N_("_Generate Fonts..."), (GImage *) "filegenerate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Generate Fonts...|No Shortcut"), NULL, NULL, FVMenuGenerate, 0 },
4420 { { (unichar_t *) N_("Generate Mac _Family..."), (GImage *) "filegeneratefamily.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate Mac Family...|No Shortcut"), NULL, NULL, FVMenuGenerateFamily, 0 },
4421 { { (unichar_t *) N_("Generate TTC..."), (GImage *) "filegeneratefamily.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate TTC...|No Shortcut"), NULL, NULL, FVMenuGenerateTTC, MID_GenerateTTC },
4422 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4423 { { (unichar_t *) N_("_Import..."), (GImage *) "fileimport.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Import...|No Shortcut"), NULL, NULL, FVMenuImport, 0 },
4424 { { (unichar_t *) N_("_Merge Feature Info..."), (GImage *) "filemergefeature.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge Feature Info...|No Shortcut"), NULL, NULL, FVMenuMergeKern, 0 },
4425 { { (unichar_t *) N_("_Revert File"), (GImage *) "filerevert.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert File|No Shortcut"), NULL, NULL, FVMenuRevert, MID_Revert },
4426 { { (unichar_t *) N_("Revert To _Backup"), (GImage *) "filerevertbackup.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert To Backup|No Shortcut"), NULL, NULL, FVMenuRevertBackup, MID_RevertToBackup },
4427 { { (unichar_t *) N_("Revert Gl_yph"), (GImage *) "filerevertglyph.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert Glyph|No Shortcut"), NULL, NULL, FVMenuRevertGlyph, MID_RevertGlyph },
4428 { { (unichar_t *) N_("Clear Special Data"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Clear Special Data|No Shortcut"), NULL, NULL, FVMenuClearSpecialData, MID_ClearSpecialData },
4429 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4430 { { (unichar_t *) N_("_Print..."), (GImage *) "fileprint.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Print...|No Shortcut"), NULL, NULL, FVMenuPrint, MID_Print },
4431 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4432 #if !defined(_NO_PYTHON)
4433 { { (unichar_t *) N_("E_xecute Script..."), (GImage *) "python.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Execute Script...|No Shortcut"), NULL, NULL, FVMenuExecute, 0 },
4434 #elif !defined(_NO_FFSCRIPT)
4435 { { (unichar_t *) N_("E_xecute Script..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Execute Script...|No Shortcut"), NULL, NULL, FVMenuExecute, 0 },
4436 #endif
4437 #if !defined(_NO_FFSCRIPT)
4438 { { (unichar_t *) N_("Script Menu"), (GImage *) "fileexecute.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Script Menu|No Shortcut"), dummyitem, MenuScriptsBuild, NULL, MID_ScriptMenu },
4439 #endif
4440 #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
4441 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4442 #endif
4443 { { (unichar_t *) N_("Pr_eferences..."), (GImage *) "fileprefs.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Preferences...|No Shortcut"), NULL, NULL, MenuPrefs, 0 },
4444 { { (unichar_t *) N_("_X Resource Editor..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("X Resource Editor...|No Shortcut"), NULL, NULL, MenuXRes, 0 },
4445 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4446 { { (unichar_t *) N_("_Quit"), (GImage *) "filequit.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'Q' }, H_("Quit|Ctl+Q"), /* WARNING: THIS BINDING TO PROPERLY INITIALIZE KEYBOARD INPUT */
4447 NULL, NULL, FVMenuExit, 0 },
4448 GMENUITEM2_EMPTY
4449 };
4450
4451 static GMenuItem2 cflist[] = {
4452 { { (unichar_t *) N_("_All Fonts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'A' }, H_("All Fonts|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_AllFonts },
4453 { { (unichar_t *) N_("_Displayed Font"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'D' }, H_("Displayed Font|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_DisplayedFont },
4454 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4455 { { (unichar_t *) N_("Glyph _Metadata"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'N' }, H_("Glyph Metadata|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_CharName },
4456 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4457 { { (unichar_t *) N_("_TrueType Instructions"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'N' }, H_("TrueType Instructions|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_TTFInstr },
4458 GMENUITEM2_EMPTY
4459 };
4460
4461 static GMenuItem2 sclist[] = {
4462 { { (unichar_t *) N_("Color|Choose..."), (GImage *)"colorwheel.png", COLOR_DEFAULT, COLOR_DEFAULT, (void *) -10, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Choose...|No Shortcut"), NULL, NULL, FVMenuSelectColor, 0 },
4463 { { (unichar_t *) N_("Color|Default"), &def_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) COLOR_DEFAULT, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Default|No Shortcut"), NULL, NULL, FVMenuSelectColor, 0 },
4464 { { NULL, &white_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4465 { { NULL, &red_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff0000, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4466 { { NULL, &green_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4467 { { NULL, &blue_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x0000ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4468 { { NULL, &yellow_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4469 { { NULL, &cyan_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4470 { { NULL, &magenta_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff00ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor, 0 },
4471 GMENUITEM2_EMPTY
4472 };
4473
4474 static GMenuItem2 sllist[] = {
4475 { { (unichar_t *) N_("Select _All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Select All|No Shortcut"), NULL, NULL, FVMenuSelectAll, 0 },
4476 { { (unichar_t *) N_("_Invert Selection"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Invert Selection|No Shortcut"), NULL, NULL, FVMenuInvertSelection, 0 },
4477 { { (unichar_t *) N_("_Deselect All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Deselect All|Escape"), NULL, NULL, FVMenuDeselectAll, 0 },
4478 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4479 { { (unichar_t *) N_("Select by _Color"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Select by Color|No Shortcut"), sclist, NULL, NULL, 0 },
4480 { { (unichar_t *) N_("Select by _Wildcard..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Select by Wildcard...|No Shortcut"), NULL, NULL, FVMenuSelectByName, 0 },
4481 { { (unichar_t *) N_("Select by _Script..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Select by Script...|No Shortcut"), NULL, NULL, FVMenuSelectByScript, 0 },
4482 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4483 { { (unichar_t *) N_("_Glyphs Worth Outputting"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Glyphs Worth Outputting|No Shortcut"), NULL,NULL, FVMenuSelectWorthOutputting, 0 },
4484 { { (unichar_t *) N_("Glyphs with only _References"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Glyphs with only References|No Shortcut"), NULL,NULL, FVMenuGlyphsRefs, 0 },
4485 { { (unichar_t *) N_("Glyphs with only S_plines"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Glyphs with only Splines|No Shortcut"), NULL,NULL, FVMenuGlyphsSplines, 0 },
4486 { { (unichar_t *) N_("Glyphs with both"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Glyphs with both|No Shortcut"), NULL,NULL, FVMenuGlyphsBoth, 0 },
4487 { { (unichar_t *) N_("W_hitespace Glyphs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Whitespace Glyphs|No Shortcut"), NULL,NULL, FVMenuGlyphsWhite, 0 },
4488 { { (unichar_t *) N_("_Changed Glyphs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Changed Glyphs|No Shortcut"), NULL,NULL, FVMenuSelectChanged, 0 },
4489 { { (unichar_t *) N_("_Hinting Needed"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Hinting Needed|No Shortcut"), NULL,NULL, FVMenuSelectHintingNeeded, 0 },
4490 { { (unichar_t *) N_("Autohinta_ble"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Autohintable|No Shortcut"), NULL,NULL, FVMenuSelectAutohintable, 0 },
4491 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4492 { { (unichar_t *) N_("Hold [Shift] key to merge"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, NULL, NULL, NULL, 0 },
4493 { { (unichar_t *) N_("Hold [Control] key to restrict"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, NULL, NULL, NULL, 0 },
4494 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4495 { { (unichar_t *) N_("Selec_t By Lookup Subtable..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Select By Lookup Subtable...|No Shortcut"), NULL, NULL, FVMenuSelectByPST, 0 },
4496 GMENUITEM2_EMPTY
4497 };
4498
4499 static GMenuItem2 edlist[] = {
4500 { { (unichar_t *) N_("_Undo"), (GImage *) "editundo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo|No Shortcut"), NULL, NULL, FVMenuUndo, MID_Undo },
4501 { { (unichar_t *) N_("_Redo"), (GImage *) "editredo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Redo|No Shortcut"), NULL, NULL, FVMenuRedo, MID_Redo},
4502 { { (unichar_t *) N_("Undo Fontlevel"), (GImage *) "editundo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo Fontlevel|No Shortcut"), NULL, NULL, FVMenuUndoFontLevel, MID_UndoFontLevel },
4503 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4504 { { (unichar_t *) N_("Cu_t"), (GImage *) "editcut.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Cut|No Shortcut"), NULL, NULL, FVMenuCut, MID_Cut },
4505 { { (unichar_t *) N_("_Copy"), (GImage *) "editcopy.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Copy|No Shortcut"), NULL, NULL, FVMenuCopy, MID_Copy },
4506 { { (unichar_t *) N_("C_opy Reference"), (GImage *) "editcopyref.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Reference|No Shortcut"), NULL, NULL, FVMenuCopyRef, MID_CopyRef },
4507 { { (unichar_t *) N_("Copy _Lookup Data"), (GImage *) "editcopylookupdata.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Lookup Data|No Shortcut"), NULL, NULL, FVMenuCopyLookupData, MID_CopyLookupData },
4508 { { (unichar_t *) N_("Copy _Width"), (GImage *) "editcopywidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Copy Width|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyWidth },
4509 { { (unichar_t *) N_("Copy _VWidth"), (GImage *) "editcopyvwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Copy VWidth|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyVWidth },
4510 { { (unichar_t *) N_("Co_py LBearing"), (GImage *) "editcopylbearing.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Copy LBearing|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyLBearing },
4511 { { (unichar_t *) N_("Copy RBearin_g"), (GImage *) "editcopyrbearing.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'g' }, H_("Copy RBearing|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyRBearing },
4512 { { (unichar_t *) N_("_Paste"), (GImage *) "editpaste.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Paste|No Shortcut"), NULL, NULL, FVMenuPaste, MID_Paste },
4513 { { (unichar_t *) N_("Paste Into"), (GImage *) "editpasteinto.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Paste Into|No Shortcut"), NULL, NULL, FVMenuPasteInto, MID_PasteInto },
4514 { { (unichar_t *) N_("Paste After"), (GImage *) "editpasteafter.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Paste After|No Shortcut"), NULL, NULL, FVMenuPasteAfter, MID_PasteAfter },
4515 { { (unichar_t *) N_("Sa_me Glyph As"), (GImage *) "editsameas.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'm' }, H_("Same Glyph As|No Shortcut"), NULL, NULL, FVMenuSameGlyphAs, MID_SameGlyphAs },
4516 { { (unichar_t *) N_("C_lear"), (GImage *) "editclear.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Clear|No Shortcut"), NULL, NULL, FVMenuClear, MID_Clear },
4517 { { (unichar_t *) N_("Clear _Background"), (GImage *) "editclearback.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Clear Background|No Shortcut"), NULL, NULL, FVMenuClearBackground, MID_ClearBackground },
4518 { { (unichar_t *) N_("Copy _Fg To Bg"), (GImage *) "editcopyfg2bg.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy Fg To Bg|No Shortcut"), NULL, NULL, FVMenuCopyFgBg, MID_CopyFgToBg },
4519 { { (unichar_t *) N_("Copy Layer To Layer"), (GImage *) "editcopylayer2layer.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy Layer To Layer|No Shortcut"), NULL, NULL, FVMenuCopyL2L, MID_CopyL2L },
4520 { { (unichar_t *) N_("_Join"), (GImage *) "editjoin.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'J' }, H_("Join|No Shortcut"), NULL, NULL, FVMenuJoin, MID_Join },
4521 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4522 { { (unichar_t *) N_("_Select"), (GImage *) "editselect.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Select|No Shortcut"), sllist, sllistcheck, NULL, 0 },
4523 { { (unichar_t *) N_("F_ind / Replace..."), (GImage *) "editfind.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Find / Replace...|No Shortcut"), NULL, NULL, FVMenuFindRpl, 0 },
4524 { { (unichar_t *) N_("Replace with Reference"), (GImage *) "editrplref.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Replace with Reference|No Shortcut"), NULL, NULL, FVMenuReplaceWithRef, MID_RplRef },
4525 { { (unichar_t *) N_("Correct References"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Correct References|No Shortcut"), NULL, NULL, FVMenuCorrectRefs, MID_CorrectRefs },
4526 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4527 { { (unichar_t *) N_("U_nlink Reference"), (GImage *) "editunlink.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Unlink Reference|No Shortcut"), NULL, NULL, FVMenuUnlinkRef, MID_UnlinkRef },
4528 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4529 { { (unichar_t *) N_("Copy _From"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy From|No Shortcut"), cflist, cflistcheck, NULL, 0 },
4530 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4531 { { (unichar_t *) N_("Remo_ve Undoes"), (GImage *) "editrmundoes.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Remove Undoes|No Shortcut"), NULL, NULL, FVMenuRemoveUndoes, MID_RemoveUndoes },
4532 GMENUITEM2_EMPTY
4533 };
4534
4535 static GMenuItem2 smlist[] = {
4536 { { (unichar_t *) N_("_Simplify"), (GImage *) "elementsimplify.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Simplify|No Shortcut"), NULL, NULL, FVMenuSimplify, MID_Simplify },
4537 { { (unichar_t *) N_("Simplify More..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Simplify More...|No Shortcut"), NULL, NULL, FVMenuSimplifyMore, MID_SimplifyMore },
4538 { { (unichar_t *) N_("Clea_nup Glyph"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Cleanup Glyph|No Shortcut"), NULL, NULL, FVMenuCleanup, MID_CleanupGlyph },
4539 { { (unichar_t *) N_("Canonical Start _Point"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Start Point|No Shortcut"), NULL, NULL, FVMenuCanonicalStart, MID_CanonicalStart },
4540 { { (unichar_t *) N_("Canonical _Contours"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Contours|No Shortcut"), NULL, NULL, FVMenuCanonicalContours, MID_CanonicalContours },
4541 GMENUITEM2_EMPTY
4542 };
4543
4544 static GMenuItem2 rmlist[] = {
4545 { { (unichar_t *) N_("_Remove Overlap"), (GImage *) "overlaprm.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Remove Overlap|No Shortcut"), NULL, NULL, FVMenuOverlap, MID_RmOverlap },
4546 { { (unichar_t *) N_("_Intersect"), (GImage *) "overlapintersection.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Intersect|No Shortcut"), NULL, NULL, FVMenuOverlap, MID_Intersection },
4547 { { (unichar_t *) N_("_Find Intersections"), (GImage *) "overlapfindinter.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Find Intersections|No Shortcut"), NULL, NULL, FVMenuOverlap, MID_FindInter },
4548 GMENUITEM2_EMPTY
4549 };
4550
4551 static GMenuItem2 eflist[] = {
4552 { { (unichar_t *) N_("Change _Weight..."), (GImage *) "styleschangeweight.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Change Weight...|No Shortcut"), NULL, NULL, FVMenuEmbolden, MID_Embolden },
4553 { { (unichar_t *) N_("_Italic..."), (GImage *) "stylesitalic.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Italic...|No Shortcut"), NULL, NULL, FVMenuItalic, MID_Italic },
4554 { { (unichar_t *) N_("Obli_que..."), (GImage *) "stylesoblique.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Oblique...|No Shortcut"), NULL, NULL, FVMenuOblique, 0 },
4555 { { (unichar_t *) N_("_Condense/Extend..."), (GImage *) "stylesextendcondense.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Condense/Extend...|No Shortcut"), NULL, NULL, FVMenuCondense, MID_Condense },
4556 { { (unichar_t *) N_("Change _X-Height..."), (GImage *) "styleschangexheight.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Change X-Height...|No Shortcut"), NULL, NULL, FVMenuChangeXHeight, MID_ChangeXHeight },
4557 { { (unichar_t *) N_("Change _Glyph..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Change Glyph...|No Shortcut"), NULL, NULL, FVMenuChangeGlyph, MID_ChangeGlyph },
4558 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4559 { { (unichar_t *) N_("Add _Small Capitals..."), (GImage *) "stylessmallcaps.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Add Small Capitals...|No Shortcut"), NULL, NULL, FVMenuSmallCaps, MID_SmallCaps },
4560 { { (unichar_t *) N_("Add Subscripts/Superscripts..."), (GImage *) "stylessubsuper.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Add Subscripts/Superscripts...|No Shortcut"), NULL, NULL, FVMenuSubSup, MID_SubSup },
4561 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4562 { { (unichar_t *) N_("In_line..."), (GImage *) "stylesinline.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Inline...|No Shortcut"), NULL, NULL, FVMenuInline, 0 },
4563 { { (unichar_t *) N_("_Outline..."), (GImage *) "stylesoutline.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Outline...|No Shortcut"), NULL, NULL, FVMenuOutline, 0 },
4564 { { (unichar_t *) N_("S_hadow..."), (GImage *) "stylesshadow.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Shadow...|No Shortcut"), NULL, NULL, FVMenuShadow, 0 },
4565 { { (unichar_t *) N_("_Wireframe..."), (GImage *) "styleswireframe.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Wireframe...|No Shortcut"), NULL, NULL, FVMenuWireframe, 0 },
4566 GMENUITEM2_EMPTY
4567 };
4568
4569 static GMenuItem2 balist[] = {
4570 { { (unichar_t *) N_("_Build Accented Glyph"), (GImage *) "elementbuildaccent.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Accented Glyph|No Shortcut"), NULL, NULL, FVMenuBuildAccent, MID_BuildAccent },
4571 { { (unichar_t *) N_("Build _Composite Glyph"), (GImage *) "elementbuildcomposite.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Composite Glyph|No Shortcut"), NULL, NULL, FVMenuBuildComposite, MID_BuildComposite },
4572 { { (unichar_t *) N_("Buil_d Duplicate Glyph"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Duplicate Glyph|No Shortcut"), NULL, NULL, FVMenuBuildDuplicate, MID_BuildDuplicates },
4573 #ifdef KOREAN
4574 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4575 { { (unichar_t *) _STR_ShowGrp, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, NULL, NULL, NULL, FVMenuShowGroup },
4576 #endif
4577 GMENUITEM2_EMPTY
4578 };
4579
4580 static GMenuItem2 delist[] = {
4581 { { (unichar_t *) N_("_References..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("References...|No Shortcut"), NULL, NULL, FVMenuShowDependentRefs, MID_ShowDependentRefs },
4582 { { (unichar_t *) N_("_Substitutions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Substitutions...|No Shortcut"), NULL, NULL, FVMenuShowDependentSubs, MID_ShowDependentSubs },
4583 GMENUITEM2_EMPTY
4584 };
4585
4586 static GMenuItem2 trlist[] = {
4587 { { (unichar_t *) N_("_Transform..."), (GImage *) "elementtransform.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transform...|No Shortcut"), NULL, NULL, FVMenuTransform, MID_Transform },
4588 { { (unichar_t *) N_("_Point of View Projection..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Point of View Projection...|No Shortcut"), NULL, NULL, FVMenuPOV, MID_POV },
4589 { { (unichar_t *) N_("_Non Linear Transform..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Non Linear Transform...|No Shortcut"), NULL, NULL, FVMenuNLTransform, MID_NLTransform },
4590 GMENUITEM2_EMPTY
4591 };
4592
4593 static GMenuItem2 rndlist[] = {
4594 { { (unichar_t *) N_("To _Int"), (GImage *) "elementround.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Int|No Shortcut"), NULL, NULL, FVMenuRound2Int, MID_Round },
4595 { { (unichar_t *) N_("To _Hundredths"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Hundredths|No Shortcut"), NULL, NULL, FVMenuRound2Hundredths, 0 },
4596 { { (unichar_t *) N_("_Cluster"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Cluster|No Shortcut"), NULL, NULL, FVMenuCluster, 0 },
4597 GMENUITEM2_EMPTY
4598 };
4599
4600 static GMenuItem2 scollist[] = {
4601 { { (unichar_t *) N_("Color|Choose..."), (GImage *)"colorwheel.png", COLOR_DEFAULT, COLOR_DEFAULT, (void *) -10, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Choose...|No Shortcut"), NULL, NULL, FVMenuSetColor, 0 },
4602 { { (unichar_t *) N_("Color|Default"), &def_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) COLOR_DEFAULT, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Default|No Shortcut"), NULL, NULL, FVMenuSetColor, 0 },
4603 { { NULL, &white_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4604 { { NULL, &red_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff0000, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4605 { { NULL, &green_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4606 { { NULL, &blue_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x0000ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4607 { { NULL, &yellow_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4608 { { NULL, &cyan_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4609 { { NULL, &magenta_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff00ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSetColor, 0 },
4610 GMENUITEM2_EMPTY
4611 };
4612
4613 static GMenuItem2 infolist[] = {
4614 { { (unichar_t *) N_("_MATH Info..."), (GImage *) "elementmathinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("MATH Info...|No Shortcut"), NULL, NULL, FVMenuMATHInfo, 0 },
4615 { { (unichar_t *) N_("_BDF Info..."), (GImage *) "elementbdfinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("BDF Info...|No Shortcut"), NULL, NULL, FVMenuBDFInfo, MID_StrikeInfo },
4616 { { (unichar_t *) N_("_Horizontal Baselines..."), (GImage *) "elementhbaselines.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Horizontal Baselines...|No Shortcut"), NULL, NULL, FVMenuBaseHoriz, 0 },
4617 { { (unichar_t *) N_("_Vertical Baselines..."), (GImage *) "elementvbaselines.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Vertical Baselines...|No Shortcut"), NULL, NULL, FVMenuBaseVert, 0 },
4618 { { (unichar_t *) N_("_Justification..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Justification...|No Shortcut"), NULL, NULL, FVMenuJustify, 0 },
4619 { { (unichar_t *) N_("Show _Dependent"), (GImage *) "elementshowdep.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Show Dependent|No Shortcut"), delist, delistcheck, NULL, 0 },
4620 { { (unichar_t *) N_("Mass Glyph _Rename..."), (GImage *) "elementrenameglyph.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Mass Glyph Rename...|No Shortcut"), NULL, NULL, FVMenuMassRename, MID_MassRename },
4621 { { (unichar_t *) N_("Set _Color"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Set Color|No Shortcut"), scollist, NULL, NULL, MID_SetColor },
4622 GMENUITEM2_EMPTY
4623 };
4624
4625 static GMenuItem2 validlist[] = {
4626 { { (unichar_t *) N_("Find Pr_oblems..."), (GImage *) "elementfindprobs.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Find Problems...|No Shortcut"), NULL, NULL, FVMenuFindProblems, MID_FindProblems },
4627 { { (unichar_t *) N_("_Validate..."), (GImage *) "elementvalidate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Validate...|No Shortcut"), NULL, NULL, FVMenuValidate, MID_Validate },
4628 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4629 { { (unichar_t *) N_("Set E_xtremum Bound..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Set Extremum Bound...|No Shortcut"), NULL, NULL, FVMenuSetExtremumBound, MID_SetExtremumBound },
4630 GMENUITEM2_EMPTY
4631 };
4632
4633 static GMenuItem2 ellist[] = {
4634 { { (unichar_t *) N_("_Font Info..."), (GImage *) "elementfontinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Font Info...|No Shortcut"), NULL, NULL, FVMenuFontInfo, MID_FontInfo },
4635 { { (unichar_t *) N_("_Glyph Info..."), (GImage *) "elementglyphinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Glyph Info...|No Shortcut"), NULL, NULL, FVMenuCharInfo, MID_CharInfo },
4636 { { (unichar_t *) N_("Other Info"), (GImage *) "elementotherinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Other Info|No Shortcut"), infolist, infolistcheck, NULL, 0 },
4637 { { (unichar_t *) N_("_Validation"), (GImage *) "elementvalidate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Validation|No Shortcut"), validlist, validlistcheck, NULL, 0 },
4638 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4639 { { (unichar_t *) N_("Bitm_ap Strikes Available..."), (GImage *) "elementbitmapsavail.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Bitmap Strikes Available...|No Shortcut"), NULL, NULL, FVMenuBitmaps, MID_AvailBitmaps },
4640 { { (unichar_t *) N_("Regenerate _Bitmap Glyphs..."), (GImage *) "elementregenbitmaps.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Regenerate Bitmap Glyphs...|No Shortcut"), NULL, NULL, FVMenuBitmaps, MID_RegenBitmaps },
4641 { { (unichar_t *) N_("Remove Bitmap Glyphs..."), (GImage *) "elementremovebitmaps.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Remove Bitmap Glyphs...|No Shortcut"), NULL, NULL, FVMenuBitmaps, MID_RemoveBitmaps },
4642 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4643 { { (unichar_t *) N_("St_yle"), (GImage *) "elementstyles.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Style|No Shortcut"), eflist, NULL, NULL, MID_Styles },
4644 { { (unichar_t *) N_("_Transformations"), (GImage *) "elementtransform.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transformations|No Shortcut"), trlist, trlistcheck, NULL, MID_Transform },
4645 { { (unichar_t *) N_("_Expand Stroke..."), (GImage *) "elementexpandstroke.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Expand Stroke...|No Shortcut"), NULL, NULL, FVMenuStroke, MID_Stroke },
4646 #ifdef FONTFORGE_CONFIG_TILEPATH
4647 { { (unichar_t *) N_("Tile _Path..."), (GImage *) "elementtilepath.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Tile Path...|No Shortcut"), NULL, NULL, FVMenuTilePath, MID_TilePath },
4648 { { (unichar_t *) N_("Tile Pattern..."), (GImage *) "elementtilepattern.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Tile Pattern...|No Shortcut"), NULL, NULL, FVMenuPatternTile, 0 },
4649 #endif
4650 { { (unichar_t *) N_("O_verlap"), (GImage *) "overlaprm.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Overlap|No Shortcut"), rmlist, NULL, NULL, MID_RmOverlap },
4651 { { (unichar_t *) N_("_Simplify"), (GImage *) "elementsimplify.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Simplify|No Shortcut"), smlist, NULL, NULL, MID_Simplify },
4652 { { (unichar_t *) N_("Add E_xtrema"), (GImage *) "elementaddextrema.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Add Extrema|No Shortcut"), NULL, NULL, FVMenuAddExtrema, MID_AddExtrema },
4653 { { (unichar_t *) N_("Roun_d"), (GImage *) "elementround.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Round|No Shortcut"), rndlist, NULL, NULL, MID_Round },
4654 { { (unichar_t *) N_("Autot_race"), (GImage *) "elementautotrace.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Autotrace|No Shortcut"), NULL, NULL, FVMenuAutotrace, MID_Autotrace },
4655 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4656 { { (unichar_t *) N_("_Correct Direction"), (GImage *) "elementcorrectdir.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Correct Direction|No Shortcut"), NULL, NULL, FVMenuCorrectDir, MID_Correct },
4657 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4658 { { (unichar_t *) N_("B_uild"), (GImage *) "elementbuildaccent.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build|No Shortcut"), balist, balistcheck, NULL, MID_BuildAccent },
4659 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4660 { { (unichar_t *) N_("_Merge Fonts..."), (GImage *) "elementmergefonts.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge Fonts...|No Shortcut"), NULL, NULL, FVMenuMergeFonts, MID_MergeFonts },
4661 { { (unichar_t *) N_("Interpo_late Fonts..."), (GImage *) "elementinterpolatefonts.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Interpolate Fonts...|No Shortcut"), NULL, NULL, FVMenuInterpFonts, MID_InterpolateFonts },
4662 { { (unichar_t *) N_("Compare Fonts..."), (GImage *) "elementcomparefonts.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Compare Fonts...|No Shortcut"), NULL, NULL, FVMenuCompareFonts, MID_FontCompare },
4663 { { (unichar_t *) N_("Compare Layers..."), (GImage *) "elementcomparelayers.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Compare Layers...|No Shortcut"), NULL, NULL, FVMenuCompareL2L, 0 },
4664 GMENUITEM2_EMPTY
4665 };
4666
4667 static GMenuItem2 dummyall[] = {
4668 { { (unichar_t *) N_("All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("All|No Shortcut"), NULL, NULL, NULL, 0 },
4669 GMENUITEM2_EMPTY
4670 };
4671
4672 /* Builds up a menu containing all the anchor classes */
aplistbuild(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4673 static void aplistbuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4674 FontView *fv = (FontView *) GDrawGetUserData(gw);
4675
4676 GMenuItemArrayFree(mi->sub);
4677 mi->sub = NULL;
4678
4679 _aplistbuild(mi,fv->b.sf,FVMenuAnchorPairs);
4680 }
4681
4682 static GMenuItem2 cblist[] = {
4683 { { (unichar_t *) N_("_Kern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Kern Pairs|No Shortcut"), NULL, NULL, FVMenuKernPairs, MID_KernPairs },
4684 { { (unichar_t *) N_("_Anchored Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Anchored Pairs|No Shortcut"), dummyall, aplistbuild, NULL, MID_AnchorPairs },
4685 { { (unichar_t *) N_("_Ligatures"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Ligatures|No Shortcut"), NULL, NULL, FVMenuLigatures, MID_Ligatures },
4686 GMENUITEM2_EMPTY
4687 };
4688
cblistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4689 static void cblistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4690 FontView *fv = (FontView *) GDrawGetUserData(gw);
4691 SplineFont *sf = fv->b.sf;
4692 int i, anyligs=0, anykerns=0, gid;
4693 PST *pst;
4694
4695 if ( sf->kerns ) anykerns=true;
4696 for ( i=0; i<fv->b.map->enccount; ++i ) if ( (gid = fv->b.map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
4697 for ( pst=sf->glyphs[gid]->possub; pst!=NULL; pst=pst->next ) {
4698 if ( pst->type==pst_ligature ) {
4699 anyligs = true;
4700 if ( anykerns )
4701 break;
4702 }
4703 }
4704 if ( sf->glyphs[gid]->kerns!=NULL ) {
4705 anykerns = true;
4706 if ( anyligs )
4707 break;
4708 }
4709 }
4710
4711 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4712 switch ( mi->mid ) {
4713 case MID_Ligatures:
4714 mi->ti.disabled = !anyligs;
4715 break;
4716 case MID_KernPairs:
4717 mi->ti.disabled = !anykerns;
4718 break;
4719 case MID_AnchorPairs:
4720 mi->ti.disabled = sf->anchor==NULL;
4721 break;
4722 }
4723 }
4724 }
4725
4726
4727 static GMenuItem2 gllist[] = {
4728 { { (unichar_t *) N_("_Glyph Image"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'K' }, H_("Glyph Image|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_glyph },
4729 { { (unichar_t *) N_("_Name"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'K' }, H_("Name|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_name },
4730 { { (unichar_t *) N_("_Unicode"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Unicode|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_unicode },
4731 { { (unichar_t *) N_("_Encoding Hex"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Encoding Hex|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_encoding },
4732 GMENUITEM2_EMPTY
4733 };
4734
gllistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4735 static void gllistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4736 FontView *fv = (FontView *) GDrawGetUserData(gw);
4737
4738 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4739 mi->ti.checked = fv->glyphlabel == mi->mid;
4740 }
4741 }
4742
4743 static GMenuItem2 emptymenu[] = {
4744 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0},
4745 GMENUITEM2_EMPTY
4746 };
4747
FVEncodingMenuBuild(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4748 static void FVEncodingMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4749 FontView *fv = (FontView *) GDrawGetUserData(gw);
4750
4751 if ( mi->sub!=NULL ) {
4752 GMenuItemArrayFree(mi->sub);
4753 mi->sub = NULL;
4754 }
4755 mi->sub = GetEncodingMenu(FVMenuReencode,fv->b.map->enc);
4756 }
4757
FVMenuAddUnencoded(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4758 static void FVMenuAddUnencoded(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4759 FontView *fv = (FontView *) GDrawGetUserData(gw);
4760 char *ret, *end;
4761 int cnt;
4762
4763 ret = gwwv_ask_string(_("Add Encoding Slots..."),"1",fv->b.cidmaster?_("How many CID slots do you wish to add?"):_("How many unencoded glyph slots do you wish to add?"));
4764 if ( ret==NULL )
4765 return;
4766 cnt = strtol(ret,&end,10);
4767 if ( *end!='\0' || cnt<=0 ) {
4768 free(ret);
4769 ff_post_error( _("Bad Number"),_("Bad Number") );
4770 return;
4771 }
4772 free(ret);
4773 FVAddUnencoded((FontViewBase *) fv, cnt);
4774 }
4775
FVMenuRemoveUnused(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4776 static void FVMenuRemoveUnused(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4777 FontView *fv = (FontView *) GDrawGetUserData(gw);
4778 FVRemoveUnused((FontViewBase *) fv);
4779 }
4780
FVMenuCompact(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4781 static void FVMenuCompact(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4782 FontView *fv = (FontView *) GDrawGetUserData(gw);
4783 SplineChar *sc;
4784
4785 sc = FVFindACharInDisplay(fv);
4786 FVCompact((FontViewBase *) fv);
4787 if ( sc!=NULL ) {
4788 int enc = fv->b.map->backmap[sc->orig_pos];
4789 if ( enc!=-1 )
4790 FVScrollToChar(fv,enc);
4791 }
4792 }
4793
FVMenuDetachGlyphs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4794 static void FVMenuDetachGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4795 FontView *fv = (FontView *) GDrawGetUserData(gw);
4796 FVDetachGlyphs((FontViewBase *) fv);
4797 }
4798
FVMenuDetachAndRemoveGlyphs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4799 static void FVMenuDetachAndRemoveGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4800 FontView *fv = (FontView *) GDrawGetUserData(gw);
4801 char *buts[3];
4802
4803 buts[0] = _("_Remove");
4804 buts[1] = _("_Cancel");
4805 buts[2] = NULL;
4806
4807 if ( gwwv_ask(_("Detach & Remove Glyphs"),(const char **) buts,0,1,_("Are you sure you wish to remove these glyphs? This operation cannot be undone."))==1 )
4808 return;
4809
4810 FVDetachAndRemoveGlyphs((FontViewBase *) fv);
4811 }
4812
FVForceEncodingMenuBuild(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))4813 static void FVForceEncodingMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4814 FontView *fv = (FontView *) GDrawGetUserData(gw);
4815
4816 if ( mi->sub!=NULL ) {
4817 GMenuItemArrayFree(mi->sub);
4818 mi->sub = NULL;
4819 }
4820 mi->sub = GetEncodingMenu(FVMenuForceEncode,fv->b.map->enc);
4821 }
4822
FVMenuAddEncodingName(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4823 static void FVMenuAddEncodingName(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4824 char *ret;
4825 Encoding *enc;
4826
4827 /* Search the iconv database for the named encoding */
4828 ret = gwwv_ask_string(_("Add Encoding Name..."),NULL,_("Please provide the name of an encoding in the iconv database which you want in the menu."));
4829 if ( ret==NULL )
4830 return;
4831 enc = FindOrMakeEncoding(ret);
4832 if ( enc==NULL )
4833 ff_post_error(_("Invalid Encoding"),_("Invalid Encoding"));
4834 free(ret);
4835 }
4836
FVMenuLoadEncoding(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4837 static void FVMenuLoadEncoding(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4838 LoadEncodingFile();
4839 }
4840
FVMenuMakeFromFont(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4841 static void FVMenuMakeFromFont(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4842 FontView *fv = (FontView *) GDrawGetUserData(gw);
4843 (void) MakeEncoding(fv->b.sf,fv->b.map);
4844 }
4845
FVMenuRemoveEncoding(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4846 static void FVMenuRemoveEncoding(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4847 RemoveEncoding();
4848 }
4849
FVMenuMakeNamelist(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4850 static void FVMenuMakeNamelist(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4851 FontView *fv = (FontView *) GDrawGetUserData(gw);
4852 char buffer[1025];
4853 char *filename, *temp;
4854 FILE *file;
4855
4856 snprintf(buffer, sizeof(buffer),"%s/%s.nam", getFontForgeUserDir(Config), fv->b.sf->fontname );
4857 temp = def2utf8_copy(buffer);
4858 filename = gwwv_save_filename(_("Make Namelist"), temp,"*.nam");
4859 free(temp);
4860 if ( filename==NULL )
4861 return;
4862 temp = utf82def_copy(filename);
4863 file = fopen(temp,"w");
4864 free(temp);
4865 if ( file==NULL ) {
4866 ff_post_error(_("Namelist creation failed"),_("Could not write %s"), filename);
4867 free(filename);
4868 return;
4869 }
4870 FVB_MakeNamelist((FontViewBase *) fv, file);
4871 fclose(file);
4872 }
4873
FVMenuLoadNamelist(GWindow UNUSED (gw),struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4874 static void FVMenuLoadNamelist(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4875 /* Read in a name list and copy it into the prefs dir so that we'll find */
4876 /* it in the future */
4877 /* Be prepared to update what we've already got if names match */
4878 char buffer[1025];
4879 char *ret = gwwv_open_filename(_("Load Namelist"),NULL,
4880 "*.nam",NULL);
4881 char *temp, *pt;
4882 char *buts[3];
4883 FILE *old, *new;
4884 int ch, ans;
4885 NameList *nl;
4886
4887 if ( ret==NULL )
4888 return; /* Cancelled */
4889 temp = utf82def_copy(ret);
4890 pt = strrchr(temp,'/');
4891 if ( pt==NULL )
4892 pt = temp;
4893 else
4894 ++pt;
4895 snprintf(buffer,sizeof(buffer),"%s/%s", getFontForgeUserDir(Config), pt);
4896 if ( access(buffer,F_OK)==0 ) {
4897 buts[0] = _("_Replace");
4898 buts[1] = _("_Cancel");
4899 buts[2] = NULL;
4900 ans = gwwv_ask( _("Replace"),(const char **) buts,0,1,_("A name list with this name already exists. Replace it?"));
4901 if ( ans==1 ) {
4902 free(temp);
4903 free(ret);
4904 return;
4905 }
4906 }
4907
4908 old = fopen( temp,"r");
4909 if ( old==NULL ) {
4910 ff_post_error(_("No such file"),_("Could not read %s"), ret );
4911 free(ret); free(temp);
4912 return;
4913 }
4914 if ( (nl = LoadNamelist(temp))==NULL ) {
4915 ff_post_error(_("Bad namelist file"),_("Could not parse %s"), ret );
4916 free(ret); free(temp);
4917 fclose(old);
4918 return;
4919 }
4920 free(ret); free(temp);
4921 if ( nl->uses_unicode ) {
4922 if ( nl->a_utf8_name!=NULL )
4923 ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist contains at least one non-ASCII glyph name, namely: %s"), nl->a_utf8_name );
4924 else
4925 ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist is based on a namelist which contains non-ASCII glyph names"));
4926 }
4927
4928 new = fopen( buffer,"w");
4929 if ( new==NULL ) {
4930 ff_post_error(_("Create failed"),_("Could not write %s"), buffer );
4931 fclose(old);
4932 return;
4933 }
4934
4935 while ( (ch=getc(old))!=EOF )
4936 putc(ch,new);
4937 fclose(old);
4938 fclose(new);
4939 }
4940
FVMenuRenameByNamelist(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4941 static void FVMenuRenameByNamelist(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4942 FontView *fv = (FontView *) GDrawGetUserData(gw);
4943 char **namelists = AllNamelistNames();
4944 int i;
4945 int ret;
4946 NameList *nl;
4947 extern int allow_utf8_glyphnames;
4948
4949 for ( i=0; namelists[i]!=NULL; ++i );
4950 ret = gwwv_choose(_("Rename by NameList"),(const char **) namelists,i,0,_("Rename the glyphs in this font to the names found in the selected namelist"));
4951 if ( ret==-1 )
4952 return;
4953 nl = NameListByName(namelists[ret]);
4954 if ( nl==NULL ) {
4955 IError("Couldn't find namelist");
4956 return;
4957 } else if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames) {
4958 ff_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
4959 return;
4960 }
4961 SFRenameGlyphsToNamelist(fv->b.sf,nl);
4962 GDrawRequestExpose(fv->v,NULL,false);
4963 }
4964
FVMenuNameGlyphs(GWindow gw,struct gmenuitem * UNUSED (mi),GEvent * UNUSED (e))4965 static void FVMenuNameGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4966 FontView *fv = (FontView *) GDrawGetUserData(gw);
4967 /* Read a file containing a list of names, and add an unencoded glyph for */
4968 /* each name */
4969 char buffer[33];
4970 char *ret = gwwv_open_filename(_("Load glyph names"),NULL, "*",NULL);
4971 char *temp, *pt;
4972 FILE *file;
4973 int ch;
4974 SplineChar *sc;
4975 FontView *fvs;
4976
4977 if ( ret==NULL )
4978 return; /* Cancelled */
4979 temp = utf82def_copy(ret);
4980
4981 file = fopen( temp,"r");
4982 if ( file==NULL ) {
4983 ff_post_error(_("No such file"),_("Could not read %s"), ret );
4984 free(ret); free(temp);
4985 return;
4986 }
4987 pt = buffer;
4988 for (;;) {
4989 ch = getc(file);
4990 if ( ch!=EOF && !isspace(ch)) {
4991 if ( pt<buffer+sizeof(buffer)-1 )
4992 *pt++ = ch;
4993 } else {
4994 if ( pt!=buffer ) {
4995 *pt = '\0';
4996 sc = NULL;
4997 for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) ) {
4998 EncMap *map = fvs->b.map;
4999 if ( map->enccount+1>=map->encmax )
5000 map->map = realloc(map->map,(map->encmax += 20)*sizeof(int));
5001 map->map[map->enccount] = -1;
5002 fvs->b.selected = realloc(fvs->b.selected,(map->enccount+1));
5003 memset(fvs->b.selected+map->enccount,0,1);
5004 ++map->enccount;
5005 if ( sc==NULL ) {
5006 sc = SFMakeChar(fv->b.sf,map,map->enccount-1);
5007 free(sc->name);
5008 sc->name = copy(buffer);
5009 sc->comment = copy("."); /* Mark as something for sfd file */
5010 }
5011 map->map[map->enccount-1] = sc->orig_pos;
5012 map->backmap[sc->orig_pos] = map->enccount-1;
5013 }
5014 pt = buffer;
5015 }
5016 if ( ch==EOF )
5017 break;
5018 }
5019 }
5020 fclose(file);
5021 free(ret); free(temp);
5022 FontViewReformatAll(fv->b.sf);
5023 }
5024
5025 static GMenuItem2 enlist[] = {
5026 { { (unichar_t *) N_("_Reencode"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Reencode|No Shortcut"), emptymenu, FVEncodingMenuBuild, NULL, MID_Reencode },
5027 { { (unichar_t *) N_("_Compact"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Compact|No Shortcut"), NULL, NULL, FVMenuCompact, MID_Compact },
5028 { { (unichar_t *) N_("_Force Encoding"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Force Encoding|No Shortcut"), emptymenu, FVForceEncodingMenuBuild, NULL, MID_ForceReencode },
5029 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5030 { { (unichar_t *) N_("_Add Encoding Slots..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Add Encoding Slots...|No Shortcut"), NULL, NULL, FVMenuAddUnencoded, MID_AddUnencoded },
5031 { { (unichar_t *) N_("Remove _Unused Slots"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Remove Unused Slots|No Shortcut"), NULL, NULL, FVMenuRemoveUnused, MID_RemoveUnused },
5032 { { (unichar_t *) N_("_Detach Glyphs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Detach Glyphs|No Shortcut"), NULL, NULL, FVMenuDetachGlyphs, MID_DetachGlyphs },
5033 { { (unichar_t *) N_("Detach & Remo_ve Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Detach & Remove Glyphs...|No Shortcut"), NULL, NULL, FVMenuDetachAndRemoveGlyphs, MID_DetachAndRemoveGlyphs },
5034 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5035 { { (unichar_t *) N_("Add E_ncoding Name..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Add Encoding Name...|No Shortcut"), NULL, NULL, FVMenuAddEncodingName, 0 },
5036 { { (unichar_t *) N_("_Load Encoding..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Load Encoding...|No Shortcut"), NULL, NULL, FVMenuLoadEncoding, MID_LoadEncoding },
5037 { { (unichar_t *) N_("Ma_ke From Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Make From Font...|No Shortcut"), NULL, NULL, FVMenuMakeFromFont, MID_MakeFromFont },
5038 { { (unichar_t *) N_("Remove En_coding..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Remove Encoding...|No Shortcut"), NULL, NULL, FVMenuRemoveEncoding, MID_RemoveEncoding },
5039 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5040 { { (unichar_t *) N_("Display By _Groups..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Display By Groups...|No Shortcut"), NULL, NULL, FVMenuDisplayByGroups, MID_DisplayByGroups },
5041 { { (unichar_t *) N_("D_efine Groups..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Define Groups...|No Shortcut"), NULL, NULL, FVMenuDefineGroups, 0 },
5042 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5043 { { (unichar_t *) N_("_Save Namelist of Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Save Namelist of Font...|No Shortcut"), NULL, NULL, FVMenuMakeNamelist, MID_SaveNamelist },
5044 { { (unichar_t *) N_("L_oad Namelist..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Load Namelist...|No Shortcut"), NULL, NULL, FVMenuLoadNamelist, 0 },
5045 { { (unichar_t *) N_("Rename Gl_yphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Rename Glyphs...|No Shortcut"), NULL, NULL, FVMenuRenameByNamelist, MID_RenameGlyphs },
5046 { { (unichar_t *) N_("Cre_ate Named Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Create Named Glyphs...|No Shortcut"), NULL, NULL, FVMenuNameGlyphs, MID_NameGlyphs },
5047 GMENUITEM2_EMPTY
5048 };
5049
enlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))5050 static void enlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5051 FontView *fv = (FontView *) GDrawGetUserData(gw);
5052 int i, gid;
5053 SplineFont *sf = fv->b.sf;
5054 EncMap *map = fv->b.map;
5055 int anyglyphs = false;
5056
5057 for ( i=map->enccount-1; i>=0 ; --i )
5058 if ( fv->b.selected[i] && (gid=map->map[i])!=-1 )
5059 anyglyphs = true;
5060
5061 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5062 switch ( mi->mid ) {
5063 case MID_Compact:
5064 mi->ti.checked = fv->b.normal!=NULL;
5065 break;
5066 case MID_HideNoGlyphSlots:
5067 break;
5068 case MID_Reencode: case MID_ForceReencode:
5069 mi->ti.disabled = fv->b.cidmaster!=NULL;
5070 break;
5071 case MID_DetachGlyphs: case MID_DetachAndRemoveGlyphs:
5072 mi->ti.disabled = !anyglyphs;
5073 break;
5074 case MID_RemoveUnused:
5075 gid = map->enccount>0 ? map->map[map->enccount-1] : -1;
5076 mi->ti.disabled = gid!=-1 && SCWorthOutputting(sf->glyphs[gid]);
5077 break;
5078 case MID_MakeFromFont:
5079 mi->ti.disabled = fv->b.cidmaster!=NULL || map->enccount>1024 || map->enc!=&custom;
5080 break;
5081 case MID_RemoveEncoding:
5082 break;
5083 case MID_DisplayByGroups:
5084 mi->ti.disabled = fv->b.cidmaster!=NULL || group_root==NULL;
5085 break;
5086 case MID_NameGlyphs:
5087 mi->ti.disabled = fv->b.normal!=NULL || fv->b.cidmaster!=NULL;
5088 break;
5089 case MID_RenameGlyphs: case MID_SaveNamelist:
5090 mi->ti.disabled = fv->b.cidmaster!=NULL;
5091 break;
5092 }
5093 }
5094 }
5095
5096 static GMenuItem2 lylist[] = {
5097 { { (unichar_t *) N_("Layer|Foreground"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 1, 1, 0, 0, 1, 1, 0, '\0' }, NULL, NULL, NULL, FVMenuChangeLayer, ly_fore },
5098 GMENUITEM2_EMPTY
5099 };
5100
lylistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))5101 static void lylistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5102 FontView *fv = (FontView *) GDrawGetUserData(gw);
5103 SplineFont *sf = fv->b.sf;
5104 int ly;
5105 GMenuItem *sub;
5106
5107 sub = calloc(sf->layer_cnt+1,sizeof(GMenuItem));
5108 for ( ly=ly_fore; ly<sf->layer_cnt; ++ly ) {
5109 sub[ly-1].ti.text = utf82u_copy(sf->layers[ly].name);
5110 sub[ly-1].ti.checkable = true;
5111 sub[ly-1].ti.checked = ly == fv->b.active_layer;
5112 sub[ly-1].invoke = FVMenuChangeLayer;
5113 sub[ly-1].mid = ly;
5114 sub[ly-1].ti.fg = sub[ly-1].ti.bg = COLOR_DEFAULT;
5115 }
5116 GMenuItemArrayFree(mi->sub);
5117 mi->sub = sub;
5118 }
5119
5120 static GMenuItem2 vwlist[] = {
5121 { { (unichar_t *) N_("_Next Glyph"), (GImage *) "viewnext.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Glyph|No Shortcut"), NULL, NULL, FVMenuChangeChar, MID_Next },
5122 { { (unichar_t *) N_("_Prev Glyph"), (GImage *) "viewprev.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Glyph|No Shortcut"), NULL, NULL, FVMenuChangeChar, MID_Prev },
5123 { { (unichar_t *) N_("Next _Defined Glyph"), (GImage *) "viewnextdef.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Next Defined Glyph|No Shortcut"), NULL, NULL, FVMenuChangeChar, MID_NextDef },
5124 { { (unichar_t *) N_("Prev Defined Gl_yph"), (GImage *) "viewprevdef.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Prev Defined Glyph|No Shortcut"), NULL, NULL, FVMenuChangeChar, MID_PrevDef },
5125 { { (unichar_t *) N_("_Goto"), (GImage *) "viewgoto.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Goto|No Shortcut"), NULL, NULL, FVMenuGotoChar, 0 },
5126 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5127 { { (unichar_t *) N_("_Layers"), (GImage *) "viewlayers.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Layers|No Shortcut"), lylist, lylistcheck, NULL, 0 },
5128 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5129 { { (unichar_t *) N_("_Show ATT"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Show ATT|No Shortcut"), NULL, NULL, FVMenuShowAtt, 0 },
5130 { { (unichar_t *) N_("Display S_ubstitutions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'u' }, H_("Display Substitutions...|No Shortcut"), NULL, NULL, FVMenuDisplaySubs, MID_DisplaySubs },
5131 { { (unichar_t *) N_("Com_binations"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'b' }, H_("Combinations|No Shortcut"), cblist, cblistcheck, NULL, 0 },
5132 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5133 { { (unichar_t *) N_("Label Gl_yph By"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'b' }, H_("Label Glyph By|No Shortcut"), gllist, gllistcheck, NULL, 0 },
5134 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5135 { { (unichar_t *) N_("S_how H. Metrics..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Show H. Metrics...|No Shortcut"), NULL, NULL, FVMenuShowMetrics, MID_ShowHMetrics },
5136 { { (unichar_t *) N_("Show _V. Metrics..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Show V. Metrics...|No Shortcut"), NULL, NULL, FVMenuShowMetrics, MID_ShowVMetrics },
5137 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5138 { { (unichar_t *) N_("32x8 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '2' }, H_("32x8 cell window|No Shortcut"), NULL, NULL, FVMenuWSize, MID_32x8 },
5139 { { (unichar_t *) N_("_16x4 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("16x4 cell window|No Shortcut"), NULL, NULL, FVMenuWSize, MID_16x4 },
5140 { { (unichar_t *) N_("_8x2 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("8x2 cell window|No Shortcut"), NULL, NULL, FVMenuWSize, MID_8x2 },
5141 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5142 { { (unichar_t *) N_("_24 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '2' }, H_("24 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_24 },
5143 { { (unichar_t *) N_("_36 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("36 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_36 },
5144 { { (unichar_t *) N_("_48 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("48 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_48 },
5145 { { (unichar_t *) N_("_72 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("72 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_72 },
5146 { { (unichar_t *) N_("_96 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("96 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_96 },
5147 { { (unichar_t *) N_("_128 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("128 pixel outline|No Shortcut"), NULL, NULL, FVMenuSize, MID_128 },
5148 { { (unichar_t *) N_("_Anti Alias"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'A' }, H_("Anti Alias|No Shortcut"), NULL, NULL, FVMenuSize, MID_AntiAlias },
5149 { { (unichar_t *) N_("_Fit to font bounding box"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'F' }, H_("Fit to font bounding box|No Shortcut"), NULL, NULL, FVMenuSize, MID_FitToBbox },
5150 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5151 { { (unichar_t *) N_("Bitmap _Magnification..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'F' }, H_("Bitmap Magnification...|No Shortcut"), NULL, NULL, FVMenuMagnify, MID_BitmapMag },
5152 GMENUITEM2_EMPTY, /* Some extra room to show bitmaps */
5153 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5154 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5155 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5156 GMENUITEM2_EMPTY
5157 };
5158
vwlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))5159 static void vwlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5160 FontView *fv = (FontView *) GDrawGetUserData(gw);
5161 int anychars = FVAnyCharSelected(fv);
5162 int i, base;
5163 BDFFont *bdf;
5164 char buffer[50];
5165 int pos;
5166 SplineFont *sf = fv->b.sf;
5167 SplineFont *master = sf->cidmaster ? sf->cidmaster : sf;
5168 EncMap *map = fv->b.map;
5169 OTLookup *otl;
5170
5171 for ( i=0; vwlist[i].ti.text==NULL || strcmp((char *) vwlist[i].ti.text, _("Bitmap _Magnification..."))!=0; ++i );
5172 base = i+1;
5173 for ( i=base; vwlist[i].ti.text!=NULL; ++i ) {
5174 free( vwlist[i].ti.text);
5175 vwlist[i].ti.text = NULL;
5176 }
5177
5178 vwlist[base-1].ti.disabled = true;
5179 if ( master->bitmaps!=NULL ) {
5180 for ( bdf = master->bitmaps, i=base;
5181 i<sizeof(vwlist)/sizeof(vwlist[0])-1 && bdf!=NULL;
5182 ++i, bdf = bdf->next ) {
5183 if ( BDFDepth(bdf)==1 )
5184 sprintf( buffer, _("%d pixel bitmap"), bdf->pixelsize );
5185 else
5186 sprintf( buffer, _("%d@%d pixel bitmap"),
5187 bdf->pixelsize, BDFDepth(bdf) );
5188 vwlist[i].ti.text = (unichar_t *) utf82u_copy(buffer);
5189 vwlist[i].ti.checkable = true;
5190 vwlist[i].ti.checked = bdf==fv->show;
5191 vwlist[i].ti.userdata = bdf;
5192 vwlist[i].invoke = FVMenuShowBitmap;
5193 vwlist[i].ti.fg = vwlist[i].ti.bg = COLOR_DEFAULT;
5194 if ( bdf==fv->show )
5195 vwlist[base-1].ti.disabled = false;
5196 }
5197 }
5198 GMenuItemArrayFree(mi->sub);
5199 mi->sub = GMenuItem2ArrayCopy(vwlist,NULL);
5200
5201 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5202 switch ( mi->mid ) {
5203 case MID_Next: case MID_Prev:
5204 mi->ti.disabled = anychars<0;
5205 break;
5206 case MID_NextDef:
5207 pos = anychars+1;
5208 if ( anychars<0 ) pos = map->enccount;
5209 for ( ; pos<map->enccount &&
5210 (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
5211 ++pos );
5212 mi->ti.disabled = pos==map->enccount;
5213 break;
5214 case MID_PrevDef:
5215 for ( pos = anychars-1; pos>=0 &&
5216 (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
5217 --pos );
5218 mi->ti.disabled = pos<0;
5219 break;
5220 case MID_DisplaySubs: { SplineFont *_sf = sf;
5221 mi->ti.checked = fv->cur_subtable!=NULL;
5222 if ( _sf->cidmaster ) _sf = _sf->cidmaster;
5223 for ( otl=_sf->gsub_lookups; otl!=NULL; otl=otl->next )
5224 if ( otl->lookup_type == gsub_single && otl->subtables!=NULL )
5225 break;
5226 mi->ti.disabled = otl==NULL;
5227 } break;
5228 case MID_ShowHMetrics:
5229 break;
5230 case MID_ShowVMetrics:
5231 mi->ti.disabled = !sf->hasvmetrics;
5232 break;
5233 case MID_32x8:
5234 mi->ti.checked = (fv->rowcnt==8 && fv->colcnt==32);
5235 mi->ti.disabled = fv->b.container!=NULL;
5236 break;
5237 case MID_16x4:
5238 mi->ti.checked = (fv->rowcnt==4 && fv->colcnt==16);
5239 mi->ti.disabled = fv->b.container!=NULL;
5240 break;
5241 case MID_8x2:
5242 mi->ti.checked = (fv->rowcnt==2 && fv->colcnt==8);
5243 mi->ti.disabled = fv->b.container!=NULL;
5244 break;
5245 case MID_24:
5246 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==24);
5247 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5248 break;
5249 case MID_36:
5250 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==36);
5251 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5252 break;
5253 case MID_48:
5254 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==48);
5255 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5256 break;
5257 case MID_72:
5258 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==72);
5259 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5260 break;
5261 case MID_96:
5262 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==96);
5263 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5264 break;
5265 case MID_128:
5266 mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==128);
5267 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5268 break;
5269 case MID_AntiAlias:
5270 mi->ti.checked = (fv->show!=NULL && fv->show->clut!=NULL);
5271 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5272 break;
5273 case MID_FitToBbox:
5274 mi->ti.checked = (fv->show!=NULL && fv->show->bbsized);
5275 mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5276 break;
5277 case MID_Layers:
5278 mi->ti.disabled = sf->layer_cnt<=2 || sf->multilayer;
5279 break;
5280 }
5281 }
5282 }
5283
5284 static GMenuItem2 histlist[] = {
5285 { { (unichar_t *) N_("_HStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("HStem|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_HStemHist },
5286 { { (unichar_t *) N_("_VStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("VStem|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_VStemHist },
5287 { { (unichar_t *) N_("BlueValues"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("BlueValues|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_BlueValuesHist },
5288 GMENUITEM2_EMPTY
5289 };
5290
5291 static GMenuItem2 htlist[] = {
5292 { { (unichar_t *) N_("Auto_Hint"), (GImage *) "hintsautohint.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("AutoHint|No Shortcut"), NULL, NULL, FVMenuAutoHint, MID_AutoHint },
5293 { { (unichar_t *) N_("Hint _Substitution Pts"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Hint Substitution Pts|No Shortcut"), NULL, NULL, FVMenuAutoHintSubs, MID_HintSubsPt },
5294 { { (unichar_t *) N_("Auto _Counter Hint"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Auto Counter Hint|No Shortcut"), NULL, NULL, FVMenuAutoCounter, MID_AutoCounter },
5295 { { (unichar_t *) N_("_Don't AutoHint"), (GImage *) "hintsdontautohint.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Don't AutoHint|No Shortcut"), NULL, NULL, FVMenuDontAutoHint, MID_DontAutoHint },
5296 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5297 { { (unichar_t *) N_("Auto_Instr"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("AutoInstr|No Shortcut"), NULL, NULL, FVMenuAutoInstr, MID_AutoInstr },
5298 { { (unichar_t *) N_("_Edit Instructions..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Edit Instructions...|No Shortcut"), NULL, NULL, FVMenuEditInstrs, MID_EditInstructions },
5299 { { (unichar_t *) N_("Edit 'fpgm'..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'fpgm'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editfpgm },
5300 { { (unichar_t *) N_("Edit 'prep'..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'prep'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editprep },
5301 { { (unichar_t *) N_("Edit 'maxp'..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'maxp'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editmaxp },
5302 { { (unichar_t *) N_("Edit 'cvt '..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'cvt '...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editcvt },
5303 { { (unichar_t *) N_("Remove Instr Tables"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Remove Instr Tables|No Shortcut"), NULL, NULL, FVMenuRmInstrTables, MID_RmInstrTables },
5304 { { (unichar_t *) N_("S_uggest Deltas..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Suggest Deltas...|No Shortcut"), NULL, NULL, FVMenuDeltas, MID_Deltas },
5305 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5306 { { (unichar_t *) N_("_Clear Hints"), (GImage *) "hintsclearvstems.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear Hints|No Shortcut"), NULL, NULL, FVMenuClearHints, MID_ClearHints },
5307 { { (unichar_t *) N_("Clear Instructions"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear Instructions|No Shortcut"), NULL, NULL, FVMenuClearInstrs, MID_ClearInstrs },
5308 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5309 { { (unichar_t *) N_("Histograms"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Histograms|No Shortcut"), histlist, NULL, NULL, 0 },
5310 GMENUITEM2_EMPTY
5311 };
5312
5313 static GMenuItem2 mtlist[] = {
5314 { { (unichar_t *) N_("New _Metrics Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("New Metrics Window|No Shortcut"), NULL, NULL, FVMenuOpenMetrics, MID_OpenMetrics },
5315 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5316 { { (unichar_t *) N_("_Center in Width"), (GImage *) "metricscenter.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Center in Width|No Shortcut"), NULL, NULL, FVMenuCenter, MID_Center },
5317 { { (unichar_t *) N_("_Thirds in Width"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Thirds in Width|No Shortcut"), NULL, NULL, FVMenuCenter, MID_Thirds },
5318 { { (unichar_t *) N_("Set _Width..."), (GImage *) "metricssetwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Set Width...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetWidth },
5319 { { (unichar_t *) N_("Set _LBearing..."), (GImage *) "metricssetlbearing.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Set LBearing...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetLBearing },
5320 { { (unichar_t *) N_("Set _RBearing..."), (GImage *) "metricssetrbearing.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Set RBearing...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetRBearing },
5321 { { (unichar_t *) N_("Set Both Bearings..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Set Both Bearings...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetBearings },
5322 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5323 { { (unichar_t *) N_("Set _Vertical Advance..."), (GImage *) "metricssetvwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Set Vertical Advance...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetVWidth },
5324 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5325 { { (unichar_t *) N_("_Auto Width..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Auto Width...|No Shortcut"), NULL, NULL, FVMenuAutoWidth, 0 },
5326 { { (unichar_t *) N_("Ker_n By Classes..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Kern By Classes...|No Shortcut"), NULL, NULL, FVMenuKernByClasses, 0 },
5327 { { (unichar_t *) N_("Remove All Kern _Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove All Kern Pairs|No Shortcut"), NULL, NULL, FVMenuRemoveKern, MID_RmHKern },
5328 { { (unichar_t *) N_("Kern Pair Closeup..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Kern Pair Closeup...|No Shortcut"), NULL, NULL, FVMenuKPCloseup, 0 },
5329 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5330 { { (unichar_t *) N_("VKern By Classes..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("VKern By Classes...|No Shortcut"), NULL, NULL, FVMenuVKernByClasses, MID_VKernByClass },
5331 { { (unichar_t *) N_("VKern From HKern"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("VKern From HKern|No Shortcut"), NULL, NULL, FVMenuVKernFromHKern, MID_VKernFromH },
5332 { { (unichar_t *) N_("Remove All VKern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove All VKern Pairs|No Shortcut"), NULL, NULL, FVMenuRemoveVKern, MID_RmVKern },
5333 GMENUITEM2_EMPTY
5334 };
5335
5336 static GMenuItem2 cdlist[] = {
5337 { { (unichar_t *) N_("_Convert to CID"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Convert to CID|No Shortcut"), NULL, NULL, FVMenuConvert2CID, MID_Convert2CID },
5338 { { (unichar_t *) N_("Convert By C_Map"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Convert By CMap|No Shortcut"), NULL, NULL, FVMenuConvertByCMap, MID_ConvertByCMap },
5339 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5340 { { (unichar_t *) N_("_Flatten"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Flatten|No Shortcut"), NULL, NULL, FVMenuFlatten, MID_Flatten },
5341 { { (unichar_t *) N_("Fl_attenByCMap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("FlattenByCMap|No Shortcut"), NULL, NULL, FVMenuFlattenByCMap, MID_FlattenByCMap },
5342 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5343 { { (unichar_t *) N_("Insert F_ont..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Insert Font...|No Shortcut"), NULL, NULL, FVMenuInsertFont, MID_InsertFont },
5344 { { (unichar_t *) N_("Insert _Blank"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Insert Blank|No Shortcut"), NULL, NULL, FVMenuInsertBlank, MID_InsertBlank },
5345 { { (unichar_t *) N_("_Remove Font"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Remove Font|No Shortcut"), NULL, NULL, FVMenuRemoveFontFromCID, MID_RemoveFromCID },
5346 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5347 { { (unichar_t *) N_("_Change Supplement..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Change Supplement...|No Shortcut"), NULL, NULL, FVMenuChangeSupplement, MID_ChangeSupplement },
5348 { { (unichar_t *) N_("C_ID Font Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("CID Font Info...|No Shortcut"), NULL, NULL, FVMenuCIDFontInfo, MID_CIDFontInfo },
5349 GMENUITEM2_EMPTY, /* Extra room to show sub-font names */
5350 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5351 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5352 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5353 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5354 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5355 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5356 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5357 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5358 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5359 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5360 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5361 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5362 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5363 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5364 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5365 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5366 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5367 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5368 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5369 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5370 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5371 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5372 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5373 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5374 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5375 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5376 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5377 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5378 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5379 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5380 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5381 GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5382 GMENUITEM2_EMPTY
5383 };
5384
cdlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))5385 static void cdlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5386 FontView *fv = (FontView *) GDrawGetUserData(gw);
5387 int i, base, j;
5388 SplineFont *sub, *cidmaster = fv->b.cidmaster;
5389
5390 for ( i=0; cdlist[i].mid!=MID_CIDFontInfo; ++i );
5391 base = i+2;
5392 for ( i=base; cdlist[i].ti.text!=NULL; ++i ) {
5393 free( cdlist[i].ti.text);
5394 cdlist[i].ti.text = NULL;
5395 }
5396
5397 cdlist[base-1].ti.fg = cdlist[base-1].ti.bg = COLOR_DEFAULT;
5398 if ( cidmaster==NULL ) {
5399 cdlist[base-1].ti.line = false;
5400 } else {
5401 cdlist[base-1].ti.line = true;
5402 for ( j = 0, i=base;
5403 i<sizeof(cdlist)/sizeof(cdlist[0])-1 && j<cidmaster->subfontcnt;
5404 ++i, ++j ) {
5405 sub = cidmaster->subfonts[j];
5406 cdlist[i].ti.text = uc_copy(sub->fontname);
5407 cdlist[i].ti.checkable = true;
5408 cdlist[i].ti.checked = sub==fv->b.sf;
5409 cdlist[i].ti.userdata = sub;
5410 cdlist[i].invoke = FVMenuShowSubFont;
5411 cdlist[i].ti.fg = cdlist[i].ti.bg = COLOR_DEFAULT;
5412 }
5413 }
5414 GMenuItemArrayFree(mi->sub);
5415 mi->sub = GMenuItem2ArrayCopy(cdlist,NULL);
5416
5417 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5418 switch ( mi->mid ) {
5419 case MID_Convert2CID: case MID_ConvertByCMap:
5420 mi->ti.disabled = cidmaster!=NULL || fv->b.sf->mm!=NULL;
5421 break;
5422 case MID_InsertFont: case MID_InsertBlank:
5423 /* OpenType allows at most 255 subfonts (PS allows more, but why go to the effort to make safe font check that? */
5424 mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt>=255;
5425 break;
5426 case MID_RemoveFromCID:
5427 mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt<=1;
5428 break;
5429 case MID_Flatten: case MID_FlattenByCMap: case MID_CIDFontInfo:
5430 case MID_ChangeSupplement:
5431 mi->ti.disabled = cidmaster==NULL;
5432 break;
5433 }
5434 }
5435 }
5436
5437 static GMenuItem2 mmlist[] = {
5438 /* GT: Here (and following) MM means "MultiMaster" */
5439 { { (unichar_t *) N_("_Create MM..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Create MM...|No Shortcut"), NULL, NULL, FVMenuCreateMM, MID_CreateMM },
5440 { { (unichar_t *) N_("MM _Validity Check"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Validity Check|No Shortcut"), NULL, NULL, FVMenuMMValid, MID_MMValid },
5441 { { (unichar_t *) N_("MM _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Info...|No Shortcut"), NULL, NULL, FVMenuMMInfo, MID_MMInfo },
5442 { { (unichar_t *) N_("_Blend to New Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Blend to New Font...|No Shortcut"), NULL, NULL, FVMenuBlendToNew, MID_BlendToNew },
5443 { { (unichar_t *) N_("MM Change Default _Weights..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Change Default Weights...|No Shortcut"), NULL, NULL, FVMenuChangeMMBlend, MID_ChangeMMBlend },
5444 GMENUITEM2_EMPTY, /* Extra room to show sub-font names */
5445 };
5446
mmlistcheck(GWindow gw,struct gmenuitem * mi,GEvent * UNUSED (e))5447 static void mmlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5448 FontView *fv = (FontView *) GDrawGetUserData(gw);
5449 int i, base, j;
5450 MMSet *mm = fv->b.sf->mm;
5451 SplineFont *sub;
5452 GMenuItem2 *mml;
5453
5454 for ( i=0; mmlist[i].mid!=MID_ChangeMMBlend; ++i );
5455 base = i+2;
5456 if ( mm==NULL )
5457 mml = mmlist;
5458 else {
5459 mml = calloc(base+mm->instance_count+2,sizeof(GMenuItem2));
5460 memcpy(mml,mmlist,sizeof(mmlist));
5461 mml[base-1].ti.fg = mml[base-1].ti.bg = COLOR_DEFAULT;
5462 mml[base-1].ti.line = true;
5463 for ( j = 0, i=base; j<mm->instance_count+1; ++i, ++j ) {
5464 if ( j==0 )
5465 sub = mm->normal;
5466 else
5467 sub = mm->instances[j-1];
5468 mml[i].ti.text = uc_copy(sub->fontname);
5469 mml[i].ti.checkable = true;
5470 mml[i].ti.checked = sub==fv->b.sf;
5471 mml[i].ti.userdata = sub;
5472 mml[i].invoke = FVMenuShowSubFont;
5473 mml[i].ti.fg = mml[i].ti.bg = COLOR_DEFAULT;
5474 }
5475 }
5476 GMenuItemArrayFree(mi->sub);
5477 mi->sub = GMenuItem2ArrayCopy(mml,NULL);
5478 if ( mml!=mmlist ) {
5479 for ( i=base; mml[i].ti.text!=NULL; ++i )
5480 free( mml[i].ti.text);
5481 free(mml);
5482 }
5483
5484 for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5485 switch ( mi->mid ) {
5486 case MID_CreateMM:
5487 mi->ti.disabled = false;
5488 break;
5489 case MID_MMInfo: case MID_MMValid: case MID_BlendToNew:
5490 mi->ti.disabled = mm==NULL;
5491 break;
5492 case MID_ChangeMMBlend:
5493 mi->ti.disabled = mm==NULL || mm->apple;
5494 break;
5495 }
5496 }
5497 }
5498
5499 static GMenuItem2 wnmenu[] = {
5500 { { (unichar_t *) N_("New O_utline Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("New Outline Window|No Shortcut"), NULL, NULL, FVMenuOpenOutline, MID_OpenOutline },
5501 { { (unichar_t *) N_("New _Bitmap Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("New Bitmap Window|No Shortcut"), NULL, NULL, FVMenuOpenBitmap, MID_OpenBitmap },
5502 { { (unichar_t *) N_("New _Metrics Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("New Metrics Window|No Shortcut"), NULL, NULL, FVMenuOpenMetrics, MID_OpenMetrics },
5503 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5504 { { (unichar_t *) N_("Warnings"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Warnings|No Shortcut"), NULL, NULL, _MenuWarnings, MID_Warnings },
5505 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5506 GMENUITEM2_EMPTY
5507 };
5508
FVWindowMenuBuild(GWindow gw,struct gmenuitem * mi,GEvent * e)5509 static void FVWindowMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *e) {
5510 FontView *fv = (FontView *) GDrawGetUserData(gw);
5511 int anychars = FVAnyCharSelected(fv);
5512 struct gmenuitem *wmi;
5513 int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
5514
5515 WindowMenuBuild(gw,mi,e);
5516 for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
5517 switch ( wmi->mid ) {
5518 case MID_OpenOutline:
5519 wmi->ti.disabled = anychars==-1 || in_modal;
5520 break;
5521 case MID_OpenBitmap:
5522 wmi->ti.disabled = anychars==-1 || fv->b.sf->bitmaps==NULL || in_modal;
5523 break;
5524 case MID_OpenMetrics:
5525 wmi->ti.disabled = in_modal;
5526 break;
5527 case MID_Warnings:
5528 wmi->ti.disabled = ErrorWindowExists();
5529 break;
5530 }
5531 }
5532 }
5533
5534 GMenuItem2 helplist[] = {
5535 { { (unichar_t *) N_("_Help"), (GImage *) "helphelp.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Help|F1"), NULL, NULL, FVMenuContextualHelp, 0 },
5536 { { (unichar_t *) N_("_Overview"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Overview|Shft+F1"), NULL, NULL, MenuHelp, 0 },
5537 { { (unichar_t *) N_("_Index"), (GImage *) "helpindex.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Index|No Shortcut"), NULL, NULL, MenuIndex, 0 },
5538 { { (unichar_t *) N_("_About..."), (GImage *) "helpabout.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("About...|No Shortcut"), NULL, NULL, MenuAbout, 0 },
5539 { { (unichar_t *) N_("_License..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("License...|No Shortcut"), NULL, NULL, MenuLicense, 0 },
5540 GMENUITEM2_EMPTY
5541 };
5542
5543 GMenuItem fvpopupmenu[] = {
5544 { { (unichar_t *) N_("New O_utline Window"), 0, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'u' }, '\0', ksm_control, NULL, NULL, FVMenuOpenOutline, MID_OpenOutline },
5545 GMENUITEM_LINE,
5546 { { (unichar_t *) N_("Cu_t"), (GImage *) "editcut.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, '\0', ksm_control, NULL, NULL, FVMenuCut, MID_Cut },
5547 { { (unichar_t *) N_("_Copy"), (GImage *) "editcopy.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, FVMenuCopy, MID_Copy },
5548 { { (unichar_t *) N_("C_opy Reference"), (GImage *) "editcopyref.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, FVMenuCopyRef, MID_CopyRef },
5549 { { (unichar_t *) N_("Copy _Width"), (GImage *) "editcopywidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, '\0', ksm_control, NULL, NULL, FVMenuCopyWidth, MID_CopyWidth },
5550 { { (unichar_t *) N_("_Paste"), (GImage *) "editpaste.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, '\0', ksm_control, NULL, NULL, FVMenuPaste, MID_Paste },
5551 { { (unichar_t *) N_("C_lear"), (GImage *) "editclear.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, 0, 0, NULL, NULL, FVMenuClear, MID_Clear },
5552 { { (unichar_t *) N_("Copy _Fg To Bg"), (GImage *) "editcopyfg2bg.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuCopyFgBg, MID_CopyFgToBg },
5553 { { (unichar_t *) N_("U_nlink Reference"), (GImage *) "editunlink.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, '\0', ksm_control, NULL, NULL, FVMenuUnlinkRef, MID_UnlinkRef },
5554 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, '\0', 0, NULL, NULL, NULL, 0 }, /* line */
5555 { { (unichar_t *) N_("Glyph _Info..."), (GImage *) "elementglyphinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, '\0', ksm_control, NULL, NULL, FVMenuCharInfo, MID_CharInfo },
5556 { { (unichar_t *) N_("_Transform..."), (GImage *) "elementtransform.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, '\0', ksm_control, NULL, NULL, FVMenuTransform, MID_Transform },
5557 { { (unichar_t *) N_("_Expand Stroke..."), (GImage *) "elementexpandstroke.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'E' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuStroke, MID_Stroke },
5558 { { (unichar_t *) N_("To _Int"), (GImage *) "elementround.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuRound2Int, MID_Round },
5559 { { (unichar_t *) N_("_Correct Direction"), (GImage *) "elementcorrectdir.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'D' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuCorrectDir, MID_Correct },
5560 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, '\0', 0, NULL, NULL, NULL, 0 }, /* line */
5561 { { (unichar_t *) N_("Auto_Hint"), (GImage *) "hintsautohint.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuAutoHint, MID_AutoHint },
5562 { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, '\0', 0, NULL, NULL, NULL, 0 }, /* line */
5563 { { (unichar_t *) N_("_Center in Width"), (GImage *) "metricscenter.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, FVMenuCenter, MID_Center },
5564 { { (unichar_t *) N_("Set _Width..."), (GImage *) "metricssetwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuSetWidth, MID_SetWidth },
5565 { { (unichar_t *) N_("Set _Vertical Advance..."), (GImage *) "metricssetvwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuSetWidth, MID_SetVWidth },
5566 GMENUITEM_EMPTY
5567 };
5568
5569 static GMenuItem2 mblist[] = {
5570 { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("File|No Shortcut"), fllist, fllistcheck, NULL, 0 },
5571 { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Edit|No Shortcut"), edlist, edlistcheck, NULL, 0 },
5572 { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Element|No Shortcut"), ellist, ellistcheck, NULL, 0 },
5573 #ifndef _NO_PYTHON
5574 { { (unichar_t *) N_("_Tools"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Tools|No Shortcut"), NULL, fvpy_tllistcheck, NULL, 0 },
5575 #endif
5576 #ifdef NATIVE_CALLBACKS
5577 { { (unichar_t *) N_("Tools_2"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Tools2|No Shortcut"), NULL, fv_tl2listcheck, NULL, 0 },
5578 #endif
5579 { { (unichar_t *) N_("H_ints"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Hints|No Shortcut"), htlist, htlistcheck, NULL, 0 },
5580 { { (unichar_t *) N_("E_ncoding"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Encoding|No Shortcut"), enlist, enlistcheck, NULL, 0 },
5581 { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("View|No Shortcut"), vwlist, vwlistcheck, NULL, 0 },
5582 { { (unichar_t *) N_("_Metrics"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Metrics|No Shortcut"), mtlist, mtlistcheck, NULL, 0 },
5583 { { (unichar_t *) N_("_CID"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("CID|No Shortcut"), cdlist, cdlistcheck, NULL, 0 },
5584 /* GT: Here (and following) MM means "MultiMaster" */
5585 { { (unichar_t *) N_("MM"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("MM|No Shortcut"), mmlist, mmlistcheck, NULL, 0 },
5586 { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Window|No Shortcut"), wnmenu, FVWindowMenuBuild, NULL, 0 },
5587 { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Help|No Shortcut"), helplist, NULL, NULL, 0 },
5588 GMENUITEM2_EMPTY
5589 };
5590
FVRefreshChar(FontView * fv,int gid)5591 void FVRefreshChar(FontView *fv,int gid) {
5592 BDFChar *bdfc;
5593 int i, j, enc;
5594 MetricsView *mv;
5595
5596 /* Can happen in scripts */ /* Can happen if we do an AutoHint when generating a tiny font for freetype context */
5597 if ( fv->v==NULL || fv->colcnt==0 || fv->b.sf->glyphs[gid]== NULL )
5598 return;
5599 for ( fv=(FontView *) (fv->b.sf->fv); fv!=NULL; fv = (FontView *) (fv->b.nextsame) ) {
5600 if( !fv->colcnt )
5601 continue;
5602
5603 for ( mv=fv->b.sf->metrics; mv!=NULL; mv=mv->next )
5604 MVRefreshChar(mv,fv->b.sf->glyphs[gid]);
5605 if ( fv->show==fv->filled )
5606 bdfc = BDFPieceMealCheck(fv->show,gid);
5607 else
5608 bdfc = fv->show->glyphs[gid];
5609 if ( bdfc==NULL )
5610 bdfc = BDFPieceMeal(fv->show,gid);
5611 /* A glyph may be encoded in several places, all need updating */
5612 for ( enc = 0; enc<fv->b.map->enccount; ++enc ) if ( fv->b.map->map[enc]==gid ) {
5613 i = enc / fv->colcnt;
5614 j = enc - i*fv->colcnt;
5615 i -= fv->rowoff;
5616 if ( i>=0 && i<fv->rowcnt )
5617 FVDrawGlyph(fv->v,fv,enc,true);
5618 }
5619 }
5620 }
5621
FVRegenChar(FontView * fv,SplineChar * sc)5622 void FVRegenChar(FontView *fv,SplineChar *sc) {
5623 struct splinecharlist *dlist;
5624 MetricsView *mv;
5625
5626 if ( fv->v==NULL ) /* Can happen in scripts */
5627 return;
5628
5629 if ( sc->orig_pos<fv->filled->glyphcnt ) {
5630 BDFCharFree(fv->filled->glyphs[sc->orig_pos]);
5631 fv->filled->glyphs[sc->orig_pos] = NULL;
5632 }
5633 /* FVRefreshChar does NOT do this for us */
5634 for ( mv=fv->b.sf->metrics; mv!=NULL; mv=mv->next )
5635 MVRegenChar(mv,sc);
5636
5637 FVRefreshChar(fv,sc->orig_pos);
5638 #if HANYANG
5639 if ( sc->compositionunit && fv->b.sf->rules!=NULL )
5640 Disp_RefreshChar(fv->b.sf,sc);
5641 #endif
5642
5643 for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
5644 FVRegenChar(fv,dlist->sc);
5645 }
5646
AddSubPST(SplineChar * sc,struct lookup_subtable * sub,char * variant)5647 static void AddSubPST(SplineChar *sc,struct lookup_subtable *sub,char *variant) {
5648 PST *pst;
5649
5650 pst = chunkalloc(sizeof(PST));
5651 pst->type = pst_substitution;
5652 pst->subtable = sub;
5653 pst->u.alt.components = copy(variant);
5654 pst->next = sc->possub;
5655 sc->possub = pst;
5656 }
5657
FVMakeChar(FontView * fv,int enc)5658 SplineChar *FVMakeChar(FontView *fv,int enc) {
5659 SplineFont *sf = fv->b.sf;
5660 SplineChar *base_sc = SFMakeChar(sf,fv->b.map,enc), *feat_sc = NULL;
5661 int feat_gid = FeatureTrans(fv,enc);
5662
5663 if ( fv->cur_subtable==NULL )
5664 return( base_sc );
5665
5666 if ( feat_gid==-1 ) {
5667 int uni = -1;
5668 FeatureScriptLangList *fl = fv->cur_subtable->lookup->features;
5669
5670 if ( base_sc->unicodeenc>=0x600 && base_sc->unicodeenc<=0x6ff &&
5671 fl!=NULL &&
5672 (fl->featuretag == CHR('i','n','i','t') ||
5673 fl->featuretag == CHR('m','e','d','i') ||
5674 fl->featuretag == CHR('f','i','n','a') ||
5675 fl->featuretag == CHR('i','s','o','l')) ) {
5676 uni = fl->featuretag == CHR('i','n','i','t') ? ArabicForms[base_sc->unicodeenc-0x600].initial :
5677 fl->featuretag == CHR('m','e','d','i') ? ArabicForms[base_sc->unicodeenc-0x600].medial :
5678 fl->featuretag == CHR('f','i','n','a') ? ArabicForms[base_sc->unicodeenc-0x600].final :
5679 fl->featuretag == CHR('i','s','o','l') ? ArabicForms[base_sc->unicodeenc-0x600].isolated :
5680 -1;
5681 feat_sc = SFGetChar(sf,uni,NULL);
5682 if ( feat_sc!=NULL )
5683 return( feat_sc );
5684 }
5685 feat_sc = SFSplineCharCreate(sf);
5686 feat_sc->unicodeenc = uni;
5687 if ( uni!=-1 ) {
5688 feat_sc->name = malloc(8);
5689 feat_sc->unicodeenc = uni;
5690 sprintf( feat_sc->name,"uni%04X", uni );
5691 } else if ( fv->cur_subtable->suffix!=NULL ) {
5692 feat_sc->name = malloc(strlen(base_sc->name)+strlen(fv->cur_subtable->suffix)+2);
5693 sprintf( feat_sc->name, "%s.%s", base_sc->name, fv->cur_subtable->suffix );
5694 } else if ( fl==NULL ) {
5695 feat_sc->name = strconcat(base_sc->name,".unknown");
5696 } else if ( fl->ismac ) {
5697 /* mac feature/setting */
5698 feat_sc->name = malloc(strlen(base_sc->name)+14);
5699 sprintf( feat_sc->name,"%s.m%d_%d", base_sc->name,
5700 (int) (fl->featuretag>>16),
5701 (int) ((fl->featuretag)&0xffff) );
5702 } else {
5703 /* OpenType feature tag */
5704 feat_sc->name = malloc(strlen(base_sc->name)+6);
5705 sprintf( feat_sc->name,"%s.%c%c%c%c", base_sc->name,
5706 (int) (fl->featuretag>>24),
5707 (int) ((fl->featuretag>>16)&0xff),
5708 (int) ((fl->featuretag>>8)&0xff),
5709 (int) ((fl->featuretag)&0xff) );
5710 }
5711 SFAddGlyphAndEncode(sf,feat_sc,fv->b.map,fv->b.map->enccount);
5712 AddSubPST(base_sc,fv->cur_subtable,feat_sc->name);
5713 return( feat_sc );
5714 } else
5715 return( base_sc );
5716 }
5717
5718 /* we style some glyph names differently, see FVExpose() */
5719 #define _uni_italic 0x2
5720 #define _uni_vertical (1<<2)
5721 #define _uni_fontmax (2<<2)
5722
FVCheckFont(FontView * fv,int type)5723 static GFont *FVCheckFont(FontView *fv,int type) {
5724 FontRequest rq;
5725
5726 if ( fv->fontset[type]==NULL ) {
5727 memset(&rq,0,sizeof(rq));
5728 rq.utf8_family_name = fv_fontnames;
5729 rq.point_size = fv_fontsize;
5730 rq.weight = 400;
5731 rq.style = 0;
5732 if (type&_uni_italic)
5733 rq.style |= fs_italic;
5734 if (type&_uni_vertical)
5735 rq.style |= fs_vertical;
5736 fv->fontset[type] = GDrawInstanciateFont(fv->v,&rq);
5737 }
5738 return( fv->fontset[type] );
5739 }
5740
5741 extern unichar_t adobes_pua_alts[0x200][3];
5742
do_Adobe_Pua(unichar_t * buf,int sob,int uni)5743 static void do_Adobe_Pua(unichar_t *buf,int sob,int uni) {
5744 int i, j;
5745
5746 for ( i=j=0; j<sob-1 && i<3; ++i ) {
5747 int ch = adobes_pua_alts[uni-0xf600][i];
5748 if ( ch==0 )
5749 break;
5750 if ( ch>=0xf600 && ch<=0xf7ff && adobes_pua_alts[ch-0xf600]!=0 ) {
5751 do_Adobe_Pua(buf+j,sob-j,ch);
5752 while ( buf[j]!=0 ) ++j;
5753 } else
5754 buf[j++] = ch;
5755 }
5756 buf[j] = 0;
5757 }
5758
FVExpose(FontView * fv,GWindow pixmap,GEvent * event)5759 static void FVExpose(FontView *fv,GWindow pixmap, GEvent *event) {
5760 int i, j, y, width, gid;
5761 int changed;
5762 GRect old, old2, r;
5763 GClut clut;
5764 struct _GImage base;
5765 GImage gi;
5766 SplineChar dummy;
5767 int styles, laststyles=0;
5768 Color bg, def_fg;
5769 int fgxor;
5770
5771 def_fg = GDrawGetDefaultForeground(NULL);
5772 memset(&gi,'\0',sizeof(gi));
5773 memset(&base,'\0',sizeof(base));
5774 if ( fv->show->clut!=NULL ) {
5775 gi.u.image = &base;
5776 base.image_type = it_index;
5777 base.clut = fv->show->clut;
5778 GDrawSetDither(NULL, false);
5779 base.trans = -1;
5780 } else {
5781 memset(&clut,'\0',sizeof(clut));
5782 gi.u.image = &base;
5783 base.image_type = it_mono;
5784 base.clut = &clut;
5785 clut.clut_len = 2;
5786 clut.clut[0] = view_bgcol;
5787 }
5788
5789 GDrawSetFont(pixmap,fv->fontset[0]);
5790 GDrawSetLineWidth(pixmap,0);
5791 GDrawPushClip(pixmap,&event->u.expose.rect,&old);
5792 GDrawFillRect(pixmap,NULL,view_bgcol);
5793 for ( i=0; i<=fv->rowcnt; ++i ) {
5794 GDrawDrawLine(pixmap,0,i*fv->cbh,fv->width,i*fv->cbh,def_fg);
5795 GDrawDrawLine(pixmap,0,i*fv->cbh+fv->lab_height,fv->width,i*fv->cbh+fv->lab_height,0x808080);
5796 }
5797 for ( i=0; i<=fv->colcnt; ++i )
5798 GDrawDrawLine(pixmap,i*fv->cbw,0,i*fv->cbw,fv->height,def_fg);
5799 for ( i=event->u.expose.rect.y/fv->cbh; i<=fv->rowcnt &&
5800 (event->u.expose.rect.y+event->u.expose.rect.height+fv->cbh-1)/fv->cbh; ++i ) for ( j=0; j<fv->colcnt; ++j ) {
5801 int index = (i+fv->rowoff)*fv->colcnt+j;
5802 SplineChar *sc;
5803 styles = 0;
5804 if ( index < fv->b.map->enccount && index!=-1 ) {
5805 unichar_t buf[60]; char cbuf[8];
5806 char utf8_buf[8];
5807 int use_utf8 = false;
5808 Color fg;
5809 int uni;
5810 struct cidmap *cidmap = NULL;
5811 sc = (gid=fv->b.map->map[index])!=-1 ? fv->b.sf->glyphs[gid]: NULL;
5812
5813 if ( fv->b.cidmaster!=NULL )
5814 cidmap = FindCidMap(fv->b.cidmaster->cidregistry,fv->b.cidmaster->ordering,fv->b.cidmaster->supplement,fv->b.cidmaster);
5815
5816 if ( ( fv->b.map->enc==&custom && index<256 ) ||
5817 ( fv->b.map->enc!=&custom && index<fv->b.map->enc->char_cnt ) ||
5818 ( cidmap!=NULL && index<MaxCID(cidmap) ))
5819 fg = def_fg;
5820 else
5821 fg = 0x505050;
5822 if ( sc==NULL )
5823 sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,index);
5824 uni = sc->unicodeenc;
5825 buf[0] = buf[1] = 0;
5826 if ( fv->b.sf->uni_interp==ui_ams && uni>=0xe000 && uni<=0xf8ff &&
5827 amspua[uni-0xe000]!=0 )
5828 uni = amspua[uni-0xe000];
5829 switch ( fv->glyphlabel ) {
5830 case gl_name:
5831 uc_strncpy(buf,sc->name,sizeof(buf)/sizeof(buf[0]));
5832 break;
5833 case gl_unicode:
5834 if ( sc->unicodeenc!=-1 ) {
5835 sprintf(cbuf,"%04x",sc->unicodeenc);
5836 uc_strcpy(buf,cbuf);
5837 } else
5838 uc_strcpy(buf,"?");
5839 break;
5840 case gl_encoding:
5841 if ( fv->b.map->enc->only_1byte ||
5842 (fv->b.map->enc->has_1byte && index<256))
5843 sprintf(cbuf,"%02x",index);
5844 else
5845 sprintf(cbuf,"%04x",index);
5846 uc_strcpy(buf,cbuf);
5847 break;
5848 case gl_glyph:
5849 if ( uni==0xad )
5850 buf[0] = '-';
5851 else if ( fv->b.sf->uni_interp==ui_adobe && uni>=0xf600 && uni<=0xf7ff &&
5852 adobes_pua_alts[uni-0xf600]!=0 ) {
5853 use_utf8 = false;
5854 do_Adobe_Pua(buf,sizeof(buf),uni);
5855 } else if ( uni>=0xe0020 && uni<=0xe007e ) {
5856 buf[0] = uni-0xe0000; /* A map of Ascii for language names */
5857 #if HANYANG
5858 } else if ( sc->compositionunit ) {
5859 if ( sc->jamo<19 )
5860 buf[0] = 0x1100+sc->jamo;
5861 else if ( sc->jamo<19+21 )
5862 buf[0] = 0x1161 + sc->jamo-19;
5863 else /* Leave a hole for the blank char */
5864 buf[0] = 0x11a8 + sc->jamo-(19+21+1);
5865 #endif
5866 } else if ( uni>0 && uni<unicode4_size ) {
5867 char *pt = utf8_buf;
5868 use_utf8 = true;
5869 *pt = '\0'; // We terminate the string in case the appendage (?) fails.
5870 pt = utf8_idpb(pt,uni,0);
5871 if (pt) *pt = '\0';
5872 else if (uni<0xd800 || uni>0xdfff)
5873 TRACE("Invalid Unicode alert.\n");
5874 } else {
5875 char *pt = strchr(sc->name,'.');
5876 buf[0] = '?';
5877 fg = 0xff0000;
5878 if ( pt!=NULL ) {
5879 int i, n = pt-sc->name;
5880 char *end;
5881 SplineFont *cm = fv->b.sf->cidmaster;
5882 if ( n==7 && sc->name[0]=='u' && sc->name[1]=='n' && sc->name[2]=='i' &&
5883 (i=strtol(sc->name+3,&end,16), end-sc->name==7))
5884 buf[0] = i;
5885 else if ( n>=5 && n<=7 && sc->name[0]=='u' &&
5886 (i=strtol(sc->name+1,&end,16), end-sc->name==n))
5887 buf[0] = i;
5888 else if ( cm!=NULL && (i=CIDFromName(sc->name,cm))!=-1 ) {
5889 int uni;
5890 uni = CID2Uni(FindCidMap(cm->cidregistry,cm->ordering,cm->supplement,cm),
5891 i);
5892 if ( uni!=-1 )
5893 buf[0] = uni;
5894 } else {
5895 int uni;
5896 *pt = '\0';
5897 uni = UniFromName(sc->name,fv->b.sf->uni_interp,fv->b.map->enc);
5898 if ( uni!=-1 )
5899 buf[0] = uni;
5900 *pt = '.';
5901 }
5902 if ( strstr(pt,".vert")!=NULL )
5903 styles = _uni_vertical;
5904 if ( buf[0]!='?' ) {
5905 fg = def_fg;
5906 if ( strstr(pt,".italic")!=NULL )
5907 styles = _uni_italic;
5908 }
5909 } else if ( strncmp(sc->name,"hwuni",5)==0 ) {
5910 int uni=-1;
5911 sscanf(sc->name,"hwuni%x", (unsigned *) &uni );
5912 if ( uni!=-1 ) buf[0] = uni;
5913 } else if ( strncmp(sc->name,"italicuni",9)==0 ) {
5914 int uni=-1;
5915 sscanf(sc->name,"italicuni%x", (unsigned *) &uni );
5916 if ( uni!=-1 ) { buf[0] = uni; styles=_uni_italic; }
5917 fg = def_fg;
5918 } else if ( strncmp(sc->name,"vertcid_",8)==0 ||
5919 strncmp(sc->name,"vertuni",7)==0 ) {
5920 styles = _uni_vertical;
5921 }
5922 }
5923 break;
5924 }
5925 r.x = j*fv->cbw+1; r.width = fv->cbw-1;
5926 r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
5927 bg = view_bgcol;
5928 fgxor = 0x000000;
5929 changed = sc->changed;
5930 if ( fv->b.sf->onlybitmaps && gid<fv->show->glyphcnt )
5931 changed = gid==-1 || fv->show->glyphs[gid]==NULL? false : fv->show->glyphs[gid]->changed;
5932 if ( changed ||
5933 sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL ||
5934 sc->color!=COLOR_DEFAULT ) {
5935 if ( sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL ||
5936 sc->color!=COLOR_DEFAULT )
5937 bg = sc->color!=COLOR_DEFAULT?sc->color:0x808080;
5938 if ( sc->changed ) {
5939 fgxor = bg ^ fvchangedcol;
5940 bg = fvchangedcol;
5941 }
5942 GDrawFillRect(pixmap,&r,bg);
5943 }
5944 if ( (!fv->b.sf->layers[fv->b.active_layer].order2 && sc->changedsincelasthinted ) ||
5945 ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->layers[fv->b.active_layer].splines!=NULL &&
5946 sc->ttf_instrs_len<=0 ) ||
5947 ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->instructions_out_of_date ) ) {
5948 Color hintcol = fvhintingneededcol;
5949 if ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->instructions_out_of_date && sc->ttf_instrs_len>0 )
5950 hintcol = 0xff0000;
5951 GDrawDrawLine(pixmap,r.x,r.y,r.x,r.y+r.height-1,hintcol);
5952 GDrawDrawLine(pixmap,r.x+1,r.y,r.x+1,r.y+r.height-1,hintcol);
5953 GDrawDrawLine(pixmap,r.x+2,r.y,r.x+2,r.y+r.height-1,hintcol);
5954 GDrawDrawLine(pixmap,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,hintcol);
5955 GDrawDrawLine(pixmap,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,hintcol);
5956 GDrawDrawLine(pixmap,r.x+r.width-3,r.y,r.x+r.width-3,r.y+r.height-1,hintcol);
5957 }
5958 if ( use_utf8 && sc->unicodeenc!=-1 &&
5959 /* Pango complains if we try to draw non characters */
5960 /* These two are guaranteed "NOT A UNICODE CHARACTER" in all planes */
5961 ((sc->unicodeenc&0xffff)==0xfffe || (sc->unicodeenc&0xffff)==0xffff ||
5962 (sc->unicodeenc>=0xfdd0 && sc->unicodeenc<=0xfdef) || /* noncharacters */
5963 (sc->unicodeenc>=0xfe00 && sc->unicodeenc<=0xfe0f) || /* variation selectors */
5964 (sc->unicodeenc>=0xe0110 && sc->unicodeenc<=0xe01ff) || /* variation selectors */
5965 /* The surrogates in BMP aren't valid either */
5966 (sc->unicodeenc>=0xd800 && sc->unicodeenc<=0xdfff))) { /* surrogates */
5967 GDrawDrawLine(pixmap,r.x,r.y,r.x+r.width-1,r.y+r.height-1,0x000000);
5968 GDrawDrawLine(pixmap,r.x,r.y+r.height-1,r.x+r.width-1,r.y,0x000000);
5969 } else if ( use_utf8 ) {
5970 GTextBounds size;
5971 if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
5972 width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,&size);
5973 if ( size.lbearing==0 && size.rbearing==0 ) {
5974 utf8_buf[0] = 0xe0 | (0xfffd>>12);
5975 utf8_buf[1] = 0x80 | ((0xfffd>>6)&0x3f);
5976 utf8_buf[2] = 0x80 | (0xfffd&0x3f);
5977 utf8_buf[3] = 0;
5978 width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,&size);
5979 }
5980 width = size.rbearing - size.lbearing+1;
5981 if ( width >= fv->cbw-1 ) {
5982 GDrawPushClip(pixmap,&r,&old2);
5983 width = fv->cbw-1;
5984 }
5985 if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 ) {
5986 y = i*fv->cbh+fv->lab_as+1;
5987 /* move rotated glyph up a bit to center it */
5988 if (styles&_uni_vertical)
5989 y -= fv->lab_as/2;
5990 GDrawDrawText8(pixmap,j*fv->cbw+(fv->cbw-1-width)/2-size.lbearing,y,utf8_buf,-1,fg^fgxor);
5991 }
5992 if ( width >= fv->cbw-1 )
5993 GDrawPopClip(pixmap,&old2);
5994 laststyles = styles;
5995 } else {
5996 if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
5997 width = GDrawGetTextWidth(pixmap,buf,-1);
5998 if ( width >= fv->cbw-1 ) {
5999 GDrawPushClip(pixmap,&r,&old2);
6000 width = fv->cbw-1;
6001 }
6002 if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 ) {
6003 y = i*fv->cbh+fv->lab_as+1;
6004 /* move rotated glyph up a bit to center it */
6005 if (styles&_uni_vertical)
6006 y -= fv->lab_as/2;
6007 GDrawDrawText(pixmap,j*fv->cbw+(fv->cbw-1-width)/2,y,buf,-1,fg^fgxor);
6008 }
6009 if ( width >= fv->cbw-1 )
6010 GDrawPopClip(pixmap,&old2);
6011 laststyles = styles;
6012 }
6013 }
6014 FVDrawGlyph(pixmap,fv,index,false);
6015 }
6016 if ( fv->showhmetrics&fvm_baseline ) {
6017 for ( i=0; i<=fv->rowcnt; ++i )
6018 GDrawDrawLine(pixmap,0,i*fv->cbh+fv->lab_height+fv->magnify*fv->show->ascent+1,fv->width,i*fv->cbh+fv->lab_height+fv->magnify*fv->show->ascent+1,METRICS_BASELINE);
6019 }
6020 GDrawPopClip(pixmap,&old);
6021 GDrawSetDither(NULL, true);
6022 }
6023
FVDrawInfo(FontView * fv,GWindow pixmap,GEvent * event)6024 void FVDrawInfo(FontView *fv,GWindow pixmap, GEvent *event) {
6025 GRect old, r;
6026 Color bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
6027 Color fg = fvglyphinfocol;
6028 SplineChar *sc, dummy;
6029 SplineFont *sf = fv->b.sf;
6030 EncMap *map = fv->b.map;
6031 int gid, uni, localenc;
6032 GString *output = g_string_new( "" );
6033 gchar *uniname = NULL;
6034
6035 if ( event->u.expose.rect.y+event->u.expose.rect.height<=fv->mbh ) {
6036 g_string_free( output, TRUE ); output = NULL;
6037 return;
6038 }
6039
6040 GDrawSetFont(pixmap,fv->fontset[0]);
6041 GDrawPushClip(pixmap,&event->u.expose.rect,&old);
6042
6043 r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
6044 GDrawFillRect(pixmap,&r,bg);
6045 if ( fv->end_pos>=map->enccount || fv->pressed_pos>=map->enccount ||
6046 fv->end_pos<0 || fv->pressed_pos<0 )
6047 fv->end_pos = fv->pressed_pos = -1; /* Can happen after reencoding */
6048 if ( fv->end_pos == -1 ) {
6049 g_string_free( output, TRUE ); output = NULL;
6050 GDrawPopClip(pixmap,&old);
6051 return;
6052 }
6053
6054 localenc = fv->end_pos;
6055 if ( map->remap!=NULL ) {
6056 struct remap *remap = map->remap;
6057 while ( remap->infont!=-1 ) {
6058 if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
6059 localenc += remap->firstenc-remap->infont;
6060 break;
6061 }
6062 ++remap;
6063 }
6064 }
6065 g_string_printf( output, "%d (0x%x) ", localenc, localenc );
6066
6067 sc = (gid=fv->b.map->map[fv->end_pos])!=-1 ? sf->glyphs[gid] : NULL;
6068 if ( fv->b.cidmaster==NULL || fv->b.normal==NULL || sc==NULL )
6069 SCBuildDummy(&dummy,sf,fv->b.map,fv->end_pos);
6070 else
6071 dummy = *sc;
6072 if ( sc==NULL ) sc = &dummy;
6073 uni = dummy.unicodeenc!=-1 ? dummy.unicodeenc : sc->unicodeenc;
6074
6075 /* last resort at guessing unicode code point from partial name */
6076 if ( uni == -1 ) {
6077 char *pt = strchr( sc->name, '.' );
6078 if( pt != NULL ) {
6079 gchar *buf = g_strndup( (const gchar *) sc->name, pt - sc->name );
6080 uni = UniFromName( (char *) buf, fv->b.sf->uni_interp, map->enc );
6081 g_free( buf );
6082 }
6083 }
6084
6085 if ( uni != -1 )
6086 g_string_append_printf( output, "U+%04X", uni );
6087 else {
6088 output = g_string_append( output, "U+????" );
6089 }
6090
6091 /* postscript name */
6092 g_string_append_printf( output, " \"%s\" ", sc->name );
6093
6094 /* code point name or range name */
6095 if( uni != -1 ) {
6096 uniname = (gchar *) unicode_name( uni );
6097 if ( uniname == NULL ) {
6098 uniname = g_strdup( UnicodeRange( uni ) );
6099 }
6100 }
6101
6102 if ( uniname != NULL ) {
6103 output = g_string_append( output, uniname );
6104 g_free( uniname );
6105 }
6106
6107 GDrawDrawText8( pixmap, 10, fv->mbh+fv->lab_as, output->str, -1, fg );
6108 g_string_free( output, TRUE ); output = NULL;
6109 GDrawPopClip( pixmap, &old );
6110 return;
6111 }
6112
FVShowInfo(FontView * fv)6113 static void FVShowInfo(FontView *fv) {
6114 GRect r;
6115
6116 if ( fv->v==NULL ) /* Can happen in scripts */
6117 return;
6118
6119 r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
6120 GDrawRequestExpose(fv->gw,&r,false);
6121 }
6122
FVChar(FontView * fv,GEvent * event)6123 void FVChar(FontView *fv, GEvent *event) {
6124 int i,pos, cnt, gid;
6125 extern int navigation_mask;
6126
6127 #if MyMemory
6128 if ( event->u.chr.keysym == GK_F2 ) {
6129 fprintf( stderr, "Malloc debug on\n" );
6130 __malloc_debug(5);
6131 } else if ( event->u.chr.keysym == GK_F3 ) {
6132 fprintf( stderr, "Malloc debug off\n" );
6133 __malloc_debug(0);
6134 }
6135 #endif
6136
6137 if ( event->u.chr.keysym=='s' &&
6138 (event->u.chr.state&ksm_control) &&
6139 (event->u.chr.state&ksm_meta) )
6140 MenuSaveAll(NULL,NULL,NULL);
6141 else if ( event->u.chr.keysym=='q' &&
6142 (event->u.chr.state&ksm_control) &&
6143 (event->u.chr.state&ksm_meta) )
6144 MenuExit(NULL,NULL,NULL);
6145 else if ( event->u.chr.keysym=='I' &&
6146 (event->u.chr.state&ksm_shift) &&
6147 (event->u.chr.state&ksm_meta) )
6148 FVMenuCharInfo(fv->gw,NULL,NULL);
6149 else if ( (event->u.chr.keysym=='[' || event->u.chr.keysym==']') &&
6150 (event->u.chr.state&ksm_control) ) {
6151 _FVMenuChangeChar(fv,event->u.chr.keysym=='['?MID_Prev:MID_Next);
6152 } else if ( (event->u.chr.keysym=='{' || event->u.chr.keysym=='}') &&
6153 (event->u.chr.state&ksm_control) ) {
6154 _FVMenuChangeChar(fv,event->u.chr.keysym=='{'?MID_PrevDef:MID_NextDef);
6155 } else if ( event->u.chr.keysym=='\\' && (event->u.chr.state&ksm_control) ) {
6156 /* European keyboards need a funky modifier to get \ */
6157 FVDoTransform(fv);
6158 #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
6159 } else if ( isdigit(event->u.chr.keysym) && (event->u.chr.state&ksm_control) &&
6160 (event->u.chr.state&ksm_meta) ) {
6161 /* The Script menu isn't always up to date, so we might get one of */
6162 /* the shortcuts here */
6163 int index = event->u.chr.keysym-'1';
6164 if ( index<0 ) index = 9;
6165 if ( script_filenames[index]!=NULL )
6166 ExecuteScriptFile((FontViewBase *) fv,NULL,script_filenames[index]);
6167 #endif
6168 } else if ( event->u.chr.keysym == GK_Left ||
6169 event->u.chr.keysym == GK_Tab ||
6170 event->u.chr.keysym == GK_BackTab ||
6171 event->u.chr.keysym == GK_Up ||
6172 event->u.chr.keysym == GK_Right ||
6173 event->u.chr.keysym == GK_Down ||
6174 event->u.chr.keysym == GK_KP_Left ||
6175 event->u.chr.keysym == GK_KP_Up ||
6176 event->u.chr.keysym == GK_KP_Right ||
6177 event->u.chr.keysym == GK_KP_Down ||
6178 event->u.chr.keysym == GK_Home ||
6179 event->u.chr.keysym == GK_KP_Home ||
6180 event->u.chr.keysym == GK_End ||
6181 event->u.chr.keysym == GK_KP_End ||
6182 event->u.chr.keysym == GK_Page_Up ||
6183 event->u.chr.keysym == GK_KP_Page_Up ||
6184 event->u.chr.keysym == GK_Prior ||
6185 event->u.chr.keysym == GK_Page_Down ||
6186 event->u.chr.keysym == GK_KP_Page_Down ||
6187 event->u.chr.keysym == GK_Next ) {
6188 int end_pos = fv->end_pos;
6189 /* We move the currently selected char. If there is none, then pick */
6190 /* something on the screen */
6191 if ( end_pos==-1 )
6192 end_pos = (fv->rowoff+fv->rowcnt/2)*fv->colcnt;
6193 switch ( event->u.chr.keysym ) {
6194 case GK_Tab:
6195 pos = end_pos;
6196 do {
6197 if ( event->u.chr.state&ksm_shift )
6198 --pos;
6199 else
6200 ++pos;
6201 if ( pos>=fv->b.map->enccount ) pos = 0;
6202 else if ( pos<0 ) pos = fv->b.map->enccount-1;
6203 } while ( pos!=end_pos &&
6204 ((gid=fv->b.map->map[pos])==-1 || !SCWorthOutputting(fv->b.sf->glyphs[gid])));
6205 if ( pos==end_pos ) ++pos;
6206 if ( pos>=fv->b.map->enccount ) pos = 0;
6207 break;
6208 #if GK_Tab!=GK_BackTab
6209 case GK_BackTab:
6210 pos = end_pos;
6211 do {
6212 --pos;
6213 if ( pos<0 ) pos = fv->b.map->enccount-1;
6214 } while ( pos!=end_pos &&
6215 ((gid=fv->b.map->map[pos])==-1 || !SCWorthOutputting(fv->b.sf->glyphs[gid])));
6216 if ( pos==end_pos ) --pos;
6217 if ( pos<0 ) pos = 0;
6218 break;
6219 #endif
6220 case GK_Left: case GK_KP_Left:
6221 pos = end_pos-1;
6222 break;
6223 case GK_Right: case GK_KP_Right:
6224 pos = end_pos+1;
6225 break;
6226 case GK_Up: case GK_KP_Up:
6227 pos = end_pos-fv->colcnt;
6228 break;
6229 case GK_Down: case GK_KP_Down:
6230 pos = end_pos+fv->colcnt;
6231 break;
6232 case GK_End: case GK_KP_End:
6233 pos = fv->b.map->enccount;
6234 break;
6235 case GK_Home: case GK_KP_Home:
6236 pos = 0;
6237 if ( fv->b.sf->top_enc!=-1 && fv->b.sf->top_enc<fv->b.map->enccount )
6238 pos = fv->b.sf->top_enc;
6239 else {
6240 pos = SFFindSlot(fv->b.sf,fv->b.map,home_char,NULL);
6241 if ( pos==-1 ) pos = 0;
6242 }
6243 break;
6244 case GK_Page_Up: case GK_KP_Page_Up:
6245 #if GK_Prior!=GK_Page_Up
6246 case GK_Prior:
6247 #endif
6248 pos = (fv->rowoff-fv->rowcnt+1)*fv->colcnt;
6249 break;
6250 case GK_Page_Down: case GK_KP_Page_Down:
6251 #if GK_Next!=GK_Page_Down
6252 case GK_Next:
6253 #endif
6254 pos = (fv->rowoff+fv->rowcnt+1)*fv->colcnt;
6255 break;
6256 }
6257 if ( pos<0 ) pos = 0;
6258 if ( pos>=fv->b.map->enccount ) pos = fv->b.map->enccount-1;
6259 if ( event->u.chr.state&ksm_shift && event->u.chr.keysym!=GK_Tab && event->u.chr.keysym!=GK_BackTab ) {
6260 FVReselect(fv,pos);
6261 } else {
6262 FVDeselectAll(fv);
6263 fv->b.selected[pos] = true;
6264 FVToggleCharSelected(fv,pos);
6265 fv->pressed_pos = pos;
6266 fv->sel_index = 1;
6267 }
6268 fv->end_pos = pos;
6269 FVShowInfo(fv);
6270 FVScrollToChar(fv,pos);
6271 } else if ( event->u.chr.keysym == GK_Help ) {
6272 MenuHelp(NULL,NULL,NULL); /* Menu does F1 */
6273 } else if ( event->u.chr.keysym == GK_Escape ) {
6274 FVDeselectAll(fv);
6275 } else if ( event->u.chr.chars[0]=='\r' || event->u.chr.chars[0]=='\n' ) {
6276 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
6277 return;
6278 for ( i=cnt=0; i<fv->b.map->enccount && cnt<10; ++i ) if ( fv->b.selected[i] ) {
6279 SplineChar *sc = SFMakeChar(fv->b.sf,fv->b.map,i);
6280 if ( fv->show==fv->filled ) {
6281 CharViewCreate(sc,fv,i);
6282 } else {
6283 BDFFont *bdf = fv->show;
6284 BitmapViewCreate(BDFMakeGID(bdf,sc->orig_pos),bdf,fv,i);
6285 }
6286 ++cnt;
6287 }
6288 } else if ( (event->u.chr.state&((GMenuMask()|navigation_mask)&~(ksm_shift|ksm_capslock)))==navigation_mask &&
6289 event->type == et_char &&
6290 event->u.chr.keysym!=0 &&
6291 (event->u.chr.keysym<GK_Special/* || event->u.chr.keysym>=0x10000*/)) {
6292 SplineFont *sf = fv->b.sf;
6293 int enc = EncFromUni(event->u.chr.keysym,fv->b.map->enc);
6294 if ( enc==-1 ) {
6295 for ( i=0; i<sf->glyphcnt; ++i ) {
6296 if ( sf->glyphs[i]!=NULL )
6297 if ( sf->glyphs[i]->unicodeenc==event->u.chr.keysym )
6298 break;
6299 }
6300 if ( i<sf->glyphcnt )
6301 enc = fv->b.map->backmap[i];
6302 }
6303 if ( enc<fv->b.map->enccount && enc!=-1 )
6304 FVChangeChar(fv,enc);
6305 }
6306 }
6307
utf82u_annot_strncat(unichar_t * to,const char * from,int len)6308 static void utf82u_annot_strncat(unichar_t *to, const char *from, int len) {
6309 register unichar_t ch;
6310
6311 to += u_strlen(to);
6312 while ( (ch = utf8_ildb(&from)) != '\0' && --len>=0 ) {
6313 if ( ch=='\t' ) {
6314 *(to++) = ' ';
6315 ch = ' ';
6316 }
6317 *(to++) = ch;
6318 }
6319 *to = 0;
6320 }
6321
SCPreparePopup(GWindow gw,SplineChar * sc,struct remap * remap,int localenc,int actualuni)6322 void SCPreparePopup(GWindow gw,SplineChar *sc,struct remap *remap, int localenc,
6323 int actualuni) {
6324 /* This is for the popup which appears when you hover mouse over a character on main window */
6325 int upos=-1;
6326 char *msg, *msg_old;
6327
6328 /* If a glyph is multiply mapped then the inbuild unicode enc may not be */
6329 /* the actual one used to access the glyph */
6330 if ( remap!=NULL ) {
6331 while ( remap->infont!=-1 ) {
6332 if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
6333 localenc += remap->firstenc-remap->infont;
6334 break;
6335 }
6336 ++remap;
6337 }
6338 }
6339
6340 if ( actualuni!=-1 )
6341 upos = actualuni;
6342 else if ( sc->unicodeenc!=-1 )
6343 upos = sc->unicodeenc;
6344 #if HANYANG
6345 else if ( sc->compositionunit ) {
6346 if ( sc->jamo<19 )
6347 upos = 0x1100+sc->jamo;
6348 else if ( sc->jamo<19+21 )
6349 upos = 0x1161 + sc->jamo-19;
6350 else /* Leave a hole for the blank char */
6351 upos = 0x11a8 + sc->jamo-(19+21+1);
6352 }
6353 #endif
6354
6355 if ( upos == -1 ) {
6356 msg = smprintf( "%u 0x%x U+???? \"%.25s\" ",
6357 localenc, localenc,
6358 (sc->name == NULL) ? "" : sc->name );
6359 } else {
6360 /* unicode name or range name */
6361 char *uniname = unicode_name( upos );
6362 if( uniname == NULL ) uniname = strdup( UnicodeRange( upos ) );
6363 msg = smprintf ( "%u 0x%x U+%04X \"%.25s\" %.100s",
6364 localenc, localenc, upos,
6365 (sc->name == NULL) ? "" : sc->name, uniname );
6366 if ( uniname != NULL ) free( uniname ); uniname = NULL;
6367
6368 /* annotation */
6369 char *uniannot = unicode_annot( upos );
6370 if( uniannot != NULL ) {
6371 msg_old = msg;
6372 msg = smprintf("%s\n%s", msg_old, uniannot);
6373 free(msg_old);
6374 free( uniannot );
6375 }
6376 }
6377
6378 /* user comments */
6379 if ( sc->comment!=NULL ) {
6380 msg_old = msg;
6381 msg = smprintf("%s\n%s", msg_old, sc->comment);
6382 free(msg_old);
6383 }
6384
6385 GGadgetPreparePopup8( gw, msg );
6386 free(msg);
6387 }
6388
noop(void * UNUSED (_fv))6389 static void noop(void *UNUSED(_fv)) {
6390 }
6391
ddgencharlist(void * _fv,int32 * len)6392 static void *ddgencharlist(void *_fv,int32 *len) {
6393 int i,j,cnt, gid;
6394 FontView *fv = (FontView *) _fv;
6395 SplineFont *sf = fv->b.sf;
6396 EncMap *map = fv->b.map;
6397 char *data;
6398
6399 for ( i=cnt=0; i<map->enccount; ++i ) if ( fv->b.selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL )
6400 cnt += strlen(sf->glyphs[gid]->name)+1;
6401 data = malloc(cnt+1); data[0] = '\0';
6402 for ( cnt=0, j=1 ; j<=fv->sel_index; ++j ) {
6403 for ( i=cnt=0; i<map->enccount; ++i )
6404 if ( fv->b.selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
6405 strcpy(data+cnt,sf->glyphs[gid]->name);
6406 cnt += strlen(sf->glyphs[gid]->name);
6407 strcpy(data+cnt++," ");
6408 }
6409 }
6410 if ( cnt>0 )
6411 data[--cnt] = '\0';
6412 *len = cnt;
6413 return( data );
6414 }
6415
FVMouse(FontView * fv,GEvent * event)6416 static void FVMouse(FontView *fv, GEvent *event) {
6417 int pos = (event->u.mouse.y/fv->cbh + fv->rowoff)*fv->colcnt + event->u.mouse.x/fv->cbw;
6418 int gid;
6419 int realpos = pos;
6420 SplineChar *sc, dummy;
6421 int dopopup = true;
6422
6423 if ( event->type==et_mousedown )
6424 CVPaletteDeactivate();
6425 if ( pos<0 ) {
6426 pos = 0;
6427 dopopup = false;
6428 } else if ( pos>=fv->b.map->enccount ) {
6429 pos = fv->b.map->enccount-1;
6430 if ( pos<0 ) /* No glyph slots in font */
6431 return;
6432 dopopup = false;
6433 }
6434
6435 sc = (gid=fv->b.map->map[pos])!=-1 ? fv->b.sf->glyphs[gid] : NULL;
6436 if ( sc==NULL )
6437 sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,pos);
6438 if ( event->type == et_mouseup && event->u.mouse.clicks==2 ) {
6439 if ( fv->pressed ) {
6440 GDrawCancelTimer(fv->pressed);
6441 fv->pressed = NULL;
6442 }
6443 if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
6444 return;
6445 if ( fv->cur_subtable!=NULL ) {
6446 sc = FVMakeChar(fv,pos);
6447 pos = fv->b.map->backmap[sc->orig_pos];
6448 }
6449 if ( sc==&dummy ) {
6450 sc = SFMakeChar(fv->b.sf,fv->b.map,pos);
6451 gid = fv->b.map->map[pos];
6452 }
6453 if ( fv->show==fv->filled ) {
6454 SplineFont *sf = fv->b.sf;
6455 gid = -1;
6456 if ( !OpenCharsInNewWindow )
6457 for ( gid=sf->glyphcnt-1; gid>=0; --gid )
6458 if ( sf->glyphs[gid]!=NULL && sf->glyphs[gid]->views!=NULL )
6459 break;
6460 if ( gid!=-1 ) {
6461 CharView *cv = (CharView *) (sf->glyphs[gid]->views);
6462 // printf("calling CVChangeSC() sc:%p %s\n", sc, sc->name );
6463 CVChangeSC(cv,sc);
6464 GDrawSetVisible(cv->gw,true);
6465 GDrawRaise(cv->gw);
6466 } else
6467 CharViewCreate(sc,fv,pos);
6468 } else {
6469 BDFFont *bdf = fv->show;
6470 BDFChar *bc =BDFMakeGID(bdf,gid);
6471 gid = -1;
6472 if ( !OpenCharsInNewWindow )
6473 for ( gid=bdf->glyphcnt-1; gid>=0; --gid )
6474 if ( bdf->glyphs[gid]!=NULL && bdf->glyphs[gid]->views!=NULL )
6475 break;
6476 if ( gid!=-1 ) {
6477 BitmapView *bv = bdf->glyphs[gid]->views;
6478 BVChangeBC(bv,bc,true);
6479 GDrawSetVisible(bv->gw,true);
6480 GDrawRaise(bv->gw);
6481 } else
6482 BitmapViewCreate(bc,bdf,fv,pos);
6483 }
6484 } else if ( event->type == et_mousemove ) {
6485 if ( dopopup )
6486 SCPreparePopup(fv->v,sc,fv->b.map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->b.map->enc));
6487 }
6488 if ( event->type == et_mousedown ) {
6489 if ( fv->drag_and_drop ) {
6490 GDrawSetCursor(fv->v,ct_mypointer);
6491 fv->any_dd_events_sent = fv->drag_and_drop = false;
6492 }
6493 if ( !(event->u.mouse.state&ksm_shift) && event->u.mouse.clicks<=1 ) {
6494 if ( !fv->b.selected[pos] )
6495 FVDeselectAll(fv);
6496 else if ( event->u.mouse.button!=3 ) {
6497 fv->drag_and_drop = fv->has_dd_no_cursor = true;
6498 fv->any_dd_events_sent = false;
6499 GDrawSetCursor(fv->v,ct_prohibition);
6500 GDrawGrabSelection(fv->v,sn_drag_and_drop);
6501 GDrawAddSelectionType(fv->v,sn_drag_and_drop,"STRING",fv,0,sizeof(char),
6502 ddgencharlist,noop);
6503 }
6504 }
6505 fv->pressed_pos = fv->end_pos = pos;
6506 FVShowInfo(fv);
6507 if ( !fv->drag_and_drop ) {
6508 if ( !(event->u.mouse.state&ksm_shift))
6509 fv->sel_index = 1;
6510 else if ( fv->sel_index<255 )
6511 ++fv->sel_index;
6512 if ( fv->pressed!=NULL ) {
6513 GDrawCancelTimer(fv->pressed);
6514 fv->pressed = NULL;
6515 } else if ( event->u.mouse.state&ksm_shift ) {
6516 fv->b.selected[pos] = fv->b.selected[pos] ? 0 : fv->sel_index;
6517 FVToggleCharSelected(fv,pos);
6518 } else if ( !fv->b.selected[pos] ) {
6519 fv->b.selected[pos] = fv->sel_index;
6520 FVToggleCharSelected(fv,pos);
6521 }
6522 if ( event->u.mouse.button==3 )
6523 GMenuCreatePopupMenuWithName(fv->v,event, "Popup", fvpopupmenu);
6524 else
6525 fv->pressed = GDrawRequestTimer(fv->v,200,100,NULL);
6526 }
6527 } else if ( fv->drag_and_drop ) {
6528 GWindow othergw = GDrawGetPointerWindow(fv->v);
6529
6530 if ( othergw==fv->v || othergw==fv->gw || othergw==NULL ) {
6531 if ( !fv->has_dd_no_cursor ) {
6532 fv->has_dd_no_cursor = true;
6533 GDrawSetCursor(fv->v,ct_prohibition);
6534 }
6535 } else {
6536 if ( fv->has_dd_no_cursor ) {
6537 fv->has_dd_no_cursor = false;
6538 GDrawSetCursor(fv->v,ct_ddcursor);
6539 }
6540 }
6541 if ( event->type==et_mouseup ) {
6542 if ( pos!=fv->pressed_pos ) {
6543 GDrawPostDragEvent(fv->v,event,event->type==et_mouseup?et_drop:et_drag);
6544 fv->any_dd_events_sent = true;
6545 }
6546 fv->drag_and_drop = fv->has_dd_no_cursor = false;
6547 GDrawSetCursor(fv->v,ct_mypointer);
6548 if ( !fv->any_dd_events_sent )
6549 FVDeselectAll(fv);
6550 fv->any_dd_events_sent = false;
6551 }
6552 } else if ( fv->pressed!=NULL ) {
6553 int showit = realpos!=fv->end_pos;
6554 FVReselect(fv,realpos);
6555 if ( showit )
6556 FVShowInfo(fv);
6557 if ( event->type==et_mouseup ) {
6558 GDrawCancelTimer(fv->pressed);
6559 fv->pressed = NULL;
6560 }
6561 }
6562 if ( event->type==et_mouseup && dopopup )
6563 SCPreparePopup(fv->v,sc,fv->b.map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->b.map->enc));
6564 if ( event->type==et_mouseup )
6565 SVAttachFV(fv,2);
6566 }
6567
FVResize(FontView * fv,GEvent * event)6568 static void FVResize(FontView *fv, GEvent *event) {
6569 extern int default_fv_row_count, default_fv_col_count;
6570 GRect pos,screensize;
6571 int topchar;
6572
6573 if ( fv->colcnt!=0 )
6574 topchar = fv->rowoff*fv->colcnt;
6575 else if ( fv->b.sf->top_enc!=-1 && fv->b.sf->top_enc<fv->b.map->enccount )
6576 topchar = fv->b.sf->top_enc;
6577 else {
6578 /* Position on 'A' (or whatever they ask for) if it exists */
6579 topchar = SFFindSlot(fv->b.sf,fv->b.map,home_char,NULL);
6580 if ( topchar==-1 ) {
6581 for ( topchar=0; topchar<fv->b.map->enccount; ++topchar )
6582 if ( fv->b.map->map[topchar]!=-1 && fv->b.sf->glyphs[fv->b.map->map[topchar]]!=NULL )
6583 break;
6584 if ( topchar==fv->b.map->enccount )
6585 topchar = 0;
6586 }
6587 }
6588 if ( !event->u.resize.sized )
6589 /* WM isn't responding to my resize requests, so no point in trying */;
6590 else if ( (event->u.resize.size.width-
6591 GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)%fv->cbw!=0 ||
6592 (event->u.resize.size.height-fv->mbh-fv->infoh-1)%fv->cbh!=0 ) {
6593 int cc = (event->u.resize.size.width+fv->cbw/2-
6594 GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)/fv->cbw;
6595 int rc = (event->u.resize.size.height-fv->mbh-fv->infoh-1)/fv->cbh;
6596 if ( cc<=0 ) cc = 1;
6597 if ( rc<=0 ) rc = 1;
6598 GDrawGetSize(GDrawGetRoot(NULL),&screensize);
6599 if ( cc*fv->cbw+GDrawPointsToPixels(fv->gw,_GScrollBar_Width)>screensize.width )
6600 --cc;
6601 if ( rc*fv->cbh+fv->mbh+fv->infoh+10>screensize.height )
6602 --rc;
6603 GDrawResize(fv->gw,
6604 cc*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
6605 rc*fv->cbh+1+fv->mbh+fv->infoh);
6606 /* somehow KDE loses this event of mine so to get even the vague effect */
6607 /* we can't just return */
6608 /*return;*/
6609 }
6610
6611 pos.width = GDrawPointsToPixels(fv->gw,_GScrollBar_Width);
6612 pos.height = event->u.resize.size.height-fv->mbh-fv->infoh;
6613 pos.x = event->u.resize.size.width-pos.width; pos.y = fv->mbh+fv->infoh;
6614 GGadgetResize(fv->vsb,pos.width,pos.height);
6615 GGadgetMove(fv->vsb,pos.x,pos.y);
6616 pos.width = pos.x; pos.x = 0;
6617 GDrawResize(fv->v,pos.width,pos.height);
6618
6619 fv->width = pos.width; fv->height = pos.height;
6620 fv->colcnt = (fv->width-1)/fv->cbw;
6621 if ( fv->colcnt<1 ) fv->colcnt = 1;
6622 fv->rowcnt = (fv->height-1)/fv->cbh;
6623 if ( fv->rowcnt<1 ) fv->rowcnt = 1;
6624 fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
6625
6626 GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
6627 fv->rowoff = topchar/fv->colcnt;
6628 if ( fv->rowoff>=fv->rowltot-fv->rowcnt )
6629 fv->rowoff = fv->rowltot-fv->rowcnt;
6630 if ( fv->rowoff<0 ) fv->rowoff =0;
6631 GScrollBarSetPos(fv->vsb,fv->rowoff);
6632 GDrawRequestExpose(fv->gw,NULL,true);
6633 GDrawRequestExpose(fv->v,NULL,true);
6634
6635 if ( fv->rowcnt!=fv->b.sf->desired_row_cnt || fv->colcnt!=fv->b.sf->desired_col_cnt ) {
6636 default_fv_row_count = fv->rowcnt;
6637 default_fv_col_count = fv->colcnt;
6638 fv->b.sf->desired_row_cnt = fv->rowcnt;
6639 fv->b.sf->desired_col_cnt = fv->colcnt;
6640 SavePrefs(true);
6641 }
6642 }
6643
FVTimer(FontView * fv,GEvent * event)6644 static void FVTimer(FontView *fv, GEvent *event) {
6645
6646 if ( event->u.timer.timer==fv->pressed ) {
6647 GEvent e;
6648 GDrawGetPointerPosition(fv->v,&e);
6649 if ( e.u.mouse.y<0 || e.u.mouse.y >= fv->height ) {
6650 real dy = 0;
6651 if ( e.u.mouse.y<0 )
6652 dy = -1;
6653 else if ( e.u.mouse.y>=fv->height )
6654 dy = 1;
6655 if ( fv->rowoff+dy<0 )
6656 dy = 0;
6657 else if ( fv->rowoff+dy+fv->rowcnt > fv->rowltot )
6658 dy = 0;
6659 fv->rowoff += dy;
6660 if ( dy!=0 ) {
6661 GScrollBarSetPos(fv->vsb,fv->rowoff);
6662 GDrawScroll(fv->v,NULL,0,dy*fv->cbh);
6663 }
6664 }
6665 } else if ( event->u.timer.timer==fv->resize ) {
6666 /* It's a delayed resize event (for kde which sends continuous resizes) */
6667 fv->resize = NULL;
6668 FVResize(fv,(GEvent *) (event->u.timer.userdata));
6669 } else if ( event->u.timer.userdata!=NULL ) {
6670 /* It's a delayed function call */
6671 void (*func)(FontView *) = (void (*)(FontView *)) (event->u.timer.userdata);
6672 func(fv);
6673 }
6674 }
6675
FVDelay(FontView * fv,void (* func)(FontView *))6676 void FVDelay(FontView *fv,void (*func)(FontView *)) {
6677 GDrawRequestTimer(fv->v,100,0,(void *) func);
6678 }
6679
FVScroll(GGadget * g,GEvent * e)6680 static int FVScroll(GGadget *g, GEvent *e) {
6681 FontView *fv = GGadgetGetUserData(g);
6682 int newpos = fv->rowoff;
6683 struct sbevent *sb = &e->u.control.u.sb;
6684
6685 switch( sb->type ) {
6686 case et_sb_top:
6687 newpos = 0;
6688 break;
6689 case et_sb_uppage:
6690 newpos -= fv->rowcnt;
6691 break;
6692 case et_sb_up:
6693 --newpos;
6694 break;
6695 case et_sb_down:
6696 ++newpos;
6697 break;
6698 case et_sb_downpage:
6699 newpos += fv->rowcnt;
6700 break;
6701 case et_sb_bottom:
6702 newpos = fv->rowltot-fv->rowcnt;
6703 break;
6704 case et_sb_thumb:
6705 case et_sb_thumbrelease:
6706 newpos = sb->pos;
6707 break;
6708 }
6709 if ( newpos>fv->rowltot-fv->rowcnt )
6710 newpos = fv->rowltot-fv->rowcnt;
6711 if ( newpos<0 ) newpos =0;
6712 if ( newpos!=fv->rowoff ) {
6713 int diff = newpos-fv->rowoff;
6714 fv->rowoff = newpos;
6715 GScrollBarSetPos(fv->vsb,fv->rowoff);
6716 GDrawScroll(fv->v,NULL,0,diff*fv->cbh);
6717 }
6718 return( true );
6719 }
6720
v_e_h(GWindow gw,GEvent * event)6721 static int v_e_h(GWindow gw, GEvent *event) {
6722 FontView *fv = (FontView *) GDrawGetUserData(gw);
6723
6724 if (( event->type==et_mouseup || event->type==et_mousedown ) &&
6725 (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
6726 return( GGadgetDispatchEvent(fv->vsb,event));
6727 }
6728
6729 GGadgetPopupExternalEvent(event);
6730 switch ( event->type ) {
6731 case et_expose:
6732 GDrawSetLineWidth(gw,0);
6733 FVExpose(fv,gw,event);
6734 break;
6735 case et_char:
6736 if ( fv->b.container!=NULL )
6737 (fv->b.container->funcs->charEvent)(fv->b.container,event);
6738 else
6739 FVChar(fv,event);
6740 break;
6741 case et_mousemove: case et_mousedown: case et_mouseup:
6742 if ( event->type==et_mousedown )
6743 GDrawSetGIC(gw,fv->gic,0,20);
6744 if ( fv->notactive && event->type==et_mousedown )
6745 (fv->b.container->funcs->activateMe)(fv->b.container,&fv->b);
6746 FVMouse(fv,event);
6747 break;
6748 case et_timer:
6749 FVTimer(fv,event);
6750 break;
6751 case et_focus:
6752 // printf("fv.et_focus\n");
6753 if ( event->u.focus.gained_focus )
6754 GDrawSetGIC(gw,fv->gic,0,20);
6755 break;
6756 }
6757 return( true );
6758 }
6759
FontView_ReformatOne(FontView * fv)6760 static void FontView_ReformatOne(FontView *fv) {
6761 FontView *fvs;
6762
6763 if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
6764 return;
6765
6766 GDrawSetCursor(fv->v,ct_watch);
6767 fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
6768 GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
6769 if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
6770 fv->rowoff = fv->rowltot-fv->rowcnt;
6771 if ( fv->rowoff<0 ) fv->rowoff =0;
6772 GScrollBarSetPos(fv->vsb,fv->rowoff);
6773 }
6774 for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) )
6775 if ( fvs!=fv && fvs->b.sf==fv->b.sf )
6776 break;
6777 GDrawRequestExpose(fv->v,NULL,false);
6778 GDrawSetCursor(fv->v,ct_pointer);
6779 }
6780
FontView_ReformatAll(SplineFont * sf)6781 static void FontView_ReformatAll(SplineFont *sf) {
6782 BDFFont *new, *old, *bdf;
6783 FontView *fv;
6784 MetricsView *mvs;
6785 extern int use_freetype_to_rasterize_fv;
6786
6787 if ( sf->fv==NULL || ((FontView *) (sf->fv))->v==NULL ) /* Can happen in scripts */
6788 return;
6789
6790 for ( fv=(FontView *) (sf->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
6791 GDrawSetCursor(fv->v,ct_watch);
6792 old = fv->filled;
6793 /* In CID fonts fv->b.sf may not be same as sf */
6794 new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
6795 (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
6796 (use_freetype_to_rasterize_fv && !sf->strokedfont && !sf->multilayer?pf_ft_nohints:0),
6797 NULL);
6798 fv->filled = new;
6799 if ( fv->show==old )
6800 fv->show = new;
6801 else {
6802 for ( bdf=sf->bitmaps; bdf != NULL &&
6803 ( bdf->pixelsize != fv->show->pixelsize || BDFDepth( bdf ) != BDFDepth( fv->show )); bdf=bdf->next );
6804 if ( bdf != NULL ) fv->show = bdf;
6805 else fv->show = new;
6806 }
6807 BDFFontFree(old);
6808 if ( ((FontView *) (sf->fv))->colcnt!=0 ) {
6809 fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
6810 GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
6811 if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
6812 fv->rowoff = fv->rowltot-fv->rowcnt;
6813 if ( fv->rowoff<0 ) fv->rowoff =0;
6814 GScrollBarSetPos(fv->vsb,fv->rowoff);
6815 }
6816 GDrawRequestExpose(fv->v,NULL,false);
6817 }
6818 GDrawSetCursor(fv->v,ct_pointer);
6819 }
6820 for ( mvs=sf->metrics; mvs!=NULL; mvs=mvs->next ) if ( mvs->bdf==NULL ) {
6821 BDFFontFree(mvs->show);
6822 mvs->show = SplineFontPieceMeal(sf,mvs->layer,mvs->ptsize,mvs->dpi,
6823 mvs->antialias?(pf_antialias|pf_ft_recontext):pf_ft_recontext,NULL);
6824 GDrawRequestExpose(mvs->gw,NULL,false);
6825 }
6826 }
6827
FontViewRemove(FontView * fv)6828 void FontViewRemove(FontView *fv) {
6829 if ( fv_list==fv )
6830 fv_list = (FontView *) (fv->b.next);
6831 else {
6832 FontView *n;
6833 for ( n=fv_list; n->b.next!=&fv->b; n=(FontView *) (n->b.next) );
6834 n->b.next = fv->b.next;
6835 }
6836 FontViewFree(&fv->b);
6837 }
6838
6839 /**
6840 * In some cases fontview gets an et_selclear event when using copy
6841 * and paste on the OSX. So this guard lets us quietly ignore that
6842 * event when we have just done command+c or command+x.
6843 */
6844 extern int osx_fontview_copy_cut_counter;
6845
6846 static FontView* ActiveFontView = 0;
6847
fv_e_h(GWindow gw,GEvent * event)6848 static int fv_e_h(GWindow gw, GEvent *event) {
6849 FontView *fv = (FontView *) GDrawGetUserData(gw);
6850
6851 if (( event->type==et_mouseup || event->type==et_mousedown ) &&
6852 (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
6853 return( GGadgetDispatchEvent(fv->vsb,event));
6854 }
6855
6856 switch ( event->type ) {
6857 case et_focus:
6858 if ( event->u.focus.gained_focus )
6859 {
6860 ActiveFontView = fv;
6861 }
6862 else
6863 {
6864 }
6865 break;
6866 case et_selclear:
6867 #ifdef __Mac
6868 // For some reason command + c and command + x wants
6869 // to send a clear to us, even if that key was pressed
6870 // on a charview.
6871 if( osx_fontview_copy_cut_counter )
6872 {
6873 osx_fontview_copy_cut_counter--;
6874 break;
6875 }
6876 // printf("fontview et_selclear\n");
6877 #endif
6878 ClipboardClear();
6879 break;
6880 case et_expose:
6881 GDrawSetLineWidth(gw,0);
6882 FVDrawInfo(fv,gw,event);
6883 break;
6884 case et_resize:
6885 /* KDE sends a continuous stream of resize events, and gets very */
6886 /* confused if I start resizing the window myself, try to wait for */
6887 /* the user to finish before responding to resizes */
6888 if ( event->u.resize.sized || fv->resize_expected ) {
6889 if ( fv->resize )
6890 GDrawCancelTimer(fv->resize);
6891 fv->resize_event = *event;
6892 fv->resize = GDrawRequestTimer(fv->v,300,0,(void *) &fv->resize_event);
6893 fv->resize_expected = false;
6894 }
6895 break;
6896 case et_char:
6897 if ( fv->b.container!=NULL )
6898 (fv->b.container->funcs->charEvent)(fv->b.container,event);
6899 else
6900 FVChar(fv,event);
6901 break;
6902 case et_mousedown:
6903 GDrawSetGIC(gw,fv->gwgic,0,20);
6904 if ( fv->notactive )
6905 (fv->b.container->funcs->activateMe)(fv->b.container,&fv->b);
6906 break;
6907 case et_close:
6908 FVMenuClose(gw,NULL,NULL);
6909 break;
6910 case et_create:
6911 fv->b.next = (FontViewBase *) fv_list;
6912 fv_list = fv;
6913 break;
6914 case et_destroy:
6915 if ( fv->qg!=NULL )
6916 QGRmFontView(fv->qg,fv);
6917 FontViewRemove(fv);
6918 break;
6919 }
6920 return( true );
6921 }
6922
FontViewOpenKids(FontView * fv)6923 static void FontViewOpenKids(FontView *fv) {
6924 int k, i;
6925 SplineFont *sf = fv->b.sf, *_sf;
6926 #if defined(__Mac)
6927 int cnt= 0;
6928 #endif
6929
6930 if ( sf->cidmaster!=NULL )
6931 sf = sf->cidmaster;
6932
6933 k=0;
6934 do {
6935 _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
6936 for ( i=0; i<_sf->glyphcnt; ++i )
6937 if ( _sf->glyphs[i]!=NULL && _sf->glyphs[i]->wasopen ) {
6938 _sf->glyphs[i]->wasopen = false;
6939 #if defined(__Mac)
6940 /* If we open a bunch of charviews all at once on the mac, X11*/
6941 /* crashes */ /* But opening one seems ok */
6942 if ( ++cnt==1 )
6943 #endif
6944 CharViewCreate(_sf->glyphs[i],fv,-1);
6945 }
6946 ++k;
6947 } while ( k<sf->subfontcnt );
6948 }
6949
__FontViewCreate(SplineFont * sf)6950 static FontView *__FontViewCreate(SplineFont *sf) {
6951 FontView *fv = calloc(1,sizeof(FontView));
6952 int i;
6953 int ps = sf->display_size<0 ? -sf->display_size :
6954 sf->display_size==0 ? default_fv_font_size : sf->display_size;
6955
6956 if ( ps>200 ) ps = 128;
6957
6958 /* Filename != NULL if we opened an sfd file. Sfd files know whether */
6959 /* the font is compact or not and should not depend on a global flag */
6960 /* If a font is new, then compaction will make it vanish completely */
6961 if ( sf->fv==NULL && compact_font_on_open && sf->filename==NULL && !sf->new ) {
6962 sf->compacted = true;
6963 for ( i=0; i<sf->subfontcnt; ++i )
6964 sf->subfonts[i]->compacted = true;
6965 }
6966 fv->b.nextsame = sf->fv;
6967 fv->b.active_layer = sf->display_layer;
6968 sf->fv = (FontViewBase *) fv;
6969 if ( sf->mm!=NULL ) {
6970 sf->mm->normal->fv = (FontViewBase *) fv;
6971 for ( i = 0; i<sf->mm->instance_count; ++i )
6972 sf->mm->instances[i]->fv = (FontViewBase *) fv;
6973 }
6974 if ( sf->subfontcnt==0 ) {
6975 fv->b.sf = sf;
6976 if ( fv->b.nextsame!=NULL ) {
6977 fv->b.map = EncMapCopy(fv->b.nextsame->map);
6978 fv->b.normal = fv->b.nextsame->normal==NULL ? NULL : EncMapCopy(fv->b.nextsame->normal);
6979 } else if ( sf->compacted ) {
6980 fv->b.normal = sf->map;
6981 fv->b.map = CompactEncMap(EncMapCopy(sf->map),sf);
6982 sf->map = fv->b.map;
6983 } else {
6984 fv->b.map = sf->map;
6985 fv->b.normal = NULL;
6986 }
6987 } else {
6988 fv->b.cidmaster = sf;
6989 for ( i=0; i<sf->subfontcnt; ++i )
6990 sf->subfonts[i]->fv = (FontViewBase *) fv;
6991 for ( i=0; i<sf->subfontcnt; ++i ) /* Search for a subfont that contains more than ".notdef" (most significant in .gai fonts) */
6992 if ( sf->subfonts[i]->glyphcnt>1 ) {
6993 fv->b.sf = sf->subfonts[i];
6994 break;
6995 }
6996 if ( fv->b.sf==NULL )
6997 fv->b.sf = sf->subfonts[0];
6998 sf = fv->b.sf;
6999 if ( fv->b.nextsame==NULL ) { EncMapFree(sf->map); sf->map = NULL; }
7000 fv->b.map = EncMap1to1(sf->glyphcnt);
7001 if ( fv->b.nextsame==NULL ) { sf->map = fv->b.map; }
7002 if ( sf->compacted ) {
7003 fv->b.normal = fv->b.map;
7004 fv->b.map = CompactEncMap(EncMapCopy(fv->b.map),sf);
7005 if ( fv->b.nextsame==NULL ) { sf->map = fv->b.map; }
7006 }
7007 }
7008 fv->b.selected = calloc((fv->b.map ? fv->b.map->enccount : 0), sizeof(uint8));
7009 fv->user_requested_magnify = -1;
7010 fv->magnify = (ps<=9)? 3 : (ps<20) ? 2 : 1;
7011 fv->cbw = (ps*fv->magnify)+1;
7012 fv->cbh = (ps*fv->magnify)+1+fv->lab_height+1;
7013 fv->antialias = sf->display_antialias;
7014 fv->bbsized = sf->display_bbsized;
7015 fv->glyphlabel = default_fv_glyphlabel;
7016
7017 fv->end_pos = -1;
7018 #ifndef _NO_PYTHON
7019 PyFF_InitFontHook((FontViewBase *)fv);
7020 #endif
7021
7022 fv->pid_webfontserver = 0;
7023
7024 return( fv );
7025 }
7026
7027 static int fontview_ready = false;
7028
FontViewFinish()7029 static void FontViewFinish() {
7030 if (!fontview_ready) return;
7031 mb2FreeGetText(mblist);
7032 mbFreeGetText(fvpopupmenu);
7033 }
7034
FontViewFinishNonStatic()7035 void FontViewFinishNonStatic() {
7036 FontViewFinish();
7037 }
7038
FontViewInit(void)7039 static void FontViewInit(void) {
7040 // static int done = false; // superseded by fontview_ready.
7041
7042 if ( fontview_ready )
7043 return;
7044
7045 fontview_ready = true;
7046
7047 mb2DoGetText(mblist);
7048 mbDoGetText(fvpopupmenu);
7049 atexit(&FontViewFinishNonStatic);
7050 }
7051
7052 static struct resed fontview_re[] = {
7053 {N_("Glyph Info Color"), "GlyphInfoColor", rt_color, &fvglyphinfocol, N_("Color of the font used to display glyph information in the fontview"), NULL, { 0 }, 0, 0 },
7054 {N_("Empty Slot FG Color"), "EmptySlotFgColor", rt_color, &fvemtpyslotfgcol, N_("Color used to draw the foreground of empty slots"), NULL, { 0 }, 0, 0 },
7055 {N_("Selected BG Color"), "SelectedColor", rt_color, &fvselcol, N_("Color used to draw the background of selected glyphs"), NULL, { 0 }, 0, 0 },
7056 {N_("Selected FG Color"), "SelectedFgColor", rt_color, &fvselfgcol, N_("Color used to draw the foreground of selected glyphs"), NULL, { 0 }, 0, 0 },
7057 {N_("Changed Color"), "ChangedColor", rt_color, &fvchangedcol, N_("Color used to mark a changed glyph"), NULL, { 0 }, 0, 0 },
7058 {N_("Hinting Needed Color"), "HintingNeededColor", rt_color, &fvhintingneededcol, N_("Color used to mark glyphs that need hinting"), NULL, { 0 }, 0, 0 },
7059 {N_("Font Size"), "FontSize", rt_int, &fv_fontsize, N_("Size (in points) of the font used to display information and glyph labels in the fontview"), NULL, { 0 }, 0, 0 },
7060 {N_("Font Family"), "FontFamily", rt_stringlong, &fv_fontnames, N_("A comma separated list of font family names used to display small example images of glyphs over the user designed glyphs"), NULL, { 0 }, 0, 0 },
7061 RESED_EMPTY
7062 };
7063
FVCreateInnards(FontView * fv,GRect * pos)7064 static void FVCreateInnards(FontView *fv,GRect *pos) {
7065 GWindow gw = fv->gw;
7066 GWindowAttrs wattrs;
7067 GGadgetData gd;
7068 FontRequest rq;
7069 BDFFont *bdf;
7070 int as,ds,ld;
7071 extern int use_freetype_to_rasterize_fv;
7072 SplineFont *sf = fv->b.sf;
7073
7074 fv->lab_height = FV_LAB_HEIGHT-13+GDrawPointsToPixels(NULL,fv_fontsize);
7075
7076 memset(&gd,0,sizeof(gd));
7077 gd.pos.y = pos->y; gd.pos.height = pos->height;
7078 gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
7079 gd.pos.x = pos->width;
7080 gd.u.sbinit = NULL;
7081 gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
7082 gd.handle_controlevent = FVScroll;
7083 fv->vsb = GScrollBarCreate(gw,&gd,fv);
7084
7085
7086 memset(&wattrs,0,sizeof(wattrs));
7087 wattrs.mask = wam_events|wam_cursor|wam_backcol;
7088 wattrs.event_masks = ~(1<<et_charup);
7089 wattrs.cursor = ct_pointer;
7090 wattrs.background_color = view_bgcol;
7091 fv->v = GWidgetCreateSubWindow(gw,pos,v_e_h,fv,&wattrs);
7092 GDrawSetVisible(fv->v,true);
7093 GDrawSetWindowTypeName(fv->v, "FontView");
7094
7095 fv->gic = GDrawCreateInputContext(fv->v,gic_root|gic_orlesser);
7096 fv->gwgic = GDrawCreateInputContext(fv->gw,gic_root|gic_orlesser);
7097 GDrawSetGIC(fv->v,fv->gic,0,20);
7098 GDrawSetGIC(fv->gw,fv->gic,0,20);
7099
7100 fv->fontset = calloc(_uni_fontmax,sizeof(GFont *));
7101 memset(&rq,0,sizeof(rq));
7102 rq.utf8_family_name = fv_fontnames;
7103 rq.point_size = fv_fontsize;
7104 rq.weight = 400;
7105 fv->fontset[0] = GDrawInstanciateFont(gw,&rq);
7106 GDrawSetFont(fv->v,fv->fontset[0]);
7107 GDrawWindowFontMetrics(fv->v,fv->fontset[0],&as,&ds,&ld);
7108 fv->lab_as = as;
7109 fv->showhmetrics = default_fv_showhmetrics;
7110 fv->showvmetrics = default_fv_showvmetrics && sf->hasvmetrics;
7111 bdf = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,sf->display_size<0?-sf->display_size:default_fv_font_size,72,
7112 (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
7113 (use_freetype_to_rasterize_fv && !sf->strokedfont && !sf->multilayer?pf_ft_nohints:0),
7114 NULL);
7115 fv->filled = bdf;
7116 if ( sf->display_size>0 ) {
7117 for ( bdf=sf->bitmaps; bdf!=NULL && bdf->pixelsize!=sf->display_size ;
7118 bdf=bdf->next );
7119 if ( bdf==NULL )
7120 bdf = fv->filled;
7121 }
7122 if ( sf->onlybitmaps && bdf==fv->filled && sf->bitmaps!=NULL )
7123 bdf = sf->bitmaps;
7124 fv->cbw = -1;
7125 FVChangeDisplayFont(fv,bdf);
7126 }
7127
FontView_Create(SplineFont * sf,int hide)7128 static FontView *FontView_Create(SplineFont *sf, int hide) {
7129 FontView *fv = (FontView *) __FontViewCreate(sf);
7130 GRect pos;
7131 GWindow gw;
7132 GWindowAttrs wattrs;
7133 GGadgetData gd;
7134 GRect gsize;
7135 static GWindow icon = NULL;
7136 static int nexty=0;
7137 GRect size;
7138
7139 FontViewInit();
7140 if ( icon==NULL ) {
7141 #ifdef BIGICONS
7142 icon = GDrawCreateBitmap(NULL,fontview_width,fontview_height,fontview_bits);
7143 #else
7144 icon = GDrawCreateBitmap(NULL,fontview2_width,fontview2_height,fontview2_bits);
7145 #endif
7146 }
7147
7148 GDrawGetSize(GDrawGetRoot(NULL),&size);
7149
7150 memset(&wattrs,0,sizeof(wattrs));
7151 wattrs.mask = wam_events|wam_cursor|wam_icon;
7152 wattrs.event_masks = ~(1<<et_charup);
7153 wattrs.cursor = ct_pointer;
7154 wattrs.icon = icon;
7155 pos.width = sf->desired_col_cnt*fv->cbw+1;
7156 pos.height = sf->desired_row_cnt*fv->cbh+1;
7157 pos.x = size.width-pos.width-30; pos.y = nexty;
7158 nexty += 2*fv->cbh+50;
7159 if ( nexty+pos.height > size.height )
7160 nexty = 0;
7161 fv->gw = gw = GDrawCreateTopWindow(NULL,&pos,fv_e_h,fv,&wattrs);
7162 FontViewSetTitle(fv);
7163 GDrawSetWindowTypeName(fv->gw, "FontView");
7164
7165 if ( !fv_fs_init ) {
7166 GResEditFind( fontview_re, "FontView.");
7167 view_bgcol = GResourceFindColor("View.Background",GDrawGetDefaultBackground(NULL));
7168 fv_fs_init = true;
7169 }
7170
7171 memset(&gd,0,sizeof(gd));
7172 gd.flags = gg_visible | gg_enabled;
7173 helplist[0].invoke = FVMenuContextualHelp;
7174 #ifndef _NO_PYTHON
7175 if ( fvpy_menu!=NULL )
7176 mblist[3].ti.disabled = false;
7177 mblist[3].sub = fvpy_menu;
7178 #define CALLBACKS_INDEX 4 /* FIXME: There has to be a better way than this. */
7179 #else
7180 #define CALLBACKS_INDEX 3 /* FIXME: There has to be a better way than this. */
7181 #endif /* _NO_PYTHON */
7182 #ifdef NATIVE_CALLBACKS
7183 if ( fv_menu!=NULL )
7184 mblist[CALLBACKS_INDEX].ti.disabled = false;
7185 mblist[CALLBACKS_INDEX].sub = fv_menu;
7186 #endif /* NATIVE_CALLBACKS */
7187 gd.u.menu2 = mblist;
7188 fv->mb = GMenu2BarCreate( gw, &gd, NULL);
7189 GGadgetGetSize(fv->mb,&gsize);
7190 fv->mbh = gsize.height;
7191 fv->infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
7192
7193 pos.x = 0; pos.y = fv->mbh+fv->infoh;
7194 FVCreateInnards(fv,&pos);
7195
7196 if ( !hide ) {
7197 GDrawSetVisible(gw,true);
7198 FontViewOpenKids(fv);
7199 }
7200 return( fv );
7201 }
7202
FontView_Append(FontView * fv)7203 static FontView *FontView_Append(FontView *fv) {
7204 /* Normally fontviews get added to the fv list when their windows are */
7205 /* created. but we don't create any windows here, so... */
7206 FontView *test;
7207
7208 if ( fv_list==NULL ) fv_list = fv;
7209 else {
7210 for ( test = fv_list; test->b.next!=NULL; test=(FontView *) test->b.next );
7211 test->b.next = (FontViewBase *) fv;
7212 }
7213 return( fv );
7214 }
7215
FontNew(void)7216 FontView *FontNew(void) {
7217 return( FontView_Create(SplineFontNew(),false));
7218 }
7219
FontView_Free(FontView * fv)7220 static void FontView_Free(FontView *fv) {
7221 int i;
7222 FontView *prev;
7223 FontView *fvs;
7224
7225 if ( fv->b.sf == NULL ) /* Happens when usurping a font to put it into an MM */
7226 BDFFontFree(fv->filled);
7227 else if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b ) {
7228 EncMapFree(fv->b.map);
7229 if (fv->b.sf != NULL && fv->b.map == fv->b.sf->map) { fv->b.sf->map = NULL; }
7230 SplineFontFree(fv->b.cidmaster?fv->b.cidmaster:fv->b.sf);
7231 BDFFontFree(fv->filled);
7232 } else {
7233 EncMapFree(fv->b.map);
7234 if (fv->b.sf != NULL && fv->b.map == fv->b.sf->map) { fv->b.sf->map = NULL; }
7235 fv->b.map = NULL;
7236 for ( fvs=(FontView *) (fv->b.sf->fv), i=0 ; fvs!=NULL; fvs = (FontView *) (fvs->b.nextsame) )
7237 if ( fvs->filled==fv->filled ) ++i;
7238 if ( i==1 )
7239 BDFFontFree(fv->filled);
7240 if ( fv->b.sf->fv==&fv->b ) {
7241 if ( fv->b.cidmaster==NULL )
7242 fv->b.sf->fv = fv->b.nextsame;
7243 else {
7244 fv->b.cidmaster->fv = fv->b.nextsame;
7245 for ( i=0; i<fv->b.cidmaster->subfontcnt; ++i )
7246 fv->b.cidmaster->subfonts[i]->fv = fv->b.nextsame;
7247 }
7248 } else {
7249 for ( prev = (FontView *) (fv->b.sf->fv); prev->b.nextsame!=&fv->b; prev=(FontView *) (prev->b.nextsame) );
7250 prev->b.nextsame = fv->b.nextsame;
7251 }
7252 }
7253 #ifndef _NO_FFSCRIPT
7254 DictionaryFree(fv->b.fontvars);
7255 free(fv->b.fontvars);
7256 #endif
7257 free(fv->b.selected);
7258 free(fv->fontset);
7259 #ifndef _NO_PYTHON
7260 PyFF_FreeFV(&fv->b);
7261 #endif
7262 free(fv);
7263 }
7264
FontViewWinInfo(FontView * fv,int * cc,int * rc)7265 static int FontViewWinInfo(FontView *fv, int *cc, int *rc) {
7266 if ( fv==NULL || fv->colcnt==0 || fv->rowcnt==0 ) {
7267 *cc = 16; *rc = 4;
7268 return( -1 );
7269 }
7270
7271 *cc = fv->colcnt;
7272 *rc = fv->rowcnt;
7273
7274 return( fv->rowoff*fv->colcnt );
7275 }
7276
7277
7278
7279
7280
7281
7282
7283
7284
FVAny(void)7285 static FontViewBase *FVAny(void) { return (FontViewBase *) fv_list; }
7286
FontIsActive(SplineFont * sf)7287 static int FontIsActive(SplineFont *sf) {
7288 FontView *fv;
7289
7290 for ( fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) )
7291 if ( fv->b.sf == sf )
7292 return( true );
7293
7294 return( false );
7295 }
7296
FontOfFilename(const char * filename)7297 static SplineFont *FontOfFilename(const char *filename) {
7298 char buffer[1025];
7299 FontView *fv;
7300
7301 GFileGetAbsoluteName((char *) filename,buffer,sizeof(buffer));
7302 for ( fv=fv_list; fv!=NULL ; fv=(FontView *) (fv->b.next) ) {
7303 if ( fv->b.sf->filename!=NULL && strcmp(fv->b.sf->filename,buffer)==0 )
7304 return( fv->b.sf );
7305 else if ( fv->b.sf->origname!=NULL && strcmp(fv->b.sf->origname,buffer)==0 )
7306 return( fv->b.sf );
7307 }
7308 return( NULL );
7309 }
7310
FVExtraEncSlots(FontView * fv,int encmax)7311 static void FVExtraEncSlots(FontView *fv, int encmax) {
7312 if ( fv->colcnt!=0 ) { /* Ie. scripting vs. UI */
7313 fv->rowltot = (encmax+1+fv->colcnt-1)/fv->colcnt;
7314 GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7315 }
7316 }
7317
FV_BiggerGlyphCache(FontView * fv,int gidcnt)7318 static void FV_BiggerGlyphCache(FontView *fv, int gidcnt) {
7319 if ( fv->filled!=NULL )
7320 BDFOrigFixup(fv->filled,gidcnt,fv->b.sf);
7321 }
7322
FontView_Close(FontView * fv)7323 static void FontView_Close(FontView *fv) {
7324 if ( fv->gw!=NULL )
7325 GDrawDestroyWindow(fv->gw);
7326 else
7327 FontViewRemove(fv);
7328 }
7329
7330
7331 struct fv_interface gdraw_fv_interface = {
7332 (FontViewBase *(*)(SplineFont *, int)) FontView_Create,
7333 (FontViewBase *(*)(SplineFont *)) __FontViewCreate,
7334 (void (*)(FontViewBase *)) FontView_Close,
7335 (void (*)(FontViewBase *)) FontView_Free,
7336 (void (*)(FontViewBase *)) FontViewSetTitle,
7337 FontViewSetTitles,
7338 FontViewRefreshAll,
7339 (void (*)(FontViewBase *)) FontView_ReformatOne,
7340 FontView_ReformatAll,
7341 (void (*)(FontViewBase *)) FV_LayerChanged,
7342 FV_ToggleCharChanged,
7343 (int (*)(FontViewBase *, int *, int *)) FontViewWinInfo,
7344 FontIsActive,
7345 FVAny,
7346 (FontViewBase *(*)(FontViewBase *)) FontView_Append,
7347 FontOfFilename,
7348 (void (*)(FontViewBase *,int)) FVExtraEncSlots,
7349 (void (*)(FontViewBase *,int)) FV_BiggerGlyphCache,
7350 (void (*)(FontViewBase *,BDFFont *)) FV_ChangeDisplayBitmap,
7351 (void (*)(FontViewBase *)) FV_ShowFilled,
7352 FV_ReattachCVs,
7353 (void (*)(FontViewBase *)) FVDeselectAll,
7354 (void (*)(FontViewBase *,int )) FVScrollToGID,
7355 (void (*)(FontViewBase *,int )) FVScrollToChar,
7356 (void (*)(FontViewBase *,int )) FV_ChangeGID,
7357 SF_CloseAllInstrs
7358 };
7359
7360 extern GResInfo charview_ri;
7361 static struct resed view_re[] = {
7362 {N_("Color|Background"), "Background", rt_color, &view_bgcol, N_("Background color for the drawing area of all views"), NULL, { 0 }, 0, 0 },
7363 RESED_EMPTY
7364 };
7365 GResInfo view_ri = {
7366 NULL, NULL,NULL, NULL,
7367 NULL,
7368 NULL,
7369 NULL,
7370 view_re,
7371 N_("View"),
7372 N_("This is an abstract class which defines common features of the\nFontView, CharView, BitmapView and MetricsView"),
7373 "View",
7374 "fontforge",
7375 false,
7376 0,
7377 NULL,
7378 GBOX_EMPTY,
7379 NULL,
7380 NULL,
7381 NULL
7382 };
7383
7384 GResInfo fontview_ri = {
7385 &charview_ri, NULL,NULL, NULL,
7386 NULL,
7387 NULL,
7388 NULL,
7389 fontview_re,
7390 N_("FontView"),
7391 N_("This is the main fontforge window displaying a font"),
7392 "FontView",
7393 "fontforge",
7394 false,
7395 0,
7396 NULL,
7397 GBOX_EMPTY,
7398 NULL,
7399 NULL,
7400 NULL
7401 };
7402
7403 /* ************************************************************************** */
7404 /* ***************************** Embedded FontViews ************************* */
7405 /* ************************************************************************** */
7406
FVCopyInnards(FontView * fv,GRect * pos,int infoh,FontView * fvorig,GWindow dw,int def_layer,struct fvcontainer * kf)7407 static void FVCopyInnards(FontView *fv,GRect *pos,int infoh,
7408 FontView *fvorig,GWindow dw, int def_layer, struct fvcontainer *kf) {
7409
7410 fv->notactive = true;
7411 fv->gw = dw;
7412 fv->infoh = infoh;
7413 fv->b.container = kf;
7414 fv->rowcnt = 4; fv->colcnt = 16;
7415 fv->b.active_layer = def_layer;
7416 FVCreateInnards(fv,pos);
7417 memcpy(fv->b.selected,fvorig->b.selected,fv->b.map->enccount);
7418 fv->rowoff = (fvorig->rowoff*fvorig->colcnt)/fv->colcnt;
7419 }
7420
KFFontViewInits(struct kf_dlg * kf,GGadget * drawable)7421 void KFFontViewInits(struct kf_dlg *kf,GGadget *drawable) {
7422 GGadgetData gd;
7423 GRect pos, gsize, sbsize;
7424 GWindow dw = GDrawableGetWindow(drawable);
7425 int infoh;
7426 int ps;
7427 FontView *fvorig = (FontView *) kf->sf->fv;
7428
7429 FontViewInit();
7430
7431 kf->dw = dw;
7432
7433 memset(&gd,0,sizeof(gd));
7434 gd.flags = gg_visible | gg_enabled;
7435 helplist[0].invoke = FVMenuContextualHelp;
7436 gd.u.menu2 = mblist;
7437 kf->mb = GMenu2BarCreate( dw, &gd, NULL);
7438 GGadgetGetSize(kf->mb,&gsize);
7439 kf->mbh = gsize.height;
7440 kf->guts = drawable;
7441
7442 ps = kf->sf->display_size; kf->sf->display_size = -24;
7443 kf->first_fv = __FontViewCreate(kf->sf); kf->first_fv->b.container = (struct fvcontainer *) kf;
7444 kf->second_fv = __FontViewCreate(kf->sf); kf->second_fv->b.container = (struct fvcontainer *) kf;
7445
7446 kf->infoh = infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
7447 kf->first_fv->mbh = kf->mbh;
7448 pos.x = 0; pos.y = kf->mbh+infoh+kf->fh+4;
7449 pos.width = 16*kf->first_fv->cbw+1;
7450 pos.height = 4*kf->first_fv->cbh+1;
7451
7452 GDrawSetUserData(dw,kf->first_fv);
7453 FVCopyInnards(kf->first_fv,&pos,infoh,fvorig,dw,kf->def_layer,(struct fvcontainer *) kf);
7454 pos.height = 4*kf->first_fv->cbh+1; /* We don't know the real fv->cbh until after creating the innards. The size of the last window is probably wrong, we'll fix later */
7455 kf->second_fv->mbh = kf->mbh;
7456 kf->label2_y = pos.y + pos.height+2;
7457 pos.y = kf->label2_y + kf->fh + 2;
7458 GDrawSetUserData(dw,kf->second_fv);
7459 FVCopyInnards(kf->second_fv,&pos,infoh,fvorig,dw,kf->def_layer,(struct fvcontainer *) kf);
7460
7461 kf->sf->display_size = ps;
7462
7463 GGadgetGetSize(kf->second_fv->vsb,&sbsize);
7464 gsize.x = gsize.y = 0;
7465 gsize.width = pos.width + sbsize.width;
7466 gsize.height = pos.y+pos.height;
7467 GGadgetSetDesiredSize(drawable,NULL,&gsize);
7468 }
7469 /* ************************************************************************** */
7470 /* ************************** Glyph Set from Selection ********************** */
7471 /* ************************************************************************** */
7472
7473 struct gsd {
7474 struct fvcontainer base;
7475 FontView *fv;
7476 int done;
7477 int good;
7478 GWindow gw;
7479 };
7480
gs_activateMe(struct fvcontainer * UNUSED (fvc),FontViewBase * UNUSED (fvb))7481 static void gs_activateMe(struct fvcontainer *UNUSED(fvc), FontViewBase *UNUSED(fvb)) {
7482 /*struct gsd *gs = (struct gsd *) fvc;*/
7483 }
7484
gs_charEvent(struct fvcontainer * fvc,void * event)7485 static void gs_charEvent(struct fvcontainer *fvc,void *event) {
7486 struct gsd *gs = (struct gsd *) fvc;
7487 FVChar(gs->fv,event);
7488 }
7489
gs_doClose(struct fvcontainer * fvc)7490 static void gs_doClose(struct fvcontainer *fvc) {
7491 struct gsd *gs = (struct gsd *) fvc;
7492 gs->done = true;
7493 }
7494
7495 #define CID_Guts 1000
7496 #define CID_TopBox 1001
7497
gs_doResize(struct fvcontainer * fvc,FontViewBase * UNUSED (fvb),int width,int height)7498 static void gs_doResize(struct fvcontainer *fvc, FontViewBase *UNUSED(fvb),
7499 int width, int height) {
7500 struct gsd *gs = (struct gsd *) fvc;
7501 /*FontView *fv = (FontView *) fvb;*/
7502 GRect size;
7503
7504 memset(&size,0,sizeof(size));
7505 size.width = width; size.height = height;
7506 GGadgetSetDesiredSize(GWidgetGetControl(gs->gw,CID_Guts),
7507 NULL,&size);
7508 GHVBoxFitWindow(GWidgetGetControl(gs->gw,CID_TopBox));
7509 }
7510
7511 static struct fvcontainer_funcs glyphset_funcs = {
7512 fvc_glyphset,
7513 true, /* Modal dialog. No charviews, etc. */
7514 gs_activateMe,
7515 gs_charEvent,
7516 gs_doClose,
7517 gs_doResize
7518 };
7519
GS_OK(GGadget * g,GEvent * e)7520 static int GS_OK(GGadget *g, GEvent *e) {
7521
7522 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
7523 struct gsd *gs = GDrawGetUserData(GGadgetGetWindow(g));
7524 gs->done = true;
7525 gs->good = true;
7526 }
7527 return( true );
7528 }
7529
GS_Cancel(GGadget * g,GEvent * e)7530 static int GS_Cancel(GGadget *g, GEvent *e) {
7531 struct gsd *gs;
7532
7533 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
7534 gs = GDrawGetUserData(GGadgetGetWindow(g));
7535 gs->done = true;
7536 }
7537 return( true );
7538 }
7539
gs_sizeSet(struct gsd * gs,GWindow dw)7540 static void gs_sizeSet(struct gsd *gs,GWindow dw) {
7541 GRect size, gsize;
7542 int width, height, y;
7543 int cc, rc, topchar;
7544 GRect subsize;
7545 FontView *fv = gs->fv;
7546
7547 if ( gs->fv->vsb==NULL )
7548 return;
7549
7550 GDrawGetSize(dw,&size);
7551 GGadgetGetSize(gs->fv->vsb,&gsize);
7552 width = size.width - gsize.width;
7553 height = size.height - gs->fv->mbh - gs->fv->infoh;
7554
7555 y = gs->fv->mbh + gs->fv->infoh;
7556
7557 topchar = fv->rowoff*fv->colcnt;
7558 cc = (width-1) / fv->cbw;
7559 if ( cc<1 ) cc=1;
7560 rc = (height-1)/ fv->cbh;
7561 if ( rc<1 ) rc = 1;
7562 subsize.x = 0; subsize.y = 0;
7563 subsize.width = cc*fv->cbw + 1;
7564 subsize.height = rc*fv->cbh + 1;
7565 GDrawResize(fv->v,subsize.width,subsize.height);
7566 GDrawMove(fv->v,0,y);
7567 GGadgetMove(fv->vsb,subsize.width,y);
7568 GGadgetResize(fv->vsb,gsize.width,subsize.height);
7569
7570 fv->colcnt = cc; fv->rowcnt = rc;
7571 fv->width = subsize.width; fv->height = subsize.height;
7572 fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
7573 GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7574 fv->rowoff = topchar/fv->colcnt;
7575 if ( fv->rowoff>=fv->rowltot-fv->rowcnt )
7576 fv->rowoff = fv->rowltot-fv->rowcnt;
7577 if ( fv->rowoff<0 ) fv->rowoff =0;
7578 GScrollBarSetPos(fv->vsb,fv->rowoff);
7579
7580 GDrawRequestExpose(fv->v,NULL,true);
7581 }
7582
gs_sub_e_h(GWindow pixmap,GEvent * event)7583 static int gs_sub_e_h(GWindow pixmap, GEvent *event) {
7584 FontView *active_fv;
7585 struct gsd *gs;
7586
7587 if ( event->type==et_destroy )
7588 return( true );
7589
7590 active_fv = (FontView *) GDrawGetUserData(pixmap);
7591 gs = (struct gsd *) (active_fv->b.container);
7592
7593 if (( event->type==et_mouseup || event->type==et_mousedown ) &&
7594 (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
7595 return( GGadgetDispatchEvent(active_fv->vsb,event));
7596 }
7597
7598
7599 switch ( event->type ) {
7600 case et_expose:
7601 FVDrawInfo(active_fv,pixmap,event);
7602 break;
7603 case et_char:
7604 gs_charEvent(&gs->base,event);
7605 break;
7606 case et_mousedown:
7607 return(false);
7608 break;
7609 case et_mouseup: case et_mousemove:
7610 return(false);
7611 case et_resize:
7612 gs_sizeSet(gs,pixmap);
7613 break;
7614 }
7615 return( true );
7616 }
7617
gs_e_h(GWindow gw,GEvent * event)7618 static int gs_e_h(GWindow gw, GEvent *event) {
7619 struct gsd *gs = GDrawGetUserData(gw);
7620
7621 switch ( event->type ) {
7622 case et_close:
7623 gs->done = true;
7624 break;
7625 case et_char:
7626 FVChar(gs->fv,event);
7627 break;
7628 }
7629 return( true );
7630 }
7631
GlyphSetFromSelection(SplineFont * sf,int def_layer,char * current)7632 char *GlyphSetFromSelection(SplineFont *sf,int def_layer,char *current) {
7633 struct gsd gs;
7634 GRect pos;
7635 GWindowAttrs wattrs;
7636 GGadgetCreateData gcd[5], boxes[3];
7637 GGadgetCreateData *varray[21], *buttonarray[8];
7638 GTextInfo label[5];
7639 int i,j,k,guts_row,gid,enc,len;
7640 char *ret, *rpt;
7641 SplineChar *sc;
7642 GGadget *drawable;
7643 GWindow dw;
7644 GGadgetData gd;
7645 GRect gsize, sbsize;
7646 int infoh, mbh;
7647 int ps;
7648 FontView *fvorig = (FontView *) sf->fv;
7649 GGadget *mb;
7650 char *start, *pt; int ch;
7651
7652 FontViewInit();
7653
7654 memset(&wattrs,0,sizeof(wattrs));
7655 memset(&gcd,0,sizeof(gcd));
7656 memset(&boxes,0,sizeof(boxes));
7657 memset(&label,0,sizeof(label));
7658 memset(&gs,0,sizeof(gs));
7659
7660 gs.base.funcs = &glyphset_funcs;
7661
7662 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
7663 wattrs.event_masks = ~(1<<et_charup);
7664 wattrs.restrict_input_to_me = true;
7665 wattrs.undercursor = 1;
7666 wattrs.cursor = ct_pointer;
7667 wattrs.utf8_window_title = _("Glyph Set by Selection") ;
7668 wattrs.is_dlg = true;
7669 pos.x = pos.y = 0;
7670 pos.width = 100;
7671 pos.height = 100;
7672 gs.gw = GDrawCreateTopWindow(NULL,&pos,gs_e_h,&gs,&wattrs);
7673
7674 i = j = 0;
7675
7676 guts_row = j/2;
7677 gcd[i].gd.flags = gg_enabled|gg_visible;
7678 gcd[i].gd.cid = CID_Guts;
7679 gcd[i].gd.u.drawable_e_h = gs_sub_e_h;
7680 gcd[i].creator = GDrawableCreate;
7681 varray[j++] = &gcd[i++]; varray[j++] = NULL;
7682
7683 label[i].text = (unichar_t *) _("Select glyphs in the font view above.\nThe selected glyphs become your glyph class.");
7684 label[i].text_is_1byte = true;
7685 gcd[i].gd.label = &label[i];
7686 gcd[i].gd.flags = gg_enabled|gg_visible;
7687 gcd[i].creator = GLabelCreate;
7688 varray[j++] = &gcd[i++]; varray[j++] = NULL;
7689
7690 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
7691 label[i].text = (unichar_t *) _("_OK");
7692 label[i].text_is_1byte = true;
7693 label[i].text_in_resource = true;
7694 gcd[i].gd.label = &label[i];
7695 gcd[i].gd.handle_controlevent = GS_OK;
7696 gcd[i++].creator = GButtonCreate;
7697
7698 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
7699 label[i].text = (unichar_t *) _("_Cancel");
7700 label[i].text_is_1byte = true;
7701 label[i].text_in_resource = true;
7702 gcd[i].gd.label = &label[i];
7703 gcd[i].gd.handle_controlevent = GS_Cancel;
7704 gcd[i++].creator = GButtonCreate;
7705
7706 buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[i-2]; buttonarray[2] = GCD_Glue;
7707 buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[i-1]; buttonarray[5] = GCD_Glue;
7708 buttonarray[6] = NULL;
7709 boxes[2].gd.flags = gg_enabled|gg_visible;
7710 boxes[2].gd.u.boxelements = buttonarray;
7711 boxes[2].creator = GHBoxCreate;
7712 varray[j++] = &boxes[2]; varray[j++] = NULL; varray[j++] = NULL;
7713
7714 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
7715 boxes[0].gd.flags = gg_enabled|gg_visible;
7716 boxes[0].gd.u.boxelements = varray;
7717 boxes[0].gd.cid = CID_TopBox;
7718 boxes[0].creator = GHVGroupCreate;
7719
7720 GGadgetsCreate(gs.gw,boxes);
7721
7722 GHVBoxSetExpandableRow(boxes[0].ret,guts_row);
7723 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
7724
7725 drawable = GWidgetGetControl(gs.gw,CID_Guts);
7726 dw = GDrawableGetWindow(drawable);
7727
7728 memset(&gd,0,sizeof(gd));
7729 gd.flags = gg_visible | gg_enabled;
7730 helplist[0].invoke = FVMenuContextualHelp;
7731 gd.u.menu2 = mblist;
7732 mb = GMenu2BarCreate( dw, &gd, NULL);
7733 GGadgetGetSize(mb,&gsize);
7734 mbh = gsize.height;
7735
7736 ps = sf->display_size; sf->display_size = -24;
7737 gs.fv = __FontViewCreate(sf);
7738
7739 infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
7740 gs.fv->mbh = mbh;
7741 pos.x = 0; pos.y = mbh+infoh;
7742 pos.width = 16*gs.fv->cbw+1;
7743 pos.height = 4*gs.fv->cbh+1;
7744
7745 GDrawSetUserData(dw,gs.fv);
7746 FVCopyInnards(gs.fv,&pos,infoh,fvorig,dw,def_layer,(struct fvcontainer *) &gs);
7747 pos.height = 4*gs.fv->cbh+1; /* We don't know the real fv->cbh until after creating the innards. The size of the last window is probably wrong, we'll fix later */
7748 memset(gs.fv->b.selected,0,gs.fv->b.map->enccount);
7749 if ( current!=NULL && strcmp(current,_("{Everything Else}"))!=0 ) {
7750 int first = true;
7751 for ( start = current; *start==' '; ++start );
7752 while ( *start ) {
7753 for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
7754 ch = *pt; *pt='\0';
7755 sc = SFGetChar(sf,-1,start);
7756 *pt = ch;
7757 if ( sc!=NULL && (enc = gs.fv->b.map->backmap[sc->orig_pos])!=-1 ) {
7758 gs.fv->b.selected[enc] = true;
7759 if ( first ) {
7760 first = false;
7761 gs.fv->rowoff = enc/gs.fv->colcnt;
7762 }
7763 }
7764 start = pt;
7765 while ( *start==' ' ) ++start;
7766 }
7767 }
7768 sf->display_size = ps;
7769
7770 GGadgetGetSize(gs.fv->vsb,&sbsize);
7771 gsize.x = gsize.y = 0;
7772 gsize.width = pos.width + sbsize.width;
7773 gsize.height = pos.y+pos.height;
7774 GGadgetSetDesiredSize(drawable,NULL,&gsize);
7775
7776 GHVBoxFitWindow(boxes[0].ret);
7777 GDrawSetVisible(gs.gw,true);
7778 while ( !gs.done )
7779 GDrawProcessOneEvent(NULL);
7780
7781 ret = rpt = NULL;
7782 if ( gs.good ) {
7783 for ( k=0; k<2; ++k ) {
7784 len = 0;
7785 for ( enc=0; enc<gs.fv->b.map->enccount; ++enc ) {
7786 if ( gs.fv->b.selected[enc] &&
7787 (gid=gs.fv->b.map->map[enc])!=-1 &&
7788 (sc = sf->glyphs[gid])!=NULL ) {
7789 char *repr = SCNameUniStr( sc );
7790 if ( ret==NULL )
7791 len += strlen(repr)+2;
7792 else {
7793 strcpy(rpt,repr);
7794 rpt += strlen( repr );
7795 free(repr);
7796 *rpt++ = ' ';
7797 }
7798 }
7799 }
7800 if ( k==0 )
7801 ret = rpt = malloc(len+1);
7802 else if ( rpt!=ret && rpt[-1]==' ' )
7803 rpt[-1]='\0';
7804 else
7805 *rpt='\0';
7806 }
7807 }
7808 FontViewFree(&gs.fv->b);
7809 GDrawSetUserData(gs.gw,NULL);
7810 GDrawSetUserData(dw,NULL);
7811 GDrawDestroyWindow(gs.gw);
7812 return( ret );
7813 }
7814
7815 /* local variables: */
7816 /* tab-width: 8 */
7817 /* end: */
7818