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 "fontforgeui.h"
30 : #include "basics.h"
31 : #include <gfile.h>
32 : #include "splinefont.h"
33 : #include "scripting.h"
34 : #include "ustring.h"
35 :
36 0 : static void WindowSelect(GWindow base,struct gmenuitem *mi,GEvent *e) {
37 0 : GDrawRaise(mi->ti.userdata);
38 0 : }
39 :
40 0 : static void AddMI(GMenuItem *mi,GWindow gw,int changed, int top) {
41 0 : mi->ti.userdata = gw;
42 0 : mi->ti.bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(gw));
43 0 : mi->invoke = WindowSelect;
44 0 : mi->ti.text = GDrawGetWindowTitle(gw);
45 0 : if(mi->ti.text == NULL)
46 0 : mi->ti.text = utf82u_copy("(null)");
47 0 : if ( u_strlen( mi->ti.text ) > 35 )
48 0 : mi->ti.text[35] = '\0';
49 0 : }
50 :
51 : /* Builds up a menu containing the titles of all the major windows */
52 0 : void WindowMenuBuild(GWindow basew,struct gmenuitem *mi,GEvent *e) {
53 : int i, cnt, precnt;
54 : FontViewBase *fv;
55 : CharViewBase *cv;
56 : MetricsView *mv;
57 : BitmapView *bv;
58 : GMenuItem *sub;
59 : BDFFont *bdf;
60 :
61 0 : precnt = 6;
62 0 : cnt = precnt;
63 :
64 0 : for ( fv = (FontViewBase *) fv_list; fv!=NULL; fv = fv->next ) {
65 0 : ++cnt; /* for the font */
66 0 : for ( i=0; i<fv->sf->glyphcnt; ++i ) if ( fv->sf->glyphs[i]!=NULL ) {
67 0 : for ( cv = fv->sf->glyphs[i]->views; cv!=NULL; cv=cv->next )
68 0 : ++cnt; /* for each char view in the font */
69 : }
70 0 : for ( bdf= fv->sf->bitmaps; bdf!=NULL; bdf = bdf->next ) {
71 0 : for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
72 0 : for ( bv = bdf->glyphs[i]->views; bv!=NULL; bv=bv->next )
73 0 : ++cnt;
74 : }
75 : }
76 0 : for ( mv=fv->sf->metrics; mv!=NULL; mv=mv->next )
77 0 : ++cnt;
78 : }
79 0 : if ( cnt==0 ) {
80 : /* This can't happen */
81 0 : return;
82 : }
83 0 : sub = calloc(cnt+1,sizeof(GMenuItem));
84 0 : memcpy(sub,mi->sub,precnt*sizeof(struct gmenuitem));
85 0 : for ( i=0; i<precnt; ++i )
86 0 : mi->sub[i].ti.text = NULL;
87 0 : GMenuItemArrayFree(mi->sub);
88 0 : mi->sub = sub;
89 :
90 0 : for ( i=0; sub[i].ti.text!=NULL || sub[i].ti.line; ++i ) {
91 0 : if ( sub[i].ti.text_is_1byte && sub[i].ti.text_in_resource) {
92 0 : sub[i].ti.text = utf82u_mncopy((char *) sub[i].ti.text,&sub[i].ti.mnemonic);
93 0 : sub[i].ti.text_is_1byte = sub[i].ti.text_in_resource = false;
94 0 : } else if ( sub[i].ti.text_is_1byte ) {
95 0 : sub[i].ti.text = utf82u_copy((char *) sub[i].ti.text);
96 0 : sub[i].ti.text_is_1byte = false;
97 0 : } else if ( sub[i].ti.text_in_resource ) {
98 0 : sub[i].ti.text = u_copy(GStringGetResource((intpt) sub[i].ti.text,NULL));
99 0 : sub[i].ti.text_in_resource = false;
100 : } else
101 0 : sub[i].ti.text = u_copy(sub[i].ti.text);
102 : }
103 0 : cnt = precnt;
104 0 : for ( fv = (FontViewBase *) fv_list; fv!=NULL; fv = fv->next ) {
105 0 : if( !((FontView *) fv)->gw ) {
106 0 : continue;
107 : }
108 :
109 0 : AddMI(&sub[cnt++],((FontView *) fv)->gw,fv->sf->changed,true);
110 0 : for ( i=0; i<fv->sf->glyphcnt; ++i ) if ( fv->sf->glyphs[i]!=NULL ) {
111 0 : for ( cv = fv->sf->glyphs[i]->views; cv!=NULL; cv=cv->next )
112 0 : AddMI(&sub[cnt++],((CharView *) cv)->gw,cv->sc->changed,false);
113 : }
114 0 : for ( bdf= fv->sf->bitmaps; bdf!=NULL; bdf = bdf->next ) {
115 0 : for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
116 0 : for ( bv = bdf->glyphs[i]->views; bv!=NULL; bv=bv->next )
117 0 : AddMI(&sub[cnt++],bv->gw,bv->bc->changed,false);
118 : }
119 : }
120 0 : for ( mv=fv->sf->metrics; mv!=NULL; mv=mv->next )
121 0 : AddMI(&sub[cnt++],mv->gw,false,false);
122 : }
123 : }
124 :
125 0 : static void RecentSelect(GWindow base,struct gmenuitem *mi,GEvent *e) {
126 0 : ViewPostScriptFont((char *) (mi->ti.userdata),0);
127 0 : }
128 :
129 : /* Builds up a menu containing the titles of all the unused recent files */
130 0 : void MenuRecentBuild(GWindow base,struct gmenuitem *mi,GEvent *e) {
131 : int i, cnt, cnt1;
132 : FontViewBase *fv;
133 : GMenuItem *sub;
134 :
135 0 : if ( mi->sub!=NULL ) {
136 0 : GMenuItemArrayFree(mi->sub);
137 0 : mi->sub = NULL;
138 : }
139 :
140 0 : cnt = 0;
141 0 : for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i ) {
142 0 : for ( fv=(FontViewBase *) fv_list; fv!=NULL; fv=fv->next )
143 0 : if ( fv->sf->filename!=NULL && strcmp(fv->sf->filename,RecentFiles[i])==0 )
144 0 : break;
145 0 : if ( fv==NULL )
146 0 : ++cnt;
147 : }
148 0 : if ( cnt==0 ) {
149 : /* This can't happen */
150 0 : return;
151 : }
152 0 : sub = calloc(cnt+1,sizeof(GMenuItem));
153 0 : cnt1 = 0;
154 0 : for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i ) {
155 0 : for ( fv=(FontViewBase *) fv_list; fv!=NULL; fv=fv->next )
156 0 : if ( fv->sf->filename!=NULL && strcmp(fv->sf->filename,RecentFiles[i])==0 )
157 0 : break;
158 0 : if ( fv==NULL ) {
159 0 : GMenuItem *mi = &sub[cnt1++];
160 0 : mi->ti.userdata = RecentFiles[i];
161 0 : mi->ti.bg = mi->ti.fg = COLOR_DEFAULT;
162 0 : mi->invoke = RecentSelect;
163 0 : mi->ti.text = def2u_copy(GFileNameTail(RecentFiles[i]));
164 : }
165 : }
166 0 : if ( cnt!=cnt1 )
167 0 : IError( "Bad counts in MenuRecentBuild");
168 0 : mi->sub = sub;
169 : }
170 :
171 0 : int RecentFilesAny(void) {
172 : int i;
173 : FontViewBase *fvl;
174 :
175 0 : for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i ) {
176 0 : for ( fvl=(FontViewBase *) fv_list; fvl!=NULL; fvl=fvl->next )
177 0 : if ( fvl->sf->filename!=NULL && strcmp(fvl->sf->filename,RecentFiles[i])==0 )
178 0 : break;
179 0 : if ( fvl==NULL )
180 0 : return( true );
181 : }
182 0 : return( false );
183 : }
184 :
185 : #if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
186 0 : static void ScriptSelect(GWindow base,struct gmenuitem *mi,GEvent *e) {
187 0 : int index = (intpt) (mi->ti.userdata);
188 0 : FontView *fv = (FontView *) GDrawGetUserData(base);
189 :
190 : /* the menu is not always up to date. If user changed prefs and then used */
191 : /* Alt|Ctl|Digit s/he would not get a new menu built and the old one might*/
192 : /* refer to something out of bounds. Hence the check */
193 0 : if ( index<0 || script_filenames[index]==NULL )
194 0 : return;
195 0 : ExecuteScriptFile((FontViewBase *) fv,NULL,script_filenames[index]);
196 : }
197 :
198 : /* Builds up a menu containing any user defined scripts */
199 0 : void MenuScriptsBuild(GWindow base,struct gmenuitem *mi,GEvent *e) {
200 : int i;
201 : GMenuItem *sub;
202 :
203 0 : if ( mi->sub!=NULL ) {
204 0 : GMenuItemArrayFree(mi->sub);
205 0 : mi->sub = NULL;
206 : }
207 :
208 0 : for ( i=0; i<SCRIPT_MENU_MAX && script_menu_names[i]!=NULL; ++i );
209 0 : if ( i==0 ) {
210 : /* This can't happen */
211 0 : return;
212 : }
213 0 : sub = calloc(i+1,sizeof(GMenuItem));
214 0 : for ( i=0; i<SCRIPT_MENU_MAX && script_menu_names[i]!=NULL; ++i ) {
215 0 : GMenuItem *mi = &sub[i];
216 0 : mi->ti.userdata = (void *) (intpt) i;
217 0 : mi->ti.bg = mi->ti.fg = COLOR_DEFAULT;
218 0 : mi->invoke = ScriptSelect;
219 0 : mi->shortcut = i==9?'0':'1'+i;
220 0 : mi->short_mask = ksm_control|ksm_meta;
221 0 : mi->ti.text = u_copy(script_menu_names[i]);
222 : }
223 0 : mi->sub = sub;
224 : }
225 : #endif
226 :
227 : /* Builds up a menu containing all the anchor classes */
228 0 : void _aplistbuild(struct gmenuitem *top,SplineFont *sf,
229 : void (*func)(GWindow,struct gmenuitem *,GEvent *)) {
230 : int cnt;
231 : GMenuItem *mi, *sub;
232 : AnchorClass *ac;
233 :
234 0 : if ( top->sub!=NULL ) {
235 0 : GMenuItemArrayFree(top->sub);
236 0 : top->sub = NULL;
237 : }
238 :
239 0 : cnt = 0;
240 0 : for ( ac = sf->anchor; ac!=NULL; ac=ac->next ) ++cnt;
241 0 : if ( cnt==0 )
242 0 : cnt = 1;
243 : else
244 0 : cnt += 2;
245 0 : sub = calloc(cnt+1,sizeof(GMenuItem));
246 0 : mi = &sub[0];
247 0 : mi->ti.userdata = (void *) (-1);
248 0 : mi->ti.bg = mi->ti.fg = COLOR_DEFAULT;
249 0 : mi->invoke = func;
250 0 : mi->ti.text = utf82u_copy(_("All"));
251 0 : if ( cnt==1 )
252 0 : mi->ti.disabled = true;
253 : else {
254 0 : ++mi;
255 0 : mi->ti.bg = mi->ti.fg = COLOR_DEFAULT;
256 0 : mi->ti.line = true;
257 0 : ++mi;
258 : }
259 0 : for ( ac=sf->anchor; ac!=NULL; ac = ac->next, ++mi ) {
260 0 : mi->ti.userdata = (void *) ac;
261 0 : mi->ti.bg = mi->ti.fg = COLOR_DEFAULT;
262 0 : mi->invoke = func;
263 0 : mi->ti.text = utf82u_copy(ac->name);
264 : }
265 0 : top->sub = sub;
266 0 : }
267 :
268 0 : void mbFreeGetText(GMenuItem *mb) {
269 : /* free gettext substitutions on this menu and all sub menus */
270 : int i;
271 :
272 0 : if ( mb==NULL )
273 0 : return;
274 0 : for ( i=0; mb[i].ti.text!=NULL || mb[i].ti.line || mb[i].ti.image!=NULL; ++i ) {
275 0 : if (mb[i].ti.text_untranslated != NULL) { free(mb[i].ti.text_untranslated); mb[i].ti.text_untranslated = NULL; }
276 0 : if ( mb[i].ti.text!=NULL ) {
277 0 : if ( mb[i].sub!=NULL )
278 0 : mbFreeGetText(mb[i].sub);
279 : }
280 : }
281 : }
282 :
283 0 : void mbDoGetText(GMenuItem *mb) {
284 : /* perform gettext substitutions on this menu and all sub menus */
285 : int i;
286 :
287 0 : if ( mb==NULL )
288 0 : return;
289 0 : for ( i=0; mb[i].ti.text!=NULL || mb[i].ti.line || mb[i].ti.image!=NULL; ++i ) {
290 0 : if( mb[i].shortcut ) {
291 : unichar_t tmp[2];
292 0 : tmp[0] = mb[i].shortcut;
293 0 : tmp[1] = (unichar_t)(0);
294 0 : mb[i].ti.text_untranslated = cu_copy(tmp);
295 : } else
296 0 : mb[i].ti.text_untranslated = copy((char*)mb[i].ti.text);
297 0 : if ( mb[i].ti.text!=NULL ) {
298 0 : mb[i].ti.text = (unichar_t *) S_((char *) mb[i].ti.text);
299 0 : if ( mb[i].sub!=NULL )
300 0 : mbDoGetText(mb[i].sub);
301 : }
302 : }
303 : }
304 :
305 0 : void mb2FreeGetText(GMenuItem2 *mb) {
306 : /* free gettext substitutions on this menu and all sub menus */
307 : int i;
308 :
309 0 : if ( mb==NULL )
310 0 : return;
311 0 : for ( i=0; mb[i].ti.text!=NULL || mb[i].ti.line || mb[i].ti.image!=NULL; ++i ) {
312 0 : if (mb[i].ti.text_untranslated != NULL) { free(mb[i].ti.text_untranslated); mb[i].ti.text_untranslated = NULL; }
313 0 : if ( mb[i].ti.text!=NULL ) {
314 0 : if ( mb[i].sub!=NULL )
315 0 : mb2FreeGetText(mb[i].sub);
316 : }
317 : }
318 : }
319 :
320 0 : void mb2DoGetText(GMenuItem2 *mb) {
321 : /* perform gettext substitutions on this menu and all sub menus */
322 : int i;
323 :
324 0 : if ( mb==NULL )
325 0 : return;
326 0 : for ( i=0; mb[i].ti.text!=NULL || mb[i].ti.line || mb[i].ti.image!=NULL; ++i ) {
327 0 : if( mb[i].shortcut )
328 0 : mb[i].ti.text_untranslated = copy(mb[i].shortcut);
329 : else
330 0 : mb[i].ti.text_untranslated = copy((char*)mb[i].ti.text);
331 0 : if ( mb[i].ti.text!=NULL ) {
332 0 : mb[i].ti.text = (unichar_t *) S_((char *) mb[i].ti.text);
333 0 : if ( mb[i].sub!=NULL )
334 0 : mb2DoGetText(mb[i].sub);
335 : }
336 : }
337 : }
|