Line data Source code
1 : /* Copyright (C) 2007-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : #include "fontforgeui.h"
29 : #include "fvfonts.h"
30 : #include "mathconstants.h"
31 : #include "splineutil.h"
32 : #include <math.h>
33 : #include <stddef.h>
34 : #include <gkeysym.h>
35 : #include <ustring.h>
36 : #include <utype.h>
37 :
38 : extern struct math_constants_descriptor math_constants_descriptor[];
39 :
40 : static char *aspectnames[] = {
41 : N_("Constants"),
42 : N_("Sub/Superscript"),
43 : N_("Limits"),
44 : N_("Stacks"),
45 : N_("Fractions"),
46 : N_("Over/Underbars"),
47 : N_("Radicals"),
48 : N_("Connectors"),
49 : NULL
50 : };
51 :
52 : static char *GlyphConstruction_Dlg(GGadget *g, int r, int c);
53 : static char *MKChange_Dlg(GGadget *g, int r, int c);
54 : static void extpart_finishedit(GGadget *g, int r, int c, int wasnew);
55 : static void italic_finishedit(GGadget *g, int r, int c, int wasnew);
56 : static void topaccent_finishedit(GGadget *g, int r, int c, int wasnew);
57 : static void mathkern_initrow(GGadget *g, int r);
58 :
59 : static GTextInfo truefalse[] = {
60 : { (unichar_t *) N_("false"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
61 : { (unichar_t *) N_("true"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
62 : GTEXTINFO_EMPTY
63 : };
64 :
65 : static struct col_init exten_shape_ci[] = {
66 : { me_string, NULL, NULL, NULL, N_("Glyph") },
67 : { me_enum, NULL, truefalse, NULL, N_("Is Extended Shape") },
68 : COL_INIT_EMPTY
69 : };
70 :
71 : static struct col_init italic_cor_ci[] = {
72 : { me_string, NULL, NULL, NULL, N_("Glyph") },
73 : { me_int, NULL, NULL, NULL, N_("Italic Correction") },
74 : { me_funcedit, DevTab_Dlg, NULL, NULL, N_("Adjust") },
75 : COL_INIT_EMPTY
76 : };
77 :
78 : static struct col_init top_accent_ci[] = {
79 : { me_string, NULL, NULL, NULL, N_("Glyph") },
80 : { me_int, NULL, NULL, NULL, N_("Top Accent Horiz. Pos") },
81 : { me_funcedit, DevTab_Dlg, NULL, NULL, N_("Adjust") },
82 : COL_INIT_EMPTY
83 : };
84 :
85 : static struct col_init glyph_variants_ci[] = {
86 : { me_string, NULL, NULL, NULL, N_("Glyph") },
87 : { me_string, NULL, NULL, NULL, N_("Pre-Built Larger Variants") },
88 : COL_INIT_EMPTY
89 : };
90 :
91 : static struct col_init glyph_construction_ci[] = {
92 : { me_string, NULL, NULL, NULL, N_("Glyph") },
93 : /* GT: Italic correction */
94 : { me_int, NULL, NULL, NULL, N_("I.C.") },
95 : { me_funcedit, DevTab_Dlg, NULL, NULL, N_("Adjust") },
96 : { me_funcedit, GlyphConstruction_Dlg, NULL, NULL, N_("Parts List") },
97 : COL_INIT_EMPTY
98 : };
99 :
100 : static struct col_init math_kern_ci[] = {
101 : { me_string, NULL, NULL, NULL, N_("Glyph") },
102 : { me_button, MKChange_Dlg, NULL, NULL, N_("Height/Kern Data") },
103 : COL_INIT_EMPTY
104 : };
105 :
106 : struct matrixinit mis[] = {
107 : { sizeof(exten_shape_ci)/sizeof(struct col_init)-1, exten_shape_ci, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
108 : { sizeof(italic_cor_ci)/sizeof(struct col_init)-1, italic_cor_ci, 0, NULL, NULL, NULL, italic_finishedit, NULL, NULL, NULL },
109 : { sizeof(top_accent_ci)/sizeof(struct col_init)-1, top_accent_ci, 0, NULL, NULL, NULL, topaccent_finishedit, NULL, NULL, NULL },
110 : { sizeof(math_kern_ci)/sizeof(struct col_init)-1, math_kern_ci, 0, NULL, mathkern_initrow, NULL, NULL, NULL, NULL, NULL },
111 : { sizeof(glyph_variants_ci)/sizeof(struct col_init)-1, glyph_variants_ci, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
112 : { sizeof(glyph_construction_ci)/sizeof(struct col_init)-1, glyph_construction_ci, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
113 : { sizeof(glyph_variants_ci)/sizeof(struct col_init)-1, glyph_variants_ci, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
114 : { sizeof(glyph_construction_ci)/sizeof(struct col_init)-1, glyph_construction_ci, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
115 : MATRIXINIT_EMPTY
116 : };
117 :
118 : static struct col_init extensionpart[] = {
119 : { me_string , NULL, NULL, NULL, N_("Glyph") },
120 : { me_enum, NULL, truefalse, NULL, N_("Extender") },
121 : /* GT: "Len" is an abreviation for "Length" */
122 : { me_int, NULL, NULL, NULL, N_("StartLen") },
123 : { me_int, NULL, NULL, NULL, N_("EndLen") },
124 : { me_int, NULL, NULL, NULL, N_("FullLen") },
125 : COL_INIT_EMPTY
126 : };
127 : static struct matrixinit mi_extensionpart =
128 : { sizeof(extensionpart)/sizeof(struct col_init)-1, extensionpart, 0, NULL, NULL, NULL, extpart_finishedit, NULL, NULL, NULL };
129 :
130 : static struct col_init mathkern[] = {
131 : { me_int , NULL, NULL, NULL, N_("Height") },
132 : { me_int, NULL, NULL, NULL, N_("Kern") },
133 : { me_funcedit, DevTab_Dlg, NULL, NULL, N_("Height Adjusts") },
134 : { me_funcedit, DevTab_Dlg, NULL, NULL, N_("Kern Adjusts") },
135 : COL_INIT_EMPTY
136 : };
137 : static struct matrixinit mi_mathkern =
138 : { sizeof(mathkern)/sizeof(struct col_init)-1, mathkern, 0, NULL, NULL, NULL, extpart_finishedit, NULL, NULL, NULL };
139 :
140 :
141 : #define CID_Exten 1000
142 : #define CID_Italic 1001
143 : #define CID_TopAccent 1002
144 : #define CID_MathKern 1003
145 : #define CID_VGlyphVar 1004
146 : #define CID_VGlyphConst 1005
147 : #define CID_HGlyphVar 1006
148 : #define CID_HGlyphConst 1007
149 :
150 : static char *gi_aspectnames[] = {
151 : N_("Exten Shapes"),
152 : N_("Italic Correction"),
153 : N_("Top Accent"),
154 : N_("Math Kern"),
155 : N_("Vert. Variants"),
156 : N_("Vert. Construction"),
157 : N_("Hor. Variants"),
158 : N_("Hor. Construction"),
159 : NULL
160 : };
161 :
162 : static char *cornernames[] = {
163 : N_("Top Right"),
164 : N_("Top Left"),
165 : N_("Bottom Right"),
166 : N_("Bottom Left"),
167 : NULL
168 : };
169 :
170 0 : void MathInit(void) {
171 : int i, j;
172 : static int inited = false;
173 : static struct col_init *ci[] = { exten_shape_ci, italic_cor_ci,
174 : top_accent_ci, glyph_variants_ci, glyph_construction_ci,
175 : extensionpart, math_kern_ci, mathkern, NULL };
176 : static GTextInfo *tis[] = { truefalse, NULL };
177 : static char **chars[] = { aspectnames, gi_aspectnames, cornernames, NULL };
178 :
179 0 : if ( inited )
180 0 : return;
181 :
182 0 : for ( j=0; chars[j]!=NULL; ++j )
183 0 : for ( i=0; chars[j][i]!=NULL; ++i )
184 0 : chars[j][i] = _(chars[j][i]);
185 0 : for ( i=0; math_constants_descriptor[i].ui_name!=NULL; ++i ) {
186 0 : math_constants_descriptor[i].ui_name=_(math_constants_descriptor[i].ui_name);
187 0 : if ( math_constants_descriptor[i].message != NULL )
188 0 : math_constants_descriptor[i].message=_(math_constants_descriptor[i].message);
189 : }
190 :
191 0 : for ( j=0; tis[j]!=NULL; ++j )
192 0 : for ( i=0; tis[j][i].text!=NULL; ++i )
193 0 : tis[j][i].text = (unichar_t *) _((char *) tis[j][i].text);
194 0 : for ( j=0; ci[j]!=NULL; ++j )
195 0 : for ( i=0; ci[j][i].title!=NULL; ++i )
196 0 : ci[j][i].title = _(ci[j][i].title);
197 :
198 0 : inited = true;
199 : }
200 :
201 0 : static int GV_StringCheck(SplineFont *sf,char *str) {
202 : char *start, *pt;
203 : int scnt, pcnt, ch;
204 : SplineChar *sc;
205 :
206 0 : pcnt = 0;
207 0 : for ( start = str ; ; ) {
208 0 : while ( *start==' ' ) ++start;
209 0 : if ( *start=='\0' )
210 0 : return( pcnt );
211 0 : for ( pt=start; *pt!=':' && *pt!=' ' && *pt!='\0' ; ++pt );
212 0 : ch = *pt;
213 0 : if ( ch==' ' || ch=='\0' )
214 0 : return( -1 );
215 0 : if ( sf!=NULL ) {
216 0 : *pt = '\0';
217 0 : sc = SFGetChar(sf,-1,start);
218 0 : *pt = ch;
219 0 : if ( sc==NULL )
220 0 : return( -1 );
221 : }
222 0 : scnt = 0;
223 0 : while ( *pt!=' ' && *pt!='\0' ) {
224 0 : if ( *pt==':' ) ++scnt;
225 0 : else if ( !isdigit( *pt ))
226 0 : return( -1 );
227 0 : ++pt;
228 : }
229 0 : if ( scnt!=4 )
230 0 : return( -1 );
231 0 : ++pcnt;
232 0 : start = pt;
233 0 : }
234 : }
235 :
236 0 : static struct glyphvariants *GV_FromString(struct glyphvariants *gv,char *str) {
237 0 : int pcnt = GV_StringCheck(NULL,str);
238 : char *start, *pt;
239 : int ch, temp;
240 :
241 0 : if ( pcnt<=0 )
242 0 : return( gv );
243 0 : if ( gv==NULL )
244 0 : gv = chunkalloc(sizeof(struct glyphvariants));
245 0 : gv->part_cnt = pcnt;
246 0 : gv->parts = calloc(pcnt,sizeof(struct gv_part));
247 0 : pcnt = 0;
248 0 : for ( start = str ; ; ) {
249 0 : while ( *start==' ' ) ++start;
250 0 : if ( *start=='\0' )
251 0 : return( gv );
252 0 : for ( pt=start; *pt!=':' ; ++pt );
253 0 : ch = *pt; *pt = '\0';
254 0 : gv->parts[pcnt].component = copy(start);
255 0 : *pt = ch;
256 0 : sscanf(pt,":%d:%hd:%hd:%hd", &temp,
257 0 : &gv->parts[pcnt].startConnectorLength,
258 0 : &gv->parts[pcnt].endConnectorLength,
259 0 : &gv->parts[pcnt].fullAdvance);
260 0 : gv->parts[pcnt].is_extender = temp;
261 0 : while ( *pt!=' ' && *pt!='\0' ) ++pt;
262 0 : ++pcnt;
263 0 : start = pt;
264 0 : }
265 : }
266 :
267 0 : static char *GV_ToString(struct glyphvariants *gv) {
268 : int i, len;
269 : char buffer[80], *str;
270 :
271 0 : if ( gv==NULL || gv->part_cnt==0 )
272 0 : return( NULL );
273 0 : for ( i=len=0; i<gv->part_cnt; ++i ) {
274 0 : len += strlen(gv->parts[i].component);
275 0 : sprintf( buffer, ":%d:%d:%d:%d ", gv->parts[i].is_extender,
276 0 : gv->parts[i].startConnectorLength,
277 0 : gv->parts[i].endConnectorLength,
278 0 : gv->parts[i].fullAdvance);
279 0 : len += strlen( buffer );
280 : }
281 0 : str = malloc(len+1);
282 0 : for ( i=len=0; i<gv->part_cnt; ++i ) {
283 0 : strcpy(str+len,gv->parts[i].component);
284 0 : len += strlen(gv->parts[i].component);
285 0 : sprintf( buffer, ":%d:%d:%d:%d ", gv->parts[i].is_extender,
286 0 : gv->parts[i].startConnectorLength,
287 0 : gv->parts[i].endConnectorLength,
288 0 : gv->parts[i].fullAdvance);
289 0 : strcpy(str+len,buffer);
290 0 : len += strlen( buffer );
291 : }
292 0 : if ( len!=0 )
293 0 : str[len-1] = '\0';
294 : else
295 0 : *str = '\0';
296 0 : return( str );
297 : }
298 :
299 0 : static int SF_NameListCheck(SplineFont *sf,char *list) {
300 : char *start, *pt;
301 : int ch;
302 : SplineChar *sc;
303 :
304 0 : if ( list==NULL )
305 0 : return( true );
306 :
307 0 : for ( start = list ; ; ) {
308 0 : while ( *start== ' ' ) ++start;
309 0 : if ( *start=='\0' )
310 0 : return( true );
311 0 : for ( pt=start ; *pt!=' ' && *pt!='\0' && *pt!='('; ++pt );
312 0 : ch = *pt; *pt = '\0';
313 0 : sc = SFGetChar(sf,-1,start);
314 0 : *pt = ch;
315 0 : if ( ch=='(' ) {
316 0 : while ( *pt!=')' && *pt!='\0' ) ++pt;
317 0 : if ( *pt==')' ) ++pt;
318 : }
319 0 : start = pt;
320 0 : if ( sc==NULL )
321 0 : return( false );
322 0 : }
323 : }
324 :
325 : typedef struct mathdlg {
326 : GWindow gw;
327 : SplineFont *sf;
328 : int def_layer;
329 : struct MATH *math;
330 : uint8 done;
331 : uint8 ok;
332 : uint16 popup_r;
333 : GGadget *popup_g;
334 : /* Used by glyphconstruction_dlg */
335 : SplineChar *sc;
336 : int is_horiz;
337 : } MathDlg;
338 :
339 0 : static unichar_t **MATH_GlyphNameCompletion(GGadget *t,int from_tab) {
340 0 : MathDlg *math = GDrawGetUserData(GDrawGetParentWindow(GGadgetGetWindow(t)));
341 0 : SplineFont *sf = math->sf;
342 :
343 0 : return( SFGlyphNameCompletion(sf,t,from_tab,false));
344 : }
345 :
346 0 : static unichar_t **MATH_GlyphListCompletion(GGadget *t,int from_tab) {
347 0 : MathDlg *math = GDrawGetUserData(GDrawGetParentWindow(GGadgetGetWindow(t)));
348 0 : SplineFont *sf = math->sf;
349 :
350 0 : return( SFGlyphNameCompletion(sf,t,from_tab,true));
351 : }
352 :
353 0 : static void MATH_Init(MathDlg *math) {
354 : int i, cnt, ccnt, ta, h;
355 : char buffer[20];
356 : GGadget *g;
357 : struct matrix_data *mds;
358 0 : SplineFont *sf = math->sf;
359 : SplineChar *sc;
360 : int cols;
361 0 : char *change = _("Change");
362 :
363 0 : for ( i=0; math_constants_descriptor[i].ui_name!=NULL; ++i ) {
364 0 : GGadget *tf = GWidgetGetControl(math->gw,2*i+1);
365 0 : int16 *pos = (int16 *) (((char *) (math->math)) + math_constants_descriptor[i].offset );
366 :
367 0 : sprintf( buffer, "%d", *pos );
368 0 : GGadgetSetTitle8(tf,buffer);
369 0 : if ( math_constants_descriptor[i].devtab_offset >= 0 ) {
370 0 : GGadget *tf2 = GWidgetGetControl(math->gw,2*i+2);
371 0 : DeviceTable **devtab = (DeviceTable **) (((char *) (math->math)) + math_constants_descriptor[i].devtab_offset );
372 : char *str;
373 :
374 0 : DevTabToString(&str,*devtab);
375 0 : if ( str!=NULL )
376 0 : GGadgetSetTitle8(tf2,str);
377 0 : free(str);
378 : }
379 : }
380 :
381 : /* Extension Shapes */
382 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL )
383 0 : if ( sc->is_extended_shape )
384 0 : ++cnt;
385 0 : mds = calloc(cnt*2,sizeof(struct matrix_data));
386 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL )
387 0 : if ( sc->is_extended_shape ) {
388 0 : mds[2*cnt+0].u.md_str = copy(sc->name);
389 0 : mds[2*cnt+1].u.md_ival = true;
390 0 : ++cnt;
391 : }
392 0 : GMatrixEditSet(GWidgetGetControl(math->gw,CID_Exten), mds,cnt,false);
393 :
394 : /* Italic Correction && Top Angle Horizontal Position */
395 0 : for ( ta=0; ta<2; ++ta ) {
396 0 : g = GWidgetGetControl(math->gw,ta?CID_TopAccent:CID_Italic );
397 0 : cols = GMatrixEditGetColCnt(g);
398 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
399 0 : if ( (ta==0 && sc->italic_correction!=TEX_UNDEF ) ||
400 0 : (ta==1 && sc->top_accent_horiz!=TEX_UNDEF))
401 0 : ++cnt;
402 : }
403 0 : mds = calloc(cnt*cols,sizeof(struct matrix_data));
404 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
405 0 : if ( ta==0 && sc->italic_correction!=TEX_UNDEF ) {
406 0 : mds[cols*cnt+0].u.md_str = copy(sc->name);
407 0 : mds[cols*cnt+1].u.md_ival = sc->italic_correction;
408 0 : DevTabToString(&mds[cols*cnt+2].u.md_str,sc->italic_adjusts);
409 0 : ++cnt;
410 0 : } else if ( ta==1 &&sc->top_accent_horiz!=TEX_UNDEF ) {
411 0 : mds[cols*cnt+0].u.md_str = copy(sc->name);
412 0 : mds[cols*cnt+1].u.md_ival = sc->top_accent_horiz;
413 0 : DevTabToString(&mds[cols*cnt+2].u.md_str,sc->top_accent_adjusts);
414 0 : ++cnt;
415 : }
416 : }
417 0 : GMatrixEditSet(g, mds,cnt,false);
418 : }
419 :
420 : /* Math Kern */
421 0 : g = GWidgetGetControl(math->gw,CID_MathKern);
422 0 : cols = GMatrixEditGetColCnt(g);
423 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL )
424 0 : if ( sc->mathkern!=NULL )
425 0 : ++cnt;
426 0 : mds = calloc(cnt*cols,sizeof(struct matrix_data));
427 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL )
428 0 : if ( sc->mathkern!=NULL ) {
429 0 : mds[cols*cnt+0].u.md_str = copy(sc->name);
430 0 : mds[cols*cnt+1].u.md_str = copy(change);
431 0 : ++cnt;
432 : }
433 0 : GMatrixEditSet(g, mds,cnt,false);
434 :
435 : /* Horizontal/Vertical Glyph Variants */
436 0 : for ( h=0; h<2; ++h ) {
437 0 : g = GWidgetGetControl(math->gw,CID_VGlyphVar+2*h);
438 0 : cols = GMatrixEditGetColCnt(g);
439 0 : for ( i=cnt=ccnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
440 0 : struct glyphvariants *gv = h ? sc->horiz_variants : sc->vert_variants;
441 0 : if ( gv!=NULL && gv->variants!=NULL )
442 0 : ++cnt;
443 0 : if ( gv!=NULL && gv->part_cnt!=0 )
444 0 : ++ccnt;
445 : }
446 0 : mds = calloc(cnt*cols,sizeof(struct matrix_data));
447 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
448 0 : struct glyphvariants *gv = h ? sc->horiz_variants : sc->vert_variants;
449 0 : if ( gv!=NULL && gv->variants!=NULL ) {
450 0 : mds[cols*cnt+0].u.md_str = SCNameUniStr(sc);
451 0 : mds[cols*cnt+1].u.md_str = SFNameList2NameUni(sf,gv->variants);
452 0 : ++cnt;
453 : }
454 : }
455 0 : GMatrixEditSet(g, mds,cnt,false);
456 :
457 : /* Glyph Construction */
458 0 : g = GWidgetGetControl(math->gw,CID_VGlyphConst+2*h);
459 0 : cols = GMatrixEditGetColCnt(g);
460 0 : mds = calloc(ccnt*cols,sizeof(struct matrix_data));
461 0 : for ( i=cnt=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
462 0 : struct glyphvariants *gv = h ? sc->horiz_variants : sc->vert_variants;
463 0 : if ( gv!=NULL && gv->part_cnt!=0 ) {
464 0 : mds[cols*cnt+0].u.md_str = copy(sc->name);
465 0 : mds[cols*cnt+1].u.md_ival = gv->italic_correction;
466 0 : DevTabToString(&mds[cols*cnt+2].u.md_str,gv->italic_adjusts);
467 0 : mds[cols*cnt+cols-1].u.md_str = GV_ToString(gv);
468 0 : ++cnt;
469 : }
470 : }
471 0 : GMatrixEditSet(g, mds,cnt,false);
472 : }
473 0 : }
474 :
475 0 : static void MATH_FreeImage(const void *_math, GImage *img) {
476 0 : GImageDestroy(img);
477 0 : }
478 :
479 0 : static GImage *_MATHVar_GetImage(const void *_math) {
480 0 : MathDlg *math = (MathDlg *) _math;
481 0 : GGadget *varlist = math->popup_g;
482 0 : int rows, cols = GMatrixEditGetColCnt(varlist);
483 0 : struct matrix_data *old = GMatrixEditGet(varlist,&rows);
484 0 : SplineChar *sc = SFGetChar(math->sf,-1, old[cols*math->popup_r].u.md_str);
485 : static OTLookup dummyl = OTLOOKUP_EMPTY;
486 : static struct lookup_subtable dummys = LOOKUP_SUBTABLE_EMPTY;
487 :
488 0 : dummyl.lookup_type = gsub_multiple;
489 0 : dummys.lookup = &dummyl;
490 0 : return( PST_GetImage(varlist,math->sf,math->def_layer,&dummys,math->popup_r,sc) );
491 : }
492 :
493 0 : static void MATHVar_PopupPrepare(GGadget *g, int r, int c) {
494 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
495 0 : int rows, cols = GMatrixEditGetColCnt(g);
496 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
497 :
498 0 : if ( c<0 || c>=cols || r<0 || r>=rows || old[cols*r].u.md_str==NULL ||
499 0 : SFGetChar(math->sf,-1, old[cols*r+0].u.md_str)==NULL )
500 0 : return;
501 0 : math->popup_r = r;
502 0 : math->popup_g = g;
503 0 : GGadgetPreparePopupImage(GGadgetGetWindow(g),NULL,math,_MATHVar_GetImage,MATH_FreeImage);
504 : }
505 :
506 0 : static GImage *_MATHConst_GetImage(const void *_math) {
507 0 : MathDlg *math = (MathDlg *) _math;
508 0 : GGadget *varlist = math->popup_g;
509 0 : int rows, cols = GMatrixEditGetColCnt(varlist);
510 0 : struct matrix_data *old = GMatrixEditGet(varlist,&rows);
511 0 : SplineChar *sc = SFGetChar(math->sf,-1, old[cols*math->popup_r].u.md_str);
512 0 : struct glyphvariants *gv = GV_FromString(NULL,old[cols*math->popup_r+cols-1].u.md_str);
513 : GImage *ret;
514 :
515 0 : ret = GV_GetConstructedImage(sc,math->def_layer,gv,GGadgetGetCid(varlist)==CID_HGlyphConst);
516 0 : GlyphVariantsFree(gv);
517 0 : return( ret );
518 : }
519 :
520 0 : static void MATHConst_PopupPrepare(GGadget *g, int r, int c) {
521 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
522 0 : int rows, cols = GMatrixEditGetColCnt(g);
523 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
524 :
525 0 : if ( c<0 || c>=cols || r<0 || r>=rows || old[cols*r].u.md_str==NULL ||
526 0 : SFGetChar(math->sf,-1, old[cols*r+0].u.md_str)==NULL )
527 0 : return;
528 0 : math->popup_r = r;
529 0 : math->popup_g = g;
530 0 : GGadgetPreparePopupImage(GGadgetGetWindow(g),NULL,math,_MATHConst_GetImage,MATH_FreeImage);
531 : }
532 :
533 0 : static GImage *_MATHLine_GetImage(const void *_math) {
534 0 : MathDlg *math = (MathDlg *) _math;
535 0 : GGadget *varlist = math->popup_g;
536 0 : int rows, cols = GMatrixEditGetColCnt(varlist);
537 0 : struct matrix_data *old = GMatrixEditGet(varlist,&rows);
538 0 : SplineChar *sc = SFGetChar(math->sf,-1, old[cols*math->popup_r].u.md_str);
539 :
540 0 : return( SC_GetLinedImage(sc,math->def_layer,old[cols*math->popup_r+1].u.md_ival,GGadgetGetCid(varlist)==CID_Italic));
541 : }
542 :
543 0 : static void MATHLine_PopupPrepare(GGadget *g, int r, int c) {
544 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
545 0 : int rows, cols = GMatrixEditGetColCnt(g);
546 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
547 :
548 0 : if ( c<0 || c>=cols || r<0 || r>=rows || old[cols*r].u.md_str==NULL ||
549 0 : SFGetChar(math->sf,-1, old[cols*r+0].u.md_str)==NULL )
550 0 : return;
551 0 : math->popup_r = r;
552 0 : math->popup_g = g;
553 0 : GGadgetPreparePopupImage(GGadgetGetWindow(g),NULL,math,_MATHLine_GetImage,MATH_FreeImage);
554 : }
555 :
556 0 : static GImage *_GVC_GetImage(const void *_math) {
557 0 : MathDlg *math = (MathDlg *) _math;
558 0 : GGadget *varlist = math->popup_g;
559 0 : int rows, cols = GMatrixEditGetColCnt(varlist);
560 0 : struct matrix_data *old = GMatrixEditGet(varlist,&rows);
561 : GImage *ret;
562 : struct glyphvariants *gv;
563 :
564 0 : gv = GV_ParseConstruction(NULL,old,rows,cols);
565 0 : ret = GV_GetConstructedImage(math->sc,math->def_layer,gv,math->is_horiz);
566 0 : GlyphVariantsFree(gv);
567 0 : return( ret );
568 : }
569 :
570 0 : static void italic_finishedit(GGadget *g, int r, int c, int wasnew) {
571 : int rows;
572 : struct matrix_data *stuff;
573 : MathDlg *math;
574 : int cols;
575 : DBounds b;
576 : SplineChar *sc;
577 :
578 0 : if ( c!=0 )
579 0 : return;
580 0 : if ( !wasnew )
581 0 : return;
582 : /* If they added a new glyph to the sequence then set some defaults for it. */
583 : /* only the full advance has any likelyhood of being correct */
584 0 : math = GDrawGetUserData(GGadgetGetWindow(g));
585 0 : stuff = GMatrixEditGet(g, &rows);
586 0 : cols = GMatrixEditGetColCnt(g);
587 0 : if ( stuff[r*cols+0].u.md_str==NULL )
588 0 : return;
589 0 : sc = SFGetChar(math->sf,-1,stuff[r*cols+0].u.md_str);
590 0 : if ( sc==NULL )
591 0 : return;
592 0 : SplineCharFindBounds(sc,&b);
593 0 : if ( b.maxx>sc->width ) {
594 0 : stuff[r*cols+1].u.md_ival = rint((b.maxx-sc->width) +
595 0 : (math->sf->ascent+math->sf->descent)/16.0);
596 0 : GGadgetRedraw(g);
597 : }
598 : }
599 :
600 0 : static void topaccent_finishedit(GGadget *g, int r, int c, int wasnew) {
601 : int rows;
602 : struct matrix_data *stuff;
603 : MathDlg *math;
604 : int cols;
605 : DBounds b;
606 : SplineChar *sc;
607 : double italic_off;
608 :
609 0 : if ( c!=0 )
610 0 : return;
611 0 : if ( !wasnew )
612 0 : return;
613 : /* If they added a new glyph to the sequence then set some defaults for it. */
614 : /* only the full advance has any likelyhood of being correct */
615 0 : math = GDrawGetUserData(GGadgetGetWindow(g));
616 0 : stuff = GMatrixEditGet(g, &rows);
617 0 : cols = GMatrixEditGetColCnt(g);
618 0 : if ( stuff[r*cols+0].u.md_str==NULL )
619 0 : return;
620 0 : sc = SFGetChar(math->sf,-1,stuff[r*cols+0].u.md_str);
621 0 : if ( sc==NULL )
622 0 : return;
623 0 : SplineCharFindBounds(sc,&b);
624 0 : italic_off = (b.maxy-b.miny)*tan(-math->sf->italicangle);
625 0 : if ( b.maxx-b.minx-italic_off < 0 )
626 0 : stuff[r*cols+1].u.md_ival = rint(b.minx + (b.maxx-b.minx)/2);
627 : else
628 0 : stuff[r*cols+1].u.md_ival = rint(b.minx + italic_off + (b.maxx - b.minx - italic_off)/2);
629 0 : GGadgetRedraw(g);
630 : }
631 :
632 0 : static void mathkern_initrow(GGadget *g, int r) {
633 : int rows;
634 : struct matrix_data *stuff;
635 : int cols;
636 :
637 0 : cols = GMatrixEditGetColCnt(g);
638 0 : stuff = GMatrixEditGet(g, &rows);
639 0 : stuff[r*cols+1].u.md_str = copy(_("Change"));
640 0 : };
641 :
642 0 : static void extpart_finishedit(GGadget *g, int r, int c, int wasnew) {
643 : int rows;
644 : struct matrix_data *stuff;
645 : MathDlg *math;
646 : int cols;
647 : DBounds b;
648 : double full_advance;
649 : SplineChar *sc;
650 :
651 0 : if ( c!=0 )
652 0 : return;
653 0 : if ( !wasnew )
654 0 : return;
655 : /* If they added a new glyph to the sequence then set some defaults for it. */
656 : /* only the full advance has any likelyhood of being correct */
657 0 : math = GDrawGetUserData(GGadgetGetWindow(g));
658 0 : stuff = GMatrixEditGet(g, &rows);
659 0 : cols = GMatrixEditGetColCnt(g);
660 0 : if ( stuff[r*cols+0].u.md_str==NULL )
661 0 : return;
662 0 : sc = SFGetChar(math->sf,-1,stuff[r*cols+0].u.md_str);
663 0 : if ( sc==NULL )
664 0 : return;
665 0 : SplineCharFindBounds(sc,&b);
666 0 : if ( math->is_horiz )
667 0 : full_advance = b.maxx - b.minx;
668 : else
669 0 : full_advance = b.maxy - b.miny;
670 0 : stuff[r*cols+2].u.md_ival = stuff[r*cols+3].u.md_ival = rint(full_advance/3);
671 0 : stuff[r*cols+4].u.md_ival = rint(full_advance);
672 0 : GGadgetRedraw(g);
673 : }
674 :
675 0 : static void GVC_PopupPrepare(GGadget *g, int r, int c) {
676 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
677 :
678 0 : math->popup_g = g;
679 0 : if ( math->sc==NULL )
680 0 : return;
681 0 : GGadgetPreparePopupImage(GGadgetGetWindow(g),NULL,math,_GVC_GetImage,MATH_FreeImage);
682 : }
683 :
684 0 : static int GVC_OK(GGadget *g, GEvent *e) {
685 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
686 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
687 0 : math->done = true;
688 0 : math->ok = true;
689 : }
690 0 : return( true );
691 : }
692 :
693 0 : static int MATH_Cancel(GGadget *g, GEvent *e) {
694 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
695 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
696 0 : math->done = true;
697 : }
698 0 : return( true );
699 : }
700 :
701 0 : static int gc_e_h(GWindow gw, GEvent *event) {
702 0 : MathDlg *math = GDrawGetUserData(gw);
703 :
704 0 : if ( event->type==et_close ) {
705 0 : math->done = true;
706 0 : } else if ( event->type==et_char ) {
707 0 : if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
708 0 : help("math.html#GlyphConstruction");
709 0 : return( true );
710 0 : } else if ( GMenuIsCommand(event,H_("Quit|Ctl+Q") )) {
711 0 : MenuExit(NULL,NULL,NULL);
712 0 : } else if ( GMenuIsCommand(event,H_("Close|Ctl+Shft+Q") )) {
713 0 : math->done = true;
714 : }
715 0 : return( false );
716 : }
717 0 : return( true );
718 : }
719 :
720 0 : static char *GlyphConstruction_Dlg(GGadget *g, int r, int c) {
721 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
722 : MathDlg md;
723 : GRect pos;
724 : GWindow gw;
725 : GWindowAttrs wattrs;
726 0 : int rows, cols = GMatrixEditGetColCnt(g);
727 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
728 : GGadgetCreateData *harray[7], mgcd[4], *varray[6], mboxes[3];
729 : GTextInfo mlabel[3];
730 : struct glyphvariants *gv;
731 : char *ret;
732 :
733 0 : memset(&md,0,sizeof(md));
734 0 : md.sf = math->sf;
735 0 : md.is_horiz = GGadgetGetCid(g)==CID_HGlyphConst;
736 0 : md.sc = SFGetChar(md.sf,-1,old[r*cols+0].u.md_str);
737 :
738 0 : memset(&wattrs,0,sizeof(wattrs));
739 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
740 0 : wattrs.event_masks = ~(1<<et_charup);
741 0 : wattrs.restrict_input_to_me = 1;
742 0 : wattrs.is_dlg = 1;
743 0 : wattrs.undercursor = 1;
744 0 : wattrs.cursor = ct_pointer;
745 0 : wattrs.utf8_window_title = _("Glyph Construction");
746 0 : pos.x = pos.y = 0;
747 0 : pos.width = 100;
748 0 : pos.height = 100;
749 0 : md.gw = gw = GDrawCreateTopWindow(NULL,&pos,gc_e_h,&md,&wattrs);
750 :
751 0 : memset(mgcd,0,sizeof(mgcd));
752 0 : memset(mlabel,0,sizeof(mlabel));
753 0 : memset(mboxes,0,sizeof(mboxes));
754 :
755 0 : mgcd[0].gd.flags = gg_visible | gg_enabled;
756 0 : mgcd[0].gd.u.matrix = &mi_extensionpart;
757 0 : mgcd[0].gd.cid = CID_VGlyphConst;
758 0 : mgcd[0].creator = GMatrixEditCreate;
759 :
760 0 : mgcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
761 0 : mlabel[1].text = (unichar_t *) _("_OK");
762 0 : mlabel[1].text_is_1byte = true;
763 0 : mlabel[1].text_in_resource = true;
764 0 : mgcd[1].gd.label = &mlabel[1];
765 0 : mgcd[1].gd.handle_controlevent = GVC_OK;
766 0 : mgcd[1].creator = GButtonCreate;
767 :
768 0 : mgcd[2].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
769 0 : mlabel[2].text = (unichar_t *) _("_Cancel");
770 0 : mlabel[2].text_is_1byte = true;
771 0 : mlabel[2].text_in_resource = true;
772 0 : mgcd[2].gd.label = &mlabel[2];
773 0 : mgcd[2].gd.handle_controlevent = MATH_Cancel;
774 0 : mgcd[2].creator = GButtonCreate;
775 :
776 0 : harray[0] = GCD_Glue; harray[1] = &mgcd[1]; harray[2] = GCD_Glue;
777 0 : harray[3] = GCD_Glue; harray[4] = &mgcd[2]; harray[5] = GCD_Glue;
778 0 : harray[6] = NULL;
779 :
780 0 : mboxes[2].gd.flags = gg_enabled|gg_visible;
781 0 : mboxes[2].gd.u.boxelements = harray;
782 0 : mboxes[2].creator = GHBoxCreate;
783 :
784 0 : varray[0] = &mgcd[0]; varray[1] = NULL;
785 0 : varray[2] = &mboxes[2]; varray[3] = NULL;
786 0 : varray[4] = NULL;
787 :
788 0 : mboxes[0].gd.pos.x = mboxes[0].gd.pos.y = 2;
789 0 : mboxes[0].gd.flags = gg_enabled|gg_visible;
790 0 : mboxes[0].gd.u.boxelements = varray;
791 0 : mboxes[0].creator = GHVGroupCreate;
792 :
793 0 : GGadgetsCreate(gw,mboxes);
794 0 : GHVBoxSetExpandableRow(mboxes[0].ret,0);
795 0 : GHVBoxSetExpandableCol(mboxes[2].ret,gb_expandgluesame);
796 0 : GMatrixEditSetColumnCompletion(mgcd[0].ret,0,MATH_GlyphNameCompletion);
797 0 : GMatrixEditSetMouseMoveReporter(mgcd[0].ret,GVC_PopupPrepare);
798 :
799 : /* If it's unparseable, this will give 'em nothing */
800 0 : gv = GV_FromString(NULL,old[r*cols+cols-1].u.md_str);
801 0 : GV_ToMD(mgcd[0].ret,gv);
802 0 : GlyphVariantsFree(gv);
803 :
804 0 : GHVBoxFitWindow(mboxes[0].ret);
805 :
806 0 : GDrawSetVisible(md.gw,true);
807 :
808 0 : while ( !md.done )
809 0 : GDrawProcessOneEvent(NULL);
810 :
811 0 : if ( md.ok ) {
812 0 : int rs, cs = GMatrixEditGetColCnt(mgcd[0].ret);
813 0 : struct matrix_data *stuff = GMatrixEditGet(mgcd[0].ret,&rs);
814 0 : gv = GV_ParseConstruction(NULL,stuff,rs,cs);
815 0 : ret = GV_ToString(gv);
816 0 : GlyphVariantsFree(gv);
817 : } else
818 0 : ret = copy( old[r*cols+cols-1].u.md_str );
819 0 : GDrawDestroyWindow(md.gw);
820 0 : return( ret );
821 : }
822 :
823 0 : static char *MKChange_Dlg(GGadget *g, int r, int c) {
824 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
825 0 : int rows, cols = GMatrixEditGetColCnt(g);
826 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
827 : SplineChar *sc;
828 :
829 0 : if ( old[r*cols+0].u.md_str==NULL )
830 0 : return( NULL );
831 0 : sc = SFGetChar(math->sf,-1,old[r*cols+0].u.md_str);
832 0 : if ( sc==NULL )
833 0 : return( NULL );
834 :
835 0 : MathKernDialog(sc,math->def_layer);
836 0 : return( NULL );
837 : }
838 :
839 0 : static int MATH_OK(GGadget *g, GEvent *e) {
840 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
841 0 : MathDlg *math = GDrawGetUserData(GGadgetGetWindow(g));
842 0 : int err=false;
843 : int cid,i;
844 : int high,low;
845 0 : SplineFont *sf = math->sf;
846 : SplineChar *sc;
847 :
848 : /* Two passes. First checks that everything is parsable */
849 0 : for ( i=0; math_constants_descriptor[i].ui_name!=NULL; ++i ) {
850 0 : GetInt8(math->gw,2*i+1,math_constants_descriptor[i].ui_name,&err);
851 0 : if ( err )
852 0 : return( true );
853 0 : if ( math_constants_descriptor[i].devtab_offset >= 0 ) {
854 0 : GGadget *tf2 = GWidgetGetControl(math->gw,2*i+2);
855 0 : char *str = GGadgetGetTitle8(tf2);
856 0 : if ( !DeviceTableOK(str,&low,&high)) {
857 0 : ff_post_error(_("Bad device table"), _("Bad device table for %s"),
858 : math_constants_descriptor[i].ui_name);
859 0 : free(str);
860 0 : return( true );
861 : }
862 0 : free(str);
863 : }
864 : }
865 : /* Now check that the various glyph lists are parseable */
866 0 : for ( cid=CID_Exten; cid<=CID_HGlyphConst; ++cid ) {
867 0 : GGadget *g = GWidgetGetControl(math->gw,cid);
868 0 : int rows, cols = GMatrixEditGetColCnt(g);
869 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
870 0 : for ( i=0; i<rows; ++i ) {
871 0 : if ( SFGetChar(sf,-1,old[i*cols+0].u.md_str)==NULL ) {
872 0 : ff_post_error(_("Missing Glyph"), _("There is no glyph named %s (used in %s)"),
873 0 : old[i*cols+0].u.md_str, gi_aspectnames[cid-CID_Exten]);
874 0 : return( true );
875 : }
876 0 : if ( cid==CID_Italic || cid==CID_TopAccent ||
877 0 : cid == CID_VGlyphConst || cid == CID_HGlyphConst ) {
878 0 : if ( !DeviceTableOK(old[i*cols+2].u.md_str,&low,&high)) {
879 0 : ff_post_error(_("Bad device table"), _("Bad device table for glyph %s in %s"),
880 0 : old[i*cols+0].u.md_str, gi_aspectnames[cid-CID_Exten]);
881 0 : return( true );
882 : }
883 : }
884 0 : if ( cid == CID_VGlyphConst || cid == CID_HGlyphConst ) {
885 0 : if ( GV_StringCheck(sf,old[i*cols+cols-1].u.md_str)==-1 ) {
886 0 : ff_post_error(_("Bad Parts List"), _("Bad parts list for glyph %s in %s"),
887 0 : old[i*cols+0].u.md_str, gi_aspectnames[cid-CID_Exten]);
888 0 : return( true );
889 : }
890 : }
891 0 : if ( cid == CID_VGlyphVar || cid == CID_HGlyphVar ) {
892 0 : if ( !SF_NameListCheck(sf,old[i*cols+1].u.md_str)) {
893 0 : ff_post_error(_("Bad Variants List"), _("Bad Variants list for glyph %s in %s"),
894 0 : old[i*cols+0].u.md_str, gi_aspectnames[cid-CID_Exten]);
895 0 : return( true );
896 : }
897 : }
898 : }
899 : }
900 :
901 : /*********************************************/
902 : /* Ok, if we got this far it should be legal */
903 : /*********************************************/
904 0 : for ( i=0; math_constants_descriptor[i].ui_name!=NULL; ++i ) {
905 0 : int16 *pos = (int16 *) (((char *) (math->math)) + math_constants_descriptor[i].offset );
906 0 : *pos = GetInt8(math->gw,2*i+1,math_constants_descriptor[i].ui_name,&err);
907 :
908 0 : if ( math_constants_descriptor[i].devtab_offset >= 0 ) {
909 0 : GGadget *tf2 = GWidgetGetControl(math->gw,2*i+2);
910 0 : char *str = GGadgetGetTitle8(tf2);
911 0 : DeviceTable **devtab = (DeviceTable **) (((char *) (math->math)) + math_constants_descriptor[i].devtab_offset );
912 :
913 0 : *devtab = DeviceTableParse(*devtab,str);
914 0 : free(str);
915 : }
916 : }
917 0 : sf->MATH = math->math;
918 :
919 : /* As for the per-glyph stuff... Well the only way I can insure that */
920 : /* things which have been removed in the dlg are removed in the font */
921 : /* is to clear everything now, and start from a blank slate when I */
922 : /* parse stuff. (Except for math kerning which I don't support here) */
923 0 : for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
924 0 : sc->is_extended_shape = false;
925 0 : sc->italic_correction = TEX_UNDEF;
926 0 : sc->top_accent_horiz = TEX_UNDEF;
927 0 : DeviceTableFree(sc->italic_adjusts);
928 0 : DeviceTableFree(sc->top_accent_adjusts);
929 0 : sc->italic_adjusts = sc->top_accent_adjusts = NULL;
930 0 : GlyphVariantsFree(sc->vert_variants);
931 0 : GlyphVariantsFree(sc->horiz_variants);
932 0 : sc->vert_variants = sc->horiz_variants = NULL;
933 : /* MathKernFree(sc->mathkern); sc->mathkern = NULL; */
934 : }
935 : /* Then process each table to set whatever it sets */
936 0 : for ( cid=CID_Exten; cid<=CID_HGlyphConst; ++cid ) {
937 0 : GGadget *g = GWidgetGetControl(math->gw,cid);
938 0 : int rows, cols = GMatrixEditGetColCnt(g);
939 0 : struct matrix_data *old = GMatrixEditGet(g,&rows);
940 0 : for ( i=0; i<rows; ++i ) {
941 0 : sc = SFGetChar(sf,-1,old[i*cols+0].u.md_str);
942 0 : if ( cid==CID_Exten )
943 0 : sc->is_extended_shape = old[i*cols+1].u.md_ival;
944 0 : else if ( cid==CID_Italic ) {
945 0 : sc->italic_correction = old[i*cols+1].u.md_ival;
946 0 : sc->italic_adjusts = DeviceTableParse(NULL,old[i*cols+2].u.md_str);
947 0 : } else if ( cid==CID_TopAccent ) {
948 0 : sc->top_accent_horiz = old[i*cols+1].u.md_ival;
949 0 : sc->top_accent_adjusts = DeviceTableParse(NULL,old[i*cols+2].u.md_str);
950 0 : } else if ( cid==CID_VGlyphVar || cid==CID_HGlyphVar ) {
951 0 : struct glyphvariants **gvp = cid == CID_VGlyphVar ?
952 0 : &sc->vert_variants : &sc->horiz_variants;
953 0 : char *str = old[i*cols+1].u.md_str;
954 0 : if ( str!=NULL ) while ( *str==' ' ) ++str;
955 0 : if ( str!=NULL && *str!='\0' ) {
956 0 : *gvp = chunkalloc(sizeof(struct glyphvariants));
957 0 : (*gvp)->variants = GlyphNameListDeUnicode( str );
958 : }
959 0 : } else if ( cid==CID_VGlyphConst || cid==CID_HGlyphConst ) {
960 0 : struct glyphvariants **gvp = cid == CID_VGlyphConst ?
961 0 : &sc->vert_variants : &sc->horiz_variants;
962 0 : *gvp = GV_FromString(*gvp,old[cols*i+cols-1].u.md_str);
963 0 : if ( *gvp!=NULL && (*gvp)->part_cnt!=0 ) {
964 0 : (*gvp)->italic_correction = old[i*cols+1].u.md_ival;
965 0 : (*gvp)->italic_adjusts = DeviceTableParse(NULL,old[i*cols+2].u.md_str);
966 : }
967 : }
968 : }
969 : }
970 :
971 : /* Done! */
972 :
973 0 : math->done = true;
974 0 : math->ok = true;
975 : }
976 0 : return( true );
977 : }
978 :
979 0 : static int math_e_h(GWindow gw, GEvent *event) {
980 0 : MathDlg *math = GDrawGetUserData(gw);
981 :
982 0 : if ( event->type==et_close ) {
983 0 : math->done = true;
984 0 : } else if ( event->type==et_char ) {
985 0 : if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
986 0 : help("math.html");
987 0 : return( true );
988 0 : } else if ( GMenuIsCommand(event,H_("Quit|Ctl+Q") )) {
989 0 : MenuExit(NULL,NULL,NULL);
990 0 : } else if ( GMenuIsCommand(event,H_("Close|Ctl+Shft+Q") )) {
991 0 : math->done = true;
992 : }
993 0 : return( false );
994 : }
995 0 : return( true );
996 : }
997 :
998 : #define MAX_PAGE 9
999 : #define MAX_ROW 12
1000 :
1001 0 : void SFMathDlg(SplineFont *sf,int def_layer) {
1002 : MathDlg md;
1003 : int i, j, page, row, h;
1004 : GGadget *g;
1005 : GRect pos;
1006 : GWindow gw;
1007 : GWindowAttrs wattrs;
1008 : GGadgetCreateData gcd[MAX_PAGE][MAX_ROW][3], boxes[MAX_PAGE][2],
1009 : *hvarray[MAX_PAGE][MAX_ROW+1][4], *harray[7], mgcd[4],
1010 : *varray[6], mboxes[3], gi[8][2];
1011 : GTextInfo label[MAX_PAGE][MAX_ROW], mlabel[3];
1012 : GTabInfo aspects[MAX_PAGE+8+1];
1013 :
1014 0 : MathInit();
1015 :
1016 0 : memset(&md,0,sizeof(md));
1017 0 : if ( sf->cidmaster ) sf = sf->cidmaster;
1018 0 : md.sf = sf;
1019 0 : md.def_layer = def_layer;
1020 0 : md.math = sf->MATH;
1021 0 : if ( md.math==NULL )
1022 0 : md.math = MathTableNew(sf);
1023 :
1024 0 : memset(&wattrs,0,sizeof(wattrs));
1025 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
1026 0 : wattrs.event_masks = ~(1<<et_charup);
1027 0 : wattrs.restrict_input_to_me = 1;
1028 0 : wattrs.is_dlg = 1;
1029 0 : wattrs.undercursor = 1;
1030 0 : wattrs.cursor = ct_pointer;
1031 0 : wattrs.utf8_window_title = _("MATH table");
1032 0 : pos.x = pos.y = 0;
1033 0 : pos.width = 100;
1034 0 : pos.height = 100;
1035 0 : md.gw = gw = GDrawCreateTopWindow(NULL,&pos,math_e_h,&md,&wattrs);
1036 :
1037 0 : memset(gcd,0,sizeof(gcd));
1038 0 : memset(label,0,sizeof(label));
1039 0 : memset(boxes,0,sizeof(boxes));
1040 0 : memset(aspects,0,sizeof(aspects));
1041 0 : memset(gi,0,sizeof(gi));
1042 :
1043 0 : page = row = 0;
1044 0 : for ( i=0; math_constants_descriptor[i].ui_name!=NULL; ++i ) {
1045 0 : if ( math_constants_descriptor[i].new_page ) {
1046 0 : hvarray[page][row][0] = hvarray[page][row][1] = hvarray[page][row][2] = GCD_Glue;
1047 0 : hvarray[page][row][3] = NULL;
1048 0 : hvarray[page][row+1][0] = NULL;
1049 0 : ++page;
1050 0 : if ( page>=MAX_PAGE ) {
1051 0 : IError( "Too many pages" );
1052 0 : return;
1053 : }
1054 0 : row = 0;
1055 : }
1056 :
1057 0 : label[page][row].text = (unichar_t *) math_constants_descriptor[i].ui_name;
1058 0 : label[page][row].text_is_1byte = true;
1059 0 : label[page][row].text_in_resource = true;
1060 0 : gcd[page][row][0].gd.label = &label[page][row];
1061 0 : gcd[page][row][0].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
1062 0 : gcd[page][row][0].gd.popup_msg = (unichar_t *) math_constants_descriptor[i].message;
1063 0 : gcd[page][row][0].creator = GLabelCreate;
1064 0 : hvarray[page][row][0] = &gcd[page][row][0];
1065 :
1066 0 : gcd[page][row][1].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
1067 0 : gcd[page][row][1].gd.pos.width = 50;
1068 0 : gcd[page][row][1].gd.cid = 2*i+1;
1069 0 : gcd[page][row][1].gd.popup_msg = (unichar_t *) math_constants_descriptor[i].message;
1070 0 : gcd[page][row][1].creator = GTextFieldCreate;
1071 0 : hvarray[page][row][1] = &gcd[page][row][1];
1072 :
1073 0 : if ( math_constants_descriptor[i].devtab_offset>=0 ) {
1074 0 : gcd[page][row][2].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
1075 0 : gcd[page][row][2].gd.cid = 2*i+2;
1076 0 : gcd[page][row][2].gd.popup_msg = (unichar_t *) math_constants_descriptor[i].message;
1077 0 : gcd[page][row][2].creator = GTextFieldCreate;
1078 0 : hvarray[page][row][2] = &gcd[page][row][2];
1079 : } else
1080 0 : hvarray[page][row][2] = GCD_Glue;
1081 0 : hvarray[page][row][3] = NULL;
1082 :
1083 0 : if ( ++row>=MAX_ROW ) {
1084 0 : IError( "Too many rows" );
1085 0 : return;
1086 : }
1087 : }
1088 0 : hvarray[page][row][0] = hvarray[page][row][1] = hvarray[page][row][2] = GCD_Glue;
1089 0 : hvarray[page][row][3] = NULL;
1090 0 : hvarray[page][row+1][0] = NULL;
1091 :
1092 0 : for ( i=0; aspectnames[i]!=NULL; ++i ) {
1093 0 : boxes[i][0].gd.flags = gg_enabled|gg_visible;
1094 0 : boxes[i][0].gd.u.boxelements = hvarray[i][0];
1095 0 : boxes[i][0].creator = GHVBoxCreate;
1096 :
1097 0 : aspects[i].text = (unichar_t *) aspectnames[i];
1098 0 : aspects[i].text_is_1byte = true;
1099 0 : aspects[i].nesting = i!=0;
1100 0 : aspects[i].gcd = boxes[i];
1101 : }
1102 0 : if ( i!=page+1 ) { /* Page never gets its final increment */
1103 0 : IError( "Page miscount %d in descriptor table, but only %d names.", page+1, i );
1104 0 : return;
1105 : }
1106 :
1107 0 : for ( j=0; mis[j].col_cnt!=0; ++j ) {
1108 0 : gi[j][0].gd.flags = gg_enabled|gg_visible;
1109 0 : gi[j][0].gd.u.matrix = &mis[j];
1110 0 : gi[j][0].gd.cid = CID_Exten+j;
1111 0 : gi[j][0].creator = GMatrixEditCreate;
1112 :
1113 0 : aspects[i+j].text = (unichar_t *) gi_aspectnames[j];
1114 0 : aspects[i+j].text_is_1byte = true;
1115 0 : aspects[i+j].gcd = gi[j];
1116 : }
1117 :
1118 0 : memset(mgcd,0,sizeof(mgcd));
1119 0 : memset(mlabel,0,sizeof(mlabel));
1120 0 : memset(mboxes,0,sizeof(mboxes));
1121 :
1122 0 : mgcd[0].gd.u.tabs = aspects;
1123 0 : mgcd[0].gd.flags = gg_visible | gg_enabled | gg_tabset_vert;
1124 : /*mgcd[0].gd.cid = CID_Tabs;*/
1125 0 : mgcd[0].creator = GTabSetCreate;
1126 :
1127 0 : mgcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
1128 0 : mlabel[1].text = (unichar_t *) _("_OK");
1129 0 : mlabel[1].text_is_1byte = true;
1130 0 : mlabel[1].text_in_resource = true;
1131 0 : mgcd[1].gd.label = &mlabel[1];
1132 0 : mgcd[1].gd.handle_controlevent = MATH_OK;
1133 0 : mgcd[1].creator = GButtonCreate;
1134 :
1135 0 : mgcd[2].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1136 0 : mlabel[2].text = (unichar_t *) _("_Cancel");
1137 0 : mlabel[2].text_is_1byte = true;
1138 0 : mlabel[2].text_in_resource = true;
1139 0 : mgcd[2].gd.label = &mlabel[2];
1140 0 : mgcd[2].gd.handle_controlevent = MATH_Cancel;
1141 0 : mgcd[2].creator = GButtonCreate;
1142 :
1143 0 : harray[0] = GCD_Glue; harray[1] = &mgcd[1]; harray[2] = GCD_Glue;
1144 0 : harray[3] = GCD_Glue; harray[4] = &mgcd[2]; harray[5] = GCD_Glue;
1145 0 : harray[6] = NULL;
1146 :
1147 0 : mboxes[2].gd.flags = gg_enabled|gg_visible;
1148 0 : mboxes[2].gd.u.boxelements = harray;
1149 0 : mboxes[2].creator = GHBoxCreate;
1150 :
1151 0 : varray[0] = &mgcd[0]; varray[1] = NULL;
1152 0 : varray[2] = &mboxes[2]; varray[3] = NULL;
1153 0 : varray[4] = NULL;
1154 :
1155 0 : mboxes[0].gd.pos.x = mboxes[0].gd.pos.y = 2;
1156 0 : mboxes[0].gd.flags = gg_enabled|gg_visible;
1157 0 : mboxes[0].gd.u.boxelements = varray;
1158 0 : mboxes[0].creator = GHVGroupCreate;
1159 :
1160 0 : GGadgetsCreate(gw,mboxes);
1161 0 : GHVBoxSetExpandableRow(mboxes[0].ret,0);
1162 0 : GHVBoxSetExpandableCol(mboxes[2].ret,gb_expandgluesame);
1163 0 : for ( i=0; aspectnames[i]!=NULL; ++i ) {
1164 0 : GHVBoxSetExpandableCol(boxes[i][0].ret,2);
1165 0 : GHVBoxSetExpandableRow(boxes[i][0].ret,gb_expandglue);
1166 : }
1167 0 : for ( j=0; mis[j].col_cnt!=0; ++j )
1168 0 : GMatrixEditSetColumnCompletion(gi[j][0].ret,0,MATH_GlyphNameCompletion);
1169 0 : for ( h=0; h<2; ++h ) {
1170 0 : g = GWidgetGetControl(md.gw,CID_VGlyphVar+2*h);
1171 0 : GMatrixEditSetColumnCompletion(g,1,MATH_GlyphListCompletion);
1172 0 : GMatrixEditSetMouseMoveReporter(g,MATHVar_PopupPrepare);
1173 0 : g = GWidgetGetControl(md.gw,CID_VGlyphConst+2*h);
1174 0 : GMatrixEditSetMouseMoveReporter(g,MATHConst_PopupPrepare);
1175 : }
1176 0 : GMatrixEditSetMouseMoveReporter(GWidgetGetControl(md.gw,CID_Italic),MATHLine_PopupPrepare);
1177 0 : GMatrixEditSetMouseMoveReporter(GWidgetGetControl(md.gw,CID_TopAccent),MATHLine_PopupPrepare);
1178 0 : MATH_Init(&md);
1179 0 : GHVBoxFitWindow(mboxes[0].ret);
1180 :
1181 0 : GDrawSetVisible(md.gw,true);
1182 :
1183 0 : while ( !md.done )
1184 0 : GDrawProcessOneEvent(NULL);
1185 0 : if ( sf->MATH==NULL && !md.ok )
1186 0 : MATHFree(md.math);
1187 :
1188 0 : GDrawDestroyWindow(md.gw);
1189 : }
1190 :
1191 : /* ************************************************************************** */
1192 : /* ****************************** Math Kern Dlg ***************************** */
1193 : /* ************************************************************************** */
1194 :
1195 : #define CID_TopBox 1000
1196 : #define CID_Glyph 1001
1197 : #define CID_Tabs 1002
1198 : #define CID_Corners 1003
1199 : #define CID_TopRight 1004
1200 : #define CID_TopLeft 1005
1201 : #define CID_BottomRight 1006
1202 : #define CID_BottomLeft 1007
1203 :
1204 0 : static void MKD_SetGlyphList(MathKernDlg *mkd, SplineChar *sc) {
1205 0 : SplineFont *sf = sc->parent;
1206 : int k,cnt, gid;
1207 0 : GTextInfo **tis = NULL;
1208 : SplineChar *test;
1209 :
1210 0 : for ( k=0; k<2; ++k ) {
1211 0 : cnt = 0;
1212 0 : for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (test=sf->glyphs[gid])!=NULL ) {
1213 0 : if ( test==sc || test->mathkern!=NULL ) {
1214 0 : if ( k ) {
1215 0 : tis[cnt] = calloc(1,sizeof(GTextInfo));
1216 0 : tis[cnt]->text = utf82u_copy(test->name);
1217 0 : tis[cnt]->userdata = test;
1218 0 : tis[cnt]->selected = test==sc;
1219 0 : tis[cnt]->fg = tis[cnt]->bg = COLOR_DEFAULT;
1220 : }
1221 0 : ++cnt;
1222 : }
1223 : }
1224 0 : if ( !k )
1225 0 : tis = malloc((cnt+1)*sizeof(GTextInfo *));
1226 : else
1227 0 : tis[cnt] = calloc(1,sizeof(GTextInfo));
1228 : }
1229 0 : GGadgetSetList(GWidgetGetControl(mkd->gw,CID_Glyph),tis,false);
1230 0 : }
1231 :
1232 0 : static void MKDSubResize(MathKernDlg *mkd, GEvent *event) {
1233 : int width, height;
1234 : int i;
1235 : GRect r;
1236 :
1237 0 : if ( !event->u.resize.sized )
1238 0 : return;
1239 :
1240 0 : width = (event->u.resize.size.width-4*mkd->mid_space)/4;
1241 0 : height = (event->u.resize.size.height-mkd->cv_y-8);
1242 0 : if ( width<70 || height<80 ) {
1243 0 : if ( width<70 ) width = 70;
1244 0 : width = 4*(width+mkd->mid_space);
1245 0 : if ( height<80 ) height = 80;
1246 0 : height += mkd->cv_y+mkd->button_height+8;
1247 0 : GDrawGetSize(mkd->gw,&r);
1248 0 : width += r.width-event->u.resize.size.width;
1249 0 : height += r.height-event->u.resize.size.height;
1250 0 : GDrawResize(mkd->gw,width,height);
1251 0 : return;
1252 : }
1253 0 : if ( width!=mkd->cv_width || height!=mkd->cv_height ) {
1254 0 : mkd->cv_width = width; mkd->cv_height = height;
1255 0 : for ( i=0; i<4; ++i ) {
1256 0 : CharView *cv = (&mkd->cv_topright)+i;
1257 0 : GDrawResize(cv->gw,width,height);
1258 0 : if ( i!=0 )
1259 0 : GDrawMove(cv->gw,10+i*(mkd->cv_width+mkd->mid_space),mkd->cv_y);
1260 : }
1261 : }
1262 :
1263 0 : GDrawSync(NULL);
1264 0 : GDrawProcessPendingEvents(NULL);
1265 0 : GDrawRequestExpose(mkd->cvparent_w,NULL,false);
1266 : }
1267 :
1268 0 : static void MKDTopResize(MathKernDlg *mkd, GEvent *event) {
1269 :
1270 0 : if ( !event->u.resize.sized )
1271 0 : return;
1272 :
1273 0 : GGadgetMove(GWidgetGetControl(mkd->gw,CID_TopBox),4,4);
1274 0 : GGadgetResize(GWidgetGetControl(mkd->gw,CID_TopBox),
1275 0 : event->u.resize.size.width-8,
1276 0 : event->u.resize.size.height-12);
1277 : }
1278 :
1279 :
1280 0 : static void MKDDraw(MathKernDlg *mkd, GWindow pixmap, GEvent *event) {
1281 : GRect r;
1282 : int i;
1283 :
1284 0 : GDrawSetLineWidth(pixmap,0);
1285 0 : for ( i=0; i<4; ++i ) {
1286 0 : CharView *cv = (&mkd->cv_topright)+i;
1287 :
1288 0 : r.x = 10+i*(mkd->cv_width+mkd->mid_space)-1; r.y=mkd->cv_y-1;
1289 0 : r.width = mkd->cv_width+1; r.height = mkd->cv_height+1;
1290 0 : GDrawDrawRect(pixmap,&r,0);
1291 :
1292 0 : GDrawSetFont(pixmap,cv->inactive ? mkd->plain : mkd->bold);
1293 0 : GDrawDrawText8(pixmap,r.x,5+mkd->as,cornernames[i],-1,0);
1294 : }
1295 0 : }
1296 :
1297 0 : void MKDMakeActive(MathKernDlg *mkd,CharView *cv) {
1298 : GRect r;
1299 : int i;
1300 :
1301 0 : if ( mkd==NULL )
1302 0 : return;
1303 0 : for ( i=0; i<4; ++i )
1304 0 : (&mkd->cv_topright)[i].inactive = true;
1305 0 : cv->inactive = false;
1306 0 : GDrawSetUserData(mkd->gw,cv);
1307 0 : GDrawSetUserData(mkd->cvparent_w,cv);
1308 0 : for ( i=0; i<4; ++i )
1309 0 : GDrawRequestExpose((&mkd->cv_topright)[i].v,NULL,false);
1310 0 : GDrawGetSize(mkd->gw,&r);
1311 0 : r.x = 0;
1312 0 : r.y = 0;
1313 0 : r.height = mkd->fh+10;
1314 0 : GDrawRequestExpose(mkd->cvparent_w,&r,false);
1315 : }
1316 :
1317 0 : static void MKDChar(MathKernDlg *mkd, GEvent *event) {
1318 : int i;
1319 0 : for ( i=0; i<4; ++i )
1320 0 : if ( !(&mkd->cv_topright)[i].inactive )
1321 0 : break;
1322 :
1323 0 : if ( event->u.chr.keysym==GK_Tab || event->u.chr.keysym==GK_BackTab ) {
1324 0 : if ( event->u.chr.keysym==GK_Tab ) ++i; else --i;
1325 0 : if ( i<0 ) i=3; else if ( i>3 ) i = 0;
1326 0 : MKDMakeActive(mkd,(&mkd->cv_topright)+i);
1327 : } else
1328 0 : CVChar((&mkd->cv_topright)+i,event);
1329 0 : }
1330 :
1331 0 : void MKD_DoClose(struct cvcontainer *cvc) {
1332 0 : MathKernDlg *mkd = (MathKernDlg *) cvc;
1333 : int i;
1334 :
1335 0 : for ( i=0; i<4; ++i ) {
1336 0 : SplineChar *msc = &(&mkd->sc_topright)[i];
1337 0 : SplinePointListsFree(msc->layers[0].splines);
1338 0 : SplinePointListsFree(msc->layers[1].splines);
1339 0 : free( msc->layers );
1340 : }
1341 :
1342 0 : mkd->done = true;
1343 0 : }
1344 :
1345 0 : static int mkd_sub_e_h(GWindow gw, GEvent *event) {
1346 0 : MathKernDlg *mkd = (MathKernDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
1347 :
1348 0 : switch ( event->type ) {
1349 : case et_expose:
1350 0 : MKDDraw(mkd,gw,event);
1351 0 : break;
1352 : case et_resize:
1353 0 : if ( event->u.resize.sized )
1354 0 : MKDSubResize(mkd,event);
1355 0 : break;
1356 : case et_char:
1357 0 : MKDChar(mkd,event);
1358 0 : break;
1359 : }
1360 0 : return( true );
1361 : }
1362 :
1363 0 : static int mkd_e_h(GWindow gw, GEvent *event) {
1364 0 : MathKernDlg *mkd = (MathKernDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
1365 : int i;
1366 :
1367 0 : switch ( event->type ) {
1368 : case et_char:
1369 0 : MKDChar(mkd,event);
1370 0 : break;
1371 : case et_resize:
1372 0 : if ( event->u.resize.sized )
1373 0 : MKDTopResize(mkd,event);
1374 0 : break;
1375 : case et_close:
1376 0 : MKD_DoClose((struct cvcontainer *) mkd);
1377 0 : break;
1378 : case et_create:
1379 0 : break;
1380 : case et_map:
1381 0 : for ( i=0; i<4; ++i ) {
1382 0 : CharView *cv = (&mkd->cv_topright)+i;
1383 0 : if ( !cv->inactive ) {
1384 0 : if ( event->u.map.is_visible )
1385 0 : CVPaletteActivate(cv);
1386 : else
1387 0 : CVPalettesHideIfMine(cv);
1388 0 : break;
1389 : }
1390 : }
1391 : /* mkd->isvisible = event->u.map.is_visible; */
1392 0 : break;
1393 : }
1394 0 : return( true );
1395 : }
1396 :
1397 0 : static void MKDFillup(MathKernDlg *mkd, SplineChar *sc) {
1398 : int i, j, rows;
1399 : SplineSet *last, *cur;
1400 : RefChar *ref;
1401 : GTextInfo **list;
1402 :
1403 0 : if ( mkd->last_aspect==0 ) {
1404 0 : for ( i=0; i<4; ++i ) {
1405 0 : SplineChar *msc = &(&mkd->sc_topright)[i];
1406 0 : struct mathkernvertex *mkv = sc->mathkern==NULL ? NULL : &(&sc->mathkern->top_right)[i];
1407 0 : msc->width = sc->width;
1408 0 : msc->italic_correction = sc->italic_correction;
1409 0 : msc->top_accent_horiz = sc->top_accent_horiz;
1410 0 : last = NULL;
1411 0 : SplinePointListsFree(msc->layers[0].splines);
1412 0 : SplinePointListsFree(msc->layers[1].splines);
1413 0 : msc->layers[0].splines = msc->layers[1].splines = NULL;
1414 :
1415 : /* copy the character itself into the background */
1416 0 : last = msc->layers[0].splines = SplinePointListCopy(sc->layers[ly_fore].splines);
1417 0 : if ( last!=NULL )
1418 0 : while ( last->next!=NULL ) last = last->next;
1419 0 : for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
1420 0 : if ( last==NULL )
1421 0 : cur = SplinePointListCopy(ref->layers[0].splines);
1422 0 : if ( last==NULL )
1423 0 : msc->layers[0].splines = cur;
1424 : else
1425 0 : last->next = cur;
1426 0 : if ( cur!=NULL )
1427 0 : for ( last=cur; last->next==NULL; last = last->next );
1428 : }
1429 : /* Now copy the dots from the mathkern vertex structure */
1430 0 : last = NULL;
1431 0 : if ( mkv!=NULL ) {
1432 0 : for ( j=0; j<mkv->cnt; ++j ) {
1433 0 : cur = chunkalloc(sizeof(SplineSet));
1434 0 : cur->first = cur->last = SplinePointCreate(mkv->mkd[j].kern +
1435 0 : ((i&1)?0:sc->width) +
1436 0 : ((i&2)?0:sc->italic_correction==TEX_UNDEF?0:sc->italic_correction),
1437 0 : mkv->mkd[j].height );
1438 0 : cur->first->pointtype = pt_corner;
1439 0 : if ( last==NULL )
1440 0 : msc->layers[ly_fore].splines = cur;
1441 : else
1442 0 : last->next = cur;
1443 0 : last = cur;
1444 : }
1445 : }
1446 : }
1447 : } else {
1448 0 : for ( i=0; i<4; ++i ) {
1449 0 : struct mathkernvertex *mkv = sc->mathkern==NULL ? NULL : &(&sc->mathkern->top_right)[i];
1450 0 : GGadget *list = GWidgetGetControl(mkd->gw,CID_TopRight+i);
1451 0 : int cols = GMatrixEditGetColCnt(list);
1452 : struct matrix_data *md;
1453 :
1454 0 : if ( mkv!=NULL ) {
1455 0 : md = calloc(mkv->cnt*cols,sizeof(struct matrix_data));
1456 0 : for ( j=0; j<mkv->cnt; ++j ) {
1457 0 : md[j*cols+0].u.md_ival = mkv->mkd[j].height;
1458 0 : md[j*cols+1].u.md_ival = mkv->mkd[j].kern;
1459 0 : DevTabToString(&md[j*cols+2].u.md_str,mkv->mkd[j].height_adjusts);
1460 0 : DevTabToString(&md[j*cols+3].u.md_str,mkv->mkd[j].kern_adjusts);
1461 : }
1462 0 : GMatrixEditSet(list, md,mkv->cnt,false);
1463 : } else
1464 0 : GMatrixEditSet(list, NULL,0,false);
1465 : }
1466 : }
1467 0 : mkd->cursc = sc;
1468 :
1469 0 : list = GGadgetGetList(GWidgetGetControl(mkd->gw,CID_Glyph),&rows);
1470 0 : for ( i=rows-1; i>=0; --i )
1471 0 : if ( list[i]->userdata==sc )
1472 0 : break;
1473 0 : if ( i>=0 )
1474 0 : GGadgetSelectOneListItem(GWidgetGetControl(mkd->gw,CID_Glyph),i);
1475 0 : }
1476 :
1477 0 : static void MKDFillupRefresh(MathKernDlg *mkd, SplineChar *sc) {
1478 : int i;
1479 :
1480 0 : MKDFillup(mkd, sc);
1481 0 : if ( mkd->last_aspect==0 ) {
1482 0 : for ( i=0; i<4; ++i ) {
1483 0 : CharView *cv = &mkd->cv_topright + i;
1484 0 : GDrawRequestExpose(cv->gw,NULL,false);
1485 0 : GDrawRequestExpose(cv->v,NULL,false);
1486 : }
1487 : }
1488 0 : }
1489 :
1490 0 : static int bp_order_height(const void *bpp1, const void *bpp2) {
1491 0 : const BasePoint *bp1 = *(const BasePoint **) bpp1;
1492 0 : const BasePoint *bp2 = *(const BasePoint **) bpp2;
1493 0 : if ( bp1->y > bp2->y )
1494 0 : return( 1 );
1495 0 : else if ( bp1->y < bp2->y )
1496 0 : return( -1 );
1497 :
1498 0 : return( 0 );
1499 : }
1500 :
1501 0 : static int mkd_order_height(const void *_mkd1, const void *_mkd2) {
1502 0 : const struct mathkerndata *mkd1 = (const struct mathkerndata *) _mkd1;
1503 0 : const struct mathkerndata *mkd2 = (const struct mathkerndata *) _mkd2;
1504 0 : if ( mkd1->height > mkd2->height )
1505 0 : return( 1 );
1506 0 : else if ( mkd1->height < mkd2->height )
1507 0 : return( -1 );
1508 :
1509 0 : return( 0 );
1510 : }
1511 :
1512 0 : static int MKD_Parse(MathKernDlg *mkd) {
1513 : int i, cnt, j, k;
1514 : SplineSet *ss;
1515 : SplinePoint *sp;
1516 : BasePoint **bases;
1517 0 : int allzeroes = true;
1518 :
1519 0 : if ( mkd->cursc->mathkern==NULL )
1520 0 : mkd->cursc->mathkern = chunkalloc(sizeof(struct mathkern));
1521 :
1522 0 : if ( mkd->last_aspect==0 ) { /* Graphical view is current */
1523 0 : for ( i=0; i<4; ++i ) {
1524 0 : SplineChar *msc = &(&mkd->sc_topright)[i];
1525 0 : struct mathkernvertex *mkv = &(&mkd->cursc->mathkern->top_right)[i];
1526 :
1527 0 : for ( k=0; k<2; ++k ) {
1528 0 : cnt = 0;
1529 0 : for ( ss = msc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
1530 0 : for ( sp=ss->first ; ; ) {
1531 0 : if ( k )
1532 0 : bases[cnt] = &sp->me;
1533 0 : ++cnt;
1534 0 : if ( sp->next == NULL )
1535 0 : break;
1536 0 : sp = sp->next->to;
1537 0 : if ( sp == ss->first )
1538 0 : break;
1539 0 : }
1540 : }
1541 0 : if ( !k )
1542 0 : bases = malloc(cnt*sizeof(BasePoint *));
1543 : }
1544 0 : qsort(bases,cnt,sizeof(BasePoint *),bp_order_height);
1545 0 : if ( cnt>mkv->cnt ) {
1546 0 : mkv->mkd = realloc(mkv->mkd,cnt*sizeof(struct mathkernvertex));
1547 0 : memset(mkv->mkd+mkv->cnt,0,(cnt-mkv->cnt)*sizeof(struct mathkernvertex));
1548 : }
1549 0 : for ( j=0; j<cnt; ++j ) {
1550 0 : bases[j]->x = rint(bases[j]->x);
1551 0 : if ( !(i&1) ) bases[j]->x -= mkd->cursc->width;
1552 0 : if ( !(i&2) ) bases[j]->x -= mkd->cursc->italic_correction==TEX_UNDEF?0:mkd->cursc->italic_correction;
1553 0 : bases[j]->y = rint(bases[j]->y);
1554 : /* If we have a previous entry with this height retain the height dv */
1555 : /* If we have a previous entry with this height and width retain the width dv too */
1556 0 : for ( k=j; k<mkv->cnt; ++k )
1557 0 : if ( bases[j]->y == mkv->mkd[k].height )
1558 0 : break;
1559 0 : if ( k!=j ) {
1560 0 : DeviceTableFree(mkv->mkd[j].height_adjusts);
1561 0 : DeviceTableFree(mkv->mkd[j].kern_adjusts);
1562 0 : mkv->mkd[j].height_adjusts = mkv->mkd[j].kern_adjusts = NULL;
1563 : }
1564 0 : if ( k<mkv->cnt ) {
1565 0 : mkv->mkd[j].height_adjusts = mkv->mkd[k].height_adjusts;
1566 0 : if ( bases[j]->x == mkv->mkd[k].kern )
1567 0 : mkv->mkd[j].kern_adjusts = mkv->mkd[k].kern_adjusts;
1568 : else {
1569 0 : DeviceTableFree(mkv->mkd[k].kern_adjusts);
1570 0 : mkv->mkd[k].kern_adjusts = NULL;
1571 : }
1572 0 : if ( j!=k )
1573 0 : mkv->mkd[k].height_adjusts = mkv->mkd[k].kern_adjusts = NULL;
1574 : }
1575 0 : mkv->mkd[j].height = bases[j]->y;
1576 0 : mkv->mkd[j].kern = bases[j]->x;
1577 : }
1578 0 : for ( ; j<mkv->cnt; ++j ) {
1579 0 : DeviceTableFree(mkv->mkd[j].height_adjusts);
1580 0 : DeviceTableFree(mkv->mkd[j].kern_adjusts);
1581 0 : mkv->mkd[j].height_adjusts = mkv->mkd[j].kern_adjusts = NULL;
1582 : }
1583 0 : mkv->cnt = cnt;
1584 0 : free(bases);
1585 0 : if ( cnt!=0 )
1586 0 : allzeroes = false;
1587 : }
1588 : } else {
1589 : int low, high;
1590 : /* Parse the textual info */
1591 0 : for ( i=0; i<4; ++i ) {
1592 0 : GGadget *list = GWidgetGetControl(mkd->gw,CID_TopRight+i);
1593 0 : int rows, cols = GMatrixEditGetColCnt(list);
1594 0 : struct matrix_data *old = GMatrixEditGet(list,&rows);
1595 :
1596 0 : for ( j=0; j<rows; ++j ) {
1597 0 : if ( !DeviceTableOK(old[j*cols+2].u.md_str,&low,&high) ||
1598 0 : !DeviceTableOK(old[j*cols+3].u.md_str,&low,&high)) {
1599 0 : ff_post_error(_("Bad device table"), _("Bad device table for in row %d of %s"),
1600 : j, cornernames[i]);
1601 0 : return( false );
1602 : }
1603 : }
1604 : }
1605 0 : for ( i=0; i<4; ++i ) {
1606 0 : struct mathkernvertex *mkv = &(&mkd->cursc->mathkern->top_right)[i];
1607 0 : GGadget *list = GWidgetGetControl(mkd->gw,CID_TopRight+i);
1608 0 : int rows, cols = GMatrixEditGetColCnt(list);
1609 0 : struct matrix_data *old = GMatrixEditGet(list,&rows);
1610 :
1611 0 : for ( j=0; j<mkv->cnt; ++j ) {
1612 0 : DeviceTableFree(mkv->mkd[j].height_adjusts);
1613 0 : DeviceTableFree(mkv->mkd[j].kern_adjusts);
1614 0 : mkv->mkd[j].height_adjusts = mkv->mkd[j].kern_adjusts = NULL;
1615 : }
1616 0 : if ( rows>mkv->cnt ) {
1617 0 : mkv->mkd = realloc(mkv->mkd,rows*sizeof(struct mathkerndata));
1618 0 : memset(mkv->mkd+mkv->cnt,0,(rows-mkv->cnt)*sizeof(struct mathkerndata));
1619 : }
1620 0 : for ( j=0; j<rows; ++j ) {
1621 0 : mkv->mkd[j].height = old[j*cols+0].u.md_ival;
1622 0 : mkv->mkd[j].kern = old[j*cols+1].u.md_ival;
1623 0 : mkv->mkd[j].height_adjusts = DeviceTableParse(NULL,old[j*cols+2].u.md_str);
1624 0 : mkv->mkd[j].kern_adjusts = DeviceTableParse(NULL,old[j*cols+3].u.md_str);
1625 : }
1626 0 : qsort(mkv->mkd,rows,sizeof(struct mathkerndata),mkd_order_height);
1627 0 : mkv->cnt = rows;
1628 0 : if ( rows!=0 )
1629 0 : allzeroes=false;
1630 : }
1631 : }
1632 0 : if ( allzeroes ) {
1633 0 : MathKernFree(mkd->cursc->mathkern);
1634 0 : mkd->cursc->mathkern = NULL;
1635 : }
1636 : /* The only potential error is two entries with the same height, and I don't */
1637 : /* check for that */
1638 0 : return( true );
1639 : }
1640 :
1641 0 : static int MKD_AspectChange(GGadget *g, GEvent *e) {
1642 0 : if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
1643 0 : MathKernDlg *mkd = (MathKernDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1644 0 : int new_aspect = GTabSetGetSel(g);
1645 :
1646 0 : if ( new_aspect == mkd->last_aspect )
1647 0 : return( true );
1648 :
1649 0 : GGadgetSetEnabled(mkd->mb,new_aspect==0);
1650 :
1651 0 : if ( new_aspect==0 ) {
1652 : /* We are moving from textual to graphical. Parse text, clear old */
1653 : /* points, set new points */
1654 : } else {
1655 : /* We are moving from graphical to textual. */
1656 0 : if ( !mkd->saved_mathkern ) {
1657 0 : mkd->orig_mathkern = MathKernCopy(mkd->cursc->mathkern);
1658 0 : mkd->saved_mathkern = true;
1659 : }
1660 : }
1661 0 : MKD_Parse(mkd);
1662 0 : mkd->last_aspect = new_aspect;
1663 0 : MKDFillup(mkd,mkd->cursc);
1664 : }
1665 0 : return( true );
1666 : }
1667 :
1668 0 : static int MathKernD_GlyphChanged(GGadget *g, GEvent *e) {
1669 0 : MathKernDlg *mkd = (MathKernDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1670 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1671 0 : GTextInfo *sel = GGadgetGetListItemSelected(g);
1672 :
1673 0 : if ( sel!=NULL && MKD_Parse(mkd)) {
1674 0 : SplineChar *sc = sel->userdata;
1675 0 : MKDFillupRefresh(mkd, sc);
1676 : }
1677 : }
1678 0 : return( true );
1679 : }
1680 :
1681 0 : static int MathKernD_Cancel(GGadget *g, GEvent *e) {
1682 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1683 0 : MathKernDlg *mkd = (MathKernDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1684 0 : if ( mkd->saved_mathkern ) {
1685 0 : MathKernFree(mkd->cursc->mathkern);
1686 0 : mkd->cursc->mathkern = mkd->orig_mathkern;
1687 : }
1688 0 : MKD_DoClose(((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1689 : }
1690 0 : return( true );
1691 : }
1692 :
1693 0 : static int MathKernD_OK(GGadget *g, GEvent *e) {
1694 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1695 0 : MathKernDlg *mkd = (MathKernDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1696 0 : if ( MKD_Parse(mkd) ) {
1697 0 : MathKernFree(mkd->orig_mathkern);
1698 0 : mkd->orig_mathkern = NULL;
1699 0 : mkd->saved_mathkern = false;
1700 0 : MKD_DoClose( (struct cvcontainer *) mkd );
1701 : }
1702 : }
1703 0 : return( true );
1704 : }
1705 :
1706 0 : static int MKD_Can_Navigate(struct cvcontainer *cvc, enum nav_type type) {
1707 0 : return( true );
1708 : }
1709 :
1710 0 : static int MKD_Can_Open(struct cvcontainer *cvc) {
1711 0 : return( false );
1712 : }
1713 :
1714 0 : static void MKD_Do_Navigate(struct cvcontainer *cvc, enum nav_type type) {
1715 0 : MathKernDlg *mkd = ( MathKernDlg * ) cvc;
1716 0 : SplineChar *sc = NULL;
1717 : int pos;
1718 0 : GGadget *list = GWidgetGetControl(mkd->gw,CID_Glyph);
1719 : int32 rows;
1720 : GTextInfo **tis;
1721 :
1722 0 : if ( !MKD_Parse(mkd))
1723 0 : return;
1724 0 : MathKernFree(mkd->orig_mathkern);
1725 0 : mkd->orig_mathkern = NULL;
1726 0 : mkd->saved_mathkern = false;
1727 :
1728 0 : if ( type == nt_goto ) {
1729 0 : SplineFont *sf = mkd->cursc->parent;
1730 0 : int enc = GotoChar(sf,sf->fv->map,NULL);
1731 0 : if ( enc==-1 || sf->fv->map->map[enc]==-1 || (sc = sf->glyphs[ sf->fv->map->map[enc] ])==NULL )
1732 0 : return;
1733 0 : if ( sc->mathkern==NULL )
1734 0 : MKD_SetGlyphList(mkd,sc);
1735 0 : } else if ( type == nt_next || type == nt_nextdef ) {
1736 0 : tis = GGadgetGetList(list,&rows);
1737 0 : for ( pos=rows-1; pos>=0; --pos )
1738 0 : if ( tis[pos]->selected )
1739 0 : break;
1740 0 : ++pos;
1741 0 : if ( pos==rows )
1742 0 : return;
1743 0 : sc = tis[pos]->userdata;
1744 : } else {
1745 0 : tis = GGadgetGetList(list,&rows);
1746 0 : for ( pos=rows-1; pos>=0; --pos )
1747 0 : if ( tis[pos]->selected )
1748 0 : break;
1749 0 : if ( pos<=0 )
1750 0 : return;
1751 0 : --pos;
1752 0 : sc = tis[pos]->userdata;
1753 : }
1754 0 : MKDFillupRefresh(mkd,sc);
1755 : }
1756 :
1757 0 : static SplineFont *SF_Of_MKD(struct cvcontainer *foo) {
1758 0 : return( NULL );
1759 : }
1760 :
1761 : struct cvcontainer_funcs mathkern_funcs = {
1762 : cvc_mathkern,
1763 : (void (*) (struct cvcontainer *cvc,CharViewBase *cv)) MKDMakeActive,
1764 : (void (*) (struct cvcontainer *cvc,void *)) MKDChar,
1765 : MKD_Can_Navigate,
1766 : MKD_Do_Navigate,
1767 : MKD_Can_Open,
1768 : MKD_DoClose,
1769 : SF_Of_MKD
1770 : };
1771 :
1772 0 : static void MKDInit(MathKernDlg *mkd,SplineChar *sc) {
1773 : int i;
1774 :
1775 0 : memset(mkd,0,sizeof(*mkd));
1776 0 : mkd->base.funcs = &mathkern_funcs;
1777 :
1778 0 : for ( i=0; i<4; ++i ) {
1779 0 : SplineChar *msc = &(&mkd->sc_topright)[i];
1780 0 : CharView *mcv = &(&mkd->cv_topright)[i];
1781 0 : msc->orig_pos = i;
1782 0 : msc->unicodeenc = -1;
1783 0 : msc->name = i==0 ? _("TopRight") :
1784 0 : i==1 ? _("TopLeft") :
1785 0 : i==2 ? _("BottomRight"):
1786 : _("BottomLeft");
1787 0 : msc->parent = &mkd->dummy_sf;
1788 0 : msc->layer_cnt = 2;
1789 0 : msc->layers = calloc(2,sizeof(Layer));
1790 0 : LayerDefault(&msc->layers[0]);
1791 0 : LayerDefault(&msc->layers[1]);
1792 0 : mkd->chars[i] = msc;
1793 :
1794 0 : mcv->b.sc = msc;
1795 0 : mcv->b.layerheads[dm_fore] = &msc->layers[ly_fore];
1796 0 : mcv->b.layerheads[dm_back] = &msc->layers[ly_back];
1797 0 : mcv->b.layerheads[dm_grid] = &mkd->dummy_sf.grid;
1798 0 : mcv->b.drawmode = dm_fore;
1799 0 : mcv->b.container = (struct cvcontainer *) mkd;
1800 0 : mcv->inactive = i!=0;
1801 : }
1802 0 : mkd->dummy_sf.glyphs = mkd->chars;
1803 0 : mkd->dummy_sf.glyphcnt = mkd->dummy_sf.glyphmax = 4;
1804 0 : mkd->dummy_sf.pfminfo.fstype = -1;
1805 0 : mkd->dummy_sf.pfminfo.stylemap = -1;
1806 0 : mkd->dummy_sf.fontname = mkd->dummy_sf.fullname = mkd->dummy_sf.familyname = "dummy";
1807 0 : mkd->dummy_sf.weight = "Medium";
1808 0 : mkd->dummy_sf.origname = "dummy";
1809 0 : mkd->dummy_sf.ascent = sc->parent->ascent;
1810 0 : mkd->dummy_sf.descent = sc->parent->descent;
1811 0 : mkd->dummy_sf.layers = mkd->layerinfo;
1812 0 : mkd->dummy_sf.layer_cnt = 2;
1813 0 : mkd->layerinfo[ly_back].order2 = sc->layers[ly_back].order2;
1814 0 : mkd->layerinfo[ly_back].name = _("Back");
1815 0 : mkd->layerinfo[ly_fore].order2 = sc->layers[ly_fore].order2;
1816 0 : mkd->layerinfo[ly_fore].name = _("Fore");
1817 0 : mkd->dummy_sf.grid.order2 = sc->layers[ly_back].order2;
1818 0 : mkd->dummy_sf.anchor = NULL;
1819 :
1820 0 : mkd->dummy_sf.fv = (FontViewBase *) &mkd->dummy_fv;
1821 0 : mkd->dummy_fv.b.active_layer = ly_fore;
1822 0 : mkd->dummy_fv.b.sf = &mkd->dummy_sf;
1823 0 : mkd->dummy_fv.b.selected = mkd->sel;
1824 0 : mkd->dummy_fv.cbw = mkd->dummy_fv.cbh = default_fv_font_size+1;
1825 0 : mkd->dummy_fv.magnify = 1;
1826 :
1827 0 : mkd->dummy_fv.b.map = &mkd->dummy_map;
1828 0 : mkd->dummy_map.map = mkd->map;
1829 0 : mkd->dummy_map.backmap = mkd->backmap;
1830 0 : mkd->dummy_map.enccount = mkd->dummy_map.encmax = mkd->dummy_map.backmax = 4;
1831 0 : mkd->dummy_map.enc = &custom;
1832 0 : }
1833 :
1834 0 : void MathKernDialog(SplineChar *sc,int def_layer) {
1835 : MathKernDlg mkd;
1836 : GRect pos;
1837 : GWindow gw;
1838 : GWindowAttrs wattrs;
1839 : GGadgetCreateData gcd[6], boxes[4], *harray[8], *varray[5], *garray[5];
1840 : GGadgetCreateData cgcd[4][2], tabsetgcd[2];
1841 : GTextInfo label[6];
1842 : GTabInfo aspects[3], corners[5];
1843 : FontRequest rq;
1844 : int as, ds, ld;
1845 : int i,k;
1846 : static GFont *mathfont = NULL, *mathbold=NULL;
1847 :
1848 0 : MathInit();
1849 0 : MKDInit( &mkd, sc );
1850 0 : mkd.def_layer = def_layer;
1851 :
1852 0 : memset(&wattrs,0,sizeof(wattrs));
1853 0 : wattrs.mask = wam_events|wam_cursor|wam_isdlg|wam_restrict|wam_undercursor|wam_utf8_wtitle;
1854 0 : wattrs.is_dlg = true;
1855 0 : wattrs.restrict_input_to_me = 1;
1856 0 : wattrs.undercursor = 1;
1857 0 : wattrs.event_masks = -1;
1858 0 : wattrs.cursor = ct_pointer;
1859 0 : wattrs.utf8_window_title = _("Math Kerning");
1860 0 : pos.width = 600;
1861 0 : pos.height = 400;
1862 0 : mkd.gw = gw = GDrawCreateTopWindow(NULL,&pos,mkd_e_h,&mkd.cv_topright,&wattrs);
1863 :
1864 0 : if ( mathfont==NULL ) {
1865 0 : memset(&rq,0,sizeof(rq));
1866 0 : rq.utf8_family_name = SANS_UI_FAMILIES;
1867 0 : rq.point_size = 12;
1868 0 : rq.weight = 400;
1869 0 : mathfont = GDrawInstanciateFont(NULL,&rq);
1870 0 : mathfont = GResourceFindFont("Math.Font",mathfont);
1871 :
1872 0 : GDrawDecomposeFont(mathfont, &rq);
1873 0 : rq.weight = 700;
1874 0 : mathbold = GDrawInstanciateFont(NULL,&rq);
1875 0 : mathbold = GResourceFindFont("Math.BoldFont",mathbold);
1876 : }
1877 0 : mkd.plain = mathfont;
1878 0 : mkd.bold = mathbold;
1879 0 : GDrawWindowFontMetrics(mkd.gw,mkd.plain,&as,&ds,&ld);
1880 0 : mkd.fh = as+ds; mkd.as = as;
1881 :
1882 0 : memset(&label,0,sizeof(label));
1883 0 : memset(&gcd,0,sizeof(gcd));
1884 0 : memset(&boxes,0,sizeof(boxes));
1885 0 : memset(&aspects,'\0',sizeof(aspects));
1886 0 : memset(&corners,'\0',sizeof(corners));
1887 0 : memset(&cgcd,0,sizeof(cgcd));
1888 0 : memset(&tabsetgcd,0,sizeof(tabsetgcd));
1889 :
1890 0 : for ( k=0; k<4; ++k ) {
1891 0 : cgcd[k][0].gd.flags = gg_visible | gg_enabled;
1892 0 : cgcd[k][0].gd.u.matrix = &mi_mathkern;
1893 0 : cgcd[k][0].gd.cid = CID_TopRight+k;
1894 0 : cgcd[k][0].creator = GMatrixEditCreate;
1895 :
1896 0 : corners[k].text = (unichar_t *) cornernames[k];
1897 0 : corners[k].text_is_1byte = true;
1898 0 : corners[k].gcd = cgcd[k];
1899 : }
1900 :
1901 0 : tabsetgcd[0].gd.flags = gg_visible|gg_enabled|gg_tabset_vert ;
1902 0 : tabsetgcd[0].gd.u.tabs = corners;
1903 0 : tabsetgcd[0].gd.cid = CID_Corners;
1904 : /*tabsetgcd[0].gd.handle_controlevent = MKD_AspectChange;*/
1905 0 : tabsetgcd[0].creator = GTabSetCreate;
1906 :
1907 0 : k = 0;
1908 0 : gcd[k].gd.flags = gg_visible|gg_enabled ;
1909 0 : gcd[k].gd.pos.height = 18; gcd[k].gd.pos.width = 20;
1910 0 : gcd[k++].creator = GSpacerCreate;
1911 :
1912 0 : aspects[0].text = (unichar_t *) _("Graphical");
1913 0 : aspects[0].text_is_1byte = true;
1914 0 : aspects[0].gcd = NULL;
1915 :
1916 0 : aspects[1].text = (unichar_t *) _("Textual");
1917 0 : aspects[1].text_is_1byte = true;
1918 0 : aspects[1].gcd = tabsetgcd;
1919 :
1920 0 : gcd[k].gd.flags = gg_visible|gg_enabled ;
1921 0 : gcd[k].gd.u.tabs = aspects;
1922 0 : gcd[k].gd.cid = CID_Tabs;
1923 0 : gcd[k].gd.handle_controlevent = MKD_AspectChange;
1924 0 : gcd[k++].creator = GTabSetCreate;
1925 :
1926 0 : gcd[k].gd.flags = gg_visible|gg_enabled ;
1927 0 : gcd[k].gd.cid = CID_Glyph;
1928 0 : gcd[k].gd.handle_controlevent = MathKernD_GlyphChanged;
1929 0 : gcd[k++].creator = GListButtonCreate;
1930 :
1931 0 : label[k].text = (unichar_t *) _("_OK");
1932 0 : label[k].text_is_1byte = true;
1933 0 : label[k].text_in_resource = true;
1934 0 : gcd[k].gd.label = &label[k];
1935 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_default;
1936 0 : gcd[k].gd.handle_controlevent = MathKernD_OK;
1937 0 : gcd[k++].creator = GButtonCreate;
1938 :
1939 0 : label[k].text = (unichar_t *) _("_Done");
1940 0 : label[k].text_is_1byte = true;
1941 0 : label[k].text_in_resource = true;
1942 0 : gcd[k].gd.label = &label[k];
1943 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_cancel;
1944 0 : gcd[k].gd.handle_controlevent = MathKernD_Cancel;
1945 0 : gcd[k++].creator = GButtonCreate;
1946 :
1947 0 : harray[0] = GCD_Glue; harray[1] = &gcd[k-2]; harray[2] = GCD_Glue;
1948 0 : harray[3] = GCD_Glue; harray[4] = &gcd[k-1]; harray[5] = GCD_Glue;
1949 0 : harray[6] = NULL;
1950 :
1951 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
1952 0 : boxes[2].gd.u.boxelements = harray;
1953 0 : boxes[2].creator = GHBoxCreate;
1954 :
1955 0 : garray[0] = &gcd[k-3]; garray[1] = GCD_Glue; garray[2] = NULL;
1956 0 : boxes[3].gd.flags = gg_enabled|gg_visible;
1957 0 : boxes[3].gd.u.boxelements = garray;
1958 0 : boxes[3].creator = GHBoxCreate;
1959 :
1960 0 : varray[0] = &gcd[0];
1961 0 : varray[1] = &gcd[1];
1962 0 : varray[2] = &boxes[3];
1963 0 : varray[3] = &boxes[2];
1964 0 : varray[4] = NULL;
1965 :
1966 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
1967 0 : boxes[0].gd.u.boxelements = varray;
1968 0 : boxes[0].gd.cid = CID_TopBox;
1969 0 : boxes[0].creator = GVBoxCreate;
1970 :
1971 0 : GGadgetsCreate(gw,boxes);
1972 :
1973 0 : mkd.cvparent_w = GTabSetGetSubwindow(gcd[1].ret,0);
1974 0 : GDrawSetEH(mkd.cvparent_w,mkd_sub_e_h);
1975 0 : MKDCharViewInits(&mkd);
1976 :
1977 0 : MKD_SetGlyphList(&mkd, sc);
1978 0 : MKDFillup( &mkd, sc );
1979 :
1980 0 : GHVBoxSetExpandableRow(boxes[0].ret,1);
1981 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
1982 0 : GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
1983 0 : GGadgetResize(boxes[0].ret,pos.width,pos.height);
1984 :
1985 0 : mkd.button_height = GDrawPointsToPixels(gw,60);
1986 0 : GDrawResize(gw,1000,400); /* Force a resize event */
1987 :
1988 0 : GDrawSetVisible(mkd.gw,true);
1989 :
1990 0 : while ( !mkd.done )
1991 0 : GDrawProcessOneEvent(NULL);
1992 :
1993 0 : for ( i=0; i<4; ++i ) {
1994 0 : CharView *cv = &mkd.cv_topright + i;
1995 0 : if ( cv->backimgs!=NULL ) {
1996 0 : GDrawDestroyWindow(cv->backimgs);
1997 0 : cv->backimgs = NULL;
1998 : }
1999 0 : CVPalettesHideIfMine(cv);
2000 : }
2001 0 : GDrawDestroyWindow(mkd.gw);
2002 0 : }
|