LCOV - code coverage report
Current view: top level - fontforgeexe - math.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 1258 0.0 %
Date: 2017-08-04 Functions: 0 53 0.0 %

          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 : }

Generated by: LCOV version 1.10