LCOV - code coverage report
Current view: top level - fontforgeexe - cvdebug.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 8 0.0 %
Date: 2017-08-04 Functions: 0 4 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             :  * dercved 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 "cvundoes.h"
      28             : #include "fontforgeui.h"
      29             : #include "splineorder2.h"
      30             : #include "splineutil.h"
      31             : #include <math.h>
      32             : #include <gkeysym.h>
      33             : #include <ustring.h>
      34             : #include <gresource.h>
      35             : 
      36             : extern GBox _ggadget_Default_Box;
      37             : #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
      38             : 
      39             : int debug_wins = dw_registers|dw_stack;
      40             : 
      41             : #ifndef FREETYPE_HAS_DEBUGGER
      42           0 : void CVDebugReInit(CharView *cv,int restart_debug,int debug_fpgm) {
      43           0 : }
      44             : 
      45           0 : void CVDebugFree(DebugView *dv) {
      46           0 : }
      47             : 
      48           0 : int DVChar(DebugView *dv, GEvent *event) {
      49           0 : return( false );
      50             : }
      51             : 
      52           0 : void CVDebugPointPopup(CharView *cv) {
      53           0 : }
      54             : #else
      55             : #include <ft2build.h>
      56             : #include FT_FREETYPE_H
      57             : #include <internal/internal.h>
      58             : #include "ttinterp.h"
      59             : 
      60             : # define PPEMX(exc)     ((exc)->size->root.metrics.x_ppem)
      61             : # define PPEMY(exc)     ((exc)->size->root.metrics.y_ppem)
      62             : 
      63             : static Color rasterbackcol = 0xffffff;
      64             : 
      65             : static int debuggercolsinited = false;
      66             : 
      67             : static void DebugColInit( void ) {
      68             :     GResStruct debugcolors[] = {
      69             :         { "Background", rt_color, &rasterbackcol, NULL, 0 },
      70             :         GRESSTRUCT_EMPTY
      71             :     };
      72             :     if ( debuggercolsinited )
      73             : return;
      74             :     rasterbackcol = GDrawGetDefaultBackground(screen_display);
      75             :     GResourceFind( debugcolors, "DVRaster.");
      76             :     debuggercolsinited = true;
      77             : }
      78             : 
      79             : static int DVBpCheck(struct instrinfo *ii, int ip) {
      80             :     DebugView *dv = (ii->userdata);
      81             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
      82             : 
      83             :     if ( exc==NULL )
      84             : return( false );
      85             : 
      86             : return( DebuggerBpCheck( dv->dc,exc->curRange,ip));
      87             : }
      88             : 
      89             : static void DVToggleBp(struct instrinfo *ii, int ip) {
      90             :     DebugView *dv = (ii->userdata);
      91             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
      92             : 
      93             :     if ( exc==NULL )
      94             : return;
      95             :     DebuggerToggleBp(dv->dc,exc->curRange,ip);
      96             : }
      97             : 
      98             : static void DVRasterExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
      99             :     CharView *cv = dv->cv;
     100             :     int y,x,xem, yem;
     101             :     GRect r;
     102             : 
     103             :     GDrawGetSize(dv->raster,&r);
     104             :     GDrawFillRect(pixmap,&event->u.expose.rect,rasterbackcol);
     105             :     xem = cv->ft_ppemx;
     106             :     yem = cv->ft_ppemy;
     107             :     x = (r.width - xem)/2;
     108             :     y = (r.height - yem)/2 + yem*cv->b.sc->parent->ascent/(cv->b.sc->parent->ascent+cv->b.sc->parent->descent);
     109             : 
     110             :     GDrawDrawLine(pixmap,0,y,r.width,y,0xa0a0a0);       /* Axes */
     111             :     GDrawDrawLine(pixmap,x,0,x,r.height,0xa0a0a0);
     112             : 
     113             :     if ( cv->raster!=NULL ) {
     114             :         GImage gi;
     115             :         struct _GImage base;
     116             :         GClut clut;
     117             :         int i;
     118             : 
     119             :         memset(&gi,'\0',sizeof(gi));
     120             :         memset(&base,'\0',sizeof(base));
     121             :         memset(&clut,'\0',sizeof(clut));
     122             :         gi.u.image = &base;
     123             :         base.clut = &clut;
     124             :         if ( cv->raster->num_greys<=2 ) {
     125             :             base.image_type = it_mono;
     126             :             clut.clut_len = 2;
     127             :             clut.clut[0] = rasterbackcol;
     128             :             clut.trans_index = 0;
     129             :         } else {
     130             :             base.image_type = it_index;
     131             :             clut.clut_len = 256;
     132             :             clut.clut[0] = rasterbackcol;
     133             :             for ( i=1; i<256; ++i ) {
     134             :                 clut.clut[i] = ( (COLOR_RED(clut.clut[0])*(0xff-i)/0xff)<<16 ) |
     135             :                         ( (COLOR_GREEN(clut.clut[0])*(0xff-i)/0xff)<<8 ) |
     136             :                         ( (COLOR_BLUE(clut.clut[0])*(0xff-i)/0xff) );
     137             :             }
     138             :             clut.trans_index = 0;
     139             :         }
     140             :         base.data = cv->raster->bitmap;
     141             :         base.bytes_per_line = cv->raster->bytes_per_row;
     142             :         base.width = cv->raster->cols;
     143             :         base.height = cv->raster->rows;
     144             :         GDrawDrawImage(pixmap,&gi,NULL, x+cv->raster->lb,y-cv->raster->as);
     145             :     }
     146             : }
     147             : 
     148             : static void DVRegExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     149             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
     150             :     char buffer[100];
     151             :     int y;
     152             : 
     153             :     GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
     154             :     GDrawSetFont(pixmap,dv->ii.gfont);
     155             :     y = 3+dv->ii.as - dv->reg_offtop*dv->ii.fh;
     156             : 
     157             :     if ( exc==NULL ) {
     158             :         GDrawDrawText8(pixmap,3,y,"<not running>",-1,MAIN_FOREGROUND);
     159             : return;
     160             :     }
     161             : 
     162             :     sprintf( buffer, " rp0: %d", exc->GS.rp0 );
     163             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     164             :     sprintf( buffer, " rp1: %d", exc->GS.rp1 );
     165             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     166             :     sprintf( buffer, " rp2: %d", exc->GS.rp2 );
     167             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     168             :     sprintf( buffer, "loop: %ld", exc->GS.loop );
     169             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     170             :     y+=2;
     171             : 
     172             :     sprintf( buffer, " zp0: %s", exc->GS.gep0?"Normal":"Twilight" );
     173             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     174             :     sprintf( buffer, " zp1: %s", exc->GS.gep1?"Normal":"Twilight" );
     175             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     176             :     sprintf( buffer, " zp2: %s", exc->GS.gep2?"Normal":"Twilight" );
     177             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     178             :     y+=2;
     179             : 
     180             :     sprintf( buffer, "MinDist: %.2f", exc->GS.minimum_distance/64.0 );
     181             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     182             :     sprintf( buffer, "CvtCutin: %.2f", exc->GS.control_value_cutin/64.0 );
     183             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     184             :     sprintf( buffer, "SingWidCut: %.2f", exc->GS.single_width_cutin/64.0 );
     185             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     186             :     sprintf( buffer, "SingWidVal: %.2f", exc->GS.single_width_value/64.0 );
     187             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     188             :     y+=2;
     189             : 
     190             :     sprintf( buffer, "freeVec: %g,%g", (((int)exc->GS.freeVector.x<<16)>>(16+14)) + ((exc->GS.freeVector.x&0x3fff)/16384.0),
     191             :             (((int)exc->GS.freeVector.y<<16)>>(16+14)) + ((exc->GS.freeVector.y&0x3fff)/16384.0) );
     192             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     193             :     sprintf( buffer, "projVec: %g,%g", (((int)exc->GS.projVector.x<<16)>>(16+14)) + ((exc->GS.projVector.x&0x3fff)/16384.0),
     194             :             (((int)exc->GS.projVector.y<<16)>>(16+14)) + ((exc->GS.projVector.y&0x3fff)/16384.0) );
     195             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     196             :     sprintf( buffer, "dualVec: %g,%g", (((int)exc->GS.dualVector.x<<16)>>(16+14)) + ((exc->GS.dualVector.x&0x3fff)/16384.0),
     197             :             (((int)exc->GS.dualVector.y<<16)>>(16+14)) + ((exc->GS.dualVector.y&0x3fff)/16384.0) );
     198             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     199             :     y+=2;
     200             : 
     201             :     sprintf( buffer, "AutoFlip: %s", exc->GS.auto_flip?"True": "False" );
     202             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     203             :     sprintf( buffer, "DeltaBase: %d", exc->GS.delta_base );
     204             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     205             :     sprintf( buffer, "DeltaShift: %d", exc->GS.delta_shift );
     206             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     207             :     sprintf( buffer, "RndState: %s",
     208             :             exc->GS.round_state==TT_Round_To_Half_Grid? "To Half Grid" :
     209             :             exc->GS.round_state==TT_Round_To_Grid? "To Grid" :
     210             :             exc->GS.round_state==TT_Round_To_Double_Grid? "To Double Grid" :
     211             :             exc->GS.round_state==TT_Round_Down_To_Grid? "Down To Grid" :
     212             :             exc->GS.round_state==TT_Round_Up_To_Grid? "Up To Grid" :
     213             :             exc->GS.round_state==TT_Round_Off? "Off" :
     214             :             exc->GS.round_state==TT_Round_Super? "Super" :
     215             :             exc->GS.round_state==TT_Round_Super_45? "Super45" :
     216             :                 "Unknown" );
     217             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     218             :     sprintf( buffer, "SRndPeriod: %.2f", exc->period/64.0 );
     219             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     220             :     sprintf( buffer, "SRndPhase: %.2f", exc->phase/64.0 );
     221             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     222             :     sprintf( buffer, "SRndThreshold: %.2f", exc->threshold/64.0 );
     223             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     224             :     sprintf( buffer, "InstrControl: %d", exc->GS.instruct_control );
     225             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     226             :     sprintf( buffer, "ScanControl: %s", exc->GS.scan_control?"True": "False" );
     227             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     228             :     sprintf( buffer, "ScanType: %d", exc->GS.scan_type );
     229             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     230             : 
     231             :     /* Instruction control, scan control, scan type, phase, threshold for super rounding */
     232             : 
     233             :     y += 2;
     234             :     sprintf( buffer, "Pixels/Em: %d", PPEMY(exc) );
     235             :     GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND); y += dv->ii.fh;
     236             : }
     237             : 
     238             : static void DVStackExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     239             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
     240             :     char buffer[100];
     241             :     int i, y;
     242             : 
     243             :     GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
     244             :     GDrawSetFont(pixmap,dv->ii.gfont);
     245             :     y = 3+dv->ii.as - dv->stack_offtop*dv->ii.fh;
     246             :     if ( exc==NULL  || exc->top==0 ) {
     247             :         GDrawDrawText8(pixmap,3,y,"<empty>",-1,MAIN_FOREGROUND);
     248             :     } else {
     249             :         for ( i=exc->top-1; i>=0; --i ) {
     250             :             sprintf(buffer, "%3d: %3ld (%.2f)", i, exc->stack[i], exc->stack[i]/64.0 );
     251             :             GDrawDrawText8(pixmap,3,y,buffer,-1,MAIN_FOREGROUND);
     252             :             if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
     253             :         break;
     254             :             y += dv->ii.fh;
     255             :         }
     256             :     }
     257             : }
     258             : 
     259             : static void DVStorageExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     260             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
     261             :     char buffer[100];
     262             :     int i, y;
     263             : 
     264             :     GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
     265             :     GDrawSetFont(pixmap,dv->ii.gfont);
     266             :     y = 3+dv->ii.as - dv->storage_offtop*dv->ii.fh;
     267             :     if ( exc==NULL || exc->storeSize==0 ) {
     268             :         GDrawDrawText8(pixmap,3,y,_("<empty>"),-1,MAIN_FOREGROUND);
     269             :     } else {
     270             :         int n_watch;
     271             :         uint8 *watches = DebuggerGetWatchStores(dv->dc,&n_watch);
     272             :         for ( i=0; i<exc->storeSize; ++i ) {
     273             :             if ( !DebuggerIsStorageSet(dv->dc,i) )
     274             :                 sprintf( buffer, _("%3d: <uninitialized>"), i );
     275             :             else
     276             :                 sprintf(buffer, "%3d: %3ld (%.2f)", i, exc->storage[i], exc->storage[i]/64.0 );
     277             :             if ( i<n_watch && watches!=NULL && watches[i] && y>0 )
     278             :                 GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
     279             :                             y-dv->ii.as-2);
     280             :             GDrawDrawText8(pixmap,23,y,buffer,-1,MAIN_FOREGROUND);
     281             :             if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
     282             :         break;
     283             :             y += dv->ii.fh;
     284             :         }
     285             :     }
     286             : }
     287             : 
     288             : static void DVCvtExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     289             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
     290             :     char buffer[100];
     291             :     int i, y;
     292             : 
     293             :     GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
     294             :     GDrawSetFont(pixmap,dv->ii.gfont);
     295             :     y = 3+dv->ii.as;
     296             :     if ( exc==NULL || exc->cvtSize==0 ) {
     297             :         GDrawDrawText8(pixmap,3,y,_("<empty>"),-1,MAIN_FOREGROUND);
     298             :     } else {
     299             :         int n_watch;
     300             :         uint8 *watches = DebuggerGetWatchCvts(dv->dc,&n_watch);
     301             :         for ( i=0; dv->cvt_offtop+i<exc->cvtSize; ++i ) {
     302             :             sprintf(buffer, "%3d: %3ld (%.2f)", dv->cvt_offtop+i,
     303             :                     exc->cvt[dv->cvt_offtop+i], exc->cvt[dv->cvt_offtop+i]/64.0 );
     304             :             if ( dv->cvt_offtop+i<n_watch && watches!=NULL && watches[dv->cvt_offtop+i] && y>0 )
     305             :                 GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
     306             :                             y-dv->ii.as-2);
     307             :             GDrawDrawText8(pixmap,23,y,buffer,-1,MAIN_FOREGROUND);
     308             :             if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
     309             :         break;
     310             :             y += dv->ii.fh;
     311             :         }
     312             :     }
     313             : }
     314             : 
     315             : static void ScalePoint(BasePoint *me,FT_Vector *cur,real scalex, real scaley,struct reflist *a) {
     316             :     double x,y,temp, offx, offy;
     317             : 
     318             :     x = cur->x*scalex;
     319             :     y = cur->y*scaley;
     320             :     while ( a!=NULL ) {
     321             :         RefChar *r = a->ref;
     322             :         a = a->parent;
     323             :         temp = r->transform[0]*x + r->transform[2]*y;
     324             :         y    = r->transform[1]*x + r->transform[3]*y;
     325             :         x    = temp;
     326             :         offx = r->transform[4];
     327             :         offy = r->transform[5];
     328             :         if ( r->round_translation_to_grid ) {
     329             :             offx = rint(offx/(scalex*64))*scalex*64;
     330             :             offy = rint(offy/(scaley*64))*scaley*64;
     331             :         }
     332             :         x += offx; y += offy;
     333             :     }
     334             :     me->x = x;
     335             :     me->y = y;
     336             : }
     337             : 
     338             : #define CID_Twilight    1001
     339             : #define CID_Normal      1002
     340             : #define CID_Grid        1003
     341             : #define CID_EmUnit      1004
     342             : #define CID_Raw         1005
     343             : #define CID_Current     1006
     344             : #define CID_Original    1007
     345             : #define CID_Transform   1008
     346             : static int show_twilight = false, show_grid=true, show_current=true, show_transformed=true, show_raw=false;
     347             : 
     348             : static void DVPointsVExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     349             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
     350             :     char buffer[100];
     351             :     int i, l, y, c;
     352             :     FT_Vector *pts;
     353             :     int n, n_watch, ph;
     354             :     TT_GlyphZoneRec *r;
     355             :     uint8 *watches;
     356             :     BasePoint me,me2;
     357             :     struct reflist *actives;
     358             : 
     359             :     GDrawFillRect(pixmap,&event->u.expose.rect,GDrawGetDefaultBackground(screen_display));
     360             :     y = 3+dv->ii.as-dv->points_offtop*dv->ii.fh;
     361             :     if ( exc==NULL )
     362             :         n = 0;
     363             :     else {
     364             :         show_twilight = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight));
     365             :         show_grid = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Grid));
     366             : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
     367             :         show_raw = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Raw));
     368             : #endif
     369             :         if ( !show_raw )
     370             :             show_transformed = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Transform));
     371             :         show_current = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Current));
     372             :         r = show_twilight ? &exc->twilight : &exc->pts;
     373             :         n = r->n_points;
     374             :         pts = show_current ? r->cur : r->org;
     375             :         c = 0;
     376             :         ph = FreeTypeAtLeast(2,1,8)?4:2;        /* number of phantom pts */
     377             : 
     378             :         actives = dv->active_refs;
     379             :         if ( !show_transformed || show_raw )
     380             :             actives = NULL;
     381             : 
     382             :         watches = DebuggerGetWatches(dv->dc,&n_watch);
     383             : 
     384             :         GDrawSetFont(pixmap,dv->ii.gfont);
     385             :         for ( i=0; i<n; ++i ) {
     386             :             if ( i==0 ) l=n-ph; else l=i-1;     /* Skip 4 phantom points */
     387             :             if ( !show_twilight && i<n-ph &&
     388             :                     !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On)) {
     389             :                 ScalePoint(&me,&pts[i],dv->scalex,dv->scaley,actives);
     390             :                 ScalePoint(&me2,&pts[l],dv->scalex,dv->scaley,actives);
     391             :                 me.x = (me.x+me2.x)/2;  me.y = (me.y+me2.y)/2;
     392             :                 if ( show_grid )
     393             :                     sprintf(buffer, "   : I   %.2f,%.2f",
     394             :                             (double) (me.x/dv->scalex/64.0), (double) (me.y/dv->scaley/64.0) );
     395             :                 else if ( show_raw )
     396             :                     sprintf(buffer, "   : I   %g,%g",
     397             :                             (double) ((pts[i].x+pts[l].x)/2.0), (double) ((pts[i].y+pts[l].y)/2.0) );
     398             :                 else
     399             :                     sprintf(buffer, "   : I   %g,%g", (double) me.x , (double) me.y );
     400             :                 if ( y>0 )
     401             :                     GDrawDrawText8(pixmap,3+19,y,buffer,-1,MAIN_FOREGROUND);
     402             :                 y += dv->ii.fh;
     403             :             }
     404             :             if ( r->contours!=NULL && i==r->contours[c] ) {       /* No contours in twilight */
     405             :                 ++c;
     406             :                 GDrawDrawLine(pixmap,0,y+dv->ii.fh-dv->ii.as,
     407             :                             event->u.expose.rect.x+event->u.expose.rect.width,y+dv->ii.fh-dv->ii.as,
     408             :                             0x000000);
     409             :             }
     410             :             if ( i<n_watch && !show_twilight && watches!=NULL && watches[i] && y>0 )
     411             :                 GDrawDrawImage(pixmap,&GIcon_Stop,NULL,3,
     412             :                             y-dv->ii.as-2);
     413             :             ScalePoint(&me,&pts[i],dv->scalex,dv->scaley,actives);
     414             :             if ( show_grid )
     415             :                 sprintf(buffer, "%3d: %c%c%c %.2f,%.2f", i,
     416             :                         show_twilight ? 'T' : i>=n-ph? 'F' : r->tags[i]&FT_Curve_Tag_On?'P':'C',
     417             :                         r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
     418             :                         (double) (me.x/dv->scalex/64.0), (double) (me.y/dv->scaley/64.0) );
     419             :             else if ( show_raw )
     420             :                 sprintf(buffer, "%3d: %c%c%c %d,%d", i,
     421             :                         r->tags[i]&FT_Curve_Tag_On?'P':'C', r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
     422             :                         (int) pts[i].x, (int) pts[i].y );
     423             :             else
     424             :                 sprintf(buffer, "%3d: %c%c%c %g,%g", i,
     425             :                         r->tags[i]&FT_Curve_Tag_On?'P':'C', r->tags[i]&FT_Curve_Tag_Touch_X?'X':' ', r->tags[i]&FT_Curve_Tag_Touch_Y?'Y':' ',
     426             :                         (double) me.x, (double) me.y );
     427             :             if ( y>0 )
     428             :                 GDrawDrawText8(pixmap,3+19,y,buffer,-1,MAIN_FOREGROUND);
     429             :             if ( y>event->u.expose.rect.y+event->u.expose.rect.height )
     430             :         break;
     431             :             y += dv->ii.fh;
     432             :         }
     433             :     }
     434             :     if ( n==0 ) {
     435             :         GDrawDrawText8(pixmap,3,y,_("<none>"),-1,MAIN_FOREGROUND);
     436             :     }
     437             : }
     438             : 
     439             : static void DVPointsExpose(GWindow pixmap,DebugView *dv,GEvent *event) {
     440             :     GDrawSetLineWidth(pixmap,0);
     441             :     GDrawDrawLine(pixmap,event->u.expose.rect.x,dv->pts_head-1,event->u.expose.rect.x+event->u.expose.rect.width,dv->pts_head-1,0x000000);
     442             : }
     443             : 
     444             : static SplineSet *ContourFromPoint(TT_GlyphZoneRec *pts, real scalex, real scaley,int i,
     445             :         SplineSet *last, struct reflist *actives ) {
     446             :     SplineSet *cur;
     447             :     SplinePoint *sp;
     448             :     BasePoint me;
     449             : 
     450             :     ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
     451             : 
     452             :     sp = SplinePointCreate(me.x,me.y);
     453             :     sp->ttfindex = i;
     454             :     cur = chunkalloc(sizeof(SplineSet));
     455             :     if ( last!=NULL )
     456             :         last->next = cur;
     457             :     cur->first = cur->last = sp;
     458             : return( cur );
     459             : }
     460             : 
     461             : static SplineSet *SplineSetsFromPoints(TT_GlyphZoneRec *pts, real scalex, real scaley,
     462             :         struct reflist *actives) {
     463             :     int i=0, c, last_off, start;
     464             :     SplineSet *head=NULL, *last=NULL, *cur;
     465             :     SplinePoint *sp;
     466             :     BasePoint me, me2;
     467             :     /* very similar to parsettf.c: ttfbuildcontours */
     468             : 
     469             :     for ( c=0; c<pts->n_contours; ++c ) {
     470             :         if ( pts->contours[c]<i ) /* Sigh. Yes there are fonts with bad endpt info */
     471             :     continue;
     472             :         cur = chunkalloc(sizeof(SplineSet));
     473             :         if ( head==NULL )
     474             :             head = cur;
     475             :         else
     476             :             last->next = cur;
     477             :         last = cur;
     478             :         last_off = false;
     479             :         start = i;
     480             :         while ( i<=pts->contours[c] && i<pts->n_points ) {
     481             :             if ( pts->tags[i]&FT_Curve_Tag_On ) {
     482             :                 ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
     483             :                 sp = SplinePointCreate(me.x,me.y);
     484             :                 sp->ttfindex = i;
     485             :                 if ( last_off && cur->last!=NULL ) {
     486             :                     ScalePoint(&cur->last->nextcp,&pts->cur[i-1],scalex,scaley,actives);
     487             :                     sp->prevcp = cur->last->nextcp;
     488             :                     cur->last->nonextcp = false;
     489             :                     cur->last->nextcpindex = i-1;
     490             :                     sp->noprevcp = false;
     491             :                 }
     492             :                 last_off = false;
     493             :             } else if ( last_off ) {
     494             :                 ScalePoint(&me,&pts->cur[i],scalex,scaley,actives);
     495             :                 ScalePoint(&me2,&pts->cur[i-1],scalex,scaley,actives);
     496             :                 sp = SplinePointCreate((me.x+me2.x)/2, (me.y+me2.y)/2 );
     497             :                 sp->noprevcp = false;
     498             :                 sp->ttfindex = 0xffff;
     499             :                 if ( last_off && cur->last!=NULL ) {
     500             :                     cur->last->nextcp = sp->prevcp = me2;
     501             :                     cur->last->nonextcp = false;
     502             :                     cur->last->nextcpindex = i-1;
     503             :                 }
     504             :                 /* last_off continues to be true */
     505             :             } else {
     506             :                 last_off = true;
     507             :                 sp = NULL;
     508             :             }
     509             :             if ( sp!=NULL ) {
     510             :                 if ( cur->first==NULL )
     511             :                     cur->first = sp;
     512             :                 else
     513             :                     SplineMake2(cur->last,sp);
     514             :                 cur->last = sp;
     515             :             }
     516             :             ++i;
     517             :         }
     518             :         if ( start==i-1 ) {
     519             :             /* Single point contours (probably for positioning components, etc.) */
     520             :             ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
     521             :             sp = SplinePointCreate(me.x,me.y);
     522             :             sp->ttfindex = i-1;
     523             :             cur->first = cur->last = sp;
     524             :         } else if ( !(pts->tags[start]&FT_Curve_Tag_On) && !(pts->tags[i-1]&FT_Curve_Tag_On) ) {
     525             :             ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
     526             :             ScalePoint(&me2,&pts->cur[i-1],scalex,scaley,actives);
     527             :             sp = SplinePointCreate((me.x+me2.x)/2 , (me.y+me2.y)/2);
     528             :             sp->noprevcp = sp->nonextcp = false;
     529             :             cur->last->nextcp = sp->prevcp = me2;
     530             :             SplineMake2(cur->last,sp);
     531             :             cur->last = sp;
     532             :             cur->last->nextcp = cur->first->prevcp = me;
     533             :             cur->first->noprevcp = false;
     534             :             cur->last->nextcpindex = start;
     535             :         } else if ( !(pts->tags[i-1]&FT_Curve_Tag_On)) {
     536             :             ScalePoint(&me,&pts->cur[i-1],scalex,scaley,actives);
     537             :             cur->last->nextcp = cur->first->prevcp = me;
     538             :             cur->last->nonextcp = cur->first->noprevcp = false;
     539             :             cur->last->nextcpindex = i-1;
     540             :         } else if ( !(pts->tags[start]&FT_Curve_Tag_On) ) {
     541             :             ScalePoint(&me,&pts->cur[start],scalex,scaley,actives);
     542             :             cur->last->nextcp = cur->first->prevcp = me;
     543             :             cur->last->nonextcp = cur->first->noprevcp = false;
     544             :             cur->last->nextcpindex = start;
     545             :         }
     546             :         if ( cur->last!=cur->first ) {
     547             :             SplineMake2(cur->last,cur->first);
     548             :             cur->last = cur->first;
     549             :         }
     550             :     }
     551             :     if ( i+1<pts->n_points ) {
     552             :         /* depending on the version of freetype there should be either 2 or 4 */
     553             :         /*  metric phantom points (2 horizontal metrics + 2 vertical metrics) */
     554             :         last = ContourFromPoint(pts,scalex,scaley,i,last,actives);
     555             :         if ( head==NULL ) head = last;
     556             :         last = ContourFromPoint(pts,scalex,scaley,i+1,last,actives);
     557             :         if ( i+3<pts->n_points ) {
     558             :             last = ContourFromPoint(pts,scalex,scaley,i+2,last,actives);
     559             :             last = ContourFromPoint(pts,scalex,scaley,i+3,last,actives);
     560             :         }
     561             :     }
     562             : return( head );
     563             : }
     564             : 
     565             : static int DVStackTestSB(DebugView *dv, TT_ExecContext exc) {
     566             :     int min, max, page, offtop;
     567             :     GRect size;
     568             :     int top = exc==NULL ? 1 : exc->top;
     569             : 
     570             :     GScrollBarGetBounds(dv->stacksb,&min,&max,&page);
     571             :     GGadgetGetSize(dv->stacksb,&size);
     572             :     size.height /= dv->ii.fh;
     573             :     if ( max!=top || page!=size.height ) {
     574             :         GScrollBarSetBounds(dv->stacksb,0,top,size.height);
     575             :         offtop = dv->stack_offtop;
     576             :         if ( offtop+size.height > top )
     577             :             offtop = top-size.height;
     578             :         if ( offtop < 0 )
     579             :             offtop = 0;
     580             :         if ( offtop!=dv->stack_offtop ) {
     581             :             dv->stack_offtop = offtop;
     582             :             GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
     583             : return( true );
     584             :         }
     585             :     }
     586             : return( false );
     587             : }
     588             : 
     589             : static int SameInstructionSet(DebugView *dv,TT_ExecContext exc) {
     590             :     /* This is a guessing game. It's easy enough to detect when we call a */
     591             :     /*  subroutine, but detecting changing glyphs in a composite glyph is */
     592             :     /*  much harder */
     593             :     int i;
     594             : 
     595             :     if ( dv->id.instrs!=(uint8 *) exc->code )
     596             : return( false );        /* We called (or returned from) a subroutine */
     597             : 
     598             :     if ( dv->codeSize != exc->codeSize )
     599             : return( false );        /* A glyph with a different number of instrs has been copied into the glyph instr area */
     600             : 
     601             :     for ( i=0 ; i<sizeof(dv->initialbytes) && i<dv->codeSize; ++i )
     602             :         if ( dv->initialbytes[i] != ((uint8 *) exc->code)[i] )
     603             : return( false );
     604             : 
     605             : return( true );         /* As best we can tell... */
     606             : }
     607             : 
     608             : static struct reflist *ARFindBase(SplineChar *sc,struct reflist *parent,int layer) {
     609             :     struct reflist *ret, *temp;
     610             :     RefChar *ref;
     611             : 
     612             :     if ( sc->layers[layer].splines!=NULL ||
     613             :             sc->layers[layer].refs==NULL )
     614             : return( parent );
     615             :     ret = chunkalloc(sizeof(struct reflist));
     616             :     ret->parent = parent;
     617             :     for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
     618             :         ret->ref = ref;
     619             :         temp = ARFindBase(ref->sc,ret,layer);
     620             :         if ( temp!=ret )
     621             : return( temp );
     622             :         if ( ref->sc->ttf_instrs_len!=0 )
     623             : return( ret );
     624             :     }
     625             :     chunkfree(ret,sizeof(struct reflist));
     626             : return( parent );
     627             : }
     628             : 
     629             : static void DVPointsFigureSB(DebugView *dv);
     630             : 
     631             : static void ChangeCode(DebugView *dv,TT_ExecContext exc) {
     632             :     int i;
     633             : 
     634             :     dv->id.instrs =(uint8 *) exc->code;
     635             :     dv->id.instr_cnt = exc->codeSize;
     636             :     IIReinit(&dv->ii,exc->IP);
     637             :     dv->codeSize = exc->codeSize;
     638             :     dv->last_npoints = exc->pts.n_points;
     639             :     for ( i=0 ; i<sizeof(dv->initialbytes) && i<dv->codeSize; ++i )
     640             :         dv->initialbytes[i] = ((uint8 *) exc->code)[i];
     641             : 
     642             :     if ( dv->active_refs==NULL )
     643             :         dv->active_refs = ARFindBase(dv->cv->b.sc,NULL,dv->layer);
     644             :     else {
     645             :         struct reflist *temp;
     646             :         while ( dv->active_refs!=NULL ) {
     647             :             dv->active_refs->ref = dv->active_refs->ref->next;
     648             :             if ( dv->active_refs->ref==NULL ) {
     649             :                 temp = dv->active_refs;
     650             :                 dv->active_refs = temp->parent;
     651             :                 chunkfree(temp,sizeof(struct reflist));
     652             :                 if ( dv->active_refs==NULL ) {
     653             :                     if ( dv->cv->b.sc->ttf_instrs_len!=0 )
     654             :         break;
     655             :                     dv->active_refs = ARFindBase(dv->cv->b.sc,NULL,dv->layer);
     656             :         break;
     657             :                 } else if ( dv->active_refs->ref->sc->ttf_instrs_len!=0 )
     658             :         break;
     659             :                 else
     660             :         continue;
     661             :             }
     662             :             temp = ARFindBase(dv->active_refs->ref->sc,dv->active_refs,dv->layer);
     663             :             if ( temp!=dv->active_refs ) {
     664             :                 dv->active_refs = temp;
     665             :         break;
     666             :             }
     667             :             if ( temp->ref->sc->ttf_instrs_len!=0 )
     668             :         break;
     669             :         }
     670             :     }
     671             :     if ( dv->points!=NULL )
     672             :         DVPointsFigureSB(dv);
     673             : }
     674             :     
     675             : static void DVFigureNewState(DebugView *dv,TT_ExecContext exc) {
     676             :     int range = exc==NULL ? cr_none : exc->curRange;
     677             :     CharView *cv = dv->cv;
     678             : 
     679             :     /* Code to look for proper function/idef rather than the full fpgm table */
     680             :     if ( exc==NULL ) {
     681             :         dv->id.instrs = NULL;
     682             :         dv->id.instr_cnt = 0;
     683             :         IIReinit(&dv->ii,-1);
     684             :         if ( cv->oldraster!=NULL )
     685             :             FreeType_FreeRaster(cv->oldraster);
     686             :         cv->oldraster = NULL;
     687             :     } else if ( !SameInstructionSet(dv,exc) || dv->last_npoints!=exc->pts.n_points ) {
     688             :         ChangeCode(dv,exc);
     689             :     } else
     690             :         IIScrollTo(&dv->ii,exc->IP,true);
     691             : 
     692             :     /* We might ask for a fractional number of pixels for an em. Freetype */
     693             :     /*  isn't going to give us that, it rounds. Rather than guess how it does */
     694             :     /*  that, let's just ask it... */
     695             :     /* The exact size is: cv->ft_pointsize*cv->ft_dpi/72.0 */
     696             :     /* Rounded size is:   exc->size->root.metrics.x_ppem (or y_ppem) */
     697             :     if ( exc!=NULL ) {
     698             :         dv->scalex = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/((double) PPEMX(exc)) / (1<<6);
     699             :         dv->scaley = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/((double) PPEMY(exc)) / (1<<6);
     700             :     }
     701             :     if ( cv!=NULL && cv->coderange!=range ) {
     702             :         cv->coderange = range;
     703             :         CVInfoDraw(cv,cv->gw);
     704             :     }
     705             : 
     706             :     if ( exc!=NULL ) {
     707             :         if ( cv->oldraster!=NULL )
     708             :             FreeType_FreeRaster(cv->oldraster);
     709             :         cv->oldraster = cv->raster;
     710             :         SplinePointListsFree(cv->b.gridfit);
     711             :         cv->b.gridfit = SplineSetsFromPoints(&exc->pts,dv->scalex,dv->scaley,dv->active_refs);
     712             :         DVMarkPts(dv,cv->b.gridfit);
     713             :         cv->raster = DebuggerCurrentRaster(exc,cv->ft_depth);
     714             :         if ( show_transformed && !show_raw && cv->raster!=NULL ) {
     715             :             BasePoint me;
     716             :             FT_Vector cur;
     717             :             cur.y = cv->raster->as * 64;
     718             :             cur.x = cv->raster->lb * 64;
     719             :             ScalePoint(&me,&cur,dv->scalex,dv->scaley,dv->active_refs);
     720             :             cv->raster->lb = rint(me.x/dv->scalex/64);
     721             :             cv->raster->as = rint(me.y/dv->scaley/64);
     722             :         }
     723             :         if ( exc->pts.n_points<=2 )
     724             :             cv->b.ft_gridfitwidth = 0;
     725             :         /* suport for vertical phantom pts */
     726             :         else if ( FreeTypeAtLeast(2,1,8))
     727             :             cv->b.ft_gridfitwidth = exc->pts.cur[exc->pts.n_points-3].x * dv->scalex;
     728             :         else
     729             :             cv->b.ft_gridfitwidth = exc->pts.cur[exc->pts.n_points-1].x * dv->scalex;
     730             :     }
     731             : 
     732             :     if ( cv!=NULL )
     733             :         GDrawRequestExpose(cv->v,NULL,false);
     734             :     if ( dv->regs!=NULL )
     735             :         GDrawRequestExpose(dv->regs,NULL,false);
     736             :     if ( dv->stack!=NULL ) {
     737             :         DVStackTestSB(dv,exc);
     738             :         GDrawRequestExpose(dv->stack,NULL,false);
     739             :     }
     740             :     if ( dv->storage!=NULL )
     741             :         GDrawRequestExpose(dv->storage,NULL,false);
     742             :     if ( dv->cvt!=NULL )
     743             :         GDrawRequestExpose(dv->cvt,NULL,false);
     744             :     if ( dv->points!=NULL )
     745             :         GDrawRequestExpose(dv->points_v,NULL,false);
     746             :     if ( dv->raster!=NULL )
     747             :         GDrawRequestExpose(dv->raster,NULL,false);
     748             :     if ( dv->gloss!=NULL )
     749             :         GDrawRequestExpose(dv->gloss,NULL,false);
     750             : }
     751             : 
     752             : /* If a glyph has no instructions, it has no execcontext. But it is still */
     753             : /*  consistent to provide a current rasterization view (of the non-grid fit */
     754             : /*  splines) */
     755             : static void DVDefaultRaster(DebugView *dv) {
     756             :     CharView *cv = dv->cv;
     757             :     void *single_glyph_context;
     758             :     SplineFont *sf = cv->b.sc->parent;
     759             :     int layer = CVLayer((CharViewBase *) cv);
     760             : 
     761             :     if ( cv->oldraster!=NULL )
     762             :         FreeType_FreeRaster(cv->oldraster);
     763             :     cv->oldraster = cv->raster;
     764             :     SplinePointListsFree(cv->b.gridfit);
     765             :     cv->b.gridfit = NULL;
     766             :     single_glyph_context = _FreeTypeFontContext(sf,cv->b.sc,NULL,layer,
     767             :             cv->b.sc->layers[layer].order2?ff_ttf:ff_otf,0,NULL);
     768             :     if ( single_glyph_context!=NULL ) {
     769             :         cv->raster = FreeType_GetRaster(single_glyph_context,cv->b.sc->orig_pos,
     770             :                 cv->ft_pointsizey, cv->ft_pointsizex, cv->ft_dpi, cv->ft_depth );
     771             :         FreeTypeFreeContext(single_glyph_context);
     772             :     }
     773             :     cv->b.ft_gridfitwidth = 0;
     774             : 
     775             :     if ( cv->v!=NULL )
     776             :         GDrawRequestExpose(cv->v,NULL,false);
     777             :     if ( dv->raster!=NULL )
     778             :         GDrawRequestExpose(dv->raster,NULL,false);
     779             : }
     780             : 
     781             : static void DVGoFigure(DebugView *dv,enum debug_gotype go) {
     782             :     DebuggerGo(dv->dc,go,dv);
     783             :     DVFigureNewState(dv,DebuggerGetEContext(dv->dc));
     784             : }
     785             : 
     786             : static int DV_Run(GGadget *g, GEvent *e) {
     787             :     DebugView *dv;
     788             : 
     789             :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     790             :         dv = GDrawGetUserData(GGadgetGetWindow(g));
     791             :         DVGoFigure(dv,(enum debug_gotype) GGadgetGetCid(g));
     792             :     }
     793             : return( true );
     794             : }
     795             : 
     796             : static int DV_WatchPnt(GGadget *g, GEvent *e) {
     797             :     DebugView *dv;
     798             :     int pnum=0, n, any=0;
     799             :     SplineSet *ss;
     800             :     SplinePoint *sp;
     801             :     uint8 *watches;
     802             : 
     803             :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     804             :         dv = GDrawGetUserData(GGadgetGetWindow(g));
     805             :         if ( dv->cv->b.layerheads[dv->cv->b.drawmode]->refs!=NULL ) {
     806             :             ff_post_error(_("No Watch Points"),_("Watch Points not supported in glyphs with references"));
     807             : return( true );
     808             :         }
     809             : 
     810             :         DebuggerGetWatches(dv->dc,&n);
     811             :         watches = calloc(n,sizeof(uint8));
     812             : 
     813             :         for ( ss = dv->cv->b.layerheads[dv->cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
     814             :             for ( sp=ss->first; ; ) {
     815             :                 sp->watched = false;
     816             :                 if ( sp->ttfindex == 0xffff )
     817             :                     /* Ignore it */;
     818             :                 else if ( sp->selected && sp->ttfindex<n) {
     819             :                     watches[pnum=sp->ttfindex] = true;
     820             :                     any = true;
     821             :                     sp->watched = true;
     822             :                 }
     823             :                 if ( !sp->nonextcp ) {
     824             :                     ++pnum;
     825             :                     if ( sp==dv->cv->p.sp && dv->cv->p.nextcp && pnum<n )
     826             :                         watches[pnum] = true;
     827             :                 }
     828             :                 if ( sp->next==NULL )
     829             :             break;
     830             :                 sp = sp->next->to;
     831             :                 if ( sp==ss->first )
     832             :             break;
     833             :             }
     834             :         }
     835             :         if ( !any ) {
     836             :             free(watches);
     837             :             watches = NULL;
     838             :         }
     839             :         DebuggerSetWatches(dv->dc,n,watches);
     840             :         GDrawRequestExpose(dv->cv->v,NULL,false);
     841             :         if ( dv->points!=NULL )
     842             :             GDrawRequestExpose(dv->points_v,NULL,false);
     843             :     }
     844             : return( true );
     845             : }
     846             : 
     847             : #define MID_Registers   1001
     848             : #define MID_Stack       1002
     849             : #define MID_Storage     1003
     850             : #define MID_Points      1004
     851             : #define MID_Cvt         1005
     852             : #define MID_Raster      1006
     853             : #define MID_Gloss       1007
     854             : 
     855             : static void DVCreateRegs(DebugView *dv);
     856             : static void DVCreateStack(DebugView *dv);
     857             : static void DVCreateStore(DebugView *dv);
     858             : static void DVCreatePoints(DebugView *dv);
     859             : static void DVCreateCvt(DebugView *dv);
     860             : static void DVCreateRaster(DebugView *dv);
     861             : 
     862             : static struct { int flag; void (*create)(DebugView *); } wcreat[] = {
     863             :     {dw_registers, DVCreateRegs},
     864             :     {dw_stack, DVCreateStack},
     865             :     {dw_storage, DVCreateStore},
     866             :     {dw_points, DVCreatePoints},
     867             :     {dw_cvt, DVCreateCvt},
     868             :     {dw_raster, DVCreateRaster},
     869             :     {dw_gloss, DVCreateGloss},
     870             :     { 0, NULL }
     871             : };
     872             : 
     873             : static void DVMenuCreate(GWindow v, GMenuItem *mi,GEvent *e) {
     874             :     DebugView *dv = (DebugView *) GDrawGetUserData(v);
     875             : 
     876             :     if ( (&dv->regs)[mi->mid-MID_Registers]==NULL ) {
     877             :         (wcreat[mi->mid-MID_Registers].create)(dv);
     878             :         debug_wins |= wcreat[mi->mid-MID_Registers].flag;
     879             :     } else {
     880             :         GDrawDestroyWindow((&dv->regs)[mi->mid-MID_Registers]);
     881             :         debug_wins &= ~wcreat[mi->mid-MID_Registers].flag;
     882             :     }
     883             :     SavePrefs(true);
     884             : }
     885             : 
     886             : static GMenuItem popupwindowlist[] = {
     887             :     { { (unichar_t *) N_("Registers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Registers },
     888             :     { { (unichar_t *) N_("Stack"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Stack },
     889             :     { { (unichar_t *) N_("Storage"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Storage },
     890             :     { { (unichar_t *) N_("Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Points },
     891             :     { { (unichar_t *) N_("Cvt"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Cvt },
     892             :     { { (unichar_t *) N_("Raster"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Raster },
     893             :     { { (unichar_t *) N_("Gloss"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 0, 0, '\0' }, '\0', 0, NULL, NULL, DVMenuCreate, MID_Gloss },
     894             :     GMENUITEM_EMPTY
     895             : };
     896             : 
     897             : static int DV_WindowMenu(GGadget *g, GEvent *e) {
     898             :     DebugView *dv;
     899             :     GEvent fake;
     900             :     GRect pos;
     901             :     static int done = false;
     902             : 
     903             :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonpress ) {
     904             :         dv = GDrawGetUserData(GGadgetGetWindow(g));
     905             :         if ( !done ) {
     906             :             int i;
     907             :             for ( i=0; popupwindowlist[i].ti.text!=NULL; ++i )
     908             :                 popupwindowlist[i].ti.text = (unichar_t *) _((char *) popupwindowlist[i].ti.text);
     909             :             done = true;
     910             :         }
     911             :         popupwindowlist[0].ti.checked = dv->regs!=NULL;
     912             :         popupwindowlist[1].ti.checked = dv->stack!=NULL;
     913             :         popupwindowlist[2].ti.checked = dv->storage!=NULL;
     914             :         popupwindowlist[3].ti.checked = dv->points!=NULL;
     915             :         popupwindowlist[4].ti.checked = dv->cvt!=NULL;
     916             :         popupwindowlist[5].ti.checked = dv->raster!=NULL;
     917             :         popupwindowlist[6].ti.checked = dv->gloss!=NULL;
     918             :         GGadgetGetSize(g,&pos);
     919             :         memset(&fake,0,sizeof(fake));
     920             :         fake.type = et_mousedown;
     921             :         fake.w = dv->dv;
     922             :         fake.u.mouse.x = pos.x;
     923             :         fake.u.mouse.y = pos.y+pos.height;
     924             :         GMenuCreatePopupMenu(dv->dv,&fake, popupwindowlist);
     925             :     }
     926             : return( true );
     927             : }
     928             : 
     929             : static int DV_Exit(GGadget *g, GEvent *e) {
     930             :     DebugView *dv;
     931             : 
     932             :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     933             :         dv = GDrawGetUserData(GGadgetGetWindow(g));
     934             :         CVDebugFree(dv);
     935             :     }
     936             : return( true );
     937             : }
     938             : 
     939             : static void DVExpose(GWindow pixmap, DebugView *dv,GEvent *event) {
     940             :     GDrawSetLineWidth(pixmap,0);
     941             :     GDrawDrawLine(pixmap, 0, dv->toph-1, dv->dwidth, dv->toph-1, 0x000000 );
     942             : }
     943             : 
     944             : int DVChar(DebugView *dv, GEvent *event) {
     945             : 
     946             :     if ( event->u.chr.state&(ksm_control|ksm_meta) || dv==NULL )
     947             : return( false );
     948             :     /* Can't redo F1, handled by menu */
     949             :     if ( event->u.chr.keysym == GK_Help )
     950             : return( false );
     951             :     if ( event->u.chr.keysym >= GK_F1 && event->u.chr.keysym<=GK_F10 )
     952             : return( false );
     953             : 
     954             :     switch ( event->u.chr.keysym ) {
     955             :       case 's': case 'S':               /* Step */
     956             :         DVGoFigure(dv,dgt_step);
     957             :       break;
     958             :       case 'n': case 'N':               /* Next */
     959             :         DVGoFigure(dv,dgt_next);
     960             :       break;
     961             :       case 'f': case 'F':               /* finish */
     962             :         DVGoFigure(dv,dgt_stepout);
     963             :       break;
     964             :       case 'c': case 'C':               /* Continue */
     965             :         DVGoFigure(dv,dgt_continue);
     966             :       break;
     967             :       case 'k': case 'K': case 'q': case 'Q':   /* Kill (debugger) */
     968             :         CVDebugFree(dv);
     969             :       break;
     970             :       case 'r': case 'R':               /* run/restart (debugger) */
     971             :         CVDebugReInit(dv->cv,true,DebuggingFpgm(dv->dc));
     972             :       break;
     973             :       default:
     974             :         /* The window check is to prevent infinite loops since CVChar can */
     975             :         /*  call DVChar too */
     976             :         if ( event->w == dv->dv || event->w == dv->v ) {
     977             :             CVChar(dv->cv,event);
     978             : return( true );
     979             :         }
     980             : 
     981             : return( false );
     982             :     }
     983             : return( true );
     984             : }
     985             : 
     986             : static int DV_HandleChar(struct instrinfo *ii, GEvent *event) {
     987             :     DebugView *dv = (ii->userdata);
     988             : return( DVChar(dv,event));
     989             : }
     990             : 
     991             : static int dvraster_e_h(GWindow gw, GEvent *event) {
     992             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
     993             : 
     994             :     if ( dv==NULL )
     995             : return( true );
     996             : 
     997             :     switch ( event->type ) {
     998             :       case et_expose:
     999             :         DVRasterExpose(gw,dv,event);
    1000             :       break;
    1001             :       case et_char:
    1002             : return( DVChar(dv,event));
    1003             :       break;
    1004             :       case et_close:
    1005             :         GDrawDestroyWindow(dv->raster);
    1006             :         debug_wins &= ~dw_raster;
    1007             :       break;
    1008             :       case et_destroy:
    1009             :         dv->raster = NULL;
    1010             :       break;
    1011             :       case et_mouseup: case et_mousedown:
    1012             :       case et_mousemove:
    1013             :         GGadgetEndPopup();
    1014             :       break;
    1015             :       default:
    1016             :         /* */
    1017             :       break;
    1018             :     }
    1019             : return( true );
    1020             : }
    1021             : 
    1022             : static const int reg_size = 26;
    1023             : 
    1024             : static void DVReg_SetScrollBar(DebugView *dv) {
    1025             :     GRect size;
    1026             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1027             :     int lh = exc==NULL ? 0 : reg_size;
    1028             : 
    1029             :     GDrawGetSize(dv->regs,&size);
    1030             :     GScrollBarSetBounds(dv->regsb,0,lh,size.height/dv->ii.fh);
    1031             :     if ( dv->reg_offtop + size.height/dv->ii.fh > lh ) {
    1032             :         int lpos = lh-size.height/dv->ii.fh;
    1033             :         if ( lpos<0 ) lpos = 0;
    1034             :         dv->reg_offtop = lpos;
    1035             :     }
    1036             :     GScrollBarSetPos(dv->regsb,dv->reg_offtop);
    1037             : }
    1038             : 
    1039             : static void dvreg_scroll(DebugView *dv,struct sbevent *sb) {
    1040             :     int newpos = dv->reg_offtop;
    1041             :     GRect size;
    1042             :     extern int _GScrollBar_Width;
    1043             : 
    1044             :     GDrawGetSize(dv->regs,&size);
    1045             :     switch( sb->type ) {
    1046             :       case et_sb_top:
    1047             :         newpos = 0;
    1048             :       break;
    1049             :       case et_sb_uppage:
    1050             :         newpos -= size.height/dv->ii.fh;
    1051             :       break;
    1052             :       case et_sb_up:
    1053             :         --newpos;
    1054             :       break;
    1055             :       case et_sb_down:
    1056             :         ++newpos;
    1057             :       break;
    1058             :       case et_sb_downpage:
    1059             :         newpos += size.height/dv->ii.fh;
    1060             :       break;
    1061             :       case et_sb_bottom:
    1062             :         newpos = reg_size-size.height/dv->ii.fh;
    1063             :       break;
    1064             :       case et_sb_thumb:
    1065             :       case et_sb_thumbrelease:
    1066             :         newpos = sb->pos;
    1067             :       break;
    1068             :     }
    1069             :     if ( newpos>reg_size-size.height/dv->ii.fh )
    1070             :         newpos = reg_size-size.height/dv->ii.fh;
    1071             :     if ( newpos<0 ) newpos =0;
    1072             :     if ( newpos!=dv->reg_offtop ) {
    1073             :         int diff = newpos-dv->reg_offtop;
    1074             :         dv->reg_offtop = newpos;
    1075             :         GScrollBarSetPos(dv->regsb,dv->reg_offtop);
    1076             :         size.x = size.y = 0;
    1077             :         size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
    1078             :         GDrawScroll(dv->regs,&size,0,diff*dv->ii.fh);
    1079             :     }
    1080             : }
    1081             : 
    1082             : static int dvreg_e_h(GWindow gw, GEvent *event) {
    1083             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1084             :     GRect r,g;
    1085             : 
    1086             :     if ( dv==NULL )
    1087             : return( true );
    1088             : 
    1089             :     switch ( event->type ) {
    1090             :       case et_expose:
    1091             :         DVRegExpose(gw,dv,event);
    1092             :       break;
    1093             :       case et_char:
    1094             : return( DVChar(dv,event));
    1095             :       break;
    1096             :       case et_controlevent:
    1097             :         switch ( event->u.control.subtype ) {
    1098             :           case et_scrollbarchange:
    1099             :             dvreg_scroll(dv,&event->u.control.u.sb);
    1100             :           break;
    1101             :         }
    1102             :       break;
    1103             :       case et_resize:
    1104             :         GDrawGetSize(gw,&r);
    1105             :         GGadgetGetSize(dv->regsb,&g);
    1106             :         GGadgetMove(dv->regsb,r.width-g.width,0);
    1107             :         GGadgetResize(dv->regsb,g.width,r.height);
    1108             :         DVReg_SetScrollBar(dv);
    1109             :         GDrawRequestExpose(dv->regs,NULL,false);
    1110             :       break;
    1111             :       case et_close:
    1112             :         GDrawDestroyWindow(dv->regs);
    1113             :         debug_wins &= ~dw_registers;
    1114             :       break;
    1115             :       case et_destroy:
    1116             :         dv->regs = NULL;
    1117             :       break;
    1118             :       case et_mouseup: case et_mousedown:
    1119             :       case et_mousemove:
    1120             :         GGadgetEndPopup();
    1121             :       break;
    1122             :     }
    1123             : return( true );
    1124             : }
    1125             : 
    1126             : static void DVStack_SetScrollBar(DebugView *dv) {
    1127             :     GRect size;
    1128             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1129             :     int lh = exc==NULL ? 0 : exc->top;
    1130             : 
    1131             :     GDrawGetSize(dv->stack,&size);
    1132             :     GScrollBarSetBounds(dv->stacksb,0,lh,size.height/dv->ii.fh);
    1133             :     if ( dv->stack_offtop + size.height/dv->ii.fh > lh ) {
    1134             :         int lpos = lh-size.height/dv->ii.fh;
    1135             :         if ( lpos<0 ) lpos = 0;
    1136             :         dv->stack_offtop = lpos;
    1137             :     }
    1138             :     GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
    1139             : }
    1140             : 
    1141             : static void dvstack_scroll(DebugView *dv,struct sbevent *sb) {
    1142             :     int newpos = dv->stack_offtop;
    1143             :     GRect size;
    1144             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1145             :     extern int _GScrollBar_Width;
    1146             : 
    1147             :     GDrawGetSize(dv->stack,&size);
    1148             :     switch( sb->type ) {
    1149             :       case et_sb_top:
    1150             :         newpos = 0;
    1151             :       break;
    1152             :       case et_sb_uppage:
    1153             :         newpos -= size.height/dv->ii.fh;
    1154             :       break;
    1155             :       case et_sb_up:
    1156             :         --newpos;
    1157             :       break;
    1158             :       case et_sb_down:
    1159             :         ++newpos;
    1160             :       break;
    1161             :       case et_sb_downpage:
    1162             :         newpos += size.height/dv->ii.fh;
    1163             :       break;
    1164             :       case et_sb_bottom:
    1165             :         newpos = exc->top-size.height/dv->ii.fh;
    1166             :       break;
    1167             :       case et_sb_thumb:
    1168             :       case et_sb_thumbrelease:
    1169             :         newpos = sb->pos;
    1170             :       break;
    1171             :     }
    1172             :     if ( newpos>exc->top-size.height/dv->ii.fh )
    1173             :         newpos = exc->top-size.height/dv->ii.fh;
    1174             :     if ( newpos<0 ) newpos =0;
    1175             :     if ( newpos!=dv->stack_offtop ) {
    1176             :         int diff = newpos-dv->stack_offtop;
    1177             :         dv->stack_offtop = newpos;
    1178             :         GScrollBarSetPos(dv->stacksb,dv->stack_offtop);
    1179             :         size.x = size.y = 0;
    1180             :         size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
    1181             :         GDrawScroll(dv->stack,&size,0,diff*dv->ii.fh);
    1182             :     }
    1183             : }
    1184             : 
    1185             : static int dvstack_e_h(GWindow gw, GEvent *event) {
    1186             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1187             :     GRect r,g;
    1188             : 
    1189             :     if ( dv==NULL )
    1190             : return( true );
    1191             : 
    1192             :     switch ( event->type ) {
    1193             :       case et_expose:
    1194             :         DVStackExpose(gw,dv,event);
    1195             :       break;
    1196             :       case et_char:
    1197             : return( DVChar(dv,event));
    1198             :       break;
    1199             :       case et_controlevent:
    1200             :         switch ( event->u.control.subtype ) {
    1201             :           case et_scrollbarchange:
    1202             :             dvstack_scroll(dv,&event->u.control.u.sb);
    1203             :           break;
    1204             :         }
    1205             :       break;
    1206             :       case et_resize:
    1207             :         GDrawGetSize(gw,&r);
    1208             :         GGadgetGetSize(dv->stacksb,&g);
    1209             :         GGadgetMove(dv->stacksb,r.width-g.width,0);
    1210             :         GGadgetResize(dv->stacksb,g.width,r.height);
    1211             :         DVStack_SetScrollBar(dv);
    1212             :         GDrawRequestExpose(dv->stack,NULL,false);
    1213             :       break;
    1214             :       case et_close:
    1215             :         GDrawDestroyWindow(dv->stack);
    1216             :         debug_wins &= ~dw_stack;
    1217             :       break;
    1218             :       case et_destroy:
    1219             :         dv->stack = NULL;
    1220             :       break;
    1221             :       case et_mouseup: case et_mousedown:
    1222             :       case et_mousemove:
    1223             :         GGadgetEndPopup();
    1224             :       break;
    1225             :     }
    1226             : return( true );
    1227             : }
    1228             : 
    1229             : static void DVStorage_SetScrollBar(DebugView *dv) {
    1230             :     GRect size;
    1231             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1232             :     int lh = exc==NULL ? 0 : exc->storeSize;
    1233             : 
    1234             :     GDrawGetSize(dv->storage,&size);
    1235             :     GScrollBarSetBounds(dv->storagesb,0,lh,size.height/dv->ii.fh);
    1236             :     if ( dv->storage_offtop + size.height/dv->ii.fh > lh ) {
    1237             :         int lpos = lh-size.height/dv->ii.fh;
    1238             :         if ( lpos<0 ) lpos = 0;
    1239             :         dv->storage_offtop = lpos;
    1240             :     }
    1241             :     GScrollBarSetPos(dv->storagesb,dv->storage_offtop);
    1242             : }
    1243             : 
    1244             : static void dvstorage_scroll(DebugView *dv,struct sbevent *sb) {
    1245             :     int newpos = dv->storage_offtop;
    1246             :     GRect size;
    1247             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1248             :     extern int _GScrollBar_Width;
    1249             : 
    1250             :     GDrawGetSize(dv->storage,&size);
    1251             :     switch( sb->type ) {
    1252             :       case et_sb_top:
    1253             :         newpos = 0;
    1254             :       break;
    1255             :       case et_sb_uppage:
    1256             :         newpos -= size.height/dv->ii.fh;
    1257             :       break;
    1258             :       case et_sb_up:
    1259             :         --newpos;
    1260             :       break;
    1261             :       case et_sb_down:
    1262             :         ++newpos;
    1263             :       break;
    1264             :       case et_sb_downpage:
    1265             :         newpos += size.height/dv->ii.fh;
    1266             :       break;
    1267             :       case et_sb_bottom:
    1268             :         newpos = exc->storeSize-size.height/dv->ii.fh;
    1269             :       break;
    1270             :       case et_sb_thumb:
    1271             :       case et_sb_thumbrelease:
    1272             :         newpos = sb->pos;
    1273             :       break;
    1274             :     }
    1275             :     if ( newpos>exc->storeSize-size.height/dv->ii.fh )
    1276             :         newpos = exc->storeSize-size.height/dv->ii.fh;
    1277             :     if ( newpos<0 ) newpos =0;
    1278             :     if ( newpos!=dv->storage_offtop ) {
    1279             :         int diff = newpos-dv->storage_offtop;
    1280             :         dv->storage_offtop = newpos;
    1281             :         GScrollBarSetPos(dv->storagesb,dv->storage_offtop);
    1282             :         size.x = size.y = 0;
    1283             :         size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
    1284             :         GDrawScroll(dv->storage,&size,0,diff*dv->ii.fh);
    1285             :     }
    1286             : }
    1287             : 
    1288             : static int dvstore_e_h(GWindow gw, GEvent *event) {
    1289             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1290             :     GRect r,g;
    1291             : 
    1292             :     if ( dv==NULL )
    1293             : return( true );
    1294             : 
    1295             :     switch ( event->type ) {
    1296             :       case et_expose:
    1297             :         DVStorageExpose(gw,dv,event);
    1298             :       break;
    1299             :       case et_char:
    1300             : return( DVChar(dv,event));
    1301             :       break;
    1302             :       case et_controlevent:
    1303             :         switch ( event->u.control.subtype ) {
    1304             :           case et_scrollbarchange:
    1305             :             dvstorage_scroll(dv,&event->u.control.u.sb);
    1306             :           break;
    1307             :         }
    1308             :       break;
    1309             :       case et_resize:
    1310             :         GDrawGetSize(gw,&r);
    1311             :         GGadgetGetSize(dv->storagesb,&g);
    1312             :         GGadgetMove(dv->storagesb,r.width-g.width,0);
    1313             :         GGadgetResize(dv->storagesb,g.width,r.height);
    1314             :         DVStorage_SetScrollBar(dv);
    1315             :         GDrawRequestExpose(gw,NULL,false);
    1316             :       break;
    1317             :       case et_close:
    1318             :         GDrawDestroyWindow(dv->storage);
    1319             :         debug_wins &= ~dw_storage;
    1320             :       break;
    1321             :       case et_destroy:
    1322             :         dv->storage = NULL;
    1323             :       break;
    1324             :       case et_mouseup: {
    1325             :         int i;
    1326             :         int n;
    1327             :         uint8 *watches;
    1328             :         TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1329             :         i = (event->u.mouse.y-3)/dv->ii.fh+dv->storage_offtop;
    1330             :         if ( i>=0 && exc!=NULL ) {
    1331             :             watches = DebuggerGetWatchStores(dv->dc,&n);
    1332             :             if ( watches==NULL ) {
    1333             :                 watches = calloc(n,sizeof(uint8));
    1334             :                 DebuggerSetWatchStores(dv->dc,n,watches);
    1335             :             }
    1336             :             if ( i<n ) {
    1337             :                 watches[i] = !watches[i];
    1338             :                 GDrawRequestExpose(dv->storage,NULL,false);
    1339             :             }
    1340             :         }
    1341             :       } /* Fall through */;
    1342             :       case et_mousedown:
    1343             :       case et_mousemove:
    1344             :         GGadgetEndPopup();
    1345             :       break;
    1346             :     }
    1347             : return( true );
    1348             : }
    1349             : 
    1350             : static int dvpts_cnt(DebugView *dv) {
    1351             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1352             :     int i, l, cnt;
    1353             :     FT_Vector *pts;
    1354             :     int n;
    1355             :     TT_GlyphZoneRec *r;
    1356             : 
    1357             :     if ( exc==NULL )            /* Can happen in glyphs with no instructions */
    1358             : return( 0 );
    1359             : 
    1360             :     show_twilight = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight));
    1361             :     show_current = GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Current));
    1362             :     r = show_twilight ? &exc->twilight : &exc->pts;
    1363             :     n = r->n_points;
    1364             :     pts = show_current ? r->cur : r->org;
    1365             : 
    1366             :     cnt = 0;
    1367             :     for ( i=0; i<n; ++i ) {
    1368             :         if ( i==0 ) l=n-5; else l=i-1;
    1369             :         if ( !show_twilight && i<n-4 &&
    1370             :                 !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On))
    1371             :             ++cnt;
    1372             :         ++cnt;
    1373             :     }
    1374             : return( cnt );
    1375             : }
    1376             : 
    1377             : static void DVPointsFigureSB(DebugView *dv) {
    1378             :     int l, cnt;
    1379             :     GRect size;
    1380             : 
    1381             :     cnt = dvpts_cnt(dv);
    1382             :     GDrawGetSize(dv->points_v,&size);
    1383             :     l = size.height/dv->ii.fh;
    1384             :     GScrollBarSetBounds(dv->pts_vsb,0,cnt,l);
    1385             :     if ( dv->points_offtop+l > cnt )
    1386             :         dv->points_offtop = cnt-l;
    1387             :     if ( dv->points_offtop < 0 )
    1388             :         dv->points_offtop = 0;
    1389             :     GScrollBarSetPos(dv->pts_vsb,dv->points_offtop);
    1390             : }
    1391             : 
    1392             : static int dvpointsv_e_h(GWindow gw, GEvent *event) {
    1393             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1394             : 
    1395             :     if ( dv==NULL )
    1396             : return( true );
    1397             : 
    1398             :     switch ( event->type ) {
    1399             :       case et_expose:
    1400             :         DVPointsVExpose(gw,dv,event);
    1401             :       break;
    1402             :       case et_char:
    1403             : return( DVChar(dv,event));
    1404             :       break;
    1405             :       case et_mouseup: {
    1406             :         int i,j,k,l,ph;
    1407             :         TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1408             :         i = (event->u.mouse.y-3)/dv->ii.fh+dv->points_offtop;
    1409             :         if ( i>=0 && exc!=NULL && !GGadgetIsChecked(GWidgetGetControl(dv->points,CID_Twilight)) ) {
    1410             :             ph = FreeTypeAtLeast(2,1,8)?4:2;    /* number of phantom pts */
    1411             :             for ( j=k=0; j<exc->pts.n_points; ++j ) {
    1412             :                 l = (j==0) ? exc->pts.n_points-ph : j-1;
    1413             :                 if ( !(exc->pts.tags[j]&FT_Curve_Tag_On) && !(exc->pts.tags[l]&FT_Curve_Tag_On)) {
    1414             :                     if ( k==i )
    1415             :             break;
    1416             :                     ++k;
    1417             :                 }
    1418             :                 if ( k==i ) {
    1419             :                     int n;
    1420             :                     uint8 *watches;
    1421             :                     watches = DebuggerGetWatches(dv->dc,&n);
    1422             :                     if ( watches==NULL ) {
    1423             :                         watches = calloc(n,sizeof(uint8));
    1424             :                         DebuggerSetWatches(dv->dc,n,watches);
    1425             :                     }
    1426             :                     if ( j<n ) {
    1427             :                         SplineSet *ss;
    1428             :                         SplinePoint *sp;
    1429             :                         watches[j] = !watches[j];
    1430             :                         for ( ss=dv->cv->b.layerheads[dv->cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
    1431             :                             for ( sp=ss->first; sp->ttfindex<=j || sp->ttfindex==0xffff; ) {
    1432             :                                 if ( sp->ttfindex==j )
    1433             :                                     sp->watched = watches[j];
    1434             :                                 if ( sp->next==NULL )
    1435             :                             break;
    1436             :                                 sp = sp->next->to;
    1437             :                                 if ( sp==ss->first )
    1438             :                             break;
    1439             :                             }
    1440             :                         }
    1441             :                     }
    1442             :                     GDrawRequestExpose(dv->points_v,NULL,false);
    1443             :                     GDrawRequestExpose(dv->cv->v,NULL,false);
    1444             :             break;
    1445             :                 }
    1446             :                 ++k;
    1447             :             }
    1448             :         }
    1449             :       } /* Fall through */;
    1450             :       case et_mousedown:
    1451             :       case et_mousemove:
    1452             :         GGadgetEndPopup();
    1453             :       break;
    1454             :       case et_resize:
    1455             :         DVPointsFigureSB(dv);
    1456             :       break;
    1457             :     }
    1458             : return( true );
    1459             : }
    1460             : 
    1461             : static void dvpts_scroll(DebugView *dv,struct sbevent *sb) {
    1462             :     int newpos = dv->points_offtop;
    1463             :     GRect size;
    1464             :     int cnt;
    1465             : 
    1466             :     GDrawGetSize(dv->points_v,&size);
    1467             :     cnt = dvpts_cnt(dv);
    1468             :     switch( sb->type ) {
    1469             :       case et_sb_top:
    1470             :         newpos = 0;
    1471             :       break;
    1472             :       case et_sb_uppage:
    1473             :         newpos -= size.height/dv->ii.fh;
    1474             :       break;
    1475             :       case et_sb_up:
    1476             :         --newpos;
    1477             :       break;
    1478             :       case et_sb_down:
    1479             :         ++newpos;
    1480             :       break;
    1481             :       case et_sb_downpage:
    1482             :         newpos += size.height/dv->ii.fh;
    1483             :       break;
    1484             :       case et_sb_bottom:
    1485             :         newpos = cnt-size.height/dv->ii.fh;
    1486             :       break;
    1487             :       case et_sb_thumb:
    1488             :       case et_sb_thumbrelease:
    1489             :         newpos = sb->pos;
    1490             :       break;
    1491             :     }
    1492             :     if ( newpos>cnt-size.height/dv->ii.fh )
    1493             :         newpos = cnt-size.height/dv->ii.fh;
    1494             :     if ( newpos<0 ) newpos =0;
    1495             :     if ( newpos!=dv->points_offtop ) {
    1496             :         int diff = newpos-dv->points_offtop;
    1497             :         dv->points_offtop = newpos;
    1498             :         GScrollBarSetPos(dv->pts_vsb,dv->points_offtop);
    1499             :         GDrawScroll(dv->points_v,NULL,0,diff*dv->ii.fh);
    1500             :     }
    1501             : }
    1502             : 
    1503             : static int dvpoints_e_h(GWindow gw, GEvent *event) {
    1504             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1505             :     GRect r;
    1506             :     extern int _GScrollBar_Width;
    1507             :     int sbwidth;
    1508             : 
    1509             :     if ( dv==NULL )
    1510             : return( true );
    1511             : 
    1512             :     switch ( event->type ) {
    1513             :       case et_expose:
    1514             :         DVPointsExpose(gw,dv,event);
    1515             :       break;
    1516             :       case et_char:
    1517             : return( DVChar(dv,event));
    1518             :       break;
    1519             :       case et_controlevent:
    1520             :         switch ( event->u.control.subtype ) {
    1521             :           case et_radiochanged:
    1522             :             GDrawRequestExpose(dv->points_v,NULL,false);
    1523             :             DVPointsFigureSB(dv);
    1524             :           break;
    1525             :           case et_scrollbarchange:
    1526             :             dvpts_scroll(dv,&event->u.control.u.sb);
    1527             :           break;
    1528             :         }
    1529             :       break;
    1530             :       case et_resize:
    1531             :         GDrawGetSize(gw,&r);
    1532             :         sbwidth = GDrawPointsToPixels(gw,_GScrollBar_Width);
    1533             :         GDrawResize(dv->points_v,r.width-sbwidth,r.height-dv->pts_head);
    1534             :         GGadgetResize(dv->pts_vsb,sbwidth,r.height-dv->pts_head);
    1535             :         GGadgetMove(dv->pts_vsb,r.width-sbwidth,dv->pts_head);
    1536             :       break;
    1537             :       case et_close:
    1538             :         GDrawDestroyWindow(dv->points);
    1539             :         debug_wins &= ~dw_points;
    1540             :       break;
    1541             :       case et_destroy:
    1542             :         dv->points = NULL;
    1543             :         dv->points_v = NULL;
    1544             :       break;
    1545             :       case et_mouseup: case et_mousedown:
    1546             :       case et_mousemove:
    1547             :         GGadgetEndPopup();
    1548             :       break;
    1549             :     }
    1550             : return( true );
    1551             : }
    1552             : 
    1553             : static void DVCvt_SetScrollBar(DebugView *dv) {
    1554             :     GRect size;
    1555             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1556             :     int lh = exc==NULL ? 0 : exc->cvtSize;
    1557             : 
    1558             :     GDrawGetSize(dv->cvt,&size);
    1559             :     GScrollBarSetBounds(dv->cvtsb,0,lh,size.height/dv->ii.fh);
    1560             :     if ( dv->cvt_offtop + size.height/dv->ii.fh > lh ) {
    1561             :         int lpos = lh-size.height/dv->ii.fh;
    1562             :         if ( lpos<0 ) lpos = 0;
    1563             :         dv->cvt_offtop = lpos;
    1564             :     }
    1565             :     GScrollBarSetPos(dv->cvtsb,dv->cvt_offtop);
    1566             : }
    1567             : 
    1568             : 
    1569             : static void dvcvt_scroll(DebugView *dv,struct sbevent *sb) {
    1570             :     int newpos = dv->cvt_offtop;
    1571             :     GRect size;
    1572             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1573             :     extern int _GScrollBar_Width;
    1574             : 
    1575             :     GDrawGetSize(dv->cvt,&size);
    1576             :     switch( sb->type ) {
    1577             :       case et_sb_top:
    1578             :         newpos = 0;
    1579             :       break;
    1580             :       case et_sb_uppage:
    1581             :         newpos -= size.height/dv->ii.fh;
    1582             :       break;
    1583             :       case et_sb_up:
    1584             :         --newpos;
    1585             :       break;
    1586             :       case et_sb_down:
    1587             :         ++newpos;
    1588             :       break;
    1589             :       case et_sb_downpage:
    1590             :         newpos += size.height/dv->ii.fh;
    1591             :       break;
    1592             :       case et_sb_bottom:
    1593             :         newpos = exc->cvtSize-size.height/dv->ii.fh;
    1594             :       break;
    1595             :       case et_sb_thumb:
    1596             :       case et_sb_thumbrelease:
    1597             :         newpos = sb->pos;
    1598             :       break;
    1599             :     }
    1600             :     if ( newpos>exc->cvtSize-size.height/dv->ii.fh )
    1601             :         newpos = exc->cvtSize-size.height/dv->ii.fh;
    1602             :     if ( newpos<0 ) newpos =0;
    1603             :     if ( newpos!=dv->cvt_offtop ) {
    1604             :         int diff = newpos-dv->cvt_offtop;
    1605             :         dv->cvt_offtop = newpos;
    1606             :         GScrollBarSetPos(dv->cvtsb,dv->cvt_offtop);
    1607             :         size.x = size.y = 0;
    1608             :         size.width -= GDrawPointsToPixels(dv->gloss,_GScrollBar_Width);
    1609             :         GDrawScroll(dv->cvt,&size,0,diff*dv->ii.fh);
    1610             :     }
    1611             : }
    1612             : 
    1613             : static int dvcvt_e_h(GWindow gw, GEvent *event) {
    1614             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1615             :     GRect r,g;
    1616             : 
    1617             :     if ( dv==NULL )
    1618             : return( true );
    1619             : 
    1620             :     switch ( event->type ) {
    1621             :       case et_expose:
    1622             :         DVCvtExpose(gw,dv,event);
    1623             :       break;
    1624             :       case et_char:
    1625             : return( DVChar(dv,event));
    1626             :       break;
    1627             :       case et_controlevent:
    1628             :         switch ( event->u.control.subtype ) {
    1629             :           case et_scrollbarchange:
    1630             :             dvcvt_scroll(dv,&event->u.control.u.sb);
    1631             :           break;
    1632             :         }
    1633             :       break;
    1634             :       case et_resize:
    1635             :         GDrawGetSize(gw,&r);
    1636             :         GGadgetGetSize(dv->cvtsb,&g);
    1637             :         GGadgetMove(dv->cvtsb,r.width-g.width,0);
    1638             :         GGadgetResize(dv->cvtsb,g.width,r.height);
    1639             :         DVCvt_SetScrollBar(dv);
    1640             :         GDrawRequestExpose(dv->cvt,NULL,false);
    1641             :       break;
    1642             :       case et_close:
    1643             :         GDrawDestroyWindow(dv->cvt);
    1644             :         debug_wins &= ~dw_cvt;
    1645             :       break;
    1646             :       case et_destroy:
    1647             :         dv->cvt = NULL;
    1648             :       break;
    1649             :       case et_mouseup: {
    1650             :         int i;
    1651             :         int n;
    1652             :         uint8 *watches;
    1653             :         TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    1654             :         i = (event->u.mouse.y-3)/dv->ii.fh+dv->cvt_offtop;
    1655             :         if ( i>=0 && exc!=NULL ) {
    1656             :             watches = DebuggerGetWatchCvts(dv->dc,&n);
    1657             :             if ( watches==NULL ) {
    1658             :                 watches = calloc(n,sizeof(uint8));
    1659             :                 DebuggerSetWatchCvts(dv->dc,n,watches);
    1660             :             }
    1661             :             if ( i<n ) {
    1662             :                 watches[i] = !watches[i];
    1663             :                 GDrawRequestExpose(dv->cvt,NULL,false);
    1664             :             }
    1665             :         }
    1666             :       } /* Fall through */;
    1667             :       case et_mousedown:
    1668             :       case et_mousemove:
    1669             :         GGadgetEndPopup();
    1670             :       break;
    1671             :     }
    1672             : return( true );
    1673             : }
    1674             : 
    1675             : int CVXPos(DebugView *dv,int offset,int width) {
    1676             :     GRect r, screensize;
    1677             :     int x;
    1678             : 
    1679             :     GDrawGetSize(dv->cv->gw,&r);
    1680             :     GDrawGetSize(GDrawGetRoot(NULL),&screensize);
    1681             :     x = r.x+r.width+10 + offset;
    1682             :     if ( x+width >screensize.width )
    1683             :         x = screensize.width - width;
    1684             : return( x );
    1685             : }
    1686             : 
    1687             : static void DVCreateRaster(DebugView *dv) {
    1688             :     GWindowAttrs wattrs;
    1689             :     GRect pos;
    1690             : 
    1691             :     memset(&wattrs,0,sizeof(wattrs));
    1692             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1693             :     wattrs.event_masks = -1;
    1694             :     wattrs.cursor = ct_mypointer;
    1695             :     wattrs.utf8_window_title = _("Current Raster (TrueType)");
    1696             :     pos.width = 50; pos.height = 50;
    1697             :     pos.x = CVXPos(dv,143,pos.width); pos.y = 1;
    1698             :     dv->raster = GDrawCreateTopWindow(NULL,&pos,dvraster_e_h,dv,&wattrs);
    1699             :     GDrawSetVisible(dv->raster,true);
    1700             : }
    1701             : 
    1702             : static void DVCreateRegs(DebugView *dv) {
    1703             :     GWindowAttrs wattrs;
    1704             :     GRect pos;
    1705             :     GGadgetData gd;
    1706             :     extern int _GScrollBar_Width;
    1707             : 
    1708             :     memset(&wattrs,0,sizeof(wattrs));
    1709             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1710             :     wattrs.event_masks = -1;
    1711             :     wattrs.cursor = ct_mypointer;
    1712             :     wattrs.utf8_window_title = _("Registers (TrueType)");
    1713             :     pos.width = 143; pos.height = 269;
    1714             :     pos.x = CVXPos(dv,0,pos.width); pos.y = 1;
    1715             :     dv->regs = GDrawCreateTopWindow(NULL,&pos,dvreg_e_h,dv,&wattrs);
    1716             : 
    1717             :     memset(&gd,0,sizeof(gd));
    1718             : 
    1719             :     gd.pos.y = 0; gd.pos.height = pos.height;
    1720             :     gd.pos.width = GDrawPointsToPixels(dv->regs,_GScrollBar_Width);
    1721             :     gd.pos.x = pos.width-gd.pos.width;
    1722             :     gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    1723             :     dv->regsb = GScrollBarCreate(dv->regs,&gd,dv);
    1724             : 
    1725             :     GDrawSetVisible(dv->regs,true);
    1726             : }
    1727             : 
    1728             : static void DVCreateStack(DebugView *dv) {
    1729             :     GWindowAttrs wattrs;
    1730             :     GRect pos;
    1731             :     GGadgetData gd;
    1732             :     extern int _GScrollBar_Width;
    1733             : 
    1734             :     memset(&wattrs,0,sizeof(wattrs));
    1735             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1736             :     wattrs.event_masks = -1;
    1737             :     wattrs.cursor = ct_mypointer;
    1738             :     wattrs.utf8_window_title = _("Stack (TrueType)");
    1739             :     pos.width = 143; pos.height = 269;
    1740             :     pos.x = CVXPos(dv,0,pos.width); pos.y = 302;
    1741             :     dv->stack = GDrawCreateTopWindow(NULL,&pos,dvstack_e_h,dv,&wattrs);
    1742             : 
    1743             :     memset(&gd,0,sizeof(gd));
    1744             : 
    1745             :     gd.pos.y = 0; gd.pos.height = pos.height;
    1746             :     gd.pos.width = GDrawPointsToPixels(dv->stack,_GScrollBar_Width);
    1747             :     gd.pos.x = pos.width-gd.pos.width;
    1748             :     gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    1749             :     dv->stacksb = GScrollBarCreate(dv->stack,&gd,dv);
    1750             : 
    1751             :     GDrawSetVisible(dv->stack,true);
    1752             : }
    1753             : 
    1754             : static void DVCreateStore(DebugView *dv) {
    1755             :     GWindowAttrs wattrs;
    1756             :     GRect pos;
    1757             :     GGadgetData gd;
    1758             :     extern int _GScrollBar_Width;
    1759             : 
    1760             :     memset(&wattrs,0,sizeof(wattrs));
    1761             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1762             :     wattrs.event_masks = -1;
    1763             :     wattrs.cursor = ct_mypointer;
    1764             :     wattrs.utf8_window_title = _("Storage (TrueType)");
    1765             :     pos.width = 183; pos.height = 100;
    1766             :     pos.x = CVXPos(dv,0,pos.width); pos.y = 602;
    1767             :     dv->storage = GDrawCreateTopWindow(NULL,&pos,dvstore_e_h,dv,&wattrs);
    1768             : 
    1769             :     memset(&gd,0,sizeof(gd));
    1770             : 
    1771             :     gd.pos.y = 0; gd.pos.height = pos.height;
    1772             :     gd.pos.width = GDrawPointsToPixels(dv->storage,_GScrollBar_Width);
    1773             :     gd.pos.x = pos.width-gd.pos.width;
    1774             :     gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    1775             :     dv->storagesb = GScrollBarCreate(dv->storage,&gd,dv);
    1776             : 
    1777             :     GDrawSetVisible(dv->storage,true);
    1778             : }
    1779             : 
    1780             : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
    1781             : static int DV_Raw(GGadget *g, GEvent *e) {
    1782             : 
    1783             :     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
    1784             :         GWindow ew = GGadgetGetWindow(g);
    1785             :         int on = GGadgetIsChecked(g);
    1786             :         GGadget *trans = GWidgetGetControl(ew,CID_Transform);
    1787             :         GGadgetSetEnabled(trans,!on);
    1788             :         GGadgetSetChecked(trans, on? false : show_transformed );
    1789             :     }
    1790             : return( true );
    1791             : }
    1792             : #endif
    1793             : 
    1794             : static void DVCreatePoints(DebugView *dv) {
    1795             :     GWindowAttrs wattrs;
    1796             :     GRect pos;
    1797             :     /*extern int _GScrollBar_Width;*/
    1798             :     GGadgetCreateData gcd[10];
    1799             :     GTextInfo label[9];
    1800             :     extern int _GScrollBar_Width;
    1801             :     int k;
    1802             : 
    1803             :     memset(&wattrs,0,sizeof(wattrs));
    1804             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1805             :     wattrs.event_masks = -1;
    1806             :     wattrs.cursor = ct_mypointer;
    1807             :     wattrs.utf8_window_title = _("Points (TrueType)");
    1808             :     pos.width = GGadgetScale(GDrawPointsToPixels(NULL,129+_GScrollBar_Width)+19);
    1809             :     pos.height = 269;
    1810             :     pos.x = CVXPos(dv,0,pos.width); pos.y = 732;
    1811             :     dv->points = GDrawCreateTopWindow(NULL,&pos,dvpoints_e_h,dv,&wattrs);
    1812             : 
    1813             :     dv->pts_head = GDrawPointsToPixels(NULL,GGadgetScale(5+4*16+3));
    1814             : 
    1815             :     memset(&label,0,sizeof(label));
    1816             :     memset(&gcd,0,sizeof(gcd));
    1817             : 
    1818             :     label[0].text = (unichar_t *) _("Twilight");
    1819             :     label[0].text_is_1byte = true;
    1820             :     gcd[0].gd.label = &label[0];
    1821             :     gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 3;
    1822             :     gcd[0].gd.flags = gg_visible | gg_enabled | (show_twilight ? gg_cb_on : 0 );
    1823             :     gcd[0].gd.cid = CID_Twilight;
    1824             :     gcd[0].creator = GRadioCreate;
    1825             : 
    1826             :     label[1].text = (unichar_t *) _("Normal");
    1827             :     label[1].text_is_1byte = true;
    1828             :     gcd[1].gd.label = &label[1];
    1829             :     gcd[1].gd.pos.x = 60; gcd[1].gd.pos.y = gcd[0].gd.pos.y;
    1830             :     gcd[1].gd.flags = gg_visible | gg_enabled | (!show_twilight ? gg_cb_on : 0 );
    1831             :     gcd[1].gd.cid = CID_Normal;
    1832             :     gcd[1].creator = GRadioCreate;
    1833             : 
    1834             :     label[2].text = (unichar_t *) _("Current");
    1835             :     label[2].text_is_1byte = true;
    1836             :     gcd[2].gd.label = &label[2];
    1837             :     gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[0].gd.pos.y+16;
    1838             :     gcd[2].gd.flags = gg_visible | gg_enabled | gg_rad_startnew | (show_current ? gg_cb_on : 0 );
    1839             :     gcd[2].gd.cid = CID_Current;
    1840             :     gcd[2].creator = GRadioCreate;
    1841             : 
    1842             :     label[3].text = (unichar_t *) S_("Points|Original");
    1843             :     label[3].text_is_1byte = true;
    1844             :     gcd[3].gd.label = &label[3];
    1845             :     gcd[3].gd.pos.x = gcd[1].gd.pos.x; gcd[3].gd.pos.y = gcd[2].gd.pos.y;
    1846             :     gcd[3].gd.flags = gg_visible | gg_enabled | (!show_current ? gg_cb_on : 0 );
    1847             :     gcd[3].gd.cid = CID_Original;
    1848             :     gcd[3].creator = GRadioCreate;
    1849             : 
    1850             :     label[4].text = (unichar_t *) _("Grid");
    1851             :     label[4].text_is_1byte = true;
    1852             :     gcd[4].gd.label = &label[4];
    1853             :     gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[2].gd.pos.y+16;
    1854             :     gcd[4].gd.flags = gg_visible | gg_enabled | gg_rad_startnew | (show_grid ? gg_cb_on : 0 );
    1855             :     gcd[4].gd.cid = CID_Grid;
    1856             :     gcd[4].creator = GRadioCreate;
    1857             : 
    1858             :     k=5;
    1859             : 
    1860             : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
    1861             :     label[k].text = (unichar_t *) _("Raw");
    1862             :     label[k].text_is_1byte = true;
    1863             :     gcd[k].gd.label = &label[k];
    1864             :     gcd[k].gd.pos.x = 43; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
    1865             :     gcd[k].gd.flags = gg_visible | gg_enabled | (show_raw ? gg_cb_on : 0 );
    1866             :     gcd[k].gd.cid = CID_Raw;
    1867             :     gcd[k].gd.handle_controlevent = DV_Raw;
    1868             :     gcd[k++].creator = GRadioCreate;
    1869             : #endif
    1870             : 
    1871             :     label[k].text = (unichar_t *) _("Em Units");
    1872             :     label[k].text_is_1byte = true;
    1873             :     gcd[k].gd.label = &label[k];
    1874             : #if defined(FONTFORGE_CONFIG_SHOW_RAW_POINTS)
    1875             :     gcd[k].gd.pos.x = 82; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
    1876             : #else
    1877             :     gcd[k].gd.pos.x = gcd[1].gd.pos.x; gcd[k].gd.pos.y = gcd[4].gd.pos.y;
    1878             : #endif
    1879             :     gcd[k].gd.flags = gg_visible | gg_enabled | (!show_current ? gg_cb_on : 0 );
    1880             :     gcd[k].gd.cid = CID_EmUnit;
    1881             :     gcd[k++].creator = GRadioCreate;
    1882             : 
    1883             :     label[k].text = (unichar_t *) _("Transformed");
    1884             :     label[k].text_is_1byte = true;
    1885             :     gcd[k].gd.label = &label[k];
    1886             :     gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[4].gd.pos.y+16;
    1887             :     gcd[k].gd.flags = gg_visible | (show_transformed ? gg_cb_on : 0 );
    1888             :     if ( dv->cv->b.layerheads[dv->cv->b.drawmode]->splines==NULL &&
    1889             :             dv->cv->b.layerheads[dv->cv->b.drawmode]->refs!=NULL )
    1890             :         gcd[k].gd.flags |= gg_enabled;
    1891             :     gcd[k].gd.cid = CID_Transform;
    1892             :     gcd[k++].creator = GCheckBoxCreate;
    1893             : 
    1894             :     gcd[k].gd.pos.width = GDrawPointsToPixels(NULL,_GScrollBar_Width);
    1895             :     gcd[k].gd.pos.height = pos.height-dv->pts_head;
    1896             :     gcd[k].gd.pos.x = pos.width-gcd[k].gd.pos.width; gcd[k].gd.pos.y = dv->pts_head;
    1897             :     gcd[k].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels | gg_sb_vert;
    1898             :     gcd[k].creator = GScrollBarCreate;
    1899             : 
    1900             :     GGadgetsCreate(dv->points,gcd);
    1901             :     dv->pts_vsb = gcd[k].ret;
    1902             : 
    1903             :     pos.x = 0;
    1904             :     pos.y = dv->pts_head;
    1905             :     pos.height -= dv->pts_head;
    1906             :     pos.width -= gcd[6].gd.pos.width;
    1907             :     dv->points_v = GWidgetCreateSubWindow(dv->points,&pos,dvpointsv_e_h,dv,&wattrs);
    1908             :     GDrawSetVisible(dv->points_v,true);
    1909             :     GDrawSetVisible(dv->points,true);
    1910             : }
    1911             : 
    1912             : static void DVCreateCvt(DebugView *dv) {
    1913             :     GWindowAttrs wattrs;
    1914             :     GRect pos;
    1915             :     GGadgetData gd;
    1916             :     extern int _GScrollBar_Width;
    1917             : 
    1918             :     memset(&wattrs,0,sizeof(wattrs));
    1919             :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle;
    1920             :     wattrs.event_masks = -1;
    1921             :     wattrs.cursor = ct_mypointer;
    1922             :     wattrs.utf8_window_title = _("Cvt");
    1923             :     pos.x = 664; pos.y = 732;
    1924             :     pos.width = GGadgetScale(GDrawPointsToPixels(NULL,125))+20; pos.height = 169;
    1925             :     pos.x = CVXPos(dv,183,pos.width); pos.y = 602;
    1926             :     dv->cvt = GDrawCreateTopWindow(NULL,&pos,dvcvt_e_h,dv,&wattrs);
    1927             : 
    1928             :     memset(&gd,0,sizeof(gd));
    1929             : 
    1930             :     gd.pos.y = 0; gd.pos.height = pos.height;
    1931             :     gd.pos.width = GDrawPointsToPixels(dv->cvt,_GScrollBar_Width);
    1932             :     gd.pos.x = pos.width-gd.pos.width;
    1933             :     gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    1934             :     dv->cvtsb = GScrollBarCreate(dv->cvt,&gd,dv);
    1935             : 
    1936             :     DVCvt_SetScrollBar(dv);
    1937             : 
    1938             :     GDrawSetVisible(dv->cvt,true);
    1939             : }
    1940             : 
    1941             : static int dv_e_h(GWindow gw, GEvent *event) {
    1942             :     DebugView *dv = (DebugView *) GDrawGetUserData(gw);
    1943             : 
    1944             :     switch ( event->type ) {
    1945             :       case et_expose:
    1946             :         DVExpose(gw,dv,event);
    1947             :       break;
    1948             :       case et_char:
    1949             : return( DVChar(dv,event));
    1950             :       break;
    1951             :       case et_charup:
    1952             :       break;
    1953             :       case et_controlevent:
    1954             :         switch ( event->u.control.subtype ) {
    1955             :           case et_scrollbarchange:
    1956             :             instr_scroll(&dv->ii,&event->u.control.u.sb);
    1957             :           break;
    1958             :         }
    1959             :       break;
    1960             :       case et_resize:
    1961             :         if ( event->u.resize.sized ) {
    1962             :             /*DVResize(dv,event)*/;
    1963             :         }
    1964             :       break;
    1965             :       case et_destroy:
    1966             :         dv->dv = NULL;
    1967             :         if ( dv->cv!=NULL )
    1968             :             CVDebugFree(dv);
    1969             :         free(dv->id.bts);
    1970             :         free(dv);
    1971             :       break;
    1972             :       case et_mouseup: case et_mousedown:
    1973             :         GGadgetEndPopup();
    1974             :       break;
    1975             :       case et_mousemove:
    1976             :       break;
    1977             :     }
    1978             : return( true );
    1979             : }
    1980             : 
    1981             : void CVDebugFree(DebugView *dv) {
    1982             :     if ( dv!=NULL ) {
    1983             :         CharView *cv = dv->cv;
    1984             :         SplineSet *ss;
    1985             :         SplinePoint *sp;
    1986             :         int dying = dv->dv==NULL;
    1987             : 
    1988             :         cv->show_ft_results = false;
    1989             :         DebuggerTerminate(dv->dc);
    1990             :         cv->dv = NULL;
    1991             :         if ( dv->points!=NULL ) {
    1992             :             GDrawSetUserData(dv->points,NULL);
    1993             :             GDrawSetUserData(dv->points_v,NULL);
    1994             :             GDrawDestroyWindow(dv->points);
    1995             :         }
    1996             :         if ( dv->raster!=NULL ) {
    1997             :             GDrawSetUserData(dv->raster,NULL);
    1998             :             GDrawDestroyWindow(dv->raster);
    1999             :         }
    2000             :         if ( dv->cvt!=NULL ) {
    2001             :             GDrawSetUserData(dv->cvt,NULL);
    2002             :             GDrawDestroyWindow(dv->cvt);
    2003             :         }
    2004             :         if ( dv->regs!=NULL ) {
    2005             :             GDrawSetUserData(dv->regs,NULL);
    2006             :             GDrawDestroyWindow(dv->regs);
    2007             :         }
    2008             :         if ( dv->stack!=NULL ) {
    2009             :             GDrawSetUserData(dv->stack,NULL);
    2010             :             GDrawDestroyWindow(dv->stack);
    2011             :         }
    2012             :         if ( dv->storage!=NULL ) {
    2013             :             GDrawSetUserData(dv->storage,NULL);
    2014             :             GDrawDestroyWindow(dv->storage);
    2015             :         }
    2016             :         if ( dv->gloss!=NULL ) {
    2017             :             GDrawSetUserData(dv->gloss,NULL);
    2018             :             GDrawDestroyWindow(dv->gloss);
    2019             :         }
    2020             :         if ( dv->dv!=NULL ) {
    2021             :             GDrawDestroyWindow(dv->dv);
    2022             :             CVResize(cv);
    2023             :             GDrawRequestExpose(cv->v,NULL,false);
    2024             :         }
    2025             : 
    2026             :         for ( ss = cv->b.layerheads[cv->b.drawmode]->splines; ss!=NULL; ss=ss->next ) {
    2027             :             for ( sp=ss->first; ; ) {
    2028             :                 sp->watched = false;
    2029             :                 if ( sp->next==NULL )
    2030             :             break;
    2031             :                 sp = sp->next->to;
    2032             :                 if ( sp==ss->first )
    2033             :             break;
    2034             :             }
    2035             :         }
    2036             : 
    2037             :         SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
    2038             :         FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
    2039             :         FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    2040             : 
    2041             :         if ( !dying ) {
    2042             :             GDrawRequestExpose(cv->v,NULL,false);
    2043             : 
    2044             :             if ( cv->coderange!=cr_none ) {
    2045             :                 cv->coderange = cr_none;
    2046             :                 CVInfoDraw(cv,cv->gw);
    2047             :             }
    2048             :         }
    2049             :     DebugColInit();
    2050             : 
    2051             :         dv->cv = NULL;
    2052             :     }
    2053             : }
    2054             : 
    2055             : void CVDebugReInit(CharView *cv,int restart_debug,int dbg_fpgm) {
    2056             :     DebugView *dv = cv->dv;
    2057             :     GWindowAttrs wattrs;
    2058             :     GRect pos, size;
    2059             :     TT_ExecContext exc;
    2060             :     FontRequest rq;
    2061             :     int as,ds,ld;
    2062             :     GGadgetCreateData gcd[9];
    2063             :     GTextInfo label[9];
    2064             :     extern int _GScrollBar_Width;
    2065             :     double scalex, scaley;
    2066             :     int i;
    2067             :     static GFont *monofont = NULL;
    2068             : 
    2069             :     scalex = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/(rint(cv->ft_pointsizex*cv->ft_dpi/72.0)) / (1<<6);
    2070             :     scaley = (cv->b.sc->parent->ascent+cv->b.sc->parent->descent)/(rint(cv->ft_pointsizey*cv->ft_dpi/72.0)) / (1<<6);
    2071             :     if ( restart_debug ) {
    2072             :         if ( cv->b.sc->instructions_out_of_date && cv->b.sc->ttf_instrs_len!=0 )
    2073             :             ff_post_notice(_("Instructions out of date"),
    2074             :                 _("The points have been changed. This may mean that the truetype instructions now refer to the wrong points and they may cause unexpected results."));
    2075             :     }
    2076             :     if ( !restart_debug ) {
    2077             :         CVDebugFree(dv);
    2078             :     } else if ( dv==NULL ) {
    2079             :         int sbsize = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
    2080             :         cv->show_ft_results = false;
    2081             :         cv->dv = dv = calloc(1,sizeof(DebugView));
    2082             :         dv->dwidth = 260;
    2083             :         dv->scalex = scalex;
    2084             :         dv->scaley = scaley;
    2085             :         dv->cv = cv;
    2086             :         dv->layer = CVLayer((CharViewBase *) cv);
    2087             :         dv->dc = DebuggerCreate(cv->b.sc,dv->layer,cv->ft_pointsizey,cv->ft_pointsizex,cv->ft_dpi,dbg_fpgm,cv->ft_depth==1);
    2088             :         FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    2089             :         if ( dv->dc==NULL ) {
    2090             :             free(dv);
    2091             :             cv->dv = NULL;
    2092             : return;
    2093             :         }
    2094             :         memset(&wattrs,0,sizeof(wattrs));
    2095             :         wattrs.mask = wam_events|wam_cursor|wam_bordwidth|wam_bordcol;
    2096             :         wattrs.event_masks = -1;
    2097             :         wattrs.border_width = 0;
    2098             :         wattrs.border_color = 0x000000;
    2099             :         wattrs.cursor = ct_mypointer;
    2100             :         pos.x = 0; pos.y = 0;
    2101             :         pos.width = dv->dwidth; pos.height = cv->height;
    2102             :         dv->dv = GWidgetCreateSubWindow(cv->gw,&pos,dv_e_h,dv,&wattrs);
    2103             :         GDrawSetVisible(dv->dv,true);
    2104             : 
    2105             :         dv->toph = 36;
    2106             :         memset(&gcd,0,sizeof(gcd));
    2107             :         memset(&label,0,sizeof(label));
    2108             :         gcd[0].gd.pos.y = dv->toph; gcd[0].gd.pos.height = pos.height-dv->toph;
    2109             :         gcd[0].gd.pos.width = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
    2110             :         gcd[0].gd.pos.x = pos.width-gcd[0].gd.pos.width;
    2111             :         gcd[0].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    2112             :         gcd[0].creator = GScrollBarCreate;
    2113             : 
    2114             :         gcd[1].gd.pos.y = 2; gcd[1].gd.pos.x = 2;
    2115             :         gcd[1].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2116             :         gcd[1].gd.cid = dgt_step;
    2117             :         gcd[1].gd.label = &label[1];
    2118             :         label[1].image = &GIcon_stepinto;
    2119             :         gcd[1].gd.handle_controlevent = DV_Run;
    2120             :         gcd[1].gd.popup_msg = (unichar_t *) _("Step into");
    2121             :         gcd[1].creator = GButtonCreate;
    2122             : 
    2123             :         gcd[2].gd.pos.y = 2; gcd[2].gd.pos.x = 38;
    2124             :         gcd[2].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2125             :         gcd[2].gd.cid = dgt_next;
    2126             :         gcd[2].gd.label = &label[2];
    2127             :         label[2].image = &GIcon_stepover;
    2128             :         gcd[2].gd.handle_controlevent = DV_Run;
    2129             :         gcd[2].gd.popup_msg = (unichar_t *) _("Step over (Next)");
    2130             :         gcd[2].creator = GButtonCreate;
    2131             : 
    2132             :         gcd[3].gd.pos.y = 2; gcd[3].gd.pos.x = 74;
    2133             :         gcd[3].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2134             :         gcd[3].gd.cid = dgt_stepout;
    2135             :         gcd[3].gd.label = &label[3];
    2136             :         label[3].image = &GIcon_stepout;
    2137             :         gcd[3].gd.handle_controlevent = DV_Run;
    2138             :         gcd[3].gd.popup_msg = (unichar_t *) _("Step out of current function");
    2139             :         gcd[3].creator = GButtonCreate;
    2140             : 
    2141             :         gcd[4].gd.pos.y = 2; gcd[4].gd.pos.x = 110;
    2142             :         gcd[4].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2143             :         gcd[4].gd.cid = dgt_continue;
    2144             :         gcd[4].gd.label = &label[4];
    2145             :         label[4].image = &GIcon_continue;
    2146             :         gcd[4].gd.handle_controlevent = DV_Run;
    2147             :         gcd[4].gd.popup_msg = (unichar_t *) _("Continue");
    2148             :         gcd[4].creator = GButtonCreate;
    2149             : 
    2150             :         gcd[5].gd.pos.y = 2; gcd[5].gd.pos.x = 146;
    2151             :         gcd[5].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2152             :         /*gcd[5].gd.cid = dgt_continue;*/
    2153             :         gcd[5].gd.label = &label[5];
    2154             :         label[5].image = &GIcon_watchpnt;
    2155             :         gcd[5].gd.handle_controlevent = DV_WatchPnt;
    2156             :         gcd[5].gd.popup_msg = (unichar_t *) _("Watch all selected points\n(stop when a point moves)");
    2157             :         gcd[5].creator = GButtonCreate;
    2158             : 
    2159             :         gcd[6].gd.pos.y = 2; gcd[6].gd.pos.x = 182;
    2160             :         gcd[6].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2161             :         /*gcd[6].gd.cid = dgt_continue;*/
    2162             :         gcd[6].gd.label = &label[6];
    2163             :         label[6].image = &GIcon_menudelta;
    2164             :         gcd[6].gd.handle_controlevent = DV_WindowMenu;
    2165             :         gcd[6].gd.popup_msg = (unichar_t *) _("Window");
    2166             :         gcd[6].creator = GButtonCreate;
    2167             : 
    2168             :         gcd[7].gd.pos.y = 2; gcd[7].gd.pos.x = 218;
    2169             :         gcd[7].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    2170             :         /*gcd[7].gd.cid = dgt_continue;*/
    2171             :         gcd[7].gd.label = &label[7];
    2172             :         label[7].image = &GIcon_exit;
    2173             :         gcd[7].gd.handle_controlevent = DV_Exit;
    2174             :         gcd[7].gd.popup_msg = (unichar_t *) _("Exit Debugger");
    2175             :         gcd[7].creator = GButtonCreate;
    2176             : 
    2177             :         GGadgetsCreate(dv->dv,gcd);
    2178             :         GGadgetGetSize(gcd[6].ret,&size);
    2179             :         {
    2180             :             int diff = size.y+size.height+2 - dv->toph;
    2181             :             dv->toph = size.y+size.height+2;
    2182             :             GGadgetGetSize(gcd[0].ret,&size);
    2183             :             GGadgetMove(gcd[0].ret,size.x,size.y+diff);
    2184             :             GGadgetResize(gcd[0].ret,size.width,size.height-diff);
    2185             :         }
    2186             : 
    2187             :         GGadgetGetSize(gcd[0].ret,&size);
    2188             :         dv->ii.vsb = gcd[0].ret;
    2189             :         dv->ii.sbw = size.width;
    2190             :         dv->ii.vheight = size.height; dv->ii.vwidth = pos.width-sbsize;
    2191             :         dv->ii.showaddr = true;
    2192             :         dv->ii.userdata = dv;
    2193             :         dv->ii.selection_callback = DVToggleBp;
    2194             :         dv->ii.bpcheck = DVBpCheck;
    2195             :         dv->ii.handle_char = DV_HandleChar;
    2196             : 
    2197             :         pos.y = dv->toph;
    2198             :         pos.width -= sbsize; pos.height -= pos.y;
    2199             :         dv->ii.v = GWidgetCreateSubWindow(dv->dv,&pos,ii_v_e_h,&dv->ii,&wattrs);
    2200             :         dv->ii.instrdata = &dv->id;
    2201             : 
    2202             :         if ( monofont==NULL ) {
    2203             :             memset(&rq,0,sizeof(rq));
    2204             :             rq.utf8_family_name = MONO_UI_FAMILIES;
    2205             :             rq.point_size = -12;
    2206             :             rq.weight = 400;
    2207             :             monofont = GDrawInstanciateFont(cv->gw,&rq);
    2208             :             monofont = GResourceFindFont("DebugView.Font",monofont);
    2209             :         }
    2210             :         dv->ii.gfont = monofont;
    2211             :         GDrawSetFont(dv->ii.v,dv->ii.gfont);
    2212             :         GDrawWindowFontMetrics(dv->ii.v,dv->ii.gfont,&as,&ds,&ld);
    2213             :         dv->ii.as = as+1;
    2214             :         dv->ii.fh = dv->ii.as+ds;
    2215             :         dv->ii.isel_pos = -1;
    2216             : 
    2217             :         if (( exc = DebuggerGetEContext(dv->dc))!=NULL )
    2218             :             DVFigureNewState(dv,exc);
    2219             :         else
    2220             :             DVDefaultRaster(dv);
    2221             :         GDrawSetVisible(dv->ii.v,true);
    2222             :         GDrawSetVisible(dv->dv,true);
    2223             :         CVResize(cv);
    2224             :         GDrawRequestExpose(cv->v,NULL,false);
    2225             :         for ( i=0; wcreat[i].create!=NULL; ++i ) {
    2226             :             if ( debug_wins & wcreat[i].flag )
    2227             :                 (wcreat[i].create)(dv);
    2228             :         }
    2229             :     } else {
    2230             :         dv->scalex = scalex;
    2231             :         dv->scaley = scaley;
    2232             :         DebuggerReset(dv->dc,cv->ft_pointsizey,cv->ft_pointsizex,cv->ft_dpi,dbg_fpgm,cv->ft_depth==1);
    2233             :         FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    2234             :         if (( exc = DebuggerGetEContext(dv->dc))!=NULL )
    2235             :             DVFigureNewState(dv,exc);
    2236             :         else
    2237             :             DVDefaultRaster(dv);
    2238             :     }
    2239             : }
    2240             : 
    2241             : void CVDebugPointPopup(CharView *cv) {
    2242             :     DebugView *dv = cv->dv;
    2243             :     TT_ExecContext exc = DebuggerGetEContext(dv->dc);
    2244             :     TT_GlyphZoneRec *r;
    2245             :     FT_Vector *pts;
    2246             :     int i,l,n;
    2247             :     int32 x,y,fudge;
    2248             :     char cspace[210];
    2249             :     extern float snapdistance;
    2250             : 
    2251             :     if ( exc==NULL )
    2252             :   goto no_point;
    2253             :     r = &exc->pts;
    2254             :     n = r->n_points;
    2255             :     pts = r->cur;
    2256             : 
    2257             :     x = rint(cv->info.x/dv->scalex);
    2258             :     y = rint(cv->info.y/dv->scaley);
    2259             : 
    2260             :     fudge = rint(snapdistance/cv->scale/dv->scaley);
    2261             :     for ( i=n-1; i>=0; --i ) {
    2262             :         if ( x>=pts[i].x-fudge && x<=pts[i].x+fudge &&
    2263             :                 y>=pts[i].y-fudge && y<=pts[i].y+fudge )
    2264             :     break;
    2265             :     }
    2266             :     if ( i!=-1 ) {
    2267             :         snprintf(cspace,sizeof(cspace),
    2268             :                 "Point %d %s-curve\nCur (em): %7.2f,%7.2f\nCur (px): %7.2f,%7.2f\nOrg (em): %7.2f,%7.2f",
    2269             :                 i, r->tags[i]&FT_Curve_Tag_On?"On":"Off",
    2270             :                 pts[i].x*dv->scalex, pts[i].y*dv->scaley,
    2271             :                 pts[i].x/64.0, pts[i].y/64.0,
    2272             :                 r->org[i].x*dv->scalex, r->org[i].y*dv->scaley );
    2273             :     } else {
    2274             :         int xx, yy;
    2275             :         for ( i=n-1; i>=0; --i ) {
    2276             :             l = i==0?n-1:i-1;
    2277             :             if ( !(r->tags[i]&FT_Curve_Tag_On) && !(r->tags[l]&FT_Curve_Tag_On)) {
    2278             :                 xx = (pts[i].x+pts[l].x)/2; yy = (pts[i].y+pts[l].y)/2;
    2279             :                 if ( x>=xx-fudge && x<=xx+fudge &&
    2280             :                         y>=yy-fudge && y<=yy+fudge )
    2281             :         break;
    2282             :             }
    2283             :         }
    2284             :         if ( i==-1 )
    2285             :   goto no_point;
    2286             :         snprintf(cspace,sizeof(cspace),
    2287             :                 "Interpolated between %d %d\nCur (em): %7.2f,%7.2f\nCur (px): %7.2f,%7.2f\nOrg (em): %7.2f,%7.2f",
    2288             :                 l,i,
    2289             :                 xx*dv->scalex, yy*dv->scaley,
    2290             :                 xx/64.0, yy/64.0,
    2291             :                 (r->org[i].x+r->org[l].x)*dv->scalex/2.0, (r->org[i].y+r->org[l].y)*dv->scaley/2.0 );
    2292             :     }
    2293             :   goto showit;
    2294             : 
    2295             :   no_point:
    2296             :     snprintf(cspace,sizeof(cspace),
    2297             :                 "%.2f, %.2f", (double) (cv->info.x/dv->scalex/64.0), (double) (cv->info.y/dv->scaley/64.0) );
    2298             : 
    2299             :   showit:
    2300             :     if ( cv->raster!=NULL ) {
    2301             :         int x = cv->info.x/dv->scalex/64.0 - cv->raster->lb;
    2302             :         int y = cv->raster->as-cv->info.y/dv->scaley/64.0;
    2303             :         int val;
    2304             :         if ( cv->raster->num_greys>2 ) {
    2305             :             if ( x<0 || x>=cv->raster->cols || y<0 || y>=cv->raster->rows )
    2306             :                 val = 0;        /* Not in raster */
    2307             :             else
    2308             :                 val = cv->raster->bitmap[y*cv->raster->bytes_per_row+x];
    2309             :             snprintf(cspace+strlen(cspace),sizeof(cspace)-strlen(cspace),
    2310             :                     "\nRaster grey=0x%02x (%.2f)", val, val/256.0 );
    2311             :         } else {
    2312             :             if ( x<0 || x>=cv->raster->cols || y<0 || y>=cv->raster->rows )
    2313             :                 val = 0;
    2314             :             else
    2315             :                 val = cv->raster->bitmap[y*cv->raster->bytes_per_row+(x>>3)] & (1<<(7-(x&7)));
    2316             :             if ( val )
    2317             :                 strcat(cspace, "\nRaster On");
    2318             :             else
    2319             :                 strcat(cspace, "\nRaster Off");
    2320             :         }
    2321             :     }
    2322             :     if ( cv->oldraster!=NULL ) {
    2323             :         int x = cv->info.x/dv->scalex/64.0 - cv->oldraster->lb;
    2324             :         int y = cv->oldraster->as-cv->info.y/dv->scaley/64.0;
    2325             :         int val;
    2326             :         if ( cv->oldraster->num_greys>2 ) {
    2327             :             if ( x<0 || x>=cv->oldraster->cols || y<0 || y>=cv->oldraster->rows )
    2328             :                 val = 0;
    2329             :             else
    2330             :                 val = cv->oldraster->bitmap[y*cv->oldraster->bytes_per_row+x];
    2331             :             snprintf(cspace+strlen(cspace),sizeof(cspace)-strlen(cspace),
    2332             :                 "\nOld Raster grey=0x%02x (%.2f)", val, val/256.0 );
    2333             :         } else {
    2334             :             if ( x<0 || x>=cv->oldraster->cols || y<0 || y>=cv->oldraster->rows )
    2335             :                 val = 0;
    2336             :             else
    2337             :                 val = cv->oldraster->bitmap[y*cv->oldraster->bytes_per_row+(x>>3)] & (1<<(7-(x&7)));
    2338             :             if ( val )
    2339             :                 strcat(cspace, "\nOld Raster On");
    2340             :             else
    2341             :                 strcat(cspace, "\nOld Raster Off");
    2342             :         }
    2343             :     }
    2344             :     GGadgetPreparePopup8(cv->v,cspace);
    2345             : }
    2346             : #endif

Generated by: LCOV version 1.10