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

          Line data    Source code
       1             : /* Copyright (C) 2003-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "dumppfa.h"
      28             : #include "encoding.h"
      29             : #include "fontforgeui.h"
      30             : #include "fvfonts.h"
      31             : #include "macenc.h"
      32             : #include "mm.h"
      33             : #include "mem.h"
      34             : #include "parsettf.h"
      35             : #include "psread.h"
      36             : #include "sfd.h"
      37             : #include "splinefill.h"
      38             : #include "splineutil.h"
      39             : #include "splineutil2.h"
      40             : #include "tottfvar.h"
      41             : #include <ustring.h>
      42             : #include <math.h>
      43             : #include <gkeysym.h>
      44             : #include <locale.h>
      45             : #include <utype.h>
      46             : #include "ttf.h"
      47             : #include "mm.h"
      48             : 
      49             : /* As far as I can tell, the CDV in AdobeSansMM is half gibberish */
      50             : /* This is disturbing */
      51             : /* But at least the CDV in Type1_supp.pdf for Myriad appears correct */
      52             : static char *standard_cdvs[5] = {
      53             : /* 0 axes? Impossible */
      54             :     "{}",
      55             : /* 1 axis */
      56             :     "{\n"
      57             :     "  1 1 index sub 2 1 roll\n"
      58             :     "  0 index 2 1 roll\n"
      59             :     "  pop\n"
      60             :     "}",
      61             : /* 2 axes */
      62             :     "{\n"
      63             :     "  1 2 index sub 1 2 index sub mul 3 1 roll\n"
      64             :     "  1 index 1 2 index sub mul 3 1 roll\n"
      65             :     "  1 2 index sub 1 index mul 3 1 roll\n"
      66             :     "  1 index 1 index mul 3 1 roll\n"
      67             :     "  pop pop\n"
      68             :     "}",
      69             : /* 3 axes */
      70             :     "{\n"
      71             :     "  1 3 index sub 1 3 index sub mul 1 2 index sub mul 4 1 roll\n"
      72             :     "  2 index 1 3 index sub mul 1 2 index sub mul 4 1 roll\n"
      73             :     "  1 3 index sub 2 index mul 1 2 index sub mul 4 1 roll\n"
      74             :     "  2 index 2 index mul 1 2 index sub mul 4 1 roll\n"
      75             :     "  1 3 index sub 1 3 index sub mul 1 index mul 4 1 roll\n"
      76             :     "  2 index 1 3 index sub mul 1 index mul 4 1 roll\n"
      77             :     "  1 3 index sub 2 index mul 1 index mul 4 1 roll\n"
      78             :     "  2 index 2 index mul 1 index mul 4 1 roll\n"
      79             :     "  pop pop pop\n"
      80             :     "}",
      81             : /* 4 axes */
      82             : /* This requires too big a string. We must build it at runtime */
      83             :     NULL
      84             : };
      85             : static char *cdv_4axis[3] = {
      86             :     "{\n"
      87             :     "  1 4 index sub 1 4 index sub mul 1 3 index sub mul 1 2 index sub mul 5 1 roll\n"
      88             :     "  3 index 1 4 index sub mul 1 3 index sub mul 1 2 index sub mul 5 1 roll\n"
      89             :     "  1 4 index sub 3 index mul 1 3 index sub mul 1 2 index sub mul 5 1 roll\n"
      90             :     "  3 index 3 index mul 1 3 index sub mul 1 2 index sub mul 5 1 roll\n"
      91             :     "  1 4 index sub 1 4 index sub mul 2 index mul 1 2 index sub mul 5 1 roll\n"
      92             :     "  3 index 1 4 index sub mul 2 index mul 1 2 index sub mul 5 1 roll\n",
      93             :     "  1 4 index sub 3 index mul 2 index mul 1 2 index sub mul 5 1 roll\n"
      94             :     "  3 index 3 index mul 2 index mul 1 2 index sub mul 5 1 roll\n"
      95             :     "  1 4 index sub 1 4 index sub mul 1 3 index sub mul 1 index mul 5 1 roll\n"
      96             :     "  3 index 1 4 index sub mul 1 3 index sub mul 1 index mul 5 1 roll\n"
      97             :     "  1 4 index sub 3 index mul 1 3 index sub mul 1 index mul 5 1 roll\n",
      98             :     "  3 index 3 index mul 1 3 index sub mul 1 index mul 5 1 roll\n"
      99             :     "  1 4 index sub 1 4 index sub mul 2 index mul 1 index mul 5 1 roll\n"
     100             :     "  3 index 1 4 index sub mul 2 index mul 1 index mul 5 1 roll\n"
     101             :     "  1 4 index sub 3 index mul 2 index mul 1 index mul 5 1 roll\n"
     102             :     "  3 index 3 index mul 2 index mul 1 index mul 5 1 roll\n"
     103             :     "  pop pop pop pop\n"
     104             :     "}"
     105             : };
     106             : 
     107             : static char *axistablab[] = { N_("Axis 1"), N_("Axis 2"), N_("Axis 3"), N_("Axis 4") };
     108             : 
     109           0 : static int ExecConvertDesignVector(real *designs, int dcnt, char *ndv, char *cdv,
     110             :         real *stack) {
     111             :     char *temp, dv[101];
     112             :     int j, len, cnt;
     113             : 
     114             :     /* PostScript parses things in "C" locale too */
     115             :     locale_t tmplocale; locale_t oldlocale; // Declare temporary locale storage.
     116           0 :     switch_to_c_locale(&tmplocale, &oldlocale); // Switch to the C locale temporarily and cache the old locale.
     117           0 :     len = 0;
     118           0 :     for ( j=0; j<dcnt; ++j ) {
     119           0 :         sprintf(dv+len, "%g ", (double) designs[j]);
     120           0 :         len += strlen(dv+len);
     121             :     }
     122           0 :     switch_to_old_locale(&tmplocale, &oldlocale); // Switch to the cached locale.
     123             : 
     124           0 :     temp = malloc(len+strlen(ndv)+strlen(cdv)+20);
     125           0 :     strcpy(temp,dv);
     126             :     /*strcpy(temp+len++," ");*/               /* dv always will end in a space */
     127             : 
     128           0 :     while ( isspace(*ndv)) ++ndv;
     129           0 :     if ( *ndv=='{' )
     130           0 :         ++ndv;
     131           0 :     strcpy(temp+len,ndv);
     132           0 :     len += strlen(temp+len);
     133           0 :     while ( len>0 && (temp[len-1]==' '||temp[len-1]=='\n') ) --len;
     134           0 :     if ( len>0 && temp[len-1]=='}' ) --len;
     135             : 
     136           0 :     while ( isspace(*cdv)) ++cdv;
     137           0 :     if ( *cdv=='{' )
     138           0 :         ++cdv;
     139           0 :     strcpy(temp+len,cdv);
     140           0 :     len += strlen(temp+len);
     141           0 :     while ( len>0 && (temp[len-1]==' '||temp[len-1]=='\n') ) --len;
     142           0 :     if ( len>0 && temp[len-1]=='}' ) --len;
     143             : 
     144           0 :     cnt = EvaluatePS(temp,stack,MmMax);
     145           0 :     free(temp);
     146           0 : return( cnt );
     147             : }
     148             : 
     149           0 : static int StandardPositions(MMSet *mm,int instance_count, int axis_count,int isapple) {
     150             :     int i,j,factor,v;
     151             : 
     152           0 :     if ( !isapple ) {
     153           0 :         for ( i=0; i<instance_count; ++i ) {
     154           0 :             for ( j=0; j<axis_count; ++j )
     155           0 :                 if ( mm->positions[i*mm->axis_count+j]!= ( (i&(1<<j)) ? 1 : 0 ))
     156           0 :     return( false );
     157             :         }
     158             :     } else {
     159           0 :         for ( i=0; i<instance_count; ++i ) {
     160           0 :             factor = 1;
     161           0 :             for ( j=0; j<axis_count; ++j ) {
     162           0 :                 v = (i/factor)%3 -1;
     163           0 :                 if ( mm->positions[i*mm->axis_count+j]!= v )
     164           0 : return( false );
     165           0 :                 factor *= 3;
     166             :             }
     167             :         }
     168             :     }
     169           0 : return( true );
     170             : }
     171             : 
     172           0 : static int OrderedPositions(MMSet *mm,int instance_count, int isapple) {
     173             :     /* For a 1 axis system, check that the positions are ordered */
     174             :     int i;
     175             : 
     176           0 :     if ( mm->positions[0]!=isapple?-1:0 )            /* must start at 0 */
     177           0 : return( false );
     178           0 :     if ( mm->positions[(instance_count-1)*4]!=1 )    /* and end at 1 */
     179           0 : return( false );
     180           0 :     for ( i=1; i<mm->instance_count; ++i )
     181           0 :         if ( mm->positions[i*mm->axis_count]<=mm->positions[(i-1)*mm->axis_count] )
     182           0 : return( false );
     183             : 
     184           0 : return( true );
     185             : }
     186             : 
     187           0 : static unichar_t *MMDesignCoords(MMSet *mm) {
     188             :     char buffer[80], *pt;
     189             :     int i;
     190             :     real axiscoords[4];
     191             : 
     192           0 :     if ( mm->instance_count!=(1<<mm->axis_count) ||
     193           0 :             !StandardPositions(mm,mm->instance_count,mm->axis_count,false))
     194           0 : return( uc_copy(""));
     195           0 :     MMWeightsUnMap(mm->defweights,axiscoords,mm->axis_count);
     196           0 :     pt = buffer;
     197           0 :     for ( i=0; i<mm->axis_count; ++i ) {
     198           0 :         sprintf( pt,"%g ", (double) MMAxisUnmap(mm,i,axiscoords[i]));
     199           0 :         pt += strlen(pt);
     200             :     }
     201           0 :     pt[-1] = ' ';
     202           0 : return( uc_copy( buffer ));
     203             : }
     204             : 
     205           0 : static real DoDelta(int16 **deltas,int pt,int is_y,real *blends,int instance_count) {
     206           0 :     real diff = 0;
     207             :     int j;
     208             : 
     209           0 :     for ( j=0; j<instance_count; ++j ) {
     210           0 :         if ( blends[j]!=0 && deltas[2*j+is_y]!=NULL )
     211           0 :             diff += blends[j]*deltas[2*j+is_y][pt];
     212             :     }
     213           0 : return( diff );
     214             : }
     215             : 
     216           0 : static void DistortChar(SplineFont *sf,MMSet *mm,int gid,real *blends) {
     217             :     int i,j,ptcnt;
     218             :     int16 **deltas;
     219             :     SplineSet *ss;
     220             :     SplinePoint *sp;
     221             :     RefChar *ref;
     222           0 :     SplineChar *sc = sf->glyphs[gid];
     223             :     Spline *s, *first;
     224             : 
     225           0 :     if ( sc==NULL )
     226           0 : return;
     227           0 :     deltas = SCFindDeltas(mm,gid,&ptcnt);
     228           0 :     if ( deltas==NULL )
     229           0 : return;
     230             :     /* I never delta the left side bearing or top */
     231           0 :     sc->width += DoDelta(deltas,ptcnt-3,0,blends,mm->instance_count);
     232           0 :     sc->vwidth += DoDelta(deltas,ptcnt-1,1,blends,mm->instance_count);
     233           0 :     if ( sc->layers[ly_fore].refs!=NULL ) {
     234           0 :         for ( i=0,ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next, ++i ) {
     235           0 :             ref->transform[4] += DoDelta(deltas,i,0,blends,mm->instance_count);
     236           0 :             ref->transform[5] += DoDelta(deltas,i,1,blends,mm->instance_count);
     237             :         }
     238             :     } else {
     239           0 :         for ( ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
     240           0 :             for ( sp=ss->first;; ) {
     241           0 :                 if ( sp->ttfindex!=0xffff ) {
     242           0 :                     sp->me.x += DoDelta(deltas,sp->ttfindex,0,blends,mm->instance_count);
     243           0 :                     sp->me.y += DoDelta(deltas,sp->ttfindex,1,blends,mm->instance_count);
     244             :                 }
     245           0 :                 if ( sp->nextcpindex!=0xffff ) {
     246           0 :                     sp->nextcp.x += DoDelta(deltas,sp->nextcpindex,0,blends,mm->instance_count);
     247           0 :                     sp->nextcp.y += DoDelta(deltas,sp->nextcpindex,1,blends,mm->instance_count);
     248             :                 } else
     249           0 :                     sp->nextcp = sp->me;
     250           0 :                 if ( sp->next!=NULL )
     251           0 :                     sp->next->to->prevcp = sp->nextcp;
     252           0 :                 if ( sp->next==NULL )
     253           0 :             break;
     254           0 :                 sp = sp->next->to;
     255           0 :                 if ( sp==ss->first )
     256           0 :             break;
     257           0 :             }
     258           0 :             for ( sp=ss->first;; ) {
     259           0 :                 if ( sp->ttfindex==0xffff ) {
     260           0 :                     sp->me.x = (sp->prevcp.x+sp->nextcp.x)/2;
     261           0 :                     sp->me.y = (sp->prevcp.y+sp->nextcp.y)/2;
     262             :                 }
     263           0 :                 if ( sp->next==NULL )
     264           0 :             break;
     265           0 :                 sp = sp->next->to;
     266           0 :                 if ( sp==ss->first )
     267           0 :             break;
     268           0 :             }
     269           0 :             first = NULL;
     270           0 :             for ( s=ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
     271           0 :                 SplineRefigure(s);
     272           0 :                 if ( first==NULL ) first = s;
     273             :             }
     274             :         }
     275             :     }
     276           0 :     for ( j=0; j<2*mm->instance_count; ++j )
     277           0 :         free( deltas[j]);
     278           0 :     free(deltas);
     279             : }
     280             : 
     281           0 : static void DistortCvt(struct ttf_table *cvt,MMSet *mm,real *blends) {
     282             :     int i,j,ptcnt;
     283             :     real diff;
     284             :     int16 **deltas;
     285             : 
     286           0 :     deltas = CvtFindDeltas(mm,&ptcnt);
     287           0 :     if ( deltas==NULL )
     288           0 : return;
     289           0 :     for ( i=0; i<ptcnt; ++i ) {
     290           0 :         diff = 0;
     291           0 :         for ( j=0; j<mm->instance_count; ++j ) {
     292           0 :             if ( blends[j]!=0 && deltas[j]!=NULL )
     293           0 :                 diff += blends[j]*deltas[j][i];
     294             :         }
     295           0 :         memputshort(cvt->data,2*i,memushort(cvt->data,cvt->len,2*i)+rint(diff));
     296             :     }
     297           0 :     for ( j=0; j<mm->instance_count; ++j )
     298           0 :         free( deltas[j]);
     299           0 :     free(deltas);
     300             : }
     301             : 
     302           0 : static void MakeAppleBlend(FontView *fv,MMSet *mm,real *blends,real *normalized) {
     303           0 :     SplineFont *base = mm->normal;
     304           0 :     SplineFont *sf = _MMNewFont(mm,-2,base->familyname,normalized);
     305             :     int i;
     306           0 :     struct ttf_table *tab, *cvt=NULL, *last=NULL, *cur;
     307             :     RefChar *ref;
     308             : 
     309           0 :     sf->mm = NULL;
     310           0 :     for ( i=0; i<base->glyphcnt && i<sf->glyphcnt; ++i ) if ( base->glyphs[i]!=NULL ) {
     311           0 :         sf->glyphs[i] = SplineCharCopy(base->glyphs[i],base,NULL);
     312           0 :         for ( ref=sf->glyphs[i]->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
     313           0 :             ref->sc = NULL;
     314           0 :         sf->glyphs[i]->orig_pos = i;
     315           0 :         DistortChar(sf,mm,i,blends);
     316             :     }
     317           0 :     for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
     318           0 :         ttfFixupRef(sf->glyphs,i);
     319           0 :     for ( tab=base->ttf_tables; tab!=NULL; tab=tab->next ) {
     320           0 :         cur = chunkalloc(sizeof(struct ttf_table));
     321           0 :         cur->tag = tab->tag;
     322           0 :         cur->len = tab->len;
     323           0 :         cur->data = malloc(tab->len);
     324           0 :         memcpy(cur->data,tab->data,tab->len);
     325           0 :         if ( cur->tag==CHR('c','v','t',' '))
     326           0 :             cvt = cur;
     327           0 :         if ( last==NULL )
     328           0 :             sf->ttf_tables = cur;
     329             :         else
     330           0 :             last->next = cur;
     331           0 :         last = cur;
     332             :     }
     333           0 :     if ( cvt!=NULL )
     334           0 :         DistortCvt(cvt,mm,blends);
     335             :     /* I don't know how to blend kerns */
     336             :     /* Apple's Skia has 5 kerning classes (one for the base font and one for */
     337             :     /*  some of the instances) and the classes have different glyph classes */
     338             :     /* I can't make a kern class out of them. I suppose I could generate a bunch */
     339             :     /*  of kern pairs, but ug. */
     340             :     /* Nor is it clear whether the kerning info is a delta or not */
     341             : 
     342           0 :     sf->changed = true;
     343           0 :     EncMapFree(sf->map);
     344           0 :     sf->map = EncMapFromEncoding(sf,fv->b.map->enc);
     345           0 :     FontViewCreate(sf,false);
     346           0 : }
     347             : 
     348             : struct mmcb {
     349             :     int done;
     350             :     GWindow gw;
     351             :     MMSet *mm;
     352             :     FontView *fv;
     353             :     int tonew;
     354             : };
     355             : 
     356             : #define CID_Explicit            6001
     357             : #define CID_ByDesign            6002
     358             : #define CID_NewBlends           6003
     359             : #define CID_NewDesign           6004
     360             : #define CID_Knowns              6005
     361             : 
     362           0 : static GTextInfo *MMCB_KnownValues(MMSet *mm) {
     363           0 :     GTextInfo *ti = calloc(mm->named_instance_count+2,sizeof(GTextInfo));
     364             :     int i;
     365             : 
     366           0 :     ti[0].text = uc_copy(" --- ");
     367           0 :     ti[0].bg = ti[0].fg = COLOR_DEFAULT;
     368           0 :     for ( i=0; i<mm->named_instance_count; ++i ) {
     369           0 :         ti[i+1].text = (unichar_t *) PickNameFromMacName(mm->named_instances[i].names);
     370           0 :         ti[i+1].text_is_1byte = true;
     371           0 :         ti[i+1].bg = ti[i+1].fg = COLOR_DEFAULT;
     372             :     }
     373           0 : return( ti );
     374             : }
     375             : 
     376           0 : static int MMCB_PickedKnown(GGadget *g, GEvent *e) {
     377           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
     378           0 :         struct mmcb *mmcb = GDrawGetUserData(GGadgetGetWindow(g));
     379           0 :         int which = GGadgetGetFirstListSelectedItem(g);
     380             :         char buffer[24];
     381             :         int i;
     382             :         unichar_t *temp;
     383             : 
     384           0 :         --which;
     385           0 :         if ( which<0 )
     386           0 : return( true );
     387           0 :         for ( i=0; i<mmcb->mm->axis_count; ++i ) {
     388           0 :             sprintf( buffer, "%.4g", (double) mmcb->mm->named_instances[which].coords[i]);
     389           0 :             temp = uc_copy(buffer);
     390           0 :             GGadgetSetTitle(GWidgetGetControl(mmcb->gw,1000+i),temp);
     391           0 :             free(temp);
     392             :         }
     393             :     }
     394           0 : return( true );
     395             : }
     396             : 
     397           0 : static int MMCB_Changed(GGadget *g, GEvent *e) {
     398           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
     399           0 :         GWindow gw = GGadgetGetWindow(g);
     400           0 :         int explicitblends = GGadgetIsChecked(GWidgetGetControl(gw,CID_Explicit));
     401           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NewBlends),explicitblends);
     402           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NewDesign),!explicitblends);
     403             :     }
     404           0 : return( true );
     405             : }
     406             : 
     407           0 : static int GetWeights(GWindow gw, real blends[MmMax], MMSet *mm,
     408             :         int instance_count, int axis_count) {
     409           0 :     int explicitblends = GGadgetIsChecked(GWidgetGetControl(gw,CID_Explicit));
     410           0 :     const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(gw,
     411             :             explicitblends?CID_NewBlends:CID_NewDesign)), *upt;
     412             :     unichar_t *uend;
     413             :     int i;
     414             :     real sum;
     415             : 
     416           0 :     sum = 0;
     417           0 :     for ( i=0, upt = ret; i<instance_count && *upt; ++i ) {
     418           0 :         blends[i] = u_strtod(upt,&uend);
     419           0 :         sum += blends[i];
     420           0 :         if ( upt==uend )
     421           0 :     break;
     422           0 :         upt = uend;
     423           0 :         while ( *upt==',' || *upt==' ' ) ++upt;
     424             :     }
     425           0 :     if ( (explicitblends && i!=instance_count ) ||
     426           0 :             (!explicitblends && i!=axis_count ) ||
     427           0 :             *upt!='\0' ) {
     428           0 :         ff_post_error(_("Bad MM Weights"),_("Incorrect number of instances weights, or illegal numbers"));
     429           0 : return(false);
     430             :     }
     431           0 :     if ( explicitblends ) {
     432           0 :         if ( sum<.99 || sum>1.01 ) {
     433           0 :             ff_post_error(_("Bad MM Weights"),_("The weights for the default version of the font must sum to 1.0"));
     434           0 : return(false);
     435             :         }
     436             :     } else {
     437           0 :         i = ExecConvertDesignVector(blends, i, mm->ndv, mm->cdv,
     438             :                 blends);
     439           0 :         if ( i!=instance_count ) {
     440           0 :             ff_post_error(_("Bad MM Weights"),_("The results produced by applying the NormalizeDesignVector and ConvertDesignVector functions were not the results expected. You may need to change these functions"));
     441           0 : return(false);
     442             :         }
     443             :     }
     444           0 : return( true );
     445             : }
     446             : 
     447           0 : static int MMCB_OKApple(GGadget *g, GEvent *e) {
     448           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     449           0 :         struct mmcb *mmcb = GDrawGetUserData(GGadgetGetWindow(g));
     450             :         real newcoords[4];
     451           0 :         int i, j, k, err=false;
     452             :         real blends[AppleMmMax];
     453           0 :         MMSet *mm = mmcb->mm;
     454             : 
     455           0 :         for ( i=0; i<mm->axis_count; ++i )
     456           0 :             newcoords[i] = rint(GetReal8(mmcb->gw,1000+i,_(axistablab[i]),&err)*8096)/8096;
     457           0 :         if ( err )
     458           0 : return( true );
     459             :         /* Now normalize each */
     460           0 :         for ( i=0; i<mm->axis_count; ++i ) {
     461           0 :             for ( j=1; j<mm->axismaps[i].points; ++j ) {
     462           0 :                 if ( newcoords[i]<=mm->axismaps[i].designs[j] || j==mm->axismaps[i].points-1 ) {
     463           0 :                     if ( mm->axismaps[i].designs[j]==mm->axismaps[i].designs[j-1] )
     464           0 :                         newcoords[i] = mm->axismaps[i].blends[j];
     465             :                     else
     466           0 :                         newcoords[i] = mm->axismaps[i].blends[j-1] +
     467           0 :                                 (newcoords[i]-mm->axismaps[i].designs[j-1])/
     468           0 :                                 (mm->axismaps[i].designs[j]-mm->axismaps[i].designs[j-1]) *
     469           0 :                                 (mm->axismaps[i].blends[j]-mm->axismaps[i].blends[j-1]);
     470           0 :                     newcoords[i] = rint(8096*newcoords[i])/8096;        /* Apple's fixed numbers have a fair amount of rounding error */
     471           0 :             break;
     472             :                 }
     473             :             }
     474             :         }
     475             :         /* Now figure out the contribution of each design */
     476           0 :         for ( k=0; k<mm->instance_count; ++k ) {
     477           0 :             real factor = 1.0;
     478           0 :             for ( i=0; i<mm->axis_count; ++i ) {
     479           0 :                 if ( (newcoords[i]<=0 && mm->positions[k*mm->axis_count+i]>0) ||
     480           0 :                         (newcoords[i]>=0 && mm->positions[k*mm->axis_count+i]<0)) {
     481           0 :                     factor = 0;
     482           0 :             break;
     483             :                 }
     484           0 :                 if ( newcoords[i]==0 )
     485           0 :             continue;
     486           0 :                 if ( newcoords[i]<0 )
     487           0 :                     factor *= -newcoords[i];
     488             :                 else
     489           0 :                     factor *= newcoords[i];
     490             :             }
     491           0 :             blends[k] = factor;
     492             :         }
     493           0 :         MakeAppleBlend(mmcb->fv,mm,blends,newcoords);
     494           0 :         mmcb->done = true;
     495             :     }
     496           0 : return( true );
     497             : }
     498             : 
     499           0 : static int MMCB_OK(GGadget *g, GEvent *e) {
     500           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     501           0 :         struct mmcb *mmcb = GDrawGetUserData(GGadgetGetWindow(g));
     502             :         real blends[MmMax];
     503             : 
     504           0 :         if ( !GetWeights(mmcb->gw, blends, mmcb->mm, mmcb->mm->instance_count, mmcb->mm->axis_count))
     505           0 : return( true );
     506           0 :         MMCreateBlendedFont(mmcb->mm,(FontViewBase *) mmcb->fv,blends,mmcb->tonew );
     507             :     }
     508           0 : return( true );
     509             : }
     510             : 
     511           0 : static int MMCB_Cancel(GGadget *g, GEvent *e) {
     512           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     513           0 :         struct mmcb *mmcb = GDrawGetUserData(GGadgetGetWindow(g));
     514           0 :         mmcb->done = true;
     515             :     }
     516           0 : return( true );
     517             : }
     518             : 
     519           0 : static int mmcb_e_h(GWindow gw, GEvent *event) {
     520           0 :     if ( event->type==et_close ) {
     521           0 :         struct mmcb *mmcb = GDrawGetUserData(gw);
     522           0 :         mmcb->done = true;
     523           0 :     } else if ( event->type==et_char ) {
     524           0 :         if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
     525           0 :             help("mmmenu.html");
     526           0 : return( true );
     527             :         }
     528           0 : return( false );
     529             :     }
     530           0 : return( true );
     531             : }
     532             : 
     533           0 : static int GCDFillupMacWeights(GGadgetCreateData *gcd, GTextInfo *label, int k,
     534             :         char *axisnames[4], char axisval[4][24],
     535             :         real *defcoords,int axis_count,MMSet *mm) {
     536             :     int i;
     537             :     char *an;
     538             :     char axisrange[80];
     539             : 
     540           0 :     for ( i=0; i<axis_count; ++i ) {
     541           0 :         sprintf( axisrange, " [%.4g %.4g %.4g]", (double) mm->axismaps[i].min,
     542           0 :                 (double) mm->axismaps[i].def, (double) mm->axismaps[i].max );
     543           0 :         an = PickNameFromMacName(mm->axismaps[i].axisnames);
     544           0 :         if ( an==NULL )
     545           0 :             an = copy(mm->axes[i]);
     546           0 :         axisnames[i] = malloc(strlen(axisrange)+3+strlen(an));
     547           0 :         strcpy(axisnames[i],an);
     548           0 :         strcat(axisnames[i],axisrange);
     549           0 :         sprintf(axisval[i],"%.4g", (double) defcoords[i]);
     550           0 :         free(an);
     551             :     }
     552           0 :     for ( ; i<4; ++i ) {
     553           0 :         axisnames[i] = _(axistablab[i]);
     554           0 :         axisval[i][0] = '\0';
     555             :     }
     556             : 
     557           0 :     for ( i=0; i<4; ++i ) {
     558           0 :         label[k].text = (unichar_t *) axisnames[i];
     559           0 :         label[k].text_is_1byte = true;
     560           0 :         gcd[k].gd.label = &label[k];
     561           0 :         gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = k==0 ? 4 : gcd[k-1].gd.pos.y+28;
     562           0 :         gcd[k].gd.flags = i<axis_count ? (gg_visible | gg_enabled) : gg_visible;
     563           0 :         gcd[k++].creator = GLabelCreate;
     564             : 
     565           0 :         label[k].text = (unichar_t *) axisval[i];
     566           0 :         label[k].text_is_1byte = true;
     567           0 :         gcd[k].gd.label = &label[k];
     568           0 :         gcd[k].gd.pos.x = 15; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+12;
     569           0 :         gcd[k].gd.flags = gcd[k-1].gd.flags;
     570           0 :         gcd[k].gd.cid = 1000+i;
     571           0 :         gcd[k++].creator = GTextFieldCreate;
     572             :     }
     573           0 : return( k );
     574             : }
     575             : 
     576           0 : void MMChangeBlend(MMSet *mm,FontView *fv,int tonew) {
     577             :     char buffer[MmMax*20], *pt;
     578             :     unichar_t ubuf[MmMax*20];
     579             :     int i, k, j, def_name;
     580             :     struct mmcb mmcb;
     581             :     GRect pos;
     582             :     GWindow gw;
     583             :     GWindowAttrs wattrs;
     584             :     GGadgetCreateData gcd[14];
     585             :     GTextInfo label[14];
     586             :     unichar_t *utemp;
     587             :     char axisval[4][24];
     588             :     char *axisnames[4];
     589             :     real defcoords[4];
     590             : 
     591           0 :     if ( mm==NULL )
     592           0 : return;
     593             : 
     594           0 :     memset(&mmcb,0,sizeof(mmcb));
     595           0 :     mmcb.mm = mm;
     596           0 :     mmcb.fv = fv;
     597           0 :     mmcb.tonew = tonew;
     598             : 
     599           0 :     memset(&wattrs,0,sizeof(wattrs));
     600           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
     601           0 :     wattrs.event_masks = ~(1<<et_charup);
     602           0 :     wattrs.is_dlg = true;
     603           0 :     wattrs.restrict_input_to_me = true;
     604           0 :     wattrs.undercursor = 1;
     605           0 :     wattrs.cursor = ct_pointer;
     606           0 :     wattrs.utf8_window_title = tonew ? _("Blend to New Font"):_("MM Change Def Weights");
     607           0 :     pos.x = pos.y = 0;
     608             : 
     609           0 :     if ( !mm->apple ) {
     610           0 :         pt = buffer;
     611           0 :         for ( i=0; i<mm->instance_count; ++i ) {
     612           0 :             sprintf( pt, "%g ", (double) mm->defweights[i]);
     613           0 :             pt += strlen(pt);
     614             :         }
     615           0 :         if ( pt>buffer )
     616           0 :             pt[-2] = '\0';
     617           0 :         uc_strcpy(ubuf,buffer);
     618             : 
     619           0 :         pos.width =GDrawPointsToPixels(NULL,GGadgetScale(270));
     620           0 :         pos.height = GDrawPointsToPixels(NULL,200);
     621           0 :         mmcb.gw = gw = GDrawCreateTopWindow(NULL,&pos,mmcb_e_h,&mmcb,&wattrs);
     622             : 
     623           0 :         memset(&gcd,0,sizeof(gcd));
     624           0 :         memset(&label,0,sizeof(label));
     625             : 
     626           0 :         k=0;
     627             : /* GT: The following strings should be concatenated together, the result */
     628             : /* GT: translated, and then broken into lines by hand. I'm sure it would */
     629             : /* GT: be better to specify this all as one string, but my widgets won't support */
     630             : /* GT: that */
     631           0 :         label[k].text = (unichar_t *) (tonew ? _("You may specify the new instance of this font") : _("You may change the default instance of this font"));
     632           0 :         label[k].text_is_1byte = true;
     633           0 :         gcd[k].gd.label = &label[k];
     634           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = 10;
     635           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     636           0 :         gcd[k++].creator = GLabelCreate;
     637             : 
     638           0 :         label[k].text = (unichar_t *) _("either by explicitly entering the contribution");
     639           0 :         label[k].text_is_1byte = true;
     640           0 :         gcd[k].gd.label = &label[k];
     641           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+13;
     642           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     643           0 :         gcd[k++].creator = GLabelCreate;
     644             : 
     645           0 :         label[k].text = (unichar_t *) _("of each master design, or by entering the design");
     646           0 :         label[k].text_is_1byte = true;
     647           0 :         gcd[k].gd.label = &label[k];
     648           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+13;
     649           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     650           0 :         gcd[k++].creator = GLabelCreate;
     651             : 
     652           0 :         label[k].text = (unichar_t *) _("values for each axis");
     653           0 :         label[k].text_is_1byte = true;
     654           0 :         gcd[k].gd.label = &label[k];
     655           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+13;
     656           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     657           0 :         gcd[k++].creator = GLabelCreate;
     658             : 
     659           0 :         label[k].text = (unichar_t *) _("Contribution of each master design");
     660           0 :         label[k].text_is_1byte = true;
     661           0 :         gcd[k].gd.label = &label[k];
     662           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+16;
     663           0 :         gcd[k].gd.flags = gg_visible | gg_enabled | gg_cb_on;
     664           0 :         gcd[k].gd.cid = CID_Explicit;
     665           0 :         gcd[k].gd.handle_controlevent = MMCB_Changed;
     666           0 :         gcd[k++].creator = GRadioCreate;
     667             : 
     668           0 :         label[k].text = (unichar_t *) _("Design Axis Values");
     669           0 :         label[k].text_is_1byte = true;
     670           0 :         gcd[k].gd.label = &label[k];
     671           0 :         gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+45;
     672           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     673           0 :         gcd[k].gd.cid = CID_ByDesign;
     674           0 :         gcd[k].gd.handle_controlevent = MMCB_Changed;
     675           0 :         gcd[k++].creator = GRadioCreate;
     676             : 
     677           0 :         label[k].text = ubuf;
     678           0 :         gcd[k].gd.label = &label[k];
     679           0 :         gcd[k].gd.pos.x = 15; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y+18;
     680           0 :         gcd[k].gd.pos.width = 240;
     681           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     682           0 :         gcd[k].gd.cid = CID_NewBlends;
     683           0 :         gcd[k++].creator = GTextFieldCreate;
     684             : 
     685           0 :         label[k].text = utemp = MMDesignCoords(mm);
     686           0 :         gcd[k].gd.label = &label[k];
     687           0 :         gcd[k].gd.pos.x = 15; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y+18;
     688           0 :         gcd[k].gd.pos.width = 240;
     689           0 :         gcd[k].gd.flags = gg_visible;
     690           0 :         gcd[k].gd.cid = CID_NewDesign;
     691           0 :         gcd[k++].creator = GTextFieldCreate;
     692             : 
     693           0 :         gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
     694           0 :         gcd[k].gd.pos.width = -1;
     695           0 :         gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
     696           0 :         label[k].text = (unichar_t *) _("_OK");
     697           0 :         label[k].text_is_1byte = true;
     698           0 :         label[k].text_in_resource = true;
     699           0 :         gcd[k].gd.label = &label[k];
     700           0 :         gcd[k].gd.handle_controlevent = MMCB_OK;
     701           0 :         gcd[k++].creator = GButtonCreate;
     702             : 
     703           0 :         gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
     704           0 :         gcd[k].gd.pos.width = -1;
     705           0 :         gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
     706           0 :         label[k].text = (unichar_t *) _("_Cancel");
     707           0 :         label[k].text_is_1byte = true;
     708           0 :         label[k].text_in_resource = true;
     709           0 :         gcd[k].gd.label = &label[k];
     710           0 :         gcd[k].gd.handle_controlevent = MMCB_Cancel;
     711           0 :         gcd[k++].creator = GButtonCreate;
     712             : 
     713           0 :         gcd[k].gd.pos.x = 2; gcd[k].gd.pos.y = 2;
     714           0 :         gcd[k].gd.pos.width = pos.width-4; gcd[k].gd.pos.height = pos.height-4;
     715           0 :         gcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
     716           0 :         gcd[k].creator = GGroupCreate;
     717             : 
     718           0 :         GGadgetsCreate(gw,gcd);
     719           0 :         free(utemp);
     720             :     } else {
     721           0 :         pos.width =GDrawPointsToPixels(NULL,GGadgetScale(270));
     722           0 :         pos.height = GDrawPointsToPixels(NULL,200);
     723           0 :         mmcb.gw = gw = GDrawCreateTopWindow(NULL,&pos,mmcb_e_h,&mmcb,&wattrs);
     724             : 
     725           0 :         memset(&gcd,0,sizeof(gcd));
     726           0 :         memset(&label,0,sizeof(label));
     727             : 
     728           0 :         memset(defcoords,0,sizeof(defcoords));
     729           0 :         for ( i=0; i<mm->axis_count; ++i )
     730           0 :             defcoords[i] = mm->axismaps[i].def;
     731           0 :         def_name = -1;
     732           0 :         for ( i=0; i<mm->named_instance_count; ++i ) {
     733           0 :             for ( j=0; j<mm->axis_count; ++j )
     734           0 :                 if ( !RealNear(mm->named_instances[i].coords[j],defcoords[j]))
     735           0 :             break;
     736           0 :             if ( j==mm->axis_count ) {
     737           0 :                 def_name = i;
     738           0 :         break;
     739             :             }
     740             :         }
     741             : 
     742           0 :         k=0;
     743           0 :         k = GCDFillupMacWeights(gcd,label,k,axisnames,axisval,defcoords,
     744             :                 mm->axis_count,mm);
     745             : 
     746           0 :         gcd[k].gd.pos.x = 130; gcd[k].gd.pos.y = gcd[k-4].gd.pos.y-12;
     747           0 :         gcd[k].gd.flags = gg_visible | gg_enabled;
     748           0 :         if ( mm->named_instance_count==0 )
     749           0 :             gcd[k].gd.flags = 0;
     750           0 :         gcd[k].gd.u.list = MMCB_KnownValues(mm);
     751           0 :         if ( def_name!=-1 )
     752           0 :             gcd[k].gd.u.list[def_name+1].selected = true;
     753           0 :         gcd[k].gd.cid = CID_Knowns;
     754           0 :         gcd[k].gd.handle_controlevent = MMCB_PickedKnown;
     755           0 :         gcd[k++].creator = GListButtonCreate;
     756             : 
     757           0 :         gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
     758           0 :         gcd[k].gd.pos.width = -1;
     759           0 :         gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
     760           0 :         label[k].text = (unichar_t *) _("_OK");
     761           0 :         label[k].text_is_1byte = true;
     762           0 :         label[k].text_in_resource = true;
     763           0 :         gcd[k].gd.label = &label[k];
     764           0 :         gcd[k].gd.handle_controlevent = MMCB_OKApple;
     765           0 :         gcd[k++].creator = GButtonCreate;
     766             : 
     767           0 :         gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
     768           0 :         gcd[k].gd.pos.width = -1;
     769           0 :         gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
     770           0 :         label[k].text = (unichar_t *) _("_Cancel");
     771           0 :         label[k].text_is_1byte = true;
     772           0 :         label[k].text_in_resource = true;
     773           0 :         gcd[k].gd.label = &label[k];
     774           0 :         gcd[k].gd.handle_controlevent = MMCB_Cancel;
     775           0 :         gcd[k++].creator = GButtonCreate;
     776             : 
     777           0 :         gcd[k].gd.pos.x = 2; gcd[k].gd.pos.y = 2;
     778           0 :         gcd[k].gd.pos.width = pos.width-4; gcd[k].gd.pos.height = pos.height-4;
     779           0 :         gcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
     780           0 :         gcd[k++].creator = GGroupCreate;
     781             : 
     782           0 :         GGadgetsCreate(gw,gcd);
     783           0 :         for ( i=0; i<mm->axis_count; ++i )
     784           0 :             free(axisnames[i]);
     785           0 :         GTextInfoListFree(gcd[k-4].gd.u.list);
     786           0 :         GWidgetIndicateFocusGadget(gcd[1].ret);
     787             :     }
     788             : 
     789           0 :     GDrawSetVisible(gw,true);
     790             : 
     791           0 :     while ( !mmcb.done )
     792           0 :         GDrawProcessOneEvent(NULL);
     793           0 :     GDrawDestroyWindow(gw);
     794             : }
     795             : 
     796             : GTextInfo axiscounts[] = {
     797             :     { (unichar_t *) "1", NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     798             :     { (unichar_t *) "2", NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     799             :     { (unichar_t *) "3", NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     800             :     { (unichar_t *) "4", NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     801             :     GTEXTINFO_EMPTY
     802             : };
     803             : 
     804             : /* These names are fixed by Adobe & Apple and are not subject to translation */
     805             : GTextInfo axistypes[] = {
     806             :     { (unichar_t *) "Weight",         NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     807             :     { (unichar_t *) "Width",          NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     808             :     { (unichar_t *) "OpticalSize",    NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     809             :     { (unichar_t *) "Slant",          NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     810             :     GTEXTINFO_EMPTY
     811             : };
     812             : 
     813             : GTextInfo mastercounts[] = {
     814             :     { (unichar_t *) "1", NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     815             :     { (unichar_t *) "2", NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     816             :     { (unichar_t *) "3", NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     817             :     { (unichar_t *) "4", NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     818             :     { (unichar_t *) "5", NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     819             :     { (unichar_t *) "6", NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     820             :     { (unichar_t *) "7", NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     821             :     { (unichar_t *) "8", NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     822             :     { (unichar_t *) "9", NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     823             :     { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     824             :     { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     825             :     { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     826             :     { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     827             :     { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     828             :     { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     829             :     { (unichar_t *) "16", NULL, 0, 0, (void *) 16, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     830             :     { (unichar_t *) "17", NULL, 0, 0, (void *) 17, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     831             :     { (unichar_t *) "18", NULL, 0, 0, (void *) 18, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     832             :     { (unichar_t *) "19", NULL, 0, 0, (void *) 19, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     833             :     { (unichar_t *) "20", NULL, 0, 0, (void *) 20, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     834             :     { (unichar_t *) "21", NULL, 0, 0, (void *) 21, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     835             :     { (unichar_t *) "22", NULL, 0, 0, (void *) 22, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     836             :     { (unichar_t *) "23", NULL, 0, 0, (void *) 23, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     837             :     { (unichar_t *) "24", NULL, 0, 0, (void *) 24, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     838             :     { (unichar_t *) "25", NULL, 0, 0, (void *) 25, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     839             :     { (unichar_t *) "26", NULL, 0, 0, (void *) 26, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     840             :     { (unichar_t *) "27", NULL, 0, 0, (void *) 27, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
     841             : #if AppleMmMax!=26
     842             :  #error "The mastercounts array needs to be expanded to match AppleMmMax"
     843             :     /* Actually it should be one bigger than AppleMmMax */
     844             : #endif
     845             :     GTEXTINFO_EMPTY
     846             : };
     847             : 
     848             : enum mmw_state { mmw_counts, mmw_axes, mmw_designs, mmw_named, mmw_funcs,
     849             :                  mmw_others };
     850             : 
     851             : typedef struct mmw {
     852             :     GWindow gw;
     853             :     enum mmw_state state;
     854             :     GWindow subwins[mmw_others+1];
     855             :     MMSet *mm, *old;
     856             :     int isnew;
     857             :     int done;
     858             :     int old_axis_count, old_adobe;
     859             :     int axis_count, instance_count;     /* The data in mm are set to the max for each */
     860             :     int last_instance_count, last_axis_count, lastw_instance_count;
     861             :     struct axismap last_axismaps[4];
     862             :     int canceldrop, subheightdiff;
     863             :     int lcnt, lmax;
     864             :     SplineFont **loaded;
     865             : } MMW;
     866             : 
     867             : #define MMW_Width       340
     868             : #define MMW_Height      300
     869             : #define ESD_Width       262
     870             : #define ESD_Height      316
     871             : 
     872             : #define CID_OK          1001
     873             : #define CID_Prev        1002
     874             : #define CID_Next        1003
     875             : #define CID_Cancel      1004
     876             : #define CID_Group       1005
     877             : 
     878             : #define CID_AxisCount   2001
     879             : #define CID_MasterCount 2002
     880             : #define CID_Adobe       2003
     881             : #define CID_Apple       2004
     882             : 
     883             : #define CID_WhichAxis                   3000
     884             : #define CID_AxisType                    3001    /* +[0,3]*100 */
     885             : #define CID_AxisBegin                   3002    /* +[0,3]*100 */
     886             : #define CID_AxisDefault                 3003    /* +[0,3]*100 */
     887             : #define CID_AxisDefaultLabel            3004    /* +[0,3]*100 */
     888             : #define CID_AxisEnd                     3005    /* +[0,3]*100 */
     889             : #define CID_IntermediateDesign          3006    /* +[0,3]*100 */
     890             : #define CID_IntermediateNormalized      3007    /* +[0,3]*100 */
     891             : 
     892             : #define DesignScaleFactor       20
     893             : 
     894             : #define CID_WhichDesign 4000
     895             : #define CID_DesignFonts 4001    /* +[0,26]*DesignScaleFactor */
     896             : #define CID_AxisWeights 4002    /* +[0,26]*DesignScaleFactor */
     897             : 
     898             : #define CID_NDV                 5002
     899             : #define CID_CDV                 5003
     900             : 
     901             : /* CID_Explicit-CID_NewDesign already defined */
     902             : #define CID_ForceBoldThreshold  6005
     903             : #define CID_FamilyName          6006
     904             : 
     905             : #define CID_NamedDesigns        7001
     906             : #define CID_NamedNew            7002
     907             : #define CID_NamedEdit           7003
     908             : #define CID_NamedDelete         7004
     909             : 
     910             : struct esd {
     911             :     GWindow gw;
     912             :     MMW *mmw;
     913             :     GGadget *list;
     914             :     int index;
     915             :     int done;
     916             : };
     917             : 
     918           0 : static void ESD_Close(struct esd *esd) {
     919           0 :     MacNameListFree(NameGadgetsGetNames(esd->gw));
     920           0 :     esd->done = true;
     921           0 : }
     922             : 
     923           0 : static int ESD_Cancel(GGadget *g, GEvent *e) {
     924           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     925           0 :         struct esd *esd =  GDrawGetUserData(GGadgetGetWindow(g));
     926           0 :         ESD_Close(esd);
     927             :     }
     928           0 : return( true );
     929             : }
     930             : 
     931           0 : static int ESD_OK(GGadget *g, GEvent *e) {
     932           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     933           0 :         struct esd *esd =  GDrawGetUserData(GGadgetGetWindow(g));
     934             :         int i,axis_count;
     935           0 :         int err = false;
     936             :         real coords[4];
     937             :         struct macname *mn;
     938             :         char buffer[120], *pt;
     939             :         unichar_t *name; char *style;
     940             : 
     941           0 :         for ( i=0; i<esd->mmw->axis_count && i<4; ++i )
     942           0 :             coords[i] = rint(GetReal8(esd->gw,1000+i,_(axistablab[i]),&err)*8096)/8096;
     943           0 :         if ( err )
     944           0 : return( true );
     945           0 :         axis_count = i;
     946           0 :         mn = NameGadgetsGetNames(esd->gw);
     947           0 :         if ( mn==NULL ) {
     948           0 :             ff_post_error(_("Bad Multiple Master Font"),_("You must provide at least one name here"));
     949           0 : return( true );
     950             :         }
     951           0 :         pt = buffer; *pt++ = ' '; *pt++ = '[';
     952           0 :         for ( i=0; i<axis_count; ++i ) {
     953           0 :             sprintf(pt, "%g ", (double) coords[i]);
     954           0 :             pt += strlen(pt);
     955             :         }
     956           0 :         pt[-1] = ']';
     957           0 :         *pt = '\0';
     958           0 :         style = PickNameFromMacName(mn);
     959           0 :         name = malloc(((pt-buffer) + strlen(style) + 1)*sizeof(unichar_t));
     960           0 :         utf82u_strcpy(name,style);
     961           0 :         uc_strcat(name,buffer);
     962           0 :         free(style);
     963           0 :         if ( esd->index==-1 )
     964           0 :             GListAppendLine(esd->list,name,false)->userdata = mn;
     965             :         else {
     966           0 :             GTextInfo *ti = GGadgetGetListItem(esd->list,esd->index);
     967           0 :             MacNameListFree(ti->userdata);
     968           0 :             GListChangeLine(esd->list,esd->index,name)->userdata = mn;
     969             :         }
     970           0 :         esd->done = true;
     971           0 :         free(name);
     972             :     }
     973           0 : return( true );
     974             : }
     975             : 
     976           0 : static int esd_eh(GWindow gw, GEvent *event) {
     977           0 :     if ( event->type==et_close ) {
     978           0 :         struct esd *esd = GDrawGetUserData(gw);
     979           0 :         ESD_Close(esd);
     980           0 :     } else if ( event->type==et_char ) {
     981           0 :         if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
     982           0 :             help("multiplemaster.html#NamedStyles");
     983           0 : return( true );
     984           0 :         } else if ( GMenuIsCommand(event,H_("Quit|Ctl+Q") )) {
     985           0 :             MenuExit(NULL,NULL,NULL);
     986           0 : return( true );
     987           0 :         } else if ( GMenuIsCommand(event,H_("Close|Ctl+Shft+Q") )) {
     988           0 :             ESD_Close(GDrawGetUserData(gw));
     989           0 : return( true );
     990             :         }
     991           0 : return( false );
     992             :     }
     993           0 : return( true );
     994             : }
     995             : 
     996           0 : static void EditStyleName(MMW *mmw,int index) {
     997           0 :     GGadget *list = GWidgetGetControl(mmw->subwins[mmw_named],CID_NamedDesigns);
     998           0 :     GTextInfo *ti = NULL;
     999             :     int i,k;
    1000           0 :     unichar_t *pt = NULL, *end;
    1001             :     real axes[4];
    1002           0 :     struct macname *mn = NULL;
    1003             :     char axisval[4][24];
    1004             :     char *axisnames[4];
    1005             :     GGadgetCreateData gcd[17];
    1006             :     GTextInfo label[17];
    1007             :     GRect pos;
    1008             :     GWindow gw;
    1009             :     GWindowAttrs wattrs;
    1010             :     struct esd esd;
    1011             : 
    1012           0 :     for ( i=0; i<mmw->axis_count; ++i )
    1013           0 :         axes[i] = mmw->mm->axismaps[i].def;
    1014           0 :     if ( index != -1 ) {
    1015           0 :         ti = GGadgetGetListItem(list,index);
    1016           0 :         if ( ti!=NULL ) {
    1017           0 :             pt = u_strchr(ti->text,'[');
    1018           0 :             mn = ti->userdata;
    1019             :         }
    1020           0 :         if ( pt!=NULL ) {
    1021           0 :             for ( i=0, ++pt; i<4 && (*pt!=']' && *pt!='\0'); ++i ) {
    1022           0 :                 axes[i] = u_strtod(pt,&end);
    1023           0 :                 pt = end;
    1024             :             }
    1025             :         }
    1026             :     }
    1027             : 
    1028           0 :     memset(&esd,0,sizeof(esd));
    1029           0 :     esd.mmw = mmw;
    1030           0 :     esd.index = index;
    1031           0 :     esd.list = list;
    1032             : 
    1033           0 :     memset(&wattrs,0,sizeof(wattrs));
    1034           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
    1035           0 :     wattrs.event_masks = ~(1<<et_charup);
    1036           0 :     wattrs.is_dlg = true;
    1037           0 :     wattrs.restrict_input_to_me = true;
    1038           0 :     wattrs.undercursor = 1;
    1039           0 :     wattrs.cursor = ct_pointer;
    1040           0 :     wattrs.utf8_window_title = _("Named Styles");
    1041           0 :     pos.x = pos.y = 0;
    1042           0 :     pos.width =GDrawPointsToPixels(NULL,GGadgetScale(ESD_Width));
    1043           0 :     pos.height = GDrawPointsToPixels(NULL,ESD_Height);
    1044           0 :     esd.gw = gw = GDrawCreateTopWindow(NULL,&pos,esd_eh,&esd,&wattrs);
    1045             : 
    1046           0 :     memset(gcd,0,sizeof(gcd));
    1047           0 :     memset(label,0,sizeof(label));
    1048           0 :     k = 0;
    1049             : 
    1050           0 :     k = GCDFillupMacWeights(gcd,label,k,axisnames,axisval,axes,
    1051             :             mmw->axis_count,mmw->mm);
    1052           0 :     k = GCDBuildNames(gcd,label,k,mn);
    1053             : 
    1054           0 :     gcd[k].gd.pos.x = 20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+33-3;
    1055           0 :     gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
    1056           0 :     gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
    1057           0 :     label[k].text = (unichar_t *) _("_OK");
    1058           0 :     label[k].text_is_1byte = true;
    1059           0 :     label[k].text_in_resource = true;
    1060           0 :     gcd[k].gd.label = &label[k];
    1061           0 :     gcd[k].gd.handle_controlevent = ESD_OK;
    1062           0 :     gcd[k++].creator = GButtonCreate;
    1063             : 
    1064           0 :     gcd[k].gd.pos.x = -20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
    1065           0 :     gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
    1066           0 :     gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
    1067           0 :     label[k].text = (unichar_t *) _("_Cancel");
    1068           0 :     label[k].text_is_1byte = true;
    1069           0 :     label[k].text_in_resource = true;
    1070           0 :     gcd[k].gd.label = &label[k];
    1071           0 :     gcd[k].gd.handle_controlevent = ESD_Cancel;
    1072           0 :     gcd[k++].creator = GButtonCreate;
    1073             : 
    1074           0 :     gcd[k].gd.pos.x = 2; gcd[k].gd.pos.y = 2;
    1075           0 :     gcd[k].gd.pos.width = pos.width-4; gcd[k].gd.pos.height = pos.height-4;
    1076           0 :     gcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
    1077           0 :     gcd[k].creator = GGroupCreate;
    1078             : 
    1079           0 :     GGadgetsCreate(gw,gcd);
    1080             : 
    1081           0 :     for ( i=0; i<mmw->axis_count; ++i )
    1082           0 :         free( axisnames[i]);
    1083             : 
    1084           0 :     GDrawSetVisible(gw,true);
    1085             : 
    1086           0 :     while ( !esd.done )
    1087           0 :         GDrawProcessOneEvent(NULL);
    1088             : 
    1089           0 :     GDrawDestroyWindow(gw);
    1090           0 : }
    1091             : 
    1092           0 : static void SetMasterToAxis(MMW *mmw, int initial) {
    1093             :     int i, cnt, def, isadobe;
    1094             : 
    1095           0 :     cnt = GGadgetGetFirstListSelectedItem(GWidgetGetControl(mmw->subwins[mmw_counts],CID_AxisCount))
    1096             :             +1;
    1097           0 :     isadobe = GGadgetIsChecked(GWidgetGetControl(mmw->subwins[mmw_counts],CID_Adobe));
    1098           0 :     if ( cnt!=mmw->old_axis_count || isadobe!=mmw->old_adobe ) {
    1099           0 :         GGadget *list = GWidgetGetControl(mmw->subwins[mmw_counts],CID_MasterCount);
    1100             :         int32 len;
    1101           0 :         GTextInfo **ti = GGadgetGetList(list,&len);
    1102           0 :         if ( isadobe ) {
    1103           0 :             for ( i=0; i<MmMax; ++i )
    1104           0 :                 ti[i]->disabled = (i+1) < (1<<cnt);
    1105           0 :             for ( ; i<AppleMmMax+1 ; ++i )
    1106           0 :                 ti[i]->disabled = true;
    1107           0 :             def = (1<<cnt);
    1108             :         } else {
    1109           0 :             for ( i=0; i<AppleMmMax+1; ++i )
    1110           0 :                 ti[i]->disabled = (i+1) < cnt;
    1111           0 :             def = 1;
    1112           0 :             for ( i=0; i<cnt; ++i )
    1113           0 :                 def *= 3;
    1114           0 :             if ( def>AppleMmMax+1 )
    1115           0 :                 def = AppleMmMax+1;
    1116             :         }
    1117           0 :         if ( !initial )
    1118           0 :             GGadgetSelectOneListItem(list,def-1);
    1119           0 :         mmw->old_axis_count = cnt;
    1120           0 :         mmw->old_adobe = isadobe;
    1121             :     }
    1122           0 : }
    1123             : 
    1124           0 : static int MMW_AxisCntChanged(GGadget *g, GEvent *e) {
    1125             : 
    1126           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
    1127           0 :         SetMasterToAxis(GDrawGetUserData(GGadgetGetWindow(g)),false);
    1128             :     }
    1129           0 : return( true );
    1130             : }
    1131             : 
    1132           0 : static int MMW_TypeChanged(GGadget *g, GEvent *e) {
    1133           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
    1134           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    1135           0 :         int isapple = GGadgetIsChecked(GWidgetGetControl(mmw->subwins[mmw_counts],CID_Apple));
    1136             :         int i;
    1137           0 :         SetMasterToAxis(mmw,false);
    1138           0 :         for ( i=0; i<4; ++i ) {
    1139           0 :             GGadgetSetEnabled(GWidgetGetControl(mmw->subwins[mmw_axes],CID_AxisDefault+i*100),isapple);
    1140           0 :             GGadgetSetEnabled(GWidgetGetControl(mmw->subwins[mmw_axes],CID_AxisDefaultLabel+i*100),isapple);
    1141           0 :             NameGadgetsSetEnabled(GTabSetGetSubwindow(
    1142           0 :                     GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),i),isapple);
    1143             :         }
    1144             :     }
    1145           0 : return( true );
    1146             : }
    1147             : 
    1148           0 : static void MMUsurpNew(SplineFont *sf) {
    1149             :     /* This is a font that wasn't in the original MMSet */
    1150             :     /* We ARE going to use it in the final result */
    1151             :     /* So if it is attached to a fontview, we must close that window and */
    1152             :     /*  claim the splinefont for ourselves */
    1153             :     FontView *fv, *nextfv;
    1154             : 
    1155           0 :     if ( sf->fv!=NULL ) {
    1156           0 :         if ( sf->kcld!=NULL )
    1157           0 :             KCLD_End(sf->kcld);
    1158           0 :         if ( sf->vkcld!=NULL )
    1159           0 :             KCLD_End(sf->vkcld);
    1160           0 :         sf->kcld = sf->vkcld = NULL;
    1161             : 
    1162           0 :         for ( fv=(FontView *) sf->fv; fv!=NULL; fv=nextfv ) {
    1163           0 :             nextfv = (FontView *) (fv->b.nextsame);
    1164           0 :             fv->b.nextsame = NULL;
    1165           0 :             _FVCloseWindows(fv);
    1166           0 :             fv->b.sf = NULL;
    1167           0 :             GDrawDestroyWindow(fv->gw);
    1168             :         }
    1169           0 :         sf->fv = NULL;
    1170           0 :         SFClearAutoSave(sf);
    1171             :     }
    1172           0 : }
    1173             : 
    1174           0 : static void MMDetachNew(SplineFont *sf) {
    1175             :     /* This is a font that wasn't in the original MMSet */
    1176             :     /* We aren't going to use it in the final result */
    1177             :     /* If it is attached to a fontview, then the fontview retains control */
    1178             :     /* If not, then free it */
    1179           0 :     if ( sf->fv==NULL )
    1180           0 :         SplineFontFree(sf);
    1181           0 : }
    1182             : 
    1183           0 : static void MMDetachOld(SplineFont *sf) {
    1184             :     /* This is a font that was in the original MMSet */
    1185             :     /* We aren't going to use it in the final result */
    1186             :     /* So then free it */
    1187           0 :     sf->mm = NULL;
    1188           0 :     SplineFontFree(sf);
    1189           0 : }
    1190             : 
    1191           0 : static void MMW_Close(MMW *mmw) {
    1192             :     int i;
    1193           0 :     GGadget *list = GWidgetGetControl(mmw->subwins[mmw_named],CID_NamedDesigns);
    1194             :     int32 len;
    1195           0 :     GTextInfo **ti = GGadgetGetList(list,&len);
    1196             : 
    1197           0 :     for ( i=0; i<len; ++i )
    1198           0 :         if ( ti[i]->userdata!=NULL )
    1199           0 :             MacNameListFree(ti[i]->userdata);
    1200           0 :     for ( i=0; i<4; ++i )
    1201           0 :         MacNameListFree(NameGadgetsGetNames(GTabSetGetSubwindow(
    1202           0 :             GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),i)));
    1203           0 :     for ( i=0; i<mmw->lcnt; ++i )
    1204           0 :         MMDetachNew(mmw->loaded[i]);
    1205           0 :     free(mmw->loaded);
    1206           0 :     for ( i=0; i<4; ++i )
    1207           0 :         mmw->mm->axismaps[i].axisnames = NULL;
    1208           0 :     MMSetFreeContents(mmw->mm);
    1209           0 :     chunkfree(mmw->mm,sizeof(MMSet));
    1210           0 :     mmw->done = true;
    1211           0 : }
    1212             : 
    1213           0 : static int MMW_Cancel(GGadget *g, GEvent *e) {
    1214           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    1215           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    1216           0 :         MMW_Close(mmw);
    1217             :     }
    1218           0 : return( true );
    1219             : }
    1220             : 
    1221           0 : static void MMW_SetState(MMW *mmw) {
    1222             :     unsigned int i;
    1223             : 
    1224           0 :     GDrawSetVisible(mmw->subwins[mmw->state],true);
    1225           0 :     for ( i=mmw_counts; i<=mmw_others; ++i )
    1226           0 :         if ( i!=mmw->state )
    1227           0 :             GDrawSetVisible(mmw->subwins[i],false);
    1228             : 
    1229           0 :     GGadgetSetEnabled(GWidgetGetControl(mmw->gw,CID_Prev),mmw->state!=mmw_counts);
    1230           0 :     GGadgetSetEnabled(GWidgetGetControl(mmw->gw,CID_Next),
    1231           0 :             mmw->state!=mmw_others && mmw->state!=mmw_named);
    1232           0 :     GGadgetSetEnabled(GWidgetGetControl(mmw->gw,CID_OK),
    1233           0 :             mmw->state==mmw_others || mmw->state==mmw_named);
    1234           0 : }
    1235             : 
    1236           0 : static int ParseWeights(GWindow gw,int cid, char *str,
    1237             :         real *list, int expected, int tabset_cid, int aspect ) {
    1238           0 :     int cnt=0;
    1239             :     const unichar_t *ret, *pt; unichar_t *endpt;
    1240             : 
    1241           0 :     ret= _GGadgetGetTitle(GWidgetGetControl(gw,cid));
    1242             : 
    1243           0 :     for ( pt=ret; *pt==' '; ++pt );
    1244           0 :     for ( ; *pt; ) {
    1245           0 :         list[cnt++] = u_strtod(pt,&endpt);
    1246           0 :         if ( pt==endpt || ( *endpt!='\0' && *endpt!=' ' )) {
    1247           0 :             if ( tabset_cid!=-1 )
    1248           0 :                 GTabSetSetSel(GWidgetGetControl(gw,tabset_cid),aspect);
    1249           0 :             ff_post_error(_("Bad Axis"),_("Bad Number in %s"), str);
    1250           0 : return( 0 );
    1251             :         }
    1252           0 :         for ( pt = endpt; *pt==' '; ++pt );
    1253             :     }
    1254           0 :     if ( cnt!=expected && expected!=-1 ) {
    1255           0 :         if ( tabset_cid!=-1 )
    1256           0 :             GTabSetSetSel(GWidgetGetControl(gw,tabset_cid),aspect);
    1257           0 :         ff_post_error(_("Bad Axis"),_("Wrong number of entries in %s"), str);
    1258           0 : return( 0 );
    1259             :     }
    1260             : 
    1261           0 : return( cnt );
    1262             : }
    1263             : 
    1264           0 : static int ParseList(GWindow gw,int cid, char *str8, int *err, real start,
    1265             :         real def, real end, real **_list, int tabset_cid, int aspect,
    1266             :         int isapple ) {
    1267             :     int i, cnt;
    1268             :     const unichar_t *ret, *pt; unichar_t *endpt;
    1269             :     real *list, val;
    1270           0 :     int defdone = false;
    1271             : 
    1272           0 :     *_list = NULL;
    1273             : 
    1274           0 :     ret= _GGadgetGetTitle(GWidgetGetControl(gw,cid));
    1275           0 :     for ( pt=ret; *pt==' '; ++pt );
    1276           0 :     cnt = *pt=='\0'?0:1 ;
    1277           0 :     for ( ; *pt; ++pt ) {
    1278           0 :         if ( *pt==' ' ) ++cnt;
    1279           0 :         while ( *pt==' ' ) ++pt;
    1280             :     }
    1281           0 :     if ( start!=end )
    1282           0 :         cnt+=2;
    1283           0 :     if ( isapple && start!=end )
    1284           0 :         ++cnt;
    1285           0 :     if ( !isapple || start==end )
    1286           0 :         defdone = true;
    1287           0 :     list = malloc(cnt*sizeof(real));
    1288           0 :     if ( start==end )
    1289           0 :         cnt = 0;
    1290             :     else {
    1291           0 :         list[0] = start;
    1292           0 :         cnt = 1;
    1293             :     }
    1294             : 
    1295           0 :     for ( pt=ret; *pt==' '; ++pt );
    1296           0 :     for ( ; *pt; ) {
    1297           0 :         val = u_strtod(pt,&endpt);
    1298           0 :         if ( !defdone && val>def ) {
    1299           0 :             list[cnt++] = def;
    1300           0 :             defdone = true;
    1301             :         }
    1302           0 :         list[cnt++] = val;
    1303           0 :         if ( pt==endpt || ( *endpt!='\0' && *endpt!=' ' )) {
    1304           0 :             GTabSetSetSel(GWidgetGetControl(gw,tabset_cid),aspect);
    1305           0 :             free(list);
    1306           0 :             ff_post_error(_("Bad Axis"),_("Bad Number in %s"), str8);
    1307           0 :             *err = true;
    1308           0 : return( 0 );
    1309             :         }
    1310           0 :         for ( pt = endpt; *pt==' '; ++pt );
    1311             :     }
    1312           0 :     if ( start!=end )
    1313           0 :         list[cnt++] = end;
    1314           0 :     for ( i=1; i<cnt; ++i )
    1315           0 :         if ( list[i-1]>list[i] ) {
    1316           0 :             GTabSetSetSel(GWidgetGetControl(gw,tabset_cid),aspect);
    1317           0 :             ff_post_error(_("Bad Axis"),_("The %s list is not ordered"), str8);
    1318           0 :             free(list);
    1319           0 :             *err = true;
    1320           0 : return( 0 );
    1321             :         }
    1322             : 
    1323           0 :     *_list = list;
    1324           0 : return( cnt );
    1325             : }
    1326             : 
    1327           0 : static char *_ChooseFonts(char *buffer, SplineFont **sfs, real *positions,
    1328             :         int i, int cnt) {
    1329           0 :     char *elsepart=NULL, *ret;
    1330             :     int pos;
    1331             :     int k;
    1332             : 
    1333           0 :     if ( i<cnt-2 )
    1334           0 :         elsepart = _ChooseFonts(buffer,sfs,positions,i+1,cnt);
    1335             : 
    1336           0 :     pos = 0;
    1337           0 :     if ( positions[i]!=0 ) {
    1338           0 :         sprintf(buffer, "%g sub ", (double) positions[i]);
    1339           0 :         pos += strlen(buffer);
    1340             :     }
    1341           0 :     sprintf(buffer+pos, "%g div dup 1 sub exch ", (double) (positions[i+1]-positions[i]));
    1342           0 :     pos += strlen( buffer+pos );
    1343           0 :     for ( k=0; k<i; ++k ) {
    1344           0 :         strcpy(buffer+pos, "0 ");
    1345           0 :         pos += 2;
    1346             :     }
    1347           0 :     if ( i!=0 ) {
    1348           0 :         sprintf(buffer+pos, "%d -2 roll ", i+2 );
    1349           0 :         pos += strlen(buffer+pos);
    1350             :     }
    1351           0 :     for ( k=i+2; k<cnt; ++k ) {
    1352           0 :         strcpy(buffer+pos, "0 ");
    1353           0 :         pos += 2;
    1354             :     }
    1355             : 
    1356           0 :     if ( elsepart==NULL )
    1357           0 : return( copy(buffer));
    1358             : 
    1359           0 :     ret = malloc(strlen(buffer)+strlen(elsepart)+40);
    1360           0 :     sprintf(ret,"dup %g le {%s} {%s} ifelse", (double) positions[i+1], buffer, elsepart );
    1361           0 :     free(elsepart);
    1362           0 : return( ret );
    1363             : }
    1364             : 
    1365           0 : static unichar_t *Figure1AxisCDV(MMW *mmw) {
    1366             :     real positions[MmMax];
    1367             :     SplineFont *sfs[MmMax];
    1368             :     int i;
    1369             :     char *temp;
    1370             :     unichar_t *ret;
    1371             :     char buffer[400];
    1372             : 
    1373           0 :     if ( mmw->axis_count!=1 )
    1374           0 : return( uc_copy(""));
    1375           0 :     if ( mmw->instance_count==2 )
    1376           0 : return( uc_copy( standard_cdvs[1]));
    1377             : 
    1378           0 :     for ( i=0; i<mmw->instance_count; ++i ) {
    1379           0 :         positions[i] = mmw->mm->positions[4*i];
    1380           0 :         sfs[i] = mmw->mm->instances[i];
    1381           0 :         if ( i>0 && positions[i-1]>=positions[i] )
    1382           0 : return( uc_copy(""));
    1383             :     }
    1384           0 :     temp = _ChooseFonts(buffer,sfs,positions,0,mmw->instance_count);
    1385           0 :     ret = uc_copy(temp);
    1386           0 :     free(temp);
    1387           0 : return( ret );
    1388             : }
    1389             : 
    1390           0 : static char *_NormalizeAxis(char *buffer, struct axismap *axis, int i) {
    1391           0 :     char *elsepart=NULL, *ret;
    1392             :     int pos;
    1393             : 
    1394           0 :     if ( i<axis->points-2 )
    1395           0 :         elsepart = _NormalizeAxis(buffer,axis,i+1);
    1396             : 
    1397           0 :     pos = 0;
    1398           0 :     if ( axis->blends[i+1]==axis->blends[i] ) {
    1399           0 :         sprintf( buffer, "%g ", (double) axis->blends[i] );
    1400           0 :         pos = strlen(buffer);
    1401             :     } else {
    1402           0 :         if ( axis->designs[i]!=0 ) {
    1403           0 :             sprintf(buffer, "%g sub ", (double) axis->designs[i]);
    1404           0 :             pos += strlen(buffer);
    1405             :         }
    1406           0 :         sprintf(buffer+pos, "%g div ", (double) ((axis->designs[i+1]-axis->designs[i])/
    1407           0 :                     (axis->blends[i+1]-axis->blends[i])));
    1408           0 :         pos += strlen( buffer+pos );
    1409           0 :         if ( axis->blends[i]!=0 ) {
    1410           0 :             sprintf(buffer+pos, "%g add ", (double) axis->blends[i]);
    1411           0 :             pos += strlen(buffer+pos);
    1412             :         }
    1413             :     }
    1414             : 
    1415           0 :     if ( elsepart==NULL )
    1416           0 : return( copy(buffer));
    1417             : 
    1418           0 :     ret = malloc(strlen(buffer)+strlen(elsepart)+40);
    1419           0 :     sprintf(ret,"dup %g le {%s} {%s} ifelse", (double) axis->designs[i+1], buffer, elsepart );
    1420           0 :     free(elsepart);
    1421           0 : return( ret );
    1422             : }
    1423             : 
    1424           0 : static char *NormalizeAxis(char *header,struct axismap *axis) {
    1425             :     char *ret;
    1426             :     char buffer[200];
    1427             : 
    1428           0 :     ret = _NormalizeAxis(buffer,axis,0);
    1429           0 :     if ( *header ) {
    1430             :         char *temp;
    1431           0 :         temp = malloc(strlen(header)+strlen(ret)+2);
    1432           0 :         strcpy(temp,header);
    1433           0 :         strcat(temp,ret);
    1434           0 :         strcat(temp,"\n");
    1435           0 :         free(ret);
    1436           0 :         ret = temp;
    1437             :     }
    1438           0 : return( ret );
    1439             : }
    1440             : 
    1441           0 : static int SameAxes(int cnt1,int cnt2,struct axismap *axismaps1,struct axismap *axismaps2) {
    1442             :     int i,j;
    1443             : 
    1444           0 :     if ( cnt1!=cnt2 )
    1445           0 : return( false );
    1446           0 :     for ( i=0; i<cnt1; ++i ) {
    1447           0 :         if ( axismaps1[i].points!=axismaps2[i].points )
    1448           0 : return( false );
    1449           0 :         for ( j=0; j<axismaps1[i].points; ++j ) {
    1450           0 :             if ( axismaps1[i].designs[j]>=axismaps2[i].designs[j]+.01 ||
    1451           0 :                     axismaps1[i].designs[j]<=axismaps2[i].designs[j]-.01 )
    1452           0 : return( false );
    1453           0 :             if ( axismaps1[i].blends[j]>=axismaps2[i].blends[j]+.001 ||
    1454           0 :                     axismaps1[i].blends[j]<=axismaps2[i].blends[j]-.001 )
    1455           0 : return( false );
    1456             :         }
    1457             :     }
    1458           0 : return( true );
    1459             : }
    1460             : 
    1461           0 : static void AxisDataCopyFree(struct axismap *into,struct axismap *from,int count) {
    1462             :     int i;
    1463             : 
    1464           0 :     for ( i=0; i<4; ++i ) {
    1465           0 :         free(into->blends); free(into->designs);
    1466           0 :         into->blends = NULL; into->designs = NULL;
    1467           0 :         into->points = 0;
    1468             :     }
    1469           0 :     for ( i=0; i<count; ++i ) {
    1470           0 :         into[i].points = from[i].points;
    1471           0 :         into[i].blends = malloc(into[i].points*sizeof(real));
    1472           0 :         memcpy(into[i].blends,from[i].blends,into[i].points*sizeof(real));
    1473           0 :         into[i].designs = malloc(into[i].points*sizeof(real));
    1474           0 :         memcpy(into[i].designs,from[i].designs,into[i].points*sizeof(real));
    1475             :     }
    1476           0 : }
    1477             : 
    1478           0 : static int PositionsMatch(MMSet *old,MMSet *mm) {
    1479             :     int i,j;
    1480             : 
    1481           0 :     for ( i=0; i<old->instance_count; ++i ) {
    1482           0 :         for ( j=0; j<old->axis_count; ++j )
    1483           0 :             if ( old->positions[i*old->axis_count+j] != mm->positions[i*mm->axis_count+j] )
    1484           0 : return( false );
    1485             :     }
    1486           0 : return( true );
    1487             : }
    1488             : 
    1489           0 : static void MMW_FuncsValid(MMW *mmw) {
    1490             :     unichar_t *ut;
    1491             :     int pos, i;
    1492             : 
    1493           0 :     if ( !SameAxes(mmw->axis_count,mmw->last_axis_count,mmw->mm->axismaps,mmw->last_axismaps)) {
    1494           0 :         if ( mmw->old!=NULL &&
    1495           0 :                 SameAxes(mmw->axis_count,mmw->old->axis_count,mmw->mm->axismaps,mmw->old->axismaps)) {
    1496           0 :             ut = uc_copy(mmw->old->ndv);
    1497             :         } else {
    1498           0 :             char *header = mmw->axis_count==1 ?  "  " :
    1499           0 :                             mmw->axis_count==2 ? "  exch " :
    1500           0 :                             mmw->axis_count==3 ? "  3 -1 roll " :
    1501             :                                                  "  4 -1 roll ";
    1502             :             char *lines[4];
    1503           0 :             for ( i=0; i<mmw->axis_count; ++i )
    1504           0 :                 lines[i] = NormalizeAxis(header,&mmw->mm->axismaps[i]);
    1505           0 :             pos = 0;
    1506           0 :             for ( i=0; i<mmw->axis_count; ++i )
    1507           0 :                 pos += strlen(lines[i]);
    1508           0 :             ut = malloc((pos+20)*sizeof(unichar_t));
    1509           0 :             uc_strcpy(ut,"{\n" ); pos = 2;
    1510           0 :             for ( i=0; i<mmw->axis_count; ++i ) {
    1511           0 :                 uc_strcpy(ut+pos,lines[i]);
    1512           0 :                 pos += strlen(lines[i]);
    1513             :             }
    1514           0 :             uc_strcpy(ut+pos,"}" );
    1515             :         }
    1516           0 :         GGadgetSetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_NDV),
    1517             :                 ut);
    1518           0 :         free(ut);
    1519           0 :         AxisDataCopyFree(mmw->last_axismaps,mmw->mm->axismaps,mmw->axis_count);
    1520           0 :         mmw->last_axis_count = mmw->axis_count;
    1521             :     }
    1522           0 :     if ( mmw->last_instance_count!=mmw->instance_count ) {
    1523           0 :         if ( standard_cdvs[4]==NULL ) {
    1524           0 :             standard_cdvs[4] = malloc(strlen(cdv_4axis[0])+strlen(cdv_4axis[1])+
    1525           0 :                     strlen(cdv_4axis[2])+2);
    1526           0 :             strcpy(standard_cdvs[4],cdv_4axis[0]);
    1527           0 :             strcat(standard_cdvs[4],cdv_4axis[1]);
    1528           0 :             strcat(standard_cdvs[4],cdv_4axis[2]);
    1529             :         }
    1530           0 :         if ( mmw->old!=NULL &&
    1531           0 :                 mmw->axis_count==mmw->old->axis_count &&
    1532           0 :                 mmw->instance_count==mmw->old->instance_count &&
    1533           0 :                 PositionsMatch(mmw->old,mmw->mm)) {
    1534           0 :             ut = uc_copy(mmw->old->cdv);
    1535           0 :         } else if ( mmw->instance_count==(1<<mmw->axis_count) &&
    1536           0 :                 StandardPositions(mmw->mm,mmw->instance_count,mmw->axis_count,false)) {
    1537           0 :             ut = uc_copy(standard_cdvs[mmw->axis_count]);
    1538           0 :         } else if ( mmw->axis_count==1 &&
    1539           0 :                 OrderedPositions(mmw->mm,mmw->instance_count,false)) {
    1540           0 :             ut = Figure1AxisCDV(mmw);
    1541             :         } else {
    1542           0 :             ut = uc_copy("");
    1543             :         }
    1544           0 :         GGadgetSetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_CDV),
    1545             :                 ut);
    1546           0 :         free(ut);
    1547             :     }
    1548           0 :     mmw->last_instance_count = mmw->instance_count;
    1549           0 : }
    1550             : 
    1551           0 : static void MMW_WeightsValid(MMW *mmw) {
    1552             :     char *temp;
    1553             :     unichar_t *ut, *utc;
    1554             :     int pos, i;
    1555             :     real axiscoords[4], weights[2*MmMax];
    1556             : 
    1557           0 :     if ( mmw->lastw_instance_count!=mmw->instance_count ) {
    1558           0 :         temp = malloc(mmw->instance_count*20+1);
    1559           0 :         pos = 0;
    1560           0 :         if ( mmw->old!=NULL && mmw->instance_count==mmw->old->instance_count ) {
    1561           0 :             for ( i=0; i<mmw->instance_count; ++i ) {
    1562           0 :                 sprintf(temp+pos,"%g ", (double) mmw->old->defweights[i] );
    1563           0 :                 pos += strlen(temp+pos);
    1564             :             }
    1565           0 :             utc = MMDesignCoords(mmw->old);
    1566             :         } else {
    1567           0 :             for ( i=0; i<mmw->axis_count; ++i ) {
    1568           0 :                 if ( strcmp(mmw->mm->axes[i],"Weight")==0 &&
    1569           0 :                         400>=mmw->mm->axismaps[i].designs[0] &&
    1570           0 :                         400<=mmw->mm->axismaps[i].designs[mmw->mm->axismaps[i].points-1])
    1571           0 :                     axiscoords[i] = 400;
    1572           0 :                 else if ( strcmp(mmw->mm->axes[i],"OpticalSize")==0 &&
    1573           0 :                         12>=mmw->mm->axismaps[i].designs[0] &&
    1574           0 :                         12<=mmw->mm->axismaps[i].designs[mmw->mm->axismaps[i].points-1])
    1575           0 :                     axiscoords[i] = 12;
    1576             :                 else
    1577           0 :                     axiscoords[i] = (mmw->mm->axismaps[i].designs[0]+
    1578           0 :                             mmw->mm->axismaps[i].designs[mmw->mm->axismaps[i].points-1])/2;
    1579             :             }
    1580           0 :             i = ExecConvertDesignVector(axiscoords,mmw->axis_count,mmw->mm->ndv,mmw->mm->cdv,
    1581             :                     weights);
    1582           0 :             if ( i!=mmw->instance_count ) {  /* The functions don't work */
    1583           0 :                 for ( i=0; i<mmw->instance_count; ++i )
    1584           0 :                     weights[i] = 1.0/mmw->instance_count;
    1585           0 :                 utc = uc_copy("");
    1586             :             } else {
    1587           0 :                 for ( i=0; i<mmw->axis_count; ++i ) {
    1588           0 :                     sprintf(temp+pos,"%g ", (double) axiscoords[i] );
    1589           0 :                     pos += strlen(temp+pos);
    1590             :                 }
    1591           0 :                 temp[pos-1] = '\0';
    1592           0 :                 utc = uc_copy(temp);
    1593           0 :                 pos = 0;
    1594             :             }
    1595           0 :             for ( i=0; i<mmw->instance_count; ++i ) {
    1596           0 :                 sprintf(temp+pos,"%g ", (double) weights[i] );
    1597           0 :                 pos += strlen(temp+pos);
    1598             :             }
    1599             :         }
    1600           0 :         temp[pos-1] = '\0';
    1601           0 :         ut = uc_copy(temp);
    1602           0 :         GGadgetSetTitle(GWidgetGetControl(mmw->subwins[mmw_others],CID_NewBlends),
    1603             :                 ut);
    1604           0 :         free(temp); free(ut);
    1605             : 
    1606           0 :         GGadgetSetTitle(GWidgetGetControl(mmw->subwins[mmw_others],CID_NewDesign),utc);
    1607           0 :         free(utc);
    1608           0 :         mmw->lastw_instance_count = mmw->instance_count;
    1609             :     }
    1610           0 : }
    1611             : 
    1612           0 : static GTextInfo *NamedDesigns(MMW *mmw) {
    1613             :     int cnt, i, j;
    1614             :     GTextInfo *ti;
    1615             :     char buffer[120], *pt;
    1616             :     char *ustyle;
    1617             : 
    1618           0 :     if ( !mmw->mm->apple || mmw->old==NULL )
    1619           0 : return( NULL );
    1620             : 
    1621           0 :     cnt = mmw->old->named_instance_count;
    1622           0 :     ti = calloc((cnt+1),sizeof(GTextInfo));
    1623           0 :     for ( i=0; i<mmw->old->named_instance_count; ++i ) {
    1624           0 :         pt = buffer; *pt++='[';
    1625           0 :         for ( j=0; j<mmw->old->axis_count; ++j ) {
    1626           0 :             sprintf( pt, "%.4g ", (double) mmw->old->named_instances[i].coords[j]);
    1627           0 :             pt += strlen(pt);
    1628             :         }
    1629           0 :         pt[-1] = ']';
    1630           0 :         ustyle = PickNameFromMacName(mmw->old->named_instances[i].names);
    1631           0 :         ti[i].bg = ti[i].fg = COLOR_DEFAULT;
    1632           0 :         ti[i].text = malloc((strlen(buffer)+3+strlen(ustyle))*sizeof(unichar_t));
    1633           0 :         utf82u_strcpy(ti[i].text,ustyle);
    1634           0 :         uc_strcat(ti[i].text," ");
    1635           0 :         uc_strcat(ti[i].text,buffer);
    1636           0 :         ti[i].userdata = MacNameCopy(mmw->old->named_instances[i].names);
    1637           0 :         free(ustyle);
    1638             :     }
    1639             : 
    1640           0 : return(ti);
    1641             : }
    1642             : 
    1643           0 : static GTextInfo *TiFromFont(SplineFont *sf) {
    1644           0 :     GTextInfo *ti = calloc(1,sizeof(GTextInfo));
    1645           0 :     ti->text = uc_copy(sf->fontname);
    1646           0 :     ti->fg = ti->bg = COLOR_DEFAULT;
    1647           0 :     ti->userdata = sf;
    1648           0 : return( ti );
    1649             : }
    1650             : 
    1651           0 : static GTextInfo **FontList(MMW *mmw, int instance, int *sel) {
    1652             :     FontView *fv;
    1653             :     int cnt, i, pos;
    1654             :     GTextInfo **ti;
    1655             : 
    1656           0 :     cnt = 0;
    1657           0 :     if ( mmw->old!=NULL ) {
    1658           0 :         cnt = mmw->old->instance_count;
    1659           0 :         if ( mmw->old->apple )
    1660           0 :             ++cnt;
    1661             :     }
    1662           0 :     for ( fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
    1663           0 :         if ( fv->b.cidmaster==NULL && fv->b.sf->mm==NULL )
    1664           0 :             ++cnt;
    1665             :     }
    1666           0 :     cnt += mmw->lcnt;
    1667             : 
    1668           0 :     ++cnt;      /* New */
    1669           0 :     ++cnt;      /* Browse... */
    1670             : 
    1671           0 :     ti = malloc((cnt+1)*sizeof(GTextInfo *));
    1672           0 :     pos = -1;
    1673           0 :     cnt = 0;
    1674           0 :     if ( mmw->old!=NULL ) {
    1675           0 :         for ( i=0; i<mmw->old->instance_count; ++i ) {
    1676           0 :             if ( mmw->old->instances[i]==mmw->mm->instances[instance] ) pos = cnt;
    1677           0 :             ti[cnt++] = TiFromFont(mmw->old->instances[i]);
    1678             :         }
    1679           0 :         if ( mmw->old->apple ) {
    1680           0 :             if ( mmw->old->normal==mmw->mm->instances[instance] ) pos = cnt;
    1681           0 :             ti[cnt++] = TiFromFont(mmw->old->normal);
    1682             :         }
    1683             :     }
    1684           0 :     for ( fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
    1685           0 :         if ( fv->b.cidmaster==NULL && fv->b.sf->mm==NULL ) {
    1686           0 :             if ( fv->b.sf==mmw->mm->instances[instance] ) pos = cnt;
    1687           0 :             ti[cnt++] = TiFromFont(fv->b.sf);
    1688             :         }
    1689             :     }
    1690           0 :     for ( i=0; i<mmw->lcnt; ++i ) {
    1691           0 :         if ( mmw->loaded[i]==mmw->mm->instances[instance] ) pos = cnt;
    1692           0 :         ti[cnt++] = TiFromFont( mmw->loaded[i]);
    1693             :     }
    1694           0 :     if ( pos==-1 ) pos=cnt;
    1695           0 :     ti[cnt] = calloc(1,sizeof(GTextInfo));
    1696           0 :     ti[cnt]->text = utf82u_copy(S_("Font|New"));
    1697           0 :     ti[cnt]->bg = ti[cnt]->fg = COLOR_DEFAULT;
    1698           0 :     ++cnt;
    1699           0 :     ti[cnt] = calloc(1,sizeof(GTextInfo));
    1700           0 :     ti[cnt]->text = utf82u_copy(_("Browse..."));
    1701           0 :     ti[cnt]->bg = ti[cnt]->fg = COLOR_DEFAULT;
    1702           0 :     ti[cnt]->userdata = (void *) (-1);
    1703           0 :     ++cnt;
    1704           0 :     ti[cnt] = calloc(1,sizeof(GTextInfo));
    1705             : 
    1706           0 :     ti[pos]->selected = true;
    1707           0 :     *sel = pos;
    1708             : 
    1709           0 : return(ti);
    1710             : }
    1711             : 
    1712           0 : static void MMW_DesignsSetup(MMW *mmw) {
    1713             :     int i,j,sel;
    1714             :     char buffer[80], *pt;
    1715             :     unichar_t ubuf[80];
    1716             :     GTextInfo **ti;
    1717             : 
    1718           0 :     for ( i=0; i<mmw->instance_count; ++i ) {
    1719           0 :         GGadget *list = GWidgetGetControl(mmw->subwins[mmw_designs],CID_DesignFonts+i*DesignScaleFactor);
    1720           0 :         ti = FontList(mmw,i,&sel);
    1721           0 :         GGadgetSetList(list, ti,false);
    1722           0 :         GGadgetSetTitle(list, ti[sel]->text);
    1723           0 :         pt = buffer;
    1724           0 :         for ( j=0; j<mmw->axis_count; ++j ) {
    1725           0 :             sprintf(pt,"%g ",(double) mmw->mm->positions[i*4+j]);
    1726           0 :             pt += strlen(pt);
    1727             :         }
    1728           0 :         if ( pt>buffer ) pt[-1] = '\0';
    1729           0 :         uc_strcpy(ubuf,buffer);
    1730           0 :         GGadgetSetTitle(GWidgetGetControl(mmw->subwins[mmw_designs],CID_AxisWeights+i*DesignScaleFactor),
    1731             :                 ubuf);
    1732             :     }
    1733           0 : }
    1734             : 
    1735           0 : static void MMW_ParseNamedStyles(MMSet *setto,MMW *mmw) {
    1736           0 :     GGadget *list = GWidgetGetControl(mmw->subwins[mmw_named],CID_NamedDesigns);
    1737             :     int32 i,j,len;
    1738           0 :     GTextInfo **ti = GGadgetGetList(list,&len);
    1739             :     unichar_t *upt, *end;
    1740             : 
    1741           0 :     setto->named_instance_count = len;
    1742           0 :     if ( len!=0 ) {
    1743           0 :         setto->named_instances = calloc(len,sizeof(struct named_instance));
    1744           0 :         for ( i=0; i<len; ++i ) {
    1745           0 :             setto->named_instances[i].coords = calloc(setto->axis_count,sizeof(real));
    1746           0 :             upt = u_strchr(ti[i]->text,'[');
    1747           0 :             if ( upt!=NULL ) {
    1748           0 :                 for ( j=0, ++upt; j<setto->axis_count; ++j ) {
    1749           0 :                     setto->named_instances[i].coords[j] = rint(u_strtod(upt,&end)*8096)/8096;
    1750           0 :                     if ( *end==' ' ) ++end;
    1751           0 :                     upt = end;
    1752             :                 }
    1753             :             }
    1754           0 :             setto->named_instances[i].names = ti[i]->userdata;
    1755           0 :             ti[i]->userdata = NULL;
    1756             :         }
    1757             :     }
    1758           0 : }
    1759             : 
    1760           0 : static void MMW_DoOK(MMW *mmw) {
    1761             :     real weights[AppleMmMax+1];
    1762             :     real fbt;
    1763           0 :     int err = false;
    1764           0 :     char *familyname, *fn, *origname=NULL;
    1765             :     int i,j;
    1766             :     MMSet *setto, *dlgmm;
    1767           0 :     FontView *fv = NULL;
    1768           0 :     int isapple = GGadgetIsChecked(GWidgetGetControl(mmw->subwins[mmw_counts],CID_Apple));
    1769             :     int defpos;
    1770           0 :     struct psdict *oldprivate = NULL;
    1771           0 :     Encoding *enc = NULL;
    1772             : 
    1773           0 :     if ( !isapple ) {
    1774           0 :         if ( !GetWeights(mmw->gw, weights, mmw->mm, mmw->instance_count, mmw->axis_count))
    1775           0 : return;
    1776           0 :         fbt = GetReal8(mmw->subwins[mmw_others],CID_ForceBoldThreshold,
    1777             :                         _("Force Bold Threshold:"),&err);
    1778           0 :         if ( err )
    1779           0 : return;
    1780             :     }
    1781             : 
    1782           0 :     familyname = cu_copy(_GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_counts],CID_FamilyName)));
    1783             :     /* They only need specify a family name if there are new fonts */
    1784           0 :     if ( *familyname=='\0' ) {
    1785           0 :         free(familyname);
    1786           0 :         for ( i=0; i<mmw->instance_count; ++i )
    1787           0 :             if ( mmw->mm->instances[i]==NULL )
    1788           0 :         break;
    1789             :             else
    1790           0 :                 fn = mmw->mm->instances[i]->familyname;
    1791           0 :         if ( i!=mmw->instance_count ) {
    1792           0 :             ff_post_error(_("Bad Multiple Master Font"),_("A Font Family name is required"));
    1793           0 : return;
    1794             :         }
    1795           0 :         familyname = copy(fn);
    1796             :     }
    1797             : 
    1798             :     /* Did we have a fontview open on this mm? */
    1799           0 :     if ( mmw->old!=NULL ) {
    1800           0 :         for ( j=0; j<mmw->old->instance_count; ++j )
    1801           0 :             if ( mmw->old->instances[j]->fv!=NULL ) {
    1802           0 :                 fv = (FontView *) mmw->old->instances[j]->fv;
    1803           0 :                 origname = copy(mmw->old->instances[j]->origname);
    1804           0 :                 enc = fv->b.map->enc;
    1805           0 :         break;
    1806             :             }
    1807             :     }
    1808             : 
    1809             :     /* Make sure we free all fonts that we have lying around and aren't going */
    1810             :     /* to be using. (ones we opened, ones in the old version of the mm). Also */
    1811             :     /* if any font we want to use is attached to a fontview, then close the */
    1812             :     /* window */
    1813           0 :     for ( i=0; i<mmw->instance_count; ++i ) if ( mmw->mm->instances[i]!=NULL ) {
    1814           0 :         if ( mmw->old!=NULL ) {
    1815           0 :             for ( j=0; j<mmw->old->instance_count; ++j )
    1816           0 :                 if ( mmw->mm->instances[i]==mmw->old->instances[j] )
    1817           0 :             break;
    1818           0 :             if ( j!=mmw->old->instance_count ) {
    1819           0 :                 mmw->old->instances[j] = NULL;
    1820           0 :     continue;
    1821           0 :             } else if ( mmw->old->normal==mmw->mm->instances[i] ) {
    1822           0 :                 mmw->old->normal = NULL;
    1823           0 :     continue;
    1824             :             }
    1825             :         }
    1826           0 :         for ( j=0; j<mmw->lcnt; ++j )
    1827           0 :             if ( mmw->mm->instances[i]==mmw->loaded[j] )
    1828           0 :         break;
    1829           0 :         if ( j!=mmw->lcnt ) {
    1830           0 :             mmw->loaded[j] = NULL;
    1831           0 : continue;
    1832             :         }
    1833           0 :         if ( enc==NULL && mmw->mm->instances[i]->fv!=NULL )
    1834           0 :             enc = mmw->mm->instances[i]->fv->map->enc;
    1835           0 :         MMUsurpNew(mmw->mm->instances[i]);
    1836             :     }
    1837           0 :     if ( mmw->old!=NULL ) {
    1838           0 :         for ( j=0; j<mmw->old->instance_count; ++j )
    1839           0 :             if ( mmw->old->instances[j]!=NULL ) {
    1840           0 :                 MMDetachOld(mmw->old->instances[j]);
    1841           0 :                 mmw->old->instances[j] = NULL;
    1842             :             }
    1843           0 :         if ( mmw->old->normal!=NULL ) {
    1844           0 :             oldprivate = mmw->old->normal->private;
    1845           0 :             mmw->old->normal->private = NULL;
    1846           0 :             MMDetachOld(mmw->old->normal);
    1847           0 :             mmw->old->normal = NULL;
    1848             :         }
    1849             :     }
    1850           0 :     for ( j=0; j<mmw->lcnt; ++j ) {
    1851           0 :         if ( mmw->loaded[j]!=NULL ) {
    1852           0 :             MMDetachNew(mmw->loaded[j]);
    1853           0 :             mmw->loaded[j] = NULL;
    1854             :         }
    1855             :     }
    1856             : 
    1857           0 :     dlgmm = mmw->mm;
    1858           0 :     setto = mmw->old;
    1859           0 :     if ( setto!=NULL ) {
    1860           0 :         MMSetFreeContents(setto);
    1861           0 :         memset(setto,0,sizeof(MMSet));
    1862             :     } else
    1863           0 :         setto = chunkalloc(sizeof(MMSet));
    1864           0 :     setto->apple = isapple;
    1865           0 :     setto->axis_count = mmw->axis_count;
    1866           0 :     setto->instance_count = mmw->instance_count;
    1867           0 :     defpos = mmw->instance_count;
    1868           0 :     if ( isapple ) {
    1869           0 :         for ( defpos=0; defpos<mmw->instance_count; ++defpos ) {
    1870           0 :             for ( j=0; j<mmw->axis_count; ++j )
    1871           0 :                 if ( dlgmm->positions[defpos*dlgmm->axis_count+j]!=0 )
    1872           0 :             break;
    1873           0 :             if ( j==mmw->axis_count )
    1874           0 :         break;
    1875             :         }
    1876           0 :         if ( defpos==mmw->instance_count )
    1877           0 :             --defpos;
    1878           0 :         --setto->instance_count;
    1879           0 :         setto->normal = dlgmm->instances[defpos];
    1880           0 :         if ( setto->normal!=NULL )
    1881           0 :             setto->normal->mm = setto;
    1882             :     }
    1883           0 :     for ( i=0; i<setto->axis_count; ++i )
    1884           0 :         setto->axes[i] = dlgmm->axes[i];
    1885           0 :     setto->axismaps = dlgmm->axismaps;
    1886           0 :     setto->defweights = calloc(setto->instance_count,sizeof(real));
    1887           0 :     if ( !isapple )
    1888           0 :         memcpy(setto->defweights,weights,setto->instance_count*sizeof(real));
    1889           0 :     free(dlgmm->defweights);
    1890           0 :     setto->positions = malloc(setto->instance_count*setto->axis_count*sizeof(real));
    1891           0 :     for ( i=0; i<setto->instance_count; ++i ) {
    1892           0 :         int k = i<defpos ? i : i+1;
    1893           0 :         memcpy(setto->positions+i*setto->axis_count,dlgmm->positions+k*dlgmm->axis_count,
    1894           0 :                 setto->axis_count*sizeof(real));
    1895             :     }
    1896           0 :     free(dlgmm->positions);
    1897           0 :     setto->instances = calloc(setto->instance_count,sizeof(SplineFont *));
    1898           0 :     for ( i=0; i<setto->instance_count; ++i ) {
    1899           0 :         if ( dlgmm->instances[i]!=NULL ) {
    1900           0 :             int k = i<defpos ? i : i+1;
    1901           0 :             setto->instances[i] = dlgmm->instances[k];
    1902           0 :             setto->instances[i]->mm = setto;
    1903             :         }
    1904             :     }
    1905           0 :     MMMatchGlyphs(setto);
    1906           0 :     if ( setto->normal==NULL ) {
    1907           0 :         setto->normal = MMNewFont(setto,-1,familyname);
    1908           0 :         setto->normal->private = oldprivate;
    1909             :     }
    1910           0 :     if ( !isapple ) {
    1911           0 :         if ( fbt>0 && fbt<=1 ) {
    1912             :             char buffer[20];
    1913           0 :             sprintf(buffer,"%g", (double) fbt );
    1914           0 :             if ( oldprivate==NULL )
    1915           0 :                 setto->normal->private = calloc(1,sizeof(struct psdict));
    1916           0 :             PSDictChangeEntry(setto->normal->private,"ForceBoldThreshold",buffer);
    1917             :         }
    1918             :     }
    1919           0 :     if ( !isapple ) {
    1920           0 :         setto->cdv = dlgmm->cdv;
    1921           0 :         setto->ndv = dlgmm->ndv;
    1922             :     } else
    1923           0 :         MMW_ParseNamedStyles(setto,mmw);
    1924           0 :     for ( i=0; i<setto->instance_count; ++i ) {
    1925           0 :         if ( setto->instances[i]==NULL )
    1926           0 :             setto->instances[i] = MMNewFont(setto,i,familyname);
    1927           0 :         setto->instances[i]->fv = (FontViewBase *) fv;
    1928             :     }
    1929           0 :     free(dlgmm->instances);
    1930           0 :     chunkfree(dlgmm,sizeof(MMSet));
    1931           0 :     if ( origname!=NULL ) {
    1932           0 :         for ( i=0; i<setto->instance_count; ++i ) {
    1933           0 :             free(setto->instances[i]->origname);
    1934           0 :             setto->instances[i]->origname = copy(origname);
    1935             :         }
    1936           0 :         free(setto->normal->origname);
    1937           0 :         setto->normal->origname = origname;
    1938             :     } else {
    1939           0 :         for ( i=0; i<setto->instance_count; ++i ) {
    1940           0 :             free(setto->instances[i]->origname);
    1941           0 :             setto->instances[i]->origname = copy(setto->normal->origname);
    1942             :         }
    1943             :     }
    1944           0 :     if ( !isapple )
    1945           0 :         MMReblend((FontViewBase *) fv,setto);
    1946           0 :     if ( fv!=NULL ) {
    1947           0 :         for ( i=0; i<setto->instance_count; ++i )
    1948           0 :             if ( fv->b.sf==setto->instances[i])
    1949           0 :         break;
    1950           0 :         if ( i==setto->instance_count ) {
    1951           0 :             SplineFont *sf = setto->normal;
    1952             :             BDFFont *bdf;
    1953           0 :             int same = fv->filled == fv->show;
    1954           0 :             fv->b.sf = sf;
    1955           0 :             bdf = SplineFontPieceMeal(fv->b.sf,ly_fore,sf->display_size<0?-sf->display_size:default_fv_font_size,72,
    1956           0 :                     (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0),
    1957             :                     NULL);
    1958           0 :             BDFFontFree(fv->filled);
    1959           0 :             fv->filled = bdf;
    1960           0 :             if ( same )
    1961           0 :                 fv->show = bdf;
    1962             :         }
    1963             :     }
    1964           0 :     free(familyname);
    1965             : 
    1966             :     /* Multi-Mastered bitmaps don't make much sense */
    1967             :     /* Well, maybe grey-scaled could be interpolated, but yuck */
    1968           0 :     for ( i=0; i<setto->instance_count; ++i ) {
    1969             :         BDFFont *bdf, *bnext;
    1970           0 :         for ( bdf = setto->instances[i]->bitmaps; bdf!=NULL; bdf = bnext ) {
    1971           0 :             bnext = bdf->next;
    1972           0 :             BDFFontFree(bdf);
    1973             :         }
    1974           0 :         setto->instances[i]->bitmaps = NULL;
    1975             :     }
    1976             : 
    1977           0 :     if ( fv==NULL )
    1978           0 :         fv = (FontView *) FontViewCreate(setto->normal,false);
    1979           0 :     if ( enc==NULL )
    1980           0 :         enc = default_encoding;
    1981           0 :     FVReencode((FontViewBase *) fv,enc);
    1982           0 :     mmw->done = true;
    1983             : }
    1984             : 
    1985           0 : static void MMW_DoNext(MMW *mmw) {
    1986             :     int i, err;
    1987             :     real start, end, def, *designs, *norm;
    1988             :     int n, n2;
    1989           0 :     int isapple = GGadgetIsChecked(GWidgetGetControl(mmw->subwins[mmw_counts],CID_Apple));
    1990             :     char *yesno[3];
    1991           0 :     yesno[0] = _("_Yes"); yesno[1] = _("_No"); yesno[2] = NULL;
    1992             : 
    1993           0 :     if ( mmw->state==mmw_others )
    1994           0 : return;
    1995             : 
    1996           0 :     if ( mmw->state==mmw_counts ) {
    1997           0 :         mmw->axis_count = GGadgetGetFirstListSelectedItem(GWidgetGetControl(mmw->subwins[mmw_counts],CID_AxisCount))+1;
    1998           0 :         mmw->instance_count = GGadgetGetFirstListSelectedItem(GWidgetGetControl(mmw->subwins[mmw_counts],CID_MasterCount))+1;
    1999             :         /* Arrays are already allocated out to maximum, and we will just leave*/
    2000             :         /*  them there until user hits OK, then we make them the right size */
    2001           0 :         for ( i=0; i<4; ++i )
    2002           0 :             GTabSetSetEnabled(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2003           0 :                     i,i<mmw->axis_count);
    2004           0 :         for ( i=0; i<AppleMmMax+1; ++i )
    2005           0 :             GTabSetSetEnabled(GWidgetGetControl(mmw->subwins[mmw_designs],CID_WhichDesign),
    2006           0 :                     i,i<mmw->instance_count);
    2007             :         /* If we've changed the axis count, and the old selected axis isn't */
    2008             :         /*  available any more, choose another one */
    2009           0 :         if ( GTabSetGetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis))>=
    2010           0 :                 mmw->axis_count )
    2011           0 :             GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2012             :                     0);
    2013           0 :         if ( isapple ) {
    2014           0 :             int cnt = 1;
    2015           0 :             for ( i=0; i<mmw->axis_count; ++i ) cnt *= 3;
    2016           0 :             if ( mmw->instance_count==cnt ) {
    2017           0 :                 for ( i=(mmw->old==NULL)?0:mmw->old->instance_count; i<mmw->instance_count-1; ++i ) {
    2018           0 :                     int j = (i>=(cnt-1)/2) ? i+1 : i;
    2019           0 :                     mmw->mm->positions[i*4  ] = (j%3==0) ? -1: (j%3==1) ? 0 : 1;
    2020           0 :                     mmw->mm->positions[i*4+1] = ((j/3)%3==0) ? -1: ((j/3)%3==1) ? 0 : 1;
    2021           0 :                     mmw->mm->positions[i*4+2] = ((j/9)%3==0) ? -1: ((j/9)%3==1) ? 0 : 1;
    2022           0 :                     mmw->mm->positions[i*4+3] = ((j/27)%3==0) ? -1: ((j/27)%3==1) ? 0 : 1;
    2023             :                 }
    2024             :                 /* Place the default psuedo-instance last */
    2025           0 :                 mmw->mm->positions[i*4  ] = 0;
    2026           0 :                 mmw->mm->positions[i*4+1] = 0;
    2027           0 :                 mmw->mm->positions[i*4+2] = 0;
    2028           0 :                 mmw->mm->positions[i*4+3] = 0;
    2029             :             }
    2030             :         } else {
    2031           0 :             if ( mmw->instance_count==(1<<mmw->axis_count) ) {
    2032           0 :                 for ( i=(mmw->old==NULL)?0:mmw->old->instance_count; i<mmw->instance_count; ++i ) {
    2033           0 :                     mmw->mm->positions[i*4  ] = (i&1) ? 1 : 0;
    2034           0 :                     mmw->mm->positions[i*4+1] = (i&2) ? 1 : 0;
    2035           0 :                     mmw->mm->positions[i*4+2] = (i&4) ? 1 : 0;
    2036           0 :                     mmw->mm->positions[i*4+3] = (i&8) ? 1 : 0;
    2037             :                 }
    2038             :             }
    2039             :         }
    2040           0 :     } else if ( mmw->state==mmw_axes ) {
    2041           0 :         for ( i=0; i<mmw->axis_count; ++i ) {
    2042           0 :             free(mmw->mm->axes[i]);
    2043           0 :             mmw->mm->axes[i] = cu_copy(_GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_axes],CID_AxisType+i*100)));
    2044           0 :             if ( *mmw->mm->axes[i]=='\0' ) {
    2045           0 :                 GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2046             :                         i);
    2047           0 :                 ff_post_error(_("Bad Axis"),_("Please set the Axis Type field"));
    2048           0 : return;         /* Failure */
    2049             :             }
    2050             :             /* Don't free the current value. If it is non-null then it just */
    2051             :             /*  points into the data structure that the Names gadgets manipulate */
    2052             :             /*  and they will have done any freeing that needs doing. Freeing */
    2053             :             /*  it here would destroy the data they work on */
    2054             :             /*MacNameListFree(mmw->mm->axismaps[i].axisnames);*/
    2055           0 :             mmw->mm->axismaps[i].axisnames = NULL;
    2056           0 :             if ( isapple ) {
    2057           0 :                 mmw->mm->axismaps[i].axisnames = NameGadgetsGetNames(GTabSetGetSubwindow(
    2058           0 :                         GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),i));
    2059           0 :                 if ( mmw->mm->axismaps[i].axisnames == NULL ) {
    2060           0 :                     GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2061             :                             i);
    2062           0 :                     ff_post_error(_("Bad Axis"),_("When building an Apple distortable font, you must specify at least one name for the axis"));
    2063           0 : return;             /* Failure */
    2064             :                 }
    2065             :             }
    2066           0 :             err = false;
    2067           0 :             start = GetReal8(mmw->subwins[mmw_axes],CID_AxisBegin+i*100,
    2068             :                     _("Begin:"),&err);
    2069           0 :             end = GetReal8(mmw->subwins[mmw_axes],CID_AxisEnd+i*100,
    2070             :                     _("End:"),&err);
    2071           0 :             if ( isapple ) {
    2072           0 :                 def = rint(GetReal8(mmw->subwins[mmw_axes],CID_AxisDefault+i*100,
    2073             :                         S_("AxisValue|Default"),&err)*8096)/8096;
    2074           0 :                 start = rint(start*8096)/8096;
    2075           0 :                 end = rint(end*8096)/8096;
    2076             :             } else
    2077           0 :                 def = start;
    2078           0 :             if ( start>=end || def<start || def>end ) {
    2079           0 :                 GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2080             :                         i);
    2081           0 :                 ff_post_error(_("Bad Axis"),_("Axis range not valid"));
    2082           0 : return;         /* Failure */
    2083             :             }
    2084           0 :             n = ParseList(mmw->subwins[mmw_axes],CID_IntermediateDesign+i*100,
    2085             :                     _("Design Settings:"),&err,start,def,end,&designs,CID_WhichAxis,i,isapple);
    2086           0 :             n2 = ParseList(mmw->subwins[mmw_axes],CID_IntermediateNormalized+i*100,
    2087             :                     _("Normalized Settings:"),&err,
    2088             :                         isapple?-1:0,0,1,&norm,CID_WhichAxis,i,isapple);
    2089           0 :             if ( n!=n2 || err ) {
    2090           0 :                 GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_axes],CID_WhichAxis),
    2091             :                         i);
    2092           0 :                 if ( !err )
    2093           0 :                     ff_post_error(_("Bad Axis"),_("The number of entries in the design settings must match the number in normalized settings"));
    2094           0 :                 free(designs); free(norm);
    2095           0 : return;         /* Failure */
    2096             :             }
    2097           0 :             mmw->mm->axismaps[i].points = n;
    2098           0 :             free(mmw->mm->axismaps[i].blends); free(mmw->mm->axismaps[i].designs);
    2099           0 :             mmw->mm->axismaps[i].blends = norm; mmw->mm->axismaps[i].designs=designs;
    2100           0 :             mmw->mm->axismaps[i].min = start;
    2101           0 :             mmw->mm->axismaps[i].def = def;
    2102           0 :             mmw->mm->axismaps[i].max = end;
    2103             :         }
    2104           0 :     } else if ( mmw->state==mmw_designs ) {
    2105             :         real positions[AppleMmMax+1][4];
    2106             :         int used[AppleMmMax+1];
    2107             :         int j,k,mask, mul;
    2108             :         SplineFont *sfs[AppleMmMax+1];
    2109             :         GTextInfo *ti;
    2110             : 
    2111           0 :         memset(used,0,sizeof(used));
    2112           0 :         memset(positions,0,sizeof(positions));
    2113           0 :         for ( i=0; i<mmw->instance_count; ++i ) {
    2114           0 :             if ( !ParseWeights(mmw->subwins[mmw_designs],CID_AxisWeights+i*DesignScaleFactor,
    2115           0 :                     _("Normalized position of this design along each axis"),positions[i],mmw->axis_count,
    2116             :                     CID_WhichDesign,i))
    2117           0 : return;
    2118           0 :             if ( isapple ) {
    2119           0 :                 mask = 0; mul = 1;
    2120           0 :                 for ( j=0; j<mmw->axis_count; ++j ) {
    2121           0 :                     if ( positions[i][j]==-1 )
    2122             :                         /* Do Nothing */;
    2123           0 :                     else if ( positions[i][j]==0.0 )
    2124           0 :                         mask += mul;
    2125           0 :                     else if ( positions[i][j]==1.0 )
    2126           0 :                         mask += 2*mul;
    2127             :                     else
    2128           0 :                 break;
    2129             :                 }
    2130             :             } else {
    2131           0 :                 mask = 0;
    2132           0 :                 for ( j=0; j<mmw->axis_count; ++j ) {
    2133           0 :                     if ( positions[i][j]==0 )
    2134             :                         /* Do Nothing */;
    2135           0 :                     else if ( positions[i][j]==1.0 )
    2136           0 :                         mask |= (1<<j);
    2137             :                     else
    2138           0 :                 break;
    2139             :                 }
    2140             :             }
    2141           0 :             if ( j==mmw->axis_count )
    2142           0 :                 used[mask] = true;
    2143           0 :             for ( j=0; j<i-1; ++j ) {
    2144           0 :                 for ( k=0; k<mmw->axis_count; ++k )
    2145           0 :                     if ( positions[j][k] != positions[i][k] )
    2146           0 :                 break;
    2147           0 :                 if ( k==mmw->axis_count ) {
    2148             :                     char *temp;
    2149           0 :                     GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_designs],CID_WhichDesign),i);
    2150           0 :                     ff_post_error(_("Bad Multiple Master Font"),_("The set of positions, %.30s, is used more than once"),
    2151           0 :                             temp = GGadgetGetTitle8(GWidgetGetControl(mmw->subwins[mmw_designs],CID_AxisWeights+i*DesignScaleFactor)));
    2152           0 :                     free(temp);
    2153           0 : return;
    2154             :                 }
    2155             :             }
    2156           0 :             ti = GGadgetGetListItemSelected(GWidgetGetControl(mmw->subwins[mmw_designs],CID_DesignFonts+i*DesignScaleFactor));
    2157           0 :             sfs[i] = ti->userdata;
    2158           0 :             if ( sfs[i]!=NULL ) {
    2159           0 :                 for ( j=0; j<i; ++j )
    2160           0 :                     if ( sfs[i]==sfs[j] ) {
    2161           0 :                         GTabSetSetSel(GWidgetGetControl(mmw->subwins[mmw_designs],CID_WhichDesign),i);
    2162           0 :                         ff_post_error(_("Bad Multiple Master Font"),_("The font %.30s is assigned to two master designs"),sfs[i]->fontname);
    2163           0 : return;
    2164             :                     }
    2165             :             }
    2166             :         }
    2167           0 :         for ( i=0; i<(1<<mmw->axis_count); ++i ) if ( !used[i] ) {
    2168           0 :             char buffer[20], *pt = buffer;
    2169           0 :             for ( j=0; j<mmw->axis_count; ++j ) {
    2170           0 :                 sprintf( pt, "%d ", (i&(1<<j))? 1: 0 );
    2171           0 :                 pt += 2;
    2172             :             }
    2173           0 :             if ( !isapple ) {
    2174           0 :                 ff_post_error(_("Bad Multiple Master Font"),_("The set of positions, %.30s, is not specified in any design (and should be)"), buffer );
    2175           0 : return;
    2176             :             } else {
    2177           0 :                 if ( gwwv_ask(_("Bad Multiple Master Font"),(const char **) yesno,0,1,_("The set of positions, %.30s, is not specified in any design.\nIs that what you want?"),buffer)==1 )
    2178           0 : return;
    2179             :             }
    2180             :         }
    2181           0 :         memcpy(mmw->mm->positions,positions,sizeof(positions));
    2182           0 :         for ( i=0; i<mmw->instance_count; ++i )
    2183           0 :             mmw->mm->instances[i] = sfs[i];
    2184           0 :         if ( mmw->old!=NULL &&
    2185           0 :                 mmw->axis_count==mmw->old->axis_count &&
    2186           0 :                 mmw->instance_count==mmw->old->instance_count &&
    2187           0 :                 PositionsMatch(mmw->old,mmw->mm))
    2188             :             /* It's what the font started with, don't complain, already has a cdv */;
    2189           0 :         else if ( mmw->instance_count==(1<<mmw->axis_count) &&
    2190           0 :                 StandardPositions(mmw->mm,mmw->instance_count,mmw->axis_count,isapple))
    2191             :             /* It's arranged as we expect it to be */;
    2192           0 :         else if ( mmw->axis_count==1 &&
    2193           0 :                 OrderedPositions(mmw->mm,mmw->instance_count,isapple))
    2194             :             /* It's arranged according to our secondary expectations */;
    2195           0 :         else if ( !isapple && (mmw->instance_count==(1<<mmw->axis_count) ||
    2196           0 :                 mmw->axis_count==1 )) {
    2197           0 :             if ( gwwv_ask(_("Disordered designs"),(const char **) yesno,0,1,_("The master designs are not positioned in the expected order. FontForge will be unable to suggest a ConvertDesignVector for you. Is this what you want?"))==1 )
    2198           0 : return;
    2199             :         }
    2200           0 :     } else if ( mmw->state==mmw_funcs ) {
    2201           0 :         if ( *_GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_NDV))=='\0' ||
    2202           0 :                 *_GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_CDV))=='\0' ) {
    2203           0 :             ff_post_error(_("Bad PostScript function"),_("Bad PostScript function"));
    2204           0 : return;
    2205             :         }
    2206           0 :         free(mmw->mm->ndv); free(mmw->mm->cdv);
    2207           0 :         mmw->mm->ndv = cu_copy( _GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_NDV)));
    2208           0 :         mmw->mm->cdv = cu_copy( _GGadgetGetTitle(GWidgetGetControl(mmw->subwins[mmw_funcs],CID_CDV)));
    2209             :     }
    2210             : 
    2211           0 :     if ( mmw->state==mmw_designs && !isapple )
    2212           0 :         mmw->state += 2;
    2213             :     else
    2214           0 :         ++mmw->state;
    2215           0 :     if ( mmw->state==mmw_others )
    2216           0 :         MMW_WeightsValid(mmw);
    2217           0 :     else if ( mmw->state==mmw_funcs )
    2218           0 :         MMW_FuncsValid(mmw);
    2219           0 :     else if ( mmw->state==mmw_designs )
    2220           0 :         MMW_DesignsSetup(mmw);
    2221           0 :     MMW_SetState(mmw);
    2222             : }
    2223             : 
    2224           0 : static void MMW_SimulateDefaultButton(MMW *mmw) {
    2225           0 :     if ( mmw->state==mmw_others || mmw->state==mmw_named )
    2226           0 :         MMW_DoOK(mmw);
    2227             :     else
    2228           0 :         MMW_DoNext(mmw);
    2229           0 : }
    2230             : 
    2231           0 : static int MMW_OK(GGadget *g, GEvent *e) {
    2232           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2233           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2234           0 :         MMW_DoOK(mmw);
    2235             :     }
    2236           0 : return( true );
    2237             : }
    2238             : 
    2239           0 : static int MMW_Next(GGadget *g, GEvent *e) {
    2240           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2241           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2242           0 :         MMW_DoNext(mmw);
    2243             :     }
    2244           0 : return( true );
    2245             : }
    2246             : 
    2247           0 : static int MMW_Prev(GGadget *g, GEvent *e) {
    2248           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2249           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2250           0 :         if ( mmw->state!=mmw_counts ) {
    2251           0 :             if ( mmw->state==mmw_funcs )
    2252           0 :                 mmw->state = mmw_designs;
    2253             :             else
    2254           0 :                 --mmw->state;
    2255           0 :             MMW_SetState(mmw);
    2256             :         }
    2257             :     }
    2258           0 : return( true );
    2259             : }
    2260             : 
    2261           0 : static int MMW_NamedNew(GGadget *g, GEvent *e) {
    2262           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2263           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2264           0 :         EditStyleName(mmw,-1);
    2265             :     }
    2266           0 : return( true );
    2267             : }
    2268             : 
    2269           0 : static int MMW_NamedEdit(GGadget *g, GEvent *e) {
    2270           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2271           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2272           0 :         EditStyleName(mmw,GGadgetGetFirstListSelectedItem(GWidgetGetControl(mmw->subwins[mmw_named],CID_NamedDesigns)));
    2273             :     }
    2274           0 : return( true );
    2275             : }
    2276             : 
    2277           0 : static int MMW_NamedDelete(GGadget *g, GEvent *e) {
    2278           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
    2279           0 :         GWindow gw = GGadgetGetWindow(g);
    2280           0 :         GGadget *list = GWidgetGetControl(gw,CID_NamedDesigns);
    2281             :         int32 i,len;
    2282           0 :         GTextInfo **ti = GGadgetGetList(list,&len);
    2283           0 :         for ( i=0; i<len; ++i ) {
    2284           0 :             if ( ti[i]->selected ) {
    2285           0 :                 MacNameListFree(ti[i]->userdata);
    2286           0 :                 ti[i]->userdata = NULL;
    2287             :             }
    2288             :         }
    2289           0 :         GListDelSelected(list);
    2290           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NamedDelete),false);
    2291           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NamedEdit),false);
    2292             :     }
    2293           0 : return( true );
    2294             : }
    2295             : 
    2296           0 : static int MMW_NamedSel(GGadget *g, GEvent *e) {
    2297           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
    2298             :         int32 len;
    2299           0 :         GTextInfo **ti = GGadgetGetList(g,&len);
    2300           0 :         GWindow gw = GGadgetGetWindow(g);
    2301           0 :         int i, sel_cnt=0;
    2302           0 :         for ( i=0; i<len; ++i )
    2303           0 :             if ( ti[i]->selected ) ++sel_cnt;
    2304           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NamedDelete),sel_cnt!=0);
    2305           0 :         GGadgetSetEnabled(GWidgetGetControl(gw,CID_NamedEdit),sel_cnt==1);
    2306           0 :     } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
    2307           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2308           0 :         EditStyleName(mmw,GGadgetGetFirstListSelectedItem(g));
    2309             :     }
    2310           0 : return( true );
    2311             : }
    2312             : 
    2313           0 : static int MMW_CheckOptical(GGadget *g, GEvent *e) {
    2314           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
    2315           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2316             :         char *top, *bottom, *def;
    2317             :         unichar_t *ut;
    2318           0 :         const unichar_t *ret = _GGadgetGetTitle(g);
    2319           0 :         int di = (GGadgetGetCid(g)-CID_AxisType)/100;
    2320             :         char buf1[20], buf2[20], buf3[20];
    2321             : 
    2322           0 :         if ( mmw->old!=NULL && di<mmw->old->axis_count &&
    2323           0 :                 uc_strcmp(ret,mmw->old->axes[di])==0 ) {
    2324           0 :             sprintf(buf1,"%g", (double) mmw->old->axismaps[di].designs[0]);
    2325           0 :             sprintf(buf2,"%g", (double) mmw->old->axismaps[di].designs[mmw->old->axismaps[di].points-1]);
    2326           0 :             sprintf(buf3,"%g", (double) mmw->old->axismaps[di].def);
    2327           0 :             def = buf3;
    2328           0 :             top = buf2;
    2329           0 :             bottom = buf1;
    2330           0 :         } else if ( uc_strcmp(ret,"OpticalSize")==0 ) {
    2331           0 :             top = "72";
    2332           0 :             def = "12";
    2333           0 :             bottom = "6";
    2334           0 :         } else if ( uc_strcmp(ret,"Slant")==0 ) {
    2335           0 :             top = "22";
    2336           0 :             def = "0";
    2337           0 :             bottom = "-22";
    2338           0 :         } else if ( GGadgetIsChecked(GWidgetGetControl(mmw->subwins[mmw_counts],CID_Apple)) ) {
    2339           0 :             top = "2.0";
    2340           0 :             bottom = "0.5";
    2341           0 :             def = "1.0";
    2342             :         } else {
    2343           0 :             top = "999";
    2344           0 :             bottom = "50";
    2345           0 :             def = "400";
    2346             :         }
    2347           0 :         ut = uc_copy(top);
    2348           0 :         GGadgetSetTitle(GWidgetGetControl(GGadgetGetWindow(g),
    2349           0 :                 GGadgetGetCid(g)-CID_AxisType + CID_AxisEnd), ut);
    2350           0 :         free(ut);
    2351           0 :         ut = uc_copy(bottom);
    2352           0 :         GGadgetSetTitle(GWidgetGetControl(GGadgetGetWindow(g),
    2353           0 :                 GGadgetGetCid(g)-CID_AxisType + CID_AxisBegin), ut);
    2354           0 :         free(ut);
    2355           0 :         ut = uc_copy(def);
    2356           0 :         GGadgetSetTitle(GWidgetGetControl(GGadgetGetWindow(g),
    2357           0 :                 GGadgetGetCid(g)-CID_AxisType + CID_AxisDefault), ut);
    2358           0 :         free(ut);
    2359             :     }
    2360           0 : return( true );
    2361             : }
    2362             : 
    2363           0 : static int MMW_CheckBrowse(GGadget *g, GEvent *e) {
    2364           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
    2365           0 :         MMW *mmw = GDrawGetUserData(GGadgetGetWindow(g));
    2366             :         /*int di = (GGadgetGetCid(g)-CID_DesignFonts)/DesignScaleFactor;*/
    2367           0 :         GTextInfo *ti = GGadgetGetListItemSelected(g);
    2368             :         char *temp;
    2369             :         SplineFont *sf;
    2370             :         GTextInfo **tis;
    2371             :         int i,sel,oldsel;
    2372             :         unichar_t *ut;
    2373             : 
    2374           0 :         if ( ti!=NULL && ti->userdata == (void *) -1 ) {
    2375           0 :             temp = GetPostScriptFontName(NULL,false);
    2376           0 :             if ( temp==NULL )
    2377           0 : return(true);
    2378           0 :             sf = LoadSplineFont(temp,0);
    2379           0 :             free(temp); temp = NULL;
    2380           0 :             if ( sf==NULL )
    2381           0 : return(true);
    2382           0 :             if ( sf->cidmaster!=NULL || sf->subfonts!=0 ) {
    2383           0 :                 ff_post_error(_("Bad Multiple Master Font"),_("CID keyed fonts may not be a master design of a multiple master font"));
    2384           0 : return(true);
    2385           0 :             } else if ( sf->mm!=NULL ) {
    2386           0 :                 ff_post_error(_("Bad Multiple Master Font"),_("CID keyed fonts may not be a master design of a multiple master font"));
    2387           0 : return(true);
    2388             :             }
    2389           0 :             if ( sf->fv==NULL ) {
    2390           0 :                 if ( mmw->lcnt>=mmw->lmax ) {
    2391           0 :                     if ( mmw->lmax==0 )
    2392           0 :                         mmw->loaded = malloc((mmw->lmax=10)*sizeof(SplineFont *));
    2393             :                     else
    2394           0 :                         mmw->loaded = realloc(mmw->loaded,(mmw->lmax+=10)*sizeof(SplineFont *));
    2395             :                 }
    2396           0 :                 mmw->loaded[mmw->lcnt++] = sf;
    2397           0 :                 for ( i=0; i<mmw->instance_count; ++i ) {
    2398           0 :                     GGadget *list = GWidgetGetControl(mmw->subwins[mmw_designs],CID_DesignFonts+i*DesignScaleFactor);
    2399           0 :                     oldsel = GGadgetGetFirstListSelectedItem(list);
    2400           0 :                     tis = FontList(mmw,i,&sel);
    2401           0 :                     tis[sel]->selected = false;
    2402           0 :                     tis[oldsel]->selected = true;
    2403           0 :                     GGadgetSetList(list, tis, false);
    2404             :                 }
    2405             :             }
    2406           0 :             GGadgetSetTitle(g,ut = uc_copy(sf->fontname));
    2407           0 :             free(ut);
    2408             :         }
    2409             :     }
    2410           0 : return( true );
    2411             : }
    2412             : 
    2413           0 : static int mmwsub_e_h(GWindow gw, GEvent *event) {
    2414           0 :     if ( event->type==et_char ) {
    2415           0 :         if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
    2416           0 :             help("multiplemaster.html");
    2417           0 : return( true );
    2418           0 :         } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
    2419           0 :             if ( event->u.chr.state&ksm_shift )
    2420           0 :                 MMW_Close(GDrawGetUserData(gw));
    2421           0 : return( true );
    2422           0 :         } else if ( event->u.chr.chars[0]=='\r' ) {
    2423           0 :             MMW_SimulateDefaultButton( (MMW *) GDrawGetUserData(gw));
    2424           0 : return( true );
    2425             :         }
    2426           0 : return( false );
    2427             :     }
    2428           0 : return( true );
    2429             : }
    2430             : 
    2431           0 : static int mmw_e_h(GWindow gw, GEvent *event) {
    2432           0 :     if ( event->type==et_close ) {
    2433           0 :         MMW *mmw = GDrawGetUserData(gw);
    2434           0 :         MMW_Close(mmw);
    2435           0 :     } else if ( event->type==et_char ) {
    2436           0 :         if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
    2437           0 :             help("multiplemaster.html");
    2438           0 : return( true );
    2439           0 :         } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
    2440           0 :             if ( event->u.chr.state&ksm_shift )
    2441           0 :                 MMW_Close(GDrawGetUserData(gw));
    2442             :             else
    2443           0 :                 MenuExit(NULL,NULL,NULL);
    2444           0 : return( true );
    2445           0 :         } else if ( event->u.chr.chars[0]=='\r' ) {
    2446           0 :             MMW_SimulateDefaultButton( (MMW *) GDrawGetUserData(gw));
    2447           0 : return( true );
    2448             :         }
    2449           0 : return( false );
    2450             :     }
    2451           0 : return( true );
    2452             : }
    2453             : 
    2454           0 : static MMSet *MMCopy(MMSet *orig) {
    2455             :     MMSet *mm;
    2456             :     int i;
    2457             :     /* Allocate the arrays out to maximum, we'll fix them up later, and we */
    2458             :     /*  retain the proper counts in the mmw structure. This means we don't */
    2459             :     /*  lose data when they shrink and then restore a value */
    2460             : 
    2461           0 :     mm = chunkalloc(sizeof(MMSet));
    2462           0 :     mm->apple = orig->apple;
    2463           0 :     mm->instance_count = AppleMmMax+1;
    2464           0 :     mm->axis_count = 4;
    2465           0 :     for ( i=0; i<orig->axis_count; ++i )
    2466           0 :         mm->axes[i] = copy(orig->axes[i]);
    2467           0 :     mm->instances = calloc(AppleMmMax+1,sizeof(SplineFont *));
    2468           0 :     memcpy(mm->instances,orig->instances,orig->instance_count*sizeof(SplineFont *));
    2469           0 :     if ( mm->apple )
    2470           0 :         mm->instances[orig->instance_count] = orig->normal;
    2471           0 :     mm->positions = calloc((AppleMmMax+1)*4,sizeof(real));
    2472           0 :     for ( i=0; i<orig->instance_count; ++i )
    2473           0 :         memcpy(mm->positions+i*4,orig->positions+i*orig->axis_count,orig->axis_count*sizeof(real));
    2474           0 :     mm->defweights = calloc(AppleMmMax+1,sizeof(real));
    2475           0 :     memcpy(mm->defweights,orig->defweights,orig->instance_count*sizeof(real));
    2476           0 :     mm->axismaps = calloc(4,sizeof(struct axismap));
    2477           0 :     for ( i=0; i<orig->axis_count; ++i ) {
    2478           0 :         mm->axismaps[i].points = orig->axismaps[i].points;
    2479           0 :         mm->axismaps[i].blends = malloc(mm->axismaps[i].points*sizeof(real));
    2480           0 :         memcpy(mm->axismaps[i].blends,orig->axismaps[i].blends,mm->axismaps[i].points*sizeof(real));
    2481           0 :         mm->axismaps[i].designs = malloc(mm->axismaps[i].points*sizeof(real));
    2482           0 :         memcpy(mm->axismaps[i].designs,orig->axismaps[i].designs,mm->axismaps[i].points*sizeof(real));
    2483           0 :         mm->axismaps[i].min = orig->axismaps[i].min;
    2484           0 :         mm->axismaps[i].max = orig->axismaps[i].max;
    2485           0 :         mm->axismaps[i].def = orig->axismaps[i].def;
    2486             :     }
    2487           0 :     mm->cdv = copy(orig->cdv);
    2488           0 :     mm->ndv = copy(orig->ndv);
    2489           0 : return( mm );
    2490             : }
    2491             : 
    2492           0 : void MMWizard(MMSet *mm) {
    2493             :     MMW mmw;
    2494             :     GRect pos, subpos;
    2495             :     GWindow gw;
    2496             :     GWindowAttrs wattrs;
    2497             :     GTabInfo axisaspects[5], designaspects[AppleMmMax+1+1];
    2498             :     GGadgetCreateData bgcd[8], cntgcd[11], axisgcd[4][20], designgcd[AppleMmMax+1][5],
    2499             :             agcd[2], dgcd[3], ogcd[7], ngcd[7];
    2500             :     GTextInfo blabel[8], cntlabel[11], axislabel[4][20], designlabel[AppleMmMax+1][5],
    2501             :             dlabel, olabels[7], nlabel[5];
    2502             :     char axisbegins[4][20], axisends[4][20], axisdefs[4][20];
    2503             :     char *normalized[4], *designs[4];
    2504             :     char *pt, *freeme;
    2505             :     int i,k;
    2506           0 :     int isadobe = mm==NULL || !mm->apple;
    2507           0 :     int space,blen= GIntGetResource(_NUM_Buttonsize)*100/GGadgetScale(100);
    2508             :     static char *designtablab[] = { "1", "2", "3", "4", "5", "6", "7", "8",
    2509             :             "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
    2510             :             "20", "21", "22", "23", "24", "25", "26", "27", NULL };
    2511             : #if AppleMmMax!=26
    2512             :  #error "The designtablab array needs to be expanded to match AppleMmMax"
    2513             :     /* Actually it should be one bigger than AppleMmMax */
    2514             : #endif
    2515             : 
    2516           0 :     memset(&mmw,0,sizeof(mmw));
    2517           0 :     mmw.old = mm;
    2518           0 :     if ( mm!=NULL ) {
    2519           0 :         mmw.mm = MMCopy(mm);
    2520           0 :         mmw.axis_count = mm->axis_count;
    2521           0 :         mmw.instance_count = mm->instance_count;
    2522           0 :         if ( mm->apple )
    2523           0 :             ++mmw.instance_count;               /* Normal (default) design is a master in the mac format */
    2524             :     } else {
    2525           0 :         mmw.mm = chunkalloc(sizeof(MMSet));
    2526           0 :         mmw.axis_count = 1;
    2527           0 :         mmw.instance_count = 2;
    2528           0 :         mmw.mm->axis_count = 4; mmw.mm->instance_count = AppleMmMax+1;
    2529           0 :         mmw.mm->instances = calloc(AppleMmMax+1,sizeof(SplineFont *));
    2530           0 :         mmw.mm->positions = calloc((AppleMmMax+1)*4,sizeof(real));
    2531           0 :         mmw.mm->defweights = calloc(AppleMmMax+1,sizeof(real));
    2532           0 :         mmw.mm->axismaps = calloc(4,sizeof(struct axismap));
    2533           0 :         mmw.isnew = true;
    2534             :     }
    2535             : 
    2536           0 :     memset(&wattrs,0,sizeof(wattrs));
    2537           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
    2538           0 :     wattrs.event_masks = ~(1<<et_charup);
    2539           0 :     wattrs.is_dlg = true;
    2540           0 :     wattrs.restrict_input_to_me = true;
    2541           0 :     wattrs.undercursor = 1;
    2542           0 :     wattrs.cursor = ct_pointer;
    2543           0 :     wattrs.utf8_window_title = mmw.isnew?_("Create MM"):_("MM _Info") ;
    2544           0 :     pos.x = pos.y = 0;
    2545           0 :     pos.width =GDrawPointsToPixels(NULL,GGadgetScale(MMW_Width));
    2546           0 :     pos.height = GDrawPointsToPixels(NULL,MMW_Height);
    2547           0 :     mmw.gw = gw = GDrawCreateTopWindow(NULL,&pos,mmw_e_h,&mmw,&wattrs);
    2548             : 
    2549           0 :     memset(&blabel,0,sizeof(blabel));
    2550           0 :     memset(&bgcd,0,sizeof(bgcd));
    2551             : 
    2552           0 :     mmw.canceldrop = GDrawPointsToPixels(NULL,30);
    2553           0 :     bgcd[0].gd.pos.x = 20; bgcd[0].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-33;
    2554           0 :     bgcd[0].gd.pos.width = -1; bgcd[0].gd.pos.height = 0;
    2555           0 :     bgcd[0].gd.flags = gg_visible | gg_enabled;
    2556           0 :     blabel[0].text = (unichar_t *) _("_OK");
    2557           0 :     blabel[0].text_is_1byte = true;
    2558           0 :     blabel[0].text_in_resource = true;
    2559           0 :     bgcd[0].gd.label = &blabel[0];
    2560           0 :     bgcd[0].gd.cid = CID_OK;
    2561           0 :     bgcd[0].gd.handle_controlevent = MMW_OK;
    2562           0 :     bgcd[0].creator = GButtonCreate;
    2563             : 
    2564           0 :     space = (MMW_Width-4*blen-40)/3;
    2565           0 :     bgcd[1].gd.pos.x = bgcd[0].gd.pos.x+blen+space; bgcd[1].gd.pos.y = bgcd[0].gd.pos.y;
    2566           0 :     bgcd[1].gd.pos.width = -1; bgcd[1].gd.pos.height = 0;
    2567           0 :     bgcd[1].gd.flags = gg_visible;
    2568           0 :     blabel[1].text = (unichar_t *) _("< _Prev");
    2569           0 :     blabel[1].text_is_1byte = true;
    2570           0 :     blabel[1].text_in_resource = true;
    2571           0 :     bgcd[1].gd.label = &blabel[1];
    2572           0 :     bgcd[1].gd.handle_controlevent = MMW_Prev;
    2573           0 :     bgcd[1].gd.cid = CID_Prev;
    2574           0 :     bgcd[1].creator = GButtonCreate;
    2575             : 
    2576           0 :     bgcd[2].gd.pos.x = bgcd[1].gd.pos.x+blen+space; bgcd[2].gd.pos.y = bgcd[1].gd.pos.y;
    2577           0 :     bgcd[2].gd.pos.width = -1; bgcd[2].gd.pos.height = 0;
    2578           0 :     bgcd[2].gd.flags = gg_visible;
    2579           0 :     blabel[2].text = (unichar_t *) _("_Next >");
    2580           0 :     blabel[2].text_in_resource = true;
    2581           0 :     blabel[2].text_is_1byte = true;
    2582           0 :     bgcd[2].gd.label = &blabel[2];
    2583           0 :     bgcd[2].gd.handle_controlevent = MMW_Next;
    2584           0 :     bgcd[2].gd.cid = CID_Next;
    2585           0 :     bgcd[2].creator = GButtonCreate;
    2586             : 
    2587           0 :     bgcd[3].gd.pos.x = -20; bgcd[3].gd.pos.y = bgcd[1].gd.pos.y;
    2588           0 :     bgcd[3].gd.pos.width = -1; bgcd[3].gd.pos.height = 0;
    2589           0 :     bgcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
    2590           0 :     blabel[3].text = (unichar_t *) _("_Cancel");
    2591           0 :     blabel[3].text_in_resource = true;
    2592           0 :     blabel[3].text_is_1byte = true;
    2593           0 :     bgcd[3].gd.label = &blabel[3];
    2594           0 :     bgcd[3].gd.handle_controlevent = MMW_Cancel;
    2595           0 :     bgcd[3].gd.cid = CID_Cancel;
    2596           0 :     bgcd[3].creator = GButtonCreate;
    2597             : 
    2598           0 :     bgcd[4].gd.pos.x = 2; bgcd[4].gd.pos.y = 2;
    2599           0 :     bgcd[4].gd.pos.width = pos.width-4; bgcd[4].gd.pos.height = pos.height-4;
    2600           0 :     bgcd[4].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
    2601           0 :     bgcd[4].gd.cid = CID_Group;
    2602           0 :     bgcd[4].creator = GGroupCreate;
    2603             : 
    2604           0 :     GGadgetsCreate(gw,bgcd);
    2605             : 
    2606           0 :     subpos = pos;
    2607           0 :     subpos.y = subpos.x = 4;
    2608           0 :     subpos.width -= 8;
    2609           0 :     mmw.subheightdiff = GDrawPointsToPixels(NULL,44)-8;
    2610           0 :     subpos.height -= mmw.subheightdiff;
    2611           0 :     wattrs.mask = wam_events;
    2612           0 :     for ( i=mmw_counts; i<=mmw_others; ++i )
    2613           0 :         mmw.subwins[i] = GWidgetCreateSubWindow(mmw.gw,&subpos,mmwsub_e_h,&mmw,&wattrs);
    2614             : 
    2615           0 :     memset(&cntlabel,0,sizeof(cntlabel));
    2616           0 :     memset(&cntgcd,0,sizeof(cntgcd));
    2617             : 
    2618           0 :     k=0;
    2619           0 :     cntlabel[k].text = (unichar_t *) _("Type of distortable font:");
    2620           0 :     cntlabel[k].text_is_1byte = true;
    2621           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2622           0 :     cntgcd[k].gd.pos.x = 5; cntgcd[k].gd.pos.y = 11;
    2623           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2624           0 :     cntgcd[k++].creator = GLabelCreate;
    2625             : 
    2626           0 :     cntlabel[k].text = (unichar_t *) _("Adobe");
    2627           0 :     cntlabel[k].text_is_1byte = true;
    2628           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2629           0 :     cntgcd[k].gd.pos.x = 10; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+12;
    2630           0 :     cntgcd[k].gd.flags = isadobe ? (gg_visible | gg_enabled | gg_cb_on) :
    2631             :             ( gg_visible | gg_enabled );
    2632           0 :     cntgcd[k].gd.cid = CID_Adobe;
    2633           0 :     cntgcd[k].gd.handle_controlevent = MMW_TypeChanged;
    2634           0 :     cntgcd[k++].creator = GRadioCreate;
    2635             : 
    2636           0 :     cntlabel[k].text = (unichar_t *) _("Apple");
    2637           0 :     cntlabel[k].text_is_1byte = true;
    2638           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2639           0 :     cntgcd[k].gd.pos.x = 70; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y;
    2640           0 :     cntgcd[k].gd.flags = !isadobe ? (gg_visible | gg_enabled | gg_cb_on) :
    2641             :             ( gg_visible | gg_enabled );
    2642           0 :     cntgcd[k].gd.cid = CID_Apple;
    2643           0 :     cntgcd[k].gd.handle_controlevent = MMW_TypeChanged;
    2644           0 :     cntgcd[k++].creator = GRadioCreate;
    2645             : 
    2646           0 :     cntlabel[k].text = (unichar_t *) _("Number of Axes:");
    2647           0 :     cntlabel[k].text_is_1byte = true;
    2648           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2649           0 :     cntgcd[k].gd.pos.x = 5; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+18;
    2650           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2651           0 :     cntgcd[k++].creator = GLabelCreate;
    2652             : 
    2653           0 :     cntgcd[k].gd.pos.x = 10; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+12;
    2654           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2655           0 :     cntgcd[k].gd.u.list = axiscounts;
    2656           0 :     cntgcd[k].gd.label = &axiscounts[mmw.axis_count-1];
    2657           0 :     cntgcd[k].gd.cid = CID_AxisCount;
    2658           0 :     cntgcd[k].gd.handle_controlevent = MMW_AxisCntChanged;
    2659           0 :     cntgcd[k++].creator = GListButtonCreate;
    2660           0 :     for ( i=0; i<4; ++i )
    2661           0 :         axiscounts[i].selected = false;
    2662           0 :     axiscounts[mmw.axis_count-1].selected = true;
    2663             : 
    2664           0 :     cntlabel[k].text = (unichar_t *) _("Number of Master Designs:");
    2665           0 :     cntlabel[k].text_is_1byte = true;
    2666           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2667           0 :     cntgcd[k].gd.pos.x = 5; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+30;
    2668           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2669           0 :     cntgcd[k++].creator = GLabelCreate;
    2670             : 
    2671           0 :     cntgcd[k].gd.pos.x = 10; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+12;
    2672           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2673           0 :     cntgcd[k].gd.u.list = mastercounts;
    2674           0 :     cntgcd[k].gd.label = &mastercounts[mmw.instance_count-1];
    2675           0 :     cntgcd[k].gd.cid = CID_MasterCount;
    2676           0 :     cntgcd[k++].creator = GListButtonCreate;
    2677           0 :     for ( i=0; i<AppleMmMax+1; ++i )
    2678           0 :         mastercounts[i].selected = false;
    2679           0 :     mastercounts[mmw.instance_count-1].selected = true;
    2680             : 
    2681           0 :     cntlabel[k].text = (unichar_t *) _("_Family Name:");
    2682           0 :     cntlabel[k].text_is_1byte = true;
    2683           0 :     cntlabel[k].text_in_resource = true;
    2684           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2685           0 :     cntgcd[k].gd.pos.x = 10; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+30;
    2686           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2687           0 :     cntgcd[k++].creator = GLabelCreate;
    2688             : 
    2689           0 :     freeme=NULL;
    2690           0 :     if ( mmw.old!=NULL && mmw.old->normal->familyname!=NULL )
    2691           0 :         cntlabel[k].text = (unichar_t *) (mmw.old->normal->familyname);
    2692             :     else
    2693           0 :         cntlabel[k].text = (unichar_t *) (freeme= GetNextUntitledName());
    2694           0 :     cntlabel[k].text_is_1byte = true;
    2695           0 :     cntgcd[k].gd.label = &cntlabel[k];
    2696           0 :     cntgcd[k].gd.pos.x = 15; cntgcd[k].gd.pos.y = cntgcd[k-1].gd.pos.y+14;
    2697           0 :     cntgcd[k].gd.pos.width = 150;
    2698           0 :     cntgcd[k].gd.flags = gg_visible | gg_enabled;
    2699           0 :     cntgcd[k].gd.cid = CID_FamilyName;
    2700           0 :     cntgcd[k++].creator = GTextFieldCreate;
    2701             : 
    2702           0 :     GGadgetsCreate(mmw.subwins[mmw_counts],cntgcd);
    2703           0 :     SetMasterToAxis(&mmw,true);
    2704           0 :     free(freeme);
    2705             : 
    2706           0 :     memset(&axisgcd,0,sizeof(axisgcd));
    2707           0 :     memset(&axislabel,0,sizeof(axislabel));
    2708           0 :     memset(&agcd,0,sizeof(agcd));
    2709           0 :     memset(&axisaspects,0,sizeof(axisaspects));
    2710             : 
    2711           0 :     for ( i=0; i<4; ++i ) {
    2712           0 :         k=0;
    2713           0 :         axislabel[i][k].text = (unichar_t *) _("Axis Type:");
    2714           0 :         axislabel[i][k].text_is_1byte = true;
    2715           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2716           0 :         axisgcd[i][k].gd.pos.x = 5; axisgcd[i][k].gd.pos.y = 11;
    2717           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2718           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2719             : 
    2720           0 :         axisgcd[i][k].gd.pos.x = 120; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y-4;
    2721           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2722           0 :         axisgcd[i][k].gd.u.list = axistypes;
    2723           0 :         axisgcd[i][k].gd.cid = CID_AxisType+i*100;
    2724           0 :         axisgcd[i][k].gd.handle_controlevent = MMW_CheckOptical;
    2725           0 :         if ( i<mmw.axis_count && mmw.mm->axes[i]!=NULL ) {
    2726           0 :             axislabel[i][k].text = uc_copy(mmw.mm->axes[i]);
    2727           0 :             axisgcd[i][k].gd.label = &axislabel[i][k];
    2728             :         }
    2729           0 :         axisgcd[i][k++].creator = GListFieldCreate;
    2730             : 
    2731           0 :         axislabel[i][k].text = (unichar_t *) _("Axis Range:");
    2732           0 :         axislabel[i][k].text_is_1byte = true;
    2733           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2734           0 :         axisgcd[i][k].gd.pos.x = 5; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y+20;
    2735           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2736           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2737             : 
    2738           0 :         if ( mmw.mm->axismaps[i].points<2 ) {
    2739           0 :             strcpy(axisbegins[i],"50");
    2740           0 :             strcpy(axisdefs[i],"400");
    2741           0 :             strcpy(axisends[i],"999");
    2742             :         } else {
    2743           0 :             sprintf(axisbegins[i],"%.4g", (double) mmw.mm->axismaps[i].designs[0]);
    2744           0 :             sprintf(axisends[i],"%.4g", (double) mmw.mm->axismaps[i].designs[mmw.mm->axismaps[i].points-1]);
    2745           0 :             if ( mmw.mm->apple )
    2746           0 :                 sprintf(axisdefs[i],"%.4g", (double) mmw.mm->axismaps[i].def );
    2747             :             else
    2748           0 :                 sprintf(axisdefs[i],"%g", (double) (mmw.mm->axismaps[i].designs[0]+
    2749           0 :                         mmw.mm->axismaps[i].designs[mmw.mm->axismaps[i].points-1])/2);
    2750             :         }
    2751             : 
    2752           0 :         axislabel[i][k].text = (unichar_t *) _("Begin:");
    2753           0 :         axislabel[i][k].text_is_1byte = true;
    2754           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2755           0 :         axisgcd[i][k].gd.pos.x = 10; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y+16;
    2756           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2757           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2758             : 
    2759           0 :         axislabel[i][k].text = (unichar_t *) axisbegins[i];
    2760           0 :         axislabel[i][k].text_is_1byte = true;
    2761           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2762           0 :         axisgcd[i][k].gd.pos.x = 50; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y-4;
    2763           0 :         axisgcd[i][k].gd.pos.width=50;
    2764           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2765           0 :         axisgcd[i][k].gd.cid = CID_AxisBegin+i*100;
    2766           0 :         axisgcd[i][k++].creator = GTextFieldCreate;
    2767             : 
    2768           0 :         axislabel[i][k].text = (unichar_t *) _("Default:");
    2769           0 :         axislabel[i][k].text_is_1byte = true;
    2770           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2771           0 :         axisgcd[i][k].gd.pos.x = 110; axisgcd[i][k].gd.pos.y = axisgcd[i][k-2].gd.pos.y;
    2772           0 :         axisgcd[i][k].gd.flags = mmw.mm->apple ? (gg_visible | gg_enabled) : gg_visible;
    2773           0 :         axisgcd[i][k].gd.cid = CID_AxisDefaultLabel+i*100;
    2774           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2775             : 
    2776           0 :         axislabel[i][k].text = (unichar_t *) axisdefs[i];
    2777           0 :         axislabel[i][k].text_is_1byte = true;
    2778           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2779           0 :         axisgcd[i][k].gd.pos.x = 148; axisgcd[i][k].gd.pos.y = axisgcd[i][k-2].gd.pos.y;
    2780           0 :         axisgcd[i][k].gd.pos.width=50;
    2781           0 :         axisgcd[i][k].gd.flags = mmw.mm->apple ? (gg_visible | gg_enabled) : gg_visible;
    2782           0 :         axisgcd[i][k].gd.cid = CID_AxisDefault+i*100;
    2783           0 :         axisgcd[i][k++].creator = GTextFieldCreate;
    2784             : 
    2785           0 :         axislabel[i][k].text = (unichar_t *) _("End:");
    2786           0 :         axislabel[i][k].text_is_1byte = true;
    2787           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2788           0 :         axisgcd[i][k].gd.pos.x = 210; axisgcd[i][k].gd.pos.y = axisgcd[i][k-2].gd.pos.y;
    2789           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2790           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2791             : 
    2792           0 :         axislabel[i][k].text = (unichar_t *) axisends[i];
    2793           0 :         axislabel[i][k].text_is_1byte = true;
    2794           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2795           0 :         axisgcd[i][k].gd.pos.x = 240; axisgcd[i][k].gd.pos.y = axisgcd[i][k-2].gd.pos.y;
    2796           0 :         axisgcd[i][k].gd.pos.width=50;
    2797           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2798           0 :         axisgcd[i][k].gd.cid = CID_AxisEnd+i*100;
    2799           0 :         axisgcd[i][k++].creator = GTextFieldCreate;
    2800             : 
    2801           0 :         axislabel[i][k].text = (unichar_t *) _("Intermediate Points:");
    2802           0 :         axislabel[i][k].text_is_1byte = true;
    2803           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2804           0 :         axisgcd[i][k].gd.pos.x = 5; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y+26;
    2805           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2806           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2807             : 
    2808           0 :         normalized[i]=NULL;
    2809           0 :         designs[i]=NULL;
    2810           0 :         if ( mmw.mm->axismaps[i].points>2+mmw.mm->apple ) {
    2811             :             int l,j,len1, len2;
    2812             :             char buffer[30];
    2813           0 :             len1 = len2 = 0;
    2814           0 :             for ( l=0; l<2; ++l ) {
    2815           0 :                 for ( j=1; j<mmw.mm->axismaps[i].points-1; ++j ) {
    2816           0 :                     if ( mmw.mm->apple && mmw.mm->axismaps[i].designs[j]==mmw.mm->axismaps[i].def )
    2817           0 :                 continue;
    2818             :                     /* I wanted to separate things with commas, but that isn't*/
    2819             :                     /*  a good idea in Europe (comma==decimal point) */
    2820           0 :                     sprintf(buffer,"%g ",(double) mmw.mm->axismaps[i].designs[j]);
    2821           0 :                     if ( designs[i]!=NULL )
    2822           0 :                         strcpy(designs[i]+len1, buffer );
    2823           0 :                     len1 += strlen(buffer);
    2824           0 :                     sprintf(buffer,"%g ",(double) mmw.mm->axismaps[i].blends[j]);
    2825           0 :                     if ( normalized[i]!=NULL )
    2826           0 :                         strcpy(normalized[i]+len2, buffer );
    2827           0 :                     len2 += strlen(buffer);
    2828             :                 }
    2829           0 :                 if ( l==0 ) {
    2830           0 :                     normalized[i] = malloc(len2+2);
    2831           0 :                     designs[i] = malloc(len1+2);
    2832             :                 } else {
    2833           0 :                     normalized[i][len2-1] = '\0';
    2834           0 :                     designs[i][len1-1] = '\0';
    2835             :                 }
    2836             :             }
    2837             :         }
    2838             : 
    2839           0 :         axislabel[i][k].text = (unichar_t *) _("Design Settings:");
    2840           0 :         axislabel[i][k].text_is_1byte = true;
    2841           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2842           0 :         axisgcd[i][k].gd.pos.x = 10; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y+12;
    2843           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2844           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2845             : 
    2846           0 :         if ( designs[i]!=NULL ) {
    2847           0 :             axislabel[i][k].text = (unichar_t *) designs[i];
    2848           0 :             axislabel[i][k].text_is_1byte = true;
    2849           0 :             axisgcd[i][k].gd.label = &axislabel[i][k];
    2850             :         }
    2851           0 :         axisgcd[i][k].gd.pos.x = 120; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y-4;
    2852           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2853           0 :         axisgcd[i][k].gd.cid = CID_IntermediateDesign+i*100;
    2854           0 :         axisgcd[i][k++].creator = GTextFieldCreate;
    2855             : 
    2856           0 :         axislabel[i][k].text = (unichar_t *) _("Normalized Settings:");
    2857           0 :         axislabel[i][k].text_is_1byte = true;
    2858           0 :         axisgcd[i][k].gd.label = &axislabel[i][k];
    2859           0 :         axisgcd[i][k].gd.pos.x = 10; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y+28;
    2860           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2861           0 :         axisgcd[i][k++].creator = GLabelCreate;
    2862             : 
    2863           0 :         if ( normalized[i]!=NULL ) {
    2864           0 :             axislabel[i][k].text = (unichar_t *) normalized[i];
    2865           0 :             axislabel[i][k].text_is_1byte = true;
    2866           0 :             axisgcd[i][k].gd.label = &axislabel[i][k];
    2867             :         }
    2868           0 :         axisgcd[i][k].gd.pos.x = 120; axisgcd[i][k].gd.pos.y = axisgcd[i][k-1].gd.pos.y-4;
    2869           0 :         axisgcd[i][k].gd.flags = gg_visible | gg_enabled;
    2870           0 :         axisgcd[i][k].gd.cid = CID_IntermediateNormalized+i*100;
    2871           0 :         axisgcd[i][k++].creator = GTextFieldCreate;
    2872             : 
    2873           0 :         k = GCDBuildNames(axisgcd[i],axislabel[i],k,mm==NULL || i>=mm->axis_count ? NULL :
    2874           0 :                 mm->axismaps[i].axisnames);
    2875             : 
    2876           0 :         axisaspects[i].text = (unichar_t *) _(axistablab[i]);
    2877           0 :         axisaspects[i].text_is_1byte = true;
    2878           0 :         axisaspects[i].gcd = axisgcd[i];
    2879             :     }
    2880           0 :     axisaspects[0].selected = true;
    2881             : 
    2882           0 :     agcd[0].gd.pos.x = 3; agcd[0].gd.pos.y = 3;
    2883           0 :     agcd[0].gd.pos.width = MMW_Width-10;
    2884           0 :     agcd[0].gd.pos.height = MMW_Height-45;
    2885           0 :     agcd[0].gd.u.tabs = axisaspects;
    2886           0 :     agcd[0].gd.flags = gg_visible | gg_enabled;
    2887           0 :     agcd[0].gd.cid = CID_WhichAxis;
    2888           0 :     agcd[0].creator = GTabSetCreate;
    2889             : 
    2890           0 :     GGadgetsCreate(mmw.subwins[mmw_axes],agcd);
    2891           0 :     for ( i=0; i<4; ++i ) {
    2892           0 :         free(axislabel[i][1].text);
    2893           0 :         free(normalized[i]);
    2894           0 :         free(designs[i]);
    2895             :     }
    2896             : 
    2897           0 :     memset(&designgcd,0,sizeof(designgcd));
    2898           0 :     memset(&designlabel,0,sizeof(designlabel));
    2899           0 :     memset(&dgcd,0,sizeof(dgcd));
    2900           0 :     memset(&dlabel,0,sizeof(dlabel));
    2901           0 :     memset(&designaspects,0,sizeof(designaspects));
    2902             : 
    2903           0 :     for ( i=0; i<AppleMmMax+1; ++i ) {
    2904           0 :         designlabel[i][0].text = (unichar_t *) _("Source from which this design is to be taken");
    2905           0 :         designlabel[i][0].text_is_1byte = true;
    2906           0 :         designgcd[i][0].gd.label = &designlabel[i][0];
    2907           0 :         designgcd[i][0].gd.pos.x = 3; designgcd[i][0].gd.pos.y = 4;
    2908           0 :         designgcd[i][0].gd.flags = gg_visible | gg_enabled;
    2909           0 :         designgcd[i][0].creator = GLabelCreate;
    2910             : 
    2911           0 :         designgcd[i][1].gd.pos.x = 15; designgcd[i][1].gd.pos.y = 18;
    2912           0 :         designgcd[i][1].gd.pos.width = 200;
    2913           0 :         designgcd[i][1].gd.flags = gg_visible | gg_enabled;
    2914           0 :         designgcd[i][1].gd.cid = CID_DesignFonts + i*DesignScaleFactor;
    2915           0 :         designgcd[i][1].gd.handle_controlevent = MMW_CheckBrowse;
    2916           0 :         designgcd[i][1].creator = GListButtonCreate;
    2917             : 
    2918           0 :         designlabel[i][2].text = (unichar_t *) _("Normalized position of this design along each axis");
    2919           0 :         designlabel[i][2].text_is_1byte = true;
    2920           0 :         designgcd[i][2].gd.label = &designlabel[i][2];
    2921           0 :         designgcd[i][2].gd.pos.x = 3; designgcd[i][2].gd.pos.y = 50;
    2922           0 :         designgcd[i][2].gd.flags = gg_visible | gg_enabled;
    2923           0 :         designgcd[i][2].creator = GLabelCreate;
    2924             : 
    2925           0 :         designgcd[i][3].gd.pos.x = 15; designgcd[i][3].gd.pos.y = 64;
    2926           0 :         designgcd[i][3].gd.pos.width = 200;
    2927           0 :         designgcd[i][3].gd.flags = gg_visible | gg_enabled;
    2928           0 :         designgcd[i][3].gd.cid = CID_AxisWeights + i*DesignScaleFactor;
    2929           0 :         designgcd[i][3].creator = GTextFieldCreate;
    2930             : 
    2931           0 :         designaspects[i].text = (unichar_t *) designtablab[i];
    2932           0 :         designaspects[i].text_is_1byte = true;
    2933           0 :         designaspects[i].gcd = designgcd[i];
    2934             :     }
    2935           0 :     designaspects[0].selected = true;
    2936             : 
    2937           0 :     dlabel.text = (unichar_t *) _("Master Designs");
    2938           0 :     dlabel.text_is_1byte = true;
    2939           0 :     dgcd[0].gd.label = &dlabel;
    2940           0 :     dgcd[0].gd.pos.x = 3; dgcd[0].gd.pos.y = 4;
    2941           0 :     dgcd[0].gd.flags = gg_visible | gg_enabled;
    2942           0 :     dgcd[0].creator = GLabelCreate;
    2943             : 
    2944           0 :     dgcd[1].gd.pos.x = 3; dgcd[1].gd.pos.y = 18;
    2945           0 :     dgcd[1].gd.pos.width = MMW_Width-10;
    2946           0 :     dgcd[1].gd.pos.height = MMW_Height-60;
    2947           0 :     dgcd[1].gd.u.tabs = designaspects;
    2948           0 :     dgcd[1].gd.flags = gg_visible | gg_enabled;
    2949           0 :     dgcd[1].gd.cid = CID_WhichDesign;
    2950           0 :     dgcd[1].creator = GTabSetCreate;
    2951             : 
    2952           0 :     GGadgetsCreate(mmw.subwins[mmw_designs],dgcd);
    2953             : 
    2954           0 :     memset(&ngcd,0,sizeof(ngcd));
    2955           0 :     memset(&nlabel,0,sizeof(nlabel));
    2956             : 
    2957           0 :     nlabel[0].text = (unichar_t *) _("Named Styles");
    2958           0 :     nlabel[0].text_is_1byte = true;
    2959           0 :     ngcd[0].gd.label = &nlabel[0];
    2960           0 :     ngcd[0].gd.pos.x = 3; ngcd[0].gd.pos.y = 4;
    2961           0 :     ngcd[0].gd.flags = gg_visible | gg_enabled;
    2962           0 :     ngcd[0].creator = GLabelCreate;
    2963             : 
    2964           0 :     ngcd[1].gd.pos.x = 3; ngcd[1].gd.pos.y = 18;
    2965           0 :     ngcd[1].gd.pos.width = MMW_Width-10;
    2966           0 :     ngcd[1].gd.pos.height = MMW_Height-100;
    2967           0 :     ngcd[1].gd.u.list = NamedDesigns(&mmw);
    2968           0 :     ngcd[1].gd.flags = gg_visible | gg_enabled | gg_list_multiplesel;
    2969           0 :     ngcd[1].gd.cid = CID_NamedDesigns;
    2970           0 :     ngcd[1].gd.handle_controlevent = MMW_NamedSel;
    2971           0 :     ngcd[1].creator = GListCreate;
    2972             : 
    2973           0 :     ngcd[2].gd.pos.x = 20; ngcd[2].gd.pos.y = ngcd[1].gd.pos.y + ngcd[1].gd.pos.height+5;
    2974           0 :     ngcd[2].gd.pos.width = -1;
    2975           0 :     ngcd[2].gd.flags = gg_visible | gg_enabled;
    2976           0 :     nlabel[2].text = (unichar_t *) S_("Design|_New...");
    2977           0 :     nlabel[2].text_is_1byte = true;
    2978           0 :     nlabel[2].text_in_resource = true;
    2979           0 :     ngcd[2].gd.label = &nlabel[2];
    2980           0 :     ngcd[2].gd.cid = CID_NamedNew;
    2981           0 :     ngcd[2].gd.handle_controlevent = MMW_NamedNew;
    2982           0 :     ngcd[2].creator = GButtonCreate;
    2983             : 
    2984           0 :     ngcd[3].gd.pos.x = 20+blen+10; ngcd[3].gd.pos.y = ngcd[2].gd.pos.y;
    2985           0 :     ngcd[3].gd.pos.width = -1;
    2986           0 :     ngcd[3].gd.flags = gg_visible;
    2987           0 :     nlabel[3].text = (unichar_t *) _("_Delete");
    2988           0 :     nlabel[3].text_is_1byte = true;
    2989           0 :     nlabel[3].text_in_resource = true;
    2990           0 :     ngcd[3].gd.label = &nlabel[3];
    2991           0 :     ngcd[3].gd.cid = CID_NamedDelete;
    2992           0 :     ngcd[3].gd.handle_controlevent = MMW_NamedDelete;
    2993           0 :     ngcd[3].creator = GButtonCreate;
    2994             : 
    2995           0 :     ngcd[4].gd.pos.x = 20+2*blen+20; ngcd[4].gd.pos.y = ngcd[2].gd.pos.y;
    2996           0 :     ngcd[4].gd.pos.width = -1;
    2997           0 :     ngcd[4].gd.flags = gg_visible;
    2998           0 :     nlabel[4].text = (unichar_t *) _("_Edit...");
    2999           0 :     nlabel[4].text_is_1byte = true;
    3000           0 :     nlabel[4].text_in_resource = true;
    3001           0 :     ngcd[4].gd.label = &nlabel[4];
    3002           0 :     ngcd[4].gd.cid = CID_NamedEdit;
    3003           0 :     ngcd[4].gd.handle_controlevent = MMW_NamedEdit;
    3004           0 :     ngcd[4].creator = GButtonCreate;
    3005             : 
    3006           0 :     GGadgetsCreate(mmw.subwins[mmw_named],ngcd);
    3007           0 :     if ( ngcd[1].gd.u.list!=NULL )
    3008           0 :         GTextInfoListFree(ngcd[1].gd.u.list);
    3009             : 
    3010           0 :     memset(&ogcd,0,sizeof(ogcd));
    3011           0 :     memset(&olabels,0,sizeof(olabels));
    3012             : 
    3013           0 :     k=0;
    3014           0 :     olabels[k].text = (unichar_t *) _("Normalize Design Vector Function:");
    3015           0 :     olabels[k].text_is_1byte = true;
    3016           0 :     ogcd[k].gd.label = &olabels[k];
    3017           0 :     ogcd[k].gd.pos.x = 3; ogcd[k].gd.pos.y = 4;
    3018           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3019           0 :     ogcd[k++].creator = GLabelCreate;
    3020             : 
    3021           0 :     ogcd[k].gd.pos.x = 3; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+15;
    3022           0 :     ogcd[k].gd.pos.width = MMW_Width-10;
    3023           0 :     ogcd[k].gd.pos.height = 8*12+10;
    3024           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3025           0 :     ogcd[k].gd.cid = CID_NDV;
    3026           0 :     ogcd[k++].creator = GTextAreaCreate;
    3027             : 
    3028           0 :     olabels[k].text = (unichar_t *) _("Convert Design Vector Function:");
    3029           0 :     olabels[k].text_is_1byte = true;
    3030           0 :     ogcd[k].gd.label = &olabels[k];
    3031           0 :     ogcd[k].gd.pos.x = 3; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+ogcd[k-1].gd.pos.height+5;
    3032           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3033           0 :     ogcd[k++].creator = GLabelCreate;
    3034             : 
    3035           0 :     ogcd[k].gd.pos.x = 3; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+15;
    3036           0 :     ogcd[k].gd.pos.width = MMW_Width-10;
    3037           0 :     ogcd[k].gd.pos.height = 8*12+10;
    3038           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3039           0 :     ogcd[k].gd.cid = CID_CDV;
    3040           0 :     ogcd[k++].creator = GTextAreaCreate;
    3041             : 
    3042           0 :     GGadgetsCreate(mmw.subwins[mmw_funcs],ogcd);
    3043             : 
    3044           0 :     memset(&ogcd,0,sizeof(ogcd));
    3045           0 :     memset(&olabels,0,sizeof(olabels));
    3046             : 
    3047           0 :     k=0;
    3048           0 :     olabels[k].text = (unichar_t *) _("Contribution of each master design");
    3049           0 :     olabels[k].text_is_1byte = true;
    3050           0 :     ogcd[k].gd.label = &olabels[k];
    3051           0 :     ogcd[k].gd.pos.x = 10; ogcd[k].gd.pos.y = 4;
    3052           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled | gg_cb_on;
    3053           0 :     ogcd[k].gd.cid = CID_Explicit;
    3054           0 :     ogcd[k].gd.handle_controlevent = MMCB_Changed;
    3055           0 :     ogcd[k++].creator = GRadioCreate;
    3056             : 
    3057           0 :     olabels[k].text = (unichar_t *) _("Design Axis Values");
    3058           0 :     olabels[k].text_is_1byte = true;
    3059           0 :     ogcd[k].gd.label = &olabels[k];
    3060           0 :     ogcd[k].gd.pos.x = 10; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+45;
    3061           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3062           0 :     ogcd[k].gd.cid = CID_ByDesign;
    3063           0 :     ogcd[k].gd.handle_controlevent = MMCB_Changed;
    3064           0 :     ogcd[k++].creator = GRadioCreate;
    3065             : 
    3066           0 :     ogcd[k].gd.pos.x = 15; ogcd[k].gd.pos.y = ogcd[k-2].gd.pos.y+18;
    3067           0 :     ogcd[k].gd.pos.width = 240;
    3068           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3069           0 :     ogcd[k].gd.cid = CID_NewBlends;
    3070           0 :     ogcd[k++].creator = GTextFieldCreate;
    3071             : 
    3072           0 :     ogcd[k].gd.pos.x = 15; ogcd[k].gd.pos.y = ogcd[k-2].gd.pos.y+18;
    3073           0 :     ogcd[k].gd.pos.width = 240;
    3074           0 :     ogcd[k].gd.flags = gg_visible;
    3075           0 :     ogcd[k].gd.cid = CID_NewDesign;
    3076           0 :     ogcd[k++].creator = GTextFieldCreate;
    3077             : 
    3078           0 :     olabels[k].text = (unichar_t *) _("Force Bold Threshold:");
    3079           0 :     olabels[k].text_is_1byte = true;
    3080           0 :     ogcd[k].gd.label = &olabels[k];
    3081           0 :     ogcd[k].gd.pos.x = 10; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+45;
    3082           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3083           0 :     ogcd[k++].creator = GLabelCreate;
    3084             : 
    3085           0 :     if ( mmw.old!=NULL &&
    3086           0 :             (pt = PSDictHasEntry(mmw.old->normal->private,"ForceBoldThreshold"))!=NULL )
    3087           0 :         olabels[k].text = (unichar_t *) pt;
    3088             :     else
    3089           0 :         olabels[k].text = (unichar_t *) ".3";
    3090           0 :     olabels[k].text_is_1byte = true;
    3091           0 :     ogcd[k].gd.label = &olabels[k];
    3092           0 :     ogcd[k].gd.pos.x = 15; ogcd[k].gd.pos.y = ogcd[k-1].gd.pos.y+13;
    3093           0 :     ogcd[k].gd.flags = gg_visible | gg_enabled;
    3094           0 :     ogcd[k].gd.cid = CID_ForceBoldThreshold;
    3095           0 :     ogcd[k++].creator = GTextFieldCreate;
    3096             : 
    3097           0 :     GGadgetsCreate(mmw.subwins[mmw_others],ogcd);
    3098             : 
    3099           0 :     mmw.state = mmw_counts;
    3100           0 :     MMW_SetState(&mmw);
    3101           0 :     GDrawSetVisible(mmw.subwins[mmw.state],true);
    3102           0 :     GDrawSetVisible(mmw.gw,true);
    3103             : 
    3104           0 :     while ( !mmw.done )
    3105           0 :         GDrawProcessOneEvent(NULL);
    3106             : 
    3107           0 :     GDrawDestroyWindow(gw);
    3108           0 : }

Generated by: LCOV version 1.10