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

          Line data    Source code
       1             : /* Copyright (C) 2005-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 "fontforgeui.h"
      28             : #include "fvfonts.h"
      29             : #include "splinefill.h"
      30             : #include "splineutil.h"
      31             : #include <gkeysym.h>
      32             : #include <string.h>
      33             : #include <ustring.h>
      34             : #include <utype.h>
      35             : #include <math.h>
      36             : 
      37             : int aa_pixelsize = 150;
      38             : 
      39             : /* The dialog should contain a lig index !!!! */
      40             : 
      41             : struct apmatch {
      42             :     SplineChar *sc;
      43             :     AnchorPoint *ap;
      44             :     BDFChar *bdfc;
      45             :     int off;            /* a mark-to-mark display might have the same */
      46             :     int size;           /* odd positioning problems as above */
      47             :     int xstart;         /* This is scaled by factor, others are not */
      48             : };
      49             : 
      50             : struct state {
      51             :     SplineChar *sc;
      52             :     int changed;
      53             :     AnchorPoint *ap_pt;
      54             :     AnchorPoint ap_vals;
      55             :     struct state *next;
      56             : };
      57             : 
      58             : typedef struct anchord {
      59             :     GWindow gw;
      60             :     int ctl_len;
      61             :     GGadget *hsb;
      62             :     int sb_base;
      63             :     int sb_width;
      64             :     int sb_height;
      65             :     int full_width, full_height;
      66             : 
      67             :     SplineChar *sc;             /* This is the character whose anchor we are */
      68             :     AnchorPoint *ap;            /*  interested in, and this is that anchor */
      69             :     BasePoint apos;             /* Modified anchor position */
      70             :     DeviceTable xadjust;        /* Modified adjustments */
      71             :     DeviceTable yadjust;
      72             :     BDFChar *bdfc;
      73             :     int char_off;               /* Mark characters are often positioned oddly */
      74             :     int char_size;              /*  and have zero advance widths, this corrects*/
      75             :     int ymin, ymax;             /* For all combos */
      76             : 
      77             :     int pixelsize;
      78             :     double scale;               /* Does not include mag factor */
      79             :     int magfactor;
      80             :     int baseline;
      81             : 
      82             :     int xoff;                   /* for scroll bar */
      83             :     int xlen;                   /* sum of all the following lengths       */
      84             :     int cnt;                    /* Number of anchors we join with         */
      85             :         /* joining can happen in four ways:                               */
      86             :         /*   we might be a base char, we see all the accents              */
      87             :         /*      (all apmatches will be the same length (bdfc->width above)*/
      88             :         /*   we might be a mark, we see all the bases (ligs may happen twice) */
      89             :         /*      (each base provides the length)                           */
      90             :         /*   we might be cursive entry, we see all the exits that attach  */
      91             :         /*      (length is bdfc->width + apmatch->width                     */
      92             :         /*      left to right/right to left is important here!            */
      93             :         /*   we might be cursive exit, we see all the entries that attach */
      94             :     struct apmatch *apmatch;
      95             :     void *freetypecontext;
      96             :     int combo, on_ap;
      97             :     BasePoint orig_pos;
      98             :     int done;
      99             :     /* If they change more than one anchor, retain the original values so that */
     100             :     /*  we can revert to them */
     101             :     struct state *orig_vals;
     102             :     int layer;
     103             : } AnchorDlg;
     104             : 
     105             : #define CID_X           1001
     106             : #define CID_Y           1002
     107             : #define CID_XCor        1003
     108             : #define CID_YCor        1004
     109             : #define CID_DisplaySize 1005
     110             : #define CID_Mag         1006
     111             : #define CID_Glyph       1007
     112             : 
     113             : #define Add_Mark        (void *) (-1)
     114             : #define Add_Base        (void *) (-3)
     115             : 
     116           0 : static void AnchorD_FreeChar(AnchorDlg *a) {
     117             :     int i;
     118             : 
     119           0 :     BDFCharFree(a->bdfc); a->bdfc = NULL;
     120           0 :     for ( i=0; i<a->cnt; ++i )
     121           0 :         BDFCharFree(a->apmatch[i].bdfc);
     122           0 :     free(a->apmatch); a->apmatch = NULL;
     123           0 :     if ( a->freetypecontext!=NULL ) {
     124           0 :         FreeTypeFreeContext(a->freetypecontext);
     125           0 :         a->freetypecontext = NULL;
     126             :     }
     127           0 : }
     128             : 
     129           0 : static void AnchorD_FreeAll(AnchorDlg *a) {
     130             :     struct state *old, *oldnext;
     131             : 
     132           0 :     free(a->xadjust.corrections);
     133           0 :     free(a->yadjust.corrections);
     134           0 :     for ( old = a->orig_vals; old!=NULL; old=oldnext ) {
     135           0 :         oldnext = old->next;
     136           0 :         chunkfree(old,sizeof(struct state));
     137             :     }
     138           0 :     AnchorD_FreeChar(a);
     139           0 : }
     140             : 
     141           0 : static GTextInfo **AnchorD_GlyphsInClass(AnchorDlg *a) {
     142           0 :     SplineFont *_sf = a->sc->parent, *sf;
     143           0 :     AnchorClass *ac = a->ap->anchor;
     144           0 :     int bcnt, mcnt, btot=0, j, k, gid;
     145             :     GTextInfo **ti;
     146             :     AnchorPoint *ap;
     147             : 
     148           0 :     if ( _sf->cidmaster!=NULL )
     149           0 :         _sf = _sf->cidmaster;
     150           0 :     for ( j=0; j<2; ++j ) {
     151           0 :         k = 0;
     152           0 :         bcnt = mcnt = 1;        /* Reserve two spots for labels (marks vs base glyphs) */
     153             :         do {
     154           0 :             sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
     155           0 :             for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) {
     156           0 :                 for ( ap= sf->glyphs[gid]->anchor; ap!=NULL; ap=ap->next ) {
     157           0 :                     if ( ap->anchor == ac ) {
     158           0 :                         if ( ap->type==at_mark || ap->type == at_centry ) {
     159           0 :                             if ( j ) {
     160           0 :                                 ti[btot+1+mcnt] = calloc(1,sizeof(GTextInfo));
     161           0 :                                 ti[btot+1+mcnt]->text = utf82u_copy(sf->glyphs[gid]->name);
     162           0 :                                 ti[btot+1+mcnt]->fg = ti[btot+1+mcnt]->bg = COLOR_DEFAULT;
     163           0 :                                 ti[btot+1+mcnt]->userdata = ap;
     164           0 :                                 ti[btot+1+mcnt]->selected = a->ap == ap;
     165             :                             }
     166           0 :                             ++mcnt;
     167             :                         } else {
     168           0 :                             if ( j ) {
     169           0 :                                 ti[bcnt] = calloc(1,sizeof(GTextInfo));
     170           0 :                                 ti[bcnt]->text = utf82u_copy(sf->glyphs[gid]->name);
     171           0 :                                 ti[bcnt]->fg = ti[bcnt]->bg = COLOR_DEFAULT;
     172           0 :                                 ti[bcnt]->userdata = ap;
     173           0 :                                 ti[bcnt]->selected = a->ap == ap;
     174             :                             }
     175           0 :                             ++bcnt;
     176             :                         }
     177             :                     }
     178             :                 }
     179             :             }
     180           0 :             ++k;
     181           0 :         } while ( k<_sf->subfontcnt );
     182           0 :         if ( !j ) {
     183           0 :             btot = bcnt;
     184           0 :             ti = calloc(bcnt+mcnt+5,sizeof(GTextInfo*));
     185           0 :             ti[0] = calloc(1,sizeof(GTextInfo));
     186           0 :             ti[0]->text = utf82u_copy(ac->type==act_curs ? _("Exits") : _("Bases"));
     187           0 :             ti[0]->fg = ti[0]->bg = COLOR_DEFAULT;
     188           0 :             ti[0]->disabled = true;
     189           0 :             ti[btot] = calloc(1,sizeof(GTextInfo));
     190           0 :             ti[btot]->line = true;
     191           0 :             ti[btot]->fg = ti[btot]->bg = COLOR_DEFAULT;
     192           0 :             ti[btot+1] = calloc(1,sizeof(GTextInfo));
     193           0 :             ti[btot+1]->text = utf82u_copy(ac->type==act_curs ? _("Entries") : _("Marks"));
     194           0 :             ti[btot+1]->fg = ti[btot+1]->bg = COLOR_DEFAULT;
     195           0 :             ti[btot+1]->disabled = true;
     196           0 :             ti[btot+mcnt+1] = calloc(1,sizeof(GTextInfo));
     197           0 :             ti[btot+mcnt+1]->line = true;
     198           0 :             ti[btot+mcnt+1]->fg = ti[btot+mcnt+1]->bg = COLOR_DEFAULT;
     199           0 :             ti[btot+mcnt+2] = calloc(1,sizeof(GTextInfo));
     200           0 :             ti[btot+mcnt+2]->text = utf82u_copy(ac->type==act_curs ? _("Add Exit Anchor...") : _("Add Base Anchor..."));
     201           0 :             ti[btot+mcnt+2]->fg = ti[btot+mcnt+2]->bg = COLOR_DEFAULT;
     202           0 :             ti[btot+mcnt+2]->userdata = Add_Base;
     203           0 :             ti[btot+mcnt+3] = calloc(1,sizeof(GTextInfo));
     204           0 :             ti[btot+mcnt+3]->text = utf82u_copy(ac->type==act_curs ? _("Add Entry Anchor...") : _("Add Mark Anchor..."));
     205           0 :             ti[btot+mcnt+3]->fg = ti[btot+mcnt+3]->bg = COLOR_DEFAULT;
     206           0 :             ti[btot+mcnt+3]->userdata = Add_Mark;
     207           0 :             ti[btot+mcnt+4] = calloc(1,sizeof(GTextInfo));
     208             :         }
     209             :     }
     210           0 : return( ti );
     211             : }
     212             : 
     213           0 : static void AnchorD_SetTitle(AnchorDlg *a) {
     214             :     char buffer[300];
     215           0 :     snprintf(buffer,sizeof(buffer),_("Anchor Control for class %.100s in glyph %.100s as %.20s"),
     216           0 :             a->ap->anchor->name, a->sc->name,
     217           0 :             a->ap->type == at_mark ? _("mark") :
     218           0 :             a->ap->type == at_centry ? _("cursive entry") :
     219           0 :             a->ap->type == at_cexit ? _("cursive exit") :
     220             :                 _("base") );
     221           0 :     GDrawSetWindowTitles8(a->gw,buffer,_("Anchor Control"));
     222           0 : }
     223             :     
     224           0 : static void AnchorD_FindComplements(AnchorDlg *a) {
     225           0 :     AnchorClass *ac = a->ap->anchor;
     226             :     enum anchor_type match;
     227             :     AnchorPoint *ap;
     228             :     int i, k, j, cnt;
     229           0 :     SplineFont *_sf = a->sc->parent, *sf;
     230             :     uint8 *sel, *oldsel;
     231           0 :     FontView *fv = (FontView *) _sf->fv;
     232           0 :     EncMap *map = fv->b.map;
     233             : 
     234           0 :     switch ( a->ap->type ) {
     235             :       case at_mark:
     236           0 :         switch ( a->ap->anchor->type ) {
     237             :           case act_mark:
     238           0 :             match = at_basechar;
     239           0 :           break;
     240             :           case act_mklg:
     241           0 :             match = at_baselig;
     242           0 :           break;
     243             :           case act_mkmk:
     244           0 :             match = at_basemark;
     245           0 :           break;
     246             :           default:
     247           0 :             IError( "Unexpected anchor class type" );
     248           0 :             match = at_basechar;
     249             :         }
     250           0 :       break;
     251             :       case at_basechar: case at_baselig: case at_basemark:
     252           0 :         match = at_mark;
     253           0 :       break;
     254             :       case at_centry:
     255           0 :         match = at_cexit;
     256           0 :       break;
     257             :       case at_cexit:
     258           0 :         match = at_centry;
     259           0 :       break;
     260             :       default:
     261           0 :         match = at_max;
     262           0 :       break;
     263             :     }
     264             : 
     265           0 :     if ( _sf->cidmaster!=NULL )
     266           0 :         _sf = _sf->cidmaster;
     267           0 :     for ( j=0; j<2; ++j ) {
     268           0 :         k = cnt = 0;
     269             :         do {
     270           0 :             sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
     271           0 :             for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
     272           0 :                 for ( ap= sf->glyphs[i]->anchor; ap!=NULL; ap=ap->next ) {
     273           0 :                     if ( ap->anchor == ac && ap->type==match ) {
     274           0 :                         if ( j ) {
     275           0 :                             a->apmatch[cnt].ap = ap;
     276           0 :                             a->apmatch[cnt++].sc = sf->glyphs[i];
     277             :                         } else
     278           0 :                             ++cnt;
     279             :                         /* Don't break out of the loop as ligatures can have multiple locations */
     280             :                     }
     281             :                 }
     282             :             }
     283           0 :             ++k;
     284           0 :         } while ( k<_sf->subfontcnt );
     285           0 :         a->cnt = cnt;
     286           0 :         if ( cnt==0 )
     287           0 :     break;
     288           0 :         if ( j==0 )
     289           0 :             a->apmatch = calloc(cnt,sizeof(struct apmatch));
     290             :     }
     291             : 
     292           0 :     if ( hasFreeType() && _sf->subfontcnt==0 ) {
     293           0 :         int enc = map->backmap[a->sc->orig_pos];
     294           0 :         if ( enc!=-1 ) {
     295           0 :             sel = calloc(map->enccount,1);
     296           0 :             sel[enc] = true;
     297           0 :             for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
     298           0 :                 enc = map->backmap[i];
     299           0 :                 if ( enc!=-1 ) {
     300           0 :                     for ( ap= sf->glyphs[i]->anchor; ap!=NULL; ap=ap->next ) {
     301           0 :                         if ( ap->anchor == ac && ap->type==match ) {
     302           0 :                             sel[enc] = true;
     303           0 :                     break;
     304             :                         }
     305             :                     }
     306             :                 }
     307             :             }
     308           0 :             oldsel = fv->b.selected;
     309           0 :             fv->b.selected = sel;
     310           0 :             a->freetypecontext = FreeTypeFontContext(_sf,NULL,(FontViewBase *) fv,a->layer);
     311           0 :             fv->b.selected = oldsel;
     312           0 :             free(sel);
     313             :         }
     314             :     }
     315           0 : }
     316             : 
     317           0 : static BDFChar *APRasterize(void *freetypecontext, SplineChar *sc,int layer, int *off,int *size,int pixelsize) {
     318             :     BDFChar *bdfc;
     319             : 
     320           0 :     if ( freetypecontext ) {
     321           0 :         bdfc = SplineCharFreeTypeRasterize(freetypecontext,sc->orig_pos,pixelsize,72,8);
     322             :     } else
     323           0 :         bdfc = SplineCharAntiAlias(sc,layer,pixelsize,4);
     324             : 
     325           0 :     if ( bdfc->xmin<=0 ) {
     326           0 :         *off = 1-bdfc->xmin;
     327           0 :         if ( bdfc->width>bdfc->xmax-bdfc->xmin )
     328           0 :             *size = bdfc->width;
     329             :         else
     330           0 :             *size = bdfc->xmax + *off;
     331             :     } else {
     332           0 :         *off = 0;
     333           0 :         if ( bdfc->width>bdfc->xmax )
     334           0 :             *size = bdfc->width;
     335             :         else
     336           0 :             *size = bdfc->xmax + 1;
     337             :     }
     338           0 :     ++*size;
     339           0 : return( bdfc );
     340             : }
     341             : 
     342           0 : static void AnchorD_SetSB(AnchorDlg *a) {
     343           0 :     GScrollBarSetBounds(a->hsb,0,a->xlen,a->sb_width);
     344           0 :     if ( a->xoff+a->sb_width > a->xlen )
     345           0 :         a->xoff = a->xlen - a->sb_width;
     346           0 :     if ( a->xoff<0 ) a->xoff = 0;
     347           0 :     GScrollBarSetPos(a->hsb,a->xoff);
     348           0 : }
     349             : 
     350           0 : static void AnchorD_Resize(AnchorDlg *a) {
     351             :     GRect size;
     352             :     int i, extra;
     353           0 :     int factor = a->magfactor;
     354             : 
     355           0 :     GDrawGetSize(a->gw,&size);
     356           0 :     a->full_width = size.width;
     357           0 :     a->full_height = size.height;
     358           0 :     a->sb_base = a->full_height - a->sb_height;
     359           0 :     if ( a->ctl_len+a->magfactor*a->char_size + 20 < a->full_width ) {
     360           0 :         a->sb_width = a->full_width - (a->ctl_len+a->magfactor*a->char_size);
     361           0 :         GGadgetResize(a->hsb,a->sb_width, a->sb_height);
     362           0 :         GGadgetMove(a->hsb,a->ctl_len+a->magfactor*a->char_size,a->sb_base);
     363             :     }
     364           0 :     AnchorD_SetSB(a);
     365             : 
     366           0 :     for ( i=0; i<a->cnt; ++i ) {
     367           0 :         if ( i==0 )
     368           0 :             a->apmatch[i].xstart = a->ctl_len+a->char_size*factor;
     369             :         else
     370           0 :             a->apmatch[i].xstart = a->apmatch[i-1].xstart +
     371           0 :                                     a->apmatch[i-1].size*factor;
     372             :     }
     373           0 :     if ( i==0 )
     374           0 :         a->xlen = 0;
     375             :     else
     376           0 :         a->xlen = a->apmatch[i-1].xstart - a->apmatch[0].xstart +
     377           0 :                 a->apmatch[i-1].size*factor;
     378             : 
     379           0 :     if ( a->ymin>0 && a->sb_base- a->ymax*factor >=0 )
     380           0 :         extra = (a->sb_base - a->ymax*factor)/2;
     381             :     else
     382           0 :         extra = (a->sb_base - (a->ymax-a->ymin)*factor)/2;
     383           0 :     a->baseline = a->ymax*factor + extra;
     384             : 
     385           0 :     GDrawRequestExpose(a->gw,NULL,false);
     386           0 : }
     387             : 
     388           0 : static void AnchorD_ChangeMag(AnchorDlg *a) {
     389             : 
     390           0 :     AnchorD_Resize(a);
     391           0 : }
     392             : 
     393           0 : static void AnchorD_ChangeSize(AnchorDlg *a) {
     394             :     int i, off;
     395             : 
     396           0 :     GDrawSetCursor(a->gw,ct_watch);
     397           0 :     GDrawSync(NULL);
     398             :     /* GDrawProcessPendingEvents(NULL); */ /* Any expose events on the current dlg will cause a crash as there are no bdfc's now */
     399             : 
     400           0 :     a->scale = a->pixelsize / (double) (a->sc->parent->ascent + a->sc->parent->descent);
     401             : 
     402           0 :     BDFCharFree(a->bdfc);
     403           0 :     a->bdfc = APRasterize(a->freetypecontext,a->sc,a->layer,&a->char_off,&a->char_size,a->pixelsize);
     404           0 :     a->ymin = a->bdfc->ymin; a->ymax = a->bdfc->ymax;
     405           0 :     for ( i=0; i<a->cnt; ++i ) {
     406           0 :         BDFCharFree(a->apmatch[i].bdfc);
     407           0 :         a->apmatch[i].bdfc = APRasterize(a->freetypecontext,a->apmatch[i].sc,a->layer,&a->apmatch[i].off,&a->apmatch[i].size,a->pixelsize);
     408           0 :         if ( a->ap->type==at_centry || a->ap->type==at_cexit )
     409           0 :             a->apmatch[i].size += a->char_size;
     410           0 :         else if ( a->ap->type!=at_mark )
     411           0 :             a->apmatch[i].size = a->char_size;
     412           0 :         switch ( a->ap->type ) {
     413             :           case at_cexit:
     414             :           case at_basechar: case at_baselig: case at_basemark:
     415           0 :             off = rint((-a->apos.y + a->apmatch[i].ap->me.y)*a->scale);
     416           0 :             if ( a->apmatch[i].bdfc->ymax+off > a->ymax )
     417           0 :                 a->ymax = a->apmatch[i].bdfc->ymax+off;
     418           0 :             if ( a->apmatch[i].bdfc->ymin+off < a->ymin )
     419           0 :                 a->ymin = a->apmatch[i].bdfc->ymin+off;
     420           0 :           break;
     421             :           case at_centry:
     422             :           case at_mark:
     423           0 :             if ( a->apmatch[i].bdfc->ymax > a->ymax )
     424           0 :                 a->ymax = a->apmatch[i].bdfc->ymax;
     425           0 :             if ( a->apmatch[i].bdfc->ymin < a->ymin )
     426           0 :                 a->ymin = a->apmatch[i].bdfc->ymin;
     427           0 :             off = rint((-a->apmatch[i].ap->me.y + a->apos.y)*a->scale);
     428           0 :             if ( a->bdfc->ymax+off > a->ymax )
     429           0 :                 a->ymax = a->bdfc->ymax+off;
     430           0 :             if ( a->bdfc->ymin+off < a->ymin )
     431           0 :                 a->ymin = a->bdfc->ymin+off;
     432           0 :           break;
     433             :         }
     434             :     }
     435           0 :     AnchorD_ChangeMag(a);
     436           0 :     GDrawSetCursor(a->gw,ct_pointer);
     437           0 : }
     438             : 
     439           0 : static int DevTabFind(DeviceTable *adjust,int pixelsize) {
     440           0 :     if ( adjust==NULL || adjust->corrections==NULL ||
     441           0 :             pixelsize<adjust->first_pixel_size ||
     442           0 :             pixelsize>adjust->last_pixel_size )
     443           0 : return( 0 );
     444           0 : return( adjust->corrections[pixelsize-adjust->first_pixel_size]);
     445             : }
     446             : 
     447           0 : static void AnchorD_Expose(AnchorDlg *a,GWindow pixmap,GEvent *event) {
     448           0 :     GRect *area = &event->u.expose.rect;
     449             :     GRect clip, old1, old2;
     450           0 :     int expose_end = area->x+area->width;
     451           0 :     int factor = a->magfactor;
     452             :     int i,x,y;
     453             : 
     454           0 :     if ( expose_end<a->ctl_len )
     455           0 : return;
     456             : 
     457           0 :     GDrawPushClip(pixmap,area,&old1);
     458             : 
     459           0 :     if ( area->x<a->ctl_len+a->char_size*factor ) {
     460           0 :         GDrawDrawLine(pixmap,a->ctl_len,0,a->ctl_len,a->full_height,0x000000);
     461           0 :         KCD_DrawGlyph(pixmap,a->char_off*factor+a->ctl_len,a->baseline,a->bdfc,factor);
     462           0 :         DrawAnchorPoint(pixmap,
     463           0 :             a->char_off*factor+a->ctl_len + ((int) rint(a->apos.x*a->scale))*factor,
     464           0 :             a->baseline - ((int) rint(a->apos.y*a->scale))*factor,
     465             :             false);
     466           0 :         GDrawDrawLine(pixmap,a->ctl_len+a->char_size*factor,0,a->ctl_len+a->char_size*factor,a->full_height,0x000000);
     467             :     }
     468             : 
     469           0 :     if ( expose_end>a->ctl_len+a->char_size && area->y<a->sb_base ) {
     470           0 :         int xcor=0, ycor=0;
     471             :         unichar_t *end;
     472             :         const unichar_t *ret;
     473             : 
     474           0 :         ret = _GGadgetGetTitle(GWidgetGetControl(a->gw,CID_XCor));
     475           0 :         xcor = u_strtol(ret,&end,10);
     476           0 :         while ( *end==' ' ) ++end;
     477           0 :         if ( *end!='\0' || xcor<-128 || xcor>127 )
     478           0 :             xcor = 0;
     479           0 :         ret = _GGadgetGetTitle(GWidgetGetControl(a->gw,CID_YCor));
     480           0 :         ycor = u_strtol(ret,&end,10);
     481           0 :         while ( *end==' ' ) ++end;
     482           0 :         if ( *end!='\0' || ycor<-128 || ycor>127 )
     483           0 :             ycor = 0;
     484             : 
     485           0 :         clip = *area;
     486           0 :         if ( area->x<=a->ctl_len+a->char_size ) {
     487           0 :             clip.width -= a->ctl_len+a->char_size+1 - area->x;
     488           0 :             clip.x = a->ctl_len+a->char_size+1;
     489             :         }
     490           0 :         if ( area->y+area->height > a->sb_base )
     491           0 :             clip.height = a->sb_base-area->y;
     492           0 :         GDrawPushClip(pixmap,&clip,&old2);
     493           0 :         for ( i=0; i<a->cnt; ++i ) {
     494           0 :             if ( a->apmatch[i].xstart - a->xoff > clip.x+clip.width )
     495           0 :         break;
     496           0 :             if ( a->apmatch[i].xstart+a->apmatch[i].size*factor - a->xoff < clip.x )
     497           0 :         continue;
     498             : 
     499           0 :             y = a->baseline;
     500           0 :             if ( i!=0 )
     501           0 :                 GDrawDrawLine(pixmap,a->apmatch[i].xstart-a->xoff,0,
     502           0 :                         a->apmatch[i].xstart-a->xoff,a->sb_base,0x808080);
     503           0 :             if ( a->ap->type==at_cexit ||
     504           0 :                     a->ap->type==at_basechar || a->ap->type==at_baselig ||
     505           0 :                     a->ap->type==at_basemark ) {
     506           0 :                 x = a->apmatch[i].xstart+a->char_off*factor - a->xoff;
     507           0 :                 KCD_DrawGlyph(pixmap,x,y,a->bdfc,factor);
     508           0 :                 x += ((int) rint((-a->apmatch[i].ap->me.x + a->apos.x)*a->scale) +
     509           0 :                         xcor - DevTabFind(&a->apmatch[i].ap->xadjust,a->pixelsize))*factor;
     510           0 :                 y += ((int) rint((a->apmatch[i].ap->me.y - a->apos.y)*a->scale) +
     511           0 :                         -ycor + DevTabFind(&a->apmatch[i].ap->yadjust,a->pixelsize))*factor;
     512           0 :                 KCD_DrawGlyph(pixmap,x,y,a->apmatch[i].bdfc,factor);
     513             :             } else {
     514           0 :                 x = a->apmatch[i].xstart+a->apmatch[i].off*factor - a->xoff;
     515           0 :                 KCD_DrawGlyph(pixmap,x,y,a->apmatch[i].bdfc,factor);
     516           0 :                 x += ((int) rint((a->apmatch[i].ap->me.x - a->apos.x)*a->scale) +
     517           0 :                         DevTabFind(&a->apmatch[i].ap->xadjust,a->pixelsize)-xcor)*factor;
     518           0 :                 y += ((int) rint((-a->apmatch[i].ap->me.y + a->apos.y)*a->scale) +
     519           0 :                         -DevTabFind(&a->apmatch[i].ap->yadjust,a->pixelsize)+ycor)*factor;
     520           0 :                 KCD_DrawGlyph(pixmap,x,y,a->bdfc,factor);
     521             :             }
     522             :         }
     523           0 :         if ( i>0 )
     524           0 :             GDrawDrawLine(pixmap,a->apmatch[i-1].xstart+a->apmatch[i-1].size*factor-a->xoff,0,
     525           0 :                     a->apmatch[i-1].xstart+a->apmatch[i-1].size*factor-a->xoff,a->sb_base,0x808080);
     526           0 :         GDrawPopClip(pixmap,&old2);
     527             :     }
     528           0 :     GDrawPopClip(pixmap,&old1);
     529             : }
     530             : 
     531           0 : static void AnchorD_FigurePos(AnchorDlg *a,GEvent *event) {
     532           0 :     int x = (event->u.mouse.x - a->ctl_len)/a->magfactor;
     533           0 :     int y = (a->baseline - event->u.mouse.y)/a->magfactor;
     534             : 
     535           0 :     a->apos.x = rint((x-a->char_off)/a->scale);
     536           0 :     a->apos.y = rint(y/a->scale);
     537           0 : }
     538             : 
     539           0 : static void AnchorD_ClearCorrections(AnchorDlg *a) {
     540             :     unichar_t ubuf[2];
     541             : 
     542           0 :     ubuf[0] = '0'; ubuf[1] = '\0';
     543           0 :     free(a->xadjust.corrections); memset(&a->xadjust,0,sizeof(DeviceTable));
     544           0 :     free(a->yadjust.corrections); memset(&a->yadjust,0,sizeof(DeviceTable));
     545           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_XCor),ubuf);
     546           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_YCor),ubuf);
     547           0 : }
     548             : 
     549           0 : static void AnchorD_DrawPos(AnchorDlg *a) {
     550             :     GRect r;
     551             :     char buffer[20];
     552             :     unichar_t ubuf[20];
     553             : 
     554           0 :     sprintf( buffer, "%g", (double) a->apos.x );
     555           0 :     uc_strcpy(ubuf,buffer);
     556           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_X),ubuf);
     557           0 :     sprintf( buffer, "%g", (double) a->apos.y );
     558           0 :     uc_strcpy(ubuf,buffer);
     559           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_Y),ubuf);
     560             : 
     561           0 :     r.x = a->ctl_len;
     562           0 :     r.y = 0;
     563           0 :     r.width = a->char_size*a->magfactor;
     564           0 :     r.height = a->full_height;
     565           0 :     GDrawRequestExpose(a->gw,&r,false);
     566           0 : }
     567             : 
     568           0 : static void AnchorD_SelectGlyph(AnchorDlg *a, AnchorPoint *ap) {
     569             :     int i;
     570             :     int32 len;
     571           0 :     GTextInfo **ti = GGadgetGetList(GWidgetGetControl(a->gw,CID_Glyph),&len);
     572             : 
     573           0 :     for ( i=0; i<len; ++i )
     574           0 :         if ( ti[i]->userdata == ap )
     575           0 :     break;
     576           0 :     if ( i!=len )
     577           0 :         GGadgetSelectOneListItem(GWidgetGetControl(a->gw,CID_Glyph),i);
     578           0 : }
     579             : 
     580             : static int AnchorD_ChangeGlyph(AnchorDlg *a, SplineChar *sc, AnchorPoint *ap);
     581             : 
     582           0 : static int AnchorD_Mouse(AnchorDlg *a,GEvent *event) {
     583           0 :     int on_combo = -1;
     584           0 :     int on_ap = 0;
     585             :     int i;
     586             : 
     587           0 :     if ( event->u.mouse.x<a->ctl_len || event->u.mouse.y>=a->sb_base )
     588           0 : return( false );
     589           0 :     if ( a->xlen>0 && event->u.mouse.x>=a->apmatch[0].xstart ) {
     590           0 :         int x = event->u.mouse.x + a->xoff;
     591           0 :         for ( i=0; i<a->cnt; ++i ) {
     592           0 :             if ( x>=a->apmatch[i].xstart &&
     593           0 :                     x<a->apmatch[i].xstart + a->apmatch[i].size*a->magfactor ) {
     594           0 :                 on_combo = i;
     595           0 :         break;
     596             :             }
     597             :         }
     598           0 :     } else if ( event->u.mouse.x>=a->ctl_len && event->u.mouse.x<a->ctl_len+ a->magfactor*a->char_size ) {
     599           0 :         int x = event->u.mouse.x - a->ctl_len;
     600           0 :         int y = a->baseline - event->u.mouse.y;
     601           0 :         int ax = (a->char_off + (int) rint(a->apos.x*a->scale))*a->magfactor;
     602           0 :         int ay = (int) rint(a->apos.y*a->scale)*a->magfactor;
     603           0 :         if ( x>ax-4 && x<ax+4 && y>ay-4 && y<ay+4 )
     604           0 :             on_ap = 2;
     605             :         else
     606           0 :             on_ap = 1;
     607             :     }
     608             : 
     609           0 :     if ( event->type == et_mousedown ) {
     610           0 :         if ( on_combo!=-1 )
     611           0 :             a->combo = on_combo+1;
     612           0 :         else if ( on_ap==2 ) {
     613           0 :             a->on_ap = true;
     614           0 :             a->orig_pos = a->apos;
     615             :         }
     616           0 :     } else if ( event->type == et_mouseup ) {
     617           0 :         if ( on_combo!=-1 && on_combo+1==a->combo ) {
     618           0 :             AnchorPoint *ap = a->apmatch[on_combo].ap;
     619           0 :             a->combo = 0;
     620           0 :             AnchorD_ChangeGlyph(a,a->apmatch[on_combo].sc,a->apmatch[on_combo].ap);
     621           0 :             AnchorD_SelectGlyph(a,ap);
     622           0 :         } else if ( on_ap && a->on_ap ) {
     623           0 :             AnchorD_FigurePos(a,event);
     624           0 :             AnchorD_ClearCorrections(a);
     625           0 :             AnchorD_DrawPos(a);
     626           0 :             GDrawRequestExpose(a->gw,NULL,false);
     627           0 :         } else if ( a->combo!=0 ) {
     628           0 :         } else if ( a->on_ap ) {
     629           0 :             a->apos = a->orig_pos;
     630           0 :             AnchorD_DrawPos(a);
     631             :         }
     632           0 :         a->on_ap = 0;
     633           0 :         a->combo = 0;
     634           0 :     } else if ( a->on_ap ) {
     635           0 :         AnchorD_FigurePos(a,event);
     636           0 :         AnchorD_DrawPos(a);
     637             :     }
     638           0 : return( true );
     639             : }
     640             : 
     641           0 : static void AnchorD_HScroll(AnchorDlg *a,struct sbevent *sb) {
     642           0 :     int newpos = a->xoff;
     643             :     GRect rect;
     644             : 
     645           0 :     switch( sb->type ) {
     646             :       case et_sb_top:
     647           0 :         newpos = 0;
     648           0 :       break;
     649             :       case et_sb_uppage:
     650           0 :         newpos -= a->sb_width;
     651           0 :       break;
     652             :       case et_sb_up:
     653           0 :         newpos -= a->pixelsize*a->magfactor/2;
     654           0 :       break;
     655             :       case et_sb_down:
     656           0 :         newpos = a->pixelsize*a->magfactor/2;
     657           0 :       break;
     658             :       case et_sb_downpage:
     659           0 :         newpos += a->sb_width;
     660           0 :       break;
     661             :       case et_sb_bottom:
     662           0 :         newpos = a->xlen - a->sb_width;
     663           0 :       break;
     664             :       case et_sb_thumb:
     665             :       case et_sb_thumbrelease:
     666           0 :         newpos = sb->pos;
     667           0 :       break;
     668             :     }
     669           0 :     if ( newpos + a->sb_width >= a->xlen )
     670           0 :         newpos = a->xlen - a->sb_width;
     671           0 :     if ( newpos < 0 ) newpos = 0;
     672           0 :     if ( newpos!=a->xoff ) {
     673           0 :         int diff = newpos-a->xoff;
     674           0 :         a->xoff = newpos;
     675           0 :         GScrollBarSetPos(a->hsb,newpos);
     676           0 :         if ( a->cnt!=0 ) {
     677           0 :             rect.x = a->apmatch[0].xstart+1; rect.y = 0;
     678           0 :             rect.width = a->sb_width;
     679           0 :             rect.height = a->sb_base;
     680           0 :             GDrawScroll(a->gw,&rect,-diff,0);
     681             :         }
     682             :     }
     683           0 : }
     684             : 
     685           0 : static SplinePoint *SCFindPoint(SplineChar *sc,int layer,int ptnum) {
     686             :     /* We're going to want to move this point, so a point in a reference */
     687             :     /*  is totally useless to us (we'd have to move the entire reference */
     688             :     /*  and it's probably better just to detach the anchor in that case. */
     689             :     SplineSet *ss;
     690             :     SplinePoint *sp;
     691             : 
     692           0 :     for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
     693           0 :         for ( sp=ss->first; ; ) {
     694           0 :             if ( sp->ttfindex==ptnum )
     695           0 : return( sp );
     696           0 :             if ( sp->next==NULL )
     697           0 :         break;
     698           0 :             sp = sp->next->to;
     699           0 :             if ( sp==ss->first )
     700           0 :         break;
     701           0 :         }
     702             :     }
     703           0 : return( NULL );
     704             : }
     705             : 
     706           0 : static void SetAnchor(SplineChar *sc,int layer, AnchorPoint *ap,DeviceTable *xadjust, DeviceTable *yadjust, BasePoint *pos) {
     707             :     int ly;
     708             : 
     709           0 :     free(ap->xadjust.corrections);
     710           0 :     if ( xadjust->corrections==NULL ) {
     711           0 :         memset(&ap->xadjust,0,sizeof(DeviceTable));
     712             :     } else {
     713           0 :         ap->xadjust = *xadjust;
     714           0 :         xadjust->corrections = NULL;
     715             :     }
     716           0 :     free(ap->yadjust.corrections);
     717           0 :     if ( yadjust->corrections==NULL ) {
     718           0 :         memset(&ap->yadjust,0,sizeof(DeviceTable));
     719             :     } else {
     720           0 :         ap->yadjust = *yadjust;
     721           0 :         yadjust->corrections = NULL;
     722             :     }
     723           0 :     ap->me = *pos;
     724             :     /* If the anchor is bound to a truetype point we must move the point too */
     725             :     /*  or the anchor will just snap back to the point */
     726           0 :     ly = ly_none;
     727           0 :     if ( ap->has_ttf_pt && ap->ttf_pt_index!=0xffff ) {
     728           0 :         int any = false;
     729           0 :         for ( ly=ly_fore; ly<sc->layer_cnt; ++ly ) if ( sc->layers[ly].order2 ) {
     730           0 :             SplinePoint *sp = SCFindPoint(sc,layer,ap->ttf_pt_index);
     731           0 :             if ( sp!=NULL ) {
     732           0 :                 sp->nextcp.x += pos->x - sp->me.x;
     733           0 :                 sp->prevcp.x += pos->x - sp->me.x;
     734           0 :                 sp->nextcp.y += pos->y - sp->me.y;
     735           0 :                 sp->prevcp.y += pos->y - sp->me.y;
     736           0 :                 sp->me = *pos;
     737           0 :                 any = true;
     738             :             }
     739             :         }
     740           0 :         if ( !any ) {
     741           0 :             ff_post_notice(_("Detaching Anchor Point"),_("This anchor was attached to point %d, but that's not a point I can move. I'm detaching the anchor from the point.") );
     742           0 :             ap->has_ttf_pt = false;
     743           0 :             ly = ly_none;
     744             :         }
     745             :     }
     746           0 :     SCCharChangedUpdate(sc,ly);
     747           0 : }
     748             : 
     749           0 : static void AnchorD_DoCancel(AnchorDlg *a) {
     750             :     struct state *old;
     751             : 
     752           0 :     for ( old = a->orig_vals; old!=NULL; old=old->next ) {
     753           0 :         SetAnchor(old->sc,a->layer,old->ap_pt,&old->ap_vals.xadjust,&old->ap_vals.yadjust,&old->ap_vals.me);
     754           0 :         old->ap_pt->has_ttf_pt = old->ap_vals.has_ttf_pt;
     755           0 :         old->sc->changed = old->changed;       /* Must come after the charchangedupdate */
     756             :     }
     757           0 :     if ( a->orig_vals!=NULL ) {
     758           0 :         FVRefreshAll(a->sc->parent);
     759             :     }
     760             :         
     761           0 :     a->done = true;
     762           0 : }
     763             : 
     764           0 : static int AnchorD_MagnificationChanged(GGadget *g, GEvent *e) {
     765           0 :     AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     766           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
     767           0 :         int mag = GGadgetGetFirstListSelectedItem(GWidgetGetControl(a->gw,CID_Mag));
     768             : 
     769           0 :         if ( mag!=-1 && mag!=a->magfactor-1 ) {
     770           0 :             a->xoff = (mag+1)*a->xoff/a->magfactor;
     771           0 :             a->magfactor = mag+1;
     772           0 :             AnchorD_ChangeMag(a);
     773           0 :             GDrawRequestExpose(a->gw,NULL,false);
     774             :         }
     775             :     }
     776           0 : return( true );
     777             : }
     778             : 
     779           0 : static int AnchorD_DisplaySizeChanged(GGadget *g, GEvent *e) {
     780           0 :     AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     781           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
     782           0 :         const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(a->gw,CID_DisplaySize));
     783             :         unichar_t *end;
     784           0 :         int pixelsize = u_strtol(ret,&end,10);
     785             : 
     786           0 :         while ( *end==' ' ) ++end;
     787           0 :         if ( pixelsize>4 && pixelsize<400 && *end=='\0' ) {
     788             :             unichar_t ubuf[20]; char buffer[20];
     789           0 :             ubuf[0] = '0'; ubuf[1] = '\0';
     790           0 :             if ( a->xadjust.corrections!=NULL &&
     791           0 :                     pixelsize>=a->xadjust.first_pixel_size &&
     792           0 :                     pixelsize<=a->xadjust.last_pixel_size ) {
     793           0 :                 sprintf( buffer, "%d", a->xadjust.corrections[
     794           0 :                         pixelsize-a->xadjust.first_pixel_size]);
     795           0 :                 uc_strcpy(ubuf,buffer);
     796             :             }
     797           0 :             GGadgetSetTitle(GWidgetGetControl(a->gw,CID_XCor),ubuf);
     798           0 :             ubuf[0] = '0'; ubuf[1] = '\0';
     799           0 :             if ( a->yadjust.corrections!=NULL &&
     800           0 :                     pixelsize>=a->yadjust.first_pixel_size &&
     801           0 :                     pixelsize<=a->yadjust.last_pixel_size ) {
     802           0 :                 sprintf( buffer, "%d", a->yadjust.corrections[
     803           0 :                         pixelsize-a->yadjust.first_pixel_size]);
     804           0 :                 uc_strcpy(ubuf,buffer);
     805             :             }
     806           0 :             GGadgetSetTitle(GWidgetGetControl(a->gw,CID_YCor),ubuf);
     807           0 :             a->xoff = pixelsize*a->xoff/a->pixelsize;
     808           0 :             a->pixelsize = aa_pixelsize = pixelsize;
     809           0 :             AnchorD_ChangeSize(a);
     810           0 :             GDrawRequestExpose(a->gw,NULL,false);
     811             :         }
     812             :     }
     813           0 : return( true );
     814             : }
     815             : 
     816           0 : static int AnchorD_CorrectionChanged(GGadget *g, GEvent *e) {
     817           0 :     AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     818           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
     819           0 :         const unichar_t *ret = _GGadgetGetTitle(g);
     820           0 :         int is_y = GGadgetGetCid(g)==CID_YCor;
     821             :         unichar_t *end;
     822           0 :         int correction = u_strtol(ret,&end,10);
     823             : 
     824           0 :         while ( *end==' ' ) ++end;
     825           0 :         if ( *end!='\0' )
     826           0 : return( true );
     827           0 :         if ( correction<-128 || correction>127 ) {
     828           0 :             ff_post_error( _("Out of Range"), _("Corrections must be between -128 and 127 (and should be smaller)") );
     829           0 : return( true );
     830             :         }
     831             : 
     832           0 :         DeviceTableSet(is_y?&a->yadjust:&a->xadjust,a->pixelsize,correction);
     833           0 :         GDrawRequestExpose(a->gw,NULL,false);
     834             :     }
     835           0 : return( true );
     836             : }
     837             : 
     838           0 : static int AnchorD_PositionChanged(GGadget *g, GEvent *e) {
     839           0 :     AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     840           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
     841           0 :         const unichar_t *ret = _GGadgetGetTitle(g);
     842           0 :         int is_y = GGadgetGetCid(g)==CID_Y;
     843             :         unichar_t *end;
     844           0 :         int val = u_strtol(ret,&end,10);
     845             : 
     846           0 :         while ( *end==' ' ) ++end;
     847           0 :         if ( *end!='\0' )
     848           0 : return( true );
     849             : 
     850           0 :         if ( (is_y && a->apos.y==val) || (!is_y && a->apos.x==val))
     851           0 : return( true );
     852           0 :         if ( is_y )
     853           0 :             a->apos.y = val;
     854             :         else
     855           0 :             a->apos.x = val;
     856           0 :         AnchorD_ClearCorrections(a);
     857           0 :         GDrawRequestExpose(a->gw,NULL,false);
     858             :     }
     859           0 : return( true );
     860             : }
     861             : 
     862           0 : static int AnchorD_Cancel(GGadget *g, GEvent *e) {
     863           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     864           0 :         AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     865           0 :         AnchorD_DoCancel(a);
     866             :     }
     867           0 : return( true );
     868             : }
     869             : 
     870           0 : static int AnchorD_Apply(AnchorDlg *a) {
     871           0 :     SetAnchor(a->sc,a->layer,a->ap,&a->xadjust,&a->yadjust,&a->apos);
     872           0 : return( true );
     873             : }
     874             : 
     875           0 : static int AnchorD_OK(GGadget *g, GEvent *e) {
     876           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     877           0 :         AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
     878           0 :         AnchorD_Apply(a);
     879           0 :         a->done = true;
     880             :     }
     881           0 : return( true );
     882             : }
     883             : 
     884           0 : static void AnchorD_SetDevTabs(AnchorDlg *a) {
     885             :     char buffer[20];
     886             :     unichar_t ubuf[20];
     887             :     int min, max;
     888             : 
     889           0 :     GGadgetClearList(GWidgetGetControl(a->gw,CID_DisplaySize));
     890           0 :     min = 1; max = 0;
     891           0 :     if ( a->xadjust.corrections!=NULL ) {
     892           0 :         min = a->xadjust.first_pixel_size;
     893           0 :         max = a->xadjust.last_pixel_size;
     894             :     }
     895           0 :     if ( a->yadjust.corrections!=NULL ) {
     896           0 :         if ( a->yadjust.first_pixel_size<min ) min = a->yadjust.first_pixel_size;
     897           0 :         if ( a->yadjust.last_pixel_size>max ) max = a->yadjust.last_pixel_size;
     898             :     }
     899           0 :     if ( max>min ) {
     900             :         int i;
     901           0 :         int len = max-min+1;
     902             :         char buffer[20];
     903           0 :         GTextInfo **ti = malloc((len+1)*sizeof(GTextInfo *));
     904           0 :         for ( i=0; i<len; ++i ) {
     905           0 :             ti[i] = calloc(1,sizeof(GTextInfo));
     906           0 :             sprintf( buffer, "%d", i+min );
     907           0 :             ti[i]->text = uc_copy(buffer);
     908           0 :             ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
     909             :         }
     910           0 :         ti[i] = calloc(1,sizeof(GTextInfo));
     911           0 :         GGadgetSetList(GWidgetGetControl(a->gw,CID_DisplaySize),ti,false);
     912             :     }
     913           0 :     ubuf[0] = '0'; ubuf[1] = '\0';
     914           0 :     if ( a->xadjust.corrections!=NULL &&
     915           0 :             a->pixelsize>=a->xadjust.first_pixel_size &&
     916           0 :             a->pixelsize<=a->xadjust.last_pixel_size ) {
     917           0 :         sprintf( buffer, "%d", a->xadjust.corrections[
     918           0 :                 a->pixelsize-a->xadjust.first_pixel_size]);
     919           0 :         uc_strcpy(ubuf,buffer);
     920             :     }
     921           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_XCor),ubuf);
     922           0 :     ubuf[0] = '0'; ubuf[1] = '\0';
     923           0 :     if ( a->yadjust.corrections!=NULL &&
     924           0 :             a->pixelsize>=a->yadjust.first_pixel_size &&
     925           0 :             a->pixelsize<=a->yadjust.last_pixel_size ) {
     926           0 :         sprintf( buffer, "%d", a->yadjust.corrections[
     927           0 :                 a->pixelsize-a->yadjust.first_pixel_size]);
     928           0 :         uc_strcpy(ubuf,buffer);
     929             :     }
     930           0 :     GGadgetSetTitle(GWidgetGetControl(a->gw,CID_YCor),ubuf);
     931           0 : }
     932             : 
     933           0 : static int AnchorD_ChangeGlyph(AnchorDlg *a, SplineChar *sc, AnchorPoint *ap) {
     934             :     char buf[32];
     935             :     struct state *old;
     936             : 
     937           0 :     if ( ap==NULL || sc==NULL )
     938           0 : return( true );
     939           0 :     if ( a->ap==ap )
     940           0 : return( true );
     941             :     /* Do we already have an entry for the current anchor? */
     942           0 :     for ( old = a->orig_vals; old!=NULL && old->ap_pt!=a->ap; old=old->next );
     943             :     /* If so we've already noted its original state and need do nothing more */
     944             :     /*  but otherwise we must store the current state */
     945           0 :     if ( old==NULL ) {
     946           0 :         old = chunkalloc(sizeof(struct state));
     947           0 :         old->sc = a->sc;
     948           0 :         old->changed = a->sc->changed;
     949           0 :         old->ap_pt = a->ap;
     950           0 :         old->ap_vals = *a->ap;
     951           0 :         memset(&a->ap->xadjust,0,sizeof(DeviceTable));
     952           0 :         memset(&a->ap->yadjust,0,sizeof(DeviceTable));
     953           0 :         old->next = a->orig_vals;
     954           0 :         a->orig_vals = old;
     955             :     }
     956           0 :     AnchorD_Apply(a);
     957           0 :     AnchorD_FreeChar(a);
     958             : 
     959           0 :     a->ap = ap;
     960           0 :     a->sc = sc;
     961           0 :     a->apos = ap->me;
     962           0 :     sprintf( buf, "%d", (int) rint(ap->me.x) );
     963           0 :     GGadgetSetTitle8(GWidgetGetControl(a->gw,CID_X),buf);
     964           0 :     sprintf( buf, "%d", (int) rint(ap->me.y) );
     965           0 :     GGadgetSetTitle8(GWidgetGetControl(a->gw,CID_Y),buf);
     966             : 
     967           0 :     AnchorD_FindComplements(a);
     968           0 :     AnchorD_SetDevTabs(a);
     969           0 :     AnchorD_ChangeSize(a);
     970           0 :     AnchorD_SetTitle(a);
     971           0 : return( true );
     972             : }
     973             : 
     974           0 : static SplineChar *AddAnchor(AnchorDlg *a, SplineFont *sf, AnchorClass *ac,
     975             :         int ismarklike) {
     976             :     char *ret, *def;
     977             :     SplineChar *sc;
     978           0 :     int isliga = false, ismrk=false, maxlig=-1;
     979             :     AnchorPoint *ap;
     980             :     PST *pst;
     981             :     int i;
     982             : 
     983           0 :     def = copy(".notdef");
     984             :     for (;;) {
     985           0 :         ret = gwwv_ask_string(_("Provide a glyph name"),def,_("Please identify a glyph by name, and FontForge will add an anchor to that glyph."));
     986           0 :         free(def);
     987           0 :         if ( ret==NULL )
     988           0 : return( NULL );
     989           0 :         sc = SFGetChar(sf,-1,ret);
     990           0 :         def = ret;
     991           0 :         if ( sc==NULL )
     992           0 :             ff_post_error(_("Non-existant glyph"), _("The glyph, %.80s, is not in the font"), ret );
     993             :         else {
     994           0 :             isliga = ismrk = false;
     995           0 :             for ( ap=sc->anchor ; ap!=NULL; ap=ap->next ) {
     996           0 :                 if ( ap->type == at_baselig )
     997           0 :                     isliga = true;
     998           0 :                 else if ( ap->type == at_basemark || ap->type == at_mark )
     999           0 :                     ismrk = true;
    1000           0 :                 if ( ap->anchor == ac ) {
    1001           0 :                     if ( (ap->type == at_centry ||
    1002           0 :                             (ap->type == at_mark && ac->type==act_mkmk) ||
    1003           0 :                             ap->type == at_baselig ) && ismarklike==-1 )
    1004           0 :                         ismarklike = false;
    1005           0 :                     else if ( (ap->type == at_cexit || (ap->type == at_basemark && ac->type==act_mkmk)) && ismarklike==-1 )
    1006           0 :                         ismarklike = true;
    1007           0 :                     else if ( ap->type != at_baselig ||
    1008           0 :                               ( ap->type == at_baselig && ismarklike>0 ))
    1009           0 :                         ff_post_error(_("Duplicate Anchor Class"), _("The glyph, %.80s, already contains an anchor in this class, %.80s."), ret, ac->name );
    1010           0 :                     else if ( maxlig<ap->lig_index )
    1011           0 :                         maxlig = ap->lig_index;
    1012           0 :             break;
    1013             :                 }
    1014             :             }
    1015           0 :             if ( ap==NULL )
    1016           0 :     break;
    1017             :         }
    1018           0 :     }
    1019             : 
    1020           0 :     ap = chunkalloc(sizeof(AnchorPoint));
    1021           0 :     ap->anchor = ac;
    1022           0 :     ap->me.x = ap->me.y = 0;
    1023           0 :     ap->next = sc->anchor;
    1024           0 :     sc->anchor = ap;
    1025           0 :     SCCharChangedUpdate(sc,ly_none);
    1026             : 
    1027           0 :     if ( sc->width==0 ) ismrk = true;
    1028           0 :     for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
    1029           0 :         if ( pst->type == pst_ligature || pst->type == pst_lcaret ) {
    1030           0 :             isliga = true;
    1031           0 :     break;
    1032             :         }
    1033             :     }
    1034             : 
    1035           0 :     if ( isliga || (ac->type==act_mklg && ismarklike==0 ) ) {
    1036           0 :         ap->type = at_baselig;
    1037           0 :         ap->lig_index = maxlig+1;
    1038           0 :     } else if ( ismrk && ismarklike!=0 )
    1039           0 :         ap->type = at_mark;
    1040           0 :     else if ( ismarklike==0 && (ismrk || ac->type==act_mkmk) )
    1041           0 :         ap->type = at_basemark;
    1042           0 :     else if ( ac->type == act_curs ) {
    1043           0 :         if ( ismarklike==true )
    1044           0 :             ap->type = at_centry;
    1045             :         else
    1046           0 :             ap->type = at_cexit;
    1047           0 :     } else if ( ismarklike==true )
    1048           0 :         ap->type = at_mark;
    1049             :     else
    1050           0 :         ap->type = at_basechar;
    1051             : 
    1052           0 :     if ( a!=NULL ) {
    1053           0 :         GTextInfo **ti = AnchorD_GlyphsInClass(a);
    1054           0 :         GGadgetSetList(GWidgetGetControl(a->gw,CID_Glyph),ti,false);
    1055           0 :         for ( i=0; ti[i]->text!=NULL || ti[i]->line; ++i ) {
    1056           0 :             if ( ti[i]->userdata == ap ) {
    1057           0 :                 GGadgetSelectOneListItem(GWidgetGetControl(a->gw,CID_Glyph),i);
    1058           0 :         break;
    1059             :             }
    1060             :         }
    1061           0 :         AnchorD_ChangeGlyph(a,sc,ap);
    1062             :     }
    1063           0 : return( sc );
    1064             : }
    1065             : 
    1066           0 : static int AnchorD_GlyphChanged(GGadget *g, GEvent *e) {
    1067           0 :     AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
    1068           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
    1069           0 :         GTextInfo *sel = GGadgetGetListItemSelected(g);
    1070             : 
    1071           0 :         if ( sel!=NULL ) {
    1072           0 :             AnchorPoint *ap = sel->userdata;
    1073           0 :             if ( ap==Add_Mark )
    1074           0 :                 AddAnchor(a,a->sc->parent,a->ap->anchor,true);
    1075           0 :             else if ( ap==Add_Base )
    1076           0 :                 AddAnchor(a,a->sc->parent,a->ap->anchor,false);
    1077             :             else {
    1078           0 :                 char *name = u2utf8_copy(sel->text);
    1079           0 :                 SplineChar *sc = SFGetChar(a->sc->parent,-1,name);
    1080             : 
    1081           0 :                 free(name);
    1082           0 :                 AnchorD_ChangeGlyph(a,sc,ap);
    1083             :             }
    1084             :         }
    1085             :     }
    1086           0 : return( true );
    1087             : }
    1088             : 
    1089           0 : static void AnchorD_NextPrev(AnchorDlg *a,int incr) {
    1090           0 :     GGadget *g = GWidgetGetControl(a->gw,CID_Glyph);
    1091             :     int len;
    1092           0 :     GTextInfo **ti = GGadgetGetList(g,&len);
    1093           0 :     int sel = GGadgetGetFirstListSelectedItem(g);
    1094             : 
    1095           0 :     for ( sel += incr; sel>0 && sel<len; sel+=incr ) {
    1096           0 :         if ( !( ti[sel]->userdata == Add_Mark ||
    1097           0 :                 ti[sel]->userdata == Add_Base ||
    1098           0 :                 ti[sel]->line ||
    1099           0 :                 ti[sel]->disabled ))
    1100           0 :     break;
    1101             :     }
    1102           0 :     if ( sel==0 || sel>=len )
    1103           0 :         GDrawBeep(NULL);
    1104             :     else {
    1105           0 :         char *name = u2utf8_copy(ti[sel]->text);
    1106           0 :         SplineChar *sc = SFGetChar(a->sc->parent,-1,name);
    1107             : 
    1108           0 :         free(name);
    1109           0 :         GGadgetSelectOneListItem(g,sel);
    1110           0 :         AnchorD_ChangeGlyph(a,sc,ti[sel]->userdata);
    1111             :     }
    1112           0 : }
    1113             : 
    1114           0 : static int anchord_e_h(GWindow gw, GEvent *event) {
    1115           0 :     AnchorDlg *a = GDrawGetUserData(gw);
    1116             : 
    1117           0 :     switch ( event->type ) {
    1118             :       case et_close:
    1119           0 :         AnchorD_DoCancel(a);
    1120           0 :       break;
    1121             :       case et_char:
    1122           0 :         if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
    1123           0 :             help("anchorcontrol.html");
    1124           0 : return( true );
    1125           0 :         } else if ( event->u.chr.keysym == GK_Page_Down || event->u.chr.keysym == GK_KP_Page_Down ) {
    1126           0 :             AnchorD_NextPrev(a,1);
    1127           0 : return( true );
    1128           0 :         } else if ( event->u.chr.keysym == GK_Page_Up || event->u.chr.keysym == GK_KP_Page_Up ) {
    1129           0 :             AnchorD_NextPrev(a,-1);
    1130           0 : return( true );
    1131             :         }
    1132           0 : return( false );
    1133             :       break;
    1134             :       case et_mouseup: case et_mousemove: case et_mousedown:
    1135           0 : return( AnchorD_Mouse(a,event));
    1136             :       break;
    1137             :       case et_expose:
    1138           0 :         AnchorD_Expose(a,gw,event);
    1139           0 :       break;
    1140             :       case et_resize:
    1141           0 :         AnchorD_Resize(a);
    1142           0 :         GDrawRequestExpose(a->gw,NULL,false);
    1143           0 :       break;
    1144             :       case et_controlevent:
    1145           0 :         switch( event->u.control.subtype ) {
    1146             :           case et_scrollbarchange:
    1147           0 :             AnchorD_HScroll(a,&event->u.control.u.sb);
    1148           0 :           break;
    1149             :         }
    1150           0 :       break;
    1151             :     }
    1152           0 : return( true );
    1153             : }
    1154             : 
    1155             : static GTextInfo magnifications[] = {
    1156             :     { (unichar_t *) "100%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 1, 0, 1, 0, 0, '\0'},
    1157             :     { (unichar_t *) "200%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
    1158             :     { (unichar_t *) "300%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
    1159             :     { (unichar_t *) "400%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
    1160             :     GTEXTINFO_EMPTY
    1161             : };
    1162             :     
    1163           0 : void AnchorControl(SplineChar *sc,AnchorPoint *ap,int layer) {
    1164             :     GRect pos;
    1165             :     GWindowAttrs wattrs;
    1166             :     AnchorDlg a;
    1167             :     GWindow gw;
    1168             :     GGadgetCreateData gcd[15], buttonbox, maingcd[3], *hvarray[60], *buttonarray[8];
    1169             :     GGadgetCreateData glyphbox, *glypharray[5];
    1170             :     GTextInfo label[16];
    1171             :     int k, hv;
    1172             :     extern int _GScrollBar_Width;
    1173             :     char buffer[20], xbuf[20], ybuf[20];
    1174             :     GRect boxsize;
    1175             : 
    1176           0 :     memset(&a,0,sizeof(a));
    1177           0 :     a.sc = sc;
    1178           0 :     a.ap = ap;
    1179           0 :     a.apos = ap->me;
    1180           0 :     a.pixelsize = aa_pixelsize;
    1181           0 :     a.magfactor = 1;
    1182           0 :     a.layer = layer;
    1183           0 :     if ( ap->xadjust.corrections!=NULL ) {
    1184           0 :         int len = ap->xadjust.last_pixel_size-ap->xadjust.first_pixel_size+1;
    1185           0 :         a.xadjust = ap->xadjust;
    1186           0 :         a.xadjust.corrections = malloc(len);
    1187           0 :         memcpy(a.xadjust.corrections,ap->xadjust.corrections,len);
    1188             :     }
    1189           0 :     if ( ap->yadjust.corrections!=NULL ) {
    1190           0 :         int len = ap->yadjust.last_pixel_size-ap->yadjust.first_pixel_size+1;
    1191           0 :         a.yadjust = ap->yadjust;
    1192           0 :         a.yadjust.corrections = malloc(len);
    1193           0 :         memcpy(a.yadjust.corrections,ap->yadjust.corrections,len);
    1194             :     }
    1195             : 
    1196           0 :     memset(&wattrs,0,sizeof(wattrs));
    1197             : 
    1198           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
    1199           0 :     wattrs.event_masks = ~(1<<et_charup);
    1200           0 :     wattrs.restrict_input_to_me = true;
    1201           0 :     wattrs.undercursor = 1;
    1202           0 :     wattrs.cursor = ct_pointer;
    1203           0 :     wattrs.utf8_window_title = _("Anchor Control...");
    1204           0 :     wattrs.is_dlg = true;
    1205           0 :     GDrawGetSize(GDrawGetRoot(NULL),&pos);
    1206           0 :     pos.x = pos.y = 0;
    1207           0 :     pos.height = GDrawPointsToPixels(NULL,210);
    1208           0 :     if ( pos.height<aa_pixelsize+40+25 )
    1209           0 :         pos.height = aa_pixelsize+40+25;
    1210           0 :     pos.width -= 50;
    1211           0 :     a.gw = gw = GDrawCreateTopWindow(NULL,&pos,anchord_e_h,&a,&wattrs);
    1212             : 
    1213           0 :     a.ctl_len = GDrawPointsToPixels(gw,140);
    1214           0 :     a.sb_height = GDrawPointsToPixels(gw,_GScrollBar_Width);
    1215           0 :     a.sb_base = pos.height - a.sb_height;
    1216             : 
    1217           0 :     memset(maingcd,0,sizeof(maingcd));
    1218           0 :     memset(&buttonbox,0,sizeof(buttonbox));
    1219           0 :     memset(&glyphbox,0,sizeof(glyphbox));
    1220           0 :     memset(gcd,0,sizeof(gcd));
    1221           0 :     memset(label,0,sizeof(label));
    1222           0 :     k = hv = 0;
    1223             : 
    1224           0 :     gcd[k].gd.flags = gg_visible|gg_enabled ;
    1225           0 :     gcd[k].gd.cid = CID_Glyph;
    1226           0 :     gcd[k].gd.handle_controlevent = AnchorD_GlyphChanged;
    1227           0 :     gcd[k++].creator = GListButtonCreate;
    1228             : 
    1229           0 :     glypharray[0] = GCD_Glue; glypharray[1] = &gcd[k-1]; glypharray[2] = GCD_Glue; glypharray[3] = NULL;
    1230             : 
    1231           0 :     glyphbox.gd.flags = gg_enabled|gg_visible;
    1232           0 :     glyphbox.gd.u.boxelements = glypharray;
    1233           0 :     glyphbox.creator = GHBoxCreate;
    1234             : 
    1235           0 :     hvarray[hv++] = &glyphbox; hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_ColSpan;
    1236           0 :     hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1237             : 
    1238           0 :     label[k].text = (unichar_t *) _("_Size:");
    1239           0 :     label[k].text_is_1byte = true;
    1240           0 :     label[k].text_in_resource = true;
    1241           0 :     gcd[k].gd.label = &label[k];
    1242           0 :     gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 9;
    1243           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup;
    1244           0 :     gcd[k++].creator = GLabelCreate;
    1245           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1246             : 
    1247           0 :     sprintf( buffer, "%d", a.pixelsize );
    1248           0 :     label[k].text = (unichar_t *) buffer;
    1249           0 :     label[k].text_is_1byte = true;
    1250           0 :     gcd[k].gd.label = &label[k];
    1251           0 :     gcd[k].gd.pos.x = 40; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1252           0 :     gcd[k].gd.pos.width = 60;
    1253           0 :     gcd[k].gd.flags = gg_visible|gg_enabled | gg_utf8_popup ;
    1254           0 :     gcd[k].gd.cid = CID_DisplaySize;
    1255           0 :     gcd[k].gd.handle_controlevent = AnchorD_DisplaySizeChanged;
    1256           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1257           0 :             _("The size at which the current glyph is rasterized.\nFor small pixelsize you may want to use the magnification\nfactor below to get a clearer view.\n\nThe pulldown list contains the pixelsizes at which there\nare device table corrections.");
    1258           0 :     gcd[k++].creator = GListFieldCreate;
    1259           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1260             : 
    1261             : /* GT: Short for: Magnification */
    1262           0 :     label[k].text = (unichar_t *) _("Mag:");
    1263           0 :     label[k].text_is_1byte = true;
    1264           0 :     gcd[k].gd.label = &label[k];
    1265           0 :     gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y+26;
    1266           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1267           0 :     gcd[k++].creator = GLabelCreate;
    1268           0 :     hvarray[hv++] = GCD_HPad10; hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1269             : 
    1270           0 :     gcd[k].gd.pos.x = 45; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1271           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1272           0 :     gcd[k].gd.cid = CID_Mag;
    1273           0 :     gcd[k].gd.u.list = magnifications;
    1274           0 :     gcd[k].gd.handle_controlevent = AnchorD_MagnificationChanged;
    1275           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1276           0 :             _("The glyph is rasterized at the size above, but it\nmay be difficult to see the alignment errors\nthat can happen at small pixelsizes. This allows\nyou to expand each pixel to show potential problems\nbetter.");
    1277           0 :     gcd[k++].creator = GListButtonCreate;
    1278           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1279             : 
    1280           0 :     label[k].text = (unichar_t *) _("_X");
    1281           0 :     label[k].text_is_1byte = true;
    1282           0 :     label[k].text_in_resource = true;
    1283           0 :     gcd[k].gd.label = &label[k];
    1284           0 :     gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
    1285           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1286           0 :     gcd[k++].creator = GLabelCreate;
    1287           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1288             : 
    1289           0 :     sprintf( xbuf, "%d", (int) rint(ap->me.x) );
    1290           0 :     label[k].text = (unichar_t *) xbuf;
    1291           0 :     label[k].text_is_1byte = true;
    1292           0 :     gcd[k].gd.label = &label[k];
    1293           0 :     gcd[k].gd.pos.x = 40; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1294           0 :     gcd[k].gd.pos.width = 60;
    1295           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1296           0 :     gcd[k].gd.cid = CID_X;
    1297           0 :     gcd[k].gd.handle_controlevent = AnchorD_PositionChanged;
    1298           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1299           0 :             _("The X coordinate of the anchor point in this glyph");
    1300           0 :     gcd[k++].creator = GNumericFieldCreate;
    1301           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1302             : 
    1303             : /* GT: Short for Correction */
    1304           0 :     label[k].text = (unichar_t *) _("Cor:");
    1305           0 :     label[k].text_is_1byte = true;
    1306           0 :     gcd[k].gd.label = &label[k];
    1307           0 :     gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
    1308           0 :     gcd[k].gd.flags = gg_visible|gg_enabled | gg_utf8_popup ;
    1309           0 :     gcd[k].gd.popup_msg = (unichar_t *) _("Correction in pixels to the horizontal positioning of this anchor point\nwhen rasterizing at the given pixelsize.\n(Lives in a Device Table)");
    1310           0 :     gcd[k++].creator = GLabelCreate;
    1311           0 :     hvarray[hv++] = GCD_HPad10; hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1312             : 
    1313           0 :     label[k].text = (unichar_t *) "0";
    1314           0 :     label[k].text_is_1byte = true;
    1315           0 :     gcd[k].gd.label = &label[k];
    1316           0 :     gcd[k].gd.pos.x = 45; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1317           0 :     gcd[k].gd.pos.width = 60;
    1318           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1319           0 :     gcd[k].gd.cid = CID_XCor;
    1320           0 :     gcd[k].gd.handle_controlevent = AnchorD_CorrectionChanged;
    1321           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1322           0 :             _("This is the number of pixels by which the anchor\nshould be moved horizontally when the glyph is\nrasterized at the above size.  This information\nis part of the device table for this anchor.\nDevice tables are particularly important at small\npixelsizes where rounding errors will have a\nproportionally greater effect.");
    1323           0 :     gcd[k++].creator = GNumericFieldCreate;
    1324           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1325             : 
    1326           0 :     label[k].text = (unichar_t *) _("_Y");
    1327           0 :     label[k].text_is_1byte = true;
    1328           0 :     label[k].text_in_resource = true;
    1329           0 :     gcd[k].gd.label = &label[k];
    1330           0 :     gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
    1331           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1332           0 :     gcd[k++].creator = GLabelCreate;
    1333           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1334             : 
    1335           0 :     sprintf( ybuf, "%d", (int) rint(ap->me.y) );
    1336           0 :     label[k].text = (unichar_t *) ybuf;
    1337           0 :     label[k].text_is_1byte = true;
    1338           0 :     gcd[k].gd.label = &label[k];
    1339           0 :     gcd[k].gd.pos.x = 40; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1340           0 :     gcd[k].gd.pos.width = 60;
    1341           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1342           0 :     gcd[k].gd.cid = CID_Y;
    1343           0 :     gcd[k].gd.handle_controlevent = AnchorD_PositionChanged;
    1344           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1345           0 :             _("The Y coordinate of the anchor point in this glyph");
    1346           0 :     gcd[k++].creator = GNumericFieldCreate;
    1347           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1348             : 
    1349             : /* GT: Short for Correction */
    1350           0 :     label[k].text = (unichar_t *) _("Cor:");
    1351           0 :     label[k].text_is_1byte = true;
    1352           0 :     gcd[k].gd.label = &label[k];
    1353           0 :     gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
    1354           0 :     gcd[k].gd.flags = gg_visible|gg_enabled | gg_utf8_popup ;
    1355           0 :     gcd[k].gd.popup_msg = (unichar_t *) _("Correction in pixels to the horizontal positioning of this anchor point\nwhen rasterizing at the given pixelsize.\n(Lives in a Device Table)");
    1356           0 :     gcd[k++].creator = GLabelCreate;
    1357           0 :     hvarray[hv++] = GCD_HPad10; hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_ColSpan;
    1358             : 
    1359           0 :     label[k].text = (unichar_t *) "0";
    1360           0 :     label[k].text_is_1byte = true;
    1361           0 :     gcd[k].gd.label = &label[k];
    1362           0 :     gcd[k].gd.pos.x = 45; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
    1363           0 :     gcd[k].gd.pos.width = 60;
    1364           0 :     gcd[k].gd.flags = gg_visible|gg_enabled  | gg_utf8_popup ;
    1365           0 :     gcd[k].gd.cid = CID_YCor;
    1366           0 :     gcd[k].gd.handle_controlevent = AnchorD_CorrectionChanged;
    1367           0 :     gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg = (unichar_t *)
    1368           0 :             _("This is the number of pixels by which the anchor\nshould be moved vertically when the glyph is\nrasterized at the above size.  This information\nis part of the device table for this anchor.\nDevice tables are particularly important at small\npixelsizes where rounding errors will have a\nproportionally greater effect.");
    1369           0 :     gcd[k++].creator = GNumericFieldCreate;
    1370           0 :     hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1371             : 
    1372           0 :     hvarray[hv++] = GCD_Glue; hvarray[hv++] = GCD_Glue; hvarray[hv++] = GCD_Glue;
    1373           0 :     hvarray[hv++] = GCD_Glue; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1374             : 
    1375           0 :     label[k].text = (unichar_t *) _("_OK");
    1376           0 :     label[k].text_is_1byte = true;
    1377           0 :     label[k].text_in_resource = true;
    1378           0 :     gcd[k].gd.label = &label[k];
    1379           0 :     gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+40;
    1380           0 :     gcd[k].gd.pos.width = -1;
    1381           0 :     gcd[k].gd.flags = gg_visible|gg_enabled|gg_but_default;
    1382           0 :     gcd[k].gd.handle_controlevent = AnchorD_OK;
    1383           0 :     gcd[k++].creator = GButtonCreate;
    1384           0 :     buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[k-1]; buttonarray[2] = GCD_Glue;
    1385             : 
    1386           0 :     label[k].text = (unichar_t *) _("_Cancel");
    1387           0 :     label[k].text_is_1byte = true;
    1388           0 :     label[k].text_in_resource = true;
    1389           0 :     gcd[k].gd.label = &label[k];
    1390           0 :     gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
    1391           0 :     gcd[k].gd.pos.width = -1;
    1392           0 :     gcd[k].gd.flags = gg_visible|gg_enabled|gg_but_cancel;
    1393           0 :     gcd[k].gd.handle_controlevent = AnchorD_Cancel;
    1394           0 :     gcd[k++].creator = GButtonCreate;
    1395           0 :     buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[k-1]; buttonarray[5] = GCD_Glue;
    1396           0 :     buttonarray[6] = NULL;
    1397             : 
    1398           0 :     buttonbox.gd.flags = gg_enabled|gg_visible;
    1399           0 :     buttonbox.gd.u.boxelements = buttonarray;
    1400           0 :     buttonbox.creator = GHBoxCreate;
    1401             : 
    1402           0 :     hvarray[hv++] = &buttonbox; hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_ColSpan;
    1403           0 :     hvarray[hv++] = GCD_ColSpan; hvarray[hv++] = GCD_Glue; hvarray[hv++] = NULL;
    1404           0 :     hvarray[hv++] = NULL;
    1405             : 
    1406           0 :     maingcd[0].gd.pos.x = maingcd[0].gd.pos.y = 5;
    1407           0 :     maingcd[0].gd.pos.height = pos.height - 10;
    1408             : /*    maingcd[0].gd.pos.width = a.ctl_len - 10; */
    1409           0 :     maingcd[0].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels;
    1410           0 :     maingcd[0].gd.u.boxelements = hvarray;
    1411           0 :     maingcd[0].creator = GHVBoxCreate;
    1412             : 
    1413           0 :     maingcd[1].gd.pos.x = 300;
    1414           0 :     maingcd[1].gd.pos.y = pos.height-a.sb_height;
    1415           0 :     maingcd[1].gd.pos.height = a.sb_height;
    1416           0 :     maingcd[1].gd.pos.width = pos.width-300;
    1417           0 :     maingcd[1].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
    1418           0 :     maingcd[1].creator = GScrollBarCreate;
    1419             : 
    1420           0 :     GGadgetsCreate(a.gw,maingcd);
    1421           0 :     GGadgetSetList(gcd[0].ret,AnchorD_GlyphsInClass(&a),false);
    1422           0 :     GTextInfoListFree(gcd[0].gd.u.list);
    1423             : 
    1424           0 :     GHVBoxSetExpandableRow(maingcd[0].ret,gb_expandglue);
    1425           0 :     GHVBoxSetExpandableCol(maingcd[0].ret,4);
    1426           0 :     GHVBoxSetExpandableCol(buttonbox.ret,gb_expandgluesame);
    1427           0 :     GHVBoxSetExpandableCol(glyphbox.ret,gb_expandglue);
    1428           0 :     GGadgetGetDesiredSize(maingcd[0].ret,&boxsize,NULL);
    1429           0 :     a.ctl_len = boxsize.width + 10;
    1430             :     
    1431           0 :     a.hsb = maingcd[1].ret;
    1432             : 
    1433           0 :     AnchorD_FindComplements(&a);
    1434           0 :     AnchorD_SetDevTabs(&a);
    1435           0 :     AnchorD_ChangeSize(&a);
    1436           0 :     AnchorD_SetTitle(&a);
    1437             : 
    1438           0 :     GDrawSetVisible(a.gw,true);
    1439           0 :     while ( !a.done )
    1440           0 :         GDrawProcessOneEvent(NULL);
    1441           0 :     GDrawDestroyWindow(a.gw);
    1442           0 :     AnchorD_FreeAll(&a);
    1443           0 : }
    1444             : 
    1445           0 : void AnchorControlClass(SplineFont *_sf,AnchorClass *ac,int layer) {
    1446             :     /* Pick a random glyph with an anchor point in the class. If no glyph, */
    1447             :     /*  give user the chance to create one */
    1448           0 :     SplineChar *sc, *scmark = NULL;
    1449           0 :     AnchorPoint *ap, *apmark = NULL;
    1450             :     SplineFont *sf;
    1451             :     int k, gid;
    1452             : 
    1453           0 :     if ( _sf->cidmaster!=NULL ) _sf = _sf->cidmaster;
    1454           0 :     k=0;
    1455           0 :     ap = NULL;
    1456             :     do {
    1457           0 :         sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
    1458           0 :         for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
    1459           0 :             for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
    1460           0 :                 if ( ap->anchor==ac ) {
    1461           0 :                     if ( ap->type!=at_mark && ap->type!=at_centry )
    1462             :             break;
    1463           0 :                     else if ( scmark==NULL ) {
    1464           0 :                         scmark = sc;
    1465           0 :                         apmark = ap;
    1466             :                     }
    1467             :                 }
    1468             :             }
    1469           0 :             if ( ap!=NULL )
    1470           0 :         break;
    1471             :         }
    1472           0 :         if ( ap!=NULL )
    1473           0 :     break;
    1474           0 :         ++k;
    1475           0 :     } while ( k<_sf->subfontcnt );
    1476             : 
    1477           0 :     if ( ap==NULL ) {
    1478           0 :         sc = scmark;
    1479           0 :         ap = apmark;
    1480             :     }
    1481           0 :     if ( ap==NULL ) {
    1482           0 :         sc = AddAnchor(NULL,_sf,ac,-1);
    1483           0 :         if ( sc==NULL )
    1484           0 : return;
    1485           0 :         for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
    1486           0 :             if ( ap->anchor==ac )
    1487           0 :         break;
    1488             :         }
    1489           0 :         if ( ap==NULL )         /* Can't happen */
    1490           0 : return;
    1491             :     }
    1492             :         
    1493           0 :     AnchorControl(sc,ap,layer);
    1494             : }

Generated by: LCOV version 1.10