Line data Source code
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 : #include <fontforge-config.h>
28 :
29 : #include "inc/gnetwork.h"
30 : #include "collabclientui.h"
31 : #include "collabclientpriv.h"
32 :
33 : #include "autosave.h"
34 : #include "autotrace.h"
35 : #include "autowidth.h"
36 : #include "autowidth2.h"
37 : #include "bitmapchar.h"
38 : #include "bvedit.h"
39 : #include "cvundoes.h"
40 : #include "dumppfa.h"
41 : #include "encoding.h"
42 : #include "fontforgeui.h"
43 : #include "fvcomposite.h"
44 : #include "fvfonts.h"
45 : #include "groups.h"
46 : #include "mm.h"
47 : #include "namelist.h"
48 : #include "nonlineartrans.h"
49 : #include "psfont.h"
50 : #include "scripting.h"
51 : #include "splinefill.h"
52 : #include "search.h"
53 : #include "sfd.h"
54 : #include "splinesaveafm.h"
55 : #include "splineutil.h"
56 : #include "splineutil2.h"
57 : #include "tottfgpos.h"
58 : #include <gfile.h>
59 : #include <gio.h>
60 : #include <gresedit.h>
61 : #include <ustring.h>
62 : #include "../fontforge/ffglib.h"
63 : #include <gkeysym.h>
64 : #include <utype.h>
65 : #include <chardata.h>
66 : #include <gresource.h>
67 : #include <math.h>
68 : #include <unistd.h>
69 :
70 : #include "gutils/unicodelibinfo.h"
71 : #include "sfundo.h"
72 :
73 : #if defined (__MINGW32__)
74 : #include <windows.h>
75 : #endif
76 :
77 : #include "xvasprintf.h"
78 :
79 :
80 : int OpenCharsInNewWindow = 0;
81 : char *RecentFiles[RECENT_MAX] = { NULL };
82 : int save_to_dir = 0; /* use sfdir rather than sfd */
83 : unichar_t *script_menu_names[SCRIPT_MENU_MAX];
84 : char *script_filenames[SCRIPT_MENU_MAX];
85 : extern int onlycopydisplayed, copymetadata, copyttfinstr, add_char_to_name_list;
86 : int home_char='A';
87 : int compact_font_on_open=0;
88 : int navigation_mask = 0; /* Initialized in startui.c */
89 :
90 : static char *fv_fontnames = MONO_UI_FAMILIES;
91 : extern char* pref_collab_last_server_connected_to;
92 : extern void python_call_onClosingFunctions();
93 :
94 : #define FV_LAB_HEIGHT 15
95 :
96 : #ifdef BIGICONS
97 : #define fontview_width 32
98 : #define fontview_height 32
99 : static unsigned char fontview_bits[] = {
100 : 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00,
101 : 0x82, 0x20, 0x86, 0x08, 0x42, 0x21, 0x8a, 0x14, 0xc2, 0x21, 0x86, 0x04,
102 : 0x42, 0x21, 0x8a, 0x14, 0x42, 0x21, 0x86, 0x08, 0x02, 0x20, 0x80, 0x00,
103 : 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00, 0x82, 0xa0, 0x8f, 0x18,
104 : 0x82, 0x20, 0x91, 0x24, 0x42, 0x21, 0x91, 0x02, 0x42, 0x21, 0x91, 0x02,
105 : 0x22, 0x21, 0x8f, 0x02, 0xe2, 0x23, 0x91, 0x02, 0x12, 0x22, 0x91, 0x02,
106 : 0x3a, 0x27, 0x91, 0x24, 0x02, 0xa0, 0x8f, 0x18, 0x02, 0x20, 0x80, 0x00,
107 : 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00, 0x42, 0x20, 0x86, 0x18,
108 : 0xa2, 0x20, 0x8a, 0x04, 0xa2, 0x20, 0x86, 0x08, 0xa2, 0x20, 0x8a, 0x10,
109 : 0x42, 0x20, 0x8a, 0x0c, 0x82, 0x20, 0x80, 0x00, 0x02, 0x20, 0x80, 0x00,
110 : 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00};
111 : #else
112 : #define fontview2_width 16
113 : #define fontview2_height 16
114 : static unsigned char fontview2_bits[] = {
115 : 0x00, 0x07, 0x80, 0x08, 0x40, 0x17, 0x40, 0x15, 0x60, 0x09, 0x10, 0x02,
116 : 0xa0, 0x01, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x50, 0x00, 0x52, 0x00,
117 : 0x55, 0x00, 0x5d, 0x00, 0x22, 0x00, 0x1c, 0x00};
118 : #endif
119 :
120 : extern int _GScrollBar_Width;
121 :
122 : static int fv_fontsize = 11, fv_fs_init=0;
123 : static Color fvselcol = 0xffff00, fvselfgcol=0x000000;
124 : Color view_bgcol;
125 : static Color fvglyphinfocol = 0xff0000;
126 : static Color fvemtpyslotfgcol = 0xd08080;
127 : static Color fvchangedcol = 0x000060;
128 : static Color fvhintingneededcol = 0x0000ff;
129 :
130 : enum glyphlable { gl_glyph, gl_name, gl_unicode, gl_encoding };
131 : int default_fv_showhmetrics=false, default_fv_showvmetrics=false,
132 : default_fv_glyphlabel = gl_glyph;
133 : #define METRICS_BASELINE 0x0000c0
134 : #define METRICS_ORIGIN 0xc00000
135 : #define METRICS_ADVANCE 0x008000
136 : FontView *fv_list=NULL;
137 :
138 : static void AskAndMaybeCloseLocalCollabServers( void );
139 :
140 :
141 2856 : static void FV_ToggleCharChanged(SplineChar *sc) {
142 : int i, j;
143 : int pos;
144 : FontView *fv;
145 :
146 5712 : for ( fv = (FontView *) (sc->parent->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
147 2856 : if ( fv->b.sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
148 6 : continue;
149 2850 : if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
150 2850 : continue;
151 0 : for ( pos=0; pos<fv->b.map->enccount; ++pos ) if ( fv->b.map->map[pos]==sc->orig_pos ) {
152 0 : i = pos / fv->colcnt;
153 0 : j = pos - i*fv->colcnt;
154 0 : i -= fv->rowoff;
155 : /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
156 : /* but every now and then the WM forces us to use a window size which doesn't */
157 : /* fit our expectations (maximized view) and we must be prepared for half */
158 : /* lines */
159 0 : if ( i>=0 && i<=fv->rowcnt ) {
160 : GRect r;
161 0 : r.x = j*fv->cbw+1; r.width = fv->cbw-1;
162 0 : r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
163 0 : GDrawRequestExpose(fv->v,&r,false);
164 : }
165 : }
166 : }
167 2856 : }
168 :
169 2082 : void FVMarkHintsOutOfDate(SplineChar *sc) {
170 : int i, j;
171 : int pos;
172 : FontView *fv;
173 :
174 2082 : if ( sc->parent->onlybitmaps || sc->parent->multilayer || sc->parent->strokedfont )
175 2082 : return;
176 4164 : for ( fv = (FontView *) (sc->parent->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
177 2082 : if ( fv->b.sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
178 1 : continue;
179 2081 : if ( sc->layers[fv->b.active_layer].order2 )
180 1215 : continue;
181 866 : if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
182 866 : continue;
183 0 : for ( pos=0; pos<fv->b.map->enccount; ++pos ) if ( fv->b.map->map[pos]==sc->orig_pos ) {
184 0 : i = pos / fv->colcnt;
185 0 : j = pos - i*fv->colcnt;
186 0 : i -= fv->rowoff;
187 : /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
188 : /* but every now and then the WM forces us to use a window size which doesn't */
189 : /* fit our expectations (maximized view) and we must be prepared for half */
190 : /* lines */
191 0 : if ( i>=0 && i<=fv->rowcnt ) {
192 : GRect r;
193 0 : r.x = j*fv->cbw+1; r.width = fv->cbw-1;
194 0 : r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
195 0 : GDrawDrawLine(fv->v,r.x,r.y,r.x,r.y+r.height-1,fvhintingneededcol);
196 0 : GDrawDrawLine(fv->v,r.x+1,r.y,r.x+1,r.y+r.height-1,fvhintingneededcol);
197 0 : GDrawDrawLine(fv->v,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,fvhintingneededcol);
198 0 : GDrawDrawLine(fv->v,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,fvhintingneededcol);
199 : }
200 : }
201 : }
202 : }
203 :
204 0 : static int FeatureTrans(FontView *fv, int enc) {
205 : SplineChar *sc;
206 : PST *pst;
207 : char *pt;
208 : int gid;
209 :
210 0 : if ( enc<0 || enc>=fv->b.map->enccount || (gid = fv->b.map->map[enc])==-1 )
211 0 : return( -1 );
212 0 : if ( fv->cur_subtable==NULL )
213 0 : return( gid );
214 :
215 0 : sc = fv->b.sf->glyphs[gid];
216 0 : if ( sc==NULL )
217 0 : return( -1 );
218 0 : for ( pst = sc->possub; pst!=NULL; pst=pst->next ) {
219 0 : if (( pst->type == pst_substitution || pst->type == pst_alternate ) &&
220 0 : pst->subtable == fv->cur_subtable )
221 0 : break;
222 : }
223 0 : if ( pst==NULL )
224 0 : return( -1 );
225 0 : pt = strchr(pst->u.subs.variant,' ');
226 0 : if ( pt!=NULL )
227 0 : *pt = '\0';
228 0 : gid = SFFindExistingSlot(fv->b.sf, -1, pst->u.subs.variant );
229 0 : if ( pt!=NULL )
230 0 : *pt = ' ';
231 0 : return( gid );
232 : }
233 :
234 0 : static void FVDrawGlyph(GWindow pixmap, FontView *fv, int index, int forcebg ) {
235 : GRect box, old2;
236 : int feat_gid;
237 : SplineChar *sc;
238 : struct _GImage base;
239 : GImage gi;
240 : GClut clut;
241 : int i,j;
242 0 : int em = fv->b.sf->ascent+fv->b.sf->descent;
243 0 : int yorg = fv->magnify*(fv->show->ascent);
244 :
245 0 : i = index / fv->colcnt;
246 0 : j = index - i*fv->colcnt;
247 0 : i -= fv->rowoff;
248 :
249 0 : if ( index<fv->b.map->enccount && (fv->b.selected[index] || forcebg)) {
250 0 : box.x = j*fv->cbw+1; box.width = fv->cbw-1;
251 0 : box.y = i*fv->cbh+fv->lab_height+1; box.height = fv->cbw;
252 0 : GDrawFillRect(pixmap,&box,fv->b.selected[index] ? fvselcol : view_bgcol );
253 : }
254 0 : feat_gid = FeatureTrans(fv,index);
255 0 : sc = feat_gid!=-1 ? fv->b.sf->glyphs[feat_gid]: NULL;
256 0 : if ( !SCWorthOutputting(sc) ) {
257 0 : int x = j*fv->cbw+1, xend = x+fv->cbw-2;
258 0 : int y = i*fv->cbh+fv->lab_height+1, yend = y+fv->cbw-1;
259 0 : GDrawDrawLine(pixmap,x,y,xend,yend,fvemtpyslotfgcol);
260 0 : GDrawDrawLine(pixmap,x,yend,xend,y,fvemtpyslotfgcol);
261 : }
262 0 : if ( sc!=NULL ) {
263 : BDFChar *bdfc;
264 :
265 0 : if ( fv->show!=NULL && fv->show->piecemeal &&
266 0 : feat_gid!=-1 &&
267 0 : (feat_gid>=fv->show->glyphcnt || fv->show->glyphs[feat_gid]==NULL) &&
268 0 : fv->b.sf->glyphs[feat_gid]!=NULL )
269 0 : BDFPieceMeal(fv->show,feat_gid);
270 :
271 0 : if ( fv->show!=NULL && feat_gid!=-1 &&
272 0 : feat_gid < fv->show->glyphcnt &&
273 0 : fv->show->glyphs[feat_gid]==NULL &&
274 0 : SCWorthOutputting(fv->b.sf->glyphs[feat_gid]) ) {
275 : /* If we have an outline but no bitmap for this slot */
276 0 : box.x = j*fv->cbw+1; box.width = fv->cbw-2;
277 0 : box.y = i*fv->cbh+fv->lab_height+2; box.height = box.width+1;
278 0 : GDrawDrawRect(pixmap,&box,0xff0000);
279 0 : ++box.x; ++box.y; box.width -= 2; box.height -= 2;
280 0 : GDrawDrawRect(pixmap,&box,0xff0000);
281 : /* When reencoding a font we can find times where index>=show->charcnt */
282 0 : } else if ( fv->show!=NULL && feat_gid<fv->show->glyphcnt && feat_gid!=-1 &&
283 0 : fv->show->glyphs[feat_gid]!=NULL ) {
284 : /* If fontview is set to display an embedded bitmap font (not a temporary font, */
285 : /* rasterized specially for this purpose), then we can't use it directly, as bitmap */
286 : /* glyphs may contain selections and references. So create a temporary copy of */
287 : /* the glyph merging all such elements into a single bitmap */
288 0 : bdfc = fv->show->piecemeal ?
289 0 : fv->show->glyphs[feat_gid] : BDFGetMergedChar( fv->show->glyphs[feat_gid] );
290 :
291 0 : memset(&gi,'\0',sizeof(gi));
292 0 : memset(&base,'\0',sizeof(base));
293 0 : if ( bdfc->byte_data ) {
294 0 : gi.u.image = &base;
295 0 : base.image_type = it_index;
296 0 : if ( !fv->b.selected[index] )
297 0 : base.clut = fv->show->clut;
298 : else {
299 0 : int bgr=((fvselcol>>16)&0xff), bgg=((fvselcol>>8)&0xff), bgb= (fvselcol&0xff);
300 0 : int fgr=((fvselfgcol>>16)&0xff), fgg=((fvselfgcol>>8)&0xff), fgb= (fvselfgcol&0xff);
301 : int i;
302 0 : memset(&clut,'\0',sizeof(clut));
303 0 : base.clut = &clut;
304 0 : clut.clut_len = fv->show->clut->clut_len;
305 0 : for ( i=0; i<clut.clut_len; ++i ) {
306 0 : clut.clut[i] =
307 0 : COLOR_CREATE( bgr + (i*(fgr-bgr))/(clut.clut_len-1),
308 : bgg + (i*(fgg-bgg))/(clut.clut_len-1),
309 : bgb + (i*(fgb-bgb))/(clut.clut_len-1));
310 : }
311 : }
312 0 : GDrawSetDither(NULL, false); /* on 8 bit displays we don't want any dithering */
313 : } else {
314 0 : memset(&clut,'\0',sizeof(clut));
315 0 : gi.u.image = &base;
316 0 : base.image_type = it_mono;
317 0 : base.clut = &clut;
318 0 : clut.clut_len = 2;
319 0 : clut.clut[0] = fv->b.selected[index] ? fvselcol : view_bgcol ;
320 0 : clut.clut[1] = fv->b.selected[index] ? fvselfgcol : 0 ;
321 : }
322 0 : base.trans = 0;
323 0 : base.clut->trans_index = 0;
324 :
325 0 : base.data = bdfc->bitmap;
326 0 : base.bytes_per_line = bdfc->bytes_per_line;
327 0 : base.width = bdfc->xmax-bdfc->xmin+1;
328 0 : base.height = bdfc->ymax-bdfc->ymin+1;
329 0 : box.x = j*fv->cbw; box.width = fv->cbw;
330 0 : box.y = i*fv->cbh+fv->lab_height+1; box.height = box.width+1;
331 0 : GDrawPushClip(pixmap,&box,&old2);
332 0 : if ( !fv->b.sf->onlybitmaps && fv->show!=fv->filled &&
333 0 : sc->layers[fv->b.active_layer].splines==NULL && sc->layers[fv->b.active_layer].refs==NULL &&
334 0 : !sc->widthset &&
335 0 : !(bdfc->xmax<=0 && bdfc->xmin==0 && bdfc->ymax<=0 && bdfc->ymax==0) ) {
336 : /* If we have a bitmap but no outline character... */
337 : GRect b;
338 0 : b.x = box.x+1; b.y = box.y+1; b.width = box.width-2; b.height = box.height-2;
339 0 : GDrawDrawRect(pixmap,&b,0x008000);
340 0 : ++b.x; ++b.y; b.width -= 2; b.height -= 2;
341 0 : GDrawDrawRect(pixmap,&b,0x008000);
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 0 : if ( fv->magnify>1 ) {
347 0 : GDrawDrawImageMagnified(pixmap,&gi,NULL,
348 0 : j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2,
349 0 : i*fv->cbh+fv->lab_height+1+fv->magnify*(fv->show->ascent-bdfc->ymax),
350 0 : fv->magnify*base.width,fv->magnify*base.height);
351 0 : } else if ( (GDrawHasCairo(pixmap)&gc_alpha) && base.image_type==it_index ) {
352 0 : GDrawDrawGlyph(pixmap,&gi,NULL,
353 0 : j*fv->cbw+(fv->cbw-1-base.width)/2,
354 0 : i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
355 : } else
356 0 : GDrawDrawImage(pixmap,&gi,NULL,
357 0 : j*fv->cbw+(fv->cbw-1-base.width)/2,
358 0 : i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
359 0 : if ( fv->showhmetrics ) {
360 0 : int x1, x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2- bdfc->xmin*fv->magnify;
361 : /* Draw advance width & horizontal origin */
362 0 : if ( fv->showhmetrics&fvm_origin )
363 0 : GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+yorg-3,x0,
364 0 : i*fv->cbh+fv->lab_height+yorg+2,METRICS_ORIGIN);
365 0 : x1 = x0 + fv->magnify*bdfc->width;
366 0 : if ( fv->showhmetrics&fvm_advanceat )
367 0 : GDrawDrawLine(pixmap,x1,i*fv->cbh+fv->lab_height+1,x1,
368 0 : (i+1)*fv->cbh-1,METRICS_ADVANCE);
369 0 : if ( fv->showhmetrics&fvm_advanceto )
370 0 : GDrawDrawLine(pixmap,x0,(i+1)*fv->cbh-2,x1,
371 0 : (i+1)*fv->cbh-2,METRICS_ADVANCE);
372 : }
373 0 : if ( fv->showvmetrics ) {
374 0 : int x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2- bdfc->xmin*fv->magnify
375 0 : + fv->magnify*fv->show->pixelsize/2;
376 0 : int y0 = i*fv->cbh+fv->lab_height+yorg;
377 0 : int yvw = y0 + fv->magnify*sc->vwidth*fv->show->pixelsize/em;
378 0 : if ( fv->showvmetrics&fvm_baseline )
379 0 : GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+1,x0,
380 0 : (i+1)*fv->cbh-1,METRICS_BASELINE);
381 0 : if ( fv->showvmetrics&fvm_advanceat )
382 0 : GDrawDrawLine(pixmap,j*fv->cbw,yvw,(j+1)*fv->cbw,
383 : yvw,METRICS_ADVANCE);
384 0 : if ( fv->showvmetrics&fvm_advanceto )
385 0 : GDrawDrawLine(pixmap,j*fv->cbw+2,y0,j*fv->cbw+2,
386 : yvw,METRICS_ADVANCE);
387 0 : if ( fv->showvmetrics&fvm_origin )
388 0 : GDrawDrawLine(pixmap,x0-3,i*fv->cbh+fv->lab_height+yorg,x0+2,i*fv->cbh+fv->lab_height+yorg,METRICS_ORIGIN);
389 : }
390 0 : GDrawPopClip(pixmap,&old2);
391 0 : if ( !fv->show->piecemeal ) BDFCharFree( bdfc );
392 : }
393 : }
394 0 : }
395 :
396 0 : static void FVToggleCharSelected(FontView *fv,int enc) {
397 : int i, j;
398 :
399 0 : if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
400 0 : return;
401 :
402 0 : i = enc / fv->colcnt;
403 0 : j = enc - i*fv->colcnt;
404 0 : 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 0 : if ( i>=0 && i<=fv->rowcnt )
410 0 : FVDrawGlyph(fv->v,fv,enc,true);
411 : }
412 :
413 6 : static void FontViewRefreshAll(SplineFont *sf) {
414 : FontView *fv;
415 12 : for ( fv = (FontView *) (sf->fv); fv!=NULL; fv = (FontView *) (fv->b.nextsame) )
416 6 : if ( fv->v!=NULL )
417 0 : GDrawRequestExpose(fv->v,NULL,false);
418 6 : }
419 :
420 0 : void FVDeselectAll(FontView *fv) {
421 : int i;
422 :
423 0 : for ( i=0; i<fv->b.map->enccount; ++i ) {
424 0 : if ( fv->b.selected[i] ) {
425 0 : fv->b.selected[i] = false;
426 0 : FVToggleCharSelected(fv,i);
427 : }
428 : }
429 0 : fv->sel_index = 0;
430 0 : }
431 :
432 0 : static void FVInvertSelection(FontView *fv) {
433 : int i;
434 :
435 0 : for ( i=0; i<fv->b.map->enccount; ++i ) {
436 0 : fv->b.selected[i] = !fv->b.selected[i];
437 0 : FVToggleCharSelected(fv,i);
438 : }
439 0 : fv->sel_index = 1;
440 0 : }
441 :
442 0 : static void FVSelectAll(FontView *fv) {
443 : int i;
444 :
445 0 : for ( i=0; i<fv->b.map->enccount; ++i ) {
446 0 : if ( !fv->b.selected[i] ) {
447 0 : fv->b.selected[i] = true;
448 0 : FVToggleCharSelected(fv,i);
449 : }
450 : }
451 0 : fv->sel_index = 1;
452 0 : }
453 :
454 0 : static void FVReselect(FontView *fv, int newpos) {
455 : int i;
456 :
457 0 : if ( newpos<0 ) newpos = 0;
458 0 : else if ( newpos>=fv->b.map->enccount ) newpos = fv->b.map->enccount-1;
459 :
460 0 : if ( fv->pressed_pos<fv->end_pos ) {
461 0 : if ( newpos>fv->end_pos ) {
462 0 : for ( i=fv->end_pos+1; i<=newpos; ++i ) if ( !fv->b.selected[i] ) {
463 0 : fv->b.selected[i] = fv->sel_index;
464 0 : FVToggleCharSelected(fv,i);
465 : }
466 0 : } else if ( newpos<fv->pressed_pos ) {
467 0 : for ( i=fv->end_pos; i>fv->pressed_pos; --i ) if ( fv->b.selected[i] ) {
468 0 : fv->b.selected[i] = false;
469 0 : FVToggleCharSelected(fv,i);
470 : }
471 0 : for ( i=fv->pressed_pos-1; i>=newpos; --i ) if ( !fv->b.selected[i] ) {
472 0 : fv->b.selected[i] = fv->sel_index;
473 0 : FVToggleCharSelected(fv,i);
474 : }
475 : } else {
476 0 : for ( i=fv->end_pos; i>newpos; --i ) if ( fv->b.selected[i] ) {
477 0 : fv->b.selected[i] = false;
478 0 : FVToggleCharSelected(fv,i);
479 : }
480 : }
481 : } else {
482 0 : if ( newpos<fv->end_pos ) {
483 0 : for ( i=fv->end_pos-1; i>=newpos; --i ) if ( !fv->b.selected[i] ) {
484 0 : fv->b.selected[i] = fv->sel_index;
485 0 : FVToggleCharSelected(fv,i);
486 : }
487 0 : } else if ( newpos>fv->pressed_pos ) {
488 0 : for ( i=fv->end_pos; i<fv->pressed_pos; ++i ) if ( fv->b.selected[i] ) {
489 0 : fv->b.selected[i] = false;
490 0 : FVToggleCharSelected(fv,i);
491 : }
492 0 : for ( i=fv->pressed_pos+1; i<=newpos; ++i ) if ( !fv->b.selected[i] ) {
493 0 : fv->b.selected[i] = fv->sel_index;
494 0 : FVToggleCharSelected(fv,i);
495 : }
496 : } else {
497 0 : for ( i=fv->end_pos; i<newpos; ++i ) if ( fv->b.selected[i] ) {
498 0 : fv->b.selected[i] = false;
499 0 : FVToggleCharSelected(fv,i);
500 : }
501 : }
502 : }
503 0 : fv->end_pos = newpos;
504 0 : if ( newpos>=0 && newpos<fv->b.map->enccount && (i = fv->b.map->map[newpos])!=-1 &&
505 0 : fv->b.sf->glyphs[i]!=NULL &&
506 0 : fv->b.sf->glyphs[i]->unicodeenc>=0 && fv->b.sf->glyphs[i]->unicodeenc<0x10000 )
507 0 : GInsCharSetChar(fv->b.sf->glyphs[i]->unicodeenc);
508 0 : }
509 :
510 0 : static void FVFlattenAllBitmapSelections(FontView *fv) {
511 : BDFFont *bdf;
512 : int i;
513 :
514 0 : for ( bdf = fv->b.sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
515 0 : for ( i=0; i<bdf->glyphcnt; ++i )
516 0 : if ( bdf->glyphs[i]!=NULL && bdf->glyphs[i]->selection!=NULL )
517 0 : BCFlattenFloat(bdf->glyphs[i]);
518 : }
519 0 : }
520 :
521 0 : static int AskChanged(SplineFont *sf) {
522 : int ret;
523 : char *buts[4];
524 : char *filename, *fontname;
525 :
526 0 : if ( sf->cidmaster!=NULL )
527 0 : sf = sf->cidmaster;
528 :
529 0 : filename = sf->filename;
530 0 : fontname = sf->fontname;
531 :
532 0 : if ( filename==NULL && sf->origname!=NULL &&
533 0 : sf->onlybitmaps && sf->bitmaps!=NULL && sf->bitmaps->next==NULL )
534 0 : filename = sf->origname;
535 0 : if ( filename==NULL ) filename = "untitled.sfd";
536 0 : filename = GFileNameTail(filename);
537 0 : buts[0] = _("_Save");
538 0 : buts[1] = _("_Don't Save");
539 0 : buts[2] = _("_Cancel");
540 0 : buts[3] = NULL;
541 0 : 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 0 : return( ret );
543 : }
544 :
545 0 : int _FVMenuGenerate(FontView *fv,int family) {
546 0 : FVFlattenAllBitmapSelections(fv);
547 0 : return( SFGenerateFont(fv->b.sf,fv->b.active_layer,family,fv->b.normal==NULL?fv->b.map:fv->b.normal) );
548 : }
549 :
550 0 : static void FVMenuGenerate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
551 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
552 :
553 0 : _FVMenuGenerate(fv,gf_none);
554 0 : }
555 :
556 0 : static void FVMenuGenerateFamily(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
557 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
558 :
559 0 : _FVMenuGenerate(fv,gf_macfamily);
560 0 : }
561 :
562 0 : static void FVMenuGenerateTTC(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
563 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
564 :
565 0 : _FVMenuGenerate(fv,gf_ttc);
566 0 : }
567 :
568 : extern int save_to_dir;
569 :
570 0 : static int SaveAs_FormatChange(GGadget *g, GEvent *e) {
571 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
572 0 : GGadget *fc = GWidgetGetControl(GGadgetGetWindow(g),1000);
573 0 : char *oldname = GGadgetGetTitle8(fc);
574 0 : int *_s2d = GGadgetGetUserData(g);
575 0 : int s2d = GGadgetIsChecked(g);
576 0 : char *pt, *newname = malloc(strlen(oldname)+8);
577 0 : strcpy(newname,oldname);
578 0 : pt = strrchr(newname,'.');
579 0 : if ( pt==NULL )
580 0 : pt = newname+strlen(newname);
581 0 : strcpy(pt,s2d ? ".sfdir" : ".sfd" );
582 0 : GGadgetSetTitle8(fc,newname);
583 0 : save_to_dir = *_s2d = s2d;
584 0 : SavePrefs(true);
585 : }
586 0 : return( true );
587 : }
588 :
589 :
590 0 : static enum fchooserret _FVSaveAsFilterFunc(GGadget *g,struct gdirentry *ent, const unichar_t *dir)
591 : {
592 0 : char* n = u_to_c(ent->name);
593 0 : int ew = endswithi( n, "sfd" ) || endswithi( n, "sfdir" );
594 0 : if( ew )
595 0 : return fc_show;
596 0 : if( ent->isdir )
597 0 : return fc_show;
598 0 : return fc_hide;
599 : }
600 :
601 :
602 0 : int _FVMenuSaveAs(FontView *fv) {
603 : char *temp;
604 : char *ret;
605 : char *filename;
606 : int ok;
607 0 : int s2d = fv->b.cidmaster!=NULL ? fv->b.cidmaster->save_to_dir :
608 0 : fv->b.sf->mm!=NULL ? fv->b.sf->mm->normal->save_to_dir :
609 0 : fv->b.sf->save_to_dir;
610 : GGadgetCreateData gcd;
611 : GTextInfo label;
612 :
613 0 : if ( fv->b.cidmaster!=NULL && fv->b.cidmaster->filename!=NULL )
614 0 : temp=def2utf8_copy(fv->b.cidmaster->filename);
615 0 : else if ( fv->b.sf->mm!=NULL && fv->b.sf->mm->normal->filename!=NULL )
616 0 : temp=def2utf8_copy(fv->b.sf->mm->normal->filename);
617 0 : else if ( fv->b.sf->filename!=NULL )
618 0 : temp=def2utf8_copy(fv->b.sf->filename);
619 : else {
620 0 : SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:
621 0 : fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:fv->b.sf;
622 0 : char *fn = sf->defbasefilename ? sf->defbasefilename : sf->fontname;
623 0 : temp = malloc((strlen(fn)+10));
624 0 : strcpy(temp,fn);
625 0 : if ( sf->defbasefilename!=NULL )
626 : /* Don't add a default suffix, they've already told us what name to use */;
627 0 : else if ( fv->b.cidmaster!=NULL )
628 0 : strcat(temp,"CID");
629 0 : else if ( sf->mm==NULL )
630 : ;
631 0 : else if ( sf->mm->apple )
632 0 : strcat(temp,"Var");
633 : else
634 0 : strcat(temp,"MM");
635 0 : strcat(temp,save_to_dir ? ".sfdir" : ".sfd");
636 0 : s2d = save_to_dir;
637 : }
638 :
639 0 : memset(&gcd,0,sizeof(gcd));
640 0 : memset(&label,0,sizeof(label));
641 0 : gcd.gd.flags = s2d ? (gg_visible | gg_enabled | gg_cb_on) : (gg_visible | gg_enabled);
642 0 : label.text = (unichar_t *) _("Save as _Directory");
643 0 : label.text_is_1byte = true;
644 0 : label.text_in_resource = true;
645 0 : gcd.gd.label = &label;
646 0 : gcd.gd.handle_controlevent = SaveAs_FormatChange;
647 0 : gcd.data = &s2d;
648 0 : gcd.creator = GCheckBoxCreate;
649 :
650 0 : GFileChooserInputFilenameFuncType FilenameFunc = GFileChooserDefInputFilenameFunc;
651 :
652 : #if defined(__MINGW32__)
653 : //
654 : // If they are "saving as" but there is no path, lets help
655 : // the poor user by starting someplace sane rather than in `pwd`
656 : //
657 : if( !GFileIsAbsolute(temp) )
658 : {
659 : char* defaultSaveDir = GFileGetHomeDocumentsDir();
660 : printf("save-as:%s\n", temp );
661 : char* temp2 = GFileAppendFile( defaultSaveDir, temp, 0 );
662 : free(temp);
663 : temp = temp2;
664 : }
665 : #endif
666 :
667 0 : ret = GWidgetSaveAsFileWithGadget8(_("Save as..."),temp,0,NULL,
668 : _FVSaveAsFilterFunc, FilenameFunc,
669 : &gcd );
670 0 : free(temp);
671 0 : if ( ret==NULL )
672 0 : return( 0 );
673 0 : filename = utf82def_copy(ret);
674 0 : free(ret);
675 :
676 0 : if(!(endswithi( filename, ".sfdir") || endswithi( filename, ".sfd")))
677 : {
678 : // they forgot the extension, so we force the default of .sfd
679 : // and alert them to the fact that we have done this and we
680 : // are not saving to a OTF, TTF, UFO formatted file
681 :
682 0 : char* extension = ".sfd";
683 0 : char* newpath = copyn( filename, strlen(filename) + strlen(".sfd") + 1 );
684 0 : strcat( newpath, ".sfd" );
685 :
686 0 : char* oldfn = GFileNameTail( filename );
687 0 : char* newfn = GFileNameTail( newpath );
688 :
689 0 : LogError( _("You tried to save with the filename %s but it was saved as %s. "),
690 : oldfn, newfn );
691 0 : LogError( _("Please choose File/Generate Fonts to save to other formats."));
692 :
693 0 : free(filename);
694 0 : filename = newpath;
695 : }
696 :
697 0 : FVFlattenAllBitmapSelections(fv);
698 0 : fv->b.sf->compression = 0;
699 0 : ok = SFDWrite(filename,fv->b.sf,fv->b.map,fv->b.normal,s2d);
700 0 : if ( ok ) {
701 0 : SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:fv->b.sf;
702 0 : free(sf->filename);
703 0 : sf->filename = filename;
704 0 : sf->save_to_dir = s2d;
705 0 : free(sf->origname);
706 0 : sf->origname = copy(filename);
707 0 : sf->new = false;
708 0 : if ( sf->mm!=NULL ) {
709 : int i;
710 0 : for ( i=0; i<sf->mm->instance_count; ++i ) {
711 0 : free(sf->mm->instances[i]->filename);
712 0 : sf->mm->instances[i]->filename = filename;
713 0 : free(sf->mm->instances[i]->origname);
714 0 : sf->mm->instances[i]->origname = copy(filename);
715 0 : sf->mm->instances[i]->new = false;
716 : }
717 : }
718 0 : SplineFontSetUnChanged(sf);
719 0 : FVSetTitles(fv->b.sf);
720 : } else
721 0 : free(filename);
722 0 : return( ok );
723 : }
724 :
725 0 : static void FVMenuSaveAs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
726 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
727 :
728 0 : _FVMenuSaveAs(fv);
729 0 : }
730 :
731 0 : static int IsBackupName(char *filename) {
732 :
733 0 : if ( filename==NULL )
734 0 : return( false );
735 0 : return( filename[strlen(filename)-1]=='~' );
736 : }
737 :
738 0 : int _FVMenuSave(FontView *fv) {
739 0 : int ret = 0;
740 0 : SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:
741 0 : fv->b.sf->mm!=NULL?fv->b.sf->mm->normal:
742 : fv->b.sf;
743 :
744 0 : if ( sf->filename==NULL || IsBackupName(sf->filename))
745 0 : ret = _FVMenuSaveAs(fv);
746 : else {
747 0 : FVFlattenAllBitmapSelections(fv);
748 0 : if ( !SFDWriteBak(sf->filename,sf,fv->b.map,fv->b.normal) )
749 0 : ff_post_error(_("Save Failed"),_("Save Failed"));
750 : else {
751 0 : SplineFontSetUnChanged(sf);
752 0 : ret = true;
753 : }
754 : }
755 0 : return( ret );
756 : }
757 :
758 0 : static void FVMenuSave(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
759 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
760 0 : _FVMenuSave(fv);
761 0 : }
762 :
763 0 : void _FVCloseWindows(FontView *fv) {
764 : int i, j;
765 : BDFFont *bdf;
766 : MetricsView *mv, *mnext;
767 0 : SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf->mm!=NULL?fv->b.sf->mm->normal : fv->b.sf;
768 :
769 0 : PrintWindowClose();
770 0 : if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b && fv->b.sf->kcld!=NULL )
771 0 : KCLD_End(fv->b.sf->kcld);
772 0 : if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b && fv->b.sf->vkcld!=NULL )
773 0 : KCLD_End(fv->b.sf->vkcld);
774 :
775 0 : for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
776 : CharView *cv, *next;
777 0 : for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
778 0 : next = (CharView *) (cv->b.next);
779 0 : GDrawDestroyWindow(cv->gw);
780 : }
781 0 : if ( sf->glyphs[i]->charinfo )
782 0 : CharInfoDestroy(sf->glyphs[i]->charinfo);
783 : }
784 0 : if ( sf->mm!=NULL ) {
785 0 : MMSet *mm = sf->mm;
786 0 : for ( j=0; j<mm->instance_count; ++j ) {
787 0 : SplineFont *sf = mm->instances[j];
788 0 : for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
789 : CharView *cv, *next;
790 0 : for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
791 0 : next = (CharView *) (cv->b.next);
792 0 : GDrawDestroyWindow(cv->gw);
793 : }
794 0 : if ( sf->glyphs[i]->charinfo )
795 0 : CharInfoDestroy(sf->glyphs[i]->charinfo);
796 : }
797 0 : for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
798 0 : mnext = mv->next;
799 0 : GDrawDestroyWindow(mv->gw);
800 : }
801 : }
802 0 : } else if ( sf->subfontcnt!=0 ) {
803 0 : for ( j=0; j<sf->subfontcnt; ++j ) {
804 0 : for ( i=0; i<sf->subfonts[j]->glyphcnt; ++i ) if ( sf->subfonts[j]->glyphs[i]!=NULL ) {
805 : CharView *cv, *next;
806 0 : for ( cv = (CharView *) (sf->subfonts[j]->glyphs[i]->views); cv!=NULL; cv = next ) {
807 0 : next = (CharView *) (cv->b.next);
808 0 : GDrawDestroyWindow(cv->gw);
809 0 : if ( sf->subfonts[j]->glyphs[i]->charinfo )
810 0 : CharInfoDestroy(sf->subfonts[j]->glyphs[i]->charinfo);
811 : }
812 : }
813 0 : for ( mv=sf->subfonts[j]->metrics; mv!=NULL; mv = mnext ) {
814 0 : mnext = mv->next;
815 0 : GDrawDestroyWindow(mv->gw);
816 : }
817 : }
818 : } else {
819 0 : for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
820 0 : mnext = mv->next;
821 0 : GDrawDestroyWindow(mv->gw);
822 : }
823 : }
824 0 : for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
825 0 : for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
826 : BitmapView *bv, *next;
827 0 : for ( bv = bdf->glyphs[i]->views; bv!=NULL; bv = next ) {
828 0 : next = bv->next;
829 0 : GDrawDestroyWindow(bv->gw);
830 : }
831 : }
832 : }
833 0 : if ( fv->b.sf->fontinfo!=NULL )
834 0 : FontInfoDestroy(fv->b.sf);
835 0 : if ( fv->b.sf->valwin!=NULL )
836 0 : ValidationDestroy(fv->b.sf);
837 0 : SVDetachFV(fv);
838 0 : }
839 :
840 0 : static int SFAnyChanged(SplineFont *sf) {
841 0 : if ( sf->mm!=NULL ) {
842 0 : MMSet *mm = sf->mm;
843 : int i;
844 0 : if ( mm->changed )
845 0 : return( true );
846 0 : for ( i=0; i<mm->instance_count; ++i )
847 0 : if ( sf->mm->instances[i]->changed )
848 0 : return( true );
849 : /* Changes to the blended font aren't real (for adobe fonts) */
850 0 : if ( mm->apple && mm->normal->changed )
851 0 : return( true );
852 :
853 0 : return( false );
854 : } else
855 0 : return( sf->changed );
856 : }
857 :
858 0 : static int _FVMenuClose(FontView *fv) {
859 : int i;
860 0 : SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf;
861 :
862 0 : if ( !SFCloseAllInstrs(fv->b.sf) )
863 0 : return( false );
864 :
865 0 : if ( fv->b.nextsame!=NULL || fv->b.sf->fv!=&fv->b ) {
866 : /* There's another view, can close this one with no problems */
867 0 : } else if ( SFAnyChanged(sf) ) {
868 0 : i = AskChanged(fv->b.sf);
869 0 : if ( i==2 ) /* Cancel */
870 0 : return( false );
871 0 : if ( i==0 && !_FVMenuSave(fv)) /* Save */
872 0 : return(false);
873 : else
874 0 : SFClearAutoSave(sf); /* if they didn't save it, remove change record */
875 : }
876 0 : _FVCloseWindows(fv);
877 0 : if ( sf->filename!=NULL )
878 0 : RecentFilesRemember(sf->filename);
879 0 : else if ( sf->origname!=NULL )
880 0 : RecentFilesRemember(sf->origname);
881 0 : GDrawDestroyWindow(fv->gw);
882 0 : return( true );
883 : }
884 :
885 0 : void MenuNew(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
886 0 : FontNew();
887 0 : }
888 :
889 0 : static void FVMenuClose(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
890 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
891 :
892 0 : if ( fv->b.container )
893 0 : (fv->b.container->funcs->doClose)(fv->b.container);
894 : else
895 0 : _FVMenuClose(fv);
896 0 : }
897 :
898 0 : static void FV_ReattachCVs(SplineFont *old,SplineFont *new) {
899 : int i, j, pos;
900 : CharView *cv, *cvnext;
901 : SplineFont *sub;
902 :
903 0 : for ( i=0; i<old->glyphcnt; ++i ) {
904 0 : if ( old->glyphs[i]!=NULL && old->glyphs[i]->views!=NULL ) {
905 0 : if ( new->subfontcnt==0 ) {
906 0 : pos = SFFindExistingSlot(new,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
907 0 : sub = new;
908 : } else {
909 0 : pos = -1;
910 0 : for ( j=0; j<new->subfontcnt && pos==-1 ; ++j ) {
911 0 : sub = new->subfonts[j];
912 0 : pos = SFFindExistingSlot(sub,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
913 : }
914 : }
915 0 : if ( pos==-1 ) {
916 0 : for ( cv=(CharView *) (old->glyphs[i]->views); cv!=NULL; cv = cvnext ) {
917 0 : cvnext = (CharView *) (cv->b.next);
918 0 : GDrawDestroyWindow(cv->gw);
919 : }
920 : } else {
921 0 : for ( cv=(CharView *) (old->glyphs[i]->views); cv!=NULL; cv = cvnext ) {
922 0 : cvnext = (CharView *) (cv->b.next);
923 0 : CVChangeSC(cv,sub->glyphs[pos]);
924 0 : cv->b.layerheads[dm_grid] = &new->grid;
925 : }
926 : }
927 0 : GDrawProcessPendingEvents(NULL); /* Don't want to many destroy_notify events clogging up the queue */
928 : }
929 : }
930 0 : }
931 :
932 0 : static void FVMenuRevert(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
933 0 : FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
934 0 : FVRevert(fv);
935 0 : }
936 :
937 0 : static void FVMenuRevertBackup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
938 0 : FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
939 0 : FVRevertBackup(fv);
940 0 : }
941 :
942 0 : static void FVMenuRevertGlyph(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
943 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
944 0 : FVRevertGlyph((FontViewBase *) fv);
945 0 : }
946 :
947 0 : static void FVMenuClearSpecialData(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
948 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
949 0 : FVClearSpecialData((FontViewBase *) fv);
950 0 : }
951 :
952 0 : void MenuPrefs(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
953 0 : DoPrefs();
954 0 : }
955 :
956 0 : void MenuXRes(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
957 0 : DoXRes();
958 0 : }
959 :
960 0 : void MenuSaveAll(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
961 : FontView *fv;
962 :
963 0 : for ( fv = fv_list; fv!=NULL; fv = (FontView *) (fv->b.next) ) {
964 0 : if ( SFAnyChanged(fv->b.sf) && !_FVMenuSave(fv))
965 0 : return;
966 : }
967 : }
968 :
969 0 : static void _MenuExit(void *UNUSED(junk)) {
970 :
971 : FontView *fv, *next;
972 :
973 0 : if( collabclient_haveLocalServer() )
974 : {
975 0 : AskAndMaybeCloseLocalCollabServers();
976 : }
977 : #ifndef _NO_PYTHON
978 0 : python_call_onClosingFunctions();
979 : #endif
980 :
981 0 : LastFonts_Save();
982 0 : for ( fv = fv_list; fv!=NULL; fv = next )
983 : {
984 0 : next = (FontView *) (fv->b.next);
985 0 : if ( !_FVMenuClose(fv))
986 0 : return;
987 0 : if ( fv->b.nextsame!=NULL || fv->b.sf->fv!=&fv->b )
988 : {
989 0 : GDrawSync(NULL);
990 0 : GDrawProcessPendingEvents(NULL);
991 : }
992 : }
993 0 : GDrawSync(NULL);
994 0 : GDrawProcessPendingEvents(NULL);
995 0 : exit(0);
996 : }
997 :
998 0 : static void FVMenuExit(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
999 0 : _MenuExit(NULL);
1000 0 : }
1001 :
1002 0 : void MenuExit(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *e) {
1003 0 : if ( e==NULL ) /* Not from the menu directly, but a shortcut */
1004 0 : _MenuExit(NULL);
1005 : else
1006 0 : DelayEvent(_MenuExit,NULL);
1007 0 : }
1008 :
1009 0 : char *GetPostScriptFontName(char *dir, int mult) {
1010 : unichar_t *ret;
1011 : char *u_dir;
1012 : char *temp;
1013 :
1014 0 : u_dir = def2utf8_copy(dir);
1015 0 : ret = FVOpenFont(_("Open Font"), u_dir,mult);
1016 0 : temp = u2def_copy(ret);
1017 :
1018 0 : free(ret);
1019 0 : return( temp );
1020 : }
1021 :
1022 0 : void MergeKernInfo(SplineFont *sf,EncMap *map) {
1023 : #ifndef __Mac
1024 : static char wild[] = "*.{afm,tfm,ofm,pfm,bin,hqx,dfont,feature,feat,fea}";
1025 : static char wild2[] = "*.{afm,amfm,tfm,ofm,pfm,bin,hqx,dfont,feature,feat,fea}";
1026 : #else
1027 : static char wild[] = "*"; /* Mac resource files generally don't have extensions */
1028 : static char wild2[] = "*";
1029 : #endif
1030 0 : char *ret = gwwv_open_filename(_("Merge Feature Info"),NULL,
1031 : sf->mm!=NULL?wild2:wild,NULL);
1032 : char *temp;
1033 :
1034 0 : if ( ret==NULL )
1035 0 : return; /* Cancelled */
1036 0 : temp = utf82def_copy(ret);
1037 :
1038 0 : if ( !LoadKerningDataFromMetricsFile(sf,temp,map))
1039 0 : ff_post_error(_("Load of Kerning Metrics Failed"),_("Failed to load kern data from %s"), temp);
1040 0 : free(ret); free(temp);
1041 : }
1042 :
1043 0 : static void FVMenuMergeKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1044 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1045 0 : MergeKernInfo(fv->b.sf,fv->b.map);
1046 0 : }
1047 :
1048 0 : void _FVMenuOpen(FontView *fv) {
1049 : char *temp;
1050 : char *eod, *fpt, *file, *full;
1051 : FontView *test; int fvcnt, fvtest;
1052 :
1053 0 : char* OpenDir = NULL, *DefaultDir = NULL, *NewDir = NULL;
1054 : #if defined(__MINGW32__)
1055 : DefaultDir = copy(GFileGetHomeDocumentsDir()); //Default value
1056 : if (fv && fv->b.sf && fv->b.sf->filename) {
1057 : free(DefaultDir);
1058 : DefaultDir = GFileDirNameEx(fv->b.sf->filename, true);
1059 : }
1060 : #endif
1061 :
1062 0 : for ( fvcnt=0, test=fv_list; test!=NULL; ++fvcnt, test=(FontView *) (test->b.next) );
1063 : do {
1064 0 : if (NewDir != NULL) {
1065 0 : if (OpenDir != DefaultDir) {
1066 0 : free(OpenDir);
1067 : }
1068 :
1069 0 : OpenDir = NewDir;
1070 0 : NewDir = NULL;
1071 0 : } else if (OpenDir != DefaultDir) {
1072 0 : free(OpenDir);
1073 0 : OpenDir = DefaultDir;
1074 : }
1075 :
1076 0 : temp = GetPostScriptFontName(OpenDir,true);
1077 0 : if ( temp==NULL )
1078 0 : return;
1079 :
1080 : //Make a copy of the folder; may be needed later if opening fails.
1081 0 : NewDir = GFileDirName(temp);
1082 0 : if (!GFileExists(NewDir)) {
1083 0 : free(NewDir);
1084 0 : NewDir = NULL;
1085 : }
1086 :
1087 0 : eod = strrchr(temp,'/');
1088 0 : if (eod != NULL) {
1089 0 : *eod = '\0';
1090 0 : file = eod+1;
1091 :
1092 0 : if (*file) {
1093 : do {
1094 0 : fpt = strstr(file,"; ");
1095 0 : if ( fpt!=NULL ) *fpt = '\0';
1096 0 : full = malloc(strlen(temp)+1+strlen(file)+1);
1097 0 : strcpy(full,temp); strcat(full,"/"); strcat(full,file);
1098 0 : ViewPostScriptFont(full,0);
1099 0 : file = fpt+2;
1100 0 : free(full);
1101 0 : } while ( fpt!=NULL );
1102 : }
1103 : }
1104 0 : free(temp);
1105 0 : for ( fvtest=0, test=fv_list; test!=NULL; ++fvtest, test=(FontView *) (test->b.next) );
1106 0 : } while ( fvtest==fvcnt ); /* did the load fail for some reason? try again */
1107 :
1108 0 : free( NewDir );
1109 0 : free( OpenDir );
1110 0 : if (OpenDir != DefaultDir) {
1111 0 : free( DefaultDir );
1112 : }
1113 : }
1114 :
1115 0 : static void FVMenuOpen(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1116 0 : FontView *fv = (FontView*) GDrawGetUserData(gw);
1117 0 : _FVMenuOpen(fv);
1118 0 : }
1119 :
1120 0 : static void FVMenuContextualHelp(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1121 0 : help("fontview.html");
1122 0 : }
1123 :
1124 0 : void MenuHelp(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1125 0 : help("overview.html");
1126 0 : }
1127 :
1128 0 : void MenuIndex(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1129 0 : help("IndexFS.html");
1130 0 : }
1131 :
1132 0 : void MenuLicense(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1133 0 : help("license.html");
1134 0 : }
1135 :
1136 0 : void MenuAbout(GWindow UNUSED(base), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1137 0 : ShowAboutScreen();
1138 0 : }
1139 :
1140 0 : static void FVMenuImport(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1141 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1142 0 : int empty = fv->b.sf->onlybitmaps && fv->b.sf->bitmaps==NULL;
1143 : BDFFont *bdf;
1144 0 : FVImport(fv);
1145 0 : if ( empty && fv->b.sf->bitmaps!=NULL ) {
1146 0 : for ( bdf= fv->b.sf->bitmaps; bdf->next!=NULL; bdf = bdf->next );
1147 0 : FVChangeDisplayBitmap((FontViewBase *) fv,bdf);
1148 : }
1149 0 : }
1150 :
1151 0 : static int FVSelCount(FontView *fv) {
1152 0 : int i, cnt=0;
1153 :
1154 0 : for ( i=0; i<fv->b.map->enccount; ++i )
1155 0 : if ( fv->b.selected[i] ) ++cnt;
1156 0 : if ( cnt>10 ) {
1157 : char *buts[3];
1158 0 : buts[0] = _("_OK");
1159 0 : buts[1] = _("_Cancel");
1160 0 : buts[2] = NULL;
1161 0 : if ( gwwv_ask(_("Many Windows"),(const char **) buts,0,1,_("This involves opening more than 10 windows.\nIs that really what you want?"))==1 )
1162 0 : return( false );
1163 : }
1164 0 : return( true );
1165 : }
1166 :
1167 0 : static void FVMenuOpenOutline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1168 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1169 : int i;
1170 : SplineChar *sc;
1171 :
1172 0 : if ( !FVSelCount(fv))
1173 0 : return;
1174 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1175 0 : return;
1176 :
1177 0 : for ( i=0; i<fv->b.map->enccount; ++i )
1178 0 : if ( fv->b.selected[i] ) {
1179 0 : sc = FVMakeChar(fv,i);
1180 0 : CharViewCreate(sc,fv,i);
1181 : }
1182 : }
1183 :
1184 0 : static void FVMenuOpenBitmap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1185 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1186 : int i;
1187 : SplineChar *sc;
1188 :
1189 0 : if ( fv->b.cidmaster==NULL ? (fv->b.sf->bitmaps==NULL) : (fv->b.cidmaster->bitmaps==NULL) )
1190 0 : return;
1191 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1192 0 : return;
1193 0 : if ( !FVSelCount(fv))
1194 0 : return;
1195 0 : for ( i=0; i<fv->b.map->enccount; ++i )
1196 0 : if ( fv->b.selected[i] ) {
1197 0 : sc = FVMakeChar(fv,i);
1198 0 : if ( sc!=NULL )
1199 0 : BitmapViewCreatePick(i,fv);
1200 : }
1201 : }
1202 :
1203 0 : void _MenuWarnings(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1204 0 : ShowErrorWindow();
1205 0 : }
1206 :
1207 0 : static void FVMenuOpenMetrics(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1208 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1209 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1210 0 : return;
1211 0 : MetricsViewCreate(fv,NULL,fv->filled==fv->show?NULL:fv->show);
1212 : }
1213 :
1214 0 : static void FVMenuPrint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1215 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1216 :
1217 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1218 0 : return;
1219 0 : PrintFFDlg(fv,NULL,NULL);
1220 : }
1221 :
1222 : #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
1223 0 : static void FVMenuExecute(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1224 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1225 :
1226 0 : ScriptDlg(fv,NULL);
1227 0 : }
1228 : #endif
1229 :
1230 0 : static void FVMenuFontInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1231 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1232 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
1233 0 : return;
1234 0 : FontMenuFontInfo(fv);
1235 : }
1236 :
1237 0 : static void FVMenuMATHInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1238 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1239 0 : SFMathDlg(fv->b.sf,fv->b.active_layer);
1240 0 : }
1241 :
1242 0 : static void FVMenuFindProblems(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1243 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1244 0 : FindProblems(fv,NULL,NULL);
1245 0 : }
1246 :
1247 0 : static void FVMenuValidate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1248 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1249 0 : SFValidationWindow(fv->b.sf,fv->b.active_layer,ff_none);
1250 0 : }
1251 :
1252 0 : static void FVMenuSetExtremumBound(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1253 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1254 : char buffer[40], *end, *ret;
1255 : int val;
1256 :
1257 0 : sprintf( buffer, "%d", fv->b.sf->extrema_bound<=0 ?
1258 0 : (int) rint((fv->b.sf->ascent+fv->b.sf->descent)/100.0) :
1259 0 : fv->b.sf->extrema_bound );
1260 0 : 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."));
1261 0 : if ( ret==NULL )
1262 0 : return;
1263 0 : val = (int) rint(strtod(ret,&end));
1264 0 : if ( *end!='\0' )
1265 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
1266 : else {
1267 0 : fv->b.sf->extrema_bound = val;
1268 0 : if ( !fv->b.sf->changed ) {
1269 0 : fv->b.sf->changed = true;
1270 0 : FVSetTitles(fv->b.sf);
1271 : }
1272 : }
1273 0 : free(ret);
1274 : }
1275 :
1276 0 : static void FVMenuEmbolden(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1277 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1278 0 : EmboldenDlg(fv,NULL);
1279 0 : }
1280 :
1281 0 : static void FVMenuItalic(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1282 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1283 0 : ItalicDlg(fv,NULL);
1284 0 : }
1285 :
1286 0 : static void FVMenuSmallCaps(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1287 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1288 0 : GlyphChangeDlg(fv,NULL,gc_smallcaps);
1289 0 : }
1290 :
1291 0 : static void FVMenuChangeXHeight(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1292 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1293 0 : ChangeXHeightDlg(fv,NULL);
1294 0 : }
1295 :
1296 0 : static void FVMenuChangeGlyph(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1297 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1298 0 : GlyphChangeDlg(fv,NULL,gc_generic);
1299 0 : }
1300 :
1301 0 : static void FVMenuSubSup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1302 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1303 0 : GlyphChangeDlg(fv,NULL,gc_subsuper);
1304 0 : }
1305 :
1306 0 : static void FVMenuOblique(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1307 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1308 0 : ObliqueDlg(fv,NULL);
1309 0 : }
1310 :
1311 0 : static void FVMenuCondense(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1312 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1313 0 : CondenseExtendDlg(fv,NULL);
1314 0 : }
1315 :
1316 : #define MID_24 2001
1317 : #define MID_36 2002
1318 : #define MID_48 2004
1319 : #define MID_72 2014
1320 : #define MID_96 2015
1321 : #define MID_128 2018
1322 : #define MID_AntiAlias 2005
1323 : #define MID_Next 2006
1324 : #define MID_Prev 2007
1325 : #define MID_NextDef 2012
1326 : #define MID_PrevDef 2013
1327 : #define MID_ShowHMetrics 2016
1328 : #define MID_ShowVMetrics 2017
1329 : #define MID_Ligatures 2020
1330 : #define MID_KernPairs 2021
1331 : #define MID_AnchorPairs 2022
1332 : #define MID_FitToBbox 2023
1333 : #define MID_DisplaySubs 2024
1334 : #define MID_32x8 2025
1335 : #define MID_16x4 2026
1336 : #define MID_8x2 2027
1337 : #define MID_BitmapMag 2028
1338 : #define MID_Layers 2029
1339 : #define MID_FontInfo 2200
1340 : #define MID_CharInfo 2201
1341 : #define MID_Transform 2202
1342 : #define MID_Stroke 2203
1343 : #define MID_RmOverlap 2204
1344 : #define MID_Simplify 2205
1345 : #define MID_Correct 2206
1346 : #define MID_BuildAccent 2208
1347 : #define MID_AvailBitmaps 2210
1348 : #define MID_RegenBitmaps 2211
1349 : #define MID_Autotrace 2212
1350 : #define MID_Round 2213
1351 : #define MID_MergeFonts 2214
1352 : #define MID_InterpolateFonts 2215
1353 : #define MID_FindProblems 2216
1354 : #define MID_Embolden 2217
1355 : #define MID_Condense 2218
1356 : #define MID_ShowDependentRefs 2222
1357 : #define MID_AddExtrema 2224
1358 : #define MID_CleanupGlyph 2225
1359 : #define MID_TilePath 2226
1360 : #define MID_BuildComposite 2227
1361 : #define MID_NLTransform 2228
1362 : #define MID_Intersection 2229
1363 : #define MID_FindInter 2230
1364 : #define MID_Styles 2231
1365 : #define MID_SimplifyMore 2233
1366 : #define MID_ShowDependentSubs 2234
1367 : #define MID_DefaultATT 2235
1368 : #define MID_POV 2236
1369 : #define MID_BuildDuplicates 2237
1370 : #define MID_StrikeInfo 2238
1371 : #define MID_FontCompare 2239
1372 : #define MID_CanonicalStart 2242
1373 : #define MID_CanonicalContours 2243
1374 : #define MID_RemoveBitmaps 2244
1375 : #define MID_Validate 2245
1376 : #define MID_MassRename 2246
1377 : #define MID_Italic 2247
1378 : #define MID_SmallCaps 2248
1379 : #define MID_SubSup 2249
1380 : #define MID_ChangeXHeight 2250
1381 : #define MID_ChangeGlyph 2251
1382 : #define MID_SetColor 2252
1383 : #define MID_SetExtremumBound 2253
1384 : #define MID_Center 2600
1385 : #define MID_Thirds 2601
1386 : #define MID_SetWidth 2602
1387 : #define MID_SetLBearing 2603
1388 : #define MID_SetRBearing 2604
1389 : #define MID_SetVWidth 2605
1390 : #define MID_RmHKern 2606
1391 : #define MID_RmVKern 2607
1392 : #define MID_VKernByClass 2608
1393 : #define MID_VKernFromH 2609
1394 : #define MID_SetBearings 2610
1395 : #define MID_AutoHint 2501
1396 : #define MID_ClearHints 2502
1397 : #define MID_ClearWidthMD 2503
1398 : #define MID_AutoInstr 2504
1399 : #define MID_EditInstructions 2505
1400 : #define MID_Editfpgm 2506
1401 : #define MID_Editprep 2507
1402 : #define MID_ClearInstrs 2508
1403 : #define MID_HStemHist 2509
1404 : #define MID_VStemHist 2510
1405 : #define MID_BlueValuesHist 2511
1406 : #define MID_Editcvt 2512
1407 : #define MID_HintSubsPt 2513
1408 : #define MID_AutoCounter 2514
1409 : #define MID_DontAutoHint 2515
1410 : #define MID_RmInstrTables 2516
1411 : #define MID_Editmaxp 2517
1412 : #define MID_Deltas 2518
1413 : #define MID_OpenBitmap 2700
1414 : #define MID_OpenOutline 2701
1415 : #define MID_Revert 2702
1416 : #define MID_Recent 2703
1417 : #define MID_Print 2704
1418 : #define MID_ScriptMenu 2705
1419 : #define MID_RevertGlyph 2707
1420 : #define MID_RevertToBackup 2708
1421 : #define MID_GenerateTTC 2709
1422 : #define MID_OpenMetrics 2710
1423 : #define MID_ClearSpecialData 2711
1424 : #define MID_Cut 2101
1425 : #define MID_Copy 2102
1426 : #define MID_Paste 2103
1427 : #define MID_Clear 2104
1428 : #define MID_SelAll 2106
1429 : #define MID_CopyRef 2107
1430 : #define MID_UnlinkRef 2108
1431 : #define MID_Undo 2109
1432 : #define MID_Redo 2110
1433 : #define MID_CopyWidth 2111
1434 : #define MID_UndoFontLevel 2112
1435 : #define MID_AllFonts 2122
1436 : #define MID_DisplayedFont 2123
1437 : #define MID_CharName 2124
1438 : #define MID_RemoveUndoes 2114
1439 : #define MID_CopyFgToBg 2115
1440 : #define MID_ClearBackground 2116
1441 : #define MID_CopyLBearing 2125
1442 : #define MID_CopyRBearing 2126
1443 : #define MID_CopyVWidth 2127
1444 : #define MID_Join 2128
1445 : #define MID_PasteInto 2129
1446 : #define MID_SameGlyphAs 2130
1447 : #define MID_RplRef 2131
1448 : #define MID_PasteAfter 2132
1449 : #define MID_TTFInstr 2134
1450 : #define MID_CopyLookupData 2135
1451 : #define MID_CopyL2L 2136
1452 : #define MID_CorrectRefs 2137
1453 : #define MID_Convert2CID 2800
1454 : #define MID_Flatten 2801
1455 : #define MID_InsertFont 2802
1456 : #define MID_InsertBlank 2803
1457 : #define MID_CIDFontInfo 2804
1458 : #define MID_RemoveFromCID 2805
1459 : #define MID_ConvertByCMap 2806
1460 : #define MID_FlattenByCMap 2807
1461 : #define MID_ChangeSupplement 2808
1462 : #define MID_Reencode 2830
1463 : #define MID_ForceReencode 2831
1464 : #define MID_AddUnencoded 2832
1465 : #define MID_RemoveUnused 2833
1466 : #define MID_DetachGlyphs 2834
1467 : #define MID_DetachAndRemoveGlyphs 2835
1468 : #define MID_LoadEncoding 2836
1469 : #define MID_MakeFromFont 2837
1470 : #define MID_RemoveEncoding 2838
1471 : #define MID_DisplayByGroups 2839
1472 : #define MID_Compact 2840
1473 : #define MID_SaveNamelist 2841
1474 : #define MID_RenameGlyphs 2842
1475 : #define MID_NameGlyphs 2843
1476 : #define MID_HideNoGlyphSlots 2844
1477 : #define MID_CreateMM 2900
1478 : #define MID_MMInfo 2901
1479 : #define MID_MMValid 2902
1480 : #define MID_ChangeMMBlend 2903
1481 : #define MID_BlendToNew 2904
1482 : #define MID_ModifyComposition 20902
1483 : #define MID_BuildSyllables 20903
1484 : #define MID_CollabStart 22000
1485 : #define MID_CollabConnect 22001
1486 : #define MID_CollabDisconnect 22002
1487 : #define MID_CollabCloseLocalServer 22003
1488 : #define MID_CollabConnectToExplicitAddress 22004
1489 :
1490 :
1491 : #define MID_Warnings 3000
1492 :
1493 :
1494 : /* returns -1 if nothing selected, if exactly one char return it, -2 if more than one */
1495 0 : static int FVAnyCharSelected(FontView *fv) {
1496 0 : int i, val=-1;
1497 :
1498 0 : for ( i=0; i<fv->b.map->enccount; ++i ) {
1499 0 : if ( fv->b.selected[i]) {
1500 0 : if ( val==-1 )
1501 0 : val = i;
1502 : else
1503 0 : return( -2 );
1504 : }
1505 : }
1506 0 : return( val );
1507 : }
1508 :
1509 0 : static int FVAllSelected(FontView *fv) {
1510 0 : int i, any = false;
1511 : /* Is everything real selected? */
1512 :
1513 0 : for ( i=0; i<fv->b.sf->glyphcnt; ++i ) if ( SCWorthOutputting(fv->b.sf->glyphs[i])) {
1514 0 : if ( !fv->b.selected[fv->b.map->backmap[i]] )
1515 0 : return( false );
1516 0 : any = true;
1517 : }
1518 0 : return( any );
1519 : }
1520 :
1521 0 : static void FVMenuCopyFrom(GWindow UNUSED(gw), struct gmenuitem *mi, GEvent *UNUSED(e)) {
1522 : /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
1523 :
1524 0 : if ( mi->mid==MID_CharName )
1525 0 : copymetadata = !copymetadata;
1526 0 : else if ( mi->mid==MID_TTFInstr )
1527 0 : copyttfinstr = !copyttfinstr;
1528 : else
1529 0 : onlycopydisplayed = (mi->mid==MID_DisplayedFont);
1530 0 : SavePrefs(true);
1531 0 : }
1532 :
1533 0 : static void FVMenuCopy(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1534 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1535 0 : if ( FVAnyCharSelected(fv)==-1 )
1536 0 : return;
1537 0 : FVCopy((FontViewBase *) fv,ct_fullcopy);
1538 : }
1539 :
1540 0 : static void FVMenuCopyLookupData(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1541 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1542 0 : if ( FVAnyCharSelected(fv)==-1 )
1543 0 : return;
1544 0 : FVCopy((FontViewBase *) fv,ct_lookups);
1545 : }
1546 :
1547 0 : static void FVMenuCopyRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1548 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1549 0 : if ( FVAnyCharSelected(fv)==-1 )
1550 0 : return;
1551 0 : FVCopy((FontViewBase *) fv,ct_reference);
1552 : }
1553 :
1554 0 : static void FVMenuCopyWidth(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
1555 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1556 :
1557 0 : if ( FVAnyCharSelected(fv)==-1 )
1558 0 : return;
1559 0 : if ( mi->mid==MID_CopyVWidth && !fv->b.sf->hasvmetrics )
1560 0 : return;
1561 0 : FVCopyWidth((FontViewBase *) fv,
1562 0 : mi->mid==MID_CopyWidth?ut_width:
1563 0 : mi->mid==MID_CopyVWidth?ut_vwidth:
1564 0 : mi->mid==MID_CopyLBearing?ut_lbearing:
1565 : ut_rbearing);
1566 : }
1567 :
1568 0 : static void FVMenuPaste(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1569 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1570 0 : if ( FVAnyCharSelected(fv)==-1 )
1571 0 : return;
1572 0 : PasteIntoFV((FontViewBase *) fv,false,NULL);
1573 : }
1574 :
1575 0 : static void FVMenuPasteInto(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1576 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1577 0 : if ( FVAnyCharSelected(fv)==-1 )
1578 0 : return;
1579 0 : PasteIntoFV((FontViewBase *) fv,true,NULL);
1580 : }
1581 :
1582 0 : static void FVMenuPasteAfter(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1583 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1584 0 : int pos = FVAnyCharSelected(fv);
1585 0 : if ( pos<0 )
1586 0 : return;
1587 0 : PasteIntoFV(&fv->b,2,NULL);
1588 : }
1589 :
1590 0 : static void FVMenuSameGlyphAs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1591 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1592 0 : FVSameGlyphAs((FontViewBase *) fv);
1593 0 : GDrawRequestExpose(fv->v,NULL,false);
1594 0 : }
1595 :
1596 0 : static void FVMenuCopyFgBg(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1597 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1598 0 : FVCopyFgtoBg( (FontViewBase *) fv );
1599 0 : }
1600 :
1601 0 : static void FVMenuCopyL2L(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1602 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1603 0 : FVCopyLayerToLayer( fv );
1604 0 : }
1605 :
1606 0 : static void FVMenuCompareL2L(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1607 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1608 0 : FVCompareLayerToLayer( fv );
1609 0 : }
1610 :
1611 0 : static void FVMenuClear(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1612 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1613 0 : FVClear( (FontViewBase *) fv );
1614 0 : }
1615 :
1616 0 : static void FVMenuClearBackground(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1617 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1618 0 : FVClearBackground( (FontViewBase *) fv );
1619 0 : }
1620 :
1621 0 : static void FVMenuJoin(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1622 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1623 0 : FVJoin( (FontViewBase *) fv );
1624 0 : }
1625 :
1626 0 : static void FVMenuUnlinkRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1627 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1628 0 : FVUnlinkRef( (FontViewBase *) fv );
1629 0 : }
1630 :
1631 0 : static void FVMenuRemoveUndoes(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1632 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1633 0 : SFRemoveUndoes(fv->b.sf,fv->b.selected,fv->b.map);
1634 0 : }
1635 :
1636 0 : static void FVMenuUndo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1637 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1638 0 : FVUndo((FontViewBase *) fv);
1639 0 : }
1640 :
1641 0 : static void FVMenuRedo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1642 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1643 0 : FVRedo((FontViewBase *) fv);
1644 0 : }
1645 :
1646 0 : static void FVMenuUndoFontLevel(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1647 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1648 0 : FontViewBase * fvb = (FontViewBase *) fv;
1649 0 : SplineFont *sf = fvb->sf;
1650 :
1651 0 : if( !sf->undoes )
1652 0 : return;
1653 :
1654 0 : struct sfundoes *undo = sf->undoes;
1655 0 : printf("font level undo msg:%s\n", undo->msg );
1656 0 : SFUndoPerform( undo, sf );
1657 0 : SFUndoRemoveAndFree( sf, undo );
1658 : }
1659 :
1660 0 : static void FVMenuCut(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1661 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1662 0 : FVCopy(&fv->b,ct_fullcopy);
1663 0 : FVClear(&fv->b);
1664 0 : }
1665 :
1666 0 : static void FVMenuSelectAll(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1667 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1668 :
1669 0 : FVSelectAll(fv);
1670 0 : }
1671 :
1672 0 : static void FVMenuInvertSelection(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1673 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1674 :
1675 0 : FVInvertSelection(fv);
1676 0 : }
1677 :
1678 0 : static void FVMenuDeselectAll(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
1679 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
1680 :
1681 0 : FVDeselectAll(fv);
1682 0 : }
1683 :
1684 : enum merge_type { mt_set=0, mt_merge=4, mt_or=mt_merge, mt_restrict=8, mt_and=12 };
1685 : /* Index array by merge_type(*4) + selection*2 + doit */
1686 : const uint8 mergefunc[] = {
1687 : /* mt_set */
1688 : 0, 1,
1689 : 0, 1,
1690 : /* mt_merge */
1691 : 0, 1,
1692 : 1, 1,
1693 : /* mt_restrict */
1694 : 0, 0,
1695 : 1, 0,
1696 : /* mt_and */
1697 : 0, 0,
1698 : 0, 1,
1699 : };
1700 :
1701 0 : static enum merge_type SelMergeType(GEvent *e) {
1702 0 : if ( e->type!=et_mouseup )
1703 0 : return( mt_set );
1704 :
1705 0 : return( ((e->u.mouse.state&ksm_shift)?mt_merge:0) |
1706 0 : ((e->u.mouse.state&ksm_control)?mt_restrict:0) );
1707 : }
1708 :
1709 0 : static char *SubMatch(char *pattern, char *eop, char *name,int ignorecase) {
1710 : char ch, *ppt, *npt, *ept, *eon;
1711 :
1712 0 : while ( pattern<eop && ( ch = *pattern)!='\0' ) {
1713 0 : if ( ch=='*' ) {
1714 0 : if ( pattern[1]=='\0' )
1715 0 : return( name+strlen(name));
1716 0 : for ( npt=name; ; ++npt ) {
1717 0 : if ( (eon = SubMatch(pattern+1,eop,npt,ignorecase))!= NULL )
1718 0 : return( eon );
1719 0 : if ( *npt=='\0' )
1720 0 : return( NULL );
1721 0 : }
1722 0 : } else if ( ch=='?' ) {
1723 0 : if ( *name=='\0' )
1724 0 : return( NULL );
1725 0 : ++name;
1726 0 : } else if ( ch=='[' ) {
1727 : /* [<char>...] matches the chars
1728 : * [<char>-<char>...] matches any char within the range (inclusive)
1729 : * the above may be concattenated and the resultant pattern matches
1730 : * anything thing which matches any of them.
1731 : * [^<char>...] matches any char which does not match the rest of
1732 : * the pattern
1733 : * []...] as a special case a ']' immediately after the '[' matches
1734 : * itself and does not end the pattern
1735 : */
1736 0 : int found = 0, not=0;
1737 0 : ++pattern;
1738 0 : if ( pattern[0]=='^' ) { not = 1; ++pattern; }
1739 0 : for ( ppt = pattern; (ppt!=pattern || *ppt!=']') && *ppt!='\0' ; ++ppt ) {
1740 0 : ch = *ppt;
1741 0 : if ( ppt[1]=='-' && ppt[2]!=']' && ppt[2]!='\0' ) {
1742 0 : char ch2 = ppt[2];
1743 0 : if ( (*name>=ch && *name<=ch2) ||
1744 0 : (ignorecase && islower(ch) && islower(ch2) &&
1745 0 : *name>=toupper(ch) && *name<=toupper(ch2)) ||
1746 0 : (ignorecase && isupper(ch) && isupper(ch2) &&
1747 0 : *name>=tolower(ch) && *name<=tolower(ch2))) {
1748 0 : if ( !not ) {
1749 0 : found = 1;
1750 0 : break;
1751 : }
1752 : } else {
1753 0 : if ( not ) {
1754 0 : found = 1;
1755 0 : break;
1756 : }
1757 : }
1758 0 : ppt += 2;
1759 0 : } else if ( ch==*name || (ignorecase && tolower(ch)==tolower(*name)) ) {
1760 0 : if ( !not ) {
1761 0 : found = 1;
1762 0 : break;
1763 : }
1764 : } else {
1765 0 : if ( not ) {
1766 0 : found = 1;
1767 0 : break;
1768 : }
1769 : }
1770 : }
1771 0 : if ( !found )
1772 0 : return( NULL );
1773 0 : while ( *ppt!=']' && *ppt!='\0' ) ++ppt;
1774 0 : pattern = ppt;
1775 0 : ++name;
1776 0 : } else if ( ch=='{' ) {
1777 : /* matches any of a comma separated list of substrings */
1778 0 : for ( ppt = pattern+1; *ppt!='\0' ; ppt = ept ) {
1779 0 : for ( ept=ppt; *ept!='}' && *ept!=',' && *ept!='\0'; ++ept );
1780 0 : npt = SubMatch(ppt,ept,name,ignorecase);
1781 0 : if ( npt!=NULL ) {
1782 0 : char *ecurly = ept;
1783 0 : while ( *ecurly!='}' && ecurly<eop && *ecurly!='\0' ) ++ecurly;
1784 0 : if ( (eon=SubMatch(ecurly+1,eop,npt,ignorecase))!=NULL )
1785 0 : return( eon );
1786 : }
1787 0 : if ( *ept=='}' )
1788 0 : return( NULL );
1789 0 : if ( *ept==',' ) ++ept;
1790 : }
1791 0 : } else if ( ch==*name ) {
1792 0 : ++name;
1793 0 : } else if ( ignorecase && tolower(ch)==tolower(*name)) {
1794 0 : ++name;
1795 : } else
1796 0 : return( NULL );
1797 0 : ++pattern;
1798 : }
1799 0 : return( name );
1800 : }
1801 :
1802 : /* Handles *?{}[] wildcards */
1803 0 : static int WildMatch(char *pattern, char *name,int ignorecase) {
1804 0 : char *eop = pattern + strlen(pattern);
1805 :
1806 0 : if ( pattern==NULL )
1807 0 : return( true );
1808 :
1809 0 : name = SubMatch(pattern,eop,name,ignorecase);
1810 0 : if ( name==NULL )
1811 0 : return( false );
1812 0 : if ( *name=='\0' )
1813 0 : return( true );
1814 :
1815 0 : return( false );
1816 : }
1817 :
1818 0 : static int SS_ScriptChanged(GGadget *g, GEvent *e) {
1819 :
1820 0 : if ( e->type==et_controlevent && e->u.control.subtype != et_textfocuschanged ) {
1821 0 : char *txt = GGadgetGetTitle8(g);
1822 : char buf[8];
1823 : int i;
1824 : extern GTextInfo scripts[];
1825 :
1826 0 : for ( i=0; scripts[i].text!=NULL; ++i ) {
1827 0 : if ( strcmp((char *) scripts[i].text,txt)==0 )
1828 0 : break;
1829 : }
1830 0 : free(txt);
1831 0 : if ( scripts[i].text==NULL )
1832 0 : return( true );
1833 0 : buf[0] = ((intpt) scripts[i].userdata)>>24;
1834 0 : buf[1] = ((intpt) scripts[i].userdata)>>16;
1835 0 : buf[2] = ((intpt) scripts[i].userdata)>>8 ;
1836 0 : buf[3] = ((intpt) scripts[i].userdata) ;
1837 0 : buf[4] = 0;
1838 0 : GGadgetSetTitle8(g,buf);
1839 : }
1840 0 : return( true );
1841 : }
1842 :
1843 0 : static int SS_OK(GGadget *g, GEvent *e) {
1844 :
1845 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1846 0 : int *done = GDrawGetUserData(GGadgetGetWindow(g));
1847 0 : *done = 2;
1848 : }
1849 0 : return( true );
1850 : }
1851 :
1852 0 : static int SS_Cancel(GGadget *g, GEvent *e) {
1853 :
1854 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1855 0 : int *done = GDrawGetUserData(GGadgetGetWindow(g));
1856 0 : *done = true;
1857 : }
1858 0 : return( true );
1859 : }
1860 :
1861 0 : static int ss_e_h(GWindow gw, GEvent *event) {
1862 0 : int *done = GDrawGetUserData(gw);
1863 :
1864 0 : switch ( event->type ) {
1865 : case et_char:
1866 0 : return( false );
1867 : case et_close:
1868 0 : *done = true;
1869 0 : break;
1870 : }
1871 0 : return( true );
1872 : }
1873 :
1874 0 : static void FVSelectByScript(FontView *fv,int merge) {
1875 : int j, gid;
1876 : SplineChar *sc;
1877 0 : EncMap *map = fv->b.map;
1878 0 : SplineFont *sf = fv->b.sf;
1879 : extern GTextInfo scripts[];
1880 : GRect pos;
1881 : GWindow gw;
1882 : GWindowAttrs wattrs;
1883 : GGadgetCreateData gcd[10], *hvarray[21][2], *barray[8], boxes[3];
1884 : GTextInfo label[10];
1885 : int i,k;
1886 0 : int done = 0, doit;
1887 : char tagbuf[4];
1888 : uint32 tag;
1889 : const unichar_t *ret;
1890 : int lc_k, uc_k, select_k;
1891 0 : int only_uc=0, only_lc=0;
1892 :
1893 0 : LookupUIInit();
1894 :
1895 0 : memset(&wattrs,0,sizeof(wattrs));
1896 0 : memset(&gcd,0,sizeof(gcd));
1897 0 : memset(&label,0,sizeof(label));
1898 0 : memset(&boxes,0,sizeof(boxes));
1899 :
1900 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1901 0 : wattrs.event_masks = ~(1<<et_charup);
1902 0 : wattrs.restrict_input_to_me = false;
1903 0 : wattrs.is_dlg = 1;
1904 0 : wattrs.undercursor = 1;
1905 0 : wattrs.cursor = ct_pointer;
1906 0 : wattrs.utf8_window_title = _("Select by Script");
1907 0 : wattrs.is_dlg = true;
1908 0 : pos.x = pos.y = 0;
1909 0 : pos.width = 100;
1910 0 : pos.height = 100;
1911 0 : gw = GDrawCreateTopWindow(NULL,&pos,ss_e_h,&done,&wattrs);
1912 :
1913 0 : k = i = 0;
1914 :
1915 0 : gcd[k].gd.flags = gg_visible|gg_enabled ;
1916 0 : gcd[k].gd.u.list = scripts;
1917 0 : gcd[k].gd.handle_controlevent = SS_ScriptChanged;
1918 0 : gcd[k++].creator = GListFieldCreate;
1919 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1920 :
1921 0 : label[k].text = (unichar_t *) _("All glyphs");
1922 0 : label[k].text_is_1byte = true;
1923 0 : gcd[k].gd.label = &label[k];
1924 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on;
1925 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the selection of the font view to all glyphs in the script.");
1926 0 : gcd[k++].creator = GRadioCreate;
1927 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1928 0 : hvarray[i][0] = GCD_HPad10; hvarray[i++][1] = NULL;
1929 :
1930 0 : uc_k = k;
1931 0 : label[k].text = (unichar_t *) _("Only upper case");
1932 0 : label[k].text_is_1byte = true;
1933 0 : gcd[k].gd.label = &label[k];
1934 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
1935 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the selection of the font view to any upper case glyphs in the script.");
1936 0 : gcd[k++].creator = GRadioCreate;
1937 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1938 :
1939 0 : lc_k = k;
1940 0 : label[k].text = (unichar_t *) _("Only lower case");
1941 0 : label[k].text_is_1byte = true;
1942 0 : gcd[k].gd.label = &label[k];
1943 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
1944 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the selection of the font view to any lower case glyphs in the script.");
1945 0 : gcd[k++].creator = GRadioCreate;
1946 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1947 0 : hvarray[i][0] = GCD_HPad10; hvarray[i++][1] = NULL;
1948 :
1949 0 : select_k = k;
1950 0 : label[k].text = (unichar_t *) _("Select Results");
1951 0 : label[k].text_is_1byte = true;
1952 0 : gcd[k].gd.label = &label[k];
1953 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_rad_startnew;
1954 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the selection of the font view to the glyphs\nwhich match");
1955 0 : gcd[k++].creator = GRadioCreate;
1956 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1957 :
1958 0 : label[k].text = (unichar_t *) _("Merge Results");
1959 0 : label[k].text_is_1byte = true;
1960 0 : gcd[k].gd.label = &label[k];
1961 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
1962 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Expand the selection of the font view to include\nall the glyphs which match");
1963 0 : gcd[k++].creator = GRadioCreate;
1964 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1965 :
1966 0 : label[k].text = (unichar_t *) _("Restrict Selection");
1967 0 : label[k].text_is_1byte = true;
1968 0 : gcd[k].gd.label = &label[k];
1969 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
1970 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Remove matching glyphs from the selection." );
1971 0 : gcd[k++].creator = GRadioCreate;
1972 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1973 :
1974 0 : label[k].text = (unichar_t *) _("Logical And with Selection");
1975 0 : label[k].text_is_1byte = true;
1976 0 : gcd[k].gd.label = &label[k];
1977 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
1978 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Remove glyphs which do not match from the selection." );
1979 0 : gcd[k++].creator = GRadioCreate;
1980 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
1981 0 : gcd[k-4 + merge/4].gd.flags |= gg_cb_on;
1982 :
1983 0 : hvarray[i][0] = GCD_Glue; hvarray[i++][1] = NULL;
1984 :
1985 0 : label[k].text = (unichar_t *) _("_OK");
1986 0 : label[k].text_is_1byte = true;
1987 0 : label[k].text_in_resource = true;
1988 0 : gcd[k].gd.label = &label[k];
1989 0 : gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_default;
1990 0 : gcd[k].gd.handle_controlevent = SS_OK;
1991 0 : gcd[k++].creator = GButtonCreate;
1992 :
1993 0 : label[k].text = (unichar_t *) _("_Cancel");
1994 0 : label[k].text_is_1byte = true;
1995 0 : label[k].text_in_resource = true;
1996 0 : gcd[k].gd.label = &label[k];
1997 0 : gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_cancel;
1998 0 : gcd[k].gd.handle_controlevent = SS_Cancel;
1999 0 : gcd[k++].creator = GButtonCreate;
2000 :
2001 0 : barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
2002 0 : barray[1] = &gcd[k-2]; barray[5] = &gcd[k-1];
2003 0 : hvarray[i][0] = &boxes[2]; hvarray[i++][1] = NULL;
2004 0 : hvarray[i][0] = NULL;
2005 :
2006 0 : memset(boxes,0,sizeof(boxes));
2007 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2008 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
2009 0 : boxes[0].gd.u.boxelements = hvarray[0];
2010 0 : boxes[0].creator = GHVGroupCreate;
2011 :
2012 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
2013 0 : boxes[2].gd.u.boxelements = barray;
2014 0 : boxes[2].creator = GHBoxCreate;
2015 :
2016 0 : GGadgetsCreate(gw,boxes);
2017 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
2018 0 : GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2019 :
2020 :
2021 0 : GHVBoxFitWindow(boxes[0].ret);
2022 :
2023 0 : GDrawSetVisible(gw,true);
2024 0 : ret = NULL;
2025 0 : while ( !done ) {
2026 0 : GDrawProcessOneEvent(NULL);
2027 0 : if ( done==2 ) {
2028 0 : ret = _GGadgetGetTitle(gcd[0].ret);
2029 0 : if ( *ret=='\0' ) {
2030 0 : ff_post_error(_("No Script"),_("Please specify a script"));
2031 0 : done = 0;
2032 0 : } else if ( u_strlen(ret)>4 ) {
2033 0 : ff_post_error(_("Bad Script"),_("Scripts are 4 letter tags"));
2034 0 : done = 0;
2035 : }
2036 : }
2037 : }
2038 0 : memset(tagbuf,' ',4);
2039 0 : if ( done==2 && ret!=NULL ) {
2040 0 : tagbuf[0] = *ret;
2041 0 : if ( ret[1]!='\0' ) {
2042 0 : tagbuf[1] = ret[1];
2043 0 : if ( ret[2]!='\0' ) {
2044 0 : tagbuf[2] = ret[2];
2045 0 : if ( ret[3]!='\0' )
2046 0 : tagbuf[3] = ret[3];
2047 : }
2048 : }
2049 : }
2050 0 : merge = GGadgetIsChecked(gcd[select_k+0].ret) ? mt_set :
2051 0 : GGadgetIsChecked(gcd[select_k+1].ret) ? mt_merge :
2052 0 : GGadgetIsChecked(gcd[select_k+2].ret) ? mt_restrict :
2053 : mt_and;
2054 0 : only_uc = GGadgetIsChecked(gcd[uc_k+0].ret);
2055 0 : only_lc = GGadgetIsChecked(gcd[lc_k+0].ret);
2056 :
2057 0 : GDrawDestroyWindow(gw);
2058 0 : if ( done==1 )
2059 0 : return;
2060 0 : tag = (tagbuf[0]<<24) | (tagbuf[1]<<16) | (tagbuf[2]<<8) | tagbuf[3];
2061 :
2062 0 : for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2063 0 : doit = ( SCScriptFromUnicode(sc)==tag );
2064 0 : if ( doit ) {
2065 0 : if ( only_uc && (sc->unicodeenc==-1 || sc->unicodeenc>0xffff ||
2066 0 : !isupper(sc->unicodeenc)) )
2067 0 : doit = false;
2068 0 : else if ( only_lc && (sc->unicodeenc==-1 || sc->unicodeenc>0xffff ||
2069 0 : !islower(sc->unicodeenc)) )
2070 0 : doit = false;
2071 : }
2072 0 : fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2073 0 : } else if ( merge==mt_set )
2074 0 : fv->b.selected[j] = false;
2075 :
2076 0 : GDrawRequestExpose(fv->v,NULL,false);
2077 : }
2078 :
2079 0 : static void FVMenuSelectByScript(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2080 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2081 :
2082 0 : FVSelectByScript(fv,SelMergeType(e));
2083 0 : }
2084 :
2085 0 : static void FVSelectColor(FontView *fv, uint32 col, int merge) {
2086 : int i, doit;
2087 : uint32 sccol;
2088 0 : SplineChar **glyphs = fv->b.sf->glyphs;
2089 :
2090 0 : for ( i=0; i<fv->b.map->enccount; ++i ) {
2091 0 : int gid = fv->b.map->map[i];
2092 0 : sccol = ( gid==-1 || glyphs[gid]==NULL ) ? COLOR_DEFAULT : glyphs[gid]->color;
2093 0 : doit = sccol==col;
2094 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2095 : }
2096 0 : GDrawRequestExpose(fv->v,NULL,false);
2097 0 : }
2098 :
2099 0 : static void FVMenuSelectColor(GWindow gw, struct gmenuitem *mi, GEvent *e) {
2100 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2101 0 : Color col = (Color) (intpt) (mi->ti.userdata);
2102 0 : if ( (intpt) mi->ti.userdata == (intpt) -10 ) {
2103 : struct hslrgb retcol, font_cols[6];
2104 0 : retcol = GWidgetColor(_("Pick a color"),NULL,SFFontCols(fv->b.sf,font_cols));
2105 0 : if ( !retcol.rgb )
2106 0 : return;
2107 0 : col = (((int) rint(255.*retcol.r))<<16 ) |
2108 0 : (((int) rint(255.*retcol.g))<<8 ) |
2109 0 : (((int) rint(255.*retcol.b)) );
2110 : }
2111 0 : FVSelectColor(fv,col,SelMergeType(e));
2112 : }
2113 :
2114 0 : static int FVSelectByName(FontView *fv, char *ret, int merge) {
2115 : int j, gid, doit;
2116 : char *end;
2117 : SplineChar *sc;
2118 0 : EncMap *map = fv->b.map;
2119 0 : SplineFont *sf = fv->b.sf;
2120 : struct altuni *alt;
2121 :
2122 0 : if ( !merge )
2123 0 : FVDeselectAll(fv);
2124 0 : if (( *ret=='0' && ( ret[1]=='x' || ret[1]=='X' )) ||
2125 0 : ((*ret=='u' || *ret=='U') && ret[1]=='+' )) {
2126 0 : int uni = (int) strtol(ret+2,&end,16);
2127 0 : int vs= -2;
2128 0 : if ( *end=='.' ) {
2129 0 : ++end;
2130 0 : if (( *end=='0' && ( end[1]=='x' || end[1]=='X' )) ||
2131 0 : ((*end=='u' || *end=='U') && end[1]=='+' ))
2132 0 : end += 2;
2133 0 : vs = (int) strtoul(end,&end,16);
2134 : }
2135 0 : if ( *end!='\0' || uni<0 || uni>=0x110000 ) {
2136 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
2137 0 : return( false );
2138 : }
2139 0 : for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2140 0 : if ( vs==-2 ) {
2141 0 : for ( alt=sc->altuni; alt!=NULL && (alt->unienc!=uni || alt->fid!=0); alt=alt->next );
2142 : } else {
2143 0 : for ( alt=sc->altuni; alt!=NULL && (alt->unienc!=uni || alt->vs!=vs || alt->fid!=0); alt=alt->next );
2144 : }
2145 0 : doit = (sc->unicodeenc == uni && vs<0) || alt!=NULL;
2146 0 : fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2147 0 : } else if ( merge==mt_set )
2148 0 : fv->b.selected[j] = false;
2149 : } else {
2150 0 : for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
2151 0 : doit = WildMatch(ret,sc->name,false);
2152 0 : fv->b.selected[j] = mergefunc[ merge + (fv->b.selected[j]?2:0) + doit ];
2153 0 : } else if ( merge==mt_set )
2154 0 : fv->b.selected[j] = false;
2155 : }
2156 0 : GDrawRequestExpose(fv->v,NULL,false);
2157 0 : fv->sel_index = 1;
2158 0 : return( true );
2159 : }
2160 :
2161 0 : static void FVMenuSelectByName(GWindow _gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2162 0 : FontView *fv = (FontView *) GDrawGetUserData(_gw);
2163 : GRect pos;
2164 : GWindow gw;
2165 : GWindowAttrs wattrs;
2166 : GGadgetCreateData gcd[8], *hvarray[12][2], *barray[8], boxes[3];
2167 : GTextInfo label[8];
2168 0 : int merge = SelMergeType(e);
2169 0 : int done=0,k,i;
2170 :
2171 0 : memset(&wattrs,0,sizeof(wattrs));
2172 0 : memset(&gcd,0,sizeof(gcd));
2173 0 : memset(&label,0,sizeof(label));
2174 0 : memset(&boxes,0,sizeof(boxes));
2175 :
2176 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2177 0 : wattrs.event_masks = ~(1<<et_charup);
2178 0 : wattrs.restrict_input_to_me = false;
2179 0 : wattrs.undercursor = 1;
2180 0 : wattrs.cursor = ct_pointer;
2181 0 : wattrs.utf8_window_title = _("Select by Name");
2182 0 : wattrs.is_dlg = false;
2183 0 : pos.x = pos.y = 0;
2184 0 : pos.width = 100;
2185 0 : pos.height = 100;
2186 0 : gw = GDrawCreateTopWindow(NULL,&pos,ss_e_h,&done,&wattrs);
2187 :
2188 0 : k = i = 0;
2189 :
2190 0 : label[k].text = (unichar_t *) _("Enter either a wildcard pattern (to match glyph names)\n or a unicode encoding like \"U+0065\".");
2191 0 : label[k].text_is_1byte = true;
2192 0 : gcd[k].gd.label = &label[k];
2193 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
2194 0 : gcd[k].gd.popup_msg = (unichar_t *) _(
2195 : "Unix style wildcarding is accepted:\n"
2196 : "Most characters match themselves\n"
2197 : "A \"?\" will match any single character\n"
2198 : "A \"*\" will match an arbitrary number of characters (including none)\n"
2199 : "An \"[abd]\" set of characters within square brackets will match any (single) character\n"
2200 : "A \"{scmp,c2sc}\" set of strings within curly brackets will match any string\n"
2201 : "So \"a.*\" would match \"a.\" or \"a.sc\" or \"a.swash\"\n"
2202 : "While \"a.{scmp,c2sc}\" would match \"a.scmp\" or \"a.c2sc\"\n"
2203 : "And \"a.[abd]\" would match \"a.a\" or \"a.b\" or \"a.d\"");
2204 0 : gcd[k++].creator = GLabelCreate;
2205 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2206 :
2207 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
2208 0 : gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg;
2209 0 : gcd[k++].creator = GTextFieldCreate;
2210 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2211 :
2212 0 : label[k].text = (unichar_t *) _("Select Results");
2213 0 : label[k].text_is_1byte = true;
2214 0 : gcd[k].gd.label = &label[k];
2215 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
2216 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the selection of the font view to the glyphs\nwhich match");
2217 0 : gcd[k++].creator = GRadioCreate;
2218 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2219 :
2220 0 : label[k].text = (unichar_t *) _("Merge Results");
2221 0 : label[k].text_is_1byte = true;
2222 0 : gcd[k].gd.label = &label[k];
2223 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
2224 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Expand the selection of the font view to include\nall the glyphs which match");
2225 0 : gcd[k++].creator = GRadioCreate;
2226 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2227 :
2228 0 : label[k].text = (unichar_t *) _("Restrict Selection");
2229 0 : label[k].text_is_1byte = true;
2230 0 : gcd[k].gd.label = &label[k];
2231 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
2232 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Remove matching glyphs from the selection." );
2233 0 : gcd[k++].creator = GRadioCreate;
2234 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2235 :
2236 0 : label[k].text = (unichar_t *) _("Logical And with Selection");
2237 0 : label[k].text_is_1byte = true;
2238 0 : gcd[k].gd.label = &label[k];
2239 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
2240 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Remove glyphs which do not match from the selection." );
2241 0 : gcd[k++].creator = GRadioCreate;
2242 0 : hvarray[i][0] = &gcd[k-1]; hvarray[i++][1] = NULL;
2243 0 : gcd[k-4 + merge/4].gd.flags |= gg_cb_on;
2244 :
2245 0 : hvarray[i][0] = GCD_Glue; hvarray[i++][1] = NULL;
2246 :
2247 0 : label[k].text = (unichar_t *) _("_OK");
2248 0 : label[k].text_is_1byte = true;
2249 0 : label[k].text_in_resource = true;
2250 0 : gcd[k].gd.label = &label[k];
2251 0 : gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_default;
2252 0 : gcd[k].gd.handle_controlevent = SS_OK;
2253 0 : gcd[k++].creator = GButtonCreate;
2254 :
2255 0 : label[k].text = (unichar_t *) _("_Cancel");
2256 0 : label[k].text_is_1byte = true;
2257 0 : label[k].text_in_resource = true;
2258 0 : gcd[k].gd.label = &label[k];
2259 0 : gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_cancel;
2260 0 : gcd[k].gd.handle_controlevent = SS_Cancel;
2261 0 : gcd[k++].creator = GButtonCreate;
2262 :
2263 0 : barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
2264 0 : barray[1] = &gcd[k-2]; barray[5] = &gcd[k-1];
2265 0 : hvarray[i][0] = &boxes[2]; hvarray[i++][1] = NULL;
2266 0 : hvarray[i][0] = NULL;
2267 :
2268 0 : memset(boxes,0,sizeof(boxes));
2269 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2270 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
2271 0 : boxes[0].gd.u.boxelements = hvarray[0];
2272 0 : boxes[0].creator = GHVGroupCreate;
2273 :
2274 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
2275 0 : boxes[2].gd.u.boxelements = barray;
2276 0 : boxes[2].creator = GHBoxCreate;
2277 :
2278 0 : GGadgetsCreate(gw,boxes);
2279 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
2280 0 : GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2281 :
2282 :
2283 0 : GHVBoxFitWindow(boxes[0].ret);
2284 :
2285 0 : GDrawSetVisible(gw,true);
2286 0 : while ( !done ) {
2287 0 : GDrawProcessOneEvent(NULL);
2288 0 : if ( done==2 ) {
2289 0 : char *str = GGadgetGetTitle8(gcd[1].ret);
2290 0 : int merge = GGadgetIsChecked(gcd[2].ret) ? mt_set :
2291 0 : GGadgetIsChecked(gcd[3].ret) ? mt_merge :
2292 0 : GGadgetIsChecked(gcd[4].ret) ? mt_restrict :
2293 : mt_and;
2294 0 : int ret = FVSelectByName(fv,str,merge);
2295 0 : free(str);
2296 0 : if ( !ret )
2297 0 : done = 0;
2298 : }
2299 : }
2300 0 : GDrawDestroyWindow(gw);
2301 0 : }
2302 :
2303 0 : static void FVMenuSelectWorthOutputting(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2304 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2305 : int i, gid, doit;
2306 0 : EncMap *map = fv->b.map;
2307 0 : SplineFont *sf = fv->b.sf;
2308 0 : int merge = SelMergeType(e);
2309 :
2310 0 : for ( i=0; i< map->enccount; ++i ) {
2311 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2312 0 : SCWorthOutputting(sf->glyphs[gid]) );
2313 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2314 : }
2315 0 : GDrawRequestExpose(fv->v,NULL,false);
2316 0 : }
2317 :
2318 0 : static void FVMenuGlyphsRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2319 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2320 : int i, gid, doit;
2321 0 : EncMap *map = fv->b.map;
2322 0 : SplineFont *sf = fv->b.sf;
2323 0 : int merge = SelMergeType(e);
2324 0 : int layer = fv->b.active_layer;
2325 :
2326 0 : for ( i=0; i< map->enccount; ++i ) {
2327 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2328 0 : sf->glyphs[gid]->layers[layer].refs!=NULL &&
2329 0 : sf->glyphs[gid]->layers[layer].splines==NULL );
2330 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2331 : }
2332 0 : GDrawRequestExpose(fv->v,NULL,false);
2333 0 : }
2334 :
2335 0 : static void FVMenuGlyphsSplines(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2336 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2337 : int i, gid, doit;
2338 0 : EncMap *map = fv->b.map;
2339 0 : SplineFont *sf = fv->b.sf;
2340 0 : int merge = SelMergeType(e);
2341 0 : int layer = fv->b.active_layer;
2342 :
2343 0 : for ( i=0; i< map->enccount; ++i ) {
2344 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2345 0 : sf->glyphs[gid]->layers[layer].refs==NULL &&
2346 0 : sf->glyphs[gid]->layers[layer].splines!=NULL );
2347 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2348 : }
2349 0 : GDrawRequestExpose(fv->v,NULL,false);
2350 0 : }
2351 :
2352 0 : static void FVMenuGlyphsBoth(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2353 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2354 : int i, gid, doit;
2355 0 : EncMap *map = fv->b.map;
2356 0 : SplineFont *sf = fv->b.sf;
2357 0 : int merge = SelMergeType(e);
2358 0 : int layer = fv->b.active_layer;
2359 :
2360 0 : for ( i=0; i< map->enccount; ++i ) {
2361 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2362 0 : sf->glyphs[gid]->layers[layer].refs!=NULL &&
2363 0 : sf->glyphs[gid]->layers[layer].splines!=NULL );
2364 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2365 : }
2366 0 : GDrawRequestExpose(fv->v,NULL,false);
2367 0 : }
2368 :
2369 0 : static void FVMenuGlyphsWhite(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2370 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2371 : int i, gid, doit;
2372 0 : EncMap *map = fv->b.map;
2373 0 : SplineFont *sf = fv->b.sf;
2374 0 : int merge = SelMergeType(e);
2375 0 : int layer = fv->b.active_layer;
2376 :
2377 0 : for ( i=0; i< map->enccount; ++i ) {
2378 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2379 0 : sf->glyphs[gid]->layers[layer].refs==NULL &&
2380 0 : sf->glyphs[gid]->layers[layer].splines==NULL );
2381 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2382 : }
2383 0 : GDrawRequestExpose(fv->v,NULL,false);
2384 0 : }
2385 :
2386 0 : static void FVMenuSelectChanged(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2387 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2388 : int i, gid, doit;
2389 0 : EncMap *map = fv->b.map;
2390 0 : SplineFont *sf = fv->b.sf;
2391 0 : int merge = SelMergeType(e);
2392 :
2393 0 : for ( i=0; i< map->enccount; ++i ) {
2394 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->changed );
2395 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2396 : }
2397 :
2398 0 : GDrawRequestExpose(fv->v,NULL,false);
2399 0 : }
2400 :
2401 0 : static void FVMenuSelectHintingNeeded(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2402 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2403 : int i, gid, doit;
2404 0 : EncMap *map = fv->b.map;
2405 0 : SplineFont *sf = fv->b.sf;
2406 0 : int order2 = sf->layers[fv->b.active_layer].order2;
2407 0 : int merge = SelMergeType(e);
2408 :
2409 0 : for ( i=0; i< map->enccount; ++i ) {
2410 0 : doit = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2411 0 : ((!order2 && sf->glyphs[gid]->changedsincelasthinted ) ||
2412 0 : ( order2 && sf->glyphs[gid]->layers[fv->b.active_layer].splines!=NULL &&
2413 0 : sf->glyphs[gid]->ttf_instrs_len<=0 ) ||
2414 0 : ( order2 && sf->glyphs[gid]->instructions_out_of_date )) );
2415 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2416 : }
2417 0 : GDrawRequestExpose(fv->v,NULL,false);
2418 0 : }
2419 :
2420 0 : static void FVMenuSelectAutohintable(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2421 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2422 : int i, gid, doit;
2423 0 : EncMap *map = fv->b.map;
2424 0 : SplineFont *sf = fv->b.sf;
2425 0 : int merge = SelMergeType(e);
2426 :
2427 0 : for ( i=0; i< map->enccount; ++i ) {
2428 0 : doit = (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
2429 0 : !sf->glyphs[gid]->manualhints;
2430 0 : fv->b.selected[i] = mergefunc[ merge + (fv->b.selected[i]?2:0) + doit ];
2431 : }
2432 0 : GDrawRequestExpose(fv->v,NULL,false);
2433 0 : }
2434 :
2435 0 : static void FVMenuSelectByPST(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2436 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2437 :
2438 0 : FVSelectByPST(fv);
2439 0 : }
2440 :
2441 0 : static void FVMenuFindRpl(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2442 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2443 :
2444 0 : SVCreate(fv);
2445 0 : }
2446 :
2447 0 : static void FVMenuReplaceWithRef(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2448 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2449 :
2450 0 : FVReplaceOutlineWithReference(fv,.001);
2451 0 : }
2452 :
2453 0 : static void FVMenuCorrectRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2454 0 : FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
2455 :
2456 0 : FVCorrectReferences(fv);
2457 0 : }
2458 :
2459 0 : static void FVMenuCharInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2460 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2461 0 : int pos = FVAnyCharSelected(fv);
2462 0 : if ( pos<0 )
2463 0 : return;
2464 0 : if ( fv->b.cidmaster!=NULL &&
2465 0 : (fv->b.map->map[pos]==-1 || fv->b.sf->glyphs[fv->b.map->map[pos]]==NULL ))
2466 0 : return;
2467 0 : SCCharInfo(SFMakeChar(fv->b.sf,fv->b.map,pos),fv->b.active_layer,fv->b.map,pos);
2468 : }
2469 :
2470 0 : static void FVMenuBDFInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2471 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2472 0 : if ( fv->b.sf->bitmaps==NULL )
2473 0 : return;
2474 0 : if ( fv->show!=fv->filled )
2475 0 : SFBdfProperties(fv->b.sf,fv->b.map,fv->show);
2476 : else
2477 0 : SFBdfProperties(fv->b.sf,fv->b.map,NULL);
2478 : }
2479 :
2480 0 : static void FVMenuBaseHoriz(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2481 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2482 0 : SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2483 0 : sf->horiz_base = SFBaselines(sf,sf->horiz_base,false);
2484 0 : SFBaseSort(sf);
2485 0 : }
2486 :
2487 0 : static void FVMenuBaseVert(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2488 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2489 0 : SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2490 0 : sf->vert_base = SFBaselines(sf,sf->vert_base,true);
2491 0 : SFBaseSort(sf);
2492 0 : }
2493 :
2494 0 : static void FVMenuJustify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2495 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2496 0 : SplineFont *sf = fv->b.cidmaster == NULL ? fv->b.sf : fv->b.cidmaster;
2497 0 : JustifyDlg(sf);
2498 0 : }
2499 :
2500 0 : static void FVMenuMassRename(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2501 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2502 0 : FVMassGlyphRename(fv);
2503 0 : }
2504 :
2505 0 : static void FVSetColor(FontView *fv, uint32 col) {
2506 : int i;
2507 :
2508 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
2509 0 : SplineChar *sc = SFMakeChar(fv->b.sf,fv->b.map,i);
2510 0 : sc->color = col;
2511 : }
2512 0 : GDrawRequestExpose(fv->v,NULL,false);
2513 0 : }
2514 :
2515 0 : static void FVMenuSetColor(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2516 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2517 0 : Color col = (Color) (intpt) (mi->ti.userdata);
2518 0 : if ( (intpt) mi->ti.userdata == (intpt) -10 ) {
2519 : struct hslrgb retcol, font_cols[6];
2520 0 : retcol = GWidgetColor(_("Pick a color"),NULL,SFFontCols(fv->b.sf,font_cols));
2521 0 : if ( !retcol.rgb )
2522 0 : return;
2523 0 : col = (((int) rint(255.*retcol.r))<<16 ) |
2524 0 : (((int) rint(255.*retcol.g))<<8 ) |
2525 0 : (((int) rint(255.*retcol.b)) );
2526 : }
2527 0 : FVSetColor(fv,col);
2528 : }
2529 :
2530 0 : static void FVMenuShowDependentRefs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2531 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2532 0 : int pos = FVAnyCharSelected(fv);
2533 : SplineChar *sc;
2534 :
2535 0 : if ( pos<0 || fv->b.map->map[pos]==-1 )
2536 0 : return;
2537 0 : sc = fv->b.sf->glyphs[fv->b.map->map[pos]];
2538 0 : if ( sc==NULL || sc->dependents==NULL )
2539 0 : return;
2540 0 : SCRefBy(sc);
2541 : }
2542 :
2543 0 : static void FVMenuShowDependentSubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2544 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2545 0 : int pos = FVAnyCharSelected(fv);
2546 : SplineChar *sc;
2547 :
2548 0 : if ( pos<0 || fv->b.map->map[pos]==-1 )
2549 0 : return;
2550 0 : sc = fv->b.sf->glyphs[fv->b.map->map[pos]];
2551 0 : if ( sc==NULL )
2552 0 : return;
2553 0 : SCSubBy(sc);
2554 : }
2555 :
2556 0 : static int getorigin(void *UNUSED(d), BasePoint *base, int index) {
2557 : /*FontView *fv = (FontView *) d;*/
2558 :
2559 0 : base->x = base->y = 0;
2560 0 : switch ( index ) {
2561 : case 0: /* Character origin */
2562 : /* all done */
2563 0 : break;
2564 : case 1: /* Center of selection */
2565 : /*CVFindCenter(cv,base,!CVAnySel(cv,NULL,NULL,NULL,NULL));*/
2566 0 : break;
2567 : default:
2568 0 : return( false );
2569 : }
2570 0 : return( true );
2571 : }
2572 :
2573 0 : static void FVDoTransform(FontView *fv) {
2574 0 : enum transdlg_flags flags=tdf_enableback|tdf_enablekerns;
2575 0 : if ( FVAnyCharSelected(fv)==-1 )
2576 0 : return;
2577 0 : if ( FVAllSelected(fv))
2578 0 : flags=tdf_enableback|tdf_enablekerns|tdf_defaultkerns;
2579 0 : TransformDlgCreate(fv,FVTransFunc,getorigin,flags,cvt_none);
2580 : }
2581 :
2582 0 : static void FVMenuTransform(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2583 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2584 0 : FVDoTransform(fv);
2585 0 : }
2586 :
2587 0 : static void FVMenuPOV(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2588 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2589 : struct pov_data pov_data;
2590 0 : if ( FVAnyCharSelected(fv)==-1 || fv->b.sf->onlybitmaps )
2591 0 : return;
2592 0 : if ( PointOfViewDlg(&pov_data,fv->b.sf,false)==-1 )
2593 0 : return;
2594 0 : FVPointOfView((FontViewBase *) fv,&pov_data);
2595 : }
2596 :
2597 0 : static void FVMenuNLTransform(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2598 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2599 0 : if ( FVAnyCharSelected(fv)==-1 )
2600 0 : return;
2601 0 : NonLinearDlg(fv,NULL);
2602 : }
2603 :
2604 0 : static void FVMenuBitmaps(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2605 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2606 0 : BitmapDlg(fv,NULL,mi->mid==MID_RemoveBitmaps?-1:(mi->mid==MID_AvailBitmaps) );
2607 0 : }
2608 :
2609 0 : static void FVMenuStroke(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2610 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2611 0 : FVStroke(fv);
2612 0 : }
2613 :
2614 : # ifdef FONTFORGE_CONFIG_TILEPATH
2615 : static void FVMenuTilePath(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2616 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2617 : FVTile(fv);
2618 : }
2619 :
2620 : static void FVMenuPatternTile(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2621 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2622 : FVPatternTile(fv);
2623 : }
2624 : #endif
2625 :
2626 0 : static void FVMenuOverlap(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2627 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2628 :
2629 0 : if ( fv->b.sf->onlybitmaps )
2630 0 : return;
2631 :
2632 : /* We know it's more likely that we'll find a problem in the overlap code */
2633 : /* than anywhere else, so let's save the current state against a crash */
2634 0 : DoAutoSaves();
2635 :
2636 0 : FVOverlap(&fv->b,mi->mid==MID_RmOverlap ? over_remove :
2637 0 : mi->mid==MID_Intersection ? over_intersect :
2638 : over_findinter);
2639 : }
2640 :
2641 0 : static void FVMenuInline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2642 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2643 :
2644 0 : OutlineDlg(fv,NULL,NULL,true);
2645 0 : }
2646 :
2647 0 : static void FVMenuOutline(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2648 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2649 :
2650 0 : OutlineDlg(fv,NULL,NULL,false);
2651 0 : }
2652 :
2653 0 : static void FVMenuShadow(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2654 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2655 :
2656 0 : ShadowDlg(fv,NULL,NULL,false);
2657 0 : }
2658 :
2659 0 : static void FVMenuWireframe(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2660 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2661 :
2662 0 : ShadowDlg(fv,NULL,NULL,true);
2663 0 : }
2664 :
2665 0 : static void FVSimplify(FontView *fv,int type) {
2666 : static struct simplifyinfo smpls[] = {
2667 : { sf_normal, 0, 0, 0, 0, 0, 0 },
2668 : { sf_normal,.75,.05,0,-1, 0, 0 },
2669 : { sf_normal,.75,.05,0,-1, 0, 0 }};
2670 0 : struct simplifyinfo *smpl = &smpls[type+1];
2671 :
2672 0 : if ( smpl->linelenmax==-1 || (type==0 && !smpl->set_as_default)) {
2673 0 : smpl->err = (fv->b.sf->ascent+fv->b.sf->descent)/1000.;
2674 0 : smpl->linelenmax = (fv->b.sf->ascent+fv->b.sf->descent)/100.;
2675 : }
2676 :
2677 0 : if ( type==1 ) {
2678 0 : if ( !SimplifyDlg(fv->b.sf,smpl))
2679 0 : return;
2680 0 : if ( smpl->set_as_default )
2681 0 : smpls[1] = *smpl;
2682 : }
2683 0 : _FVSimplify((FontViewBase *) fv,smpl);
2684 : }
2685 :
2686 0 : static void FVMenuSimplify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2687 0 : FVSimplify( (FontView *) GDrawGetUserData(gw),false );
2688 0 : }
2689 :
2690 0 : static void FVMenuSimplifyMore(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2691 0 : FVSimplify( (FontView *) GDrawGetUserData(gw),true );
2692 0 : }
2693 :
2694 0 : static void FVMenuCleanup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2695 0 : FVSimplify( (FontView *) GDrawGetUserData(gw),-1 );
2696 0 : }
2697 :
2698 0 : static void FVMenuCanonicalStart(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2699 0 : FVCanonicalStart( (FontViewBase *) GDrawGetUserData(gw) );
2700 0 : }
2701 :
2702 0 : static void FVMenuCanonicalContours(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2703 0 : FVCanonicalContours( (FontViewBase *) GDrawGetUserData(gw) );
2704 0 : }
2705 :
2706 0 : static void FVMenuAddExtrema(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2707 0 : FVAddExtrema( (FontViewBase *) GDrawGetUserData(gw) , false);
2708 0 : }
2709 :
2710 0 : static void FVMenuCorrectDir(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2711 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2712 0 : FVCorrectDir((FontViewBase *) fv);
2713 0 : }
2714 :
2715 0 : static void FVMenuRound2Int(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2716 0 : FVRound2Int( (FontViewBase *) GDrawGetUserData(gw), 1.0 );
2717 0 : }
2718 :
2719 0 : static void FVMenuRound2Hundredths(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2720 0 : FVRound2Int( (FontViewBase *) GDrawGetUserData(gw),100.0 );
2721 0 : }
2722 :
2723 0 : static void FVMenuCluster(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2724 0 : FVCluster( (FontViewBase *) GDrawGetUserData(gw));
2725 0 : }
2726 :
2727 0 : static void FVMenuAutotrace(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *e) {
2728 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2729 0 : GCursor ct=0;
2730 :
2731 0 : if ( fv->v!=NULL ) {
2732 0 : ct = GDrawGetCursor(fv->v);
2733 0 : GDrawSetCursor(fv->v,ct_watch);
2734 0 : GDrawSync(NULL);
2735 0 : GDrawProcessPendingEvents(NULL);
2736 : }
2737 0 : FVAutoTrace(&fv->b,e!=NULL && (e->u.mouse.state&ksm_shift));
2738 0 : if ( fv->v!=NULL )
2739 0 : GDrawSetCursor(fv->v,ct);
2740 0 : }
2741 :
2742 0 : static void FVMenuBuildAccent(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2743 0 : FVBuildAccent( (FontViewBase *) GDrawGetUserData(gw), true );
2744 0 : }
2745 :
2746 0 : static void FVMenuBuildComposite(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2747 0 : FVBuildAccent( (FontViewBase *) GDrawGetUserData(gw), false );
2748 0 : }
2749 :
2750 0 : static void FVMenuBuildDuplicate(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2751 0 : FVBuildDuplicate( (FontViewBase *) GDrawGetUserData(gw));
2752 0 : }
2753 :
2754 : #ifdef KOREAN
2755 : static void FVMenuShowGroup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2756 : ShowGroup( ((FontView *) GDrawGetUserData(gw))->sf );
2757 : }
2758 : #endif
2759 :
2760 : #if HANYANG
2761 : static void FVMenuModifyComposition(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2762 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2763 : if ( fv->b.sf->rules!=NULL )
2764 : SFModifyComposition(fv->b.sf);
2765 : }
2766 :
2767 : static void FVMenuBuildSyllables(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2768 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2769 : if ( fv->b.sf->rules!=NULL )
2770 : SFBuildSyllables(fv->b.sf);
2771 : }
2772 : #endif
2773 :
2774 0 : static void FVMenuCompareFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2775 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2776 0 : FontCompareDlg(fv);
2777 0 : }
2778 :
2779 0 : static void FVMenuMergeFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2780 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2781 0 : FVMergeFonts(fv);
2782 0 : }
2783 :
2784 0 : static void FVMenuInterpFonts(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2785 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2786 0 : FVInterpolateFonts(fv);
2787 0 : }
2788 :
2789 : static void FVShowInfo(FontView *fv);
2790 :
2791 0 : void FVChangeChar(FontView *fv,int i) {
2792 :
2793 0 : if ( i!=-1 ) {
2794 0 : FVDeselectAll(fv);
2795 0 : fv->b.selected[i] = true;
2796 0 : fv->sel_index = 1;
2797 0 : fv->end_pos = fv->pressed_pos = i;
2798 0 : FVToggleCharSelected(fv,i);
2799 0 : FVScrollToChar(fv,i);
2800 0 : FVShowInfo(fv);
2801 : }
2802 0 : }
2803 :
2804 0 : void FVScrollToChar(FontView *fv,int i) {
2805 :
2806 0 : if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
2807 0 : return;
2808 :
2809 0 : if ( i!=-1 ) {
2810 0 : if ( i/fv->colcnt<fv->rowoff || i/fv->colcnt >= fv->rowoff+fv->rowcnt ) {
2811 0 : fv->rowoff = i/fv->colcnt;
2812 0 : if ( fv->rowcnt>= 3 )
2813 0 : --fv->rowoff;
2814 0 : if ( fv->rowoff+fv->rowcnt>=fv->rowltot )
2815 0 : fv->rowoff = fv->rowltot-fv->rowcnt;
2816 0 : if ( fv->rowoff<0 ) fv->rowoff = 0;
2817 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
2818 0 : GDrawRequestExpose(fv->v,NULL,false);
2819 : }
2820 : }
2821 : }
2822 :
2823 0 : static void FVScrollToGID(FontView *fv,int gid) {
2824 0 : FVScrollToChar(fv,fv->b.map->backmap[gid]);
2825 0 : }
2826 :
2827 0 : static void FV_ChangeGID(FontView *fv,int gid) {
2828 0 : FVChangeChar(fv,fv->b.map->backmap[gid]);
2829 0 : }
2830 :
2831 0 : static void _FVMenuChangeChar(FontView *fv,int mid ) {
2832 0 : SplineFont *sf = fv->b.sf;
2833 0 : EncMap *map = fv->b.map;
2834 0 : int pos = FVAnyCharSelected(fv);
2835 :
2836 0 : if ( pos>=0 ) {
2837 0 : if ( mid==MID_Next )
2838 0 : ++pos;
2839 0 : else if ( mid==MID_Prev )
2840 0 : --pos;
2841 0 : else if ( mid==MID_NextDef ) {
2842 0 : for ( ++pos; pos<map->enccount &&
2843 0 : (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
2844 0 : (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
2845 0 : ++pos );
2846 0 : if ( pos>=map->enccount ) {
2847 0 : int selpos = FVAnyCharSelected(fv);
2848 0 : char *iconv_name = map->enc->iconv_name ? map->enc->iconv_name :
2849 0 : map->enc->enc_name;
2850 0 : if ( strstr(iconv_name,"2022")!=NULL && selpos<0x2121 )
2851 0 : pos = 0x2121;
2852 0 : else if ( strstr(iconv_name,"EUC")!=NULL && selpos<0xa1a1 )
2853 0 : pos = 0xa1a1;
2854 0 : else if ( map->enc->is_tradchinese ) {
2855 0 : if ( strstrmatch(map->enc->enc_name,"HK")!=NULL &&
2856 : selpos<0x8140 )
2857 0 : pos = 0x8140;
2858 : else
2859 0 : pos = 0xa140;
2860 0 : } else if ( map->enc->is_japanese ) {
2861 0 : if ( strstrmatch(iconv_name,"SJIS")!=NULL ||
2862 0 : (strstrmatch(iconv_name,"JIS")!=NULL && strstrmatch(iconv_name,"SHIFT")!=NULL )) {
2863 0 : if ( selpos<0x8100 )
2864 0 : pos = 0x8100;
2865 0 : else if ( selpos<0xb000 )
2866 0 : pos = 0xb000;
2867 : }
2868 0 : } else if ( map->enc->is_korean ) {
2869 0 : if ( strstrmatch(iconv_name,"JOHAB")!=NULL ) {
2870 0 : if ( selpos<0x8431 )
2871 0 : pos = 0x8431;
2872 : } else { /* Wansung, EUC-KR */
2873 0 : if ( selpos<0xa1a1 )
2874 0 : pos = 0xa1a1;
2875 : }
2876 0 : } else if ( map->enc->is_simplechinese ) {
2877 0 : if ( strmatch(iconv_name,"EUC-CN")==0 && selpos<0xa1a1 )
2878 0 : pos = 0xa1a1;
2879 : }
2880 0 : if ( pos>=map->enccount )
2881 0 : return;
2882 : }
2883 0 : } else if ( mid==MID_PrevDef ) {
2884 0 : for ( --pos; pos>=0 &&
2885 0 : (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
2886 0 : (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
2887 0 : --pos );
2888 0 : if ( pos<0 )
2889 0 : return;
2890 : }
2891 : }
2892 0 : if ( pos<0 ) pos = map->enccount-1;
2893 0 : else if ( pos>= map->enccount ) pos = 0;
2894 0 : if ( pos>=0 && pos<map->enccount )
2895 0 : FVChangeChar(fv,pos);
2896 : }
2897 :
2898 0 : static void FVMenuChangeChar(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2899 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2900 0 : _FVMenuChangeChar(fv,mi->mid);
2901 0 : }
2902 :
2903 0 : static void FVShowSubFont(FontView *fv,SplineFont *new) {
2904 : MetricsView *mv, *mvnext;
2905 : BDFFont *newbdf;
2906 0 : int wascompact = fv->b.normal!=NULL;
2907 : extern int use_freetype_to_rasterize_fv;
2908 :
2909 0 : for ( mv=fv->b.sf->metrics; mv!=NULL; mv = mvnext ) {
2910 : /* Don't bother trying to fix up metrics views, just not worth it */
2911 0 : mvnext = mv->next;
2912 0 : GDrawDestroyWindow(mv->gw);
2913 : }
2914 0 : if ( wascompact ) {
2915 0 : EncMapFree(fv->b.map);
2916 0 : if (fv->b.map == fv->b.sf->map) { fv->b.sf->map = fv->b.normal; }
2917 0 : fv->b.map = fv->b.normal;
2918 0 : fv->b.normal = NULL;
2919 0 : fv->b.selected = realloc(fv->b.selected,fv->b.map->enccount);
2920 0 : memset(fv->b.selected,0,fv->b.map->enccount);
2921 : }
2922 0 : CIDSetEncMap((FontViewBase *) fv,new);
2923 0 : if ( wascompact ) {
2924 0 : fv->b.normal = EncMapCopy(fv->b.map);
2925 0 : CompactEncMap(fv->b.map,fv->b.sf);
2926 0 : FontViewReformatOne(&fv->b);
2927 0 : FVSetTitle(&fv->b);
2928 : }
2929 0 : newbdf = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
2930 0 : (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
2931 0 : (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
2932 : NULL);
2933 0 : BDFFontFree(fv->filled);
2934 0 : if ( fv->filled == fv->show )
2935 0 : fv->show = newbdf;
2936 0 : fv->filled = newbdf;
2937 0 : GDrawRequestExpose(fv->v,NULL,true);
2938 0 : }
2939 :
2940 0 : static void FVMenuGotoChar(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2941 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2942 0 : int merge_with_selection = false;
2943 0 : int pos = GotoChar(fv->b.sf,fv->b.map,&merge_with_selection);
2944 0 : if ( fv->b.cidmaster!=NULL && pos!=-1 && !fv->b.map->enc->is_compact ) {
2945 0 : SplineFont *cidmaster = fv->b.cidmaster;
2946 0 : int k, hadk= cidmaster->subfontcnt;
2947 0 : for ( k=0; k<cidmaster->subfontcnt; ++k ) {
2948 0 : SplineFont *sf = cidmaster->subfonts[k];
2949 0 : if ( pos<sf->glyphcnt && sf->glyphs[pos]!=NULL )
2950 0 : break;
2951 0 : if ( pos<sf->glyphcnt )
2952 0 : hadk = k;
2953 : }
2954 0 : if ( k==cidmaster->subfontcnt && pos>=fv->b.sf->glyphcnt )
2955 0 : k = hadk;
2956 0 : if ( k!=cidmaster->subfontcnt && cidmaster->subfonts[k] != fv->b.sf )
2957 0 : FVShowSubFont(fv,cidmaster->subfonts[k]);
2958 0 : if ( pos>=fv->b.sf->glyphcnt )
2959 0 : pos = -1;
2960 : }
2961 0 : if ( !merge_with_selection )
2962 0 : FVChangeChar(fv,pos);
2963 : else {
2964 0 : if ( !fv->b.selected[pos] ) {
2965 0 : fv->b.selected[pos] = ++fv->sel_index;
2966 0 : FVToggleCharSelected(fv,pos);
2967 : }
2968 0 : fv->end_pos = fv->pressed_pos = pos;
2969 0 : FVScrollToChar(fv,pos);
2970 0 : FVShowInfo(fv);
2971 : }
2972 0 : }
2973 :
2974 0 : static void FVMenuLigatures(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2975 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2976 0 : SFShowLigatures(fv->b.sf,NULL);
2977 0 : }
2978 :
2979 0 : static void FVMenuKernPairs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2980 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2981 0 : SFKernClassTempDecompose(fv->b.sf,false);
2982 0 : SFShowKernPairs(fv->b.sf,NULL,NULL,fv->b.active_layer);
2983 0 : SFKernCleanup(fv->b.sf,false);
2984 0 : }
2985 :
2986 0 : static void FVMenuAnchorPairs(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
2987 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2988 0 : SFShowKernPairs(fv->b.sf,NULL,mi->ti.userdata,fv->b.active_layer);
2989 0 : }
2990 :
2991 0 : static void FVMenuShowAtt(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2992 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2993 0 : ShowAtt(fv->b.sf,fv->b.active_layer);
2994 0 : }
2995 :
2996 0 : static void FVMenuDisplaySubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
2997 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
2998 :
2999 0 : if ( fv->cur_subtable!=0 ) {
3000 0 : fv->cur_subtable = NULL;
3001 : } else {
3002 0 : SplineFont *sf = fv->b.sf;
3003 : OTLookup *otf;
3004 : struct lookup_subtable *sub;
3005 : int cnt, k;
3006 0 : char **names = NULL;
3007 0 : if ( sf->cidmaster ) sf=sf->cidmaster;
3008 0 : for ( k=0; k<2; ++k ) {
3009 0 : cnt = 0;
3010 0 : for ( otf = sf->gsub_lookups; otf!=NULL; otf=otf->next ) {
3011 0 : if ( otf->lookup_type==gsub_single ) {
3012 0 : for ( sub=otf->subtables; sub!=NULL; sub=sub->next ) {
3013 0 : if ( names )
3014 0 : names[cnt] = sub->subtable_name;
3015 0 : ++cnt;
3016 : }
3017 : }
3018 : }
3019 0 : if ( cnt==0 )
3020 0 : break;
3021 0 : if ( names==NULL )
3022 0 : names = malloc((cnt+3) * sizeof(char *));
3023 : else {
3024 0 : names[cnt++] = "-";
3025 0 : names[cnt++] = _("New Lookup Subtable...");
3026 0 : names[cnt] = NULL;
3027 : }
3028 : }
3029 0 : sub = NULL;
3030 0 : if ( names!=NULL ) {
3031 0 : int ret = gwwv_choose(_("Display Substitution..."), (const char **) names, cnt, 0,
3032 0 : _("Pick a substitution to display in the window."));
3033 0 : if ( ret!=-1 )
3034 0 : sub = SFFindLookupSubtable(sf,names[ret]);
3035 0 : free(names);
3036 0 : if ( ret==-1 )
3037 0 : return;
3038 : }
3039 0 : if ( sub==NULL )
3040 0 : sub = SFNewLookupSubtableOfType(sf,gsub_single,NULL,fv->b.active_layer);
3041 0 : if ( sub!=NULL )
3042 0 : fv->cur_subtable = sub;
3043 : }
3044 0 : GDrawRequestExpose(fv->v,NULL,false);
3045 : }
3046 :
3047 0 : static void FVChangeDisplayFont(FontView *fv,BDFFont *bdf) {
3048 0 : int samesize=0;
3049 : int rcnt, ccnt;
3050 : int oldr, oldc;
3051 0 : int first_time = fv->show==NULL;
3052 :
3053 0 : if ( fv->v==NULL ) /* Can happen in scripts */
3054 0 : return;
3055 :
3056 0 : if ( fv->show!=bdf ) {
3057 0 : oldc = fv->cbw*fv->colcnt;
3058 0 : oldr = fv->cbh*fv->rowcnt;
3059 :
3060 0 : fv->show = bdf;
3061 0 : fv->b.active_bitmap = bdf==fv->filled ? NULL : bdf;
3062 0 : if ( fv->user_requested_magnify!=-1 )
3063 0 : fv->magnify=fv->user_requested_magnify;
3064 0 : else if ( bdf->pixelsize<20 ) {
3065 0 : if ( bdf->pixelsize<=9 )
3066 0 : fv->magnify = 3;
3067 : else
3068 0 : fv->magnify = 2;
3069 0 : samesize = ( fv->show && fv->cbw == (bdf->pixelsize*fv->magnify)+1 );
3070 : } else
3071 0 : fv->magnify = 1;
3072 0 : if ( !first_time && fv->cbw == fv->magnify*bdf->pixelsize+1 )
3073 0 : samesize = true;
3074 0 : fv->cbw = (bdf->pixelsize*fv->magnify)+1;
3075 0 : fv->cbh = (bdf->pixelsize*fv->magnify)+1+fv->lab_height+1;
3076 0 : fv->resize_expected = !samesize;
3077 0 : ccnt = fv->b.sf->desired_col_cnt;
3078 0 : rcnt = fv->b.sf->desired_row_cnt;
3079 0 : if ((( bdf->pixelsize<=fv->b.sf->display_size || bdf->pixelsize<=-fv->b.sf->display_size ) &&
3080 0 : fv->b.sf->top_enc!=-1 /* Not defaulting */ ) ||
3081 0 : bdf->pixelsize<=48 ) {
3082 : /* use the desired sizes */
3083 : } else {
3084 0 : if ( bdf->pixelsize>48 ) {
3085 0 : ccnt = 8;
3086 0 : rcnt = 2;
3087 0 : } else if ( bdf->pixelsize>=96 ) {
3088 0 : ccnt = 4;
3089 0 : rcnt = 1;
3090 : }
3091 0 : if ( !first_time ) {
3092 0 : if ( ccnt < oldc/fv->cbw )
3093 0 : ccnt = oldc/fv->cbw;
3094 0 : if ( rcnt < oldr/fv->cbh )
3095 0 : rcnt = oldr/fv->cbh;
3096 : }
3097 : }
3098 0 : if ( samesize ) {
3099 0 : GDrawRequestExpose(fv->v,NULL,false);
3100 0 : } else if ( fv->b.container!=NULL && fv->b.container->funcs->doResize!=NULL ) {
3101 0 : (fv->b.container->funcs->doResize)(fv->b.container,&fv->b,
3102 0 : ccnt*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3103 0 : rcnt*fv->cbh+1+fv->mbh+fv->infoh);
3104 : } else {
3105 0 : GDrawResize(fv->gw,
3106 0 : ccnt*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3107 0 : rcnt*fv->cbh+1+fv->mbh+fv->infoh);
3108 : }
3109 : }
3110 : }
3111 :
3112 : struct md_data {
3113 : int done;
3114 : int ish;
3115 : FontView *fv;
3116 : };
3117 :
3118 0 : static int md_e_h(GWindow gw, GEvent *e) {
3119 0 : if ( e->type==et_close ) {
3120 0 : struct md_data *d = GDrawGetUserData(gw);
3121 0 : d->done = true;
3122 0 : } else if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
3123 0 : struct md_data *d = GDrawGetUserData(gw);
3124 : static int masks[] = { fvm_baseline, fvm_origin, fvm_advanceat, fvm_advanceto, -1 };
3125 : int i, metrics;
3126 0 : if ( GGadgetGetCid(e->u.control.g)==10 ) {
3127 0 : metrics = 0;
3128 0 : for ( i=0; masks[i]!=-1 ; ++i )
3129 0 : if ( GGadgetIsChecked(GWidgetGetControl(gw,masks[i])))
3130 0 : metrics |= masks[i];
3131 0 : if ( d->ish )
3132 0 : default_fv_showhmetrics = d->fv->showhmetrics = metrics;
3133 : else
3134 0 : default_fv_showvmetrics = d->fv->showvmetrics = metrics;
3135 : }
3136 0 : d->done = true;
3137 0 : } else if ( e->type==et_char ) {
3138 0 : return( false );
3139 : }
3140 0 : return( true );
3141 : }
3142 :
3143 0 : static void FVMenuShowMetrics(GWindow fvgw,struct gmenuitem *mi, GEvent *UNUSED(e)) {
3144 0 : FontView *fv = (FontView *) GDrawGetUserData(fvgw);
3145 : GRect pos;
3146 : GWindow gw;
3147 : GWindowAttrs wattrs;
3148 : struct md_data d;
3149 : GGadgetCreateData gcd[7];
3150 : GTextInfo label[6];
3151 0 : int metrics = mi->mid==MID_ShowHMetrics ? fv->showhmetrics : fv->showvmetrics;
3152 :
3153 0 : d.fv = fv;
3154 0 : d.done = 0;
3155 0 : d.ish = mi->mid==MID_ShowHMetrics;
3156 :
3157 0 : memset(&wattrs,0,sizeof(wattrs));
3158 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
3159 0 : wattrs.event_masks = ~(1<<et_charup);
3160 0 : wattrs.restrict_input_to_me = 1;
3161 0 : wattrs.undercursor = 1;
3162 0 : wattrs.cursor = ct_pointer;
3163 0 : wattrs.utf8_window_title = d.ish?_("Show H. Metrics"):_("Show V. Metrics");
3164 0 : pos.x = pos.y = 0;
3165 0 : pos.width =GDrawPointsToPixels(NULL,GGadgetScale(170));
3166 0 : pos.height = GDrawPointsToPixels(NULL,130);
3167 0 : gw = GDrawCreateTopWindow(NULL,&pos,md_e_h,&d,&wattrs);
3168 :
3169 0 : memset(&label,0,sizeof(label));
3170 0 : memset(&gcd,0,sizeof(gcd));
3171 :
3172 0 : label[0].text = (unichar_t *) _("Baseline");
3173 0 : label[0].text_is_1byte = true;
3174 0 : gcd[0].gd.label = &label[0];
3175 0 : gcd[0].gd.pos.x = 8; gcd[0].gd.pos.y = 8;
3176 0 : gcd[0].gd.flags = gg_enabled|gg_visible|(metrics&fvm_baseline?gg_cb_on:0);
3177 0 : gcd[0].gd.cid = fvm_baseline;
3178 0 : gcd[0].creator = GCheckBoxCreate;
3179 :
3180 0 : label[1].text = (unichar_t *) _("Origin");
3181 0 : label[1].text_is_1byte = true;
3182 0 : gcd[1].gd.label = &label[1];
3183 0 : gcd[1].gd.pos.x = 8; gcd[1].gd.pos.y = gcd[0].gd.pos.y+16;
3184 0 : gcd[1].gd.flags = gg_enabled|gg_visible|(metrics&fvm_origin?gg_cb_on:0);
3185 0 : gcd[1].gd.cid = fvm_origin;
3186 0 : gcd[1].creator = GCheckBoxCreate;
3187 :
3188 0 : label[2].text = (unichar_t *) _("Advance Width as a Line");
3189 0 : label[2].text_is_1byte = true;
3190 0 : gcd[2].gd.label = &label[2];
3191 0 : gcd[2].gd.pos.x = 8; gcd[2].gd.pos.y = gcd[1].gd.pos.y+16;
3192 0 : gcd[2].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|(metrics&fvm_advanceat?gg_cb_on:0);
3193 0 : gcd[2].gd.cid = fvm_advanceat;
3194 0 : gcd[2].gd.popup_msg = (unichar_t *) _("Display the advance width as a line\nperpendicular to the advance direction");
3195 0 : gcd[2].creator = GCheckBoxCreate;
3196 :
3197 0 : label[3].text = (unichar_t *) _("Advance Width as a Bar");
3198 0 : label[3].text_is_1byte = true;
3199 0 : gcd[3].gd.label = &label[3];
3200 0 : gcd[3].gd.pos.x = 8; gcd[3].gd.pos.y = gcd[2].gd.pos.y+16;
3201 0 : gcd[3].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|(metrics&fvm_advanceto?gg_cb_on:0);
3202 0 : gcd[3].gd.cid = fvm_advanceto;
3203 0 : gcd[3].gd.popup_msg = (unichar_t *) _("Display the advance width as a bar under the glyph\nshowing the extent of the advance");
3204 0 : gcd[3].creator = GCheckBoxCreate;
3205 :
3206 0 : label[4].text = (unichar_t *) _("_OK");
3207 0 : label[4].text_is_1byte = true;
3208 0 : label[4].text_in_resource = true;
3209 0 : gcd[4].gd.label = &label[4];
3210 0 : gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
3211 0 : gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
3212 0 : gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
3213 0 : gcd[4].gd.cid = 10;
3214 0 : gcd[4].creator = GButtonCreate;
3215 :
3216 0 : label[5].text = (unichar_t *) _("_Cancel");
3217 0 : label[5].text_is_1byte = true;
3218 0 : label[5].text_in_resource = true;
3219 0 : gcd[5].gd.label = &label[5];
3220 0 : gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = gcd[4].gd.pos.y+3;
3221 0 : gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
3222 0 : gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3223 0 : gcd[5].creator = GButtonCreate;
3224 :
3225 0 : GGadgetsCreate(gw,gcd);
3226 :
3227 0 : GDrawSetVisible(gw,true);
3228 0 : while ( !d.done )
3229 0 : GDrawProcessOneEvent(NULL);
3230 0 : GDrawDestroyWindow(gw);
3231 :
3232 0 : SavePrefs(true);
3233 0 : GDrawRequestExpose(fv->v,NULL,false);
3234 0 : }
3235 :
3236 0 : static void FV_ChangeDisplayBitmap(FontView *fv,BDFFont *bdf) {
3237 0 : FVChangeDisplayFont(fv,bdf);
3238 0 : if (fv->show != NULL) {
3239 0 : fv->b.sf->display_size = fv->show->pixelsize;
3240 : } else {
3241 0 : fv->b.sf->display_size = 1;
3242 : }
3243 0 : }
3244 :
3245 0 : static void FVMenuSize(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3246 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3247 0 : int dspsize = fv->filled->pixelsize;
3248 0 : int changedmodifier = false;
3249 : extern int use_freetype_to_rasterize_fv;
3250 :
3251 0 : fv->magnify = 1;
3252 0 : fv->user_requested_magnify = -1;
3253 0 : if ( mi->mid == MID_24 )
3254 0 : default_fv_font_size = dspsize = 24;
3255 0 : else if ( mi->mid == MID_36 )
3256 0 : default_fv_font_size = dspsize = 36;
3257 0 : else if ( mi->mid == MID_48 )
3258 0 : default_fv_font_size = dspsize = 48;
3259 0 : else if ( mi->mid == MID_72 )
3260 0 : default_fv_font_size = dspsize = 72;
3261 0 : else if ( mi->mid == MID_96 )
3262 0 : default_fv_font_size = dspsize = 96;
3263 0 : else if ( mi->mid == MID_128 )
3264 0 : default_fv_font_size = dspsize = 128;
3265 0 : else if ( mi->mid == MID_FitToBbox ) {
3266 0 : default_fv_bbsized = fv->bbsized = !fv->bbsized;
3267 0 : fv->b.sf->display_bbsized = fv->bbsized;
3268 0 : changedmodifier = true;
3269 : } else {
3270 0 : default_fv_antialias = fv->antialias = !fv->antialias;
3271 0 : fv->b.sf->display_antialias = fv->antialias;
3272 0 : changedmodifier = true;
3273 : }
3274 :
3275 0 : SavePrefs(true);
3276 0 : if ( fv->filled!=fv->show || fv->filled->pixelsize != dspsize || changedmodifier ) {
3277 : BDFFont *new, *old;
3278 0 : old = fv->filled;
3279 0 : new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,dspsize,72,
3280 0 : (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
3281 0 : (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
3282 : NULL);
3283 0 : fv->filled = new;
3284 0 : FVChangeDisplayFont(fv,new);
3285 0 : BDFFontFree(old);
3286 0 : fv->b.sf->display_size = -dspsize;
3287 0 : if ( fv->b.cidmaster!=NULL ) {
3288 : int i;
3289 0 : for ( i=0; i<fv->b.cidmaster->subfontcnt; ++i )
3290 0 : fv->b.cidmaster->subfonts[i]->display_size = -dspsize;
3291 : }
3292 : }
3293 0 : }
3294 :
3295 0 : void FVSetUIToMatch(FontView *destfv,FontView *srcfv) {
3296 : extern int use_freetype_to_rasterize_fv;
3297 :
3298 0 : if ( destfv->filled==NULL || srcfv->filled==NULL )
3299 0 : return;
3300 0 : if ( destfv->magnify!=srcfv->magnify ||
3301 0 : destfv->user_requested_magnify!=srcfv->user_requested_magnify ||
3302 0 : destfv->bbsized!=srcfv->bbsized ||
3303 0 : destfv->antialias!=srcfv->antialias ||
3304 0 : destfv->filled->pixelsize != srcfv->filled->pixelsize ) {
3305 : BDFFont *new, *old;
3306 0 : destfv->magnify = srcfv->magnify;
3307 0 : destfv->user_requested_magnify = srcfv->user_requested_magnify;
3308 0 : destfv->bbsized = srcfv->bbsized;
3309 0 : destfv->antialias = srcfv->antialias;
3310 0 : old = destfv->filled;
3311 0 : new = SplineFontPieceMeal(destfv->b.sf,destfv->b.active_layer,srcfv->filled->pixelsize,72,
3312 0 : (destfv->antialias?pf_antialias:0)|(destfv->bbsized?pf_bbsized:0)|
3313 0 : (use_freetype_to_rasterize_fv && !destfv->b.sf->strokedfont && !destfv->b.sf->multilayer?pf_ft_nohints:0),
3314 : NULL);
3315 0 : destfv->filled = new;
3316 0 : FVChangeDisplayFont(destfv,new);
3317 0 : BDFFontFree(old);
3318 : }
3319 : }
3320 :
3321 0 : static void FV_LayerChanged( FontView *fv ) {
3322 : extern int use_freetype_to_rasterize_fv;
3323 : BDFFont *new, *old;
3324 :
3325 0 : fv->magnify = 1;
3326 0 : fv->user_requested_magnify = -1;
3327 :
3328 0 : old = fv->filled;
3329 0 : new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
3330 0 : (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
3331 0 : (use_freetype_to_rasterize_fv && !fv->b.sf->strokedfont && !fv->b.sf->multilayer?pf_ft_nohints:0),
3332 : NULL);
3333 0 : fv->filled = new;
3334 0 : FVChangeDisplayFont(fv,new);
3335 0 : fv->b.sf->display_size = -fv->filled->pixelsize;
3336 0 : BDFFontFree(old);
3337 0 : }
3338 :
3339 0 : static void FVMenuChangeLayer(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3340 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3341 :
3342 0 : fv->b.active_layer = mi->mid;
3343 0 : fv->b.sf->display_layer = mi->mid;
3344 0 : FV_LayerChanged(fv);
3345 0 : }
3346 :
3347 0 : static void FVMenuMagnify(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3348 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3349 0 : int magnify = fv->user_requested_magnify!=-1 ? fv->user_requested_magnify : fv->magnify;
3350 : char def[20], *end, *ret;
3351 : int val;
3352 0 : BDFFont *show = fv->show;
3353 :
3354 0 : sprintf( def, "%d", magnify );
3355 0 : ret = gwwv_ask_string(_("Bitmap Magnification..."),def,_("Please specify a bitmap magnification factor."));
3356 0 : if ( ret==NULL )
3357 0 : return;
3358 0 : val = strtol(ret,&end,10);
3359 0 : if ( val<1 || val>5 || *end!='\0' )
3360 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
3361 : else {
3362 0 : fv->user_requested_magnify = val;
3363 0 : fv->show = fv->filled;
3364 0 : fv->b.active_bitmap = NULL;
3365 0 : FVChangeDisplayFont(fv,show);
3366 : }
3367 0 : free(ret);
3368 : }
3369 :
3370 0 : static void FVMenuWSize(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3371 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3372 : int h,v;
3373 : extern int default_fv_col_count, default_fv_row_count;
3374 :
3375 0 : if ( mi->mid == MID_32x8 ) {
3376 0 : h = 32; v=8;
3377 0 : } else if ( mi->mid == MID_16x4 ) {
3378 0 : h = 16; v=4;
3379 : } else {
3380 0 : h = 8; v=2;
3381 : }
3382 0 : GDrawResize(fv->gw,
3383 0 : h*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
3384 0 : v*fv->cbh+1+fv->mbh+fv->infoh);
3385 0 : fv->b.sf->desired_col_cnt = default_fv_col_count = h;
3386 0 : fv->b.sf->desired_row_cnt = default_fv_row_count = v;
3387 :
3388 0 : SavePrefs(true);
3389 0 : }
3390 :
3391 0 : static void FVMenuGlyphLabel(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3392 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3393 :
3394 0 : default_fv_glyphlabel = fv->glyphlabel = mi->mid;
3395 :
3396 0 : GDrawRequestExpose(fv->v,NULL,false);
3397 :
3398 0 : SavePrefs(true);
3399 0 : }
3400 :
3401 0 : static void FVMenuShowBitmap(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3402 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3403 0 : BDFFont *bdf = mi->ti.userdata;
3404 :
3405 0 : FV_ChangeDisplayBitmap(fv,bdf); /* Let's not change any of the others */
3406 0 : }
3407 :
3408 0 : static void FV_ShowFilled(FontView *fv) {
3409 :
3410 0 : fv->magnify = 1;
3411 0 : fv->user_requested_magnify = 1;
3412 0 : if ( fv->show!=fv->filled )
3413 0 : FVChangeDisplayFont(fv,fv->filled);
3414 0 : fv->b.sf->display_size = -fv->filled->pixelsize;
3415 0 : fv->b.active_bitmap = NULL;
3416 0 : }
3417 :
3418 0 : static void FVMenuCenter(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3419 0 : FontViewBase *fv = (FontViewBase *) GDrawGetUserData(gw);
3420 0 : FVMetricsCenter(fv,mi->mid==MID_Center);
3421 0 : }
3422 :
3423 0 : static void FVMenuSetWidth(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3424 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3425 :
3426 0 : if ( FVAnyCharSelected(fv)==-1 )
3427 0 : return;
3428 0 : if ( mi->mid == MID_SetVWidth && !fv->b.sf->hasvmetrics )
3429 0 : return;
3430 0 : FVSetWidth(fv,mi->mid==MID_SetWidth ?wt_width:
3431 0 : mi->mid==MID_SetLBearing?wt_lbearing:
3432 0 : mi->mid==MID_SetRBearing?wt_rbearing:
3433 0 : mi->mid==MID_SetBearings?wt_bearings:
3434 : wt_vwidth);
3435 : }
3436 :
3437 0 : static void FVMenuAutoWidth(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3438 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3439 :
3440 0 : FVAutoWidth2(fv);
3441 0 : }
3442 :
3443 0 : static void FVMenuKernByClasses(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3444 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3445 :
3446 0 : ShowKernClasses(fv->b.sf,NULL,fv->b.active_layer,false);
3447 0 : }
3448 :
3449 0 : static void FVMenuVKernByClasses(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3450 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3451 :
3452 0 : ShowKernClasses(fv->b.sf,NULL,fv->b.active_layer,true);
3453 0 : }
3454 :
3455 0 : static void FVMenuRemoveKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3456 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3457 :
3458 0 : FVRemoveKerns(&fv->b);
3459 0 : }
3460 :
3461 0 : static void FVMenuRemoveVKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3462 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3463 :
3464 0 : FVRemoveVKerns(&fv->b);
3465 0 : }
3466 :
3467 0 : static void FVMenuKPCloseup(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3468 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3469 : int i;
3470 :
3471 0 : for ( i=0; i<fv->b.map->enccount; ++i )
3472 0 : if ( fv->b.selected[i] )
3473 0 : break;
3474 0 : KernPairD(fv->b.sf,i==fv->b.map->enccount?NULL:
3475 0 : fv->b.map->map[i]==-1?NULL:
3476 0 : fv->b.sf->glyphs[fv->b.map->map[i]],NULL,fv->b.active_layer,
3477 : false);
3478 0 : }
3479 :
3480 0 : static void FVMenuVKernFromHKern(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3481 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3482 :
3483 0 : FVVKernFromHKern(&fv->b);
3484 0 : }
3485 :
3486 0 : static void FVMenuAutoHint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3487 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3488 0 : FVAutoHint( &fv->b );
3489 0 : }
3490 :
3491 0 : static void FVMenuAutoHintSubs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3492 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3493 0 : FVAutoHintSubs( &fv->b );
3494 0 : }
3495 :
3496 0 : static void FVMenuAutoCounter(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3497 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3498 0 : FVAutoCounter( &fv->b );
3499 0 : }
3500 :
3501 0 : static void FVMenuDontAutoHint(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3502 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3503 0 : FVDontAutoHint( &fv->b );
3504 0 : }
3505 :
3506 0 : static void FVMenuDeltas(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3507 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3508 :
3509 0 : if ( !hasFreeTypeDebugger())
3510 0 : return;
3511 0 : DeltaSuggestionDlg(fv,NULL);
3512 : }
3513 :
3514 0 : static void FVMenuAutoInstr(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3515 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3516 0 : FVAutoInstr( &fv->b );
3517 0 : }
3518 :
3519 0 : static void FVMenuEditInstrs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3520 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3521 0 : int index = FVAnyCharSelected(fv);
3522 : SplineChar *sc;
3523 0 : if ( index<0 )
3524 0 : return;
3525 0 : sc = SFMakeChar(fv->b.sf,fv->b.map,index);
3526 0 : SCEditInstructions(sc);
3527 : }
3528 :
3529 0 : static void FVMenuEditTable(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3530 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3531 0 : SFEditTable(fv->b.sf,
3532 0 : mi->mid==MID_Editprep?CHR('p','r','e','p'):
3533 0 : mi->mid==MID_Editfpgm?CHR('f','p','g','m'):
3534 0 : mi->mid==MID_Editmaxp?CHR('m','a','x','p'):
3535 : CHR('c','v','t',' '));
3536 0 : }
3537 :
3538 0 : static void FVMenuRmInstrTables(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3539 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3540 0 : TtfTablesFree(fv->b.sf->ttf_tables);
3541 0 : fv->b.sf->ttf_tables = NULL;
3542 0 : if ( !fv->b.sf->changed ) {
3543 0 : fv->b.sf->changed = true;
3544 0 : FVSetTitles(fv->b.sf);
3545 : }
3546 0 : }
3547 :
3548 0 : static void FVMenuClearInstrs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3549 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3550 0 : FVClearInstrs(&fv->b);
3551 0 : }
3552 :
3553 0 : static void FVMenuClearHints(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3554 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3555 0 : FVClearHints(&fv->b);
3556 0 : }
3557 :
3558 0 : static void FVMenuHistograms(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3559 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3560 0 : SFHistogram(fv->b.sf, fv->b.active_layer, NULL,
3561 0 : FVAnyCharSelected(fv)!=-1?fv->b.selected:NULL,
3562 : fv->b.map,
3563 0 : mi->mid==MID_HStemHist ? hist_hstem :
3564 0 : mi->mid==MID_VStemHist ? hist_vstem :
3565 : hist_blues);
3566 0 : }
3567 :
3568 :
3569 23 : static void FontViewSetTitle(FontView *fv) {
3570 : unichar_t *title, *ititle, *temp;
3571 23 : char *file=NULL;
3572 : char *enc;
3573 : int len;
3574 :
3575 23 : if ( fv->gw==NULL ) /* In scripting */
3576 46 : return;
3577 :
3578 0 : const char* collabStateString = "";
3579 0 : if( collabclient_inSessionFV( &fv->b )) {
3580 0 : printf("collabclient_getState( fv ) %d %d\n",
3581 0 : fv->b.collabState, collabclient_getState( &fv->b ));
3582 0 : collabStateString = collabclient_stateToString(collabclient_getState( &fv->b ));
3583 : }
3584 :
3585 0 : enc = SFEncodingName(fv->b.sf,fv->b.normal?fv->b.normal:fv->b.map);
3586 0 : len = strlen(fv->b.sf->fontname)+1 + strlen(enc)+6;
3587 0 : if ( fv->b.normal ) len += strlen(_("Compact"))+1;
3588 0 : if ( fv->b.cidmaster!=NULL ) {
3589 0 : if ( (file = fv->b.cidmaster->filename)==NULL )
3590 0 : file = fv->b.cidmaster->origname;
3591 : } else {
3592 0 : if ( (file = fv->b.sf->filename)==NULL )
3593 0 : file = fv->b.sf->origname;
3594 : }
3595 0 : len += strlen(collabStateString);
3596 0 : if ( file!=NULL )
3597 0 : len += 2+strlen(file);
3598 0 : title = malloc((len+1)*sizeof(unichar_t));
3599 0 : uc_strcpy(title,"");
3600 :
3601 0 : if(*collabStateString) {
3602 0 : uc_strcat(title, collabStateString);
3603 0 : uc_strcat(title, " - ");
3604 : }
3605 0 : uc_strcat(title,fv->b.sf->fontname);
3606 0 : if ( fv->b.sf->changed )
3607 0 : uc_strcat(title,"*");
3608 0 : if ( file!=NULL ) {
3609 0 : uc_strcat(title," ");
3610 0 : temp = def2u_copy(GFileNameTail(file));
3611 0 : u_strcat(title,temp);
3612 0 : free(temp);
3613 : }
3614 0 : uc_strcat(title, " (" );
3615 0 : if ( fv->b.normal ) { utf82u_strcat(title,_("Compact")); uc_strcat(title," "); }
3616 0 : uc_strcat(title,enc);
3617 0 : uc_strcat(title, ")" );
3618 0 : free(enc);
3619 :
3620 0 : ititle = uc_copy(fv->b.sf->fontname);
3621 0 : GDrawSetWindowTitles(fv->gw,title,ititle);
3622 0 : free(title);
3623 0 : free(ititle);
3624 : }
3625 :
3626 0 : void FVTitleUpdate(FontViewBase *fv)
3627 : {
3628 0 : FontViewSetTitle( (FontView*)fv );
3629 0 : }
3630 :
3631 24 : static void FontViewSetTitles(SplineFont *sf) {
3632 : FontView *fv;
3633 :
3634 47 : for ( fv = (FontView *) (sf->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame))
3635 23 : FontViewSetTitle(fv);
3636 24 : }
3637 :
3638 0 : static void FVMenuShowSubFont(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3639 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3640 0 : SplineFont *new = mi->ti.userdata;
3641 0 : FVShowSubFont(fv,new);
3642 0 : }
3643 :
3644 0 : static void FVMenuConvert2CID(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3645 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3646 0 : SplineFont *cidmaster = fv->b.cidmaster;
3647 : struct cidmap *cidmap;
3648 :
3649 0 : if ( cidmaster!=NULL )
3650 0 : return;
3651 0 : SFFindNearTop(fv->b.sf);
3652 0 : cidmap = AskUserForCIDMap();
3653 0 : if ( cidmap==NULL )
3654 0 : return;
3655 0 : MakeCIDMaster(fv->b.sf,fv->b.map,false,NULL,cidmap);
3656 0 : SFRestoreNearTop(fv->b.sf);
3657 : }
3658 :
3659 0 : static enum fchooserret CMapFilter(GGadget *g,GDirEntry *ent,
3660 : const unichar_t *dir) {
3661 0 : enum fchooserret ret = GFileChooserDefFilter(g,ent,dir);
3662 : char buf2[256];
3663 : FILE *file;
3664 : static char *cmapflag = "%!PS-Adobe-3.0 Resource-CMap";
3665 :
3666 0 : if ( ret==fc_show && !ent->isdir ) {
3667 0 : int len = 3*(u_strlen(dir)+u_strlen(ent->name)+5);
3668 0 : char *filename = malloc(len);
3669 0 : u2def_strncpy(filename,dir,len);
3670 0 : strcat(filename,"/");
3671 0 : u2def_strncpy(buf2,ent->name,sizeof(buf2));
3672 0 : strcat(filename,buf2);
3673 0 : file = fopen(filename,"r");
3674 0 : if ( file==NULL )
3675 0 : ret = fc_hide;
3676 : else {
3677 0 : if ( fgets(buf2,sizeof(buf2),file)==NULL ||
3678 0 : strncmp(buf2,cmapflag,strlen(cmapflag))!=0 )
3679 0 : ret = fc_hide;
3680 0 : fclose(file);
3681 : }
3682 0 : free(filename);
3683 : }
3684 0 : return( ret );
3685 : }
3686 :
3687 0 : static void FVMenuConvertByCMap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3688 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3689 0 : SplineFont *cidmaster = fv->b.cidmaster;
3690 : char *cmapfilename;
3691 :
3692 0 : if ( cidmaster!=NULL )
3693 0 : return;
3694 0 : cmapfilename = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
3695 0 : if ( cmapfilename==NULL )
3696 0 : return;
3697 0 : MakeCIDMaster(fv->b.sf,fv->b.map,true,cmapfilename,NULL);
3698 0 : free(cmapfilename);
3699 : }
3700 :
3701 0 : static void FVMenuFlatten(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3702 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3703 0 : SplineFont *cidmaster = fv->b.cidmaster;
3704 :
3705 0 : if ( cidmaster==NULL )
3706 0 : return;
3707 0 : SFFlatten(cidmaster);
3708 : }
3709 :
3710 0 : static void FVMenuFlattenByCMap(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3711 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3712 0 : SplineFont *cidmaster = fv->b.cidmaster;
3713 : char *cmapname;
3714 :
3715 0 : if ( cidmaster==NULL )
3716 0 : return;
3717 0 : cmapname = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
3718 0 : if ( cmapname==NULL )
3719 0 : return;
3720 0 : SFFindNearTop(fv->b.sf);
3721 0 : SFFlattenByCMap(cidmaster,cmapname);
3722 0 : SFRestoreNearTop(fv->b.sf);
3723 0 : free(cmapname);
3724 : }
3725 :
3726 0 : static void FVMenuInsertFont(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3727 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3728 0 : SplineFont *cidmaster = fv->b.cidmaster;
3729 : SplineFont *new;
3730 : struct cidmap *map;
3731 : char *filename;
3732 : extern NameList *force_names_when_opening;
3733 :
3734 0 : if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
3735 0 : return;
3736 :
3737 0 : filename = GetPostScriptFontName(NULL,false);
3738 0 : if ( filename==NULL )
3739 0 : return;
3740 0 : new = LoadSplineFont(filename,0);
3741 0 : free(filename);
3742 0 : if ( new==NULL )
3743 0 : return;
3744 0 : if ( new->fv == &fv->b ) /* Already part of us */
3745 0 : return;
3746 0 : if ( new->fv != NULL ) {
3747 0 : if ( ((FontView *) (new->fv))->gw!=NULL )
3748 0 : GDrawRaise( ((FontView *) (new->fv))->gw);
3749 0 : ff_post_error(_("Please close font"),_("Please close %s before inserting it into a CID font"),new->origname);
3750 0 : return;
3751 : }
3752 0 : EncMapFree(new->map);
3753 0 : if ( force_names_when_opening!=NULL )
3754 0 : SFRenameGlyphsToNamelist(new,force_names_when_opening );
3755 :
3756 0 : map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
3757 0 : SFEncodeToMap(new,map);
3758 0 : if ( !PSDictHasEntry(new->private,"lenIV"))
3759 0 : PSDictChangeEntry(new->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
3760 0 : new->display_antialias = fv->b.sf->display_antialias;
3761 0 : new->display_bbsized = fv->b.sf->display_bbsized;
3762 0 : new->display_size = fv->b.sf->display_size;
3763 0 : FVInsertInCID((FontViewBase *) fv,new);
3764 0 : CIDMasterAsDes(new);
3765 : }
3766 :
3767 0 : static void FVMenuInsertBlank(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3768 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3769 0 : SplineFont *cidmaster = fv->b.cidmaster, *sf;
3770 : struct cidmap *map;
3771 :
3772 0 : if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
3773 0 : return;
3774 0 : map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
3775 0 : sf = SplineFontBlank(MaxCID(map));
3776 0 : sf->glyphcnt = sf->glyphmax;
3777 0 : sf->cidmaster = cidmaster;
3778 0 : sf->display_antialias = fv->b.sf->display_antialias;
3779 0 : sf->display_bbsized = fv->b.sf->display_bbsized;
3780 0 : sf->display_size = fv->b.sf->display_size;
3781 0 : sf->private = calloc(1,sizeof(struct psdict));
3782 0 : PSDictChangeEntry(sf->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
3783 0 : FVInsertInCID((FontViewBase *) fv,sf);
3784 : }
3785 :
3786 0 : static void FVMenuRemoveFontFromCID(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3787 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3788 : char *buts[3];
3789 0 : SplineFont *cidmaster = fv->b.cidmaster, *sf = fv->b.sf, *replace;
3790 : int i;
3791 : MetricsView *mv, *mnext;
3792 : FontView *fvs;
3793 :
3794 0 : if ( cidmaster==NULL || cidmaster->subfontcnt<=1 ) /* Can't remove last font */
3795 0 : return;
3796 0 : buts[0] = _("_Remove"); buts[1] = _("_Cancel"); buts[2] = NULL;
3797 0 : 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"),
3798 : sf->fontname,cidmaster->fontname)==1 )
3799 0 : return;
3800 :
3801 0 : for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
3802 : CharView *cv, *next;
3803 0 : for ( cv = (CharView *) (sf->glyphs[i]->views); cv!=NULL; cv = next ) {
3804 0 : next = (CharView *) (cv->b.next);
3805 0 : GDrawDestroyWindow(cv->gw);
3806 : }
3807 : }
3808 0 : GDrawProcessPendingEvents(NULL);
3809 0 : for ( mv=fv->b.sf->metrics; mv!=NULL; mv = mnext ) {
3810 0 : mnext = mv->next;
3811 0 : GDrawDestroyWindow(mv->gw);
3812 : }
3813 0 : GDrawSync(NULL);
3814 0 : GDrawProcessPendingEvents(NULL);
3815 : /* Just in case... */
3816 0 : GDrawSync(NULL);
3817 0 : GDrawProcessPendingEvents(NULL);
3818 :
3819 0 : for ( i=0; i<cidmaster->subfontcnt; ++i )
3820 0 : if ( cidmaster->subfonts[i]==sf )
3821 0 : break;
3822 0 : replace = i==0?cidmaster->subfonts[1]:cidmaster->subfonts[i-1];
3823 0 : while ( i<cidmaster->subfontcnt-1 ) {
3824 0 : cidmaster->subfonts[i] = cidmaster->subfonts[i+1];
3825 0 : ++i;
3826 : }
3827 0 : --cidmaster->subfontcnt;
3828 :
3829 0 : for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) ) {
3830 0 : if ( fvs->b.sf==sf )
3831 0 : CIDSetEncMap((FontViewBase *) fvs,replace);
3832 : }
3833 0 : FontViewReformatAll(fv->b.sf);
3834 0 : SplineFontFree(sf);
3835 : }
3836 :
3837 0 : static void FVMenuCIDFontInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3838 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3839 0 : SplineFont *cidmaster = fv->b.cidmaster;
3840 :
3841 0 : if ( cidmaster==NULL )
3842 0 : return;
3843 0 : FontInfo(cidmaster,fv->b.active_layer,-1,false);
3844 : }
3845 :
3846 0 : static void FVMenuChangeSupplement(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3847 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3848 0 : SplineFont *cidmaster = fv->b.cidmaster;
3849 : struct cidmap *cidmap;
3850 : char buffer[20];
3851 : char *ret, *end;
3852 : int supple;
3853 :
3854 0 : if ( cidmaster==NULL )
3855 0 : return;
3856 0 : sprintf(buffer,"%d",cidmaster->supplement);
3857 0 : ret = gwwv_ask_string(_("Change Supplement..."),buffer,_("Please specify a new supplement for %.20s-%.20s"),
3858 : cidmaster->cidregistry,cidmaster->ordering);
3859 0 : if ( ret==NULL )
3860 0 : return;
3861 0 : supple = strtol(ret,&end,10);
3862 0 : if ( *end!='\0' || supple<=0 ) {
3863 0 : free(ret);
3864 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
3865 0 : return;
3866 : }
3867 0 : free(ret);
3868 0 : if ( supple!=cidmaster->supplement ) {
3869 : /* this will make noises if it can't find an appropriate cidmap */
3870 0 : cidmap = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,supple,cidmaster);
3871 0 : cidmaster->supplement = supple;
3872 0 : FontViewSetTitle(fv);
3873 : }
3874 : }
3875 :
3876 0 : static SplineChar *FVFindACharInDisplay(FontView *fv) {
3877 : int start, end, enc, gid;
3878 0 : EncMap *map = fv->b.map;
3879 0 : SplineFont *sf = fv->b.sf;
3880 : SplineChar *sc;
3881 :
3882 0 : start = fv->rowoff*fv->colcnt;
3883 0 : end = start + fv->rowcnt*fv->colcnt;
3884 0 : for ( enc = start; enc<end && enc<map->enccount; ++enc ) {
3885 0 : if ( (gid=map->map[enc])!=-1 && (sc=sf->glyphs[gid])!=NULL )
3886 0 : return( sc );
3887 : }
3888 0 : return( NULL );
3889 : }
3890 :
3891 0 : static void FVMenuReencode(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3892 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3893 0 : Encoding *enc = NULL;
3894 : SplineChar *sc;
3895 :
3896 0 : sc = FVFindACharInDisplay(fv);
3897 0 : enc = FindOrMakeEncoding(mi->ti.userdata);
3898 0 : if ( enc==NULL ) {
3899 0 : IError("Known encoding could not be found");
3900 0 : return;
3901 : }
3902 0 : FVReencode((FontViewBase *) fv,enc);
3903 0 : if ( sc!=NULL ) {
3904 0 : int enc = fv->b.map->backmap[sc->orig_pos];
3905 0 : if ( enc!=-1 )
3906 0 : FVScrollToChar(fv,enc);
3907 : }
3908 : }
3909 :
3910 0 : static void FVMenuForceEncode(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
3911 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3912 0 : Encoding *enc = NULL;
3913 0 : int oldcnt = fv->b.map->enccount;
3914 :
3915 0 : enc = FindOrMakeEncoding(mi->ti.userdata);
3916 0 : if ( enc==NULL ) {
3917 0 : IError("Known encoding could not be found");
3918 0 : return;
3919 : }
3920 0 : SFForceEncoding(fv->b.sf,fv->b.map,enc);
3921 0 : if ( oldcnt < fv->b.map->enccount ) {
3922 0 : fv->b.selected = realloc(fv->b.selected,fv->b.map->enccount);
3923 0 : memset(fv->b.selected+oldcnt,0,fv->b.map->enccount-oldcnt);
3924 : }
3925 0 : if ( fv->b.normal!=NULL ) {
3926 0 : EncMapFree(fv->b.normal);
3927 0 : if (fv->b.normal == fv->b.sf->map) { fv->b.sf->map = NULL; }
3928 0 : fv->b.normal = NULL;
3929 : }
3930 0 : SFReplaceEncodingBDFProps(fv->b.sf,fv->b.map);
3931 0 : FontViewSetTitle(fv);
3932 0 : FontViewReformatOne(&fv->b);
3933 : }
3934 :
3935 0 : static void FVMenuDisplayByGroups(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3936 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3937 :
3938 0 : DisplayGroups(fv);
3939 0 : }
3940 :
3941 0 : static void FVMenuDefineGroups(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3942 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3943 :
3944 0 : DefineGroups(fv);
3945 0 : }
3946 :
3947 0 : static void FVMenuMMValid(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3948 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3949 0 : MMSet *mm = fv->b.sf->mm;
3950 :
3951 0 : if ( mm==NULL )
3952 0 : return;
3953 0 : MMValid(mm,true);
3954 : }
3955 :
3956 0 : static void FVMenuCreateMM(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3957 0 : MMWizard(NULL);
3958 0 : }
3959 :
3960 0 : static void FVMenuMMInfo(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3961 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3962 0 : MMSet *mm = fv->b.sf->mm;
3963 :
3964 0 : if ( mm==NULL )
3965 0 : return;
3966 0 : MMWizard(mm);
3967 : }
3968 :
3969 0 : static void FVMenuChangeMMBlend(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3970 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3971 0 : MMSet *mm = fv->b.sf->mm;
3972 :
3973 0 : if ( mm==NULL || mm->apple )
3974 0 : return;
3975 0 : MMChangeBlend(mm,fv,false);
3976 : }
3977 :
3978 0 : static void FVMenuBlendToNew(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
3979 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
3980 0 : MMSet *mm = fv->b.sf->mm;
3981 :
3982 0 : if ( mm==NULL )
3983 0 : return;
3984 0 : MMChangeBlend(mm,fv,true);
3985 : }
3986 :
3987 0 : static void cflistcheck(GWindow UNUSED(gw), struct gmenuitem *mi, GEvent *UNUSED(e)) {
3988 : /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
3989 :
3990 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
3991 0 : switch ( mi->mid ) {
3992 : case MID_AllFonts:
3993 0 : mi->ti.checked = !onlycopydisplayed;
3994 0 : break;
3995 : case MID_DisplayedFont:
3996 0 : mi->ti.checked = onlycopydisplayed;
3997 0 : break;
3998 : case MID_CharName:
3999 0 : mi->ti.checked = copymetadata;
4000 0 : break;
4001 : case MID_TTFInstr:
4002 0 : mi->ti.checked = copyttfinstr;
4003 0 : break;
4004 : }
4005 : }
4006 0 : }
4007 :
4008 0 : static void sllistcheck(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4009 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4010 0 : fv = fv;
4011 0 : }
4012 :
4013 0 : static void htlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4014 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4015 0 : int anychars = FVAnyCharSelected(fv);
4016 0 : int multilayer = fv->b.sf->multilayer;
4017 :
4018 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4019 0 : switch ( mi->mid ) {
4020 : case MID_AutoHint:
4021 0 : mi->ti.disabled = anychars==-1 || multilayer;
4022 0 : break;
4023 : case MID_HintSubsPt:
4024 0 : mi->ti.disabled = fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4025 0 : if ( fv->b.sf->mm!=NULL && fv->b.sf->mm->apple )
4026 0 : mi->ti.disabled = true;
4027 0 : break;
4028 : case MID_AutoCounter: case MID_DontAutoHint:
4029 0 : mi->ti.disabled = fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4030 0 : break;
4031 : case MID_AutoInstr: case MID_EditInstructions: case MID_Deltas:
4032 0 : mi->ti.disabled = !fv->b.sf->layers[fv->b.active_layer].order2 || anychars==-1 || multilayer;
4033 0 : break;
4034 : case MID_RmInstrTables:
4035 0 : mi->ti.disabled = fv->b.sf->ttf_tables==NULL;
4036 0 : break;
4037 : case MID_Editfpgm: case MID_Editprep: case MID_Editcvt: case MID_Editmaxp:
4038 0 : mi->ti.disabled = !fv->b.sf->layers[fv->b.active_layer].order2 || multilayer;
4039 0 : break;
4040 : case MID_ClearHints: case MID_ClearWidthMD: case MID_ClearInstrs:
4041 0 : mi->ti.disabled = anychars==-1;
4042 0 : break;
4043 : }
4044 : }
4045 0 : }
4046 :
4047 0 : static void fllistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4048 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4049 0 : int anychars = FVAnyCharSelected(fv);
4050 : FontView *fvs;
4051 0 : int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
4052 :
4053 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4054 0 : switch ( mi->mid ) {
4055 : case MID_GenerateTTC:
4056 0 : for ( fvs=fv_list; fvs!=NULL; fvs=(FontView *) (fvs->b.next) ) {
4057 0 : if ( fvs!=fv )
4058 0 : break;
4059 : }
4060 0 : mi->ti.disabled = fvs==NULL;
4061 0 : break;
4062 : case MID_Revert:
4063 0 : mi->ti.disabled = fv->b.sf->origname==NULL || fv->b.sf->new;
4064 0 : break;
4065 : case MID_RevertToBackup:
4066 : /* We really do want to use filename here and origname above */
4067 0 : mi->ti.disabled = true;
4068 0 : if ( fv->b.sf->filename!=NULL ) {
4069 0 : if ( fv->b.sf->backedup == bs_dontknow ) {
4070 0 : char *buf = malloc(strlen(fv->b.sf->filename)+20);
4071 0 : strcpy(buf,fv->b.sf->filename);
4072 0 : if ( fv->b.sf->compression!=0 )
4073 0 : strcat(buf,compressors[fv->b.sf->compression-1].ext);
4074 0 : strcat(buf,"~");
4075 0 : if ( access(buf,F_OK)==0 )
4076 0 : fv->b.sf->backedup = bs_backedup;
4077 : else
4078 0 : fv->b.sf->backedup = bs_not;
4079 0 : free(buf);
4080 : }
4081 0 : if ( fv->b.sf->backedup == bs_backedup )
4082 0 : mi->ti.disabled = false;
4083 : }
4084 0 : break;
4085 : case MID_RevertGlyph:
4086 0 : mi->ti.disabled = fv->b.sf->origname==NULL || fv->b.sf->sfd_version<2 || anychars==-1 || fv->b.sf->compression!=0;
4087 0 : break;
4088 : case MID_Recent:
4089 0 : mi->ti.disabled = !RecentFilesAny();
4090 0 : break;
4091 : case MID_ScriptMenu:
4092 0 : mi->ti.disabled = script_menu_names[0]==NULL;
4093 0 : break;
4094 : case MID_Print:
4095 0 : mi->ti.disabled = fv->b.sf->onlybitmaps || in_modal;
4096 0 : break;
4097 : }
4098 : }
4099 0 : }
4100 :
4101 0 : static void edlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4102 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4103 0 : int pos = FVAnyCharSelected(fv), i, gid;
4104 0 : int not_pasteable = pos==-1 ||
4105 0 : (!CopyContainsSomething() &&
4106 : #ifndef _NO_LIBPNG
4107 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/png") &&
4108 : #endif
4109 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/svg+xml") &&
4110 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/svg-xml") &&
4111 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/svg") &&
4112 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/bmp") &&
4113 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/eps") &&
4114 0 : !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/ps"));
4115 0 : RefChar *base = CopyContainsRef(fv->b.sf);
4116 0 : int base_enc = base!=NULL ? fv->b.map->backmap[base->orig_pos] : -1;
4117 :
4118 :
4119 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4120 0 : switch ( mi->mid ) {
4121 : case MID_Paste: case MID_PasteInto:
4122 0 : mi->ti.disabled = not_pasteable;
4123 0 : break;
4124 : case MID_PasteAfter:
4125 0 : mi->ti.disabled = not_pasteable || pos<0;
4126 0 : break;
4127 : case MID_SameGlyphAs:
4128 0 : mi->ti.disabled = not_pasteable || base==NULL || fv->b.cidmaster!=NULL ||
4129 0 : base_enc==-1 ||
4130 0 : fv->b.selected[base_enc]; /* Can't be self-referential */
4131 0 : break;
4132 : case MID_Join:
4133 : case MID_Cut: case MID_Copy: case MID_Clear:
4134 : case MID_CopyWidth: case MID_CopyLBearing: case MID_CopyRBearing:
4135 : case MID_CopyRef: case MID_UnlinkRef:
4136 : case MID_RemoveUndoes: case MID_CopyFgToBg: case MID_CopyL2L:
4137 0 : mi->ti.disabled = pos==-1;
4138 0 : break;
4139 : case MID_RplRef:
4140 : case MID_CorrectRefs:
4141 0 : mi->ti.disabled = pos==-1 || fv->b.cidmaster!=NULL || fv->b.sf->multilayer;
4142 0 : break;
4143 : case MID_CopyLookupData:
4144 0 : mi->ti.disabled = pos==-1 || (fv->b.sf->gpos_lookups==NULL && fv->b.sf->gsub_lookups==NULL);
4145 0 : break;
4146 : case MID_CopyVWidth:
4147 0 : mi->ti.disabled = pos==-1 || !fv->b.sf->hasvmetrics;
4148 0 : break;
4149 : case MID_ClearBackground:
4150 0 : mi->ti.disabled = true;
4151 0 : if ( pos!=-1 && !( onlycopydisplayed && fv->filled!=fv->show )) {
4152 0 : for ( i=0; i<fv->b.map->enccount; ++i )
4153 0 : if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4154 0 : fv->b.sf->glyphs[gid]!=NULL )
4155 0 : if ( fv->b.sf->glyphs[gid]->layers[ly_back].images!=NULL ||
4156 0 : fv->b.sf->glyphs[gid]->layers[ly_back].splines!=NULL ) {
4157 0 : mi->ti.disabled = false;
4158 0 : break;
4159 : }
4160 : }
4161 0 : break;
4162 : case MID_Undo:
4163 0 : for ( i=0; i<fv->b.map->enccount; ++i )
4164 0 : if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4165 0 : fv->b.sf->glyphs[gid]!=NULL )
4166 0 : if ( fv->b.sf->glyphs[gid]->layers[fv->b.active_layer].undoes!=NULL )
4167 0 : break;
4168 0 : mi->ti.disabled = i==fv->b.map->enccount;
4169 0 : break;
4170 : case MID_Redo:
4171 0 : for ( i=0; i<fv->b.map->enccount; ++i )
4172 0 : if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4173 0 : fv->b.sf->glyphs[gid]!=NULL )
4174 0 : if ( fv->b.sf->glyphs[gid]->layers[fv->b.active_layer].redoes!=NULL )
4175 0 : break;
4176 0 : mi->ti.disabled = i==fv->b.map->enccount;
4177 0 : break;
4178 : case MID_UndoFontLevel:
4179 0 : mi->ti.disabled = dlist_isempty( (struct dlistnode **)&fv->b.sf->undoes );
4180 0 : break;
4181 : }
4182 : }
4183 0 : }
4184 :
4185 0 : static void trlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4186 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4187 0 : int anychars = FVAnyCharSelected(fv);
4188 :
4189 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4190 0 : switch ( mi->mid ) {
4191 : case MID_Transform:
4192 0 : mi->ti.disabled = anychars==-1;
4193 0 : break;
4194 : case MID_NLTransform: case MID_POV:
4195 0 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4196 0 : break;
4197 : }
4198 : }
4199 0 : }
4200 :
4201 0 : static void validlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4202 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4203 0 : int anychars = FVAnyCharSelected(fv);
4204 :
4205 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4206 0 : switch ( mi->mid ) {
4207 : case MID_FindProblems:
4208 0 : mi->ti.disabled = anychars==-1;
4209 0 : break;
4210 : case MID_Validate:
4211 0 : mi->ti.disabled = fv->b.sf->strokedfont || fv->b.sf->multilayer;
4212 0 : break;
4213 : }
4214 : }
4215 0 : }
4216 :
4217 0 : static void ellistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4218 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4219 0 : int anychars = FVAnyCharSelected(fv), gid;
4220 : int anybuildable, anytraceable;
4221 0 : int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
4222 :
4223 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4224 0 : switch ( mi->mid ) {
4225 : case MID_FontInfo:
4226 0 : mi->ti.disabled = in_modal;
4227 0 : break;
4228 : case MID_CharInfo:
4229 0 : mi->ti.disabled = anychars<0 || (gid = fv->b.map->map[anychars])==-1 ||
4230 0 : (fv->b.cidmaster!=NULL && fv->b.sf->glyphs[gid]==NULL) ||
4231 : in_modal;
4232 0 : break;
4233 : case MID_Transform:
4234 0 : mi->ti.disabled = anychars==-1;
4235 : /* some Transformations make sense on bitmaps now */
4236 0 : break;
4237 : case MID_AddExtrema:
4238 0 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4239 0 : break;
4240 : case MID_Simplify:
4241 : case MID_Stroke: case MID_RmOverlap:
4242 0 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4243 0 : break;
4244 : case MID_Styles:
4245 0 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4246 0 : break;
4247 : case MID_Round: case MID_Correct:
4248 0 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4249 0 : break;
4250 : #ifdef FONTFORGE_CONFIG_TILEPATH
4251 : case MID_TilePath:
4252 : mi->ti.disabled = anychars==-1 || fv->b.sf->onlybitmaps;
4253 : break;
4254 : #endif
4255 : case MID_AvailBitmaps:
4256 0 : mi->ti.disabled = fv->b.sf->mm!=NULL;
4257 0 : break;
4258 : case MID_RegenBitmaps: case MID_RemoveBitmaps:
4259 0 : mi->ti.disabled = fv->b.sf->bitmaps==NULL || fv->b.sf->onlybitmaps ||
4260 0 : fv->b.sf->mm!=NULL;
4261 0 : break;
4262 : case MID_BuildAccent:
4263 0 : anybuildable = false;
4264 0 : if ( anychars!=-1 ) {
4265 : int i;
4266 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4267 0 : SplineChar *sc=NULL, dummy;
4268 0 : gid = fv->b.map->map[i];
4269 0 : if ( gid!=-1 )
4270 0 : sc = fv->b.sf->glyphs[gid];
4271 0 : if ( sc==NULL )
4272 0 : sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4273 0 : if ( SFIsSomethingBuildable(fv->b.sf,sc,fv->b.active_layer,false) ||
4274 0 : SFIsDuplicatable(fv->b.sf,sc)) {
4275 0 : anybuildable = true;
4276 0 : break;
4277 : }
4278 : }
4279 : }
4280 0 : mi->ti.disabled = !anybuildable;
4281 0 : break;
4282 : case MID_Autotrace:
4283 0 : anytraceable = false;
4284 0 : if ( FindAutoTraceName()!=NULL && anychars!=-1 ) {
4285 : int i;
4286 0 : for ( i=0; i<fv->b.map->enccount; ++i )
4287 0 : if ( fv->b.selected[i] && (gid = fv->b.map->map[i])!=-1 &&
4288 0 : fv->b.sf->glyphs[gid]!=NULL &&
4289 0 : fv->b.sf->glyphs[gid]->layers[ly_back].images!=NULL ) {
4290 0 : anytraceable = true;
4291 0 : break;
4292 : }
4293 : }
4294 0 : mi->ti.disabled = !anytraceable;
4295 0 : break;
4296 : case MID_MergeFonts:
4297 0 : mi->ti.disabled = fv->b.sf->bitmaps!=NULL && fv->b.sf->onlybitmaps;
4298 0 : break;
4299 : case MID_FontCompare:
4300 0 : mi->ti.disabled = fv_list->b.next==NULL;
4301 0 : break;
4302 : case MID_InterpolateFonts:
4303 0 : mi->ti.disabled = fv->b.sf->onlybitmaps;
4304 0 : break;
4305 : }
4306 : }
4307 0 : }
4308 :
4309 0 : static void mtlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4310 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4311 0 : int anychars = FVAnyCharSelected(fv);
4312 :
4313 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4314 0 : switch ( mi->mid ) {
4315 : case MID_Center: case MID_Thirds: case MID_SetWidth:
4316 : case MID_SetLBearing: case MID_SetRBearing: case MID_SetBearings:
4317 0 : mi->ti.disabled = anychars==-1;
4318 0 : break;
4319 : case MID_SetVWidth:
4320 0 : mi->ti.disabled = anychars==-1 || !fv->b.sf->hasvmetrics;
4321 0 : break;
4322 : case MID_VKernByClass:
4323 : case MID_VKernFromH:
4324 : case MID_RmVKern:
4325 0 : mi->ti.disabled = !fv->b.sf->hasvmetrics;
4326 0 : break;
4327 : }
4328 : }
4329 0 : }
4330 :
4331 : #if HANYANG
4332 : static void hglistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4333 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4334 :
4335 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4336 : if ( mi->mid==MID_BuildSyllables || mi->mid==MID_ModifyComposition )
4337 : mi->ti.disabled = fv->b.sf->rules==NULL;
4338 : }
4339 : }
4340 :
4341 : static GMenuItem2 hglist[] = {
4342 : { { (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 },
4343 : { { (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 },
4344 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, }},
4345 : { { (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 },
4346 : { NULL }
4347 : };
4348 : #endif
4349 :
4350 0 : static void balistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4351 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4352 :
4353 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4354 0 : if ( mi->mid==MID_BuildAccent || mi->mid==MID_BuildComposite ) {
4355 0 : int anybuildable = false;
4356 0 : int onlyaccents = mi->mid==MID_BuildAccent;
4357 : int i, gid;
4358 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4359 0 : SplineChar *sc=NULL, dummy;
4360 0 : if ( (gid=fv->b.map->map[i])!=-1 )
4361 0 : sc = fv->b.sf->glyphs[gid];
4362 0 : if ( sc==NULL )
4363 0 : sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4364 0 : if ( SFIsSomethingBuildable(fv->b.sf,sc,fv->b.active_layer,onlyaccents)) {
4365 0 : anybuildable = true;
4366 0 : break;
4367 : }
4368 : }
4369 0 : mi->ti.disabled = !anybuildable;
4370 0 : } else if ( mi->mid==MID_BuildDuplicates ) {
4371 0 : int anybuildable = false;
4372 : int i, gid;
4373 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] ) {
4374 0 : SplineChar *sc=NULL, dummy;
4375 0 : if ( (gid=fv->b.map->map[i])!=-1 )
4376 0 : sc = fv->b.sf->glyphs[gid];
4377 0 : if ( sc==NULL )
4378 0 : sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,i);
4379 0 : if ( SFIsDuplicatable(fv->b.sf,sc)) {
4380 0 : anybuildable = true;
4381 0 : break;
4382 : }
4383 : }
4384 0 : mi->ti.disabled = !anybuildable;
4385 : }
4386 : }
4387 0 : }
4388 :
4389 0 : static void delistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4390 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4391 0 : int i = FVAnyCharSelected(fv);
4392 0 : int gid = i<0 ? -1 : fv->b.map->map[i];
4393 :
4394 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4395 0 : switch ( mi->mid ) {
4396 : case MID_ShowDependentRefs:
4397 0 : mi->ti.disabled = gid<0 || fv->b.sf->glyphs[gid]==NULL ||
4398 0 : fv->b.sf->glyphs[gid]->dependents == NULL;
4399 0 : break;
4400 : case MID_ShowDependentSubs:
4401 0 : mi->ti.disabled = gid<0 || fv->b.sf->glyphs[gid]==NULL ||
4402 0 : !SCUsedBySubs(fv->b.sf->glyphs[gid]);
4403 0 : break;
4404 : }
4405 : }
4406 0 : }
4407 :
4408 0 : static void infolistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4409 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4410 0 : int anychars = FVAnyCharSelected(fv);
4411 :
4412 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4413 0 : switch ( mi->mid ) {
4414 : case MID_StrikeInfo:
4415 0 : mi->ti.disabled = fv->b.sf->bitmaps==NULL;
4416 0 : break;
4417 : case MID_MassRename:
4418 0 : mi->ti.disabled = anychars==-1;
4419 0 : break;
4420 : case MID_SetColor:
4421 0 : mi->ti.disabled = anychars==-1;
4422 0 : break;
4423 : }
4424 : }
4425 0 : }
4426 :
4427 : static GMenuItem2 dummyitem[] = {
4428 : { { (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 },
4429 : GMENUITEM2_EMPTY
4430 : };
4431 :
4432 : static GMenuItem2 fllist[] = {
4433 : { { (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 },
4434 : #if HANYANG
4435 : { { (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 },
4436 : #endif
4437 : { { (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 },
4438 : { { (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 },
4439 : { { (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 },
4440 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4441 : { { (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 },
4442 : { { (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 },
4443 : { { (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 },
4444 : { { (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 },
4445 : { { (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 },
4446 : { { (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 },
4447 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4448 : { { (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 },
4449 : { { (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 Kern Info...|No Shortcut"), NULL, NULL, FVMenuMergeKern, 0 },
4450 : { { (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 },
4451 : { { (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 },
4452 : { { (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 },
4453 : { { (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 },
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_("_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 },
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 : #if !defined(_NO_PYTHON)
4458 : { { (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 },
4459 : #elif !defined(_NO_FFSCRIPT)
4460 : { { (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 },
4461 : #endif
4462 : #if !defined(_NO_FFSCRIPT)
4463 : { { (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 },
4464 : #endif
4465 : #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
4466 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4467 : #endif
4468 : { { (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 },
4469 : { { (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 },
4470 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4471 : { { (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 */
4472 : NULL, NULL, FVMenuExit, 0 },
4473 : GMENUITEM2_EMPTY
4474 : };
4475 :
4476 : static GMenuItem2 cflist[] = {
4477 : { { (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 },
4478 : { { (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 },
4479 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4480 : { { (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 },
4481 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4482 : { { (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 },
4483 : GMENUITEM2_EMPTY
4484 : };
4485 :
4486 : static GMenuItem2 sclist[] = {
4487 : { { (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_("Color Choose|No Shortcut"), NULL, NULL, FVMenuSelectColor, 0 },
4488 : { { (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 },
4489 : { { 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 },
4490 : { { 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 },
4491 : { { 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 },
4492 : { { 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 },
4493 : { { 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 },
4494 : { { 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 },
4495 : { { 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 },
4496 : GMENUITEM2_EMPTY
4497 : };
4498 :
4499 : static GMenuItem2 sllist[] = {
4500 : { { (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 },
4501 : { { (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 },
4502 : { { (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 },
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_("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 },
4505 : { { (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 },
4506 : { { (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 },
4507 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4508 : { { (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 },
4509 : { { (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 },
4510 : { { (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 },
4511 : { { (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 },
4512 : { { (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 },
4513 : { { (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 },
4514 : { { (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 },
4515 : { { (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 },
4516 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4517 : { { (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 },
4518 : { { (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 },
4519 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4520 : { { (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 },
4521 : GMENUITEM2_EMPTY
4522 : };
4523 :
4524 : static GMenuItem2 edlist[] = {
4525 : { { (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 },
4526 : { { (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},
4527 : { { (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 },
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_("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 },
4530 : { { (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 },
4531 : { { (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 },
4532 : { { (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 },
4533 : { { (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 },
4534 : { { (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 },
4535 : { { (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 },
4536 : { { (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 },
4537 : { { (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 },
4538 : { { (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 },
4539 : { { (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 },
4540 : { { (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 },
4541 : { { (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 },
4542 : { { (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 },
4543 : { { (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 },
4544 : { { (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 },
4545 : { { (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 },
4546 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4547 : { { (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 },
4548 : { { (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 },
4549 : { { (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 },
4550 : { { (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 },
4551 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4552 : { { (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 },
4553 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4554 : { { (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 },
4555 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4556 : { { (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 },
4557 : GMENUITEM2_EMPTY
4558 : };
4559 :
4560 : static GMenuItem2 smlist[] = {
4561 : { { (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 },
4562 : { { (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 },
4563 : { { (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 },
4564 : { { (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 },
4565 : { { (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 },
4566 : GMENUITEM2_EMPTY
4567 : };
4568 :
4569 : static GMenuItem2 rmlist[] = {
4570 : { { (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 },
4571 : { { (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 },
4572 : { { (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 },
4573 : GMENUITEM2_EMPTY
4574 : };
4575 :
4576 : static GMenuItem2 eflist[] = {
4577 : { { (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 },
4578 : { { (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 },
4579 : { { (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 },
4580 : { { (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...|No Shortcut"), NULL, NULL, FVMenuCondense, MID_Condense },
4581 : { { (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 XHeight...|No Shortcut"), NULL, NULL, FVMenuChangeXHeight, MID_ChangeXHeight },
4582 : { { (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 },
4583 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4584 : { { (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 Caps...|No Shortcut"), NULL, NULL, FVMenuSmallCaps, MID_SmallCaps },
4585 : { { (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 },
4586 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4587 : { { (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 },
4588 : { { (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 },
4589 : { { (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 },
4590 : { { (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 },
4591 : GMENUITEM2_EMPTY
4592 : };
4593 :
4594 : static GMenuItem2 balist[] = {
4595 : { { (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 },
4596 : { { (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 },
4597 : { { (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 },
4598 : #ifdef KOREAN
4599 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4600 : { { (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 },
4601 : #endif
4602 : GMENUITEM2_EMPTY
4603 : };
4604 :
4605 : static GMenuItem2 delist[] = {
4606 : { { (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 },
4607 : { { (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 },
4608 : GMENUITEM2_EMPTY
4609 : };
4610 :
4611 : static GMenuItem2 trlist[] = {
4612 : { { (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 },
4613 : { { (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 },
4614 : { { (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 },
4615 : GMENUITEM2_EMPTY
4616 : };
4617 :
4618 : static GMenuItem2 rndlist[] = {
4619 : { { (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 },
4620 : { { (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 },
4621 : { { (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 },
4622 : GMENUITEM2_EMPTY
4623 : };
4624 :
4625 : static GMenuItem2 scollist[] = {
4626 : { { (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_("Color Choose|No Shortcut"), NULL, NULL, FVMenuSetColor, 0 },
4627 : { { (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 },
4628 : { { 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 },
4629 : { { 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 },
4630 : { { 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 },
4631 : { { 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 },
4632 : { { 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 },
4633 : { { 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 },
4634 : { { 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 },
4635 : GMENUITEM2_EMPTY
4636 : };
4637 :
4638 : static GMenuItem2 infolist[] = {
4639 : { { (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 },
4640 : { { (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 },
4641 : { { (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 },
4642 : { { (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 },
4643 : { { (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 },
4644 : { { (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 },
4645 : { { (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 },
4646 : { { (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 },
4647 : GMENUITEM2_EMPTY
4648 : };
4649 :
4650 : static GMenuItem2 validlist[] = {
4651 : { { (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 },
4652 : { { (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 },
4653 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4654 : { { (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 },
4655 : GMENUITEM2_EMPTY
4656 : };
4657 :
4658 : static GMenuItem2 ellist[] = {
4659 : { { (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 },
4660 : { { (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 },
4661 : { { (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 },
4662 : { { (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 },
4663 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4664 : { { (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 },
4665 : { { (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 },
4666 : { { (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 },
4667 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4668 : { { (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 },
4669 : { { (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 },
4670 : { { (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 },
4671 : #ifdef FONTFORGE_CONFIG_TILEPATH
4672 : { { (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 },
4673 : { { (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 },
4674 : #endif
4675 : { { (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 },
4676 : { { (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 },
4677 : { { (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 },
4678 : { { (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 },
4679 : { { (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 },
4680 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4681 : { { (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 },
4682 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4683 : { { (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 },
4684 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
4685 : { { (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 },
4686 : { { (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 },
4687 : { { (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 },
4688 : { { (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 },
4689 : GMENUITEM2_EMPTY
4690 : };
4691 :
4692 : static GMenuItem2 dummyall[] = {
4693 : { { (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 },
4694 : GMENUITEM2_EMPTY
4695 : };
4696 :
4697 : /* Builds up a menu containing all the anchor classes */
4698 0 : static void aplistbuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4699 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4700 :
4701 0 : GMenuItemArrayFree(mi->sub);
4702 0 : mi->sub = NULL;
4703 :
4704 0 : _aplistbuild(mi,fv->b.sf,FVMenuAnchorPairs);
4705 0 : }
4706 :
4707 : static GMenuItem2 cblist[] = {
4708 : { { (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 },
4709 : { { (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 },
4710 : { { (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 },
4711 : GMENUITEM2_EMPTY
4712 : };
4713 :
4714 0 : static void cblistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4715 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4716 0 : SplineFont *sf = fv->b.sf;
4717 0 : int i, anyligs=0, anykerns=0, gid;
4718 : PST *pst;
4719 :
4720 0 : if ( sf->kerns ) anykerns=true;
4721 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( (gid = fv->b.map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
4722 0 : for ( pst=sf->glyphs[gid]->possub; pst!=NULL; pst=pst->next ) {
4723 0 : if ( pst->type==pst_ligature ) {
4724 0 : anyligs = true;
4725 0 : if ( anykerns )
4726 0 : break;
4727 : }
4728 : }
4729 0 : if ( sf->glyphs[gid]->kerns!=NULL ) {
4730 0 : anykerns = true;
4731 0 : if ( anyligs )
4732 0 : break;
4733 : }
4734 : }
4735 :
4736 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4737 0 : switch ( mi->mid ) {
4738 : case MID_Ligatures:
4739 0 : mi->ti.disabled = !anyligs;
4740 0 : break;
4741 : case MID_KernPairs:
4742 0 : mi->ti.disabled = !anykerns;
4743 0 : break;
4744 : case MID_AnchorPairs:
4745 0 : mi->ti.disabled = sf->anchor==NULL;
4746 0 : break;
4747 : }
4748 : }
4749 0 : }
4750 :
4751 :
4752 : static GMenuItem2 gllist[] = {
4753 : { { (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 },
4754 : { { (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 },
4755 : { { (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 },
4756 : { { (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 },
4757 : GMENUITEM2_EMPTY
4758 : };
4759 :
4760 0 : static void gllistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4761 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4762 :
4763 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
4764 0 : mi->ti.checked = fv->glyphlabel == mi->mid;
4765 : }
4766 0 : }
4767 :
4768 : static GMenuItem2 emptymenu[] = {
4769 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0},
4770 : GMENUITEM2_EMPTY
4771 : };
4772 :
4773 0 : static void FVEncodingMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4774 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4775 :
4776 0 : if ( mi->sub!=NULL ) {
4777 0 : GMenuItemArrayFree(mi->sub);
4778 0 : mi->sub = NULL;
4779 : }
4780 0 : mi->sub = GetEncodingMenu(FVMenuReencode,fv->b.map->enc);
4781 0 : }
4782 :
4783 0 : static void FVMenuAddUnencoded(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4784 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4785 : char *ret, *end;
4786 : int cnt;
4787 :
4788 0 : 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?"));
4789 0 : if ( ret==NULL )
4790 0 : return;
4791 0 : cnt = strtol(ret,&end,10);
4792 0 : if ( *end!='\0' || cnt<=0 ) {
4793 0 : free(ret);
4794 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
4795 0 : return;
4796 : }
4797 0 : free(ret);
4798 0 : FVAddUnencoded((FontViewBase *) fv, cnt);
4799 : }
4800 :
4801 0 : static void FVMenuRemoveUnused(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4802 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4803 0 : FVRemoveUnused((FontViewBase *) fv);
4804 0 : }
4805 :
4806 0 : static void FVMenuCompact(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4807 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4808 : SplineChar *sc;
4809 :
4810 0 : sc = FVFindACharInDisplay(fv);
4811 0 : FVCompact((FontViewBase *) fv);
4812 0 : if ( sc!=NULL ) {
4813 0 : int enc = fv->b.map->backmap[sc->orig_pos];
4814 0 : if ( enc!=-1 )
4815 0 : FVScrollToChar(fv,enc);
4816 : }
4817 0 : }
4818 :
4819 0 : static void FVMenuDetachGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4820 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4821 0 : FVDetachGlyphs((FontViewBase *) fv);
4822 0 : }
4823 :
4824 0 : static void FVMenuDetachAndRemoveGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4825 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4826 : char *buts[3];
4827 :
4828 0 : buts[0] = _("_Remove");
4829 0 : buts[1] = _("_Cancel");
4830 0 : buts[2] = NULL;
4831 :
4832 0 : 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 )
4833 0 : return;
4834 :
4835 0 : FVDetachAndRemoveGlyphs((FontViewBase *) fv);
4836 : }
4837 :
4838 0 : static void FVForceEncodingMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
4839 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4840 :
4841 0 : if ( mi->sub!=NULL ) {
4842 0 : GMenuItemArrayFree(mi->sub);
4843 0 : mi->sub = NULL;
4844 : }
4845 0 : mi->sub = GetEncodingMenu(FVMenuForceEncode,fv->b.map->enc);
4846 0 : }
4847 :
4848 0 : static void FVMenuAddEncodingName(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4849 : char *ret;
4850 : Encoding *enc;
4851 :
4852 : /* Search the iconv database for the named encoding */
4853 0 : 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."));
4854 0 : if ( ret==NULL )
4855 0 : return;
4856 0 : enc = FindOrMakeEncoding(ret);
4857 0 : if ( enc==NULL )
4858 0 : ff_post_error(_("Invalid Encoding"),_("Invalid Encoding"));
4859 0 : free(ret);
4860 : }
4861 :
4862 0 : static void FVMenuLoadEncoding(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4863 0 : LoadEncodingFile();
4864 0 : }
4865 :
4866 0 : static void FVMenuMakeFromFont(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4867 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4868 0 : (void) MakeEncoding(fv->b.sf,fv->b.map);
4869 0 : }
4870 :
4871 0 : static void FVMenuRemoveEncoding(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4872 0 : RemoveEncoding();
4873 0 : }
4874 :
4875 0 : static void FVMenuMakeNamelist(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4876 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4877 : char buffer[1025];
4878 : char *filename, *temp;
4879 : FILE *file;
4880 :
4881 0 : snprintf(buffer, sizeof(buffer),"%s/%s.nam", getFontForgeUserDir(Config), fv->b.sf->fontname );
4882 0 : temp = def2utf8_copy(buffer);
4883 0 : filename = gwwv_save_filename(_("Make Namelist"), temp,"*.nam");
4884 0 : free(temp);
4885 0 : if ( filename==NULL )
4886 0 : return;
4887 0 : temp = utf82def_copy(filename);
4888 0 : file = fopen(temp,"w");
4889 0 : free(temp);
4890 0 : if ( file==NULL ) {
4891 0 : ff_post_error(_("Namelist creation failed"),_("Could not write %s"), filename);
4892 0 : free(filename);
4893 0 : return;
4894 : }
4895 0 : FVB_MakeNamelist((FontViewBase *) fv, file);
4896 0 : fclose(file);
4897 : }
4898 :
4899 0 : static void FVMenuLoadNamelist(GWindow UNUSED(gw), struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4900 : /* Read in a name list and copy it into the prefs dir so that we'll find */
4901 : /* it in the future */
4902 : /* Be prepared to update what we've already got if names match */
4903 : char buffer[1025];
4904 0 : char *ret = gwwv_open_filename(_("Load Namelist"),NULL,
4905 : "*.nam",NULL);
4906 : char *temp, *pt;
4907 : char *buts[3];
4908 : FILE *old, *new;
4909 : int ch, ans;
4910 : NameList *nl;
4911 :
4912 0 : if ( ret==NULL )
4913 0 : return; /* Cancelled */
4914 0 : temp = utf82def_copy(ret);
4915 0 : pt = strrchr(temp,'/');
4916 0 : if ( pt==NULL )
4917 0 : pt = temp;
4918 : else
4919 0 : ++pt;
4920 0 : snprintf(buffer,sizeof(buffer),"%s/%s", getFontForgeUserDir(Config), pt);
4921 0 : if ( access(buffer,F_OK)==0 ) {
4922 0 : buts[0] = _("_Replace");
4923 0 : buts[1] = _("_Cancel");
4924 0 : buts[2] = NULL;
4925 0 : ans = gwwv_ask( _("Replace"),(const char **) buts,0,1,_("A name list with this name already exists. Replace it?"));
4926 0 : if ( ans==1 ) {
4927 0 : free(temp);
4928 0 : free(ret);
4929 0 : return;
4930 : }
4931 : }
4932 :
4933 0 : old = fopen( temp,"r");
4934 0 : if ( old==NULL ) {
4935 0 : ff_post_error(_("No such file"),_("Could not read %s"), ret );
4936 0 : free(ret); free(temp);
4937 0 : return;
4938 : }
4939 0 : if ( (nl = LoadNamelist(temp))==NULL ) {
4940 0 : ff_post_error(_("Bad namelist file"),_("Could not parse %s"), ret );
4941 0 : free(ret); free(temp);
4942 0 : fclose(old);
4943 0 : return;
4944 : }
4945 0 : free(ret); free(temp);
4946 0 : if ( nl->uses_unicode ) {
4947 0 : if ( nl->a_utf8_name!=NULL )
4948 0 : ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist contains at least one non-ASCII glyph name, namely: %s"), nl->a_utf8_name );
4949 : else
4950 0 : ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist is based on a namelist which contains non-ASCII glyph names"));
4951 : }
4952 :
4953 0 : new = fopen( buffer,"w");
4954 0 : if ( new==NULL ) {
4955 0 : ff_post_error(_("Create failed"),_("Could not write %s"), buffer );
4956 0 : fclose(old);
4957 0 : return;
4958 : }
4959 :
4960 0 : while ( (ch=getc(old))!=EOF )
4961 0 : putc(ch,new);
4962 0 : fclose(old);
4963 0 : fclose(new);
4964 : }
4965 :
4966 0 : static void FVMenuRenameByNamelist(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4967 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4968 0 : char **namelists = AllNamelistNames();
4969 : int i;
4970 : int ret;
4971 : NameList *nl;
4972 : extern int allow_utf8_glyphnames;
4973 :
4974 0 : for ( i=0; namelists[i]!=NULL; ++i );
4975 0 : 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"));
4976 0 : if ( ret==-1 )
4977 0 : return;
4978 0 : nl = NameListByName(namelists[ret]);
4979 0 : if ( nl==NULL ) {
4980 0 : IError("Couldn't find namelist");
4981 0 : return;
4982 0 : } else if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames) {
4983 0 : 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."));
4984 0 : return;
4985 : }
4986 0 : SFRenameGlyphsToNamelist(fv->b.sf,nl);
4987 0 : GDrawRequestExpose(fv->v,NULL,false);
4988 : }
4989 :
4990 0 : static void FVMenuNameGlyphs(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) {
4991 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
4992 : /* Read a file containing a list of names, and add an unencoded glyph for */
4993 : /* each name */
4994 : char buffer[33];
4995 0 : char *ret = gwwv_open_filename(_("Load glyph names"),NULL, "*",NULL);
4996 : char *temp, *pt;
4997 : FILE *file;
4998 : int ch;
4999 : SplineChar *sc;
5000 : FontView *fvs;
5001 :
5002 0 : if ( ret==NULL )
5003 0 : return; /* Cancelled */
5004 0 : temp = utf82def_copy(ret);
5005 :
5006 0 : file = fopen( temp,"r");
5007 0 : if ( file==NULL ) {
5008 0 : ff_post_error(_("No such file"),_("Could not read %s"), ret );
5009 0 : free(ret); free(temp);
5010 0 : return;
5011 : }
5012 0 : pt = buffer;
5013 : for (;;) {
5014 0 : ch = getc(file);
5015 0 : if ( ch!=EOF && !isspace(ch)) {
5016 0 : if ( pt<buffer+sizeof(buffer)-1 )
5017 0 : *pt++ = ch;
5018 : } else {
5019 0 : if ( pt!=buffer ) {
5020 0 : *pt = '\0';
5021 0 : sc = NULL;
5022 0 : for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) ) {
5023 0 : EncMap *map = fvs->b.map;
5024 0 : if ( map->enccount+1>=map->encmax )
5025 0 : map->map = realloc(map->map,(map->encmax += 20)*sizeof(int));
5026 0 : map->map[map->enccount] = -1;
5027 0 : fvs->b.selected = realloc(fvs->b.selected,(map->enccount+1));
5028 0 : memset(fvs->b.selected+map->enccount,0,1);
5029 0 : ++map->enccount;
5030 0 : if ( sc==NULL ) {
5031 0 : sc = SFMakeChar(fv->b.sf,map,map->enccount-1);
5032 0 : free(sc->name);
5033 0 : sc->name = copy(buffer);
5034 0 : sc->comment = copy("."); /* Mark as something for sfd file */
5035 : }
5036 0 : map->map[map->enccount-1] = sc->orig_pos;
5037 0 : map->backmap[sc->orig_pos] = map->enccount-1;
5038 : }
5039 0 : pt = buffer;
5040 : }
5041 0 : if ( ch==EOF )
5042 0 : break;
5043 : }
5044 0 : }
5045 0 : fclose(file);
5046 0 : free(ret); free(temp);
5047 0 : FontViewReformatAll(fv->b.sf);
5048 : }
5049 :
5050 : static GMenuItem2 enlist[] = {
5051 : { { (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 },
5052 : { { (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 },
5053 : { { (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 },
5054 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5055 : { { (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 },
5056 : { { (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 },
5057 : { { (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 },
5058 : { { (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 },
5059 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5060 : { { (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 },
5061 : { { (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 },
5062 : { { (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 },
5063 : { { (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 },
5064 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5065 : { { (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 },
5066 : { { (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 },
5067 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5068 : { { (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 },
5069 : { { (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 },
5070 : { { (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 },
5071 : { { (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 },
5072 : GMENUITEM2_EMPTY
5073 : };
5074 :
5075 0 : static void enlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5076 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5077 : int i, gid;
5078 0 : SplineFont *sf = fv->b.sf;
5079 0 : EncMap *map = fv->b.map;
5080 0 : int anyglyphs = false;
5081 :
5082 0 : for ( i=map->enccount-1; i>=0 ; --i )
5083 0 : if ( fv->b.selected[i] && (gid=map->map[i])!=-1 )
5084 0 : anyglyphs = true;
5085 :
5086 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5087 0 : switch ( mi->mid ) {
5088 : case MID_Compact:
5089 0 : mi->ti.checked = fv->b.normal!=NULL;
5090 0 : break;
5091 : case MID_HideNoGlyphSlots:
5092 0 : break;
5093 : case MID_Reencode: case MID_ForceReencode:
5094 0 : mi->ti.disabled = fv->b.cidmaster!=NULL;
5095 0 : break;
5096 : case MID_DetachGlyphs: case MID_DetachAndRemoveGlyphs:
5097 0 : mi->ti.disabled = !anyglyphs;
5098 0 : break;
5099 : case MID_RemoveUnused:
5100 0 : gid = map->enccount>0 ? map->map[map->enccount-1] : -1;
5101 0 : mi->ti.disabled = gid!=-1 && SCWorthOutputting(sf->glyphs[gid]);
5102 0 : break;
5103 : case MID_MakeFromFont:
5104 0 : mi->ti.disabled = fv->b.cidmaster!=NULL || map->enccount>1024 || map->enc!=&custom;
5105 0 : break;
5106 : case MID_RemoveEncoding:
5107 0 : break;
5108 : case MID_DisplayByGroups:
5109 0 : mi->ti.disabled = fv->b.cidmaster!=NULL || group_root==NULL;
5110 0 : break;
5111 : case MID_NameGlyphs:
5112 0 : mi->ti.disabled = fv->b.normal!=NULL || fv->b.cidmaster!=NULL;
5113 0 : break;
5114 : case MID_RenameGlyphs: case MID_SaveNamelist:
5115 0 : mi->ti.disabled = fv->b.cidmaster!=NULL;
5116 0 : break;
5117 : }
5118 : }
5119 0 : }
5120 :
5121 : static GMenuItem2 lylist[] = {
5122 : { { (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 },
5123 : GMENUITEM2_EMPTY
5124 : };
5125 :
5126 0 : static void lylistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5127 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5128 0 : SplineFont *sf = fv->b.sf;
5129 : int ly;
5130 : GMenuItem *sub;
5131 :
5132 0 : sub = calloc(sf->layer_cnt+1,sizeof(GMenuItem));
5133 0 : for ( ly=ly_fore; ly<sf->layer_cnt; ++ly ) {
5134 0 : sub[ly-1].ti.text = utf82u_copy(sf->layers[ly].name);
5135 0 : sub[ly-1].ti.checkable = true;
5136 0 : sub[ly-1].ti.checked = ly == fv->b.active_layer;
5137 0 : sub[ly-1].invoke = FVMenuChangeLayer;
5138 0 : sub[ly-1].mid = ly;
5139 0 : sub[ly-1].ti.fg = sub[ly-1].ti.bg = COLOR_DEFAULT;
5140 : }
5141 0 : GMenuItemArrayFree(mi->sub);
5142 0 : mi->sub = sub;
5143 0 : }
5144 :
5145 : static GMenuItem2 vwlist[] = {
5146 : { { (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 },
5147 : { { (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 },
5148 : { { (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 },
5149 : { { (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 },
5150 : { { (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 },
5151 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5152 : { { (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 },
5153 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5154 : { { (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 },
5155 : { { (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 },
5156 : { { (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 },
5157 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5158 : { { (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 },
5159 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5160 : { { (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 },
5161 : { { (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 },
5162 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5163 : { { (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 },
5164 : { { (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 },
5165 : { { (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 },
5166 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5167 : { { (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 },
5168 : { { (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 },
5169 : { { (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 },
5170 : { { (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 },
5171 : { { (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 },
5172 : { { (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 },
5173 : { { (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 },
5174 : { { (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 em|No Shortcut"), NULL, NULL, FVMenuSize, MID_FitToBbox },
5175 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5176 : { { (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 },
5177 : GMENUITEM2_EMPTY, /* Some extra room to show bitmaps */
5178 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5179 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5180 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5181 : GMENUITEM2_EMPTY
5182 : };
5183 :
5184 0 : static void vwlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5185 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5186 0 : int anychars = FVAnyCharSelected(fv);
5187 : int i, base;
5188 : BDFFont *bdf;
5189 : char buffer[50];
5190 : int pos;
5191 0 : SplineFont *sf = fv->b.sf;
5192 0 : SplineFont *master = sf->cidmaster ? sf->cidmaster : sf;
5193 0 : EncMap *map = fv->b.map;
5194 : OTLookup *otl;
5195 :
5196 0 : for ( i=0; vwlist[i].ti.text==NULL || strcmp((char *) vwlist[i].ti.text, _("Bitmap _Magnification..."))!=0; ++i );
5197 0 : base = i+1;
5198 0 : for ( i=base; vwlist[i].ti.text!=NULL; ++i ) {
5199 0 : free( vwlist[i].ti.text);
5200 0 : vwlist[i].ti.text = NULL;
5201 : }
5202 :
5203 0 : vwlist[base-1].ti.disabled = true;
5204 0 : if ( master->bitmaps!=NULL ) {
5205 0 : for ( bdf = master->bitmaps, i=base;
5206 0 : i<sizeof(vwlist)/sizeof(vwlist[0])-1 && bdf!=NULL;
5207 0 : ++i, bdf = bdf->next ) {
5208 0 : if ( BDFDepth(bdf)==1 )
5209 0 : sprintf( buffer, _("%d pixel bitmap"), bdf->pixelsize );
5210 : else
5211 0 : sprintf( buffer, _("%d@%d pixel bitmap"),
5212 0 : bdf->pixelsize, BDFDepth(bdf) );
5213 0 : vwlist[i].ti.text = (unichar_t *) utf82u_copy(buffer);
5214 0 : vwlist[i].ti.checkable = true;
5215 0 : vwlist[i].ti.checked = bdf==fv->show;
5216 0 : vwlist[i].ti.userdata = bdf;
5217 0 : vwlist[i].invoke = FVMenuShowBitmap;
5218 0 : vwlist[i].ti.fg = vwlist[i].ti.bg = COLOR_DEFAULT;
5219 0 : if ( bdf==fv->show )
5220 0 : vwlist[base-1].ti.disabled = false;
5221 : }
5222 : }
5223 0 : GMenuItemArrayFree(mi->sub);
5224 0 : mi->sub = GMenuItem2ArrayCopy(vwlist,NULL);
5225 :
5226 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5227 0 : switch ( mi->mid ) {
5228 : case MID_Next: case MID_Prev:
5229 0 : mi->ti.disabled = anychars<0;
5230 0 : break;
5231 : case MID_NextDef:
5232 0 : pos = anychars+1;
5233 0 : if ( anychars<0 ) pos = map->enccount;
5234 0 : for ( ; pos<map->enccount &&
5235 0 : (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
5236 0 : ++pos );
5237 0 : mi->ti.disabled = pos==map->enccount;
5238 0 : break;
5239 : case MID_PrevDef:
5240 0 : for ( pos = anychars-1; pos>=0 &&
5241 0 : (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
5242 0 : --pos );
5243 0 : mi->ti.disabled = pos<0;
5244 0 : break;
5245 0 : case MID_DisplaySubs: { SplineFont *_sf = sf;
5246 0 : mi->ti.checked = fv->cur_subtable!=NULL;
5247 0 : if ( _sf->cidmaster ) _sf = _sf->cidmaster;
5248 0 : for ( otl=_sf->gsub_lookups; otl!=NULL; otl=otl->next )
5249 0 : if ( otl->lookup_type == gsub_single && otl->subtables!=NULL )
5250 0 : break;
5251 0 : mi->ti.disabled = otl==NULL;
5252 0 : } break;
5253 : case MID_ShowHMetrics:
5254 0 : break;
5255 : case MID_ShowVMetrics:
5256 0 : mi->ti.disabled = !sf->hasvmetrics;
5257 0 : break;
5258 : case MID_32x8:
5259 0 : mi->ti.checked = (fv->rowcnt==8 && fv->colcnt==32);
5260 0 : mi->ti.disabled = fv->b.container!=NULL;
5261 0 : break;
5262 : case MID_16x4:
5263 0 : mi->ti.checked = (fv->rowcnt==4 && fv->colcnt==16);
5264 0 : mi->ti.disabled = fv->b.container!=NULL;
5265 0 : break;
5266 : case MID_8x2:
5267 0 : mi->ti.checked = (fv->rowcnt==2 && fv->colcnt==8);
5268 0 : mi->ti.disabled = fv->b.container!=NULL;
5269 0 : break;
5270 : case MID_24:
5271 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==24);
5272 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5273 0 : break;
5274 : case MID_36:
5275 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==36);
5276 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5277 0 : break;
5278 : case MID_48:
5279 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==48);
5280 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5281 0 : break;
5282 : case MID_72:
5283 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==72);
5284 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5285 0 : break;
5286 : case MID_96:
5287 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==96);
5288 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5289 0 : break;
5290 : case MID_128:
5291 0 : mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==128);
5292 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5293 0 : break;
5294 : case MID_AntiAlias:
5295 0 : mi->ti.checked = (fv->show!=NULL && fv->show->clut!=NULL);
5296 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5297 0 : break;
5298 : case MID_FitToBbox:
5299 0 : mi->ti.checked = (fv->show!=NULL && fv->show->bbsized);
5300 0 : mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
5301 0 : break;
5302 : case MID_Layers:
5303 0 : mi->ti.disabled = sf->layer_cnt<=2 || sf->multilayer;
5304 0 : break;
5305 : }
5306 : }
5307 0 : }
5308 :
5309 : static GMenuItem2 histlist[] = {
5310 : { { (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 },
5311 : { { (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 },
5312 : { { (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 },
5313 : GMENUITEM2_EMPTY
5314 : };
5315 :
5316 : static GMenuItem2 htlist[] = {
5317 : { { (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 },
5318 : { { (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 },
5319 : { { (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 },
5320 : { { (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 },
5321 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5322 : { { (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 },
5323 : { { (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 },
5324 : { { (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 },
5325 : { { (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 },
5326 : { { (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 },
5327 : { { (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 },
5328 : { { (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 },
5329 : { { (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 },
5330 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5331 : { { (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 },
5332 : { { (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 },
5333 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5334 : { { (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 },
5335 : GMENUITEM2_EMPTY
5336 : };
5337 :
5338 : static GMenuItem2 mtlist[] = {
5339 : { { (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 },
5340 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5341 : { { (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 },
5342 : { { (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 },
5343 : { { (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 },
5344 : { { (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 },
5345 : { { (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 },
5346 : { { (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 },
5347 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5348 : { { (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 },
5349 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5350 : { { (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 },
5351 : { { (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 },
5352 : { { (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 },
5353 : { { (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 },
5354 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5355 : { { (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 },
5356 : { { (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 },
5357 : { { (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 },
5358 : GMENUITEM2_EMPTY
5359 : };
5360 :
5361 : static GMenuItem2 cdlist[] = {
5362 : { { (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 },
5363 : { { (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 },
5364 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5365 : { { (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 },
5366 : { { (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 },
5367 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5368 : { { (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 },
5369 : { { (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 },
5370 : { { (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 },
5371 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5372 : { { (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 },
5373 : { { (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 },
5374 : GMENUITEM2_EMPTY, /* Extra room to show sub-font names */
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, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5383 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5384 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5385 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5386 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5387 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5388 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5389 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5390 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5391 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5392 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5393 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5394 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5395 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5396 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5397 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5398 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5399 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5400 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5401 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5402 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5403 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5404 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5405 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5406 : GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY, GMENUITEM2_EMPTY,
5407 : GMENUITEM2_EMPTY
5408 : };
5409 :
5410 0 : static void cdlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5411 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5412 : int i, base, j;
5413 0 : SplineFont *sub, *cidmaster = fv->b.cidmaster;
5414 :
5415 0 : for ( i=0; cdlist[i].mid!=MID_CIDFontInfo; ++i );
5416 0 : base = i+2;
5417 0 : for ( i=base; cdlist[i].ti.text!=NULL; ++i ) {
5418 0 : free( cdlist[i].ti.text);
5419 0 : cdlist[i].ti.text = NULL;
5420 : }
5421 :
5422 0 : cdlist[base-1].ti.fg = cdlist[base-1].ti.bg = COLOR_DEFAULT;
5423 0 : if ( cidmaster==NULL ) {
5424 0 : cdlist[base-1].ti.line = false;
5425 : } else {
5426 0 : cdlist[base-1].ti.line = true;
5427 0 : for ( j = 0, i=base;
5428 0 : i<sizeof(cdlist)/sizeof(cdlist[0])-1 && j<cidmaster->subfontcnt;
5429 0 : ++i, ++j ) {
5430 0 : sub = cidmaster->subfonts[j];
5431 0 : cdlist[i].ti.text = uc_copy(sub->fontname);
5432 0 : cdlist[i].ti.checkable = true;
5433 0 : cdlist[i].ti.checked = sub==fv->b.sf;
5434 0 : cdlist[i].ti.userdata = sub;
5435 0 : cdlist[i].invoke = FVMenuShowSubFont;
5436 0 : cdlist[i].ti.fg = cdlist[i].ti.bg = COLOR_DEFAULT;
5437 : }
5438 : }
5439 0 : GMenuItemArrayFree(mi->sub);
5440 0 : mi->sub = GMenuItem2ArrayCopy(cdlist,NULL);
5441 :
5442 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5443 0 : switch ( mi->mid ) {
5444 : case MID_Convert2CID: case MID_ConvertByCMap:
5445 0 : mi->ti.disabled = cidmaster!=NULL || fv->b.sf->mm!=NULL;
5446 0 : break;
5447 : case MID_InsertFont: case MID_InsertBlank:
5448 : /* OpenType allows at most 255 subfonts (PS allows more, but why go to the effort to make safe font check that? */
5449 0 : mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt>=255;
5450 0 : break;
5451 : case MID_RemoveFromCID:
5452 0 : mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt<=1;
5453 0 : break;
5454 : case MID_Flatten: case MID_FlattenByCMap: case MID_CIDFontInfo:
5455 : case MID_ChangeSupplement:
5456 0 : mi->ti.disabled = cidmaster==NULL;
5457 0 : break;
5458 : }
5459 : }
5460 0 : }
5461 :
5462 : static GMenuItem2 mmlist[] = {
5463 : /* GT: Here (and following) MM means "MultiMaster" */
5464 : { { (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 },
5465 : { { (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 },
5466 : { { (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 },
5467 : { { (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 },
5468 : { { (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 },
5469 : GMENUITEM2_EMPTY, /* Extra room to show sub-font names */
5470 : };
5471 :
5472 0 : static void mmlistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e)) {
5473 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5474 : int i, base, j;
5475 0 : MMSet *mm = fv->b.sf->mm;
5476 : SplineFont *sub;
5477 : GMenuItem2 *mml;
5478 :
5479 0 : for ( i=0; mmlist[i].mid!=MID_ChangeMMBlend; ++i );
5480 0 : base = i+2;
5481 0 : if ( mm==NULL )
5482 0 : mml = mmlist;
5483 : else {
5484 0 : mml = calloc(base+mm->instance_count+2,sizeof(GMenuItem2));
5485 0 : memcpy(mml,mmlist,sizeof(mmlist));
5486 0 : mml[base-1].ti.fg = mml[base-1].ti.bg = COLOR_DEFAULT;
5487 0 : mml[base-1].ti.line = true;
5488 0 : for ( j = 0, i=base; j<mm->instance_count+1; ++i, ++j ) {
5489 0 : if ( j==0 )
5490 0 : sub = mm->normal;
5491 : else
5492 0 : sub = mm->instances[j-1];
5493 0 : mml[i].ti.text = uc_copy(sub->fontname);
5494 0 : mml[i].ti.checkable = true;
5495 0 : mml[i].ti.checked = sub==fv->b.sf;
5496 0 : mml[i].ti.userdata = sub;
5497 0 : mml[i].invoke = FVMenuShowSubFont;
5498 0 : mml[i].ti.fg = mml[i].ti.bg = COLOR_DEFAULT;
5499 : }
5500 : }
5501 0 : GMenuItemArrayFree(mi->sub);
5502 0 : mi->sub = GMenuItem2ArrayCopy(mml,NULL);
5503 0 : if ( mml!=mmlist ) {
5504 0 : for ( i=base; mml[i].ti.text!=NULL; ++i )
5505 0 : free( mml[i].ti.text);
5506 0 : free(mml);
5507 : }
5508 :
5509 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
5510 0 : switch ( mi->mid ) {
5511 : case MID_CreateMM:
5512 0 : mi->ti.disabled = false;
5513 0 : break;
5514 : case MID_MMInfo: case MID_MMValid: case MID_BlendToNew:
5515 0 : mi->ti.disabled = mm==NULL;
5516 0 : break;
5517 : case MID_ChangeMMBlend:
5518 0 : mi->ti.disabled = mm==NULL || mm->apple;
5519 0 : break;
5520 : }
5521 : }
5522 0 : }
5523 :
5524 : static GMenuItem2 wnmenu[] = {
5525 : { { (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 },
5526 : { { (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 },
5527 : { { (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 },
5528 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5529 : { { (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 },
5530 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
5531 : GMENUITEM2_EMPTY
5532 : };
5533 :
5534 0 : static void FVWindowMenuBuild(GWindow gw, struct gmenuitem *mi, GEvent *e) {
5535 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5536 0 : int anychars = FVAnyCharSelected(fv);
5537 : struct gmenuitem *wmi;
5538 0 : int in_modal = (fv->b.container!=NULL && fv->b.container->funcs->is_modal);
5539 :
5540 0 : WindowMenuBuild(gw,mi,e);
5541 0 : for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
5542 0 : switch ( wmi->mid ) {
5543 : case MID_OpenOutline:
5544 0 : wmi->ti.disabled = anychars==-1 || in_modal;
5545 0 : break;
5546 : case MID_OpenBitmap:
5547 0 : wmi->ti.disabled = anychars==-1 || fv->b.sf->bitmaps==NULL || in_modal;
5548 0 : break;
5549 : case MID_OpenMetrics:
5550 0 : wmi->ti.disabled = in_modal;
5551 0 : break;
5552 : case MID_Warnings:
5553 0 : wmi->ti.disabled = ErrorWindowExists();
5554 0 : break;
5555 : }
5556 : }
5557 0 : }
5558 :
5559 : #ifdef BUILD_COLLAB
5560 : static void FVMenuCollabStart(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e))
5561 : {
5562 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5563 :
5564 : printf("connecting to server and sending initial SFD to it...\n");
5565 :
5566 : int port_default = 5556;
5567 : int port = port_default;
5568 : char address[IPADDRESS_STRING_LENGTH_T];
5569 : if( !getNetworkAddress( address ))
5570 : {
5571 : snprintf( address, IPADDRESS_STRING_LENGTH_T-1,
5572 : "%s", HostPortPack( "127.0.0.1", port ));
5573 : }
5574 : else
5575 : {
5576 : snprintf( address, IPADDRESS_STRING_LENGTH_T-1,
5577 : "%s", HostPortPack( address, port ));
5578 : }
5579 :
5580 : printf("host address:%s\n",address);
5581 :
5582 : char* res = gwwv_ask_string(
5583 : "Starting Collab Server",
5584 : address,
5585 : "FontForge has determined that your computer can be accessed"
5586 : " using the below address. Share that address with other people"
5587 : " who you wish to collaborate with...\n\nPress OK to start the collaboration server...");
5588 :
5589 : if( res )
5590 : {
5591 : printf("res:%s\n", res );
5592 : HostPortUnpack( res, &port, port_default );
5593 :
5594 : printf("address:%s\n", res );
5595 : printf("port:%d\n", port );
5596 :
5597 : void* cc = collabclient_new( res, port );
5598 : fv->b.collabClient = cc;
5599 : collabclient_sessionStart( cc, fv );
5600 : printf("connecting to server...sent the sfd for session start.\n");
5601 : free(res);
5602 : }
5603 : }
5604 : #endif
5605 :
5606 0 : static int collab_MakeChoicesArray( GHashTable* peers, char** choices, int choices_sz, int localOnly )
5607 : {
5608 : GHashTableIter iter;
5609 : gpointer key, value;
5610 0 : int lastidx = 0;
5611 0 : memset( choices, 0, sizeof(char*) * choices_sz );
5612 :
5613 0 : int i=0;
5614 0 : int maxUserNameLength = 1;
5615 0 : g_hash_table_iter_init (&iter, peers);
5616 0 : for( i=0; g_hash_table_iter_next (&iter, &key, &value); i++ )
5617 : {
5618 0 : beacon_announce_t* ba = (beacon_announce_t*)value;
5619 0 : maxUserNameLength = imax( maxUserNameLength, strlen(ba->username) );
5620 : }
5621 :
5622 0 : g_hash_table_iter_init (&iter, peers);
5623 0 : for( i=0; g_hash_table_iter_next (&iter, &key, &value); i++ )
5624 : {
5625 0 : beacon_announce_t* ba = (beacon_announce_t*)value;
5626 0 : if( localOnly && !collabclient_isAddressLocal( ba->ip ))
5627 0 : continue;
5628 :
5629 0 : printf("user:%s\n", ba->username );
5630 0 : printf("mach:%s\n", ba->machinename );
5631 :
5632 : char buf[101];
5633 0 : if( localOnly )
5634 : {
5635 0 : snprintf( buf, 100, "%s", ba->fontname );
5636 : }
5637 : else
5638 : {
5639 : char format[50];
5640 0 : sprintf( format, "%s %%%d", "%s", maxUserNameLength );
5641 0 : strcat( format, "s %s");
5642 0 : snprintf( buf, 100, format, ba->fontname, ba->username, ba->machinename );
5643 : }
5644 0 : choices[i] = copy( buf );
5645 0 : if( i >= choices_sz )
5646 0 : break;
5647 0 : lastidx++;
5648 : }
5649 :
5650 0 : return lastidx;
5651 : }
5652 :
5653 0 : static beacon_announce_t* collab_getBeaconFromChoicesArray( GHashTable* peers, int choice, int localOnly )
5654 : {
5655 : GHashTableIter iter;
5656 : gpointer key, value;
5657 0 : int i=0;
5658 :
5659 0 : g_hash_table_iter_init (&iter, peers);
5660 0 : for( i=0; g_hash_table_iter_next (&iter, &key, &value); i++ )
5661 : {
5662 0 : beacon_announce_t* ba = (beacon_announce_t*)value;
5663 0 : if( localOnly && !collabclient_isAddressLocal( ba->ip ))
5664 0 : continue;
5665 0 : if( i != choice )
5666 0 : continue;
5667 0 : return ba;
5668 : }
5669 0 : return 0;
5670 : }
5671 :
5672 :
5673 : #ifdef BUILD_COLLAB
5674 : static void FVMenuCollabConnect(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e))
5675 : {
5676 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5677 :
5678 : printf("connecting to server...\n");
5679 :
5680 : {
5681 : int choices_sz = 100;
5682 : char* choices[101];
5683 : memset( choices, 0, sizeof(choices));
5684 :
5685 : collabclient_trimOldBeaconInformation( 0 );
5686 : GHashTable* peers = collabclient_getServersFromBeaconInfomration();
5687 : int localOnly = 0;
5688 : int max = collab_MakeChoicesArray( peers, choices, choices_sz, localOnly );
5689 : int choice = gwwv_choose(_("Connect to Collab Server"),(const char **) choices, max,
5690 : 0,_("Select a collab server to connect to..."));
5691 : printf("you wanted %d\n", choice );
5692 : if( choice <= max )
5693 : {
5694 : beacon_announce_t* ba = collab_getBeaconFromChoicesArray( peers, choice, localOnly );
5695 :
5696 : if( ba )
5697 : {
5698 : int port = ba->port;
5699 : char address[IPADDRESS_STRING_LENGTH_T];
5700 : strncpy( address, ba->ip, IPADDRESS_STRING_LENGTH_T-1 );
5701 : void* cc = collabclient_new( address, port );
5702 : fv->b.collabClient = cc;
5703 : collabclient_sessionJoin( cc, fv );
5704 : }
5705 : }
5706 : }
5707 :
5708 : printf("FVMenuCollabConnect(done)\n");
5709 : }
5710 :
5711 : static void FVMenuCollabConnectToExplicitAddress(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e))
5712 : {
5713 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5714 :
5715 : printf("********** connecting to server... explicit address... p:%p\n", pref_collab_last_server_connected_to);
5716 :
5717 : char* default_server = "localhost";
5718 : if( pref_collab_last_server_connected_to ) {
5719 : default_server = pref_collab_last_server_connected_to;
5720 : }
5721 :
5722 : char* res = gwwv_ask_string(
5723 : "Connect to Collab Server",
5724 : default_server,
5725 : "Please enter the network location of the Collab server you wish to connect to...");
5726 : if( res )
5727 : {
5728 : if( pref_collab_last_server_connected_to ) {
5729 : free( pref_collab_last_server_connected_to );
5730 : }
5731 : pref_collab_last_server_connected_to = copy( res );
5732 : SavePrefs(true);
5733 :
5734 : int port_default = 5556;
5735 : int port = port_default;
5736 : char address[IPADDRESS_STRING_LENGTH_T];
5737 : strncpy( address, res, IPADDRESS_STRING_LENGTH_T-1 );
5738 : HostPortUnpack( address, &port, port_default );
5739 :
5740 : void* cc = collabclient_new( address, port );
5741 : fv->b.collabClient = cc;
5742 : collabclient_sessionJoin( cc, fv );
5743 : }
5744 :
5745 : printf("FVMenuCollabConnect(done)\n");
5746 : }
5747 :
5748 : static void FVMenuCollabDisconnect(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e))
5749 : {
5750 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5751 : collabclient_sessionDisconnect( &fv->b );
5752 : }
5753 : #endif
5754 :
5755 0 : static void AskAndMaybeCloseLocalCollabServers()
5756 : {
5757 : char *buts[3];
5758 0 : buts[0] = _("_OK");
5759 0 : buts[1] = _("_Cancel");
5760 0 : buts[2] = NULL;
5761 :
5762 0 : int i=0;
5763 0 : int choices_sz = 100;
5764 : char* choices[101];
5765 0 : collabclient_trimOldBeaconInformation( 0 );
5766 0 : GHashTable* peers = collabclient_getServersFromBeaconInfomration();
5767 0 : if( !peers )
5768 0 : return;
5769 :
5770 0 : int localOnly = 1;
5771 0 : int max = collab_MakeChoicesArray( peers, choices, choices_sz, localOnly );
5772 0 : if( !max )
5773 0 : return;
5774 :
5775 : char sel[101];
5776 0 : memset( sel, 1, max );
5777 0 : int choice = gwwv_choose_multiple(_("Close Collab Server(s)"),
5778 : (const char **) choices, sel, max,
5779 0 : buts, _("Select which servers you wish to close..."));
5780 :
5781 0 : int allServersSelected = 1;
5782 0 : printf("you wanted %d\n", choice );
5783 0 : for( i=0; i < max; i++ )
5784 : {
5785 0 : printf("sel[%d] is %d\n", i, sel[i] );
5786 0 : beacon_announce_t* ba = collab_getBeaconFromChoicesArray( peers, choice, localOnly );
5787 :
5788 0 : if( sel[i] && ba )
5789 0 : {
5790 0 : int port = ba->port;
5791 :
5792 0 : if( sel[i] )
5793 : {
5794 0 : FontViewBase* fv = FontViewFind( FontViewFind_byCollabBasePort, (void*)(intptr_t)port );
5795 0 : if( fv )
5796 0 : collabclient_sessionDisconnect( fv );
5797 0 : printf("CLOSING port:%d fv:%p\n", port, fv );
5798 0 : collabclient_closeLocalServer( port );
5799 : }
5800 : }
5801 : else
5802 : {
5803 0 : allServersSelected = 0;
5804 : }
5805 : }
5806 :
5807 0 : printf("allServersSelected:%d\n", allServersSelected );
5808 0 : if( allServersSelected )
5809 0 : collabclient_closeAllLocalServersForce();
5810 : }
5811 :
5812 0 : static void FVMenuCollabCloseLocalServer(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e))
5813 : {
5814 0 : AskAndMaybeCloseLocalCollabServers();
5815 0 : }
5816 :
5817 :
5818 : #if defined(__MINGW32__)
5819 : //
5820 : // This is an imperfect implemenation of kill() for windows.
5821 : //
5822 : static int kill( int pid, int sig )
5823 : {
5824 : HANDLE hHandle;
5825 : hHandle = OpenProcess( PROCESS_ALL_ACCESS, 0, pid );
5826 : TerminateProcess( hHandle, 0 );
5827 : }
5828 : #endif
5829 :
5830 :
5831 :
5832 0 : static void collablistcheck(GWindow gw, struct gmenuitem *mi, GEvent *UNUSED(e))
5833 : {
5834 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
5835 :
5836 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi )
5837 : {
5838 0 : switch ( mi->mid )
5839 : {
5840 : case MID_CollabDisconnect:
5841 : {
5842 0 : enum collabState_t st = collabclient_getState( &fv->b );
5843 0 : mi->ti.disabled = ( st < cs_server );
5844 0 : break;
5845 : }
5846 : case MID_CollabCloseLocalServer:
5847 0 : printf("can close local server: %d\n", collabclient_haveLocalServer() );
5848 0 : mi->ti.disabled = !collabclient_haveLocalServer();
5849 0 : break;
5850 : }
5851 : }
5852 0 : }
5853 :
5854 : #ifdef BUILD_COLLAB
5855 :
5856 : static GMenuItem2 collablist[] = {
5857 : { { (unichar_t *) N_("_Start Session..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Start Session...|No Shortcut"), NULL, NULL, FVMenuCollabStart, MID_CollabStart },
5858 : { { (unichar_t *) N_("_Connect to Session..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Connect to Session...|No Shortcut"), NULL, NULL, FVMenuCollabConnect, MID_CollabConnect },
5859 : { { (unichar_t *) N_("_Connect to Session (ip:port)..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Connect to Session (ip:port)...|No Shortcut"), NULL, NULL, FVMenuCollabConnectToExplicitAddress, MID_CollabConnectToExplicitAddress },
5860 : { { (unichar_t *) N_("_Disconnect"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Disconnect|No Shortcut"), NULL, NULL, FVMenuCollabDisconnect, MID_CollabDisconnect },
5861 : GMENUITEM2_LINE,
5862 : { { (unichar_t *) N_("Close local server"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Close local server|No Shortcut"), NULL, NULL, FVMenuCollabCloseLocalServer, MID_CollabCloseLocalServer },
5863 :
5864 : GMENUITEM2_EMPTY, /* Extra room to show sub-font names */
5865 : };
5866 : #endif
5867 :
5868 : GMenuItem2 helplist[] = {
5869 : { { (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 },
5870 : { { (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 },
5871 : { { (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 },
5872 : { { (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 },
5873 : { { (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 },
5874 : GMENUITEM2_EMPTY
5875 : };
5876 :
5877 : GMenuItem fvpopupmenu[] = {
5878 : { { (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 },
5879 : GMENUITEM_LINE,
5880 : { { (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 },
5881 : { { (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 },
5882 : { { (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 },
5883 : { { (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 },
5884 : { { (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 },
5885 : { { (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 },
5886 : { { (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 },
5887 : { { (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 },
5888 : { { 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 */
5889 : { { (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 },
5890 : { { (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 },
5891 : { { (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 },
5892 : { { (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 },
5893 : { { (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 },
5894 : { { 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 */
5895 : { { (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 },
5896 : { { 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 */
5897 : { { (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 },
5898 : { { (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 },
5899 : { { (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 },
5900 : GMENUITEM_EMPTY
5901 : };
5902 :
5903 : static GMenuItem2 mblist[] = {
5904 : { { (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 },
5905 : { { (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 },
5906 : { { (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 },
5907 : #ifndef _NO_PYTHON
5908 : { { (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 },
5909 : #endif
5910 : #ifdef NATIVE_CALLBACKS
5911 : { { (unichar_t *) N_("Tools_2"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Tools 2|No Shortcut"), NULL, fv_tl2listcheck, NULL, 0 },
5912 : #endif
5913 : { { (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 },
5914 : { { (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 },
5915 : { { (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 },
5916 : { { (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 },
5917 : { { (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 },
5918 : /* GT: Here (and following) MM means "MultiMaster" */
5919 : { { (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 },
5920 : { { (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 },
5921 : #ifdef BUILD_COLLAB
5922 : { { (unichar_t *) N_("C_ollaborate"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Collaborate|No Shortcut"), collablist, collablistcheck, NULL, 0 },
5923 : #endif
5924 : { { (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 },
5925 : GMENUITEM2_EMPTY
5926 : };
5927 :
5928 0 : void FVRefreshChar(FontView *fv,int gid) {
5929 : BDFChar *bdfc;
5930 : int i, j, enc;
5931 : MetricsView *mv;
5932 :
5933 : /* Can happen in scripts */ /* Can happen if we do an AutoHint when generating a tiny font for freetype context */
5934 0 : if ( fv->v==NULL || fv->colcnt==0 || fv->b.sf->glyphs[gid]== NULL )
5935 0 : return;
5936 0 : for ( fv=(FontView *) (fv->b.sf->fv); fv!=NULL; fv = (FontView *) (fv->b.nextsame) ) {
5937 0 : if( !fv->colcnt )
5938 0 : continue;
5939 :
5940 0 : for ( mv=fv->b.sf->metrics; mv!=NULL; mv=mv->next )
5941 0 : MVRefreshChar(mv,fv->b.sf->glyphs[gid]);
5942 0 : if ( fv->show==fv->filled )
5943 0 : bdfc = BDFPieceMealCheck(fv->show,gid);
5944 : else
5945 0 : bdfc = fv->show->glyphs[gid];
5946 0 : if ( bdfc==NULL )
5947 0 : bdfc = BDFPieceMeal(fv->show,gid);
5948 : /* A glyph may be encoded in several places, all need updating */
5949 0 : for ( enc = 0; enc<fv->b.map->enccount; ++enc ) if ( fv->b.map->map[enc]==gid ) {
5950 0 : i = enc / fv->colcnt;
5951 0 : j = enc - i*fv->colcnt;
5952 0 : i -= fv->rowoff;
5953 0 : if ( i>=0 && i<fv->rowcnt )
5954 0 : FVDrawGlyph(fv->v,fv,enc,true);
5955 : }
5956 : }
5957 : }
5958 :
5959 6159 : void FVRegenChar(FontView *fv,SplineChar *sc) {
5960 : struct splinecharlist *dlist;
5961 : MetricsView *mv;
5962 :
5963 6159 : if ( fv->v==NULL ) /* Can happen in scripts */
5964 12318 : return;
5965 :
5966 0 : if ( sc->orig_pos<fv->filled->glyphcnt ) {
5967 0 : BDFCharFree(fv->filled->glyphs[sc->orig_pos]);
5968 0 : fv->filled->glyphs[sc->orig_pos] = NULL;
5969 : }
5970 : /* FVRefreshChar does NOT do this for us */
5971 0 : for ( mv=fv->b.sf->metrics; mv!=NULL; mv=mv->next )
5972 0 : MVRegenChar(mv,sc);
5973 :
5974 0 : FVRefreshChar(fv,sc->orig_pos);
5975 : #if HANYANG
5976 : if ( sc->compositionunit && fv->b.sf->rules!=NULL )
5977 : Disp_RefreshChar(fv->b.sf,sc);
5978 : #endif
5979 :
5980 0 : for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
5981 0 : FVRegenChar(fv,dlist->sc);
5982 : }
5983 :
5984 0 : static void AddSubPST(SplineChar *sc,struct lookup_subtable *sub,char *variant) {
5985 : PST *pst;
5986 :
5987 0 : pst = chunkalloc(sizeof(PST));
5988 0 : pst->type = pst_substitution;
5989 0 : pst->subtable = sub;
5990 0 : pst->u.alt.components = copy(variant);
5991 0 : pst->next = sc->possub;
5992 0 : sc->possub = pst;
5993 0 : }
5994 :
5995 0 : SplineChar *FVMakeChar(FontView *fv,int enc) {
5996 0 : SplineFont *sf = fv->b.sf;
5997 0 : SplineChar *base_sc = SFMakeChar(sf,fv->b.map,enc), *feat_sc = NULL;
5998 0 : int feat_gid = FeatureTrans(fv,enc);
5999 :
6000 0 : if ( fv->cur_subtable==NULL )
6001 0 : return( base_sc );
6002 :
6003 0 : if ( feat_gid==-1 ) {
6004 0 : int uni = -1;
6005 0 : FeatureScriptLangList *fl = fv->cur_subtable->lookup->features;
6006 :
6007 0 : if ( base_sc->unicodeenc>=0x600 && base_sc->unicodeenc<=0x6ff &&
6008 0 : fl!=NULL &&
6009 0 : (fl->featuretag == CHR('i','n','i','t') ||
6010 0 : fl->featuretag == CHR('m','e','d','i') ||
6011 0 : fl->featuretag == CHR('f','i','n','a') ||
6012 0 : fl->featuretag == CHR('i','s','o','l')) ) {
6013 0 : uni = fl->featuretag == CHR('i','n','i','t') ? ArabicForms[base_sc->unicodeenc-0x600].initial :
6014 0 : fl->featuretag == CHR('m','e','d','i') ? ArabicForms[base_sc->unicodeenc-0x600].medial :
6015 0 : fl->featuretag == CHR('f','i','n','a') ? ArabicForms[base_sc->unicodeenc-0x600].final :
6016 0 : fl->featuretag == CHR('i','s','o','l') ? ArabicForms[base_sc->unicodeenc-0x600].isolated :
6017 : -1;
6018 0 : feat_sc = SFGetChar(sf,uni,NULL);
6019 0 : if ( feat_sc!=NULL )
6020 0 : return( feat_sc );
6021 : }
6022 0 : feat_sc = SFSplineCharCreate(sf);
6023 0 : feat_sc->unicodeenc = uni;
6024 0 : if ( uni!=-1 ) {
6025 0 : feat_sc->name = malloc(8);
6026 0 : feat_sc->unicodeenc = uni;
6027 0 : sprintf( feat_sc->name,"uni%04X", uni );
6028 0 : } else if ( fv->cur_subtable->suffix!=NULL ) {
6029 0 : feat_sc->name = malloc(strlen(base_sc->name)+strlen(fv->cur_subtable->suffix)+2);
6030 0 : sprintf( feat_sc->name, "%s.%s", base_sc->name, fv->cur_subtable->suffix );
6031 0 : } else if ( fl==NULL ) {
6032 0 : feat_sc->name = strconcat(base_sc->name,".unknown");
6033 0 : } else if ( fl->ismac ) {
6034 : /* mac feature/setting */
6035 0 : feat_sc->name = malloc(strlen(base_sc->name)+14);
6036 0 : sprintf( feat_sc->name,"%s.m%d_%d", base_sc->name,
6037 0 : (int) (fl->featuretag>>16),
6038 0 : (int) ((fl->featuretag)&0xffff) );
6039 : } else {
6040 : /* OpenType feature tag */
6041 0 : feat_sc->name = malloc(strlen(base_sc->name)+6);
6042 0 : sprintf( feat_sc->name,"%s.%c%c%c%c", base_sc->name,
6043 0 : (int) (fl->featuretag>>24),
6044 0 : (int) ((fl->featuretag>>16)&0xff),
6045 0 : (int) ((fl->featuretag>>8)&0xff),
6046 0 : (int) ((fl->featuretag)&0xff) );
6047 : }
6048 0 : SFAddGlyphAndEncode(sf,feat_sc,fv->b.map,fv->b.map->enccount);
6049 0 : AddSubPST(base_sc,fv->cur_subtable,feat_sc->name);
6050 0 : return( feat_sc );
6051 : } else
6052 0 : return( base_sc );
6053 : }
6054 :
6055 : /* we style some glyph names differently, see FVExpose() */
6056 : #define _uni_italic 0x2
6057 : #define _uni_vertical (1<<2)
6058 : #define _uni_fontmax (2<<2)
6059 :
6060 0 : static GFont *FVCheckFont(FontView *fv,int type) {
6061 : FontRequest rq;
6062 :
6063 0 : if ( fv->fontset[type]==NULL ) {
6064 0 : memset(&rq,0,sizeof(rq));
6065 0 : rq.utf8_family_name = fv_fontnames;
6066 0 : rq.point_size = fv_fontsize;
6067 0 : rq.weight = 400;
6068 0 : rq.style = 0;
6069 0 : if (type&_uni_italic)
6070 0 : rq.style |= fs_italic;
6071 0 : if (type&_uni_vertical)
6072 0 : rq.style |= fs_vertical;
6073 0 : fv->fontset[type] = GDrawInstanciateFont(fv->v,&rq);
6074 : }
6075 0 : return( fv->fontset[type] );
6076 : }
6077 :
6078 : extern unichar_t adobes_pua_alts[0x200][3];
6079 :
6080 0 : static void do_Adobe_Pua(unichar_t *buf,int sob,int uni) {
6081 : int i, j;
6082 :
6083 0 : for ( i=j=0; j<sob-1 && i<3; ++i ) {
6084 0 : int ch = adobes_pua_alts[uni-0xf600][i];
6085 0 : if ( ch==0 )
6086 0 : break;
6087 0 : if ( ch>=0xf600 && ch<=0xf7ff && adobes_pua_alts[ch-0xf600]!=0 ) {
6088 0 : do_Adobe_Pua(buf+j,sob-j,ch);
6089 0 : while ( buf[j]!=0 ) ++j;
6090 : } else
6091 0 : buf[j++] = ch;
6092 : }
6093 0 : buf[j] = 0;
6094 0 : }
6095 :
6096 0 : static void FVExpose(FontView *fv,GWindow pixmap, GEvent *event) {
6097 : int i, j, y, width, gid;
6098 : int changed;
6099 : GRect old, old2, r;
6100 : GClut clut;
6101 : struct _GImage base;
6102 : GImage gi;
6103 : SplineChar dummy;
6104 0 : int styles, laststyles=0;
6105 : Color bg, def_fg;
6106 : int fgxor;
6107 :
6108 0 : def_fg = GDrawGetDefaultForeground(NULL);
6109 0 : memset(&gi,'\0',sizeof(gi));
6110 0 : memset(&base,'\0',sizeof(base));
6111 0 : if ( fv->show->clut!=NULL ) {
6112 0 : gi.u.image = &base;
6113 0 : base.image_type = it_index;
6114 0 : base.clut = fv->show->clut;
6115 0 : GDrawSetDither(NULL, false);
6116 0 : base.trans = -1;
6117 : } else {
6118 0 : memset(&clut,'\0',sizeof(clut));
6119 0 : gi.u.image = &base;
6120 0 : base.image_type = it_mono;
6121 0 : base.clut = &clut;
6122 0 : clut.clut_len = 2;
6123 0 : clut.clut[0] = view_bgcol;
6124 : }
6125 :
6126 0 : GDrawSetFont(pixmap,fv->fontset[0]);
6127 0 : GDrawSetLineWidth(pixmap,0);
6128 0 : GDrawPushClip(pixmap,&event->u.expose.rect,&old);
6129 0 : GDrawFillRect(pixmap,NULL,view_bgcol);
6130 0 : for ( i=0; i<=fv->rowcnt; ++i ) {
6131 0 : GDrawDrawLine(pixmap,0,i*fv->cbh,fv->width,i*fv->cbh,def_fg);
6132 0 : GDrawDrawLine(pixmap,0,i*fv->cbh+fv->lab_height,fv->width,i*fv->cbh+fv->lab_height,0x808080);
6133 : }
6134 0 : for ( i=0; i<=fv->colcnt; ++i )
6135 0 : GDrawDrawLine(pixmap,i*fv->cbw,0,i*fv->cbw,fv->height,def_fg);
6136 0 : for ( i=event->u.expose.rect.y/fv->cbh; i<=fv->rowcnt &&
6137 0 : (event->u.expose.rect.y+event->u.expose.rect.height+fv->cbh-1)/fv->cbh; ++i ) for ( j=0; j<fv->colcnt; ++j ) {
6138 0 : int index = (i+fv->rowoff)*fv->colcnt+j;
6139 : SplineChar *sc;
6140 0 : styles = 0;
6141 0 : if ( index < fv->b.map->enccount && index!=-1 ) {
6142 : unichar_t buf[60]; char cbuf[8];
6143 : char utf8_buf[8];
6144 0 : int use_utf8 = false;
6145 : Color fg;
6146 : extern const int amspua[];
6147 : int uni;
6148 0 : struct cidmap *cidmap = NULL;
6149 0 : sc = (gid=fv->b.map->map[index])!=-1 ? fv->b.sf->glyphs[gid]: NULL;
6150 :
6151 0 : if ( fv->b.cidmaster!=NULL )
6152 0 : cidmap = FindCidMap(fv->b.cidmaster->cidregistry,fv->b.cidmaster->ordering,fv->b.cidmaster->supplement,fv->b.cidmaster);
6153 :
6154 0 : if ( ( fv->b.map->enc==&custom && index<256 ) ||
6155 0 : ( fv->b.map->enc!=&custom && index<fv->b.map->enc->char_cnt ) ||
6156 0 : ( cidmap!=NULL && index<MaxCID(cidmap) ))
6157 0 : fg = def_fg;
6158 : else
6159 0 : fg = 0x505050;
6160 0 : if ( sc==NULL )
6161 0 : sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,index);
6162 0 : uni = sc->unicodeenc;
6163 0 : buf[0] = buf[1] = 0;
6164 0 : if ( fv->b.sf->uni_interp==ui_ams && uni>=0xe000 && uni<=0xf8ff &&
6165 0 : amspua[uni-0xe000]!=0 )
6166 0 : uni = amspua[uni-0xe000];
6167 0 : switch ( fv->glyphlabel ) {
6168 : case gl_name:
6169 0 : uc_strncpy(buf,sc->name,sizeof(buf)/sizeof(buf[0]));
6170 0 : break;
6171 : case gl_unicode:
6172 0 : if ( sc->unicodeenc!=-1 ) {
6173 0 : sprintf(cbuf,"%04x",sc->unicodeenc);
6174 0 : uc_strcpy(buf,cbuf);
6175 : } else
6176 0 : uc_strcpy(buf,"?");
6177 0 : break;
6178 : case gl_encoding:
6179 0 : if ( fv->b.map->enc->only_1byte ||
6180 0 : (fv->b.map->enc->has_1byte && index<256))
6181 0 : sprintf(cbuf,"%02x",index);
6182 : else
6183 0 : sprintf(cbuf,"%04x",index);
6184 0 : uc_strcpy(buf,cbuf);
6185 0 : break;
6186 : case gl_glyph:
6187 0 : if ( uni==0xad )
6188 0 : buf[0] = '-';
6189 0 : else if ( fv->b.sf->uni_interp==ui_adobe && uni>=0xf600 && uni<=0xf7ff &&
6190 : adobes_pua_alts[uni-0xf600]!=0 ) {
6191 0 : use_utf8 = false;
6192 0 : do_Adobe_Pua(buf,sizeof(buf),uni);
6193 0 : } else if ( uni>=0xe0020 && uni<=0xe007e ) {
6194 0 : buf[0] = uni-0xe0000; /* A map of Ascii for language names */
6195 : #if HANYANG
6196 : } else if ( sc->compositionunit ) {
6197 : if ( sc->jamo<19 )
6198 : buf[0] = 0x1100+sc->jamo;
6199 : else if ( sc->jamo<19+21 )
6200 : buf[0] = 0x1161 + sc->jamo-19;
6201 : else /* Leave a hole for the blank char */
6202 : buf[0] = 0x11a8 + sc->jamo-(19+21+1);
6203 : #endif
6204 0 : } else if ( uni>0 && uni<unicode4_size ) {
6205 0 : char *pt = utf8_buf;
6206 0 : use_utf8 = true;
6207 0 : *pt = '\0'; // We terminate the string in case the appendage (?) fails.
6208 0 : pt = utf8_idpb(pt,uni,0);
6209 0 : if (pt) *pt = '\0'; else fprintf(stderr, "Invalid Unicode alert.\n");
6210 : } else {
6211 0 : char *pt = strchr(sc->name,'.');
6212 0 : buf[0] = '?';
6213 0 : fg = 0xff0000;
6214 0 : if ( pt!=NULL ) {
6215 0 : int i, n = pt-sc->name;
6216 : char *end;
6217 0 : SplineFont *cm = fv->b.sf->cidmaster;
6218 0 : if ( n==7 && sc->name[0]=='u' && sc->name[1]=='n' && sc->name[2]=='i' &&
6219 0 : (i=strtol(sc->name+3,&end,16), end-sc->name==7))
6220 0 : buf[0] = i;
6221 0 : else if ( n>=5 && n<=7 && sc->name[0]=='u' &&
6222 0 : (i=strtol(sc->name+1,&end,16), end-sc->name==n))
6223 0 : buf[0] = i;
6224 0 : else if ( cm!=NULL && (i=CIDFromName(sc->name,cm))!=-1 ) {
6225 : int uni;
6226 0 : uni = CID2Uni(FindCidMap(cm->cidregistry,cm->ordering,cm->supplement,cm),
6227 : i);
6228 0 : if ( uni!=-1 )
6229 0 : buf[0] = uni;
6230 : } else {
6231 : int uni;
6232 0 : *pt = '\0';
6233 0 : uni = UniFromName(sc->name,fv->b.sf->uni_interp,fv->b.map->enc);
6234 0 : if ( uni!=-1 )
6235 0 : buf[0] = uni;
6236 0 : *pt = '.';
6237 : }
6238 0 : if ( strstr(pt,".vert")!=NULL )
6239 0 : styles = _uni_vertical;
6240 0 : if ( buf[0]!='?' ) {
6241 0 : fg = def_fg;
6242 0 : if ( strstr(pt,".italic")!=NULL )
6243 0 : styles = _uni_italic;
6244 : }
6245 0 : } else if ( strncmp(sc->name,"hwuni",5)==0 ) {
6246 0 : int uni=-1;
6247 0 : sscanf(sc->name,"hwuni%x", (unsigned *) &uni );
6248 0 : if ( uni!=-1 ) buf[0] = uni;
6249 0 : } else if ( strncmp(sc->name,"italicuni",9)==0 ) {
6250 0 : int uni=-1;
6251 0 : sscanf(sc->name,"italicuni%x", (unsigned *) &uni );
6252 0 : if ( uni!=-1 ) { buf[0] = uni; styles=_uni_italic; }
6253 0 : fg = def_fg;
6254 0 : } else if ( strncmp(sc->name,"vertcid_",8)==0 ||
6255 0 : strncmp(sc->name,"vertuni",7)==0 ) {
6256 0 : styles = _uni_vertical;
6257 : }
6258 : }
6259 0 : break;
6260 : }
6261 0 : r.x = j*fv->cbw+1; r.width = fv->cbw-1;
6262 0 : r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
6263 0 : bg = view_bgcol;
6264 0 : fgxor = 0x000000;
6265 0 : changed = sc->changed;
6266 0 : if ( fv->b.sf->onlybitmaps && gid<fv->show->glyphcnt )
6267 0 : changed = gid==-1 || fv->show->glyphs[gid]==NULL? false : fv->show->glyphs[gid]->changed;
6268 0 : if ( changed ||
6269 0 : sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL ||
6270 0 : sc->color!=COLOR_DEFAULT ) {
6271 0 : if ( sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL ||
6272 0 : sc->color!=COLOR_DEFAULT )
6273 0 : bg = sc->color!=COLOR_DEFAULT?sc->color:0x808080;
6274 0 : if ( sc->changed ) {
6275 0 : fgxor = bg ^ fvchangedcol;
6276 0 : bg = fvchangedcol;
6277 : }
6278 0 : GDrawFillRect(pixmap,&r,bg);
6279 : }
6280 0 : if ( (!fv->b.sf->layers[fv->b.active_layer].order2 && sc->changedsincelasthinted ) ||
6281 0 : ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->layers[fv->b.active_layer].splines!=NULL &&
6282 0 : sc->ttf_instrs_len<=0 ) ||
6283 0 : ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->instructions_out_of_date ) ) {
6284 0 : Color hintcol = fvhintingneededcol;
6285 0 : if ( fv->b.sf->layers[fv->b.active_layer].order2 && sc->instructions_out_of_date && sc->ttf_instrs_len>0 )
6286 0 : hintcol = 0xff0000;
6287 0 : GDrawDrawLine(pixmap,r.x,r.y,r.x,r.y+r.height-1,hintcol);
6288 0 : GDrawDrawLine(pixmap,r.x+1,r.y,r.x+1,r.y+r.height-1,hintcol);
6289 0 : GDrawDrawLine(pixmap,r.x+2,r.y,r.x+2,r.y+r.height-1,hintcol);
6290 0 : GDrawDrawLine(pixmap,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,hintcol);
6291 0 : GDrawDrawLine(pixmap,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,hintcol);
6292 0 : GDrawDrawLine(pixmap,r.x+r.width-3,r.y,r.x+r.width-3,r.y+r.height-1,hintcol);
6293 : }
6294 0 : if ( use_utf8 && sc->unicodeenc!=-1 &&
6295 : /* Pango complains if we try to draw non characters */
6296 : /* These two are guaranteed "NOT A UNICODE CHARACTER" in all planes */
6297 0 : ((sc->unicodeenc&0xffff)==0xfffe || (sc->unicodeenc&0xffff)==0xffff ||
6298 0 : (sc->unicodeenc>=0xfdd0 && sc->unicodeenc<=0xfdef) || /* noncharacters */
6299 0 : (sc->unicodeenc>=0xfe00 && sc->unicodeenc<=0xfe0f) || /* variation selectors */
6300 0 : (sc->unicodeenc>=0xe0110 && sc->unicodeenc<=0xe01ff) || /* variation selectors */
6301 : /* The surrogates in BMP aren't valid either */
6302 0 : (sc->unicodeenc>=0xd800 && sc->unicodeenc<=0xdfff))) { /* surrogates */
6303 0 : GDrawDrawLine(pixmap,r.x,r.y,r.x+r.width-1,r.y+r.height-1,0x000000);
6304 0 : GDrawDrawLine(pixmap,r.x,r.y+r.height-1,r.x+r.width-1,r.y,0x000000);
6305 0 : } else if ( use_utf8 ) {
6306 : GTextBounds size;
6307 0 : if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
6308 0 : width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,&size);
6309 0 : if ( size.lbearing==0 && size.rbearing==0 ) {
6310 0 : utf8_buf[0] = 0xe0 | (0xfffd>>12);
6311 0 : utf8_buf[1] = 0x80 | ((0xfffd>>6)&0x3f);
6312 0 : utf8_buf[2] = 0x80 | (0xfffd&0x3f);
6313 0 : utf8_buf[3] = 0;
6314 0 : width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,&size);
6315 : }
6316 0 : width = size.rbearing - size.lbearing+1;
6317 0 : if ( width >= fv->cbw-1 ) {
6318 0 : GDrawPushClip(pixmap,&r,&old2);
6319 0 : width = fv->cbw-1;
6320 : }
6321 0 : if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 ) {
6322 0 : y = i*fv->cbh+fv->lab_as+1;
6323 : /* move rotated glyph up a bit to center it */
6324 0 : if (styles&_uni_vertical)
6325 0 : y -= fv->lab_as/2;
6326 0 : GDrawDrawText8(pixmap,j*fv->cbw+(fv->cbw-1-width)/2-size.lbearing,y,utf8_buf,-1,fg^fgxor);
6327 : }
6328 0 : if ( width >= fv->cbw-1 )
6329 0 : GDrawPopClip(pixmap,&old2);
6330 0 : laststyles = styles;
6331 : } else {
6332 0 : if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
6333 0 : width = GDrawGetTextWidth(pixmap,buf,-1);
6334 0 : if ( width >= fv->cbw-1 ) {
6335 0 : GDrawPushClip(pixmap,&r,&old2);
6336 0 : width = fv->cbw-1;
6337 : }
6338 0 : if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 ) {
6339 0 : y = i*fv->cbh+fv->lab_as+1;
6340 : /* move rotated glyph up a bit to center it */
6341 0 : if (styles&_uni_vertical)
6342 0 : y -= fv->lab_as/2;
6343 0 : GDrawDrawText(pixmap,j*fv->cbw+(fv->cbw-1-width)/2,y,buf,-1,fg^fgxor);
6344 : }
6345 0 : if ( width >= fv->cbw-1 )
6346 0 : GDrawPopClip(pixmap,&old2);
6347 0 : laststyles = styles;
6348 : }
6349 : }
6350 0 : FVDrawGlyph(pixmap,fv,index,false);
6351 : }
6352 0 : if ( fv->showhmetrics&fvm_baseline ) {
6353 0 : for ( i=0; i<=fv->rowcnt; ++i )
6354 0 : 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);
6355 : }
6356 0 : GDrawPopClip(pixmap,&old);
6357 0 : GDrawSetDither(NULL, true);
6358 0 : }
6359 :
6360 0 : void FVDrawInfo(FontView *fv,GWindow pixmap, GEvent *event) {
6361 : GRect old, r;
6362 0 : Color bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
6363 0 : Color fg = fvglyphinfocol;
6364 : SplineChar *sc, dummy;
6365 0 : SplineFont *sf = fv->b.sf;
6366 0 : EncMap *map = fv->b.map;
6367 : int gid, uni, localenc;
6368 0 : GString *output = g_string_new( "" );
6369 0 : gchar *uniname = NULL;
6370 :
6371 0 : if ( event->u.expose.rect.y+event->u.expose.rect.height<=fv->mbh ) {
6372 0 : g_string_free( output, TRUE ); output = NULL;
6373 0 : return;
6374 : }
6375 :
6376 0 : GDrawSetFont(pixmap,fv->fontset[0]);
6377 0 : GDrawPushClip(pixmap,&event->u.expose.rect,&old);
6378 :
6379 0 : r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
6380 0 : GDrawFillRect(pixmap,&r,bg);
6381 0 : if ( fv->end_pos>=map->enccount || fv->pressed_pos>=map->enccount ||
6382 0 : fv->end_pos<0 || fv->pressed_pos<0 )
6383 0 : fv->end_pos = fv->pressed_pos = -1; /* Can happen after reencoding */
6384 0 : if ( fv->end_pos == -1 ) {
6385 0 : g_string_free( output, TRUE ); output = NULL;
6386 0 : GDrawPopClip(pixmap,&old);
6387 0 : return;
6388 : }
6389 :
6390 0 : localenc = fv->end_pos;
6391 0 : if ( map->remap!=NULL ) {
6392 0 : struct remap *remap = map->remap;
6393 0 : while ( remap->infont!=-1 ) {
6394 0 : if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
6395 0 : localenc += remap->firstenc-remap->infont;
6396 0 : break;
6397 : }
6398 0 : ++remap;
6399 : }
6400 : }
6401 0 : g_string_printf( output, "%d (0x%x) ", localenc, localenc );
6402 :
6403 0 : sc = (gid=fv->b.map->map[fv->end_pos])!=-1 ? sf->glyphs[gid] : NULL;
6404 0 : if ( fv->b.cidmaster==NULL || fv->b.normal==NULL || sc==NULL )
6405 0 : SCBuildDummy(&dummy,sf,fv->b.map,fv->end_pos);
6406 : else
6407 0 : dummy = *sc;
6408 0 : if ( sc==NULL ) sc = &dummy;
6409 0 : uni = dummy.unicodeenc!=-1 ? dummy.unicodeenc : sc->unicodeenc;
6410 :
6411 : /* last resort at guessing unicode code point from partial name */
6412 0 : if ( uni == -1 ) {
6413 0 : char *pt = strchr( sc->name, '.' );
6414 0 : if( pt != NULL ) {
6415 0 : gchar *buf = g_strndup( (const gchar *) sc->name, pt - sc->name );
6416 0 : uni = UniFromName( (char *) buf, fv->b.sf->uni_interp, map->enc );
6417 0 : g_free( buf );
6418 : }
6419 : }
6420 :
6421 0 : if ( uni != -1 )
6422 0 : g_string_append_printf( output, "U+%04X", uni );
6423 : else {
6424 0 : output = g_string_append( output, "U+????" );
6425 : }
6426 :
6427 : /* postscript name */
6428 0 : g_string_append_printf( output, " \"%s\" ", sc->name );
6429 :
6430 : /* code point name or range name */
6431 0 : if( uni != -1 ) {
6432 0 : uniname = (gchar *) unicode_name( uni );
6433 0 : if ( uniname == NULL ) {
6434 0 : uniname = g_strdup( UnicodeRange( uni ) );
6435 : }
6436 : }
6437 :
6438 0 : if ( uniname != NULL ) {
6439 0 : output = g_string_append( output, uniname );
6440 0 : g_free( uniname );
6441 : }
6442 :
6443 0 : GDrawDrawText8( pixmap, 10, fv->mbh+fv->lab_as, output->str, -1, fg );
6444 0 : g_string_free( output, TRUE ); output = NULL;
6445 0 : GDrawPopClip( pixmap, &old );
6446 0 : return;
6447 : }
6448 :
6449 0 : static void FVShowInfo(FontView *fv) {
6450 : GRect r;
6451 :
6452 0 : if ( fv->v==NULL ) /* Can happen in scripts */
6453 0 : return;
6454 :
6455 0 : r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
6456 0 : GDrawRequestExpose(fv->gw,&r,false);
6457 : }
6458 :
6459 0 : void FVChar(FontView *fv, GEvent *event) {
6460 : int i,pos, cnt, gid;
6461 : extern int navigation_mask;
6462 :
6463 : #if MyMemory
6464 : if ( event->u.chr.keysym == GK_F2 ) {
6465 : fprintf( stderr, "Malloc debug on\n" );
6466 : __malloc_debug(5);
6467 : } else if ( event->u.chr.keysym == GK_F3 ) {
6468 : fprintf( stderr, "Malloc debug off\n" );
6469 : __malloc_debug(0);
6470 : }
6471 : #endif
6472 :
6473 0 : if ( event->u.chr.keysym=='s' &&
6474 0 : (event->u.chr.state&ksm_control) &&
6475 0 : (event->u.chr.state&ksm_meta) )
6476 0 : MenuSaveAll(NULL,NULL,NULL);
6477 0 : else if ( event->u.chr.keysym=='q' &&
6478 0 : (event->u.chr.state&ksm_control) &&
6479 0 : (event->u.chr.state&ksm_meta) )
6480 0 : MenuExit(NULL,NULL,NULL);
6481 0 : else if ( event->u.chr.keysym=='I' &&
6482 0 : (event->u.chr.state&ksm_shift) &&
6483 0 : (event->u.chr.state&ksm_meta) )
6484 0 : FVMenuCharInfo(fv->gw,NULL,NULL);
6485 0 : else if ( (event->u.chr.keysym=='[' || event->u.chr.keysym==']') &&
6486 0 : (event->u.chr.state&ksm_control) ) {
6487 0 : _FVMenuChangeChar(fv,event->u.chr.keysym=='['?MID_Prev:MID_Next);
6488 0 : } else if ( (event->u.chr.keysym=='{' || event->u.chr.keysym=='}') &&
6489 0 : (event->u.chr.state&ksm_control) ) {
6490 0 : _FVMenuChangeChar(fv,event->u.chr.keysym=='{'?MID_PrevDef:MID_NextDef);
6491 0 : } else if ( event->u.chr.keysym=='\\' && (event->u.chr.state&ksm_control) ) {
6492 : /* European keyboards need a funky modifier to get \ */
6493 0 : FVDoTransform(fv);
6494 : #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
6495 0 : } else if ( isdigit(event->u.chr.keysym) && (event->u.chr.state&ksm_control) &&
6496 0 : (event->u.chr.state&ksm_meta) ) {
6497 : /* The Script menu isn't always up to date, so we might get one of */
6498 : /* the shortcuts here */
6499 0 : int index = event->u.chr.keysym-'1';
6500 0 : if ( index<0 ) index = 9;
6501 0 : if ( script_filenames[index]!=NULL )
6502 0 : ExecuteScriptFile((FontViewBase *) fv,NULL,script_filenames[index]);
6503 : #endif
6504 0 : } else if ( event->u.chr.keysym == GK_Left ||
6505 0 : event->u.chr.keysym == GK_Tab ||
6506 0 : event->u.chr.keysym == GK_BackTab ||
6507 0 : event->u.chr.keysym == GK_Up ||
6508 0 : event->u.chr.keysym == GK_Right ||
6509 0 : event->u.chr.keysym == GK_Down ||
6510 0 : event->u.chr.keysym == GK_KP_Left ||
6511 0 : event->u.chr.keysym == GK_KP_Up ||
6512 0 : event->u.chr.keysym == GK_KP_Right ||
6513 0 : event->u.chr.keysym == GK_KP_Down ||
6514 0 : event->u.chr.keysym == GK_Home ||
6515 0 : event->u.chr.keysym == GK_KP_Home ||
6516 0 : event->u.chr.keysym == GK_End ||
6517 0 : event->u.chr.keysym == GK_KP_End ||
6518 0 : event->u.chr.keysym == GK_Page_Up ||
6519 0 : event->u.chr.keysym == GK_KP_Page_Up ||
6520 0 : event->u.chr.keysym == GK_Prior ||
6521 0 : event->u.chr.keysym == GK_Page_Down ||
6522 0 : event->u.chr.keysym == GK_KP_Page_Down ||
6523 0 : event->u.chr.keysym == GK_Next ) {
6524 0 : int end_pos = fv->end_pos;
6525 : /* We move the currently selected char. If there is none, then pick */
6526 : /* something on the screen */
6527 0 : if ( end_pos==-1 )
6528 0 : end_pos = (fv->rowoff+fv->rowcnt/2)*fv->colcnt;
6529 0 : switch ( event->u.chr.keysym ) {
6530 : case GK_Tab:
6531 0 : pos = end_pos;
6532 : do {
6533 0 : if ( event->u.chr.state&ksm_shift )
6534 0 : --pos;
6535 : else
6536 0 : ++pos;
6537 0 : if ( pos>=fv->b.map->enccount ) pos = 0;
6538 0 : else if ( pos<0 ) pos = fv->b.map->enccount-1;
6539 0 : } while ( pos!=end_pos &&
6540 0 : ((gid=fv->b.map->map[pos])==-1 || !SCWorthOutputting(fv->b.sf->glyphs[gid])));
6541 0 : if ( pos==end_pos ) ++pos;
6542 0 : if ( pos>=fv->b.map->enccount ) pos = 0;
6543 0 : break;
6544 : #if GK_Tab!=GK_BackTab
6545 : case GK_BackTab:
6546 0 : pos = end_pos;
6547 : do {
6548 0 : --pos;
6549 0 : if ( pos<0 ) pos = fv->b.map->enccount-1;
6550 0 : } while ( pos!=end_pos &&
6551 0 : ((gid=fv->b.map->map[pos])==-1 || !SCWorthOutputting(fv->b.sf->glyphs[gid])));
6552 0 : if ( pos==end_pos ) --pos;
6553 0 : if ( pos<0 ) pos = 0;
6554 0 : break;
6555 : #endif
6556 : case GK_Left: case GK_KP_Left:
6557 0 : pos = end_pos-1;
6558 0 : break;
6559 : case GK_Right: case GK_KP_Right:
6560 0 : pos = end_pos+1;
6561 0 : break;
6562 : case GK_Up: case GK_KP_Up:
6563 0 : pos = end_pos-fv->colcnt;
6564 0 : break;
6565 : case GK_Down: case GK_KP_Down:
6566 0 : pos = end_pos+fv->colcnt;
6567 0 : break;
6568 : case GK_End: case GK_KP_End:
6569 0 : pos = fv->b.map->enccount;
6570 0 : break;
6571 : case GK_Home: case GK_KP_Home:
6572 0 : pos = 0;
6573 0 : if ( fv->b.sf->top_enc!=-1 && fv->b.sf->top_enc<fv->b.map->enccount )
6574 0 : pos = fv->b.sf->top_enc;
6575 : else {
6576 0 : pos = SFFindSlot(fv->b.sf,fv->b.map,home_char,NULL);
6577 0 : if ( pos==-1 ) pos = 0;
6578 : }
6579 0 : break;
6580 : case GK_Page_Up: case GK_KP_Page_Up:
6581 : #if GK_Prior!=GK_Page_Up
6582 : case GK_Prior:
6583 : #endif
6584 0 : pos = (fv->rowoff-fv->rowcnt+1)*fv->colcnt;
6585 0 : break;
6586 : case GK_Page_Down: case GK_KP_Page_Down:
6587 : #if GK_Next!=GK_Page_Down
6588 : case GK_Next:
6589 : #endif
6590 0 : pos = (fv->rowoff+fv->rowcnt+1)*fv->colcnt;
6591 0 : break;
6592 : }
6593 0 : if ( pos<0 ) pos = 0;
6594 0 : if ( pos>=fv->b.map->enccount ) pos = fv->b.map->enccount-1;
6595 0 : if ( event->u.chr.state&ksm_shift && event->u.chr.keysym!=GK_Tab && event->u.chr.keysym!=GK_BackTab ) {
6596 0 : FVReselect(fv,pos);
6597 : } else {
6598 0 : FVDeselectAll(fv);
6599 0 : fv->b.selected[pos] = true;
6600 0 : FVToggleCharSelected(fv,pos);
6601 0 : fv->pressed_pos = pos;
6602 0 : fv->sel_index = 1;
6603 : }
6604 0 : fv->end_pos = pos;
6605 0 : FVShowInfo(fv);
6606 0 : FVScrollToChar(fv,pos);
6607 0 : } else if ( event->u.chr.keysym == GK_Help ) {
6608 0 : MenuHelp(NULL,NULL,NULL); /* Menu does F1 */
6609 0 : } else if ( event->u.chr.keysym == GK_Escape ) {
6610 0 : FVDeselectAll(fv);
6611 0 : } else if ( event->u.chr.chars[0]=='\r' || event->u.chr.chars[0]=='\n' ) {
6612 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
6613 0 : return;
6614 0 : for ( i=cnt=0; i<fv->b.map->enccount && cnt<10; ++i ) if ( fv->b.selected[i] ) {
6615 0 : SplineChar *sc = SFMakeChar(fv->b.sf,fv->b.map,i);
6616 0 : if ( fv->show==fv->filled ) {
6617 0 : CharViewCreate(sc,fv,i);
6618 : } else {
6619 0 : BDFFont *bdf = fv->show;
6620 0 : BitmapViewCreate(BDFMakeGID(bdf,sc->orig_pos),bdf,fv,i);
6621 : }
6622 0 : ++cnt;
6623 : }
6624 0 : } else if ( (event->u.chr.state&((GMenuMask()|navigation_mask)&~(ksm_shift|ksm_capslock)))==navigation_mask &&
6625 0 : event->type == et_char &&
6626 0 : event->u.chr.keysym!=0 &&
6627 0 : (event->u.chr.keysym<GK_Special/* || event->u.chr.keysym>=0x10000*/)) {
6628 0 : SplineFont *sf = fv->b.sf;
6629 0 : int enc = EncFromUni(event->u.chr.keysym,fv->b.map->enc);
6630 0 : if ( enc==-1 ) {
6631 0 : for ( i=0; i<sf->glyphcnt; ++i ) {
6632 0 : if ( sf->glyphs[i]!=NULL )
6633 0 : if ( sf->glyphs[i]->unicodeenc==event->u.chr.keysym )
6634 0 : break;
6635 : }
6636 0 : if ( i!=-1 )
6637 0 : enc = fv->b.map->backmap[i];
6638 : }
6639 0 : if ( enc<fv->b.map->enccount && enc!=-1 )
6640 0 : FVChangeChar(fv,enc);
6641 : }
6642 : }
6643 :
6644 0 : static void utf82u_annot_strncat(unichar_t *to, const char *from, int len) {
6645 : register unichar_t ch;
6646 :
6647 0 : to += u_strlen(to);
6648 0 : while ( (ch = utf8_ildb(&from)) != '\0' && --len>=0 ) {
6649 0 : if ( ch=='\t' ) {
6650 0 : *(to++) = ' ';
6651 0 : ch = ' ';
6652 : }
6653 0 : *(to++) = ch;
6654 : }
6655 0 : *to = 0;
6656 0 : }
6657 :
6658 0 : void SCPreparePopup(GWindow gw,SplineChar *sc,struct remap *remap, int localenc,
6659 : int actualuni) {
6660 : /* This is for the popup which appears when you hover mouse over a character on main window */
6661 0 : int upos=-1;
6662 : char *msg, *msg_old;
6663 :
6664 : /* If a glyph is multiply mapped then the inbuild unicode enc may not be */
6665 : /* the actual one used to access the glyph */
6666 0 : if ( remap!=NULL ) {
6667 0 : while ( remap->infont!=-1 ) {
6668 0 : if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
6669 0 : localenc += remap->firstenc-remap->infont;
6670 0 : break;
6671 : }
6672 0 : ++remap;
6673 : }
6674 : }
6675 :
6676 0 : if ( actualuni!=-1 )
6677 0 : upos = actualuni;
6678 0 : else if ( sc->unicodeenc!=-1 )
6679 0 : upos = sc->unicodeenc;
6680 : #if HANYANG
6681 : else if ( sc->compositionunit ) {
6682 : if ( sc->jamo<19 )
6683 : upos = 0x1100+sc->jamo;
6684 : else if ( sc->jamo<19+21 )
6685 : upos = 0x1161 + sc->jamo-19;
6686 : else /* Leave a hole for the blank char */
6687 : upos = 0x11a8 + sc->jamo-(19+21+1);
6688 : }
6689 : #endif
6690 :
6691 0 : if ( upos == -1 ) {
6692 0 : msg = xasprintf( "%u 0x%x U+???? \"%.25s\" ",
6693 : localenc, localenc,
6694 0 : (sc->name == NULL) ? "" : sc->name );
6695 : } else {
6696 : /* unicode name or range name */
6697 0 : char *uniname = unicode_name( upos );
6698 0 : if( uniname == NULL ) uniname = strdup( UnicodeRange( upos ) );
6699 0 : msg = xasprintf ( "%u 0x%x U+%04X \"%.25s\" %.100s",
6700 : localenc, localenc, upos,
6701 0 : (sc->name == NULL) ? "" : sc->name, uniname );
6702 0 : if ( uniname != NULL ) free( uniname ); uniname = NULL;
6703 :
6704 : /* annotation */
6705 0 : char *uniannot = unicode_annot( upos );
6706 0 : if( uniannot != NULL ) {
6707 0 : msg_old = msg;
6708 0 : msg = xasprintf("%s\n%s", msg_old, uniannot);
6709 0 : free(msg_old);
6710 0 : free( uniannot );
6711 : }
6712 : }
6713 :
6714 : /* user comments */
6715 0 : if ( sc->comment!=NULL ) {
6716 0 : msg_old = msg;
6717 0 : msg = xasprintf("%s\n%s", msg_old, sc->comment);
6718 0 : free(msg_old);
6719 : }
6720 :
6721 0 : GGadgetPreparePopup8( gw, msg );
6722 0 : free(msg);
6723 0 : }
6724 :
6725 0 : static void noop(void *UNUSED(_fv)) {
6726 0 : }
6727 :
6728 0 : static void *ddgencharlist(void *_fv,int32 *len) {
6729 : int i,j,cnt, gid;
6730 0 : FontView *fv = (FontView *) _fv;
6731 0 : SplineFont *sf = fv->b.sf;
6732 0 : EncMap *map = fv->b.map;
6733 : char *data;
6734 :
6735 0 : for ( i=cnt=0; i<map->enccount; ++i ) if ( fv->b.selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL )
6736 0 : cnt += strlen(sf->glyphs[gid]->name)+1;
6737 0 : data = malloc(cnt+1); data[0] = '\0';
6738 0 : for ( cnt=0, j=1 ; j<=fv->sel_index; ++j ) {
6739 0 : for ( i=cnt=0; i<map->enccount; ++i )
6740 0 : if ( fv->b.selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
6741 0 : strcpy(data+cnt,sf->glyphs[gid]->name);
6742 0 : cnt += strlen(sf->glyphs[gid]->name);
6743 0 : strcpy(data+cnt++," ");
6744 : }
6745 : }
6746 0 : if ( cnt>0 )
6747 0 : data[--cnt] = '\0';
6748 0 : *len = cnt;
6749 0 : return( data );
6750 : }
6751 :
6752 0 : static void FVMouse(FontView *fv, GEvent *event) {
6753 0 : int pos = (event->u.mouse.y/fv->cbh + fv->rowoff)*fv->colcnt + event->u.mouse.x/fv->cbw;
6754 : int gid;
6755 0 : int realpos = pos;
6756 : SplineChar *sc, dummy;
6757 0 : int dopopup = true;
6758 :
6759 0 : if ( event->type==et_mousedown )
6760 0 : CVPaletteDeactivate();
6761 0 : if ( pos<0 ) {
6762 0 : pos = 0;
6763 0 : dopopup = false;
6764 0 : } else if ( pos>=fv->b.map->enccount ) {
6765 0 : pos = fv->b.map->enccount-1;
6766 0 : if ( pos<0 ) /* No glyph slots in font */
6767 0 : return;
6768 0 : dopopup = false;
6769 : }
6770 :
6771 0 : sc = (gid=fv->b.map->map[pos])!=-1 ? fv->b.sf->glyphs[gid] : NULL;
6772 0 : if ( sc==NULL )
6773 0 : sc = SCBuildDummy(&dummy,fv->b.sf,fv->b.map,pos);
6774 0 : if ( event->type == et_mouseup && event->u.mouse.clicks==2 ) {
6775 0 : if ( fv->pressed ) {
6776 0 : GDrawCancelTimer(fv->pressed);
6777 0 : fv->pressed = NULL;
6778 : }
6779 0 : if ( fv->b.container!=NULL && fv->b.container->funcs->is_modal )
6780 0 : return;
6781 0 : if ( fv->cur_subtable!=NULL ) {
6782 0 : sc = FVMakeChar(fv,pos);
6783 0 : pos = fv->b.map->backmap[sc->orig_pos];
6784 : }
6785 0 : if ( sc==&dummy ) {
6786 0 : sc = SFMakeChar(fv->b.sf,fv->b.map,pos);
6787 0 : gid = fv->b.map->map[pos];
6788 : }
6789 0 : if ( fv->show==fv->filled ) {
6790 0 : SplineFont *sf = fv->b.sf;
6791 0 : gid = -1;
6792 0 : if ( !OpenCharsInNewWindow )
6793 0 : for ( gid=sf->glyphcnt-1; gid>=0; --gid )
6794 0 : if ( sf->glyphs[gid]!=NULL && sf->glyphs[gid]->views!=NULL )
6795 0 : break;
6796 0 : if ( gid!=-1 ) {
6797 0 : CharView *cv = (CharView *) (sf->glyphs[gid]->views);
6798 0 : printf("calling CVChangeSC() sc:%p %s\n", sc, sc->name );
6799 0 : CVChangeSC(cv,sc);
6800 0 : GDrawSetVisible(cv->gw,true);
6801 0 : GDrawRaise(cv->gw);
6802 : } else
6803 0 : CharViewCreate(sc,fv,pos);
6804 : } else {
6805 0 : BDFFont *bdf = fv->show;
6806 0 : BDFChar *bc =BDFMakeGID(bdf,gid);
6807 0 : gid = -1;
6808 0 : if ( !OpenCharsInNewWindow )
6809 0 : for ( gid=bdf->glyphcnt-1; gid>=0; --gid )
6810 0 : if ( bdf->glyphs[gid]!=NULL && bdf->glyphs[gid]->views!=NULL )
6811 0 : break;
6812 0 : if ( gid!=-1 ) {
6813 0 : BitmapView *bv = bdf->glyphs[gid]->views;
6814 0 : BVChangeBC(bv,bc,true);
6815 0 : GDrawSetVisible(bv->gw,true);
6816 0 : GDrawRaise(bv->gw);
6817 : } else
6818 0 : BitmapViewCreate(bc,bdf,fv,pos);
6819 : }
6820 0 : } else if ( event->type == et_mousemove ) {
6821 0 : if ( dopopup )
6822 0 : SCPreparePopup(fv->v,sc,fv->b.map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->b.map->enc));
6823 : }
6824 0 : if ( event->type == et_mousedown ) {
6825 0 : if ( fv->drag_and_drop ) {
6826 0 : GDrawSetCursor(fv->v,ct_mypointer);
6827 0 : fv->any_dd_events_sent = fv->drag_and_drop = false;
6828 : }
6829 0 : if ( !(event->u.mouse.state&ksm_shift) && event->u.mouse.clicks<=1 ) {
6830 0 : if ( !fv->b.selected[pos] )
6831 0 : FVDeselectAll(fv);
6832 0 : else if ( event->u.mouse.button!=3 ) {
6833 0 : fv->drag_and_drop = fv->has_dd_no_cursor = true;
6834 0 : fv->any_dd_events_sent = false;
6835 0 : GDrawSetCursor(fv->v,ct_prohibition);
6836 0 : GDrawGrabSelection(fv->v,sn_drag_and_drop);
6837 0 : GDrawAddSelectionType(fv->v,sn_drag_and_drop,"STRING",fv,0,sizeof(char),
6838 : ddgencharlist,noop);
6839 : }
6840 : }
6841 0 : fv->pressed_pos = fv->end_pos = pos;
6842 0 : FVShowInfo(fv);
6843 0 : if ( !fv->drag_and_drop ) {
6844 0 : if ( !(event->u.mouse.state&ksm_shift))
6845 0 : fv->sel_index = 1;
6846 0 : else if ( fv->sel_index<255 )
6847 0 : ++fv->sel_index;
6848 0 : if ( fv->pressed!=NULL ) {
6849 0 : GDrawCancelTimer(fv->pressed);
6850 0 : fv->pressed = NULL;
6851 0 : } else if ( event->u.mouse.state&ksm_shift ) {
6852 0 : fv->b.selected[pos] = fv->b.selected[pos] ? 0 : fv->sel_index;
6853 0 : FVToggleCharSelected(fv,pos);
6854 0 : } else if ( !fv->b.selected[pos] ) {
6855 0 : fv->b.selected[pos] = fv->sel_index;
6856 0 : FVToggleCharSelected(fv,pos);
6857 : }
6858 0 : if ( event->u.mouse.button==3 )
6859 0 : GMenuCreatePopupMenuWithName(fv->v,event, "Popup", fvpopupmenu);
6860 : else
6861 0 : fv->pressed = GDrawRequestTimer(fv->v,200,100,NULL);
6862 : }
6863 0 : } else if ( fv->drag_and_drop ) {
6864 0 : GWindow othergw = GDrawGetPointerWindow(fv->v);
6865 :
6866 0 : if ( othergw==fv->v || othergw==fv->gw || othergw==NULL ) {
6867 0 : if ( !fv->has_dd_no_cursor ) {
6868 0 : fv->has_dd_no_cursor = true;
6869 0 : GDrawSetCursor(fv->v,ct_prohibition);
6870 : }
6871 : } else {
6872 0 : if ( fv->has_dd_no_cursor ) {
6873 0 : fv->has_dd_no_cursor = false;
6874 0 : GDrawSetCursor(fv->v,ct_ddcursor);
6875 : }
6876 : }
6877 0 : if ( event->type==et_mouseup ) {
6878 0 : if ( pos!=fv->pressed_pos ) {
6879 0 : GDrawPostDragEvent(fv->v,event,event->type==et_mouseup?et_drop:et_drag);
6880 0 : fv->any_dd_events_sent = true;
6881 : }
6882 0 : fv->drag_and_drop = fv->has_dd_no_cursor = false;
6883 0 : GDrawSetCursor(fv->v,ct_mypointer);
6884 0 : if ( !fv->any_dd_events_sent )
6885 0 : FVDeselectAll(fv);
6886 0 : fv->any_dd_events_sent = false;
6887 : }
6888 0 : } else if ( fv->pressed!=NULL ) {
6889 0 : int showit = realpos!=fv->end_pos;
6890 0 : FVReselect(fv,realpos);
6891 0 : if ( showit )
6892 0 : FVShowInfo(fv);
6893 0 : if ( event->type==et_mouseup ) {
6894 0 : GDrawCancelTimer(fv->pressed);
6895 0 : fv->pressed = NULL;
6896 : }
6897 : }
6898 0 : if ( event->type==et_mouseup && dopopup )
6899 0 : SCPreparePopup(fv->v,sc,fv->b.map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->b.map->enc));
6900 0 : if ( event->type==et_mouseup )
6901 0 : SVAttachFV(fv,2);
6902 : }
6903 :
6904 0 : static void FVResize(FontView *fv, GEvent *event) {
6905 : extern int default_fv_row_count, default_fv_col_count;
6906 : GRect pos,screensize;
6907 : int topchar;
6908 :
6909 0 : if ( fv->colcnt!=0 )
6910 0 : topchar = fv->rowoff*fv->colcnt;
6911 0 : else if ( fv->b.sf->top_enc!=-1 && fv->b.sf->top_enc<fv->b.map->enccount )
6912 0 : topchar = fv->b.sf->top_enc;
6913 : else {
6914 : /* Position on 'A' (or whatever they ask for) if it exists */
6915 0 : topchar = SFFindSlot(fv->b.sf,fv->b.map,home_char,NULL);
6916 0 : if ( topchar==-1 ) {
6917 0 : for ( topchar=0; topchar<fv->b.map->enccount; ++topchar )
6918 0 : if ( fv->b.map->map[topchar]!=-1 && fv->b.sf->glyphs[fv->b.map->map[topchar]]!=NULL )
6919 0 : break;
6920 0 : if ( topchar==fv->b.map->enccount )
6921 0 : topchar = 0;
6922 : }
6923 : }
6924 0 : if ( !event->u.resize.sized )
6925 : /* WM isn't responding to my resize requests, so no point in trying */;
6926 0 : else if ( (event->u.resize.size.width-
6927 0 : GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)%fv->cbw!=0 ||
6928 0 : (event->u.resize.size.height-fv->mbh-fv->infoh-1)%fv->cbh!=0 ) {
6929 0 : int cc = (event->u.resize.size.width+fv->cbw/2-
6930 0 : GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)/fv->cbw;
6931 0 : int rc = (event->u.resize.size.height-fv->mbh-fv->infoh-1)/fv->cbh;
6932 0 : if ( cc<=0 ) cc = 1;
6933 0 : if ( rc<=0 ) rc = 1;
6934 0 : GDrawGetSize(GDrawGetRoot(NULL),&screensize);
6935 0 : if ( cc*fv->cbw+GDrawPointsToPixels(fv->gw,_GScrollBar_Width)>screensize.width )
6936 0 : --cc;
6937 0 : if ( rc*fv->cbh+fv->mbh+fv->infoh+10>screensize.height )
6938 0 : --rc;
6939 0 : GDrawResize(fv->gw,
6940 0 : cc*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
6941 0 : rc*fv->cbh+1+fv->mbh+fv->infoh);
6942 : /* somehow KDE loses this event of mine so to get even the vague effect */
6943 : /* we can't just return */
6944 : /*return;*/
6945 : }
6946 :
6947 0 : pos.width = GDrawPointsToPixels(fv->gw,_GScrollBar_Width);
6948 0 : pos.height = event->u.resize.size.height-fv->mbh-fv->infoh;
6949 0 : pos.x = event->u.resize.size.width-pos.width; pos.y = fv->mbh+fv->infoh;
6950 0 : GGadgetResize(fv->vsb,pos.width,pos.height);
6951 0 : GGadgetMove(fv->vsb,pos.x,pos.y);
6952 0 : pos.width = pos.x; pos.x = 0;
6953 0 : GDrawResize(fv->v,pos.width,pos.height);
6954 :
6955 0 : fv->width = pos.width; fv->height = pos.height;
6956 0 : fv->colcnt = (fv->width-1)/fv->cbw;
6957 0 : if ( fv->colcnt<1 ) fv->colcnt = 1;
6958 0 : fv->rowcnt = (fv->height-1)/fv->cbh;
6959 0 : if ( fv->rowcnt<1 ) fv->rowcnt = 1;
6960 0 : fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
6961 :
6962 0 : GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
6963 0 : fv->rowoff = topchar/fv->colcnt;
6964 0 : if ( fv->rowoff>=fv->rowltot-fv->rowcnt )
6965 0 : fv->rowoff = fv->rowltot-fv->rowcnt;
6966 0 : if ( fv->rowoff<0 ) fv->rowoff =0;
6967 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
6968 0 : GDrawRequestExpose(fv->gw,NULL,true);
6969 0 : GDrawRequestExpose(fv->v,NULL,true);
6970 :
6971 0 : if ( fv->rowcnt!=fv->b.sf->desired_row_cnt || fv->colcnt!=fv->b.sf->desired_col_cnt ) {
6972 0 : default_fv_row_count = fv->rowcnt;
6973 0 : default_fv_col_count = fv->colcnt;
6974 0 : fv->b.sf->desired_row_cnt = fv->rowcnt;
6975 0 : fv->b.sf->desired_col_cnt = fv->colcnt;
6976 0 : SavePrefs(true);
6977 : }
6978 0 : }
6979 :
6980 0 : static void FVTimer(FontView *fv, GEvent *event) {
6981 :
6982 0 : if ( event->u.timer.timer==fv->pressed ) {
6983 : GEvent e;
6984 0 : GDrawGetPointerPosition(fv->v,&e);
6985 0 : if ( e.u.mouse.y<0 || e.u.mouse.y >= fv->height ) {
6986 0 : real dy = 0;
6987 0 : if ( e.u.mouse.y<0 )
6988 0 : dy = -1;
6989 0 : else if ( e.u.mouse.y>=fv->height )
6990 0 : dy = 1;
6991 0 : if ( fv->rowoff+dy<0 )
6992 0 : dy = 0;
6993 0 : else if ( fv->rowoff+dy+fv->rowcnt > fv->rowltot )
6994 0 : dy = 0;
6995 0 : fv->rowoff += dy;
6996 0 : if ( dy!=0 ) {
6997 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
6998 0 : GDrawScroll(fv->v,NULL,0,dy*fv->cbh);
6999 : }
7000 : }
7001 0 : } else if ( event->u.timer.timer==fv->resize ) {
7002 : /* It's a delayed resize event (for kde which sends continuous resizes) */
7003 0 : fv->resize = NULL;
7004 0 : FVResize(fv,(GEvent *) (event->u.timer.userdata));
7005 0 : } else if ( event->u.timer.userdata!=NULL ) {
7006 : /* It's a delayed function call */
7007 0 : void (*func)(FontView *) = (void (*)(FontView *)) (event->u.timer.userdata);
7008 0 : func(fv);
7009 : }
7010 0 : }
7011 :
7012 0 : void FVDelay(FontView *fv,void (*func)(FontView *)) {
7013 0 : GDrawRequestTimer(fv->v,100,0,(void *) func);
7014 0 : }
7015 :
7016 0 : static int FVScroll(GGadget *g, GEvent *e) {
7017 0 : FontView *fv = GGadgetGetUserData(g);
7018 0 : int newpos = fv->rowoff;
7019 0 : struct sbevent *sb = &e->u.control.u.sb;
7020 :
7021 0 : switch( sb->type ) {
7022 : case et_sb_top:
7023 0 : newpos = 0;
7024 0 : break;
7025 : case et_sb_uppage:
7026 0 : newpos -= fv->rowcnt;
7027 0 : break;
7028 : case et_sb_up:
7029 0 : --newpos;
7030 0 : break;
7031 : case et_sb_down:
7032 0 : ++newpos;
7033 0 : break;
7034 : case et_sb_downpage:
7035 0 : newpos += fv->rowcnt;
7036 0 : break;
7037 : case et_sb_bottom:
7038 0 : newpos = fv->rowltot-fv->rowcnt;
7039 0 : break;
7040 : case et_sb_thumb:
7041 : case et_sb_thumbrelease:
7042 0 : newpos = sb->pos;
7043 0 : break;
7044 : }
7045 0 : if ( newpos>fv->rowltot-fv->rowcnt )
7046 0 : newpos = fv->rowltot-fv->rowcnt;
7047 0 : if ( newpos<0 ) newpos =0;
7048 0 : if ( newpos!=fv->rowoff ) {
7049 0 : int diff = newpos-fv->rowoff;
7050 0 : fv->rowoff = newpos;
7051 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
7052 0 : GDrawScroll(fv->v,NULL,0,diff*fv->cbh);
7053 : }
7054 0 : return( true );
7055 : }
7056 :
7057 0 : static int v_e_h(GWindow gw, GEvent *event) {
7058 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
7059 :
7060 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
7061 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
7062 0 : return( GGadgetDispatchEvent(fv->vsb,event));
7063 : }
7064 :
7065 0 : GGadgetPopupExternalEvent(event);
7066 0 : switch ( event->type ) {
7067 : case et_expose:
7068 0 : GDrawSetLineWidth(gw,0);
7069 0 : FVExpose(fv,gw,event);
7070 0 : break;
7071 : case et_char:
7072 0 : if ( fv->b.container!=NULL )
7073 0 : (fv->b.container->funcs->charEvent)(fv->b.container,event);
7074 : else
7075 0 : FVChar(fv,event);
7076 0 : break;
7077 : case et_mousemove: case et_mousedown: case et_mouseup:
7078 0 : if ( event->type==et_mousedown )
7079 0 : GDrawSetGIC(gw,fv->gic,0,20);
7080 0 : if ( fv->notactive && event->type==et_mousedown )
7081 0 : (fv->b.container->funcs->activateMe)(fv->b.container,&fv->b);
7082 0 : FVMouse(fv,event);
7083 0 : break;
7084 : case et_timer:
7085 0 : FVTimer(fv,event);
7086 0 : break;
7087 : case et_focus:
7088 0 : printf("fv.et_focus\n");
7089 0 : if ( event->u.focus.gained_focus )
7090 0 : GDrawSetGIC(gw,fv->gic,0,20);
7091 0 : break;
7092 : }
7093 0 : return( true );
7094 : }
7095 :
7096 0 : static void FontView_ReformatOne(FontView *fv) {
7097 : FontView *fvs;
7098 :
7099 0 : if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
7100 0 : return;
7101 :
7102 0 : GDrawSetCursor(fv->v,ct_watch);
7103 0 : fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
7104 0 : GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7105 0 : if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
7106 0 : fv->rowoff = fv->rowltot-fv->rowcnt;
7107 0 : if ( fv->rowoff<0 ) fv->rowoff =0;
7108 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
7109 : }
7110 0 : for ( fvs=(FontView *) (fv->b.sf->fv); fvs!=NULL; fvs=(FontView *) (fvs->b.nextsame) )
7111 0 : if ( fvs!=fv && fvs->b.sf==fv->b.sf )
7112 0 : break;
7113 0 : GDrawRequestExpose(fv->v,NULL,false);
7114 0 : GDrawSetCursor(fv->v,ct_pointer);
7115 : }
7116 :
7117 1 : static void FontView_ReformatAll(SplineFont *sf) {
7118 : BDFFont *new, *old, *bdf;
7119 : FontView *fv;
7120 : MetricsView *mvs;
7121 : extern int use_freetype_to_rasterize_fv;
7122 :
7123 1 : if ( ((FontView *) (sf->fv))->v==NULL || ((FontView *) (sf->fv))->colcnt==0 ) /* Can happen in scripts */
7124 2 : return;
7125 :
7126 0 : for ( fv=(FontView *) (sf->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) ) {
7127 0 : GDrawSetCursor(fv->v,ct_watch);
7128 0 : old = fv->filled;
7129 : /* In CID fonts fv->b.sf may not be same as sf */
7130 0 : new = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,fv->filled->pixelsize,72,
7131 0 : (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
7132 0 : (use_freetype_to_rasterize_fv && !sf->strokedfont && !sf->multilayer?pf_ft_nohints:0),
7133 : NULL);
7134 0 : fv->filled = new;
7135 0 : if ( fv->show==old )
7136 0 : fv->show = new;
7137 : else {
7138 0 : for ( bdf=sf->bitmaps; bdf != NULL &&
7139 0 : ( bdf->pixelsize != fv->show->pixelsize || BDFDepth( bdf ) != BDFDepth( fv->show )); bdf=bdf->next );
7140 0 : if ( bdf != NULL ) fv->show = bdf;
7141 0 : else fv->show = new;
7142 : }
7143 0 : BDFFontFree(old);
7144 0 : fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
7145 0 : GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7146 0 : if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
7147 0 : fv->rowoff = fv->rowltot-fv->rowcnt;
7148 0 : if ( fv->rowoff<0 ) fv->rowoff =0;
7149 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
7150 : }
7151 0 : GDrawRequestExpose(fv->v,NULL,false);
7152 0 : GDrawSetCursor(fv->v,ct_pointer);
7153 : }
7154 0 : for ( mvs=sf->metrics; mvs!=NULL; mvs=mvs->next ) if ( mvs->bdf==NULL ) {
7155 0 : BDFFontFree(mvs->show);
7156 0 : mvs->show = SplineFontPieceMeal(sf,mvs->layer,mvs->ptsize,mvs->dpi,
7157 0 : mvs->antialias?(pf_antialias|pf_ft_recontext):pf_ft_recontext,NULL);
7158 0 : GDrawRequestExpose(mvs->gw,NULL,false);
7159 : }
7160 : }
7161 :
7162 31 : void FontViewRemove(FontView *fv) {
7163 31 : if ( fv_list==fv )
7164 27 : fv_list = (FontView *) (fv->b.next);
7165 : else {
7166 : FontView *n;
7167 4 : for ( n=fv_list; n->b.next!=&fv->b; n=(FontView *) (n->b.next) );
7168 4 : n->b.next = fv->b.next;
7169 : }
7170 31 : FontViewFree(&fv->b);
7171 31 : }
7172 :
7173 : /**
7174 : * In some cases fontview gets an et_selclear event when using copy
7175 : * and paste on the OSX. So this guard lets us quietly ignore that
7176 : * event when we have just done command+c or command+x.
7177 : */
7178 : extern int osx_fontview_copy_cut_counter;
7179 :
7180 : static FontView* ActiveFontView = 0;
7181 :
7182 0 : static int fv_e_h(GWindow gw, GEvent *event) {
7183 0 : FontView *fv = (FontView *) GDrawGetUserData(gw);
7184 :
7185 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
7186 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
7187 0 : return( GGadgetDispatchEvent(fv->vsb,event));
7188 : }
7189 :
7190 0 : switch ( event->type ) {
7191 : case et_focus:
7192 0 : if ( event->u.focus.gained_focus )
7193 : {
7194 0 : ActiveFontView = fv;
7195 : }
7196 : else
7197 : {
7198 : }
7199 0 : break;
7200 : case et_selclear:
7201 : #ifdef __Mac
7202 : // For some reason command + c and command + x wants
7203 : // to send a clear to us, even if that key was pressed
7204 : // on a charview.
7205 : if( osx_fontview_copy_cut_counter )
7206 : {
7207 : osx_fontview_copy_cut_counter--;
7208 : break;
7209 : }
7210 : // printf("fontview et_selclear\n");
7211 : #endif
7212 0 : ClipboardClear();
7213 0 : break;
7214 : case et_expose:
7215 0 : GDrawSetLineWidth(gw,0);
7216 0 : FVDrawInfo(fv,gw,event);
7217 0 : break;
7218 : case et_resize:
7219 : /* KDE sends a continuous stream of resize events, and gets very */
7220 : /* confused if I start resizing the window myself, try to wait for */
7221 : /* the user to finish before responding to resizes */
7222 0 : if ( event->u.resize.sized || fv->resize_expected ) {
7223 0 : if ( fv->resize )
7224 0 : GDrawCancelTimer(fv->resize);
7225 0 : fv->resize_event = *event;
7226 0 : fv->resize = GDrawRequestTimer(fv->v,300,0,(void *) &fv->resize_event);
7227 0 : fv->resize_expected = false;
7228 : }
7229 0 : break;
7230 : case et_char:
7231 0 : if ( fv->b.container!=NULL )
7232 0 : (fv->b.container->funcs->charEvent)(fv->b.container,event);
7233 : else
7234 0 : FVChar(fv,event);
7235 0 : break;
7236 : case et_mousedown:
7237 0 : GDrawSetGIC(gw,fv->gwgic,0,20);
7238 0 : if ( fv->notactive )
7239 0 : (fv->b.container->funcs->activateMe)(fv->b.container,&fv->b);
7240 0 : break;
7241 : case et_close:
7242 0 : FVMenuClose(gw,NULL,NULL);
7243 0 : break;
7244 : case et_create:
7245 0 : fv->b.next = (FontViewBase *) fv_list;
7246 0 : fv_list = fv;
7247 0 : break;
7248 : case et_destroy:
7249 0 : if ( fv->qg!=NULL )
7250 0 : QGRmFontView(fv->qg,fv);
7251 0 : FontViewRemove(fv);
7252 0 : break;
7253 : }
7254 0 : return( true );
7255 : }
7256 :
7257 0 : static void FontViewOpenKids(FontView *fv) {
7258 : int k, i;
7259 0 : SplineFont *sf = fv->b.sf, *_sf;
7260 : #if defined(__Mac)
7261 : int cnt= 0;
7262 : #endif
7263 :
7264 0 : if ( sf->cidmaster!=NULL )
7265 0 : sf = sf->cidmaster;
7266 :
7267 0 : k=0;
7268 : do {
7269 0 : _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
7270 0 : for ( i=0; i<_sf->glyphcnt; ++i )
7271 0 : if ( _sf->glyphs[i]!=NULL && _sf->glyphs[i]->wasopen ) {
7272 0 : _sf->glyphs[i]->wasopen = false;
7273 : #if defined(__Mac)
7274 : /* If we open a bunch of charviews all at once on the mac, X11*/
7275 : /* crashes */ /* But opening one seems ok */
7276 : if ( ++cnt==1 )
7277 : #endif
7278 0 : CharViewCreate(_sf->glyphs[i],fv,-1);
7279 : }
7280 0 : ++k;
7281 0 : } while ( k<sf->subfontcnt );
7282 0 : }
7283 :
7284 68 : static FontView *__FontViewCreate(SplineFont *sf) {
7285 68 : FontView *fv = calloc(1,sizeof(FontView));
7286 : int i;
7287 69 : int ps = sf->display_size<0 ? -sf->display_size :
7288 1 : sf->display_size==0 ? default_fv_font_size : sf->display_size;
7289 :
7290 68 : if ( ps>200 ) ps = 128;
7291 :
7292 : /* Filename != NULL if we opened an sfd file. Sfd files know whether */
7293 : /* the font is compact or not and should not depend on a global flag */
7294 : /* If a font is new, then compaction will make it vanish completely */
7295 68 : if ( sf->fv==NULL && compact_font_on_open && sf->filename==NULL && !sf->new ) {
7296 0 : sf->compacted = true;
7297 0 : for ( i=0; i<sf->subfontcnt; ++i )
7298 0 : sf->subfonts[i]->compacted = true;
7299 : }
7300 68 : fv->b.nextsame = sf->fv;
7301 68 : fv->b.active_layer = sf->display_layer;
7302 68 : sf->fv = (FontViewBase *) fv;
7303 68 : if ( sf->mm!=NULL ) {
7304 2 : sf->mm->normal->fv = (FontViewBase *) fv;
7305 6 : for ( i = 0; i<sf->mm->instance_count; ++i )
7306 4 : sf->mm->instances[i]->fv = (FontViewBase *) fv;
7307 : }
7308 68 : if ( sf->subfontcnt==0 ) {
7309 67 : fv->b.sf = sf;
7310 67 : if ( fv->b.nextsame!=NULL ) {
7311 0 : fv->b.map = EncMapCopy(fv->b.nextsame->map);
7312 0 : fv->b.normal = fv->b.nextsame->normal==NULL ? NULL : EncMapCopy(fv->b.nextsame->normal);
7313 67 : } else if ( sf->compacted ) {
7314 0 : fv->b.normal = sf->map;
7315 0 : fv->b.map = CompactEncMap(EncMapCopy(sf->map),sf);
7316 0 : sf->map = fv->b.map;
7317 : } else {
7318 67 : fv->b.map = sf->map;
7319 67 : fv->b.normal = NULL;
7320 : }
7321 : } else {
7322 1 : fv->b.cidmaster = sf;
7323 5 : for ( i=0; i<sf->subfontcnt; ++i )
7324 4 : sf->subfonts[i]->fv = (FontViewBase *) fv;
7325 1 : for ( i=0; i<sf->subfontcnt; ++i ) /* Search for a subfont that contains more than ".notdef" (most significant in .gai fonts) */
7326 1 : if ( sf->subfonts[i]->glyphcnt>1 ) {
7327 1 : fv->b.sf = sf->subfonts[i];
7328 1 : break;
7329 : }
7330 1 : if ( fv->b.sf==NULL )
7331 0 : fv->b.sf = sf->subfonts[0];
7332 1 : sf = fv->b.sf;
7333 1 : if ( fv->b.nextsame==NULL ) { EncMapFree(sf->map); sf->map = NULL; }
7334 1 : fv->b.map = EncMap1to1(sf->glyphcnt);
7335 1 : if ( fv->b.nextsame==NULL ) { sf->map = fv->b.map; }
7336 1 : if ( sf->compacted ) {
7337 0 : fv->b.normal = fv->b.map;
7338 0 : fv->b.map = CompactEncMap(EncMapCopy(fv->b.map),sf);
7339 0 : if ( fv->b.nextsame==NULL ) { sf->map = fv->b.map; }
7340 : }
7341 : }
7342 68 : fv->b.selected = calloc((fv->b.map ? fv->b.map->enccount : 0), sizeof(char));
7343 68 : fv->user_requested_magnify = -1;
7344 68 : fv->magnify = (ps<=9)? 3 : (ps<20) ? 2 : 1;
7345 68 : fv->cbw = (ps*fv->magnify)+1;
7346 68 : fv->cbh = (ps*fv->magnify)+1+fv->lab_height+1;
7347 68 : fv->antialias = sf->display_antialias;
7348 68 : fv->bbsized = sf->display_bbsized;
7349 68 : fv->glyphlabel = default_fv_glyphlabel;
7350 :
7351 68 : fv->end_pos = -1;
7352 : #ifndef _NO_PYTHON
7353 68 : PyFF_InitFontHook((FontViewBase *)fv);
7354 : #endif
7355 :
7356 68 : fv->pid_webfontserver = 0;
7357 :
7358 68 : return( fv );
7359 : }
7360 :
7361 : static int fontview_ready = false;
7362 :
7363 0 : static void FontViewFinish() {
7364 0 : if (!fontview_ready) return;
7365 0 : mb2FreeGetText(mblist);
7366 0 : mbFreeGetText(fvpopupmenu);
7367 : }
7368 :
7369 0 : void FontViewFinishNonStatic() {
7370 0 : FontViewFinish();
7371 0 : }
7372 :
7373 0 : static void FontViewInit(void) {
7374 : // static int done = false; // superseded by fontview_ready.
7375 :
7376 0 : if ( fontview_ready )
7377 0 : return;
7378 :
7379 0 : fontview_ready = true;
7380 :
7381 0 : mb2DoGetText(mblist);
7382 0 : mbDoGetText(fvpopupmenu);
7383 0 : atexit(&FontViewFinishNonStatic);
7384 : }
7385 :
7386 : static struct resed fontview_re[] = {
7387 : {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 },
7388 : {N_("Empty Slot FG Color"), "EmptySlotFgColor", rt_color, &fvemtpyslotfgcol, N_("Color used to draw the foreground of empty slots"), NULL, { 0 }, 0, 0 },
7389 : {N_("Selected BG Color"), "SelectedColor", rt_color, &fvselcol, N_("Color used to draw the background of selected glyphs"), NULL, { 0 }, 0, 0 },
7390 : {N_("Selected FG Color"), "SelectedFgColor", rt_color, &fvselfgcol, N_("Color used to draw the foreground of selected glyphs"), NULL, { 0 }, 0, 0 },
7391 : {N_("Changed Color"), "ChangedColor", rt_color, &fvchangedcol, N_("Color used to mark a changed glyph"), NULL, { 0 }, 0, 0 },
7392 : {N_("Hinting Needed Color"), "HintingNeededColor", rt_color, &fvhintingneededcol, N_("Color used to mark glyphs that need hinting"), NULL, { 0 }, 0, 0 },
7393 : {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 },
7394 : {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 },
7395 : RESED_EMPTY
7396 : };
7397 :
7398 0 : static void FVCreateInnards(FontView *fv,GRect *pos) {
7399 0 : GWindow gw = fv->gw;
7400 : GWindowAttrs wattrs;
7401 : GGadgetData gd;
7402 : FontRequest rq;
7403 : BDFFont *bdf;
7404 : int as,ds,ld;
7405 : extern int use_freetype_to_rasterize_fv;
7406 0 : SplineFont *sf = fv->b.sf;
7407 :
7408 0 : fv->lab_height = FV_LAB_HEIGHT-13+GDrawPointsToPixels(NULL,fv_fontsize);
7409 :
7410 0 : memset(&gd,0,sizeof(gd));
7411 0 : gd.pos.y = pos->y; gd.pos.height = pos->height;
7412 0 : gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
7413 0 : gd.pos.x = pos->width;
7414 0 : gd.u.sbinit = NULL;
7415 0 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
7416 0 : gd.handle_controlevent = FVScroll;
7417 0 : fv->vsb = GScrollBarCreate(gw,&gd,fv);
7418 :
7419 :
7420 0 : memset(&wattrs,0,sizeof(wattrs));
7421 0 : wattrs.mask = wam_events|wam_cursor|wam_backcol;
7422 0 : wattrs.event_masks = ~(1<<et_charup);
7423 0 : wattrs.cursor = ct_pointer;
7424 0 : wattrs.background_color = view_bgcol;
7425 0 : fv->v = GWidgetCreateSubWindow(gw,pos,v_e_h,fv,&wattrs);
7426 0 : GDrawSetVisible(fv->v,true);
7427 0 : GDrawSetWindowTypeName(fv->v, "FontView");
7428 :
7429 0 : fv->gic = GDrawCreateInputContext(fv->v,gic_root|gic_orlesser);
7430 0 : fv->gwgic = GDrawCreateInputContext(fv->gw,gic_root|gic_orlesser);
7431 0 : GDrawSetGIC(fv->v,fv->gic,0,20);
7432 0 : GDrawSetGIC(fv->gw,fv->gic,0,20);
7433 :
7434 0 : fv->fontset = calloc(_uni_fontmax,sizeof(GFont *));
7435 0 : memset(&rq,0,sizeof(rq));
7436 0 : rq.utf8_family_name = fv_fontnames;
7437 0 : rq.point_size = fv_fontsize;
7438 0 : rq.weight = 400;
7439 0 : fv->fontset[0] = GDrawInstanciateFont(gw,&rq);
7440 0 : GDrawSetFont(fv->v,fv->fontset[0]);
7441 0 : GDrawWindowFontMetrics(fv->v,fv->fontset[0],&as,&ds,&ld);
7442 0 : fv->lab_as = as;
7443 0 : fv->showhmetrics = default_fv_showhmetrics;
7444 0 : fv->showvmetrics = default_fv_showvmetrics && sf->hasvmetrics;
7445 0 : bdf = SplineFontPieceMeal(fv->b.sf,fv->b.active_layer,sf->display_size<0?-sf->display_size:default_fv_font_size,72,
7446 0 : (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0)|
7447 0 : (use_freetype_to_rasterize_fv && !sf->strokedfont && !sf->multilayer?pf_ft_nohints:0),
7448 : NULL);
7449 0 : fv->filled = bdf;
7450 0 : if ( sf->display_size>0 ) {
7451 0 : for ( bdf=sf->bitmaps; bdf!=NULL && bdf->pixelsize!=sf->display_size ;
7452 0 : bdf=bdf->next );
7453 0 : if ( bdf==NULL )
7454 0 : bdf = fv->filled;
7455 : }
7456 0 : if ( sf->onlybitmaps && bdf==fv->filled && sf->bitmaps!=NULL )
7457 0 : bdf = sf->bitmaps;
7458 0 : fv->cbw = -1;
7459 0 : FVChangeDisplayFont(fv,bdf);
7460 0 : }
7461 :
7462 0 : static FontView *FontView_Create(SplineFont *sf, int hide) {
7463 0 : FontView *fv = (FontView *) __FontViewCreate(sf);
7464 : GRect pos;
7465 : GWindow gw;
7466 : GWindowAttrs wattrs;
7467 : GGadgetData gd;
7468 : GRect gsize;
7469 : static GWindow icon = NULL;
7470 : static int nexty=0;
7471 : GRect size;
7472 :
7473 0 : FontViewInit();
7474 0 : if ( icon==NULL ) {
7475 : #ifdef BIGICONS
7476 : icon = GDrawCreateBitmap(NULL,fontview_width,fontview_height,fontview_bits);
7477 : #else
7478 0 : icon = GDrawCreateBitmap(NULL,fontview2_width,fontview2_height,fontview2_bits);
7479 : #endif
7480 : }
7481 :
7482 0 : GDrawGetSize(GDrawGetRoot(NULL),&size);
7483 :
7484 0 : memset(&wattrs,0,sizeof(wattrs));
7485 0 : wattrs.mask = wam_events|wam_cursor|wam_icon;
7486 0 : wattrs.event_masks = ~(1<<et_charup);
7487 0 : wattrs.cursor = ct_pointer;
7488 0 : wattrs.icon = icon;
7489 0 : pos.width = sf->desired_col_cnt*fv->cbw+1;
7490 0 : pos.height = sf->desired_row_cnt*fv->cbh+1;
7491 0 : pos.x = size.width-pos.width-30; pos.y = nexty;
7492 0 : nexty += 2*fv->cbh+50;
7493 0 : if ( nexty+pos.height > size.height )
7494 0 : nexty = 0;
7495 0 : fv->gw = gw = GDrawCreateTopWindow(NULL,&pos,fv_e_h,fv,&wattrs);
7496 0 : FontViewSetTitle(fv);
7497 0 : GDrawSetWindowTypeName(fv->gw, "FontView");
7498 :
7499 0 : if ( !fv_fs_init ) {
7500 0 : GResEditFind( fontview_re, "FontView.");
7501 0 : view_bgcol = GResourceFindColor("View.Background",GDrawGetDefaultBackground(NULL));
7502 0 : fv_fs_init = true;
7503 : }
7504 :
7505 0 : memset(&gd,0,sizeof(gd));
7506 0 : gd.flags = gg_visible | gg_enabled;
7507 0 : helplist[0].invoke = FVMenuContextualHelp;
7508 : #ifndef _NO_PYTHON
7509 0 : if ( fvpy_menu!=NULL )
7510 0 : mblist[3].ti.disabled = false;
7511 0 : mblist[3].sub = fvpy_menu;
7512 : #define CALLBACKS_INDEX 4 /* FIXME: There has to be a better way than this. */
7513 : #else
7514 : #define CALLBACKS_INDEX 3 /* FIXME: There has to be a better way than this. */
7515 : #endif /* _NO_PYTHON */
7516 : #ifdef NATIVE_CALLBACKS
7517 : if ( fv_menu!=NULL )
7518 : mblist[CALLBACKS_INDEX].ti.disabled = false;
7519 : mblist[CALLBACKS_INDEX].sub = fv_menu;
7520 : #endif /* NATIVE_CALLBACKS */
7521 0 : gd.u.menu2 = mblist;
7522 0 : fv->mb = GMenu2BarCreate( gw, &gd, NULL);
7523 0 : GGadgetGetSize(fv->mb,&gsize);
7524 0 : fv->mbh = gsize.height;
7525 0 : fv->infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
7526 :
7527 0 : pos.x = 0; pos.y = fv->mbh+fv->infoh;
7528 0 : FVCreateInnards(fv,&pos);
7529 :
7530 0 : if ( !hide ) {
7531 0 : GDrawSetVisible(gw,true);
7532 0 : FontViewOpenKids(fv);
7533 : }
7534 0 : return( fv );
7535 : }
7536 :
7537 68 : static FontView *FontView_Append(FontView *fv) {
7538 : /* Normally fontviews get added to the fv list when their windows are */
7539 : /* created. but we don't create any windows here, so... */
7540 : FontView *test;
7541 :
7542 68 : if ( fv_list==NULL ) fv_list = fv;
7543 : else {
7544 13 : for ( test = fv_list; test->b.next!=NULL; test=(FontView *) test->b.next );
7545 13 : test->b.next = (FontViewBase *) fv;
7546 : }
7547 68 : return( fv );
7548 : }
7549 :
7550 0 : FontView *FontNew(void) {
7551 0 : return( FontView_Create(SplineFontNew(),false));
7552 : }
7553 :
7554 31 : static void FontView_Free(FontView *fv) {
7555 : int i;
7556 : FontView *prev;
7557 : FontView *fvs;
7558 :
7559 31 : if ( fv->b.sf == NULL ) /* Happens when usurping a font to put it into an MM */
7560 0 : BDFFontFree(fv->filled);
7561 31 : else if ( fv->b.nextsame==NULL && fv->b.sf->fv==&fv->b ) {
7562 31 : EncMapFree(fv->b.map);
7563 31 : if (fv->b.sf != NULL && fv->b.map == fv->b.sf->map) { fv->b.sf->map = NULL; }
7564 31 : SplineFontFree(fv->b.cidmaster?fv->b.cidmaster:fv->b.sf);
7565 31 : BDFFontFree(fv->filled);
7566 : } else {
7567 0 : EncMapFree(fv->b.map);
7568 0 : if (fv->b.sf != NULL && fv->b.map == fv->b.sf->map) { fv->b.sf->map = NULL; }
7569 0 : fv->b.map = NULL;
7570 0 : for ( fvs=(FontView *) (fv->b.sf->fv), i=0 ; fvs!=NULL; fvs = (FontView *) (fvs->b.nextsame) )
7571 0 : if ( fvs->filled==fv->filled ) ++i;
7572 0 : if ( i==1 )
7573 0 : BDFFontFree(fv->filled);
7574 0 : if ( fv->b.sf->fv==&fv->b ) {
7575 0 : if ( fv->b.cidmaster==NULL )
7576 0 : fv->b.sf->fv = fv->b.nextsame;
7577 : else {
7578 0 : fv->b.cidmaster->fv = fv->b.nextsame;
7579 0 : for ( i=0; i<fv->b.cidmaster->subfontcnt; ++i )
7580 0 : fv->b.cidmaster->subfonts[i]->fv = fv->b.nextsame;
7581 : }
7582 : } else {
7583 0 : for ( prev = (FontView *) (fv->b.sf->fv); prev->b.nextsame!=&fv->b; prev=(FontView *) (prev->b.nextsame) );
7584 0 : prev->b.nextsame = fv->b.nextsame;
7585 : }
7586 : }
7587 : #ifndef _NO_FFSCRIPT
7588 31 : DictionaryFree(fv->b.fontvars);
7589 31 : free(fv->b.fontvars);
7590 : #endif
7591 31 : free(fv->b.selected);
7592 31 : free(fv->fontset);
7593 : #ifndef _NO_PYTHON
7594 31 : PyFF_FreeFV(&fv->b);
7595 : #endif
7596 31 : free(fv);
7597 31 : }
7598 :
7599 4 : static int FontViewWinInfo(FontView *fv, int *cc, int *rc) {
7600 4 : if ( fv==NULL || fv->colcnt==0 || fv->rowcnt==0 ) {
7601 4 : *cc = 16; *rc = 4;
7602 4 : return( -1 );
7603 : }
7604 :
7605 0 : *cc = fv->colcnt;
7606 0 : *rc = fv->rowcnt;
7607 :
7608 0 : return( fv->rowoff*fv->colcnt );
7609 : }
7610 :
7611 :
7612 :
7613 :
7614 :
7615 :
7616 :
7617 :
7618 :
7619 145 : static FontViewBase *FVAny(void) { return (FontViewBase *) fv_list; }
7620 :
7621 0 : static int FontIsActive(SplineFont *sf) {
7622 : FontView *fv;
7623 :
7624 0 : for ( fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) )
7625 0 : if ( fv->b.sf == sf )
7626 0 : return( true );
7627 :
7628 0 : return( false );
7629 : }
7630 :
7631 202138 : static SplineFont *FontOfFilename(const char *filename) {
7632 : char buffer[1025];
7633 : FontView *fv;
7634 :
7635 202138 : GFileGetAbsoluteName((char *) filename,buffer,sizeof(buffer));
7636 206532 : for ( fv=fv_list; fv!=NULL ; fv=(FontView *) (fv->b.next) ) {
7637 206469 : if ( fv->b.sf->filename!=NULL && strcmp(fv->b.sf->filename,buffer)==0 )
7638 197698 : return( fv->b.sf );
7639 8771 : else if ( fv->b.sf->origname!=NULL && strcmp(fv->b.sf->origname,buffer)==0 )
7640 4377 : return( fv->b.sf );
7641 : }
7642 63 : return( NULL );
7643 : }
7644 :
7645 0 : static void FVExtraEncSlots(FontView *fv, int encmax) {
7646 0 : if ( fv->colcnt!=0 ) { /* Ie. scripting vs. UI */
7647 0 : fv->rowltot = (encmax+1+fv->colcnt-1)/fv->colcnt;
7648 0 : GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7649 : }
7650 0 : }
7651 :
7652 8 : static void FV_BiggerGlyphCache(FontView *fv, int gidcnt) {
7653 8 : if ( fv->filled!=NULL )
7654 0 : BDFOrigFixup(fv->filled,gidcnt,fv->b.sf);
7655 8 : }
7656 :
7657 31 : static void FontView_Close(FontView *fv) {
7658 31 : if ( fv->gw!=NULL )
7659 0 : GDrawDestroyWindow(fv->gw);
7660 : else
7661 31 : FontViewRemove(fv);
7662 31 : }
7663 :
7664 :
7665 : struct fv_interface gdraw_fv_interface = {
7666 : (FontViewBase *(*)(SplineFont *, int)) FontView_Create,
7667 : (FontViewBase *(*)(SplineFont *)) __FontViewCreate,
7668 : (void (*)(FontViewBase *)) FontView_Close,
7669 : (void (*)(FontViewBase *)) FontView_Free,
7670 : (void (*)(FontViewBase *)) FontViewSetTitle,
7671 : FontViewSetTitles,
7672 : FontViewRefreshAll,
7673 : (void (*)(FontViewBase *)) FontView_ReformatOne,
7674 : FontView_ReformatAll,
7675 : (void (*)(FontViewBase *)) FV_LayerChanged,
7676 : FV_ToggleCharChanged,
7677 : (int (*)(FontViewBase *, int *, int *)) FontViewWinInfo,
7678 : FontIsActive,
7679 : FVAny,
7680 : (FontViewBase *(*)(FontViewBase *)) FontView_Append,
7681 : FontOfFilename,
7682 : (void (*)(FontViewBase *,int)) FVExtraEncSlots,
7683 : (void (*)(FontViewBase *,int)) FV_BiggerGlyphCache,
7684 : (void (*)(FontViewBase *,BDFFont *)) FV_ChangeDisplayBitmap,
7685 : (void (*)(FontViewBase *)) FV_ShowFilled,
7686 : FV_ReattachCVs,
7687 : (void (*)(FontViewBase *)) FVDeselectAll,
7688 : (void (*)(FontViewBase *,int )) FVScrollToGID,
7689 : (void (*)(FontViewBase *,int )) FVScrollToChar,
7690 : (void (*)(FontViewBase *,int )) FV_ChangeGID,
7691 : SF_CloseAllInstrs
7692 : };
7693 :
7694 : extern GResInfo charview_ri;
7695 : static struct resed view_re[] = {
7696 : {N_("Color|Background"), "Background", rt_color, &view_bgcol, N_("Background color for the drawing area of all views"), NULL, { 0 }, 0, 0 },
7697 : RESED_EMPTY
7698 : };
7699 : GResInfo view_ri = {
7700 : NULL, NULL,NULL, NULL,
7701 : NULL,
7702 : NULL,
7703 : NULL,
7704 : view_re,
7705 : N_("View"),
7706 : N_("This is an abstract class which defines common features of the\nFontView, CharView, BitmapView and MetricsView"),
7707 : "View",
7708 : "fontforge",
7709 : false,
7710 : 0,
7711 : NULL,
7712 : GBOX_EMPTY,
7713 : NULL,
7714 : NULL,
7715 : NULL
7716 : };
7717 :
7718 : GResInfo fontview_ri = {
7719 : &charview_ri, NULL,NULL, NULL,
7720 : NULL,
7721 : NULL,
7722 : NULL,
7723 : fontview_re,
7724 : N_("FontView"),
7725 : N_("This is the main fontforge window displaying a font"),
7726 : "FontView",
7727 : "fontforge",
7728 : false,
7729 : 0,
7730 : NULL,
7731 : GBOX_EMPTY,
7732 : NULL,
7733 : NULL,
7734 : NULL
7735 : };
7736 :
7737 : /* ************************************************************************** */
7738 : /* ***************************** Embedded FontViews ************************* */
7739 : /* ************************************************************************** */
7740 :
7741 0 : static void FVCopyInnards(FontView *fv,GRect *pos,int infoh,
7742 : FontView *fvorig,GWindow dw, int def_layer, struct fvcontainer *kf) {
7743 :
7744 0 : fv->notactive = true;
7745 0 : fv->gw = dw;
7746 0 : fv->infoh = infoh;
7747 0 : fv->b.container = kf;
7748 0 : fv->rowcnt = 4; fv->colcnt = 16;
7749 0 : fv->b.active_layer = def_layer;
7750 0 : FVCreateInnards(fv,pos);
7751 0 : memcpy(fv->b.selected,fvorig->b.selected,fv->b.map->enccount);
7752 0 : fv->rowoff = (fvorig->rowoff*fvorig->colcnt)/fv->colcnt;
7753 0 : }
7754 :
7755 0 : void KFFontViewInits(struct kf_dlg *kf,GGadget *drawable) {
7756 : GGadgetData gd;
7757 : GRect pos, gsize, sbsize;
7758 0 : GWindow dw = GDrawableGetWindow(drawable);
7759 : int infoh;
7760 : int ps;
7761 0 : FontView *fvorig = (FontView *) kf->sf->fv;
7762 :
7763 0 : FontViewInit();
7764 :
7765 0 : kf->dw = dw;
7766 :
7767 0 : memset(&gd,0,sizeof(gd));
7768 0 : gd.flags = gg_visible | gg_enabled;
7769 0 : helplist[0].invoke = FVMenuContextualHelp;
7770 0 : gd.u.menu2 = mblist;
7771 0 : kf->mb = GMenu2BarCreate( dw, &gd, NULL);
7772 0 : GGadgetGetSize(kf->mb,&gsize);
7773 0 : kf->mbh = gsize.height;
7774 0 : kf->guts = drawable;
7775 :
7776 0 : ps = kf->sf->display_size; kf->sf->display_size = -24;
7777 0 : kf->first_fv = __FontViewCreate(kf->sf); kf->first_fv->b.container = (struct fvcontainer *) kf;
7778 0 : kf->second_fv = __FontViewCreate(kf->sf); kf->second_fv->b.container = (struct fvcontainer *) kf;
7779 :
7780 0 : kf->infoh = infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
7781 0 : kf->first_fv->mbh = kf->mbh;
7782 0 : pos.x = 0; pos.y = kf->mbh+infoh+kf->fh+4;
7783 0 : pos.width = 16*kf->first_fv->cbw+1;
7784 0 : pos.height = 4*kf->first_fv->cbh+1;
7785 :
7786 0 : GDrawSetUserData(dw,kf->first_fv);
7787 0 : FVCopyInnards(kf->first_fv,&pos,infoh,fvorig,dw,kf->def_layer,(struct fvcontainer *) kf);
7788 0 : 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 */
7789 0 : kf->second_fv->mbh = kf->mbh;
7790 0 : kf->label2_y = pos.y + pos.height+2;
7791 0 : pos.y = kf->label2_y + kf->fh + 2;
7792 0 : GDrawSetUserData(dw,kf->second_fv);
7793 0 : FVCopyInnards(kf->second_fv,&pos,infoh,fvorig,dw,kf->def_layer,(struct fvcontainer *) kf);
7794 :
7795 0 : kf->sf->display_size = ps;
7796 :
7797 0 : GGadgetGetSize(kf->second_fv->vsb,&sbsize);
7798 0 : gsize.x = gsize.y = 0;
7799 0 : gsize.width = pos.width + sbsize.width;
7800 0 : gsize.height = pos.y+pos.height;
7801 0 : GGadgetSetDesiredSize(drawable,NULL,&gsize);
7802 0 : }
7803 : /* ************************************************************************** */
7804 : /* ************************** Glyph Set from Selection ********************** */
7805 : /* ************************************************************************** */
7806 :
7807 : struct gsd {
7808 : struct fvcontainer base;
7809 : FontView *fv;
7810 : int done;
7811 : int good;
7812 : GWindow gw;
7813 : };
7814 :
7815 0 : static void gs_activateMe(struct fvcontainer *UNUSED(fvc), FontViewBase *UNUSED(fvb)) {
7816 : /*struct gsd *gs = (struct gsd *) fvc;*/
7817 0 : }
7818 :
7819 0 : static void gs_charEvent(struct fvcontainer *fvc,void *event) {
7820 0 : struct gsd *gs = (struct gsd *) fvc;
7821 0 : FVChar(gs->fv,event);
7822 0 : }
7823 :
7824 0 : static void gs_doClose(struct fvcontainer *fvc) {
7825 0 : struct gsd *gs = (struct gsd *) fvc;
7826 0 : gs->done = true;
7827 0 : }
7828 :
7829 : #define CID_Guts 1000
7830 : #define CID_TopBox 1001
7831 :
7832 0 : static void gs_doResize(struct fvcontainer *fvc, FontViewBase *UNUSED(fvb),
7833 : int width, int height) {
7834 0 : struct gsd *gs = (struct gsd *) fvc;
7835 : /*FontView *fv = (FontView *) fvb;*/
7836 : GRect size;
7837 :
7838 0 : memset(&size,0,sizeof(size));
7839 0 : size.width = width; size.height = height;
7840 0 : GGadgetSetDesiredSize(GWidgetGetControl(gs->gw,CID_Guts),
7841 : NULL,&size);
7842 0 : GHVBoxFitWindow(GWidgetGetControl(gs->gw,CID_TopBox));
7843 0 : }
7844 :
7845 : static struct fvcontainer_funcs glyphset_funcs = {
7846 : fvc_glyphset,
7847 : true, /* Modal dialog. No charviews, etc. */
7848 : gs_activateMe,
7849 : gs_charEvent,
7850 : gs_doClose,
7851 : gs_doResize
7852 : };
7853 :
7854 0 : static int GS_OK(GGadget *g, GEvent *e) {
7855 :
7856 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
7857 0 : struct gsd *gs = GDrawGetUserData(GGadgetGetWindow(g));
7858 0 : gs->done = true;
7859 0 : gs->good = true;
7860 : }
7861 0 : return( true );
7862 : }
7863 :
7864 0 : static int GS_Cancel(GGadget *g, GEvent *e) {
7865 : struct gsd *gs;
7866 :
7867 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
7868 0 : gs = GDrawGetUserData(GGadgetGetWindow(g));
7869 0 : gs->done = true;
7870 : }
7871 0 : return( true );
7872 : }
7873 :
7874 0 : static void gs_sizeSet(struct gsd *gs,GWindow dw) {
7875 : GRect size, gsize;
7876 : int width, height, y;
7877 : int cc, rc, topchar;
7878 : GRect subsize;
7879 0 : FontView *fv = gs->fv;
7880 :
7881 0 : if ( gs->fv->vsb==NULL )
7882 0 : return;
7883 :
7884 0 : GDrawGetSize(dw,&size);
7885 0 : GGadgetGetSize(gs->fv->vsb,&gsize);
7886 0 : width = size.width - gsize.width;
7887 0 : height = size.height - gs->fv->mbh - gs->fv->infoh;
7888 :
7889 0 : y = gs->fv->mbh + gs->fv->infoh;
7890 :
7891 0 : topchar = fv->rowoff*fv->colcnt;
7892 0 : cc = (width-1) / fv->cbw;
7893 0 : if ( cc<1 ) cc=1;
7894 0 : rc = (height-1)/ fv->cbh;
7895 0 : if ( rc<1 ) rc = 1;
7896 0 : subsize.x = 0; subsize.y = 0;
7897 0 : subsize.width = cc*fv->cbw + 1;
7898 0 : subsize.height = rc*fv->cbh + 1;
7899 0 : GDrawResize(fv->v,subsize.width,subsize.height);
7900 0 : GDrawMove(fv->v,0,y);
7901 0 : GGadgetMove(fv->vsb,subsize.width,y);
7902 0 : GGadgetResize(fv->vsb,gsize.width,subsize.height);
7903 :
7904 0 : fv->colcnt = cc; fv->rowcnt = rc;
7905 0 : fv->width = subsize.width; fv->height = subsize.height;
7906 0 : fv->rowltot = (fv->b.map->enccount+fv->colcnt-1)/fv->colcnt;
7907 0 : GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
7908 0 : fv->rowoff = topchar/fv->colcnt;
7909 0 : if ( fv->rowoff>=fv->rowltot-fv->rowcnt )
7910 0 : fv->rowoff = fv->rowltot-fv->rowcnt;
7911 0 : if ( fv->rowoff<0 ) fv->rowoff =0;
7912 0 : GScrollBarSetPos(fv->vsb,fv->rowoff);
7913 :
7914 0 : GDrawRequestExpose(fv->v,NULL,true);
7915 : }
7916 :
7917 0 : static int gs_sub_e_h(GWindow pixmap, GEvent *event) {
7918 : FontView *active_fv;
7919 : struct gsd *gs;
7920 :
7921 0 : if ( event->type==et_destroy )
7922 0 : return( true );
7923 :
7924 0 : active_fv = (FontView *) GDrawGetUserData(pixmap);
7925 0 : gs = (struct gsd *) (active_fv->b.container);
7926 :
7927 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
7928 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
7929 0 : return( GGadgetDispatchEvent(active_fv->vsb,event));
7930 : }
7931 :
7932 :
7933 0 : switch ( event->type ) {
7934 : case et_expose:
7935 0 : FVDrawInfo(active_fv,pixmap,event);
7936 0 : break;
7937 : case et_char:
7938 0 : gs_charEvent(&gs->base,event);
7939 0 : break;
7940 : case et_mousedown:
7941 0 : return(false);
7942 : break;
7943 : case et_mouseup: case et_mousemove:
7944 0 : return(false);
7945 : case et_resize:
7946 0 : gs_sizeSet(gs,pixmap);
7947 0 : break;
7948 : }
7949 0 : return( true );
7950 : }
7951 :
7952 0 : static int gs_e_h(GWindow gw, GEvent *event) {
7953 0 : struct gsd *gs = GDrawGetUserData(gw);
7954 :
7955 0 : switch ( event->type ) {
7956 : case et_close:
7957 0 : gs->done = true;
7958 0 : break;
7959 : case et_char:
7960 0 : FVChar(gs->fv,event);
7961 0 : break;
7962 : }
7963 0 : return( true );
7964 : }
7965 :
7966 0 : char *GlyphSetFromSelection(SplineFont *sf,int def_layer,char *current) {
7967 : struct gsd gs;
7968 : GRect pos;
7969 : GWindowAttrs wattrs;
7970 : GGadgetCreateData gcd[5], boxes[3];
7971 : GGadgetCreateData *varray[21], *buttonarray[8];
7972 : GTextInfo label[5];
7973 : int i,j,k,guts_row,gid,enc,len;
7974 : char *ret, *rpt;
7975 : SplineChar *sc;
7976 : GGadget *drawable;
7977 : GWindow dw;
7978 : GGadgetData gd;
7979 : GRect gsize, sbsize;
7980 : int infoh, mbh;
7981 : int ps;
7982 0 : FontView *fvorig = (FontView *) sf->fv;
7983 : GGadget *mb;
7984 : char *start, *pt; int ch;
7985 :
7986 0 : FontViewInit();
7987 :
7988 0 : memset(&wattrs,0,sizeof(wattrs));
7989 0 : memset(&gcd,0,sizeof(gcd));
7990 0 : memset(&boxes,0,sizeof(boxes));
7991 0 : memset(&label,0,sizeof(label));
7992 0 : memset(&gs,0,sizeof(gs));
7993 :
7994 0 : gs.base.funcs = &glyphset_funcs;
7995 :
7996 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
7997 0 : wattrs.event_masks = ~(1<<et_charup);
7998 0 : wattrs.restrict_input_to_me = true;
7999 0 : wattrs.undercursor = 1;
8000 0 : wattrs.cursor = ct_pointer;
8001 0 : wattrs.utf8_window_title = _("Glyph Set by Selection") ;
8002 0 : wattrs.is_dlg = true;
8003 0 : pos.x = pos.y = 0;
8004 0 : pos.width = 100;
8005 0 : pos.height = 100;
8006 0 : gs.gw = GDrawCreateTopWindow(NULL,&pos,gs_e_h,&gs,&wattrs);
8007 :
8008 0 : i = j = 0;
8009 :
8010 0 : guts_row = j/2;
8011 0 : gcd[i].gd.flags = gg_enabled|gg_visible;
8012 0 : gcd[i].gd.cid = CID_Guts;
8013 0 : gcd[i].gd.u.drawable_e_h = gs_sub_e_h;
8014 0 : gcd[i].creator = GDrawableCreate;
8015 0 : varray[j++] = &gcd[i++]; varray[j++] = NULL;
8016 :
8017 0 : label[i].text = (unichar_t *) _("Select glyphs in the font view above.\nThe selected glyphs become your glyph class.");
8018 0 : label[i].text_is_1byte = true;
8019 0 : gcd[i].gd.label = &label[i];
8020 0 : gcd[i].gd.flags = gg_enabled|gg_visible;
8021 0 : gcd[i].creator = GLabelCreate;
8022 0 : varray[j++] = &gcd[i++]; varray[j++] = NULL;
8023 :
8024 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
8025 0 : label[i].text = (unichar_t *) _("_OK");
8026 0 : label[i].text_is_1byte = true;
8027 0 : label[i].text_in_resource = true;
8028 0 : gcd[i].gd.label = &label[i];
8029 0 : gcd[i].gd.handle_controlevent = GS_OK;
8030 0 : gcd[i++].creator = GButtonCreate;
8031 :
8032 0 : gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
8033 0 : label[i].text = (unichar_t *) _("_Cancel");
8034 0 : label[i].text_is_1byte = true;
8035 0 : label[i].text_in_resource = true;
8036 0 : gcd[i].gd.label = &label[i];
8037 0 : gcd[i].gd.handle_controlevent = GS_Cancel;
8038 0 : gcd[i++].creator = GButtonCreate;
8039 :
8040 0 : buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[i-2]; buttonarray[2] = GCD_Glue;
8041 0 : buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[i-1]; buttonarray[5] = GCD_Glue;
8042 0 : buttonarray[6] = NULL;
8043 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
8044 0 : boxes[2].gd.u.boxelements = buttonarray;
8045 0 : boxes[2].creator = GHBoxCreate;
8046 0 : varray[j++] = &boxes[2]; varray[j++] = NULL; varray[j++] = NULL;
8047 :
8048 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
8049 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
8050 0 : boxes[0].gd.u.boxelements = varray;
8051 0 : boxes[0].gd.cid = CID_TopBox;
8052 0 : boxes[0].creator = GHVGroupCreate;
8053 :
8054 0 : GGadgetsCreate(gs.gw,boxes);
8055 :
8056 0 : GHVBoxSetExpandableRow(boxes[0].ret,guts_row);
8057 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
8058 :
8059 0 : drawable = GWidgetGetControl(gs.gw,CID_Guts);
8060 0 : dw = GDrawableGetWindow(drawable);
8061 :
8062 0 : memset(&gd,0,sizeof(gd));
8063 0 : gd.flags = gg_visible | gg_enabled;
8064 0 : helplist[0].invoke = FVMenuContextualHelp;
8065 0 : gd.u.menu2 = mblist;
8066 0 : mb = GMenu2BarCreate( dw, &gd, NULL);
8067 0 : GGadgetGetSize(mb,&gsize);
8068 0 : mbh = gsize.height;
8069 :
8070 0 : ps = sf->display_size; sf->display_size = -24;
8071 0 : gs.fv = __FontViewCreate(sf);
8072 :
8073 0 : infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
8074 0 : gs.fv->mbh = mbh;
8075 0 : pos.x = 0; pos.y = mbh+infoh;
8076 0 : pos.width = 16*gs.fv->cbw+1;
8077 0 : pos.height = 4*gs.fv->cbh+1;
8078 :
8079 0 : GDrawSetUserData(dw,gs.fv);
8080 0 : FVCopyInnards(gs.fv,&pos,infoh,fvorig,dw,def_layer,(struct fvcontainer *) &gs);
8081 0 : 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 */
8082 0 : memset(gs.fv->b.selected,0,gs.fv->b.map->enccount);
8083 0 : if ( current!=NULL && strcmp(current,_("{Everything Else}"))!=0 ) {
8084 0 : int first = true;
8085 0 : for ( start = current; *start==' '; ++start );
8086 0 : while ( *start ) {
8087 0 : for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
8088 0 : ch = *pt; *pt='\0';
8089 0 : sc = SFGetChar(sf,-1,start);
8090 0 : *pt = ch;
8091 0 : if ( sc!=NULL && (enc = gs.fv->b.map->backmap[sc->orig_pos])!=-1 ) {
8092 0 : gs.fv->b.selected[enc] = true;
8093 0 : if ( first ) {
8094 0 : first = false;
8095 0 : gs.fv->rowoff = enc/gs.fv->colcnt;
8096 : }
8097 : }
8098 0 : start = pt;
8099 0 : while ( *start==' ' ) ++start;
8100 : }
8101 : }
8102 0 : sf->display_size = ps;
8103 :
8104 0 : GGadgetGetSize(gs.fv->vsb,&sbsize);
8105 0 : gsize.x = gsize.y = 0;
8106 0 : gsize.width = pos.width + sbsize.width;
8107 0 : gsize.height = pos.y+pos.height;
8108 0 : GGadgetSetDesiredSize(drawable,NULL,&gsize);
8109 :
8110 0 : GHVBoxFitWindow(boxes[0].ret);
8111 0 : GDrawSetVisible(gs.gw,true);
8112 0 : while ( !gs.done )
8113 0 : GDrawProcessOneEvent(NULL);
8114 :
8115 0 : ret = rpt = NULL;
8116 0 : if ( gs.good ) {
8117 0 : for ( k=0; k<2; ++k ) {
8118 0 : len = 0;
8119 0 : for ( enc=0; enc<gs.fv->b.map->enccount; ++enc ) {
8120 0 : if ( gs.fv->b.selected[enc] &&
8121 0 : (gid=gs.fv->b.map->map[enc])!=-1 &&
8122 0 : (sc = sf->glyphs[gid])!=NULL ) {
8123 0 : char *repr = SCNameUniStr( sc );
8124 0 : if ( ret==NULL )
8125 0 : len += strlen(repr)+2;
8126 : else {
8127 0 : strcpy(rpt,repr);
8128 0 : rpt += strlen( repr );
8129 0 : free(repr);
8130 0 : *rpt++ = ' ';
8131 : }
8132 : }
8133 : }
8134 0 : if ( k==0 )
8135 0 : ret = rpt = malloc(len+1);
8136 0 : else if ( rpt!=ret && rpt[-1]==' ' )
8137 0 : rpt[-1]='\0';
8138 : else
8139 0 : *rpt='\0';
8140 : }
8141 : }
8142 0 : FontViewFree(&gs.fv->b);
8143 0 : GDrawSetUserData(gs.gw,NULL);
8144 0 : GDrawSetUserData(dw,NULL);
8145 0 : GDrawDestroyWindow(gs.gw);
8146 0 : return( ret );
8147 : }
8148 :
8149 :
8150 : /****************************************/
8151 : /****************************************/
8152 : /****************************************/
8153 :
8154 0 : int FontViewFind_byXUID( FontViewBase* fv, void* udata )
8155 : {
8156 0 : if( !fv || !fv->sf )
8157 0 : return 0;
8158 0 : return !strcmp( fv->sf->xuid, (char*)udata );
8159 : }
8160 :
8161 0 : int FontViewFind_byXUIDConnected( FontViewBase* fv, void* udata )
8162 : {
8163 0 : if( !fv || !fv->sf )
8164 0 : return 0;
8165 0 : return ( fv->collabState == cs_server || fv->collabState == cs_client )
8166 0 : && fv->sf->xuid
8167 0 : && !strcmp( fv->sf->xuid, (char*)udata );
8168 : }
8169 :
8170 0 : int FontViewFind_byCollabPtr( FontViewBase* fv, void* udata )
8171 : {
8172 0 : if( !fv || !fv->sf )
8173 0 : return 0;
8174 0 : return fv->collabClient == udata;
8175 : }
8176 :
8177 0 : int FontViewFind_byCollabBasePort( FontViewBase* fv, void* udata )
8178 : {
8179 0 : if( !fv || !fv->sf || !fv->collabClient )
8180 0 : return 0;
8181 0 : int port = (int)(intptr_t)udata;
8182 0 : return port == collabclient_getBasePort( fv->collabClient );
8183 : }
8184 :
8185 0 : int FontViewFind_bySplineFont( FontViewBase* fv, void* udata )
8186 : {
8187 0 : if( !fv || !fv->sf )
8188 0 : return 0;
8189 0 : return fv->sf == udata;
8190 : }
8191 :
8192 0 : static int FontViewFind_ActiveWindow( FontViewBase* fvb, void* udata )
8193 : {
8194 0 : FontView* fv = (FontView*)fvb;
8195 0 : return( fv->gw == udata || fv->v == udata );
8196 : }
8197 :
8198 0 : FontViewBase* FontViewFindActive()
8199 : {
8200 0 : return (FontViewBase*) ActiveFontView;
8201 : /* GWindow w = GWindowGetCurrentFocusTopWindow(); */
8202 : /* FontViewBase* ret = FontViewFind( FontViewFind_ActiveWindow, w ); */
8203 : /* return ret; */
8204 : }
8205 :
8206 :
8207 :
8208 0 : FontViewBase* FontViewFind( int (*testFunc)( FontViewBase*, void* udata ), void* udata )
8209 : {
8210 : FontViewBase *fv;
8211 0 : printf("FontViewFind(top) fv_list:%p\n", fv_list );
8212 0 : for ( fv = (FontViewBase*)fv_list; fv!=NULL; fv=fv->next )
8213 : {
8214 0 : if( testFunc( fv, udata ))
8215 0 : return fv;
8216 : }
8217 0 : return 0;
8218 : }
8219 :
8220 0 : FontView* FontViewFindUI( int (*testFunc)( FontViewBase*, void* udata ), void* udata )
8221 : {
8222 0 : return (FontView*)FontViewFind( testFunc, udata );
8223 : }
8224 :
8225 :
8226 : /****************************************/
8227 : /****************************************/
8228 : /****************************************/
8229 :
8230 : /* local variables: */
8231 : /* tab-width: 8 */
8232 : /* end: */
|