LCOV - code coverage report
Current view: top level - fontforgeexe - cvpalettes.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 6 2944 0.2 %
Date: 2017-08-04 Functions: 2 110 1.8 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "cvundoes.h"
      28             : #include "fontforgeui.h"
      29             : #include "spiro.h"
      30             : #include "splinefill.h"
      31             : #include "splineorder2.h"
      32             : #include "splineutil.h"
      33             : #include "splineutil2.h"
      34             : #include "collabclientui.h"
      35             : 
      36             : int palettes_docked=1;
      37             : int rectelipse=0, polystar=0, regular_star=1;
      38             : int center_out[2] = { false, true };
      39             : float rr_radius=0;
      40             : int ps_pointcnt=6;
      41             : float star_percent=1.7320508;   /* Regular 6 pointed star */
      42             : extern int interpCPsOnMotion;
      43             : 
      44             : #include <gkeysym.h>
      45             : #include <math.h>
      46             : #include "splinefont.h"
      47             : #include <ustring.h>
      48             : #include <utype.h>
      49             : #include <gresource.h>
      50             : #include "charview_private.h"
      51             : #include "gdraw/hotkeys.h"
      52             : 
      53             : static void CVLCheckLayerCount(CharView *cv, int resize);
      54             : 
      55             : extern void CVDebugFree(DebugView *dv);
      56             : 
      57             : extern GBox _ggadget_Default_Box;
      58             : #define ACTIVE_BORDER   (_ggadget_Default_Box.active_border)
      59             : #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
      60             : 
      61             : extern GDevEventMask input_em[];
      62             : extern const int input_em_cnt;
      63             : 
      64             : int cvvisible[2] = { 1, 1}, bvvisible[3]= { 1,1,1 };
      65             : static GWindow cvlayers, cvtools, bvlayers, bvtools, bvshades;
      66             : static GWindow cvlayers2=NULL;
      67             : 
      68             : #define LSHOW_CUBIC   1
      69             : #define LSHOW_FG      2
      70             : #define LSHOW_PREVIEW 4
      71             : static int layerscols = LSHOW_CUBIC|LSHOW_FG|LSHOW_PREVIEW; /* which columns to show in layers1 palette */
      72             : static int layer_height = 0;        /* height of each layer row in layers1 palette */
      73             : static int layer_header_height = 0; /* height of initial stuff in layers1 palette  */
      74             : static int layer_footer_height = 0; /* height of +/- buttons at bottom of layers1 palette */
      75             : static int layers_max = 2; /* Maximum number of layers for which widgets have been allocated in layers1 palette */
      76             : struct l2 {
      77             :     int active;           /* index of the active layer */
      78             :     int offtop;           /* first layer to show at the top line in layers palette */
      79             :     int visible_layers;   /* number of layers apart from the guides layer to show before using a scrollbar      */
      80             :     int current_layers;   /* number of layers for the current character, and the number used in l2.layers       */
      81             :     int max_layers;       /* maximum number of layers for which layer controls and previews have been allocated */
      82             :     BDFChar **layers;     /* layer thumbnail previews              */
      83             :     int sb_start;         /* x pixel position of the scrollbar     */
      84             :     int column_width;     /* width of various indicator columns    */
      85             :     int header_height;    /* height of the header in pixels before the first layer */
      86             :     int mo_col, mo_layer; /* mouse over column and layer           */
      87             :     int rename_active;    /* If >=2, layer number for which the edit box for layer names is active */
      88             :     GClut *clut;
      89             :     GFont *font;          /* font to draw text in the palette with */
      90             : } layerinfo = {           /* info about the current layers in the layers palette */
      91             :     2, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL
      92             : };
      93             : 
      94             : struct l2 layer2 = { 2, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL };
      95             : static int layers2_active = -1;
      96             : static GPoint cvtoolsoff = { -9999, -9999 }, cvlayersoff = { -9999, -9999 }, bvlayersoff = { -9999, -9999 }, bvtoolsoff = { -9999, -9999 }, bvshadesoff = { -9999, -9999 };
      97             : int palettes_fixed=1;
      98             : static GCursor tools[cvt_max+1] = { ct_pointer }, spirotools[cvt_max+1];
      99             : 
     100             : enum cvtools cv_b1_tool = cvt_pointer, cv_cb1_tool = cvt_pointer,
     101             :              cv_b2_tool = cvt_magnify, cv_cb2_tool = cvt_ruler;
     102             : 
     103             : static GFont *toolsfont=NULL, *layersfont=NULL;
     104             : 
     105             : #define CV_LAYERS_WIDTH         104
     106             : #define CV_LAYERS_HEIGHT        100
     107             : #define CV_LAYERS_INITIALCNT    6
     108             : #define CV_LAYERS_LINE_HEIGHT   25
     109             : #define CV_LAYERS2_WIDTH        185
     110             : #define CV_LAYERS2_HEIGHT       126
     111             : #define CV_LAYERS2_LINE_HEIGHT  25
     112             : #define CV_LAYERS2_HEADER_HEIGHT        20
     113             : #define BV_TOOLS_WIDTH          53
     114             : #define BV_TOOLS_HEIGHT         80
     115             : #define BV_LAYERS_HEIGHT        73
     116             : #define BV_LAYERS_WIDTH         73
     117             : #define BV_SHADES_HEIGHT        (8+9*16)
     118             : 
     119             : /* These are control ids for the layers palette controls */
     120             : #define CID_VBase       1000
     121             : #define CID_VGrid       (CID_VBase+ly_grid)
     122             : #define CID_VBack       (CID_VBase+ly_back)
     123             : #define CID_VFore       (CID_VBase+ly_fore)
     124             : 
     125             : #define CID_EBase       3000
     126             : #define CID_EGrid       (CID_EBase+ly_grid)
     127             : #define CID_EBack       (CID_EBase+ly_back)
     128             : #define CID_EFore       (CID_EBase+ly_fore)
     129             : 
     130             : #define CID_QBase       5000
     131             : #define CID_QGrid       (CID_QBase+ly_grid)
     132             : #define CID_QBack       (CID_QBase+ly_back)
     133             : #define CID_QFore       (CID_QBase+ly_fore)
     134             : 
     135             : #define CID_FBase       7000
     136             : 
     137             : #define CID_SB          8000
     138             : #define CID_Edit        8001
     139             : 
     140             : #define CID_AddLayer    9000
     141             : #define CID_RemoveLayer 9001
     142             : #define CID_RenameLayer 9002
     143             : #define CID_LayersMenu  9003
     144             : #define CID_LayerLabel  9004
     145             : 
     146           0 : static void ReparentFixup(GWindow child,GWindow parent, int x, int y, int width, int height ) {
     147             :     /* This is so nice */
     148             :     /* KDE does not honor my request for a border for top level windows */
     149             :     /* KDE does not honor my request for size (for narrow) top level windows */
     150             :     /* Gnome gets very confused by reparenting */
     151             :         /* If we've got a top level window, then reparenting it removes gnome's */
     152             :         /* decoration window, but sets the new parent to root (rather than what */
     153             :         /* we asked for */
     154             :         /* I have tried reparenting it twice, unmapping & reparenting. Nothing works */
     155             : 
     156           0 :     GWidgetReparentWindow(child,parent,x,y);
     157           0 :     if ( width!=0 )
     158           0 :         GDrawResize(child,width,height);
     159           0 :     GDrawSetWindowBorder(child,1,GDrawGetDefaultForeground(NULL));
     160           0 : }
     161             : 
     162           0 : void onCollabSessionStateChanged( gpointer instance, FontViewBase* fv, gpointer user_data )
     163             : {
     164           0 :     bool inCollab = collabclient_inSessionFV( fv );
     165             : 
     166           0 :     if (cvlayers != NULL) {
     167           0 :       GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_AddLayer),    !inCollab );
     168           0 :       GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_RemoveLayer), !inCollab );
     169           0 :       GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_RenameLayer), !inCollab );
     170             :     } else if (cvlayers2 != NULL && 0) {
     171             :       // These controls seem not to exist in cvlayers2. We can look deeper into this later.
     172             :       GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_AddLayer),    !inCollab );
     173             :       GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_RemoveLayer), !inCollab );
     174             :       GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_RenameLayer), !inCollab );
     175             :     }
     176           0 : }
     177             : 
     178             : /* Initialize a window that is to be used for a palette. Specific widgets and other functionality are added elsewhere. */
     179           0 : static GWindow CreatePalette(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs, GWindow v) {
     180             :     GWindow gw;
     181             :     GPoint pt, base;
     182             :     GRect newpos;
     183             :     GWindow root;
     184             :     GRect ownerpos, screensize;
     185             : 
     186           0 :     pt.x = pos->x; pt.y = pos->y;
     187           0 :     if ( !palettes_fixed ) {
     188           0 :         root = GDrawGetRoot(NULL);
     189           0 :         GDrawGetSize(w,&ownerpos);
     190           0 :         GDrawGetSize(root,&screensize);
     191           0 :         GDrawTranslateCoordinates(w,root,&pt);
     192           0 :         base.x = base.y = 0;
     193           0 :         GDrawTranslateCoordinates(w,root,&base);
     194           0 :         if ( pt.x<0 ) {
     195           0 :             if ( base.x+ownerpos.width+20+pos->width+20 > screensize.width )
     196           0 :                 pt.x=0;
     197             :             else
     198           0 :                 pt.x = base.x+ownerpos.width+20;
     199             :         }
     200           0 :         if ( pt.y<0 ) pt.y=0;
     201           0 :         if ( pt.x+pos->width>screensize.width )
     202           0 :             pt.x = screensize.width-pos->width;
     203           0 :         if ( pt.y+pos->height>screensize.height )
     204           0 :             pt.y = screensize.height-pos->height;
     205             :     }
     206           0 :     wattrs->mask |= wam_bordcol|wam_bordwidth;
     207           0 :     wattrs->border_width = 1;
     208           0 :     wattrs->border_color = GDrawGetDefaultForeground(NULL);
     209             : 
     210           0 :     newpos.x = pt.x; newpos.y = pt.y; newpos.width = pos->width; newpos.height = pos->height;
     211           0 :     wattrs->mask|= wam_positioned;
     212           0 :     wattrs->positioned = true;
     213           0 :     gw = GDrawCreateTopWindow(NULL,&newpos,eh,user_data,wattrs);
     214           0 :     if ( palettes_docked )
     215           0 :         ReparentFixup(gw,v,0,pos->y,pos->width,pos->height);
     216             : 
     217           0 :     collabclient_addSessionJoiningCallback( onCollabSessionStateChanged );
     218           0 :     collabclient_addSessionLeavingCallback( onCollabSessionStateChanged );
     219             :     
     220           0 : return( gw );
     221             : }
     222             : 
     223             : 
     224             : 
     225             : /* Return screen coordinates of the palette in off, relative to the root window origin. */
     226           0 : static void SaveOffsets(GWindow main, GWindow palette, GPoint *off) {
     227           0 :     if ( !palettes_docked && !palettes_fixed && GDrawIsVisible(palette)) {
     228             :         GRect mr, pr;
     229             :         GWindow root, temp;
     230           0 :         root = GDrawGetRoot(NULL);
     231           0 :         while ( (temp=GDrawGetParentWindow(main))!=root )
     232           0 :             main = temp;
     233           0 :         GDrawGetSize(main,&mr);
     234           0 :         GDrawGetSize(palette,&pr);
     235           0 :         off->x = pr.x-mr.x;
     236           0 :         off->y = pr.y-mr.y;
     237           0 :         if ( off->x<0 ) off->x = 0;
     238           0 :         if ( off->y<0 ) off->y = 0;
     239             :     }
     240           0 : }
     241             : 
     242             : /* Set the palette window position to off, a point in the root window space. */
     243           0 : static void RestoreOffsets(GWindow main, GWindow palette, GPoint *off) {
     244             :     GPoint pt;
     245             :     GWindow root,temp;
     246             :     GRect screensize, pos;
     247             : 
     248           0 :     if ( palettes_fixed )
     249           0 : return;
     250           0 :     pt = *off;
     251           0 :     root = GDrawGetRoot(NULL);
     252           0 :     GDrawGetSize(root,&screensize);
     253           0 :     GDrawGetSize(palette,&pos);
     254           0 :     while ( (temp=GDrawGetParentWindow(main))!=root )
     255           0 :         main = temp;
     256           0 :     GDrawTranslateCoordinates(main,root,&pt);
     257           0 :     if ( pt.x<0 ) pt.x=0;
     258           0 :     if ( pt.y<0 ) pt.y=0;
     259           0 :     if ( pt.x+pos.width>screensize.width )
     260           0 :         pt.x = screensize.width-pos.width;
     261           0 :     if ( pt.y+pos.height>screensize.height )
     262           0 :         pt.y = screensize.height-pos.height;
     263           0 :     GDrawTrueMove(palette,pt.x,pt.y);
     264           0 :     GDrawRaise(palette);
     265             : }
     266             : 
     267           0 : static void CVMenuTool(GWindow gw,struct gmenuitem *mi,GEvent *e) {
     268           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
     269           0 :     cv->b1_tool = mi->mid;
     270           0 :     if ( cvtools!=NULL )
     271           0 :         GDrawRequestExpose(cvtools,NULL,false);
     272           0 :     CVToolsSetCursor(cv,0,NULL);
     273           0 : }
     274             : 
     275             : static void CVChangeSpiroMode(CharView *cv);
     276           0 : static void CVMenuSpiroSet(GWindow gw,struct gmenuitem *mi,GEvent *e) {
     277           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
     278           0 :     CVChangeSpiroMode(cv);
     279           0 : }
     280             : 
     281           0 : void cvtoollist_check(GWindow gw,struct gmenuitem *mi,GEvent *e) {
     282           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
     283           0 :     int order2 = cv->b.layerheads[cv->b.drawmode]->order2;
     284             : 
     285           0 :     for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
     286           0 :         mi->ti.checked = mi->mid==cv->b1_tool;
     287           0 :         switch ( mi->mid ) {
     288             :           case cvt_freehand:
     289           0 :             mi->ti.disabled = order2;
     290           0 :           break;
     291             :           case cvt_spiro:
     292           0 :             mi->ti.disabled = !hasspiro();
     293           0 :           break;
     294             :         }
     295             :     }
     296           0 : }
     297             : 
     298             : /* Note: If you change this ordering, change enum cvtools */
     299             : static char *popupsres[] = {
     300             :     N_("Pointer"),               N_("Magnify (Minify with alt)"),
     301             :     N_("Draw a freehand curve"), N_("Scroll by hand"),
     302             :     N_("Cut splines in two"),    N_("Measure distance, angle between points"),
     303             :     N_("Add a point, then drag out its control points"), N_("Change whether spiro is active or not"),
     304             :     N_("Add a curve point"),     N_("Add a curve point always either horizontal or vertical"),
     305             :     N_("Add a corner point"),    N_("Add a tangent point"),
     306             :     N_("Scale the selection"),   N_("Rotate the selection"),
     307             :     N_("Flip the selection"),  N_("Skew the selection"),
     308             :     N_("Rotate the selection in 3D and project back to plain"), N_("Perform a perspective transformation on the selection"),
     309             :     N_("Rectangle or Ellipse"),  N_("Polygon or Star"),
     310             :     N_("Rectangle or Ellipse"),  N_("Polygon or Star")};
     311             : GMenuItem2 cvtoollist[] = {
     312             :     { { (unichar_t *) N_("_Pointer"), (GImage *) "toolspointer.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Pointer|No Shortcut"), NULL, NULL, CVMenuTool, cvt_pointer },
     313             :     { { (unichar_t *) N_("_Magnify"), (GImage *) "toolsmagnify.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Magnify|No Shortcut"), NULL, NULL, CVMenuTool, cvt_magnify },
     314             :     { { (unichar_t *) N_("_Freehand"), (GImage *) "toolsfreehand.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Freehand|No Shortcut"), NULL, NULL, CVMenuTool, cvt_freehand },
     315             :     { { (unichar_t *) N_("_Scroll"), (GImage *) "toolsscroll.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Scroll|No Shortcut"), NULL, NULL, CVMenuTool, cvt_hand },
     316             :     { { (unichar_t *) N_("_Knife"), (GImage *) "toolsknife.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Knife|No Shortcut"), NULL, NULL, CVMenuTool, cvt_knife },
     317             :     { { (unichar_t *) N_("_Ruler"), (GImage *) "toolsruler.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Ruler|No Shortcut"), NULL, NULL, CVMenuTool, cvt_ruler },
     318             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     319             :     { { (unichar_t *) N_("P_en"), (GImage *) "toolspen.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Pen|No Shortcut"), NULL, NULL, CVMenuTool, cvt_pen },
     320             :     { { (unichar_t *) N_("_Activate Spiro"), (GImage *) "toolsspiro.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Activate Spiro|No Shortcut"), NULL, NULL, CVMenuSpiroSet, cvt_spiro },
     321             :     { { (unichar_t *) N_("_Curve"), (GImage *) "pointscurve.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Curve Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_curve },
     322             :     { { (unichar_t *) N_("_HVCurve"), (GImage *) "pointshvcurve.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("HVCurve Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_hvcurve },
     323             :     { { (unichar_t *) N_("C_orner"), (GImage *) "pointscorner.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Corner Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_corner },
     324             :     { { (unichar_t *) N_("_Tangent"), (GImage *) "pointstangent.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tangent Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_tangent },
     325             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     326             :     { { (unichar_t *) N_("Sca_le"), (GImage *) "toolsscale.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Scale|No Shortcut"), NULL, NULL, CVMenuTool, cvt_scale },
     327             :     { { (unichar_t *) N_("Rotate"), (GImage *) "toolsrotate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Rotate|No Shortcut"), NULL, NULL, CVMenuTool, cvt_rotate },
     328             :     { { (unichar_t *) N_("Flip"), (GImage *) "toolsflip.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Flip|No Shortcut"), NULL, NULL, CVMenuTool, cvt_flip },
     329             :     { { (unichar_t *) N_("Ske_w"), (GImage *) "toolsskew.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Skew|No Shortcut"), NULL, NULL, CVMenuTool, cvt_skew },
     330             :     { { (unichar_t *) N_("_3D Rotate"), (GImage *) "tools3drotate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("3D Rotate|No Shortcut"), NULL, NULL, CVMenuTool, cvt_3d_rotate },
     331             :     { { (unichar_t *) N_("Perspecti_ve"), (GImage *) "toolsperspective.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Perspective|No Shortcut"), NULL, NULL, CVMenuTool, cvt_perspective },
     332             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     333             :     { { (unichar_t *) N_("Rectan_gle"), (GImage *) "toolsrect.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Rectangle|No Shortcut"), NULL, NULL, CVMenuTool, cvt_rect },
     334             :     { { (unichar_t *) N_("Pol_ygon"), (GImage *) "toolspolygon.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Polygon|No Shortcut"), NULL, NULL, CVMenuTool, cvt_poly },
     335             :     { { (unichar_t *) N_("Ellipse"), (GImage *) "toolselipse.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Ellipse|No Shortcut"), NULL, NULL, CVMenuTool, cvt_elipse },
     336             :     { { (unichar_t *) N_("Star"), (GImage *) "toolsstar.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Star|No Shortcut"), NULL, NULL, CVMenuTool, cvt_star },
     337             :     GMENUITEM2_EMPTY
     338             : };
     339             : GMenuItem2 cvspirotoollist[] = {
     340             :     { { (unichar_t *) N_("_Pointer"), (GImage *) "toolspointer.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Pointer|No Shortcut"), NULL, NULL, CVMenuTool, cvt_pointer },
     341             :     { { (unichar_t *) N_("_Magnify"), (GImage *) "toolsmagnify.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Magnify|No Shortcut"), NULL, NULL, CVMenuTool, cvt_magnify },
     342             :     { { (unichar_t *) N_("_Freehand"), (GImage *) "toolsfreehand.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Freehand|No Shortcut"), NULL, NULL, CVMenuTool, cvt_freehand },
     343             :     { { (unichar_t *) N_("_Scroll"), (GImage *) "toolsscroll.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Scroll|No Shortcut"), NULL, NULL, CVMenuTool, cvt_hand },
     344             :     { { (unichar_t *) N_("_Knife"), (GImage *) "toolsknife.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Knife|No Shortcut"), NULL, NULL, CVMenuTool, cvt_knife },
     345             :     { { (unichar_t *) N_("_Ruler"), (GImage *) "toolsruler.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Ruler|No Shortcut"), NULL, NULL, CVMenuTool, cvt_ruler },
     346             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     347             :     { { (unichar_t *) N_("_Knife"), (GImage *) "toolsknife.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Knife|No Shortcut"), NULL, NULL, CVMenuTool, cvt_knife },
     348             :     { { (unichar_t *) N_("_Ruler"), (GImage *) "toolsruler.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Ruler|No Shortcut"), NULL, NULL, CVMenuTool, cvt_ruler },
     349             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     350             :     { { (unichar_t *) N_("De_activate Spiro"), (GImage *) "toolsspiro.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Activate Spiro|No Shortcut"), NULL, NULL, CVMenuSpiroSet, cvt_spiro },
     351             :     { { (unichar_t *) N_("C_orner"), (GImage *) "pointscorner.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Corner Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_spirocorner },
     352             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     353             :     { { (unichar_t *) N_("G_4"), (GImage *) "pointscurve.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("G4 Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_spirog4 },
     354             :     { { (unichar_t *) N_("G_2"), (GImage *) "pointsG2curve.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("G2 Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_spirog2 },
     355             :     { { (unichar_t *) N_("Lef_t"), (GImage *) "pointsspiroprev.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Left Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_spiroleft },
     356             :     { { (unichar_t *) N_("Rig_ht"), (GImage *) "pointsspironext.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Right Tool|No Shortcut"), NULL, NULL, CVMenuTool, cvt_spiroright },
     357             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     358             :     { { (unichar_t *) N_("Sca_le"), (GImage *) "toolsscale.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Scale|No Shortcut"), NULL, NULL, CVMenuTool, cvt_scale },
     359             :     { { (unichar_t *) N_("Rotate"), (GImage *) "toolsrotate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Rotate|No Shortcut"), NULL, NULL, CVMenuTool, cvt_rotate },
     360             :     { { (unichar_t *) N_("Flip"), (GImage *) "toolsflip.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Flip|No Shortcut"), NULL, NULL, CVMenuTool, cvt_flip },
     361             :     { { (unichar_t *) N_("Ske_w"), (GImage *) "toolsskew.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Skew|No Shortcut"), NULL, NULL, CVMenuTool, cvt_skew },
     362             :     { { (unichar_t *) N_("_3D Rotate"), (GImage *) "tools3drotate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("3D Rotate|No Shortcut"), NULL, NULL, CVMenuTool, cvt_3d_rotate },
     363             :     { { (unichar_t *) N_("Perspecti_ve"), (GImage *) "toolsperspective.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Perspective|No Shortcut"), NULL, NULL, CVMenuTool, cvt_perspective },
     364             :     { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
     365             :     { { (unichar_t *) N_("Rectan_gle"), (GImage *) "toolsrect.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Rectangle|No Shortcut"), NULL, NULL, CVMenuTool, cvt_rect },
     366             :     { { (unichar_t *) N_("Pol_ygon"), (GImage *) "toolspolygon.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Polygon|No Shortcut"), NULL, NULL, CVMenuTool, cvt_poly },
     367             :     { { (unichar_t *) N_("Ellipse"), (GImage *) "toolselipse.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Ellipse|No Shortcut"), NULL, NULL, CVMenuTool, cvt_elipse },
     368             :     { { (unichar_t *) N_("Star"), (GImage *) "toolsstar.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Star|No Shortcut"), NULL, NULL, CVMenuTool, cvt_star },
     369             :     GMENUITEM2_EMPTY
     370             : };
     371             : 
     372             : static char *editablelayers[] = {
     373             : /* GT: Foreground, make it short */
     374             :     N_("F_ore"),
     375             : /* GT: Background, make it short */
     376             :     N_("_Back"),
     377             : /* GT: Guide layer, make it short */
     378             :     N_("_Guide")
     379             : };
     380             : static real raddiam_x = 20, raddiam_y = 20, rotate_by=0;
     381             : static StrokeInfo expand = {
     382             :     25, lj_round, lc_butt, si_centerline,
     383             :     false, /* removeexternal */
     384             :     false, /* removeinternal */
     385             :     false, /* leave users */
     386             :     3.1415926535897932/4, 25, NULL, 50,
     387             :     0.0, 0, 0, NULL, NULL
     388             : };
     389             : 
     390           0 : real CVRoundRectRadius(void) {
     391           0 : return( rr_radius );
     392             : }
     393             : 
     394           0 : int CVRectElipseCenter(void) {
     395           0 : return( center_out[rectelipse] );
     396             : }
     397             : 
     398           0 : int CVPolyStarPoints(void) {
     399           0 : return( ps_pointcnt );
     400             : }
     401             : 
     402           0 : real CVStarRatio(void) {
     403           0 :     if ( regular_star )
     404           0 : return( sin(3.1415926535897932/ps_pointcnt)*tan(2*3.1415926535897932/ps_pointcnt)+cos(3.1415926535897932/ps_pointcnt) );
     405             :         
     406           0 : return( star_percent );
     407             : }
     408             : 
     409           0 : StrokeInfo *CVFreeHandInfo(void) {
     410           0 : return( &expand );
     411             : }
     412             :     
     413             : struct ask_info {
     414             :     GWindow gw;
     415             :     int done;
     416             :     int ret;
     417             :     float *val;
     418             :     int *co;
     419             :     GGadget *rb1;
     420             :     GGadget *reg;
     421             :     GGadget *pts;
     422             :     int ispolystar;
     423             :     int haspos;
     424             :     char *lab;
     425             :     CharView *cv;
     426             : };
     427             : #define CID_ValText             1001
     428             : #define CID_PointPercent        1002
     429             : #define CID_CentCornLab         1003
     430             : #define CID_CentCornX           1004
     431             : #define CID_CentCornY           1005
     432             : #define CID_RadDiamLab          1006
     433             : #define CID_RadDiamX            1007
     434             : #define CID_RadDiamY            1008
     435             : #define CID_Angle               1009
     436             : 
     437           0 : static void FakeShapeEvents(CharView *cv) {
     438             :     GEvent event;
     439             :     real trans[6];
     440             : 
     441           0 :     cv->active_tool = rectelipse ? cvt_elipse : cvt_rect;
     442           0 :     if ( cv->b.sc->inspiro && hasspiro() ) {
     443           0 :         GDrawSetCursor(cv->v,spirotools[cv->active_tool]);
     444           0 :         GDrawSetCursor(cvtools,spirotools[cv->active_tool]);
     445             :     } else {
     446           0 :         GDrawSetCursor(cv->v,tools[cv->active_tool]);
     447           0 :         GDrawSetCursor(cvtools,tools[cv->active_tool]);
     448             :     }
     449           0 :     cv->showing_tool = cv->active_tool;
     450             : 
     451           0 :     memset(&event,0,sizeof(event));
     452           0 :     event.type = et_mousedown;
     453           0 :     CVMouseDownShape(cv,&event);
     454           0 :     cv->info.x += raddiam_x;
     455           0 :     cv->info.y += raddiam_y;
     456           0 :     CVMouseMoveShape(cv);
     457           0 :     CVMouseUpShape(cv);
     458           0 :     if ( raddiam_x!=0 && raddiam_y!=0 && rotate_by!=0 ) {
     459           0 :         trans[0] = trans[3] = cos ( rotate_by*3.1415926535897932/180. );
     460           0 :         trans[1] = sin( rotate_by*3.1415926535897932/180. );
     461           0 :         trans[2] = -trans[1];
     462           0 :         trans[4] = -cv->p.x*trans[0] - cv->p.y*trans[2] + cv->p.x;
     463           0 :         trans[5] = -cv->p.x*trans[1] - cv->p.y*trans[3] + cv->p.y;
     464           0 :         SplinePointListTransform(cv->b.layerheads[cv->b.drawmode]->splines,trans,
     465           0 :                 interpCPsOnMotion?tpt_OnlySelectedInterpCPs:tpt_OnlySelected);
     466           0 :         SCUpdateAll(cv->b.sc);
     467             :     }
     468           0 :     cv->active_tool = cvt_none;
     469           0 : }
     470             : 
     471           0 : static int TA_OK(GGadget *g, GEvent *e) {
     472           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     473           0 :         struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
     474           0 :         real val, val2=0;
     475           0 :         int err=0;
     476           0 :         int re = !GGadgetIsChecked(d->rb1);
     477           0 :         if ( d->ispolystar ) {
     478           0 :             val = GetInt8(d->gw,CID_ValText,d->lab,&err);
     479           0 :             if ( !(regular_star = GGadgetIsChecked(d->reg)))
     480           0 :                 val2 = GetReal8(d->gw,CID_PointPercent,_("Size of Points"),&err);
     481             :         } else {
     482           0 :             val = GetReal8(d->gw,CID_ValText,d->lab,&err);
     483           0 :             d->co[re] = !GGadgetIsChecked(d->reg);
     484             :         }
     485           0 :         if ( err )
     486           0 : return( true );
     487           0 :         if ( d->haspos ) {
     488             :             real x,y, radx,rady, ang;
     489           0 :             x = GetInt8(d->gw,CID_CentCornX,_("_X"),&err);
     490           0 :             y = GetInt8(d->gw,CID_CentCornY,_("_Y"),&err);
     491           0 :             radx = GetInt8(d->gw,CID_RadDiamX,_("Radius:   "),&err);
     492           0 :             rady = GetInt8(d->gw,CID_RadDiamY,_("Radius:   "),&err);
     493           0 :             ang = GetInt8(d->gw,CID_Angle,_("Angle:"),&err);
     494           0 :             if ( err )
     495           0 : return( true );
     496           0 :             d->cv->p.x = d->cv->info.x = x;
     497           0 :             d->cv->p.y = d->cv->info.y = y;
     498           0 :             raddiam_x = radx; raddiam_y = rady;
     499           0 :             rotate_by = ang;
     500           0 :             rectelipse = re;
     501           0 :             *d->val = val;
     502           0 :             FakeShapeEvents(d->cv);
     503             :         }
     504           0 :         *d->val = val;
     505           0 :         d->ret = re;
     506           0 :         d->done = true;
     507           0 :         if ( !regular_star && d->ispolystar )
     508           0 :             star_percent = val2/100;
     509           0 :         SavePrefs(true);
     510             :     }
     511           0 : return( true );
     512             : }
     513             : 
     514           0 : static int TA_Cancel(GGadget *g, GEvent *e) {
     515           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
     516           0 :         struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
     517           0 :         d->done = true;
     518             :     }
     519           0 : return( true );
     520             : }
     521             : 
     522           0 : static int TA_CenRadChange(GGadget *g, GEvent *e) {
     523           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
     524           0 :         struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
     525           0 :         int is_bb = GGadgetIsChecked(d->reg);
     526           0 :         GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_CentCornLab),
     527             :                 is_bb ? _("Corner") : _("C_enter"));
     528           0 :         GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_RadDiamLab),
     529             :                 is_bb ? _("Diameter:") : _("Radius:   "));
     530             :     }
     531           0 : return( true );
     532             : }
     533             : 
     534           0 : static int TA_RadChange(GGadget *g, GEvent *e) {
     535           0 :     if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
     536           0 :         struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
     537           0 :         int is_ellipse = !GGadgetIsChecked(d->rb1);
     538           0 :         GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_ValText), !is_ellipse );
     539           0 :         GGadgetSetChecked(d->reg,!center_out[is_ellipse]);
     540           0 :         GGadgetSetChecked(d->pts,center_out[is_ellipse]);
     541           0 :         if ( d->haspos )
     542           0 :             TA_CenRadChange(g,e);
     543             :     }
     544           0 : return( true );
     545             : }
     546             : 
     547           0 : static int toolask_e_h(GWindow gw, GEvent *event) {
     548           0 :     if ( event->type==et_close ) {
     549           0 :         struct ask_info *d = GDrawGetUserData(gw);
     550           0 :         d->done = true;
     551           0 :     } else if ( event->type == et_map ) {
     552             :         /* Above palettes */
     553           0 :         GDrawRaise(gw);
     554             :     }
     555           0 : return( event->type!=et_char );
     556             : }
     557             : 
     558           0 : static int Ask(char *rb1, char *rb2, int rb, char *lab, float *val, int *co,
     559             :         int ispolystar, CharView *cv ) {
     560             :     struct ask_info d;
     561             :     char buffer[20], buf[20];
     562             :     char cenx[20], ceny[20], radx[20], rady[20], angle[20];
     563             :     GRect pos;
     564             :     GWindowAttrs wattrs;
     565             :     GGadgetCreateData gcd[19];
     566             :     GTextInfo label[19];
     567           0 :     int off = ((ispolystar&1)?15:0) + ((ispolystar&2)?84:0);
     568           0 :     int haspos = (ispolystar&2)?1:0;
     569             : 
     570           0 :     ispolystar &= 1;
     571             : 
     572           0 :     d.done = false;
     573           0 :     d.ret = rb;
     574           0 :     d.val = val;
     575           0 :     d.co = co;
     576           0 :     d.ispolystar = ispolystar;
     577           0 :     d.haspos = haspos;
     578           0 :     d.lab = lab;
     579           0 :     d.cv = cv;
     580             : 
     581           0 :         memset(&wattrs,0,sizeof(wattrs));
     582           0 :         wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
     583           0 :         wattrs.event_masks = ~(1<<et_charup);
     584           0 :         wattrs.restrict_input_to_me = 1;
     585           0 :         wattrs.undercursor = 1;
     586           0 :         wattrs.cursor = ct_pointer;
     587           0 :         wattrs.utf8_window_title = _("Shape Type");
     588           0 :         wattrs.is_dlg = true;
     589           0 :         pos.x = pos.y = 0;
     590           0 :         pos.width = GGadgetScale(GDrawPointsToPixels(NULL,190));
     591           0 :         pos.height = GDrawPointsToPixels(NULL,120+off);
     592           0 :         d.gw = GDrawCreateTopWindow(NULL,&pos,toolask_e_h,&d,&wattrs);
     593             : 
     594           0 :         memset(&label,0,sizeof(label));
     595           0 :         memset(&gcd,0,sizeof(gcd));
     596             : 
     597           0 :         label[0].text = (unichar_t *) rb1;
     598           0 :         label[0].text_is_1byte = true;
     599           0 :         gcd[0].gd.label = &label[0];
     600           0 :         gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5; 
     601           0 :         gcd[0].gd.flags = gg_enabled|gg_visible | (rb==0?gg_cb_on:0);
     602           0 :         gcd[0].creator = GRadioCreate;
     603             : 
     604           0 :         label[1].text = (unichar_t *) rb2;
     605           0 :         label[1].text_is_1byte = true;
     606           0 :         gcd[1].gd.label = &label[1];
     607           0 :         gcd[1].gd.pos.x = ispolystar?65:75; gcd[1].gd.pos.y = 5; 
     608           0 :         gcd[1].gd.flags = gg_enabled|gg_visible | (rb==1?gg_cb_on:0);
     609           0 :         gcd[1].creator = GRadioCreate;
     610             : 
     611           0 :         label[2].text = (unichar_t *) lab;
     612           0 :         label[2].text_is_1byte = true;
     613           0 :         gcd[2].gd.label = &label[2];
     614           0 :         gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = 25; 
     615           0 :         gcd[2].gd.flags = gg_enabled|gg_visible ;
     616           0 :         gcd[2].creator = GLabelCreate;
     617             : 
     618           0 :         sprintf( buffer, "%g", *val );
     619           0 :         label[3].text = (unichar_t *) buffer;
     620           0 :         label[3].text_is_1byte = true;
     621           0 :         gcd[3].gd.label = &label[3];
     622           0 :         gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 40; 
     623           0 :         gcd[3].gd.flags = gg_enabled|gg_visible ;
     624           0 :         gcd[3].gd.cid = CID_ValText;
     625           0 :         gcd[3].creator = GTextFieldCreate;
     626             : 
     627           0 :         gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = 85+off;
     628           0 :         gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
     629           0 :         gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
     630           0 :         label[4].text = (unichar_t *) _("_OK");
     631           0 :         label[4].text_is_1byte = true;
     632           0 :         label[4].text_in_resource = true;
     633           0 :         gcd[4].gd.mnemonic = 'O';
     634           0 :         gcd[4].gd.label = &label[4];
     635           0 :         gcd[4].gd.handle_controlevent = TA_OK;
     636           0 :         gcd[4].creator = GButtonCreate;
     637             : 
     638           0 :         gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = 85+3+off;
     639           0 :         gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
     640           0 :         gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
     641           0 :         label[5].text = (unichar_t *) _("_Cancel");
     642           0 :         label[5].text_is_1byte = true;
     643           0 :         label[5].text_in_resource = true;
     644           0 :         gcd[5].gd.label = &label[5];
     645           0 :         gcd[5].gd.mnemonic = 'C';
     646           0 :         gcd[5].gd.handle_controlevent = TA_Cancel;
     647           0 :         gcd[5].creator = GButtonCreate;
     648             : 
     649           0 :         if ( ispolystar ) {
     650           0 :             label[6].text = (unichar_t *) _("Regular");
     651           0 :             label[6].text_is_1byte = true;
     652           0 :             gcd[6].gd.label = &label[6];
     653           0 :             gcd[6].gd.pos.x = 5; gcd[6].gd.pos.y = 70; 
     654           0 :             gcd[6].gd.flags = gg_enabled|gg_visible | (rb==0?gg_cb_on:0);
     655           0 :             gcd[6].creator = GRadioCreate;
     656             : 
     657           0 :             label[7].text = (unichar_t *) _("Points:");
     658           0 :             label[7].text_is_1byte = true;
     659           0 :             gcd[7].gd.label = &label[7];
     660           0 :             gcd[7].gd.pos.x = 65; gcd[7].gd.pos.y = 70; 
     661           0 :             gcd[7].gd.flags = gg_enabled|gg_visible | (rb==1?gg_cb_on:0);
     662           0 :             gcd[7].creator = GRadioCreate;
     663             : 
     664           0 :             sprintf( buf, "%4g", star_percent*100 );
     665           0 :             label[8].text = (unichar_t *) buf;
     666           0 :             label[8].text_is_1byte = true;
     667           0 :             gcd[8].gd.label = &label[8];
     668           0 :             gcd[8].gd.pos.x = 125; gcd[8].gd.pos.y = 70;  gcd[8].gd.pos.width=50;
     669           0 :             gcd[8].gd.flags = gg_enabled|gg_visible ;
     670           0 :             gcd[8].gd.cid = CID_PointPercent;
     671           0 :             gcd[8].creator = GTextFieldCreate;
     672             : 
     673           0 :             label[9].text = (unichar_t *) "%";
     674           0 :             label[9].text_is_1byte = true;
     675           0 :             gcd[9].gd.label = &label[9];
     676           0 :             gcd[9].gd.pos.x = 180; gcd[9].gd.pos.y = 70; 
     677           0 :             gcd[9].gd.flags = gg_enabled|gg_visible ;
     678           0 :             gcd[9].creator = GLabelCreate;
     679             :         } else {
     680           0 :             label[6].text = (unichar_t *) _("Bounding Box");
     681           0 :             label[6].text_is_1byte = true;
     682           0 :             gcd[6].gd.label = &label[6];
     683           0 :             gcd[6].gd.pos.x = 5; gcd[6].gd.pos.y = 65; 
     684           0 :             gcd[6].gd.flags = gg_enabled|gg_visible | (co[rb]==0?gg_cb_on:0);
     685           0 :             gcd[6].creator = GRadioCreate;
     686             : 
     687           0 :             label[7].text = (unichar_t *) _("Center Out");
     688           0 :             label[7].text_is_1byte = true;
     689           0 :             gcd[7].gd.label = &label[7];
     690           0 :             gcd[7].gd.pos.x = 90; gcd[7].gd.pos.y = 65; 
     691           0 :             gcd[7].gd.flags = gg_enabled|gg_visible | (co[rb]==1?gg_cb_on:0);
     692           0 :             gcd[7].creator = GRadioCreate;
     693             : 
     694           0 :             if ( rb )
     695           0 :                 gcd[3].gd.flags = gg_visible;
     696           0 :             gcd[0].gd.handle_controlevent = TA_RadChange;
     697           0 :             gcd[1].gd.handle_controlevent = TA_RadChange;
     698             : 
     699           0 :             if ( haspos ) {
     700           0 :                 gcd[6].gd.handle_controlevent = TA_CenRadChange;
     701           0 :                 gcd[7].gd.handle_controlevent = TA_CenRadChange;
     702             : 
     703           0 :                 label[8].text = (unichar_t *) _("_X");
     704           0 :                 label[8].text_is_1byte = true;
     705           0 :                 label[8].text_in_resource = true;
     706           0 :                 gcd[8].gd.label = &label[8];
     707           0 :                 gcd[8].gd.pos.x = 70; gcd[8].gd.pos.y = gcd[7].gd.pos.y+15;
     708           0 :                 gcd[8].gd.flags = gg_enabled|gg_visible;
     709           0 :                 gcd[8].creator = GLabelCreate;
     710             : 
     711           0 :                 label[9].text = (unichar_t *) _("_Y");
     712           0 :                 label[9].text_is_1byte = true;
     713           0 :                 label[9].text_in_resource = true;
     714           0 :                 gcd[9].gd.label = &label[9];
     715           0 :                 gcd[9].gd.pos.x = 120; gcd[9].gd.pos.y = gcd[8].gd.pos.y;
     716           0 :                 gcd[9].gd.flags = gg_enabled|gg_visible;
     717           0 :                 gcd[9].creator = GLabelCreate;
     718             : 
     719           0 :                 label[10].text = (unichar_t *) (co[rb] ? _("C_enter") : _("C_orner") );
     720           0 :                 label[10].text_is_1byte = true;
     721           0 :                 label[10].text_in_resource = true;
     722           0 :                 gcd[10].gd.label = &label[10];
     723           0 :                 gcd[10].gd.pos.x = 5; gcd[10].gd.pos.y = gcd[8].gd.pos.y+17;
     724           0 :                 gcd[10].gd.flags = gg_enabled|gg_visible;
     725           0 :                 gcd[10].gd.cid = CID_CentCornLab;
     726           0 :                 gcd[10].creator = GLabelCreate;
     727             : 
     728           0 :                 sprintf( cenx, "%g", (double) cv->info.x );
     729           0 :                 label[11].text = (unichar_t *) cenx;
     730           0 :                 label[11].text_is_1byte = true;
     731           0 :                 gcd[11].gd.label = &label[11];
     732           0 :                 gcd[11].gd.pos.x = 60; gcd[11].gd.pos.y = gcd[10].gd.pos.y-4;
     733           0 :                 gcd[11].gd.pos.width = 40;
     734           0 :                 gcd[11].gd.flags = gg_enabled|gg_visible;
     735           0 :                 gcd[11].gd.cid = CID_CentCornX;
     736           0 :                 gcd[11].creator = GTextFieldCreate;
     737             : 
     738           0 :                 sprintf( ceny, "%g", (double) cv->info.y );
     739           0 :                 label[12].text = (unichar_t *) ceny;
     740           0 :                 label[12].text_is_1byte = true;
     741           0 :                 gcd[12].gd.label = &label[12];
     742           0 :                 gcd[12].gd.pos.x = 110; gcd[12].gd.pos.y = gcd[11].gd.pos.y;
     743           0 :                 gcd[12].gd.pos.width = gcd[11].gd.pos.width;
     744           0 :                 gcd[12].gd.flags = gg_enabled|gg_visible;
     745           0 :                 gcd[12].gd.cid = CID_CentCornY;
     746           0 :                 gcd[12].creator = GTextFieldCreate;
     747             : 
     748           0 :                 label[13].text = (unichar_t *) (co[rb] ? _("Radius:   ") : _("Diameter:") );
     749           0 :                 label[13].text_is_1byte = true;
     750           0 :                 gcd[13].gd.label = &label[13];
     751           0 :                 gcd[13].gd.pos.x = 5; gcd[13].gd.pos.y = gcd[10].gd.pos.y+24;
     752           0 :                 gcd[13].gd.flags = gg_enabled|gg_visible;
     753           0 :                 gcd[13].gd.cid = CID_RadDiamLab;
     754           0 :                 gcd[13].creator = GLabelCreate;
     755             : 
     756           0 :                 sprintf( radx, "%g", (double) raddiam_x );
     757           0 :                 label[14].text = (unichar_t *) radx;
     758           0 :                 label[14].text_is_1byte = true;
     759           0 :                 gcd[14].gd.label = &label[14];
     760           0 :                 gcd[14].gd.pos.x = gcd[11].gd.pos.x; gcd[14].gd.pos.y = gcd[13].gd.pos.y-4;
     761           0 :                 gcd[14].gd.pos.width = gcd[11].gd.pos.width;
     762           0 :                 gcd[14].gd.flags = gg_enabled|gg_visible;
     763           0 :                 gcd[14].gd.cid = CID_RadDiamX;
     764           0 :                 gcd[14].creator = GTextFieldCreate;
     765             : 
     766           0 :                 sprintf( rady, "%g", (double) raddiam_y );
     767           0 :                 label[15].text = (unichar_t *) rady;
     768           0 :                 label[15].text_is_1byte = true;
     769           0 :                 gcd[15].gd.label = &label[15];
     770           0 :                 gcd[15].gd.pos.x = gcd[12].gd.pos.x; gcd[15].gd.pos.y = gcd[14].gd.pos.y;
     771           0 :                 gcd[15].gd.pos.width = gcd[11].gd.pos.width;
     772           0 :                 gcd[15].gd.flags = gg_enabled|gg_visible;
     773           0 :                 gcd[15].gd.cid = CID_RadDiamY;
     774           0 :                 gcd[15].creator = GTextFieldCreate;
     775             : 
     776           0 :                 label[16].text = (unichar_t *) _("Angle:");
     777           0 :                 label[16].text_is_1byte = true;
     778           0 :                 gcd[16].gd.label = &label[16];
     779           0 :                 gcd[16].gd.pos.x = 5; gcd[16].gd.pos.y = gcd[13].gd.pos.y+24;
     780           0 :                 gcd[16].gd.flags = gg_enabled|gg_visible;
     781           0 :                 gcd[16].creator = GLabelCreate;
     782             : 
     783           0 :                 sprintf( angle, "%g", (double) rotate_by );
     784           0 :                 label[17].text = (unichar_t *) angle;
     785           0 :                 label[17].text_is_1byte = true;
     786           0 :                 gcd[17].gd.label = &label[17];
     787           0 :                 gcd[17].gd.pos.x = 60; gcd[17].gd.pos.y = gcd[16].gd.pos.y-4;
     788           0 :                 gcd[17].gd.pos.width = gcd[11].gd.pos.width;
     789           0 :                 gcd[17].gd.flags = gg_enabled|gg_visible;
     790           0 :                 gcd[17].gd.cid = CID_Angle;
     791           0 :                 gcd[17].creator = GTextFieldCreate;
     792             :             }
     793             :         }
     794           0 :         GGadgetsCreate(d.gw,gcd);
     795           0 :     d.rb1 = gcd[0].ret;
     796           0 :     d.reg = gcd[6].ret;
     797           0 :     d.pts = gcd[7].ret;
     798             : 
     799           0 :     GWidgetHidePalettes();
     800           0 :     GDrawSetVisible(d.gw,true);
     801           0 :     while ( !d.done )
     802           0 :         GDrawProcessOneEvent(NULL);
     803           0 :     GDrawDestroyWindow(d.gw);
     804           0 : return( d.ret );
     805             : }
     806             : 
     807           0 : static void CVRectElipse(CharView *cv) {
     808           0 :     rectelipse = Ask(_("Rectangle"),_("Ellipse"),rectelipse,
     809             :             _("Round Rectangle Radius"),&rr_radius,center_out,false, cv);
     810           0 :     GDrawRequestExpose(cvtools,NULL,false);
     811           0 : }
     812             : 
     813           0 : void CVRectEllipsePosDlg(CharView *cv) {
     814           0 :     rectelipse = Ask(_("Rectangle"),_("Ellipse"),rectelipse,
     815             :             _("Round Rectangle Radius"),&rr_radius,center_out,2, cv);
     816           0 :     GDrawRequestExpose(cvtools,NULL,false);
     817           0 : }
     818             : 
     819           0 : static void CVPolyStar(CharView *cv) {
     820           0 :     float temp = ps_pointcnt;
     821             :     int foo[2];
     822           0 :     polystar = Ask(_("Polygon"),_("Star"),polystar,
     823             :             _("Number of star points/Polygon vertices"),&temp,foo,true, cv);
     824           0 :     ps_pointcnt = temp;
     825           0 : }
     826             : 
     827             : /* Note: If you change this ordering, change enum cvtools */
     828             : // index0 is non selected / selected image
     829             : // index1 is the row    in the toolbar
     830             : // index2 is the column in the toolbar
     831             : //
     832             : // This is two null terminated collections. The second collection
     833             : // contains the alternate icons for circle and star at the bottom of
     834             : // the toolbar.
     835             : static GImage *normbuttons[2][14][2] = {
     836             :     {
     837             :         { &GIcon_pointer,  &GIcon_magnify },
     838             :         { &GIcon_freehand, &GIcon_hand },
     839             :         { &GIcon_knife,    &GIcon_ruler },
     840             :         { &GIcon_pen,      &GIcon_spirodisabled },
     841             :         { &GIcon_curve,    &GIcon_hvcurve },
     842             :         { &GIcon_corner,   &GIcon_tangent},
     843             :         { &GIcon_scale,    &GIcon_rotate },
     844             :         { &GIcon_flip,     &GIcon_skew },
     845             :         { &GIcon_3drotate, &GIcon_perspective },
     846             :         { &GIcon_rect,     &GIcon_poly},
     847             :         { 0, 0 },
     848             :         { &GIcon_elipse,   &GIcon_star},
     849             :         { 0, 0 },
     850             :         { 0, 0 }
     851             :     }
     852             :     , {
     853             :         { &GIcon_pointer_selected,  &GIcon_magnify_selected },
     854             :         { &GIcon_freehand_selected, &GIcon_hand_selected },
     855             :         { &GIcon_knife_selected,    &GIcon_ruler_selected },
     856             :         { &GIcon_pen_selected,      &GIcon_spiroup_selected },
     857             :         { &GIcon_curve_selected,    &GIcon_hvcurve_selected },
     858             :         { &GIcon_corner_selected,   &GIcon_tangent_selected},
     859             :         { &GIcon_scale_selected,    &GIcon_rotate_selected },
     860             :         { &GIcon_flip_selected,     &GIcon_skew_selected },
     861             :         { &GIcon_3drotate_selected, &GIcon_perspective_selected },
     862             :         { &GIcon_rect_selected,     &GIcon_poly_selected},
     863             :         { 0, 0 },
     864             :         { &GIcon_elipse_selected,   &GIcon_star_selected},
     865             :         { 0, 0 },
     866             :         { 0, 0 }
     867             :     }};
     868             : static GImage *spirobuttons[2][14][2] = {
     869             :     {
     870             :         { &GIcon_pointer,      &GIcon_magnify },
     871             :         { &GIcon_freehand,     &GIcon_hand },
     872             :         { &GIcon_knife,        &GIcon_ruler },
     873             :         { &GIcon_spiroright,   &GIcon_spirodown },
     874             :         { &GIcon_spirocurve,   &GIcon_spirog2curve },
     875             :         { &GIcon_spirocorner,  &GIcon_spiroleft },
     876             :         { &GIcon_scale,        &GIcon_rotate },
     877             :         { &GIcon_flip,         &GIcon_skew },
     878             :         { &GIcon_3drotate,     &GIcon_perspective },
     879             :         { &GIcon_rect,         &GIcon_poly},
     880             :         { 0, 0 },
     881             :         { &GIcon_elipse,       &GIcon_star},
     882             :         { 0, 0 },
     883             :         { 0, 0 }
     884             :     }
     885             :     , {
     886             :         { &GIcon_pointer_selected,     &GIcon_magnify_selected },
     887             :         { &GIcon_freehand_selected,    &GIcon_hand_selected },
     888             :         { &GIcon_knife_selected,       &GIcon_ruler_selected },
     889             :         { &GIcon_spiroright_selected,  &GIcon_spirodown_selected },
     890             :         { &GIcon_spirocurve_selected,  &GIcon_spirog2curve_selected },
     891             :         { &GIcon_spirocorner_selected, &GIcon_spiroleft_selected },
     892             :         { &GIcon_scale_selected,       &GIcon_rotate_selected },
     893             :         { &GIcon_flip_selected,        &GIcon_skew_selected },
     894             :         { &GIcon_3drotate_selected,    &GIcon_perspective_selected },
     895             :         { &GIcon_rect_selected,        &GIcon_poly_selected},
     896             :         { 0, 0 },
     897             :         { &GIcon_elipse_selected,      &GIcon_star_selected},
     898             :         { 0, 0 },
     899             :         { 0, 0 }
     900             :     }};
     901             : static GImage *normsmalls[] = { &GIcon_smallpointer,  &GIcon_smallmag,
     902             :                                 &GIcon_smallpencil,   &GIcon_smallhand,
     903             :                                 &GIcon_smallknife,    &GIcon_smallruler,
     904             :                                 &GIcon_smallpen,      NULL,
     905             :                                 &GIcon_smallcurve,    &GIcon_smallhvcurve,
     906             :                                 &GIcon_smallcorner,   &GIcon_smalltangent,
     907             :                                 &GIcon_smallscale,    &GIcon_smallrotate,
     908             :                                 &GIcon_smallflip,     &GIcon_smallskew,
     909             :                                 &GIcon_small3drotate, &GIcon_smallperspective,
     910             :                                 &GIcon_smallrect,     &GIcon_smallpoly,
     911             :                                 &GIcon_smallelipse,   &GIcon_smallstar };
     912             : static GImage *spirosmalls[] = { &GIcon_smallpointer, &GIcon_smallmag,
     913             :                                  &GIcon_smallpencil,  &GIcon_smallhand,
     914             :                                  &GIcon_smallknife,   &GIcon_smallruler,
     915             :                                  &GIcon_smallspiroright,  NULL,
     916             :                                  &GIcon_smallspirocurve,  &GIcon_smallspirog2curve,
     917             :                                  &GIcon_smallspirocorner, &GIcon_smallspiroleft,
     918             :                                  &GIcon_smallscale,       &GIcon_smallrotate,
     919             :                                  &GIcon_smallflip,        &GIcon_smallskew,
     920             :                                  &GIcon_small3drotate,    &GIcon_smallperspective,
     921             :                                  &GIcon_smallrect,        &GIcon_smallpoly,
     922             :                                  &GIcon_smallelipse,      &GIcon_smallstar };
     923             : 
     924           0 : static int getSmallIconsHeight()
     925             : {
     926           0 :     return GIcon_smallpointer.u.image->height;
     927             : }
     928             : 
     929           0 : static int getToolbarWidth( CharView *cv ) 
     930             : {
     931           0 :     int cache = 0;
     932           0 :     if( !cache ) {
     933           0 :         GImage* (*buttons)[14][2] = (CVInSpiro(cv) ? spirobuttons : normbuttons);
     934           0 :         int i = 0;
     935             :         
     936           0 :         for ( i=0; buttons[0][i][0]; ++i ) {
     937           0 :             cache = MAX( cache, buttons[0][i][0]->u.image->width + buttons[0][i][1]->u.image->width );
     938             :         }
     939             :     }
     940           0 :     return cache;
     941             : }
     942             : 
     943           0 : static int getToolbarHeight( CharView *cv ) 
     944             : {
     945           0 :     int cache = 0;
     946           0 :     if( !cache ) {
     947           0 :         GImage* (*buttons)[14][2] = (CVInSpiro(cv) ? spirobuttons : normbuttons);
     948           0 :         int i = 0;
     949             :         
     950           0 :         for ( i=0; buttons[0][i][0]; ++i ) {
     951           0 :             cache += MAX( buttons[0][i][0]->u.image->height, buttons[0][i][1]->u.image->height );
     952             :         }
     953             :     }
     954           0 :     cache += getSmallIconsHeight() * 4;
     955           0 :     cache += 6;
     956           0 :     return cache;
     957             : }
     958             : 
     959             : 
     960             : typedef struct _IJ 
     961             : {
     962             :     int i;
     963             :     int j;
     964             : } IJ;
     965             : 
     966             : typedef void (*visitButtonsVisitor) ( CharView *cv,             // CharView passed to visitButtons()
     967             :                                       GImage* gimage, int mi,   // button we are visiting and adjusted 'i'
     968             :                                       int i, int j,             // i and j position of button (j is across 0,1) (i is down 0...11)
     969             :                                       int iconx, int icony,     // pixel where this button starts
     970             :                                       int selected,             // is this button the active tool
     971             :                                       void* udata );            // user data
     972             : 
     973             : 
     974             : /**
     975             :  * Visit every button in the toolbar calling the function 'v' with a
     976             :  * collection of interesting state data.
     977             :  */
     978           0 : static void visitButtons( CharView* cv, visitButtonsVisitor v, void* udata ) 
     979             : {
     980           0 :     GImage* (*buttons)[14][2] = (CVInSpiro(cv) ? spirobuttons : normbuttons);
     981             :     int i,j,sel,norm, mi;
     982           0 :     int tool = cv->cntrldown?cv->cb1_tool:cv->b1_tool;
     983           0 :     int icony = 1;
     984           0 :     for ( i=0; buttons[0][i][0]; ++i ) {
     985           0 :         int iconx = 1;
     986           0 :         for ( j=0; j<2 && buttons[0][i][j]; ++j ) {
     987             : 
     988           0 :             mi = i;
     989           0 :             sel = (tool == mi*2+j );
     990           0 :             if( buttons[0][mi][j] == &GIcon_rect && rectelipse
     991           0 :                 || buttons[0][mi][j] == &GIcon_poly && polystar )
     992             :             {
     993           0 :                 sel = (tool == (mi+1)*2+j );
     994           0 :                 mi+=2;
     995             :             }
     996             :             
     997           0 :             v( cv, buttons[sel][mi][j], mi, i, j, iconx, icony, sel, udata );
     998           0 :             iconx += buttons[sel][mi][j]->u.image->width;
     999             :         }
    1000           0 :         icony += MAX( buttons[0][i][0]->u.image->width, buttons[0][i][1]->u.image->width );
    1001             :     }
    1002           0 : }
    1003             : 
    1004             : typedef struct _getIJFromMouseVisitorData 
    1005             : {
    1006             :     int mx, my;
    1007             :     IJ ret;
    1008             : } getIJFromMouseVisitorData;
    1009             : 
    1010           0 : static void getIJFromMouseVisitor( CharView *cv, GImage* gimage,
    1011             :                                    int mi, int i, int j,
    1012             :                                    int iconx, int icony, int selected, void* udata )
    1013             : {
    1014           0 :     getIJFromMouseVisitorData* d = (getIJFromMouseVisitorData*)udata;
    1015           0 :     if( IS_IN_ORDER3( iconx, d->mx, iconx + gimage->u.image->width )
    1016           0 :         && IS_IN_ORDER3( icony, d->my, icony + gimage->u.image->height ))
    1017             :         {
    1018           0 :             d->ret.i = i;
    1019           0 :             d->ret.j = j;
    1020             :         }
    1021           0 : }
    1022             : 
    1023             : /**
    1024             :  * Get the i,j coordinates of the toolbar button that is under the
    1025             :  * mouse at mx,my or return -1,-1 if nothing is under the mouse.
    1026             :  */ 
    1027           0 : static IJ getIJFromMouse( CharView* cv, int mx, int my ) 
    1028             : {
    1029             :     getIJFromMouseVisitorData d;
    1030           0 :     d.mx = mx;
    1031           0 :     d.my = my;
    1032           0 :     d.ret.i = -1;
    1033           0 :     d.ret.j = -1;
    1034           0 :     visitButtons( cv, getIJFromMouseVisitor, &d );
    1035           0 :     return d.ret;
    1036             : }
    1037             : 
    1038             : /*
    1039             :  * This draws the three-dimensional relief on a button. It gets the dimensions from the button image.
    1040             :  */
    1041             : 
    1042           0 : void cvp_draw_relief(GWindow pixmap, GImage *iconimg, int iconx, int icony, int selected) {
    1043             :         extern Color cvbutton3dedgelightcol; // Default 0xe0e0e0.               
    1044             :         extern Color cvbutton3dedgedarkcol; // Default 0x707070.
    1045           0 :         int iconw = iconimg->u.image->width;
    1046           0 :         int iconh = iconimg->u.image->height;
    1047           0 :         int norm = !selected;
    1048             :         // Note: The original code placed the right and bottom fake relief
    1049             :         // outside of the button image area (offset by 25 instead of 24),
    1050             :         // but we are staying just inside the image area now.
    1051           0 :         GDrawDrawLine(pixmap,iconx,icony,iconx+iconw,icony,norm?cvbutton3dedgelightcol:cvbutton3dedgedarkcol);          
    1052           0 :         GDrawDrawLine(pixmap,iconx,icony,iconx,icony+iconh,norm?cvbutton3dedgelightcol:cvbutton3dedgedarkcol);          
    1053           0 :         GDrawDrawLine(pixmap,iconx,icony+iconh,iconx+iconw,icony+iconh,norm?cvbutton3dedgedarkcol:cvbutton3dedgelightcol);              
    1054           0 :         GDrawDrawLine(pixmap,iconx+iconw,icony,iconx+iconw,icony+iconh,norm?cvbutton3dedgedarkcol:cvbutton3dedgelightcol);
    1055           0 : }
    1056             : 
    1057             : 
    1058             : /**
    1059             :  * This visitor draws the actual image for each toolbar button
    1060             :  * The drawing is done to d->pixmap.
    1061             :  * icony is the max 
    1062             :  */
    1063             : typedef struct _ToolsExposeVisitorData 
    1064             : {
    1065             :     GWindow pixmap;
    1066             :     int     maxicony;       //< largest icony that the visitor saw
    1067             :     int     lastIconHeight; //< height of the last icon visited
    1068             : } ToolsExposeVisitorData;
    1069           0 : static void ToolsExposeVisitor( CharView *cv, GImage* gimage,
    1070             :                                 int mi, int i, int j,
    1071             :                                 int iconx, int icony, int selected, void* udata )
    1072             : {
    1073             :                 extern int cvbutton3d; // This comes from elsewhere.
    1074           0 :     ToolsExposeVisitorData* d = (ToolsExposeVisitorData*)udata;
    1075           0 :     GImage* (*buttons)[14][2] = (CVInSpiro(cv) ? spirobuttons : normbuttons);
    1076             : 
    1077             :                 // We draw the button image onto the toolbar image.
    1078           0 :                 GDrawDrawImage(d->pixmap,buttons[selected][mi][j],NULL,iconx,icony);
    1079             : 
    1080             :                 // We may need to draw relief, too.
    1081           0 :                 if (cvbutton3d > 0) cvp_draw_relief(d->pixmap, buttons[0][mi][j], iconx, icony, selected);
    1082             : 
    1083           0 :     d->maxicony = MAX( d->maxicony, icony );
    1084           0 :     d->lastIconHeight = buttons[selected][mi][j]->u.image->height;
    1085           0 : }
    1086             : 
    1087             : 
    1088           0 : static void ToolsExpose(GWindow pixmap, CharView *cv, GRect *r) {
    1089             :     GRect old;
    1090             :     static const unichar_t _Mouse[][9] = {
    1091             :             { 'M', 's', 'e', '1',  '\0' },
    1092             :             { '^', 'M', 's', 'e', '1',  '\0' },
    1093             :             { 'M', 's', 'e', '2',  '\0' },
    1094             :             { '^', 'M', 's', 'e', '2',  '\0' }};
    1095             :     int i,j,sel,norm, mi;
    1096           0 :     int tool = cv->cntrldown?cv->cb1_tool:cv->b1_tool;
    1097           0 :     int dither = GDrawSetDither(NULL,false);
    1098             :     GRect temp;
    1099           0 :     int canspiro = hasspiro(), inspiro = canspiro && cv->b.sc->inspiro;
    1100           0 :     GImage* (*buttons)[14][2] = (inspiro ? spirobuttons : normbuttons);
    1101           0 :     GImage **smalls = inspiro ? spirosmalls : normsmalls;
    1102             : 
    1103           0 :     normbuttons[0][3][1] = canspiro ? &GIcon_spiroup : &GIcon_spirodisabled;
    1104             : 
    1105           0 :     GDrawPushClip(pixmap,r,&old);
    1106           0 :     GDrawFillRect(pixmap,r,GDrawGetDefaultBackground(NULL));
    1107           0 :     GDrawSetLineWidth(pixmap,0);
    1108             : 
    1109             :     ToolsExposeVisitorData d;
    1110           0 :     d.pixmap = pixmap;
    1111           0 :     d.maxicony = 0;
    1112           0 :     visitButtons( cv, ToolsExposeVisitor, &d );
    1113           0 :     int bottomOfMainIconsY = d.maxicony + d.lastIconHeight;
    1114             :     
    1115             :     
    1116           0 :     GDrawSetFont(pixmap,toolsfont);
    1117           0 :     temp.x = 52-16;
    1118           0 :     temp.y = bottomOfMainIconsY;
    1119           0 :     temp.width = 16;
    1120           0 :     temp.height = 4*12;
    1121           0 :     GDrawFillRect(pixmap,&temp,GDrawGetDefaultBackground(NULL));
    1122           0 :     for ( j=0; j<4; ++j ) {
    1123           0 :         GDrawDrawText(pixmap,2,bottomOfMainIconsY+j*getSmallIconsHeight()+10,
    1124           0 :                       (unichar_t *) _Mouse[j],-1,GDrawGetDefaultForeground(NULL));
    1125           0 :         if ( (&cv->b1_tool)[j]!=cvt_none && smalls[(&cv->b1_tool)[j]])
    1126           0 :             GDrawDrawImage(pixmap,smalls[(&cv->b1_tool)[j]],NULL,52-16,bottomOfMainIconsY+j*getSmallIconsHeight());
    1127             :     }
    1128           0 :     GDrawPopClip(pixmap,&old);
    1129           0 :     GDrawSetDither(NULL,dither);
    1130           0 : }
    1131             : 
    1132           0 : int TrueCharState(GEvent *event) {
    1133           0 :     int bit = 0;
    1134             :     /* X doesn't set the state until after the event. I want the state to */
    1135             :     /*  reflect whatever key just got depressed/released */
    1136           0 :     int keysym = event->u.chr.keysym;
    1137             : 
    1138           0 :     if ( keysym == GK_Caps_Lock || keysym == GK_Shift_Lock ) {
    1139             :         static int set_on_last_down = false;
    1140             :         /* caps lock is sticky and doesn't work like the other modifiers */
    1141             :         /* but it is even worse. the bit seems to be set on key down, but */
    1142             :         /* unset on key up. In other words on key up, the bit will always */
    1143             :         /* set and we have no idea which way it will go. So we guess, and */
    1144             :         /* if they haven't messed with the key outside ff we should be right */
    1145           0 :         if ( event->type == et_char ) {
    1146           0 :             set_on_last_down = (event->u.chr.state ^ ksm_capslock)& ksm_capslock;
    1147           0 : return( event->u.chr.state ^ ksm_capslock );
    1148           0 :         } else if ( !(event->u.chr.state & ksm_capslock) || set_on_last_down )
    1149           0 : return( event->u.chr.state );
    1150             :         else
    1151           0 : return( event->u.chr.state & ~ksm_capslock );
    1152             :     }
    1153             : 
    1154           0 :     if ( keysym == GK_Meta_L || keysym == GK_Meta_R ||
    1155           0 :             keysym == GK_Alt_L || keysym == GK_Alt_R )
    1156           0 :         bit = ksm_meta;
    1157           0 :     else if ( keysym == GK_Shift_L || keysym == GK_Shift_R )
    1158           0 :         bit = ksm_shift;
    1159           0 :     else if ( keysym == GK_Control_L || keysym == GK_Control_R )
    1160           0 :         bit = ksm_control;
    1161           0 :     else if ( keysym == GK_Super_L || keysym == GK_Super_R )
    1162           0 :         bit = ksm_super;
    1163           0 :     else if ( keysym == GK_Hyper_L || keysym == GK_Hyper_R )
    1164           0 :         bit = ksm_hyper;
    1165             :     else
    1166           0 : return( event->u.chr.state );
    1167             : 
    1168           0 :     if ( event->type == et_char )
    1169           0 : return( event->u.chr.state | bit );
    1170             :     else
    1171           0 : return( event->u.chr.state & ~bit );
    1172             : }
    1173             : 
    1174           0 : void CVToolsSetCursor(CharView *cv, int state, char *device) {
    1175             :     int shouldshow;
    1176             :     int cntrl;
    1177             : 
    1178           0 :     if ( tools[0] == ct_pointer ) {
    1179           0 :         tools[cvt_pointer] = ct_mypointer;
    1180           0 :         tools[cvt_magnify] = ct_magplus;
    1181           0 :         tools[cvt_freehand] = ct_pencil;
    1182           0 :         tools[cvt_hand] = ct_myhand;
    1183           0 :         tools[cvt_curve] = ct_circle;
    1184           0 :         tools[cvt_hvcurve] = ct_hvcircle;
    1185           0 :         tools[cvt_corner] = ct_square;
    1186           0 :         tools[cvt_tangent] = ct_triangle;
    1187           0 :         tools[cvt_pen] = ct_pen;
    1188           0 :         tools[cvt_knife] = ct_knife;
    1189           0 :         tools[cvt_ruler] = ct_ruler;
    1190           0 :         tools[cvt_scale] = ct_scale;
    1191           0 :         tools[cvt_flip] = ct_flip;
    1192           0 :         tools[cvt_rotate] = ct_rotate;
    1193           0 :         tools[cvt_skew] = ct_skew;
    1194           0 :         tools[cvt_3d_rotate] = ct_3drotate;
    1195           0 :         tools[cvt_perspective] = ct_perspective;
    1196           0 :         tools[cvt_rect] = ct_rect;
    1197           0 :         tools[cvt_poly] = ct_poly;
    1198           0 :         tools[cvt_elipse] = ct_elipse;
    1199           0 :         tools[cvt_star] = ct_star;
    1200           0 :         tools[cvt_minify] = ct_magminus;
    1201           0 :         memcpy(spirotools,tools,sizeof(tools));
    1202           0 :         spirotools[cvt_spirog2] = ct_g2circle;
    1203           0 :         spirotools[cvt_spiroleft] = ct_spiroleft;
    1204           0 :         spirotools[cvt_spiroright] = ct_spiroright;
    1205             :     }
    1206             : 
    1207           0 :     shouldshow = cvt_none;
    1208           0 :     if ( cv->active_tool!=cvt_none )
    1209           0 :         shouldshow = cv->active_tool;
    1210           0 :     else if ( cv->pressed_display!=cvt_none )
    1211           0 :         shouldshow = cv->pressed_display;
    1212           0 :     else if ( device==NULL || strcmp(device,"Mouse1")==0 ) {
    1213           0 :         if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button4))
    1214           0 :             shouldshow = cvt_magnify;
    1215           0 :         else if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button5))
    1216           0 :             shouldshow = cvt_minify;
    1217           0 :         else if ( (state&ksm_control) && (state&(ksm_button2|ksm_super)) )
    1218           0 :             shouldshow = cv->cb2_tool;
    1219           0 :         else if ( (state&(ksm_button2|ksm_super)) )
    1220           0 :             shouldshow = cv->b2_tool;
    1221           0 :         else if ( (state&ksm_control) )
    1222           0 :             shouldshow = cv->cb1_tool;
    1223             :         else
    1224           0 :             shouldshow = cv->b1_tool;
    1225           0 :     } else if ( strcmp(device,"eraser")==0 )
    1226           0 :         shouldshow = cv->er_tool;
    1227           0 :     else if ( strcmp(device,"stylus")==0 ) {
    1228           0 :         if ( (state&(ksm_button2|ksm_control|ksm_super)) )
    1229           0 :             shouldshow = cv->s2_tool;
    1230             :         else
    1231           0 :             shouldshow = cv->s1_tool;
    1232             :     }
    1233           0 :     if ( shouldshow==cvt_magnify && (state&ksm_meta))
    1234           0 :         shouldshow = cvt_minify;
    1235           0 :     if ( shouldshow!=cv->showing_tool ) {
    1236           0 :         CPEndInfo(cv);
    1237           0 :         if ( cv->b.sc->inspiro && hasspiro()) {
    1238           0 :             GDrawSetCursor(cv->v,spirotools[shouldshow]);
    1239           0 :             if ( cvtools!=NULL )        /* Might happen if window owning docked palette destroyed */
    1240           0 :                 GDrawSetCursor(cvtools,spirotools[shouldshow]);
    1241             :         } else {
    1242           0 :             GDrawSetCursor(cv->v,tools[shouldshow]);
    1243           0 :             if ( cvtools!=NULL )        /* Might happen if window owning docked palette destroyed */
    1244           0 :                 GDrawSetCursor(cvtools,tools[shouldshow]);
    1245             :         }
    1246           0 :         cv->showing_tool = shouldshow;
    1247             :     }
    1248             : 
    1249           0 :     if ( device==NULL || strcmp(device,"stylus")==0 ) {
    1250           0 :         cntrl = (state&ksm_control)?1:0;
    1251           0 :         if ( device!=NULL && (state&ksm_button2))
    1252           0 :             cntrl = true;
    1253           0 :         if ( cntrl != cv->cntrldown ) {
    1254           0 :             cv->cntrldown = cntrl;
    1255           0 :             GDrawRequestExpose(cvtools,NULL,false);
    1256             :         }
    1257             :     }
    1258           0 : }
    1259             : 
    1260           0 : static int CVCurrentTool(CharView *cv, GEvent *event) {
    1261           0 :     if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"eraser")==0 )
    1262           0 : return( cv->er_tool );
    1263           0 :     else if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"stylus")==0 ) {
    1264           0 :         if ( event->u.mouse.button==2 )
    1265             :             /* Only thing that matters is touch which maps to button 1 */;
    1266           0 :         else if ( cv->had_control )
    1267           0 : return( cv->s2_tool );
    1268             :         else
    1269           0 : return( cv->s1_tool );
    1270             :     }
    1271           0 :     if ( cv->had_control && event->u.mouse.button==2 )
    1272           0 : return( cv->cb2_tool );
    1273           0 :     else if ( event->u.mouse.button==2 )
    1274           0 : return( cv->b2_tool );
    1275           0 :     else if ( cv->had_control ) {
    1276           0 : return( cv->cb1_tool );
    1277             :     } else {
    1278           0 : return( cv->b1_tool );
    1279             :     }
    1280             : }
    1281             : 
    1282           0 : static void SCCheckForSSToOptimize(SplineChar *sc, SplineSet *ss,int order2) {
    1283             : 
    1284           0 :     for ( ; ss!=NULL ; ss = ss->next ) {
    1285           0 :         if ( ss->beziers_need_optimizer ) {
    1286           0 :             SplineSetAddExtrema(sc,ss,ae_only_good,sc->parent->ascent+sc->parent->descent);
    1287           0 :             ss->beziers_need_optimizer = false;
    1288             :         }
    1289           0 :         if ( order2 && ss->first->next!=NULL && !ss->first->next->order2 ) {
    1290           0 :             SplineSet *temp = SSttfApprox(ss), foo;
    1291           0 :             foo = *ss;
    1292           0 :             ss->first = temp->first; ss->last = temp->last;
    1293           0 :             temp->first = foo.first; temp->last = foo.last;
    1294           0 :             SplinePointListFree(temp);
    1295             :         }
    1296             :     }
    1297           0 : }
    1298             : 
    1299           0 : static void CVChangeSpiroMode(CharView *cv) {
    1300           0 :     if ( hasspiro() ) {
    1301           0 :         cv->b.sc->inspiro = !cv->b.sc->inspiro;
    1302           0 :         cv->showing_tool = cvt_none;
    1303           0 :         CVClearSel(cv);
    1304           0 :         if ( !cv->b.sc->inspiro )
    1305           0 :             SCCheckForSSToOptimize(cv->b.sc,cv->b.layerheads[cv->b.drawmode]->splines,
    1306           0 :                     cv->b.layerheads[cv->b.drawmode]->order2);
    1307           0 :         GDrawRequestExpose(cvtools,NULL,false);
    1308           0 :         SCUpdateAll(cv->b.sc);
    1309             :     } else
    1310             : #ifdef _NO_LIBSPIRO
    1311             :         ff_post_error(_("You may not use spiros"),_("This version of fontforge was not linked with the spiro library, so you may not use them."));
    1312             : #else
    1313           0 :         ff_post_error(_("You may not use spiros"),_("FontForge was unable to load libspiro, spiros are not available for use."));
    1314             : #endif
    1315           0 : }
    1316             : 
    1317             : char* HKTextInfoToUntranslatedTextFromTextInfo( GTextInfo* ti ); // From ../gdraw/gmenu.c.
    1318             : 
    1319             : 
    1320           0 : static void ToolsMouse(CharView *cv, GEvent *event) {
    1321           0 :     IJ ij = getIJFromMouse( cv, event->u.mouse.x, event->u.mouse.y );
    1322           0 :     int i = ij.i;
    1323           0 :     int j = ij.j;
    1324           0 :     int mi = i;
    1325             :     int pos;
    1326           0 :     int isstylus = event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"stylus")==0;
    1327           0 :     int styluscntl = isstylus && (event->u.mouse.state&0x200);
    1328             :     static int settings[2];
    1329             : 
    1330           0 :     if( j==-1 || i==-1 )
    1331           0 :         return;
    1332             :     
    1333           0 :     if(j >= 2)
    1334           0 :         return;                 /* If the wm gave me a window the wrong size */
    1335             : 
    1336             : 
    1337           0 :     if ( i==(cvt_rect)/2 ) {
    1338           0 :         int current = CVCurrentTool(cv,event);
    1339           0 :         int changed = false;
    1340           0 :         if ( event->type == et_mousedown && event->u.mouse.clicks>=2 ) {
    1341           0 :             rectelipse = settings[0];
    1342           0 :             polystar = settings[1];
    1343           0 :         } else if ( event->type == et_mousedown ) {
    1344           0 :             settings[0] = rectelipse; settings[1] = polystar;
    1345             :             /* A double click will change the type twice, which leaves it where it was, which is desired */
    1346           0 :             if ( j==0 && ((!rectelipse && current==cvt_rect) || (rectelipse && current==cvt_elipse)) ) {
    1347           0 :                 rectelipse = !rectelipse;
    1348           0 :                 changed = true;
    1349           0 :             } else if (j==1 && ((!polystar && current==cvt_poly) || (polystar && current==cvt_star)) ) {
    1350           0 :                 polystar = !polystar;
    1351           0 :                 changed = true;
    1352             :             }
    1353           0 :             if ( changed ) {
    1354           0 :                 SavePrefs(true);
    1355           0 :                 GDrawRequestExpose(cvtools,NULL,false);
    1356             :             }
    1357             :         }
    1358           0 :         if ( (j==0 && rectelipse) || (j==1 && polystar) )
    1359           0 :             ++mi;
    1360             :     }
    1361           0 :     pos = mi*2 + j;
    1362           0 :     GGadgetEndPopup();
    1363             :     /* we have two fewer buttons than commands as two bottons each control two commands */
    1364           0 :     if ( pos<0 || pos>=cvt_max )
    1365           0 :         pos = cvt_none;
    1366           0 :     if ( event->type == et_mousedown ) {
    1367           0 :         if ( isstylus && event->u.mouse.button==2 )
    1368             :             /* Not a real button press, only touch counts. This is a modifier */;
    1369           0 :         else if ( pos==cvt_spiro ) {
    1370           0 :             CVChangeSpiroMode(cv);
    1371             :             /* This is just a button that indicates a state */
    1372             :         } else {
    1373           0 :             cv->pressed_tool = cv->pressed_display = pos;
    1374           0 :             cv->had_control = ((event->u.mouse.state&ksm_control) || styluscntl)?1:0;
    1375           0 :             event->u.mouse.state |= (1<<(7+event->u.mouse.button));
    1376             :         }
    1377           0 :         if ( event->u.mouse.clicks>=2 &&
    1378           0 :                 (pos/2 == cvt_scale/2 || pos/2 == cvt_rotate/2 || pos == cvt_3d_rotate ))
    1379           0 :             CVDoTransform(cv,pos);
    1380           0 :     } else if ( event->type == et_mousemove ) {
    1381           0 :         if ( cv->pressed_tool==cvt_none && pos!=cvt_none ) {
    1382             :             /* Not pressed */
    1383           0 :             char *msg = _(popupsres[pos]);
    1384           0 :             if ( cv->b.sc->inspiro && hasspiro()) {
    1385           0 :                 if ( pos==cvt_spirog2 )
    1386           0 :                     msg = _("Add a g2 curve point");
    1387           0 :                 else if ( pos==cvt_spiroleft )
    1388           0 :                     msg = _("Add a prev constraint point (sometimes like a tangent)");
    1389           0 :                 else if ( pos==cvt_spiroright )
    1390           0 :                     msg = _("Add a next constraint point (sometimes like a tangent)");
    1391             :             }
    1392             :             // We want to display the hotkey for the key in question if possible.
    1393           0 :             char * mininame = HKTextInfoToUntranslatedTextFromTextInfo(&cvtoollist[pos].ti);
    1394           0 :             char * menuname = NULL;
    1395           0 :             Hotkey* toolhotkey = NULL;
    1396           0 :             if (mininame != NULL) {
    1397           0 :               if (asprintf(&menuname, "%s%s", "Point.Tools.", mininame) != -1) {
    1398           0 :                 toolhotkey = hotkeyFindByMenuPath(cv->gw, menuname);
    1399           0 :                 free(menuname); menuname = NULL;
    1400             :               }
    1401           0 :               free(mininame); mininame = NULL;
    1402             :             }
    1403           0 :             char * finalmsg = NULL;
    1404           0 :             if (toolhotkey != NULL && asprintf(&finalmsg, "%s (%s)", msg, toolhotkey->text) != -1) {
    1405           0 :               GGadgetPreparePopup8(cvtools, finalmsg);
    1406           0 :               free(finalmsg); finalmsg = NULL;
    1407           0 :             } else GGadgetPreparePopup8(cvtools, msg); // That's what we were doing before. Much simpler.
    1408           0 :         } else if ( pos!=cv->pressed_tool || cv->had_control != (((event->u.mouse.state&ksm_control) || styluscntl)?1:0) )
    1409           0 :             cv->pressed_display = cvt_none;
    1410             :         else
    1411           0 :             cv->pressed_display = cv->pressed_tool;
    1412           0 :     } else if ( event->type == et_mouseup ) {
    1413           0 :         if ( pos==cvt_freehand && event->u.mouse.clicks==2 ) {
    1414           0 :             FreeHandStrokeDlg(&expand);
    1415           0 :         } else if ( pos==cvt_pointer && event->u.mouse.clicks==2 ) {
    1416           0 :             PointerDlg(cv);
    1417           0 :         } else if ( pos==cvt_ruler && event->u.mouse.clicks==2 ) {
    1418           0 :             RulerDlg(cv);
    1419           0 :         } else if ( i==cvt_rect/2 && event->u.mouse.clicks==2 ) {
    1420           0 :             ((j==0)?CVRectElipse:CVPolyStar)(cv);
    1421           0 :             mi = i;
    1422           0 :             if ( (j==0 && rectelipse) || (j==1 && polystar) )
    1423           0 :                 ++mi;
    1424           0 :             pos = mi*2 + j;
    1425           0 :             cv->pressed_tool = cv->pressed_display = pos;
    1426             :         }
    1427           0 :         if ( pos!=cv->pressed_tool || cv->had_control != (((event->u.mouse.state&ksm_control)||styluscntl)?1:0) )
    1428           0 :             cv->pressed_tool = cv->pressed_display = cvt_none;
    1429             :         else {
    1430           0 :             if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"eraser")==0 )
    1431           0 :                 cv->er_tool = pos;
    1432           0 :             else if ( isstylus ) {
    1433           0 :                 if ( event->u.mouse.button==2 )
    1434             :                     /* Only thing that matters is touch which maps to button 1 */;
    1435           0 :                 else if ( cv->had_control )
    1436           0 :                     cv->s2_tool = pos;
    1437             :                 else
    1438           0 :                     cv->s1_tool = pos;
    1439           0 :             } else if ( cv->had_control && event->u.mouse.button==2 )
    1440           0 :                 cv->cb2_tool = cv_cb2_tool = pos;
    1441           0 :             else if ( event->u.mouse.button==2 )
    1442           0 :                 cv->b2_tool = cv_b2_tool = pos;
    1443           0 :             else if ( cv->had_control ) {
    1444           0 :                 cv->cb1_tool = cv_cb1_tool = pos;
    1445             :             } else {
    1446           0 :                 cv->b1_tool = cv_b1_tool = pos;
    1447             :             }
    1448           0 :             SavePrefs(true);
    1449           0 :             cv->pressed_tool = cv->pressed_display = cvt_none;
    1450             :         }
    1451           0 :         GDrawRequestExpose(cvtools,NULL,false);
    1452           0 :         event->u.chr.state &= ~(1<<(7+event->u.mouse.button));
    1453             :     }
    1454           0 :     CVToolsSetCursor(cv,event->u.mouse.state,event->u.mouse.device);
    1455             : }
    1456             : 
    1457           0 : static void PostCharToWindow(GWindow to, GEvent *e) {
    1458             :     GPoint p;
    1459             : 
    1460           0 :     p.x = e->u.chr.x; p.y = e->u.chr.y;
    1461           0 :     GDrawTranslateCoordinates(e->w,to,&p);
    1462           0 :     e->u.chr.x = p.x; e->u.chr.y = p.y;
    1463           0 :     e->w = to;
    1464           0 :     GDrawPostEvent(e);
    1465           0 : }
    1466             : 
    1467           0 : static int cvtools_e_h(GWindow gw, GEvent *event) {
    1468           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
    1469             : 
    1470           0 :     if ( event->type==et_destroy ) {
    1471           0 :         cvtools = NULL;
    1472           0 : return( true );
    1473             :     }
    1474             : 
    1475           0 :     if ( cv==NULL )
    1476           0 : return( true );
    1477             : 
    1478           0 :     GGadgetPopupExternalEvent(event);
    1479           0 :     switch ( event->type ) {
    1480             :       case et_expose:
    1481           0 :         ToolsExpose(gw,cv,&event->u.expose.rect);
    1482           0 :       break;
    1483             :       case et_mousedown:
    1484           0 :         ToolsMouse(cv,event);
    1485           0 :       break;
    1486             :       case et_mousemove:
    1487           0 :         ToolsMouse(cv,event);
    1488           0 :       break;
    1489             :       case et_mouseup:
    1490           0 :         ToolsMouse(cv,event);
    1491           0 :       break;
    1492             :       case et_crossing:
    1493           0 :         cv->pressed_display = cvt_none;
    1494           0 :         CVToolsSetCursor(cv,event->u.mouse.state,NULL);
    1495           0 :       break;
    1496             :       case et_char: case et_charup:
    1497           0 :         if ( cv->had_control != ((event->u.chr.state&ksm_control)?1:0) )
    1498           0 :             cv->pressed_display = cvt_none;
    1499           0 :         PostCharToWindow(cv->gw,event);
    1500           0 :       break;
    1501             :       case et_close:
    1502           0 :         GDrawSetVisible(gw,false);
    1503           0 :       break;
    1504             :     }
    1505           0 : return( true );
    1506             : }
    1507             : 
    1508           0 : GWindow CVMakeTools(CharView *cv) {
    1509             :     GRect r;
    1510             :     GWindowAttrs wattrs;
    1511             :     FontRequest rq;
    1512             : 
    1513           0 :     if ( cvtools!=NULL )
    1514           0 : return( cvtools );
    1515             : 
    1516           0 :     memset(&wattrs,0,sizeof(wattrs));
    1517           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
    1518           0 :     wattrs.event_masks = -1;
    1519           0 :     wattrs.cursor = ct_mypointer;
    1520           0 :     wattrs.positioned = true;
    1521           0 :     wattrs.is_dlg = true;
    1522           0 :     wattrs.utf8_window_title = _("Tools");
    1523             : 
    1524           0 :     r.width = getToolbarWidth(cv); r.height = getToolbarHeight(cv);
    1525           0 :     if ( cvtoolsoff.x==-9999 ) {
    1526           0 :         cvtoolsoff.x = -r.width-6; cvtoolsoff.y = cv->mbh+20;
    1527             :     }
    1528           0 :     r.x = cvtoolsoff.x; r.y = cvtoolsoff.y;
    1529           0 :     if ( palettes_docked )
    1530           0 :         r.x = r.y = 0;
    1531           0 :     cvtools = CreatePalette( cv->gw, &r, cvtools_e_h, NULL, &wattrs, cv->v );
    1532             : 
    1533           0 :     if ( GDrawRequestDeviceEvents(cvtools,input_em_cnt,input_em)>0 ) {
    1534             :         /* Success! They've got a wacom tablet */
    1535             :     }
    1536             : 
    1537           0 :     if ( toolsfont==NULL ) {
    1538           0 :         memset(&rq,0,sizeof(rq));
    1539           0 :         rq.utf8_family_name = SANS_UI_FAMILIES;
    1540           0 :         rq.point_size = -10;
    1541           0 :         rq.weight = 400;
    1542           0 :         toolsfont = GDrawInstanciateFont(NULL,&rq);
    1543           0 :         toolsfont = GResourceFindFont("ToolsPalette.Font",toolsfont);
    1544             :     }
    1545             : 
    1546           0 :     if ( cvvisible[1])
    1547           0 :         GDrawSetVisible(cvtools,true);
    1548           0 : return( cvtools );
    1549             : }
    1550             : 
    1551             : 
    1552             :     /* ********************************************************* */
    1553             :     /* ******************  Layers Palette  ********************* */
    1554             :     /* ********************************************************* */
    1555             : 
    1556             : 
    1557             : 
    1558             : /* Create a layer thumbnail */
    1559           0 : static BDFChar *BDFCharFromLayer(SplineChar *sc,int layer) {
    1560             :     SplineChar dummy;
    1561           0 :     memset(&dummy,0,sizeof(dummy));
    1562           0 :     dummy.layer_cnt = 2;
    1563           0 :     dummy.layers = sc->layers+layer-1;
    1564           0 :     dummy.parent = sc->parent;
    1565           0 : return( SplineCharAntiAlias(&dummy,ly_fore,24,4));
    1566             : }
    1567             : 
    1568             : /**
    1569             :  *  \brief Recalculate the number of visible layers,
    1570             :  *         reposition the visibility checkboxes, and
    1571             :  *         if requested, reposition/resize the scrollbar.
    1572             :  *
    1573             :  *  \param [in] cv The charview
    1574             :  */
    1575           0 : static void CVLayers2Reflow(CharView *cv, bool resize) {
    1576             :     extern int _GScrollBar_Width;
    1577             :     GGadget *scrollbar;
    1578             :     GRect cvl2size;
    1579             : 
    1580           0 :     GDrawGetSize(cvlayers2, &cvl2size);
    1581             :     // Minus 2 because we always have the 'Guide' and 'Back' entries
    1582           0 :     layer2.visible_layers = (cvl2size.height - layer2.header_height - 2 * CV_LAYERS2_LINE_HEIGHT) / CV_LAYERS2_LINE_HEIGHT;
    1583           0 :     if (layer2.visible_layers < 0) {
    1584           0 :         layer2.visible_layers = 0;
    1585             :     }
    1586             : 
    1587             :     // Reposition the visibility checkboxes
    1588           0 :     int num_potentially_visible = 2 + layer2.visible_layers + 1;
    1589           0 :     if (num_potentially_visible > layer2.current_layers){
    1590           0 :         num_potentially_visible = layer2.current_layers;
    1591             :     }
    1592           0 :     for (int i = 2, first_visible = 2 + layer2.offtop; i < layer2.current_layers; i++) {
    1593           0 :         GGadget *vis = GWidgetGetControl(cvlayers2, CID_VBase + i - 1);
    1594           0 :         if (vis == NULL) {
    1595           0 :             break;
    1596             :         }
    1597           0 :         if (i >= first_visible && (i - layer2.offtop) < num_potentially_visible) {
    1598           0 :             GGadgetMove(vis, 5, layer2.header_height + (i - layer2.offtop) * CV_LAYERS2_LINE_HEIGHT);
    1599           0 :             GGadgetSetVisible(vis, true);
    1600             :         } else {
    1601           0 :             GGadgetSetVisible(vis, false);
    1602             :         }
    1603             :     }
    1604             : 
    1605           0 :     if (!resize) {
    1606           0 :         return;
    1607             :     }
    1608             : 
    1609           0 :     scrollbar = GWidgetGetControl(cvlayers2, CID_SB);
    1610             :     // Check if we need the scrollbar or not.
    1611           0 :     if (layer2.current_layers - 2 <= layer2.visible_layers || layer2.visible_layers <= 0) {
    1612           0 :         GGadgetSetVisible(scrollbar, false);
    1613           0 :         layer2.sb_start = cvl2size.width;
    1614           0 :         layer2.offtop = 0;
    1615             :     } else {
    1616           0 :         layer2.sb_start = cvl2size.width - GDrawPointsToPixels(cv->gw, _GScrollBar_Width);
    1617           0 :         GGadgetMove(scrollbar, layer2.sb_start, 0);
    1618           0 :         GGadgetResize(scrollbar, GDrawPointsToPixels(cv->gw, _GScrollBar_Width), cvl2size.height);
    1619           0 :         GGadgetSetVisible(scrollbar, true);
    1620             : 
    1621           0 :         GScrollBarSetBounds(scrollbar, 0, layer2.current_layers - 2, layer2.visible_layers);
    1622           0 :         GScrollBarSetPos(scrollbar, layer2.offtop);
    1623             :     }
    1624             : 
    1625           0 :     GDrawRequestExpose(cvlayers2, NULL, false);
    1626             : }
    1627             : 
    1628             : /* Update the type3 layers palette to the given character view */
    1629           0 : static void CVLayers2Set(CharView *cv) {
    1630             :     int i, top;
    1631             : 
    1632           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers2,CID_VFore),cv->showfore);
    1633           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers2,CID_VBack),cv->showback[0]&1);
    1634           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers2,CID_VGrid),cv->showgrids);
    1635             : 
    1636           0 :     int ly = 0;
    1637             :     // We want to look at the unhandled layers.
    1638           0 :     if (ly <= ly_back) ly = ly_back + 1;
    1639           0 :     if (ly <= ly_fore) ly = ly_fore + 1;
    1640           0 :     if (ly <= ly_grid) ly = ly_grid + 1;
    1641           0 :     while (ly < cv->b.sc->parent->layer_cnt) {
    1642           0 :       GGadget *tmpgadget = GWidgetGetControl(cvlayers2, CID_VBase + ly);
    1643           0 :       if (tmpgadget != NULL) {
    1644             :         // We set a low cap on the number of layers provisioned with check boxes for safety.
    1645             :         // So it is important to check that this exists.
    1646           0 :         GGadgetSetChecked(tmpgadget, cv->showback[ly>>5]&(1<<(ly&31)));
    1647             :       }
    1648           0 :       ly ++;
    1649             :     }
    1650             : 
    1651             :          /* set old to NULL */
    1652           0 :     layer2.offtop = 0;
    1653           0 :     for ( i=2; i<layer2.current_layers; ++i ) {
    1654           0 :         BDFCharFree(layer2.layers[i]);
    1655           0 :         layer2.layers[i]=NULL;
    1656             :     }
    1657             : 
    1658             :          /* reallocate enough space if necessary */
    1659           0 :     if ( cv->b.sc->layer_cnt+1>=layer2.max_layers ) {
    1660           0 :         top = cv->b.sc->layer_cnt+10;
    1661           0 :         if ( layer2.layers==NULL )
    1662           0 :             layer2.layers = calloc(top,sizeof(BDFChar *));
    1663             :         else {
    1664           0 :             layer2.layers = realloc(layer2.layers,top*sizeof(BDFChar *));
    1665           0 :             for ( i=layer2.current_layers; i<top; ++i )
    1666           0 :                 layer2.layers[i] = NULL;
    1667             :         }
    1668           0 :         layer2.max_layers = top;
    1669             :     }
    1670           0 :     layer2.current_layers = cv->b.sc->layer_cnt+1;
    1671           0 :     for ( i=ly_fore; i<cv->b.sc->layer_cnt; ++i )
    1672           0 :         layer2.layers[i+1] = BDFCharFromLayer(cv->b.sc,i);
    1673           0 :     layer2.active = CVLayer(&cv->b)+1;
    1674             : 
    1675           0 :     CVLayers2Reflow(cv, true);
    1676           0 : }
    1677             : 
    1678           0 : static void Layers2Expose(CharView *cv,GWindow pixmap,GEvent *event) {
    1679             :     int i, ll;
    1680             :     const char *str;
    1681             :     GRect r, oldclip;
    1682             :     struct _GImage base;
    1683             :     GImage gi;
    1684           0 :     int as = (24*cv->b.sc->parent->ascent)/(cv->b.sc->parent->ascent+cv->b.sc->parent->descent);
    1685             :     int leftOffset, layerCount;
    1686             : 
    1687           0 :     if ( event->u.expose.rect.y+event->u.expose.rect.height<layer2.header_height )
    1688           0 : return;
    1689             : 
    1690             :     // Calculate the left offset (from the checkboxes)
    1691           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers2, CID_VGrid), &r);
    1692           0 :     leftOffset = r.x + r.width;
    1693             :     // Compute the drawable area and clip to it.
    1694           0 :     GDrawGetSize(cvlayers2, &r);
    1695           0 :     r.x = leftOffset;
    1696           0 :     r.width = layer2.sb_start - r.x;
    1697           0 :     r.y = layer2.header_height;
    1698           0 :     r.height = r.height - layer2.header_height;
    1699           0 :     GDrawPushClip(pixmap, &r, &oldclip);
    1700           0 :     GDrawFillRect(pixmap,&r,GDrawGetDefaultBackground(NULL));
    1701             : 
    1702           0 :     GDrawSetDither(NULL, false);        /* on 8 bit displays we don't want any dithering */
    1703             : 
    1704           0 :     memset(&gi,0,sizeof(gi));
    1705           0 :     memset(&base,0,sizeof(base));
    1706           0 :     gi.u.image = &base;
    1707           0 :     base.image_type = it_index;
    1708           0 :     base.clut = layer2.clut;
    1709           0 :     base.trans = -1;
    1710           0 :     GDrawSetFont(pixmap,layer2.font);
    1711             : 
    1712             :     // +2 for the defaults, +1 to show one extra (could be partially visible)
    1713           0 :     layerCount = layer2.visible_layers + 2 + 1;
    1714           0 :     if (layerCount > layer2.current_layers) {
    1715           0 :         layerCount = layer2.current_layers;
    1716             :     }
    1717           0 :     for (i = 0; i < layerCount; ++i) {
    1718           0 :         ll = i<2 ? i : i+layer2.offtop;
    1719           0 :         if ( ll==layer2.active ) {
    1720           0 :             r.x = leftOffset;
    1721           0 :             r.width = layer2.sb_start - r.x;
    1722           0 :             r.y = layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT;
    1723           0 :             r.height = CV_LAYERS2_LINE_HEIGHT;
    1724           0 :             GDrawFillRect(pixmap,&r,GDrawGetDefaultForeground(NULL));
    1725             :         }
    1726           0 :         GDrawDrawLine(pixmap, r.x, layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT,
    1727           0 :                       r.x + r.width, layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT,
    1728             :                 0x808080);
    1729           0 :         if ( i==0 || i==1 ) {
    1730           0 :             str = i==0?_("Guide") : _("Back");
    1731           0 :             GDrawDrawText8(pixmap, r.x + 2, layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT + (CV_LAYERS2_LINE_HEIGHT - 12) / 2 + 12,
    1732           0 :                     (char *) str,-1,ll==layer2.active?0xffffff:GDrawGetDefaultForeground(NULL));
    1733           0 :         } else if ( layer2.offtop+i>=layer2.current_layers ) {
    1734           0 :     break;
    1735           0 :         } else if ( layer2.layers[layer2.offtop+i]!=NULL ) {
    1736             : #if 0
    1737             :             // This is currently broken, and we do not have time to fix it.
    1738             :             BDFChar *bdfc = layer2.layers[layer2.offtop+i];
    1739             :             base.data = bdfc->bitmap;
    1740             :             base.bytes_per_line = bdfc->bytes_per_line;
    1741             :             base.width = bdfc->xmax-bdfc->xmin+1;
    1742             :             base.height = bdfc->ymax-bdfc->ymin+1;
    1743             :             GDrawDrawImage(pixmap,&gi,NULL,
    1744             :                     r.x+2+bdfc->xmin,
    1745             :                            layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT + as - bdfc->ymax);
    1746             : #else
    1747             :             // This logic comes from CVInfoDrawText.
    1748           0 :             const int layernamesz = 100;
    1749           0 :             char layername[layernamesz+1];
    1750           0 :             strncpy(layername,_("Guide"),layernamesz);
    1751           0 :             int idx = layer2.offtop+i-1;
    1752           0 :             if(idx >= 0 && idx < cv->b.sc->parent->layer_cnt) {
    1753           0 :               strncpy(layername,cv->b.sc->parent->layers[idx].name,layernamesz);
    1754             :             } else {
    1755           0 :               fprintf(stderr, "Invalid layer!\n");
    1756             :             }
    1757             :             // And this comes from above.
    1758           0 :             GDrawDrawText8(pixmap, r.x + 2, layer2.header_height + i * CV_LAYERS2_LINE_HEIGHT + (CV_LAYERS2_LINE_HEIGHT - 12) / 2 + 12,
    1759           0 :                     (char *) layername,-1,ll==layer2.active?0xffffff:GDrawGetDefaultForeground(NULL));
    1760             : #endif // 0
    1761             :         }
    1762             :     }
    1763           0 :     GDrawPopClip(pixmap, &oldclip);
    1764             : }
    1765             : 
    1766             : // Frank changed the prefix from MID to MIDL in order to avert conflicts with values set in charview_private.h.
    1767             : #define MIDL_LayerInfo  1
    1768             : #define MIDL_NewLayer   2
    1769             : #define MIDL_DelLayer   3
    1770             : #define MIDL_First      4
    1771             : #define MIDL_Earlier    5
    1772             : #define MIDL_Later      6
    1773             : #define MIDL_Last       7
    1774             : #define MIDL_MakeLine 100
    1775             : #define MIDL_MakeArc  200
    1776             : #define MIDL_InsertPtOnSplineAt  2309
    1777             : #define MIDL_NamePoint  2318
    1778             : #define MIDL_NameContour  2319
    1779             : 
    1780           0 : static void CVLayer2Invoked(GWindow v, GMenuItem *mi, GEvent *e) {
    1781           0 :     CharView *cv = (CharView *) GDrawGetUserData(v);
    1782             :     Layer temp;
    1783           0 :     int layer = CVLayer(&cv->b);
    1784           0 :     SplineChar *sc = cv->b.sc;
    1785             :     int i;
    1786             :     char *buts[3];
    1787           0 :     buts[0] = _("_Yes"); buts[1]=_("_No"); buts[2] = NULL;
    1788             : 
    1789           0 :     switch ( mi->mid ) {
    1790             :       case MIDL_LayerInfo:
    1791           0 :         if ( !LayerDialog(cv->b.layerheads[cv->b.drawmode],cv->b.sc->parent))
    1792           0 : return;
    1793           0 :       break;
    1794             :       case MIDL_NewLayer:
    1795           0 :         LayerDefault(&temp);
    1796           0 :         if ( !LayerDialog(&temp,cv->b.sc->parent))
    1797           0 : return;
    1798           0 :         sc->layers = realloc(sc->layers,(sc->layer_cnt+1)*sizeof(Layer));
    1799           0 :         sc->layers[sc->layer_cnt] = temp;
    1800           0 :         cv->b.layerheads[dm_fore] = &sc->layers[sc->layer_cnt];
    1801           0 :         cv->b.layerheads[dm_back] = &sc->layers[ly_back];
    1802           0 :         ++sc->layer_cnt;
    1803           0 :       break;
    1804             :       case MIDL_DelLayer:
    1805           0 :         if ( sc->layer_cnt==2 )              /* May not delete the last foreground layer */
    1806           0 : return;
    1807           0 :         if ( gwwv_ask(_("Cannot Be Undone"),(const char **) buts,0,1,_("This operation cannot be undone, do it anyway?"))==1 )
    1808           0 : return;
    1809           0 :         SplinePointListsFree(sc->layers[layer].splines);
    1810           0 :         RefCharsFree(sc->layers[layer].refs);
    1811           0 :         ImageListsFree(sc->layers[layer].images);
    1812           0 :         UndoesFree(sc->layers[layer].undoes);
    1813           0 :         UndoesFree(sc->layers[layer].redoes);
    1814           0 :         for ( i=layer+1; i<sc->layer_cnt; ++i )
    1815           0 :             sc->layers[i-1] = sc->layers[i];
    1816           0 :         --sc->layer_cnt;
    1817           0 :         if ( layer==sc->layer_cnt )
    1818           0 :             cv->b.layerheads[dm_fore] = &sc->layers[layer-1];
    1819           0 :       break;
    1820             :       case MIDL_First:
    1821           0 :         if ( layer==ly_fore )
    1822           0 : return;
    1823           0 :         temp = sc->layers[layer];
    1824           0 :         for ( i=layer-1; i>=ly_fore; --i )
    1825           0 :             sc->layers[i+1] = sc->layers[i];
    1826           0 :         sc->layers[i+1] = temp;
    1827           0 :         cv->b.layerheads[dm_fore] = &sc->layers[ly_fore];
    1828           0 :       break;
    1829             :       case MIDL_Earlier:
    1830           0 :         if ( layer==ly_fore )
    1831           0 : return;
    1832           0 :         temp = sc->layers[layer];
    1833           0 :         sc->layers[layer] = sc->layers[layer-1];
    1834           0 :         sc->layers[layer-1] = temp;
    1835           0 :         cv->b.layerheads[dm_fore] = &sc->layers[layer-1];
    1836           0 :       break;
    1837             :       case MIDL_Later:
    1838           0 :         if ( layer==sc->layer_cnt-1 )
    1839           0 : return;
    1840           0 :         temp = sc->layers[layer];
    1841           0 :         sc->layers[layer] = sc->layers[layer+1];
    1842           0 :         sc->layers[layer+1] = temp;
    1843           0 :         cv->b.layerheads[dm_fore] = &sc->layers[layer+1];
    1844           0 :       break;
    1845             :       case MIDL_Last:
    1846           0 :         if ( layer==sc->layer_cnt-1 )
    1847           0 : return;
    1848           0 :         temp = sc->layers[layer];
    1849           0 :         for ( i=layer+1; i<sc->layer_cnt; ++i )
    1850           0 :             sc->layers[i-1] = sc->layers[i];
    1851           0 :         sc->layers[i-1] = temp;
    1852           0 :         cv->b.layerheads[dm_fore] = &sc->layers[i-1];
    1853           0 :       break;
    1854             :     }
    1855           0 :     CVLayers2Set(cv);
    1856           0 :     CVCharChangedUpdate(&cv->b);
    1857             : }
    1858             : 
    1859           0 : static void Layer2Menu(CharView *cv,GEvent *event, int nolayer) {
    1860             :     GMenuItem mi[20];
    1861             :     int i;
    1862             :     static char *names[] = { N_("Layer Info..."), N_("New Layer..."), N_("Del Layer"), (char *) -1,
    1863             :             N_("_First"), N_("_Earlier"), N_("L_ater"), N_("_Last"), NULL };
    1864             :     static int mids[] = { MIDL_LayerInfo, MIDL_NewLayer, MIDL_DelLayer, -1,
    1865             :             MIDL_First, MIDL_Earlier, MIDL_Later, MIDL_Last, 0 };
    1866           0 :     int layer = CVLayer(&cv->b);
    1867             : 
    1868           0 :     memset(mi,'\0',sizeof(mi));
    1869           0 :     for ( i=0; names[i]!=0; ++i ) {
    1870           0 :         if ( names[i]!=(char *) -1 ) {
    1871           0 :             mi[i].ti.text = (unichar_t *) _(names[i]);
    1872           0 :             mi[i].ti.text_is_1byte = true;
    1873             :         } else
    1874           0 :             mi[i].ti.line = true;
    1875           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    1876           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    1877           0 :         mi[i].mid = mids[i];
    1878           0 :         mi[i].invoke = CVLayer2Invoked;
    1879           0 :         if ( mids[i]!=MIDL_NewLayer && nolayer )
    1880           0 :             mi[i].ti.disabled = true;
    1881           0 :         if (( mids[i]==MIDL_First || mids[i]==MIDL_Earlier ) && layer==ly_fore )
    1882           0 :             mi[i].ti.disabled = true;
    1883           0 :         if (( mids[i]==MIDL_Last || mids[i]==MIDL_Later ) && layer==cv->b.sc->layer_cnt-1 )
    1884           0 :             mi[i].ti.disabled = true;
    1885           0 :         if ( mids[i]==MIDL_DelLayer && cv->b.sc->layer_cnt==2 )
    1886           0 :             mi[i].ti.disabled = true;
    1887             :     }
    1888           0 :     GMenuCreatePopupMenu(cvlayers2,event, mi);
    1889           0 : }
    1890             : 
    1891           0 : static void Layer2Scroll(CharView *cv, GEvent *event) {
    1892           0 :     int off = 0;
    1893           0 :     enum sb sbt = event->u.control.u.sb.type;
    1894             : 
    1895           0 :     if ( sbt==et_sb_top )
    1896           0 :         off = 0;
    1897           0 :     else if ( sbt==et_sb_bottom )
    1898           0 :         off = cv->b.sc->layer_cnt-1-layer2.visible_layers;
    1899           0 :     else if ( sbt==et_sb_up ) {
    1900           0 :         off = layer2.offtop-1;
    1901           0 :     } else if ( sbt==et_sb_down ) {
    1902           0 :         off = layer2.offtop+1;
    1903           0 :     } else if ( sbt==et_sb_uppage ) {
    1904           0 :         off = layer2.offtop-layer2.visible_layers+1;
    1905           0 :     } else if ( sbt==et_sb_downpage ) {
    1906           0 :         off = layer2.offtop+layer2.visible_layers-1;
    1907             :     } else /* if ( sbt==et_sb_thumb || sbt==et_sb_thumbrelease ) */ {
    1908           0 :         off = event->u.control.u.sb.pos;
    1909             :     }
    1910           0 :     if ( off>cv->b.sc->layer_cnt-1-layer2.visible_layers )
    1911           0 :         off = cv->b.sc->layer_cnt-1-layer2.visible_layers;
    1912           0 :     if ( off<0 ) off=0;
    1913           0 :     if ( off==layer2.offtop )
    1914           0 : return;
    1915           0 :     layer2.offtop = off;
    1916           0 :     GScrollBarSetPos(GWidgetGetControl(cvlayers2,CID_SB),off);
    1917           0 :     CVLayers2Reflow(cv, false);
    1918           0 :     GDrawRequestExpose(cvlayers2,NULL,false);
    1919             : }
    1920             : 
    1921           0 : static int cvlayers2_e_h(GWindow gw, GEvent *event) {
    1922           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
    1923             : 
    1924           0 :     if ( event->type==et_destroy ) {
    1925           0 :         cvlayers2 = NULL;
    1926           0 : return( true );
    1927             :     }
    1928             : 
    1929           0 :     if ( cv==NULL )
    1930           0 : return( true );
    1931             : 
    1932           0 :     switch ( event->type ) {
    1933             :       case et_close:
    1934           0 :         GDrawSetVisible(gw,false);
    1935           0 :       break;
    1936             :       case et_char: case et_charup:
    1937           0 :         PostCharToWindow(cv->gw,event);
    1938           0 :       break;
    1939             :       case et_resize:
    1940           0 :         CVLayers2Reflow(cv, true);
    1941           0 :       break;
    1942             :       case et_expose:
    1943           0 :         Layers2Expose(cv,gw,event);
    1944           0 :       break;
    1945             :       case et_mousedown: {
    1946           0 :         if ( event->u.mouse.y>CV_LAYERS2_HEADER_HEIGHT ) {
    1947           0 :         if (event->u.mouse.button >= 4) {
    1948             :             // Scroll the list
    1949           0 :             event->u.control.u.sb.type = (event->u.mouse.button == 4 || event->u.mouse.button == 6) ? et_sb_up : et_sb_down;
    1950           0 :             Layer2Scroll(cv, event);
    1951           0 :             return true;
    1952             :         }
    1953           0 :         int layer = (event->u.mouse.y-CV_LAYERS2_HEADER_HEIGHT)/CV_LAYERS2_LINE_HEIGHT;
    1954           0 :             if ( layer<2 ) {
    1955           0 :                 cv->b.drawmode = layer==0 ? dm_grid : dm_back;
    1956           0 :                 layer2.active = layer;
    1957           0 :             } else if ( layer-1+layer2.offtop >= cv->b.sc->layer_cnt ) {
    1958           0 :                 if ( event->u.mouse.button==3 )
    1959           0 :                     Layer2Menu(cv,event,true);
    1960             :                 else
    1961           0 :                     GDrawBeep(NULL);
    1962           0 : return(true);
    1963             :             } else {
    1964           0 :                 layer2.active = layer+layer2.offtop;
    1965           0 :                 cv->b.drawmode = dm_fore;
    1966           0 :                 cv->b.layerheads[dm_fore] = &cv->b.sc->layers[layer-1+layer2.offtop];
    1967             :             }
    1968           0 :             GDrawRequestExpose(cvlayers2,NULL,false);
    1969           0 :             GDrawRequestExpose(cv->v,NULL,false);
    1970           0 :             GDrawRequestExpose(cv->gw,NULL,false);   /* the logo (where the scrollbars join) shows what layer we are in */
    1971           0 :             if ( event->u.mouse.button==3 )
    1972           0 :                 Layer2Menu(cv,event,cv->b.drawmode!=dm_fore);
    1973           0 :             else if ( event->u.mouse.clicks==2 && cv->b.drawmode==dm_fore ) {
    1974           0 :                 if ( LayerDialog(cv->b.layerheads[cv->b.drawmode],cv->b.sc->parent))
    1975           0 :                     CVCharChangedUpdate(&cv->b);
    1976             :             }
    1977             :         }
    1978           0 :       } break;
    1979             :       case et_controlevent:
    1980           0 :         if ( event->u.control.subtype == et_radiochanged ) {
    1981           0 :             enum drawmode dm = cv->b.drawmode;
    1982           0 :             int tmpcid = -1;
    1983           0 :             int tmplayer = -1;
    1984           0 :             switch(GGadgetGetCid(event->u.control.g)) {
    1985             :               case CID_VFore:
    1986           0 :                 CVShows.showfore = cv->showfore = GGadgetIsChecked(event->u.control.g);
    1987           0 :                 if ( CVShows.showback )
    1988           0 :                     cv->showback[0] |= 2;
    1989             :                 else
    1990           0 :                     cv->showback[0] &= ~2;
    1991           0 :               break;
    1992             :               case CID_VBack:
    1993           0 :                 CVShows.showback = GGadgetIsChecked(event->u.control.g);
    1994           0 :                 if ( CVShows.showback )
    1995           0 :                     cv->showback[0] |= 1;
    1996             :                 else
    1997           0 :                     cv->showback[0] &= ~1;
    1998           0 :                 cv->back_img_out_of_date = true;
    1999           0 :               break;
    2000             :               case CID_VGrid:
    2001           0 :                 CVShows.showgrids = cv->showgrids = GGadgetIsChecked(event->u.control.g);
    2002           0 :               break;
    2003             :               default:
    2004           0 :                 tmpcid = GGadgetGetCid(event->u.control.g);
    2005           0 :                 tmplayer = tmpcid - CID_VBase;
    2006           0 :                 if (tmpcid < 0 || tmplayer < 0) break;
    2007             :                 // We check that the layer is valid (since the code does not presently, as far as Frank knows, handle layer deletion).
    2008             :                 // We also check that the CID is within the allocated range (although this may not be necessary since the checkbox would not exist otherwise).
    2009           0 :                 if (tmplayer > 0 && tmplayer < 999 && tmplayer < cv->b.sc->parent->layer_cnt) {
    2010           0 :                   if (GGadgetIsChecked(event->u.control.g)) {
    2011           0 :                     cv->showback[tmplayer>>5]|=(1<<(tmplayer&31));
    2012             :                   } else {
    2013           0 :                     cv->showback[tmplayer>>5]&=~(1<<(tmplayer&31));
    2014             :                   }
    2015             :                 }
    2016           0 :                 break;
    2017             :             }
    2018           0 :             GDrawRequestExpose(cv->v,NULL,false);
    2019           0 :             if ( dm!=cv->b.drawmode )
    2020           0 :                 GDrawRequestExpose(cv->gw,NULL,false);       /* the logo (where the scrollbars join) shows what layer we are in */
    2021             :         } else
    2022           0 :             Layer2Scroll(cv,event);
    2023           0 :       break;
    2024             :     }
    2025           0 : return( true );
    2026             : }
    2027             : 
    2028             : /* This is used for Type 3 fonts. CVMakeLayers is used for other fonts. */
    2029           0 : static void CVMakeLayers2(CharView *cv) {
    2030             :     GRect r;
    2031             :     GWindowAttrs wattrs;
    2032             :     GGadgetCreateData gcd[25];
    2033             :     GTextInfo label[25];
    2034             :     static GBox radio_box = { bt_none, bs_rect, 0, 0, 0, 0, 0, 0, 0, 0, COLOR_DEFAULT, COLOR_DEFAULT, 0, 0, 0, 0, 0, 0, 0 };
    2035             :     FontRequest rq;
    2036             :     int i;
    2037             :     extern int _GScrollBar_Width;
    2038             : 
    2039           0 :     if ( layer2.clut==NULL )
    2040           0 :         layer2.clut = _BDFClut(4);
    2041           0 :     if ( cvlayers2!=NULL )
    2042           0 : return;
    2043           0 :     memset(&wattrs,0,sizeof(wattrs));
    2044           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
    2045           0 :     wattrs.event_masks = -1;
    2046           0 :     wattrs.cursor = ct_mypointer;
    2047           0 :     wattrs.positioned = true;
    2048           0 :     wattrs.is_dlg = true;
    2049           0 :     wattrs.utf8_window_title = _("Layers");
    2050             : 
    2051           0 :     r.width = GGadgetScale(CV_LAYERS2_WIDTH); r.height = CV_LAYERS2_HEIGHT;
    2052           0 :     if ( cvlayersoff.x==-9999 ) {
    2053           0 :         cvlayersoff.x = -r.width-6;
    2054           0 :         cvlayersoff.y = cv->mbh+getToolbarHeight(cv)+45/*25*/;       /* 45 is right if there's decor, 25 when none. twm gives none, kde gives decor */
    2055             :     }
    2056           0 :     r.x = cvlayersoff.x; r.y = cvlayersoff.y;
    2057           0 :     if ( palettes_docked ) { r.x = 0; r.y=getToolbarHeight(cv)+2; }
    2058           0 :     cvlayers2 = CreatePalette( cv->gw, &r, cvlayers2_e_h, NULL, &wattrs, cv->v );
    2059             : 
    2060           0 :     memset(&label,0,sizeof(label));
    2061           0 :     memset(&gcd,0,sizeof(gcd));
    2062             : 
    2063           0 :     if ( layersfont==NULL ) {
    2064           0 :         memset(&rq,'\0',sizeof(rq));
    2065           0 :         rq.utf8_family_name = SANS_UI_FAMILIES;
    2066           0 :         rq.point_size = -12;
    2067           0 :         rq.weight = 400;
    2068           0 :         layersfont = GDrawInstanciateFont(cvlayers2,&rq);
    2069           0 :         layersfont = GResourceFindFont("LayersPalette.Font",layersfont);
    2070             :     }
    2071             : 
    2072           0 :     for ( i=0; i<sizeof(label)/sizeof(label[0]); ++i )
    2073           0 :         label[i].font = layersfont;
    2074           0 :     layer2.font = layersfont;
    2075             : 
    2076           0 :     gcd[0].gd.pos.width = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
    2077           0 :     gcd[0].gd.pos.x = CV_LAYERS2_WIDTH-gcd[0].gd.pos.width;
    2078           0 :     gcd[0].gd.pos.y = CV_LAYERS2_HEADER_HEIGHT+2*CV_LAYERS2_LINE_HEIGHT;
    2079           0 :     gcd[0].gd.pos.height = CV_LAYERS2_HEIGHT-gcd[0].gd.pos.y;
    2080           0 :     gcd[0].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_sb_vert;
    2081           0 :     gcd[0].gd.cid = CID_SB;
    2082           0 :     gcd[0].creator = GScrollBarCreate;
    2083           0 :     layer2.sb_start = gcd[0].gd.pos.x;
    2084             : 
    2085             : /* GT: Abbreviation for "Visible" */
    2086           0 :     label[1].text = (unichar_t *) _("V");
    2087           0 :     label[1].text_is_1byte = true;
    2088           0 :     gcd[1].gd.label = &label[1];
    2089           0 :     gcd[1].gd.pos.x = 7; gcd[1].gd.pos.y = 5; 
    2090           0 :     gcd[1].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    2091           0 :     gcd[1].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2092           0 :     gcd[1].creator = GLabelCreate;
    2093             : 
    2094           0 :     label[2].text = (unichar_t *) _("Layer");
    2095           0 :     label[2].text_is_1byte = true;
    2096           0 :     gcd[2].gd.label = &label[2];
    2097           0 :     gcd[2].gd.pos.x = 30; gcd[2].gd.pos.y = 5; 
    2098           0 :     gcd[2].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    2099           0 :     gcd[2].gd.cid = CID_LayerLabel;
    2100           0 :     gcd[2].gd.popup_msg = (unichar_t *) _("Is Layer Editable?");
    2101           0 :     gcd[2].creator = GLabelCreate;
    2102             : 
    2103           0 :     gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = CV_LAYERS2_HEADER_HEIGHT+(CV_LAYERS2_LINE_HEIGHT-12)/2; 
    2104           0 :     gcd[3].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    2105           0 :     gcd[3].gd.cid = CID_VGrid;
    2106           0 :     gcd[3].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2107           0 :     gcd[3].gd.box = &radio_box;
    2108           0 :     gcd[3].creator = GCheckBoxCreate;
    2109             : 
    2110           0 :     gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[3].gd.pos.y+CV_LAYERS2_LINE_HEIGHT; 
    2111           0 :     gcd[4].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    2112           0 :     gcd[4].gd.cid = CID_VBack;
    2113           0 :     gcd[4].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2114           0 :     gcd[4].gd.box = &radio_box;
    2115           0 :     gcd[4].creator = GCheckBoxCreate;
    2116             : 
    2117           0 :     gcd[5].gd.pos.x = 5; gcd[5].gd.pos.y = gcd[4].gd.pos.y+CV_LAYERS2_LINE_HEIGHT; 
    2118           0 :     gcd[5].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    2119           0 :     gcd[5].gd.cid = CID_VFore;
    2120           0 :     gcd[5].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2121           0 :     gcd[5].gd.box = &radio_box;
    2122           0 :     gcd[5].creator = GCheckBoxCreate;
    2123             : 
    2124           0 :     int wi = 6; // Widget index.
    2125           0 :     int ly = 0;
    2126             :     // We want to look at the unhandled layers.
    2127           0 :     if (ly <= ly_back) ly = ly_back + 1;
    2128           0 :     if (ly <= ly_fore) ly = ly_fore + 1;
    2129           0 :     if (ly <= ly_grid) ly = ly_grid + 1;
    2130           0 :     while (ly < cv->b.sc->parent->layer_cnt && wi < 24) {
    2131           0 :       gcd[wi].gd.pos.x = 5; gcd[wi].gd.pos.y = gcd[wi-1].gd.pos.y+CV_LAYERS2_LINE_HEIGHT; 
    2132           0 :       gcd[wi].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    2133           0 :       gcd[wi].gd.cid = CID_VBase + ly; // There are plenty of CID values available for these above CID_VBase.
    2134           0 :       gcd[wi].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2135           0 :       gcd[wi].gd.box = &radio_box;
    2136           0 :       gcd[wi].creator = GCheckBoxCreate;
    2137           0 :       ly++;
    2138           0 :       wi++;
    2139             :     }
    2140             : 
    2141           0 :     if ( cv->showgrids ) gcd[3].gd.flags |= gg_cb_on;
    2142           0 :     if ( cv->showback[0]&1 ) gcd[4].gd.flags |= gg_cb_on;
    2143           0 :     if ( cv->showfore ) gcd[5].gd.flags |= gg_cb_on;
    2144             : 
    2145           0 :     GGadgetsCreate(cvlayers2, gcd);
    2146             :     // Calculate the header height. The '-1' is magic! Needed to obtain symmetry
    2147           0 :     layer2.header_height = GGadgetGetY(GWidgetGetControl(cvlayers2, CID_VGrid)) - 1;
    2148             :     // Move the "Layer" label into the correct position based on the width of the checkbox
    2149           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers2, CID_VGrid), &r);
    2150           0 :     GGadgetMove(GWidgetGetControl(cvlayers2, CID_LayerLabel), r.x + r.width, 5);
    2151           0 :     if ( cvvisible[0] )
    2152           0 :         GDrawSetVisible(cvlayers2,true);
    2153             : }
    2154             : 
    2155           0 : static void LayersSwitch(CharView *cv) {
    2156           0 : }
    2157             : 
    2158         363 : void SC_MoreLayers(SplineChar *sc, Layer *old) { /* We've added more layers */
    2159             :     CharView *curcv, *cv;
    2160         363 :     if ( sc->parent==NULL || !sc->parent->multilayer )
    2161         363 : return;
    2162           0 :     for ( cv=(CharView *) (sc->views); cv!=NULL ; cv=(CharView *) (cv->b.next) ) {
    2163           0 :         cv->b.layerheads[dm_fore] = &cv->b.sc->layers[cv->b.layerheads[dm_fore]-old];
    2164           0 :         cv->b.layerheads[dm_back] = &cv->b.sc->layers[ly_back];
    2165             :     }
    2166           0 :     if ( cvtools==NULL )
    2167           0 : return;
    2168           0 :     curcv = GDrawGetUserData(cvtools);
    2169           0 :     if ( curcv==NULL || curcv->b.sc!=sc )
    2170           0 : return;
    2171           0 :     CVLayers2Set(curcv);
    2172             : }
    2173             : 
    2174         895 : void SCLayersChange(SplineChar *sc) { /* many of the foreground layers need to be redrawn */
    2175             :     CharView *curcv;
    2176         895 :     if ( cvtools==NULL || !sc->parent->multilayer )
    2177         895 : return;
    2178           0 :     curcv = GDrawGetUserData(cvtools);
    2179           0 :     if ( curcv==NULL || curcv->b.sc!=sc )
    2180           0 : return;
    2181           0 :     CVLayers2Set(curcv);
    2182             : }
    2183             : 
    2184           0 : void CVLayerChange(CharView *cv) { /* Current layer needs to be redrawn */
    2185             :     CharView *curcv;
    2186             :     int layer;
    2187             : 
    2188           0 :     if ( cvtools==NULL  || !cv->b.sc->parent->multilayer )
    2189           0 : return;
    2190           0 :     curcv = GDrawGetUserData(cvtools);
    2191           0 :     if ( curcv!=cv )
    2192           0 : return;
    2193           0 :     if ( cv->b.drawmode==dm_grid || cv->b.drawmode==dm_back )
    2194           0 : return;
    2195           0 :     layer = CVLayer(&cv->b);
    2196           0 :     BDFCharFree(layer2.layers[layer+1]);
    2197           0 :     layer2.layers[layer+1] = BDFCharFromLayer(cv->b.sc,layer);
    2198           0 :     GDrawRequestExpose(cvlayers2,NULL,false);
    2199             : }
    2200             : 
    2201             : /* Update the state of the controls of the non-type3 layers palette to the given character view */
    2202             : /* New widgets are not allocated here. For that, see CVLCheckLayerCount(). */
    2203           0 : static void CVLayers1Set(CharView *cv) {
    2204             :     int i, top;
    2205             : 
    2206           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers,CID_VFore),cv->showfore);
    2207           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers,CID_VBack),cv->showback[0]&1);
    2208           0 :     GGadgetSetChecked(GWidgetGetControl(cvlayers,CID_VGrid),cv->showgrids);
    2209             : 
    2210             :      /* clear old layer previews */
    2211           0 :     layerinfo.offtop = 0;
    2212           0 :     for ( i=2; i<layerinfo.current_layers; ++i ) {
    2213           0 :         BDFCharFree(layerinfo.layers[i]);
    2214           0 :         layerinfo.layers[i]=NULL;
    2215             :     }
    2216             : 
    2217             :      /* reallocate enough space if necessary */
    2218           0 :     if ( cv->b.sc->layer_cnt+1>=layerinfo.max_layers ) {
    2219           0 :         top = cv->b.sc->layer_cnt+10;
    2220           0 :         if ( layerinfo.layers==NULL )
    2221           0 :             layerinfo.layers = calloc(top,sizeof(BDFChar *));
    2222             :         else {
    2223           0 :             layerinfo.layers = realloc(layerinfo.layers,top*sizeof(BDFChar *));
    2224           0 :             for ( i=layerinfo.current_layers; i<top; ++i )
    2225           0 :                 layerinfo.layers[i] = NULL;
    2226             :         }
    2227           0 :         layerinfo.max_layers = top;
    2228             :     }
    2229           0 :     layerinfo.current_layers = cv->b.sc->layer_cnt+1;
    2230           0 :     for ( i=ly_fore; i<cv->b.sc->layer_cnt; ++i )
    2231           0 :         layerinfo.layers[i+1] = BDFCharFromLayer(cv->b.sc,i);
    2232           0 :     layerinfo.active = CVLayer(&cv->b)+1;
    2233             : 
    2234           0 :     if ( layerinfo.visible_layers==0 ) {
    2235             :         GRect size;
    2236           0 :         GDrawGetSize(cvlayers,&size);
    2237           0 :         layerinfo.visible_layers=(size.height-layer_header_height)/layer_height;
    2238             :     }
    2239           0 :     GScrollBarSetBounds(GWidgetGetControl(cvlayers,CID_SB),0,cv->b.sc->layer_cnt+1-2, layerinfo.visible_layers);
    2240           0 :     if ( layerinfo.offtop>cv->b.sc->layer_cnt-1-layerinfo.visible_layers )
    2241           0 :         layerinfo.offtop = cv->b.sc->layer_cnt-1-layerinfo.visible_layers;
    2242           0 :     if ( layerinfo.offtop<0 ) layerinfo.offtop = 0;
    2243           0 :     GScrollBarSetPos(GWidgetGetControl(cvlayers,CID_SB),layerinfo.offtop);
    2244             : 
    2245           0 :     for ( i=0; i<cv->b.sc->layer_cnt; i++ ) {
    2246           0 :         GGadgetSetChecked(GWidgetGetControl(cvlayers,CID_VBase+i),cv->showback[i>>5]&(1<<(i&31)));
    2247             :     }
    2248             : 
    2249           0 :     layerinfo.active = CVLayer(&cv->b); /* the index of the active layer */
    2250           0 :     GDrawRequestExpose(cvlayers,NULL,false);
    2251           0 : }
    2252             : 
    2253             : /* Update the layers palette to reflect the given character view. No new gadgets
    2254             :  * are created or hid here, only the state of existing gadgets is changed.
    2255             :  * New layer gadgets are created in CVLCheckLayerCount(). */
    2256           0 : void CVLayersSet(CharView *cv) {
    2257           0 :     if( cv )
    2258           0 :         onCollabSessionStateChanged( NULL, cv->b.fv, NULL );
    2259             :     
    2260           0 :     if ( cv->b.sc->parent->multilayer ) {
    2261           0 :         CVLayers2Set(cv);
    2262           0 : return;
    2263             :     }
    2264             :      /* This is for the non-type3 layers palette: */
    2265           0 :     CVLayers1Set(cv);
    2266             : }
    2267             : 
    2268             : /**
    2269             :  * Get the offset at the right hand size of the eyeball to show/hide
    2270             :  * a layer. This is the x offset where the Q/C indicators might be drawn.
    2271             :  */
    2272           0 : static int32 Layers_getOffsetAtRightOfViewLayer(CharView *cv)
    2273             : {
    2274           0 :     int32 ret = 64;
    2275           0 :     GGadget *v = GWidgetGetControl(cvlayers,CID_VBack);
    2276           0 :     if( v )
    2277             :     {
    2278             :         GRect size;
    2279           0 :         GGadgetGetSize(v,&size);
    2280           0 :         ret = 7 + size.width;
    2281             :     }
    2282           0 :     return ret;
    2283             : }
    2284             : 
    2285             : 
    2286             :  /* Draw the fg/bg, cubic/quadratic columns, plus layer preview and label name */
    2287           0 : static void LayersExpose(CharView *cv,GWindow pixmap,GEvent *event) {
    2288             :     int i, ll, y;
    2289             :     const char *str;
    2290             :     GRect r;
    2291             :     struct _GImage base;
    2292             :     GImage gi;
    2293           0 :     Color mocolor = ACTIVE_BORDER; /* mouse over color */
    2294             :     int ww;
    2295             : 
    2296           0 :     int yt = .7*layer_height; /* vertical spacer to add when drawing text in the row */
    2297             :     int column_width;
    2298             :     int quadcol, fgcol, editcol;
    2299             : 
    2300           0 :     if ( event->u.expose.rect.y+event->u.expose.rect.height<layer_header_height )
    2301           0 : return;
    2302             : 
    2303           0 :     int offsetAtRightOfViewLayer = Layers_getOffsetAtRightOfViewLayer(cv);
    2304           0 :     column_width = layerinfo.column_width;
    2305             :     
    2306           0 :     GDrawSetDither(NULL, false);        /* on 8 bit displays we don't want any dithering */
    2307           0 :     ww=layerinfo.sb_start;
    2308             : 
    2309           0 :     memset(&gi,0,sizeof(gi));
    2310           0 :     memset(&base,0,sizeof(base));
    2311           0 :     gi.u.image = &base;
    2312           0 :     base.image_type = it_index;
    2313           0 :     base.clut = layer2.clut;
    2314           0 :     base.trans = -1;
    2315           0 :     GDrawSetFont(pixmap,layerinfo.font);
    2316             : 
    2317           0 :     quadcol=fgcol=offsetAtRightOfViewLayer;
    2318           0 :     if ( layerscols & LSHOW_CUBIC )
    2319             :     {
    2320             :         /* show quad col */
    2321           0 :         quadcol = offsetAtRightOfViewLayer;
    2322           0 :         fgcol   = offsetAtRightOfViewLayer+column_width;
    2323             :     } 
    2324           0 :     if ( layerscols & LSHOW_FG )
    2325             :     {
    2326             :         /* show fg col */
    2327           0 :         fgcol = quadcol+column_width;
    2328             :     }
    2329             :     // editcol is the X offset where the layer name label should be drawn
    2330           0 :     editcol = fgcol+column_width;
    2331           0 :     int bottomOfLast = 0;
    2332             :     
    2333             :      /* loop once per layer, where 0==guides, 1=back, 2=fore, etc */
    2334           0 :     for ( i=(event->u.expose.rect.y-layer_header_height)/layer_height;
    2335           0 :             i<(event->u.expose.rect.y+event->u.expose.rect.height+layer_height-layer_header_height)/layer_height;
    2336           0 :             ++i ) {
    2337           0 :         ll = i-1+layerinfo.offtop;
    2338           0 :         if ( ll>=cv->b.sc->layer_cnt || ll<-1 ) continue;
    2339             : 
    2340           0 :         y = layer_header_height + i*layer_height;
    2341           0 :         bottomOfLast = y + layer_height;
    2342           0 :         if ( y<layer_header_height ) continue;
    2343             : 
    2344             :          /* draw quadratic/cubic toggle */
    2345           0 :         if ( layerscols & LSHOW_CUBIC ) {
    2346           0 :             if ( layerinfo.mo_layer==ll && layerinfo.mo_col==CID_QBase ) {
    2347           0 :                 r.x = quadcol; r.width = column_width;
    2348           0 :                 r.y = y;
    2349           0 :                 r.height = layer_height;
    2350           0 :                 GDrawFillRect(pixmap,&r,mocolor);
    2351             :             }
    2352           0 :             str = ( ll>=0 && ll<cv->b.sc->layer_cnt ? (cv->b.sc->layers[ll].order2? "Q" : "C") : " ");
    2353           0 :             GDrawDrawText8(pixmap, quadcol, y + yt,
    2354             :                     (char *) str,-1,GDrawGetDefaultForeground(NULL));
    2355             :         }
    2356             : 
    2357             :          /* draw fg/bg toggle */
    2358           0 :         if ( layerscols & LSHOW_FG ) {
    2359           0 :             if ( layerinfo.mo_layer==ll && layerinfo.mo_col==CID_FBase ) {
    2360           0 :                 r.x = fgcol; r.width = column_width;
    2361           0 :                 r.y = y;
    2362           0 :                 r.height = layer_height;
    2363           0 :                 GDrawFillRect(pixmap,&r,mocolor);
    2364             :             }
    2365           0 :             str = ( ll>=0 && ll<cv->b.sc->layer_cnt ? (cv->b.sc->layers[ll].background? "B" : "F") : "#");
    2366           0 :             GDrawDrawText8(pixmap, fgcol, y + yt,
    2367             :                     (char *) str,-1,GDrawGetDefaultForeground(NULL));
    2368             :         }
    2369             : 
    2370             :          /* draw layer thumbnail and label */
    2371           0 :         if ( ll==layerinfo.active ) {
    2372           0 :             r.x = editcol; r.width = ww-r.x;
    2373           0 :             r.y = y;
    2374           0 :             r.height = layer_height;
    2375           0 :             GDrawFillRect(pixmap,&r,GDrawGetDefaultForeground(NULL));
    2376           0 :         } else if ( layerinfo.mo_layer==ll && layerinfo.mo_col==CID_EBase ) {
    2377           0 :             r.x = editcol; r.width = ww-r.x;
    2378           0 :             r.y = y;
    2379           0 :             r.height = layer_height;
    2380           0 :             GDrawFillRect(pixmap,&r,mocolor);
    2381             :         }
    2382           0 :         r.x=editcol;
    2383           0 :         if ( ll==-1 || ll==0 || ll==1) {
    2384           0 :             str = ll==-1 ? _("Guide") : (ll==0 ?_("Back") : _("Fore")) ;
    2385           0 :             GDrawDrawText8(pixmap,r.x+2,y + yt,
    2386           0 :                     (char *) str,-1,ll==layerinfo.active?0xffffff:GDrawGetDefaultForeground(NULL));
    2387           0 :         } else if ( ll>=layerinfo.current_layers ) {
    2388           0 :              break; /* no more layers to draw! */
    2389           0 :         } else if ( ll>=0 && layerinfo.layers[ll]!=NULL ) {
    2390           0 :             BDFChar *bdfc = layerinfo.layers[ll];
    2391           0 :             base.data = bdfc->bitmap;
    2392           0 :             base.bytes_per_line = bdfc->bytes_per_line;
    2393           0 :             base.width = bdfc->xmax-bdfc->xmin+1;
    2394           0 :             base.height = bdfc->ymax-bdfc->ymin+1;
    2395             : //          GDrawDrawImage(pixmap,&gi,NULL,
    2396             : //                  r.x+2+bdfc->xmin,
    2397             : //                  y+as-bdfc->ymax);
    2398           0 :             str = cv->b.sc->parent->layers[ll].name;
    2399           0 :             if ( !str || !*str ) str="-";
    2400           0 :             GDrawDrawText8(pixmap, r.x+2, y + yt,
    2401           0 :                         (char *) str,-1,ll==layerinfo.active?0xffffff:GDrawGetDefaultForeground(NULL));
    2402             :         }
    2403             :     }
    2404             : 
    2405           0 :     if( bottomOfLast )
    2406             :     {
    2407           0 :         GGadgetSetY(GWidgetGetControl(cvlayers,CID_AddLayer),    bottomOfLast + 2 );
    2408           0 :         GGadgetSetY(GWidgetGetControl(cvlayers,CID_RemoveLayer), bottomOfLast + 2 );
    2409           0 :         GGadgetSetY(GWidgetGetControl(cvlayers,CID_LayersMenu),  bottomOfLast + 2 );
    2410             :     }
    2411             :     
    2412             : }
    2413             : 
    2414             : /* Remove the layer rename edit box. If save!=0, then record the text as the new layer name. */
    2415           0 : static void CVLRemoveEdit(CharView *cv, int save) {
    2416           0 :     if ( layerinfo.rename_active ) {
    2417           0 :         GGadget *g = GWidgetGetControl(cvlayers,CID_Edit);
    2418           0 :         const unichar_t *str = GGadgetGetTitle(g);
    2419           0 :         int l = layerinfo.active;
    2420             : 
    2421           0 :         if ( save
    2422           0 :                 && layerinfo.active>=0 && str!=NULL && str[0]!='\0' 
    2423           0 :                 && uc_strcmp( str,cv->b.sc->parent->layers[l].name) ) {
    2424           0 :             free( cv->b.sc->parent->layers[l].name );
    2425           0 :             cv->b.sc->parent->layers[l].name = cu_copy( str );
    2426             : 
    2427           0 :             CVLCheckLayerCount(cv,true);
    2428           0 :             CVLayersSet(cv);
    2429             :         }
    2430           0 :         GGadgetSetVisible(g,false);
    2431           0 :         GDrawRequestExpose(cvlayers,NULL,false);
    2432             : 
    2433           0 :         layerinfo.rename_active = 0;
    2434           0 :         CVInfoDrawText(cv,cv->gw);
    2435             :     }
    2436           0 : }
    2437             : 
    2438             :  /* Make sure we've got the right number of gadgets in the layers palette, and that
    2439             :   * they are positioned properly. Their state are updated in CVLayers1Set().
    2440             :   * If resize, then make the palette fit the layers up to a max number of layers. */
    2441           0 : static void CVLCheckLayerCount(CharView *cv, int resize) {
    2442             : 
    2443           0 :     SplineChar *sc = cv->b.sc;
    2444             :     int i;
    2445             :     GGadgetCreateData gcd[4];
    2446             :     GTextInfo label[3];
    2447             :     GRect size;
    2448             :     int width;
    2449           0 :     int maxwidth=0;
    2450           0 :     int togsize=0;
    2451             :     int x, y;
    2452           0 :     int column_width = layerinfo.column_width;
    2453             :     char namebuf[40];
    2454           0 :     int viscol=0, quadcol, fgcol, editcol;
    2455             :     extern int _GScrollBar_Width;
    2456           0 :     int offsetAtRightOfViewLayer = Layers_getOffsetAtRightOfViewLayer(cv);
    2457             : 
    2458           0 :     if (layerinfo.rename_active) CVLRemoveEdit(cv,true);
    2459             : 
    2460           0 :     quadcol=fgcol=offsetAtRightOfViewLayer;
    2461           0 :     if ( layerscols & LSHOW_CUBIC )
    2462             :     {
    2463           0 :         quadcol = offsetAtRightOfViewLayer;
    2464           0 :         fgcol   = offsetAtRightOfViewLayer+column_width;
    2465             :     }
    2466           0 :     if ( layerscols & LSHOW_FG )
    2467             :     {
    2468           0 :         fgcol = quadcol+column_width;
    2469             :     }
    2470             :     // editcol is the X offset where the layer name label should be drawn
    2471           0 :     editcol = fgcol+column_width;
    2472             : 
    2473             :     /* First figure out if we need to create any new widgets. If we have more */
    2474             :     /* widgets than we need, we just set them to be invisible.                */
    2475           0 :     if ( sc->layer_cnt > layers_max ) {
    2476           0 :         memset(&label,0,sizeof(label));
    2477           0 :         memset(&gcd,0,sizeof(gcd));
    2478           0 :         for ( i=layers_max; i<sc->layer_cnt; ++i ) {
    2479             :              /* for each new layer, create new widgets */
    2480             : 
    2481             :              /* Visibility toggle */
    2482           0 :             gcd[0].gd.flags = gg_enabled|gg_utf8_popup;
    2483           0 :             gcd[0].gd.cid = CID_VBase+i;
    2484           0 :             gcd[0].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    2485           0 :             gcd[0].creator = GVisibilityBoxCreate;
    2486             : 
    2487           0 :             GGadgetsCreate(cvlayers,gcd);
    2488           0 :             GVisibilityBoxSetToMinWH(GWidgetGetControl(cvlayers,CID_VBase+i));
    2489             :         }
    2490           0 :         layers_max = sc->layer_cnt;
    2491             :     }
    2492             : 
    2493             :     /* Then position everything, and name it properly */
    2494             : 
    2495           0 :     GDrawSetFont(cvlayers,layerinfo.font); /* for width finding code, need this */
    2496             : 
    2497             :      /* First need to position the add, remove, and layers gadgets */
    2498           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers,CID_RemoveLayer),&size);
    2499           0 :     x = 7+size.width;
    2500           0 :     y = layer_header_height;
    2501           0 :     GGadgetMove(GWidgetGetControl(cvlayers,CID_AddLayer), x, 5);
    2502           0 :     GGadgetSetSize(GWidgetGetControl(cvlayers,CID_AddLayer),&size);
    2503           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers,CID_AddLayer),&size);
    2504           0 :     x += size.width;
    2505           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers,CID_LayersMenu),&size);
    2506           0 :     GGadgetMove(GWidgetGetControl(cvlayers,CID_LayersMenu), x+5, 5+(y-8-size.height)/2);
    2507           0 :     maxwidth=x+5+size.width;
    2508             : 
    2509           0 :     if ( !resize )
    2510             :     {
    2511             :          /* adjust the number of layers that can be visible in the palette */
    2512           0 :         GDrawGetSize(cvlayers,&size);
    2513           0 :         layerinfo.visible_layers=(size.height-layer_header_height)/layer_height;
    2514           0 :         if ( layerinfo.offtop+layerinfo.visible_layers>=sc->layer_cnt )
    2515           0 :             layerinfo.offtop = sc->layer_cnt-layerinfo.visible_layers;
    2516           0 :         if ( layerinfo.offtop<0 ) layerinfo.offtop=0;
    2517             :     }
    2518           0 :     if ( layerinfo.visible_layers<2 ) layerinfo.visible_layers=2;
    2519             : 
    2520             :      /* Now position each layer row */
    2521           0 :     for ( i=-1; i<layers_max; ++i ) {
    2522           0 :         GGadget *v = GWidgetGetControl(cvlayers,CID_VBase+i);
    2523             : 
    2524           0 :         width=0;
    2525           0 :         togsize = editcol;
    2526             :         
    2527           0 :         if ( i>=0 && i<sc->layer_cnt ) {
    2528           0 :             char *hasmn = strchr(sc->parent->layers[i].name,'_');
    2529           0 :             if ( hasmn==NULL && i>=2 && i<9 && strlen(sc->parent->layers[i].name)<30 ) {
    2530             :                  /* For the first 10 or so layers, add a mnemonic like "(_3)" to the name label */
    2531             :                  /* if it does not already have a mnemonic.                                     */
    2532             :                 /* sprintf(namebuf, "%s (_%d)", sc->parent->layers[i].name, i+1); */
    2533           0 :                 sprintf(namebuf, "%s", sc->parent->layers[i].name);
    2534           0 :             } else if ( hasmn==NULL ) {
    2535           0 :                 sprintf(namebuf,"%s", i==-1 ? _("Guide") : (i==0 ?_("Back") : _("Fore")) );
    2536             :             }
    2537           0 :             width = GDrawGetText8Width(cvlayers, namebuf, -1);
    2538           0 :             width += 10; // padding takes up some space.
    2539           0 :             if ( width+togsize>maxwidth ) maxwidth = width + togsize;
    2540           0 :         } else if ( i==-1 ) {
    2541           0 :             if ( width+togsize>maxwidth ) maxwidth = width + togsize;
    2542             :         }
    2543             : 
    2544           0 :         if ( i+1<layerinfo.offtop || i>=layerinfo.offtop+layerinfo.visible_layers ||
    2545           0 :                 (sc->layer_cnt<=layerinfo.visible_layers && i>=sc->layer_cnt)) {
    2546             :              /* layer is currently scrolled out of palette */
    2547           0 :             GGadgetSetVisible(v,false);
    2548             :         } else {
    2549           0 :             GGadgetMove(v,viscol ,y);
    2550           0 :             GGadgetSetVisible(v,true);
    2551           0 :             y += layer_height;
    2552             :         }
    2553             :     }
    2554             : 
    2555             :      /* Update the scroll bar */
    2556           0 :     if ( sc->layer_cnt+1<=layerinfo.visible_layers ) {
    2557             :          /* don't need the scroll bar, so turn it off */
    2558           0 :         GGadgetSetVisible(GWidgetGetControl(cvlayers,CID_SB),false);
    2559             :     } else {
    2560           0 :         if( !resize )
    2561             :         {
    2562           0 :             GGadget *sb = GWidgetGetControl(cvlayers,CID_SB);
    2563           0 :             maxwidth += 2 + GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
    2564           0 :             GScrollBarSetBounds(sb,0,sc->layer_cnt,layerinfo.visible_layers);
    2565           0 :             GScrollBarSetPos(sb,cv->layers_off_top);
    2566           0 :             GGadgetSetVisible(sb,true);
    2567             :         }
    2568             :     }
    2569             : 
    2570             :      /* Resize the palette to fit */
    2571           0 :     if ( resize )
    2572             :     {
    2573           0 :         y += GDrawPointsToPixels(NULL,3);
    2574           0 :         GDrawGetSize(cvlayers,&size);
    2575           0 :         GDrawResize(cvlayers,maxwidth,y+layer_footer_height);
    2576             :     }
    2577             : 
    2578           0 :     GDrawGetSize(cvlayers,&size);
    2579           0 :     layerinfo.sb_start = size.width
    2580           0 :                 - (sc->layer_cnt+1<=layerinfo.visible_layers ? 0 : GDrawPointsToPixels(cv->gw,_GScrollBar_Width));
    2581           0 :     GGadget *sb = GWidgetGetControl(cvlayers,CID_SB);
    2582           0 :     GGadgetResize(sb, GDrawPointsToPixels(cv->gw,_GScrollBar_Width), size.height-layer_header_height);
    2583           0 :     GGadgetMove(sb,layerinfo.sb_start,layer_header_height);
    2584             : 
    2585           0 :     GDrawRequestExpose(cvlayers,NULL,false);
    2586           0 : }
    2587             : 
    2588             : /* Respond to scroll events from cvlayers scrollbar. */
    2589           0 : static void LayerScroll(CharView *cv, GEvent *event) {
    2590           0 :     int off = 0;
    2591           0 :     enum sb sbt = event->u.control.u.sb.type;
    2592             : 
    2593           0 :     if ( sbt==et_sb_top )
    2594           0 :         off = 0;
    2595           0 :     else if ( sbt==et_sb_bottom )
    2596           0 :         off = cv->b.sc->layer_cnt-layerinfo.visible_layers;
    2597           0 :     else if ( sbt==et_sb_up ) {
    2598           0 :         off = cv->layers_off_top-1;
    2599           0 :     } else if ( sbt==et_sb_down ) {
    2600           0 :         off = cv->layers_off_top+1;
    2601           0 :     } else if ( sbt==et_sb_uppage ) {
    2602           0 :         off = cv->layers_off_top-layerinfo.visible_layers+1;
    2603           0 :     } else if ( sbt==et_sb_downpage ) {
    2604           0 :         off = cv->layers_off_top+layerinfo.visible_layers-1;
    2605             :     } else /* if ( sbt==et_sb_thumb || sbt==et_sb_thumbrelease ) */ {
    2606           0 :         off = event->u.control.u.sb.pos;
    2607             :     }
    2608           0 :     if ( off>cv->b.sc->layer_cnt-layerinfo.visible_layers )
    2609           0 :         off = cv->b.sc->layer_cnt-layerinfo.visible_layers;
    2610           0 :     if ( off<0 ) off=0;
    2611           0 :     if ( off==cv->layers_off_top )
    2612           0 : return;
    2613           0 :     cv->layers_off_top = off;
    2614           0 :     layerinfo.offtop = off;
    2615           0 :     CVLCheckLayerCount(cv, false);
    2616           0 :     GScrollBarSetPos(GWidgetGetControl(cvlayers,CID_SB),off);
    2617           0 :     GDrawRequestExpose(cvlayers,NULL,false);
    2618             : }
    2619             : 
    2620             : /* Layers palette menu ids */
    2621             : #define LMID_LayerInfo  1
    2622             : #define LMID_NewLayer   2
    2623             : #define LMID_DelLayer   3
    2624             : #define LMID_Fill       4
    2625             : #define LMID_First      5
    2626             : #define LMID_Up         6
    2627             : #define LMID_Down       7
    2628             : #define LMID_Last       8
    2629             : #define LMID_Foreground 9
    2630             : #define LMID_Background 10
    2631             : #define LMID_Cubic      11
    2632             : #define LMID_Quadratic  12
    2633             : #define LMID_ShowCubic  13
    2634             : #define LMID_ShowFore   14
    2635             : 
    2636             : /* Return a unique layer name based on base.
    2637             :  * This just appends a number to base until the name is not found. */
    2638           0 : static char *UniqueLayerName(SplineChar *sc, const char *base)
    2639             : {
    2640             :     static char buffer[100];
    2641           0 :     const char *basestr=base;
    2642           0 :     int i=1, c;
    2643             :     
    2644           0 :     if ( basestr==NULL || basestr[0]=='\0' ) basestr=_("Layer");
    2645             : 
    2646             :     while (1) {
    2647           0 :         if (i==1) sprintf( buffer,"%s",basestr );
    2648           0 :         else sprintf( buffer,"%s %d",basestr, i );
    2649             :         
    2650           0 :         for (c=0; c<sc->layer_cnt; c++) {
    2651           0 :             if (!strcmp(sc->parent->layers[c].name,buffer)) break;
    2652             :         }
    2653             : 
    2654           0 :         if ( c==sc->layer_cnt ) break;
    2655           0 :         i++;
    2656           0 :     }
    2657             : 
    2658           0 :     return buffer;
    2659             : }
    2660             : 
    2661             : /* Layers palette menu selection */
    2662           0 : static void CVLayerInvoked(GWindow v, GMenuItem *mi, GEvent *e) {
    2663           0 :     CharView *cv = (CharView *) GDrawGetUserData(v);
    2664           0 :     int layer = CVLayer(&cv->b);
    2665           0 :     SplineChar *sc = cv->b.sc;
    2666             :     Layer temp;
    2667             :     int i;
    2668             :     char *buts[3];
    2669           0 :     buts[0] = _("_Yes"); buts[1]=_("_No"); buts[2] = NULL;
    2670             : 
    2671           0 :     switch ( mi->mid ) {
    2672             :       case LMID_Fill:
    2673           0 :         cv->showfilled = !cv->showfilled;
    2674           0 :         CVRegenFill(cv);
    2675           0 :         GDrawRequestExpose(cv->v,NULL,false);
    2676           0 :       break;
    2677             : 
    2678             :       case LMID_ShowCubic:
    2679           0 :         layerscols=(layerscols&~LSHOW_CUBIC)|((layerscols&LSHOW_CUBIC)?0:1);
    2680           0 :         CVLCheckLayerCount(cv, true);
    2681           0 :       break;
    2682             : 
    2683             :       case LMID_ShowFore:
    2684           0 :         layerscols=(layerscols&~LSHOW_FG)|((layerscols&LSHOW_FG)?0:2);
    2685           0 :         CVLCheckLayerCount(cv, true);
    2686           0 :       break;
    2687             : 
    2688             :       case LMID_Foreground:
    2689           0 :         if ( layer>ly_fore && cv->b.sc->parent->layers[layer].background==1) {
    2690           0 :             SFLayerSetBackground(cv->b.sc->parent,layer,0);
    2691           0 :             GDrawRequestExpose(cvlayers,NULL,false);
    2692             :         }
    2693           0 :       break;
    2694             : 
    2695             :       case LMID_Background:
    2696           0 :         if ( layer>=ly_fore && cv->b.sc->parent->layers[layer].background==0) {
    2697           0 :             SFLayerSetBackground(cv->b.sc->parent,layer,1);
    2698           0 :             GDrawRequestExpose(cvlayers,NULL,false);
    2699             :         }
    2700           0 :       break;
    2701             : 
    2702             :       case LMID_Cubic:
    2703           0 :         if ( layer!=ly_grid && cv->b.sc->layers[layer].order2 ) {
    2704           0 :             SFConvertLayerToOrder3(cv->b.sc->parent, layer);
    2705           0 :             GDrawRequestExpose(cvlayers,NULL,false);
    2706           0 :             cv->back_img_out_of_date = true;
    2707             :         }
    2708           0 :       break;
    2709             : 
    2710             :       case LMID_Quadratic:
    2711           0 :         if ( layer!=ly_grid && !cv->b.sc->layers[layer].order2 ) {
    2712           0 :             SFConvertLayerToOrder2(cv->b.sc->parent, layer);
    2713           0 :             GDrawRequestExpose(cvlayers,NULL,false);
    2714           0 :             cv->back_img_out_of_date = true;
    2715             :         }
    2716           0 :       break;
    2717             : 
    2718             :       case LMID_NewLayer:
    2719           0 :         SFAddLayer(cv->b.sc->parent, /* font of the glyph in the charview */
    2720           0 :                         UniqueLayerName(sc,_("Back")),     /* Name */
    2721             :                         0,         /* 0=cubic, 1=quad */
    2722             :                         1);       /* 1=back,  0=fore */
    2723             : 
    2724           0 :         layer=cv->b.sc->parent->layer_cnt-1;
    2725             :         
    2726           0 :         cv->showback[layer>>5] |=  (1<<(layer&31)); /* make it visible */
    2727           0 :         CVLCheckLayerCount(cv, true); /* update widget existence */
    2728           0 :         CVLayersSet(cv);       /* update widget state     */
    2729           0 :       break;
    2730             :       case LMID_DelLayer:
    2731           0 :         layer = CVLayer((CharViewBase *) cv); /* the index of the active layer */
    2732           0 :         if (layer==ly_fore || layer==ly_back || layer==ly_grid)
    2733           0 : return;
    2734           0 :         if ( gwwv_ask(_("Cannot Be Undone"),(const char **) buts,0,1,_("This operation cannot be undone, do it anyway?"))==1 )
    2735           0 : return;
    2736           0 :         SFRemoveLayer(cv->b.sc->parent, layer);
    2737           0 :         CVLCheckLayerCount(cv, true); /* update widget existence */
    2738           0 :         CVLayersSet(cv);       /* update widget state     */
    2739           0 :       break;
    2740             : 
    2741             :       case LMID_First: /* move layer contents to top */
    2742           0 :         if ( layer==ly_fore )
    2743           0 : return;
    2744           0 :         temp = sc->layers[layer];
    2745           0 :         for ( i=layer-1; i>=ly_fore; --i )
    2746           0 :             sc->layers[i+1] = sc->layers[i];
    2747           0 :         sc->layers[i+1] = temp;
    2748           0 :         cv->b.layerheads[dm_fore] = &sc->layers[ly_fore];
    2749           0 :       break;
    2750             :       case LMID_Up: /* move layer contents one up */
    2751           0 :         if ( layer==ly_fore )
    2752           0 : return;
    2753           0 :         temp = sc->layers[layer];
    2754           0 :         sc->layers[layer] = sc->layers[layer-1];
    2755           0 :         sc->layers[layer-1] = temp;
    2756           0 :         cv->b.layerheads[dm_fore] = &sc->layers[layer-1];
    2757           0 :       break;
    2758             :       case LMID_Down: /* move layer contents one down */
    2759           0 :         if ( layer==sc->layer_cnt-1 )
    2760           0 : return;
    2761           0 :         temp = sc->layers[layer];
    2762           0 :         sc->layers[layer] = sc->layers[layer+1];
    2763           0 :         sc->layers[layer+1] = temp;
    2764           0 :         cv->b.layerheads[dm_fore] = &sc->layers[layer+1];
    2765           0 :       break;
    2766             :       case LMID_Last:
    2767           0 :         if ( layer==sc->layer_cnt-1 )
    2768           0 : return;
    2769           0 :         temp = sc->layers[layer]; /* move layer contents to bottom */
    2770           0 :         for ( i=layer+1; i<sc->layer_cnt; ++i )
    2771           0 :             sc->layers[i-1] = sc->layers[i];
    2772           0 :         sc->layers[i-1] = temp;
    2773           0 :         cv->b.layerheads[dm_fore] = &sc->layers[i-1];
    2774           0 :       break;
    2775             :     }
    2776           0 :     CVLayersSet(cv);
    2777           0 :     CVCharChangedUpdate(&cv->b);
    2778             : }
    2779             : 
    2780             : /* Pop up the layers palette context menu */
    2781           0 : static void LayerMenu(CharView *cv,GEvent *event, int nolayer) {
    2782             :     GMenuItem mi[20];
    2783             :     int i;
    2784             :     static char *names[] = {
    2785             :                      /*N_("Rename Layer..."),*/
    2786             :                      N_("New Layer"),
    2787             :                      N_("Del Layer"),
    2788             :                      (char *) -1,
    2789             :                      N_("Shift Contents To _First"),
    2790             :                      N_("Shift Contents _Up"),
    2791             :                      N_("Shift Contents _Down"),
    2792             :                      N_("Shift Contents To _Last"),
    2793             :                      (char *) -1,
    2794             :                      N_("Make Foreground"),/* or N_("Make Background"), */
    2795             :                      N_("Make Cubic"),     /* or N_("Make Quadratic"),  */
    2796             :                      (char *) -1,
    2797             :                      N_("Fill"),
    2798             :                      (char *) -1,
    2799             :                      N_("Show Cubic Column"),
    2800             :                      N_("Show Fore/Back Column"),
    2801             :                      NULL,
    2802             :                     };
    2803             :     static int mids[] = {
    2804             :                      /*LMID_RenameLayer,*/
    2805             :                      LMID_NewLayer,
    2806             :                      LMID_DelLayer,
    2807             :                      -1,
    2808             :                      LMID_First,
    2809             :                      LMID_Up,
    2810             :                      LMID_Down,
    2811             :                      LMID_Last,
    2812             :                      -1,
    2813             :                      LMID_Foreground, /* or LMID_Background, */
    2814             :                      LMID_Cubic,      /* or LMID_Quadratic,  */
    2815             :                      -1,
    2816             :                      LMID_Fill,
    2817             :                      -1,
    2818             :                      LMID_ShowCubic,
    2819             :                      LMID_ShowFore,
    2820             :                      0
    2821             :                     };
    2822           0 :     int layer = CVLayer(&cv->b);
    2823             : 
    2824           0 :     memset(mi,'\0',sizeof(mi));
    2825           0 :     for ( i=0; names[i]!=0; ++i ) {
    2826           0 :         if ( names[i]!=(char *) -1 ) {
    2827           0 :             mi[i].ti.text = (unichar_t *) _(names[i]);
    2828           0 :             mi[i].ti.text_is_1byte = true;
    2829           0 :             mi[i].ti.text_in_resource = true;
    2830             :         } else
    2831           0 :             mi[i].ti.line = true;
    2832             : 
    2833           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    2834           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    2835           0 :         mi[i].mid = mids[i];
    2836           0 :         mi[i].invoke = CVLayerInvoked;
    2837             : 
    2838             :         /*if ( mids[i]!=LMID_NewLayer && nolayer )
    2839             :             mi[i].ti.disabled = true;*/
    2840             : 
    2841           0 :         if ( ( mids[i]==LMID_First || mids[i]==LMID_Up ) && ( layer==-1 || layer==0) )
    2842           0 :             mi[i].ti.disabled = true;
    2843             : 
    2844           0 :         else if ( ( mids[i]==LMID_Last || mids[i]==LMID_Down ) && (layer==ly_grid || layer==cv->b.sc->layer_cnt-1) )
    2845           0 :             mi[i].ti.disabled = true;
    2846             : 
    2847           0 :         else if ( mids[i]==LMID_DelLayer && ( layer<2 || cv->b.sc->layer_cnt==2) )
    2848           0 :             mi[i].ti.disabled = true;
    2849             : 
    2850           0 :         else if ( mids[i]==LMID_Fill ) {
    2851           0 :             mi[i].ti.checkable = 1;
    2852           0 :             mi[i].ti.checked = cv->showfilled;
    2853             : 
    2854           0 :         } else if ( mids[i]==LMID_Foreground ) {
    2855           0 :             if ( layer>=0 ) {
    2856           0 :                 if ( ! cv->b.sc->layers[layer].background ) {
    2857           0 :                     mi[i].mid = LMID_Background;
    2858           0 :                     mi[i].ti.text = (unichar_t *) _("Make Background");
    2859             :                 }
    2860             :             } else {
    2861           0 :                 mi[i].ti.disabled = true;
    2862             :             }
    2863           0 :         } else if ( mids[i]==LMID_Cubic ) {
    2864           0 :             if ( ! cv->b.sc->layers[layer].order2 ) {
    2865           0 :                 mi[i].mid = LMID_Quadratic;
    2866           0 :                 mi[i].ti.text = (unichar_t *) _("Make Quadratic");
    2867             :             }
    2868             : 
    2869           0 :         } else if ( mids[i]==LMID_ShowCubic ) {
    2870           0 :             mi[i].ti.checkable = 1;
    2871           0 :             mi[i].ti.checked = (layerscols & LSHOW_CUBIC)?1:0;
    2872             : 
    2873           0 :         } else if ( mids[i]==LMID_ShowFore ) {
    2874           0 :             mi[i].ti.checkable = 1;
    2875           0 :             mi[i].ti.checked = (layerscols & LSHOW_FG)?1:0;
    2876             :         }
    2877             :     }
    2878           0 :     GMenuCreatePopupMenu(cvlayers, event, mi);
    2879           0 : }
    2880             : 
    2881             : /* Scan for which layer and column one clicks on in the layers 1 palette                */
    2882             : /* -1 is the guides layer, 0 is default back, 1 default fore, etc.                      */
    2883             : /* col will be set to either -1 for none, CID_VBase, CID_QBase, CID_FBase, or CID_EBase */
    2884           0 : static int CVLScanForItem(int x, int y, int *col) {
    2885           0 :     int l=(y-layer_header_height)/layer_height + layerinfo.offtop - 1;
    2886           0 :     int viscol=0, quadcol, fgcol, editcol;
    2887           0 :     int cw=layerinfo.column_width;
    2888             : 
    2889           0 :     quadcol=fgcol=viscol;
    2890           0 :     if ( layerscols & LSHOW_CUBIC ) { quadcol = viscol+cw; fgcol=viscol+cw; }
    2891           0 :     if ( layerscols & LSHOW_FG    ) { fgcol = quadcol+cw; }
    2892           0 :     editcol=fgcol+cw;
    2893             : 
    2894           0 :     *col=-1;
    2895           0 :     if ( x>0 && x<viscol+cw ) *col=CID_VBase;
    2896             :     /**
    2897             :      * The two below options, CID_QBase and CID_FBase allow the curve
    2898             :      * type and foreground/background to be changed simply by clicking
    2899             :      * on them. The cubic/quadratic and background/foreground
    2900             :      * attributes should NOT be buttons that can change these
    2901             :      * attributes, they should only SHOW the attribute. Changing the
    2902             :      * attributes can be done in Font Info, Layers, and is done
    2903             :      * infrequently and has a lot of implications so shouldn't be
    2904             :      * easily done by mistake.
    2905             :      */
    2906             : //    else if ( (layerscols & LSHOW_CUBIC) && x>=quadcol && x<quadcol+cw ) *col=CID_QBase;
    2907             : //    else if ( (layerscols & LSHOW_FG) && x>=fgcol && x<fgcol+cw ) *col=CID_FBase;
    2908           0 :     else if ( x>=editcol ) *col=CID_EBase;
    2909             : 
    2910           0 :     return l;
    2911             : }
    2912             : 
    2913             : /* Called in response to some event where we want to change the current layer. */
    2914           0 : void CVLSelectLayer(CharView *cv, int layer) {
    2915           0 :     enum drawmode dm = cv->b.drawmode;
    2916             : 
    2917           0 :     if ( layer<-1 || layer>=cv->b.sc->layer_cnt )
    2918           0 :         return;
    2919             : 
    2920           0 :     if ( layer==-1 ) {
    2921           0 :         cv->b.drawmode = dm_grid;
    2922           0 :         cv->lastselpt = NULL;
    2923             :     } else {
    2924           0 :         if ( layer==1 ) {
    2925           0 :             cv->b.drawmode = dm_fore;
    2926           0 :             cv->lastselpt = NULL;
    2927             :         } else {
    2928           0 :             cv->b.drawmode = dm_back;
    2929           0 :             cv->b.layerheads[dm_back] = &cv->b.sc->layers[layer];
    2930           0 :             cv->lastselpt = NULL;
    2931             :         }
    2932             : 
    2933           0 :         CVDebugFree(cv->dv);
    2934           0 :         SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
    2935           0 :         FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
    2936           0 :         FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    2937           0 :         cv->show_ft_results = false;
    2938             :     }
    2939           0 :     layerinfo.active = CVLayer(&cv->b); /* the index of the active layer */
    2940             : 
    2941           0 :     CVRegenFill(cv);
    2942           0 :     GDrawRequestExpose(cv->v,NULL,false);
    2943           0 :     if (cvlayers2) GDrawRequestExpose(cvlayers2,NULL,false);
    2944           0 :     if (cvlayers)  GDrawRequestExpose(cvlayers,NULL,false);
    2945           0 :     if ( dm!=cv->b.drawmode )
    2946           0 :         GDrawRequestExpose(cv->gw,NULL,false); /* the logo (where the scrollbars join) shows what layer we are in */
    2947           0 :     CVInfoDrawText(cv,cv->gw);
    2948             : }
    2949             : 
    2950           0 : static int cvlayers_e_h(GWindow gw, GEvent *event) {
    2951           0 :     CharView *cv = (CharView *) GDrawGetUserData(gw);
    2952             :     char *buts[3];
    2953           0 :     buts[0] = _("_Yes"); buts[1]=_("_No"); buts[2] = NULL;
    2954             : 
    2955           0 :     if ( event->type==et_destroy )
    2956             :     {
    2957           0 :         cvlayers = NULL;
    2958           0 :         return( true );
    2959             :     }
    2960             : 
    2961           0 :     if ( cv==NULL )
    2962           0 :         return( true );
    2963             : 
    2964           0 :     switch ( event->type ) {
    2965             :       case et_close:
    2966           0 :         GDrawSetVisible(gw,false);
    2967           0 :       break;
    2968             :       case et_char: case et_charup:
    2969           0 :         if ( event->u.chr.keysym == GK_Return) {
    2970           0 :             CVLRemoveEdit(cv, true);
    2971           0 :         } else if ( event->u.chr.keysym == GK_Escape) {
    2972           0 :             CVLRemoveEdit(cv, false);
    2973           0 :         } else PostCharToWindow(cv->gw,event);
    2974           0 :       break;
    2975             :       case et_mousemove: {
    2976             :         int l, col;
    2977             : 
    2978           0 :         l = CVLScanForItem(event->u.mouse.x,event->u.mouse.y, &col);
    2979           0 :         if ( l!=layerinfo.mo_layer || col!=layerinfo.mo_col ) {
    2980           0 :             layerinfo.mo_layer = l;
    2981           0 :             layerinfo.mo_col = col;
    2982           0 :             GDrawRequestExpose(cvlayers,NULL,false);
    2983             :         }
    2984             : 
    2985           0 : return( true );
    2986             : 
    2987             :       } break;
    2988             :       case et_mousedown: {
    2989           0 :         if ( layerinfo.rename_active ) CVLRemoveEdit(cv, true);
    2990           0 :       } break;
    2991             :       case et_mouseup: {
    2992             :         int l, x, cid, h;
    2993             :         GGadget *g;
    2994           0 :         l = CVLScanForItem(event->u.mouse.x,event->u.mouse.y, &cid);
    2995             : 
    2996           0 :         if ( cid==CID_EBase && l>=-1 && l<cv->b.sc->layer_cnt )
    2997             :         {
    2998             :             /* Need to check for this BEFORE checking for right click! */
    2999           0 :             if ( event->u.mouse.button==1 && event->u.mouse.clicks==2 )
    3000             :             {
    3001             :                  /* bring up edit box for layer name */
    3002             : 
    3003           0 :                 if ( l<2 )
    3004           0 :                     return ( true );
    3005             : 
    3006           0 :                 x = 7+(1+((layerscols&LSHOW_CUBIC)?1:0)+((layerscols&LSHOW_FG)?1:0))*layerinfo.column_width;
    3007           0 :                 g = GWidgetGetControl(cvlayers,CID_Edit);
    3008           0 :                 h = 1.5*layer_height;
    3009             : 
    3010           0 :                 GGadgetResize(g, layerinfo.sb_start-x, h);
    3011           0 :                 GGadgetMove(g, x,layer_header_height+(l+1.5+layerinfo.offtop)*layer_height-h/2);
    3012           0 :                 GGadgetSetVisible(g,true);
    3013             :                 /* GGadgetSetTitle8((GTextField*)g, cv->b.sc->parent->layers[l].name); */
    3014           0 :                 GGadgetSetTitle8(g, cv->b.sc->parent->layers[l].name);
    3015             : 
    3016           0 :                 layerinfo.active=l;
    3017           0 :                 layerinfo.rename_active=1;
    3018           0 :                 return ( true );
    3019             :             }
    3020             : 
    3021           0 :             CVLSelectLayer(cv, l);
    3022             :         }
    3023             : 
    3024             :          /* right click to pop up menu */
    3025           0 :         if ( event->u.mouse.button==3 ) {
    3026           0 :             LayerMenu(cv,event,true);
    3027           0 :             return(true);
    3028             :         }
    3029             : 
    3030             :          /* otherwise, deal with clicking up on the various controls */
    3031           0 :         if ( l<-1 || l>=cv->b.sc->layer_cnt)
    3032           0 :             return (true);
    3033             : 
    3034           0 :         if ( cid==CID_QBase) {
    3035           0 :             if (l>=0) { /* don't try to adjust if calling for guides layer */
    3036           0 :                 if (cv->b.sc->layers[l].order2)
    3037           0 :                     SFConvertLayerToOrder3(cv->b.sc->parent, l);
    3038             :                 else
    3039           0 :                     SFConvertLayerToOrder2(cv->b.sc->parent, l);
    3040           0 :                 cv->back_img_out_of_date = true;
    3041           0 :                 GDrawRequestExpose(cvlayers,NULL,false);
    3042           0 :                 GDrawRequestExpose(cv->v,NULL,false);
    3043             :             }
    3044           0 :         } else if ( cid==CID_FBase) {
    3045           0 :             if (l>1) { /* don't try to adjust if calling guides, default fore or back layer */
    3046           0 :                 if (cv->b.sc->layers[l].background)
    3047           0 :                     SFLayerSetBackground(cv->b.sc->parent,l,0);
    3048             :                 else
    3049           0 :                     SFLayerSetBackground(cv->b.sc->parent,l,1);
    3050           0 :                 GDrawRequestExpose(cvlayers,NULL,false);
    3051           0 :                 GDrawRequestExpose(cv->v,NULL,false);
    3052             :             }
    3053             :         }
    3054           0 :       } break; /* case et_mouseup */
    3055             :       case et_expose:
    3056           0 :         LayersExpose(cv,gw,event);
    3057           0 :       break;
    3058             :       case et_resize:
    3059           0 :         if ( event->u.resize.sized ) {
    3060           0 :             CVLCheckLayerCount(cv,false); /* update widget existence, but do not resize */
    3061             :         }
    3062           0 :       break;
    3063             :       case et_controlevent:
    3064           0 :         if ( event->u.control.subtype == et_buttonactivate ) {
    3065           0 :             int cid = GGadgetGetCid(event->u.control.g);
    3066             :             int layer;
    3067             : 
    3068           0 :             switch( cid ) {
    3069             :               case CID_AddLayer: {
    3070           0 :                 SplineChar *sc = cv->b.sc;
    3071             : 
    3072             :                  /* This adds a new layer to the end of the current layers list.
    3073             :                   * Somehow it is created as an invisible layer. */
    3074           0 :                 SFAddLayer(cv->b.sc->parent, /* font of the glyph in the charview */
    3075           0 :                                 UniqueLayerName(sc,_("Back")),     /* Name */
    3076             :                                 0,         /* 0=cubic, 1=quad */
    3077             :                                 1);       /* 1=back,  0=fore */
    3078             : 
    3079           0 :                 layer=cv->b.sc->parent->layer_cnt-1;
    3080             :                 
    3081           0 :                 cv->showback[layer>>5] |=  (1<<(layer&31)); /* make it visible */
    3082           0 :                 CVLCheckLayerCount(cv,true); /* update widget existence */
    3083           0 :                 CVLayersSet(cv);       /* update widget state     */
    3084           0 :               } break;
    3085             :               case CID_RemoveLayer:
    3086           0 :                 layer = CVLayer((CharViewBase *) cv); /* the index of the active layer */
    3087           0 :                 if (layer==ly_fore || layer==ly_back || layer==ly_grid)
    3088           0 : return ( true );
    3089           0 :                 if ( gwwv_ask(_("Cannot Be Undone"),(const char **) buts,0,1,_("This operation cannot be undone, do it anyway?"))==1 )
    3090           0 : return ( true );
    3091           0 :                 SFRemoveLayer(cv->b.sc->parent, layer);
    3092           0 :                 CVLCheckLayerCount(cv,true); /* update widget existence */
    3093           0 :                 CVLayersSet(cv);       /* update widget state     */
    3094           0 :               break;
    3095             :               case CID_RenameLayer: {
    3096             :                 /* *** */
    3097           0 :                 int x = 7+(1+((layerscols&LSHOW_CUBIC)?1:0)+((layerscols&LSHOW_FG)?1:0))*layerinfo.column_width;
    3098           0 :                 GGadget *g = GWidgetGetControl(cvlayers,CID_Edit);
    3099           0 :                 layer = CVLayer((CharViewBase *) cv); /* the index of the active layer */
    3100             :                 /* layer = layerinfo.active */ /* the index of the active layer */
    3101             : 
    3102           0 :                 GGadgetResize(g, layerinfo.sb_start-x,1.5*layer_height);
    3103           0 :                 GGadgetMove(g, x,layer_header_height+(layer+1+layerinfo.offtop)*layer_height);
    3104           0 :                 GGadgetSetVisible(g,true);
    3105           0 :                 GGadgetSetTitle8(g, cv->b.sc->parent->layers[layer].name);
    3106             : 
    3107           0 :                 layerinfo.rename_active=1;
    3108             : 
    3109           0 :                 CVLCheckLayerCount(cv,true); /* update widget existence */
    3110           0 :                 CVLayersSet(cv);       /* update widget state     */
    3111           0 :                 GDrawRequestExpose(cvtools,NULL,false);
    3112             :                 
    3113           0 :               } break;
    3114             :             }
    3115           0 :         } else if ( event->u.control.subtype == et_radiochanged ) {
    3116           0 :             enum drawmode dm = cv->b.drawmode;
    3117           0 :             int cid = GGadgetGetCid(event->u.control.g);
    3118             : 
    3119           0 :             switch( cid ) {
    3120             :               case CID_VFore:
    3121           0 :                 CVShows.showfore = cv->showfore = GGadgetIsChecked(event->u.control.g);
    3122           0 :                 GDrawRequestExpose(cv->v,NULL,false);
    3123           0 :               break;
    3124             :               case CID_VBack:
    3125           0 :                 CVShows.showback = GGadgetIsChecked(event->u.control.g);
    3126           0 :                 if ( CVShows.showback )
    3127           0 :                     cv->showback[0] |= 1;
    3128             :                 else
    3129           0 :                     cv->showback[0] &= ~1;
    3130           0 :                 cv->back_img_out_of_date = true;
    3131           0 :                 GDrawRequestExpose(cv->v,NULL,false);
    3132           0 :               break;
    3133             :               case CID_VGrid:
    3134           0 :                 CVShows.showgrids = cv->showgrids = GGadgetIsChecked(event->u.control.g);
    3135           0 :                 GDrawRequestExpose(cv->v,NULL,false);
    3136           0 :               break;
    3137             :               case CID_EFore:
    3138           0 :                 cv->b.drawmode = dm_fore;
    3139           0 :                 cv->lastselpt = NULL;
    3140             : 
    3141           0 :                 CVDebugFree(cv->dv);
    3142           0 :                 SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
    3143           0 :                 FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
    3144           0 :                 FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    3145           0 :                 cv->show_ft_results = false;
    3146           0 :               break;
    3147             :               case CID_EBack:
    3148           0 :                 cv->b.drawmode = dm_back;
    3149           0 :                 cv->b.layerheads[dm_back] = &cv->b.sc->layers[ly_back];
    3150           0 :                 cv->lastselpt = NULL;
    3151             : 
    3152           0 :                 CVDebugFree(cv->dv);
    3153           0 :                 SplinePointListsFree(cv->b.gridfit); cv->b.gridfit = NULL;
    3154           0 :                 FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
    3155           0 :                 FreeType_FreeRaster(cv->raster); cv->raster = NULL;
    3156           0 :                 cv->show_ft_results = false;
    3157           0 :               break;
    3158             :               case CID_EGrid:
    3159           0 :                 cv->b.drawmode = dm_grid;
    3160           0 :                 cv->lastselpt = NULL;
    3161           0 :               break;
    3162             :               default:
    3163           0 :                 if ( cid>=CID_VBase-1 && cid<CID_VBase+999) {
    3164           0 :                     cid -= CID_VBase;
    3165           0 :                     if ( GGadgetIsChecked(event->u.control.g))
    3166           0 :                         cv->showback[cid>>5] |=  (1<<(cid&31));
    3167             :                     else
    3168           0 :                         cv->showback[cid>>5] &= ~(1<<(cid&31));
    3169           0 :                     cv->back_img_out_of_date = true;
    3170             : 
    3171           0 :                     GDrawRequestExpose(cv->v,NULL,false);
    3172           0 :                     if ( dm!=cv->b.drawmode )
    3173           0 :                         GDrawRequestExpose(cv->gw,NULL,false);       /* the logo (where the scrollbars join) shows what layer we are in */
    3174             :                 }
    3175             :             }
    3176             : 
    3177           0 :         } else if ( event->u.control.subtype == et_scrollbarchange ) {
    3178           0 :             LayerScroll(cv,event);
    3179             : 
    3180             :         }
    3181           0 :       break; /* case et_controlevent */
    3182             :       default: {
    3183           0 :       } break;
    3184             :     } /* switch ( event->type ) */
    3185           0 : return( true );
    3186             : }
    3187             : 
    3188             : /* Set to true the editable field for the current layer, and false for the other layers. */
    3189           0 : void CVSetLayer(CharView *cv,int layer) {
    3190             : 
    3191             :      /* Update the drawmode of cv */
    3192           0 :     if ( layer == ly_grid )
    3193           0 :         cv->b.drawmode = dm_grid;
    3194           0 :     else if (layer == ly_fore )
    3195           0 :         cv->b.drawmode = dm_fore;
    3196             :     else {
    3197           0 :         cv->b.drawmode = dm_back;
    3198           0 :         cv->b.layerheads[dm_back] = &cv->b.sc->layers[layer];
    3199             :     }
    3200           0 :     if ( cvlayers!=NULL && GDrawGetUserData(cvlayers)==cv ) 
    3201           0 :         GDrawRequestExpose(cvlayers,NULL,false);
    3202           0 : }
    3203             : 
    3204             : /* Check if a key press corresponds to a mnemonic the palette knows about. */
    3205           0 : int CVPaletteMnemonicCheck(GEvent *event) {
    3206             :     static struct strmatch { char *str; int cid; } strmatch[] = {
    3207             : /* GT: Foreground, make it short */
    3208             :         { N_("F_ore"), CID_EFore },
    3209             : /* GT: Background, make it short */
    3210             :         { N_("_Back"), CID_EBack },
    3211             : /* GT: Guide layer, make it short */
    3212             :         { N_("_Guide"), CID_EGrid },
    3213             :         { NULL, 0 }
    3214             :     };
    3215             :     unichar_t mn, mnc;
    3216             :     int j, i, ch;
    3217             :     char *foo;
    3218             :     GEvent fake;
    3219             :     GGadget *g;
    3220             :     CharView *cv;
    3221             :     SplineFont *parent;
    3222             :     int curlayer;
    3223             : 
    3224           0 :     if ( cvtools==NULL )
    3225           0 : return( false );
    3226           0 :     cv = GDrawGetUserData(cvtools);
    3227           0 :     parent = cv->b.sc->parent;
    3228           0 :     curlayer = CVLayer(&cv->b); /* the index of the active layer */
    3229             : 
    3230           0 :     if ( isdigit(event->u.chr.keysym) ) {
    3231           0 :         int off = event->u.chr.keysym - '0';
    3232             : 
    3233           0 :         g = GWidgetGetControl(cvlayers, CID_EBase+off-1);
    3234           0 :         if ( off-1<parent->layer_cnt && off!=curlayer ) {
    3235           0 :             CVLSelectLayer(cv, off);
    3236           0 :             if ( cv->b.sc->parent->multilayer )
    3237           0 :                 GDrawRequestExpose(cvlayers2,NULL,false);
    3238             :             else
    3239           0 : return( true );
    3240             :         }
    3241             :     }
    3242             : 
    3243             :      /* mnemonic is encoded in the layer name */
    3244           0 :     for ( j=0; j<2; ++j ) {
    3245           0 :         for ( i=0; j==0 ? i<parent->layer_cnt : strmatch[i].str!=NULL; ++i ) {
    3246           0 :             for ( foo = j==0 ? parent->layers[i].name : _(strmatch[i].str);
    3247             :                     (ch=utf8_ildb((const char **) &foo))!=0; )
    3248           0 :                 if ( ch=='_' )
    3249           0 :             break;
    3250           0 :             if ( ch=='_' )
    3251           0 :                 mnc = utf8_ildb((const char **) &foo);
    3252             :             else
    3253           0 :                 mnc = 0;
    3254           0 :             mn = mnc;
    3255           0 :             if ( islower(mn)) mnc = toupper(mn);
    3256           0 :             else if ( isupper(mn)) mnc = tolower(mn);
    3257           0 :             if ( event->u.chr.chars[0]==mn || event->u.chr.chars[0]==mnc ) {
    3258           0 :                 if ( cv->b.sc->parent->multilayer ) {
    3259           0 :                     fake.type = et_mousedown;
    3260           0 :                     fake.w = cvlayers;
    3261           0 :                     fake.u.mouse.x = 40;
    3262           0 :                     if ( strmatch[i].cid==CID_EGrid ) {
    3263           0 :                         fake.u.mouse.y = layer2.header_height+12;
    3264           0 :                     } else if ( strmatch[i].cid==CID_EBack ) {
    3265           0 :                         fake.u.mouse.y = layer2.header_height+12+CV_LAYERS2_LINE_HEIGHT;
    3266             :                     } else {
    3267           0 :                         fake.u.mouse.y = layer2.header_height+12+2*CV_LAYERS2_LINE_HEIGHT;
    3268             :                     }
    3269           0 :                     cvlayers2_e_h(cvlayers2,&fake);
    3270             :                 } else {
    3271           0 :                     CVLSelectLayer(cv, i);
    3272           0 :                     GDrawRequestExpose(cvlayers,NULL,false);
    3273             :                 }
    3274           0 :     return( true );
    3275             :             }
    3276             :         }
    3277             :     }
    3278           0 : return( false );
    3279             : }
    3280             : 
    3281             : /* This is used for fonts other than Type 3 fonts. CVMakeLayers2() is used for Type 3.
    3282             :  * Only the basics of the palette are set up here, with the widgets for the default fore, back,
    3283             :  * and guides layers. The palette is updated to actual character views in CVLCheckLayerCount(). */
    3284           0 : GWindow CVMakeLayers(CharView *cv) {
    3285             :     GRect r,size;
    3286             :     GWindowAttrs wattrs;
    3287             :     GGadgetCreateData gcd[25];
    3288             :     GTextInfo label[25];
    3289             :     GGadget *gadget;
    3290             :     FontRequest rq;
    3291             :     extern int _GScrollBar_Width;
    3292           0 :     int i=0;
    3293           0 :     int viscol=0;
    3294             : 
    3295           0 :     if ( cvlayers!=NULL )
    3296           0 : return( cvlayers );
    3297             : 
    3298             :      /* Initialize layerinfo */
    3299           0 :     if ( layerinfo.clut==NULL )
    3300           0 :         layerinfo.clut = _BDFClut(4);
    3301           0 :     if ( layersfont==NULL ) {
    3302           0 :         memset(&rq,'\0',sizeof(rq));
    3303           0 :         rq.utf8_family_name = SANS_UI_FAMILIES;
    3304           0 :         rq.point_size = -12;
    3305           0 :         rq.weight = 400;
    3306           0 :         layersfont = GDrawInstanciateFont(cvlayers2,&rq);
    3307           0 :         layersfont = GResourceFindFont("LayersPalette.Font",layersfont);
    3308             :     }
    3309           0 :     layerinfo.font = layersfont;
    3310             : 
    3311             :      /* Initialize palette window */
    3312           0 :     memset(&wattrs,0,sizeof(wattrs));
    3313           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
    3314           0 :     wattrs.event_masks = -1;
    3315           0 :     wattrs.cursor = ct_mypointer;
    3316           0 :     wattrs.positioned = true;
    3317           0 :     wattrs.is_dlg = true;
    3318           0 :     wattrs.utf8_window_title = _("Layers");
    3319             : 
    3320           0 :     r.width = GGadgetScale(104); r.height = CV_LAYERS_HEIGHT;
    3321           0 :     if ( cvlayersoff.x==-9999 ) {
    3322             :          /* Offset of window on screen, by default make it sit just below the tools palette */
    3323           0 :         cvlayersoff.x = -r.width-6;
    3324           0 :         cvlayersoff.y = cv->mbh+getToolbarHeight(cv)+45/*25*/; /* 45 is right if there's decor, 25 when none. twm gives none, kde gives decor */
    3325             :     }
    3326           0 :     r.x = cvlayersoff.x; r.y = cvlayersoff.y;
    3327           0 :     if ( palettes_docked ) { r.x = 0; r.y=getToolbarHeight(cv)+2; }
    3328           0 :     cvlayers = CreatePalette( cv->gw, &r, cvlayers_e_h, NULL, &wattrs, cv->v );
    3329             : 
    3330           0 :     memset(&label,0,sizeof(label));
    3331           0 :     memset(&gcd,0,sizeof(gcd));
    3332             : 
    3333           0 :     int32 plusw = GDrawGetText8Width(cv->gw,  _("+"), -1);
    3334           0 :     int32 plush = GDrawGetText8Height(cv->gw, _("+"), -1);
    3335           0 :     plusw = GDrawPointsToPixels(NULL,plusw+4);
    3336           0 :     plush = GDrawPointsToPixels(NULL,plush+4);
    3337           0 :     plush = MAX( plush, plusw ); // make it square.
    3338             :     
    3339             :      /* Remove Layer button */
    3340           0 :     label[0].text = (unichar_t *) _("-");
    3341           0 :     label[0].text_is_1byte = true;
    3342           0 :     gcd[i].gd.label = &label[0];
    3343           0 :     gcd[i].gd.pos.x = 7; gcd[i].gd.pos.y = 5; 
    3344           0 :     gcd[i].gd.pos.width  = plusw; gcd[i].gd.pos.height = plush;
    3345           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    3346           0 :     gcd[i].gd.cid = CID_RemoveLayer;
    3347           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Delete the current layer");
    3348           0 :     gcd[i].creator = GButtonCreate;
    3349           0 :     ++i;
    3350             : 
    3351             :      /* Add Layer button */
    3352           0 :     label[1].text = (unichar_t *) _("+");
    3353           0 :     label[1].text_is_1byte = true;
    3354           0 :     gcd[i].gd.label = &label[1];
    3355           0 :     gcd[i].gd.pos.x = 30; gcd[i].gd.pos.y = 5; 
    3356           0 :     gcd[i].gd.pos.width  = plusw; gcd[i].gd.pos.height = plush;
    3357           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    3358           0 :     gcd[i].gd.cid = CID_AddLayer;
    3359           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Add a new layer");
    3360           0 :     gcd[i].creator = GButtonCreate;
    3361           0 :     ++i;
    3362             : 
    3363             :      /* "Layers" label next to the add and remove buttons */
    3364           0 :     label[2].text = (unichar_t *) "";
    3365           0 :     label[2].text_is_1byte = true;
    3366           0 :     gcd[i].gd.label = &label[2];
    3367           0 :     gcd[i].gd.pos.x = 47; gcd[i].gd.pos.y = 5; 
    3368           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    3369           0 :     gcd[i].gd.cid = CID_LayersMenu;
    3370             :     /* gcd[i].gd.popup_msg = (unichar_t *) _("Rename the current layer"); */
    3371           0 :     gcd[i].creator = GLabelCreate;
    3372           0 :     ++i;
    3373             : 
    3374             :      /* Default visibility toggles for Fore, Back, and Guides */
    3375           0 :     gcd[i].gd.pos.x = viscol; gcd[i].gd.pos.y = 38; 
    3376           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    3377           0 :     if ( cv->showgrids ) gcd[i].gd.flags |= gg_cb_on;
    3378           0 :     gcd[i].gd.cid = CID_VGrid;
    3379           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    3380           0 :     gcd[i].creator = GVisibilityBoxCreate;
    3381           0 :     ++i;
    3382             : 
    3383           0 :     gcd[i].gd.pos.x = viscol; gcd[i].gd.pos.y = 38; 
    3384           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    3385           0 :     if ( cv->showback[0]&1 ) gcd[i].gd.flags |= gg_cb_on;
    3386           0 :     gcd[i].gd.cid = CID_VBack;
    3387           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    3388           0 :     gcd[i].creator = GVisibilityBoxCreate;
    3389           0 :     ++i;
    3390             : 
    3391           0 :     gcd[i].gd.pos.x = viscol; gcd[i].gd.pos.y = 21; 
    3392           0 :     gcd[i].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    3393           0 :     if ( cv->showfore ) gcd[i].gd.flags |= gg_cb_on;
    3394           0 :     gcd[i].gd.cid = CID_VFore;
    3395           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    3396           0 :     gcd[i].creator = GVisibilityBoxCreate;
    3397           0 :     ++i;
    3398             : 
    3399             : 
    3400             :      /* Scroll bar */
    3401           0 :     gcd[i].gd.pos.width = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
    3402           0 :     gcd[i].gd.pos.x = 0; /* <- these get updated to real values later */
    3403           0 :     gcd[i].gd.pos.y = 0;
    3404           0 :     gcd[i].gd.pos.height = 50;
    3405           0 :     gcd[i].gd.flags = gg_enabled|gg_pos_in_pixels|gg_sb_vert;
    3406           0 :     gcd[i].gd.cid = CID_SB;
    3407           0 :     gcd[i].creator = GScrollBarCreate;
    3408           0 :     layerinfo.sb_start = gcd[i].gd.pos.x;
    3409           0 :     ++i;
    3410             : 
    3411             :      /* Edit box for in place layer rename */
    3412           0 :     gcd[i].gd.pos.width=gcd[i].gd.pos.height=1;
    3413           0 :     gcd[i].gd.flags = gg_enabled|gg_pos_in_pixels|gg_utf8_popup;
    3414           0 :     gcd[i].gd.cid = CID_Edit;
    3415           0 :     gcd[i].gd.popup_msg = (unichar_t *) _("Type in new layer name");
    3416           0 :     gcd[i].creator = GTextFieldCreate;
    3417           0 :     ++i;
    3418             : 
    3419           0 :     GGadgetsCreate(cvlayers,gcd);
    3420           0 :     if ( cvvisible[0] )
    3421           0 :         GDrawSetVisible(cvlayers,true);
    3422           0 :     layers_max=2;
    3423             : 
    3424           0 :     gadget=GWidgetGetControl(cvlayers,CID_AddLayer);
    3425           0 :     GGadgetGetSize(gadget,&size);
    3426           0 :     layer_header_height = 0;
    3427           0 :     layer_footer_height = size.y + size.height;
    3428             : 
    3429           0 :     GGadgetGetSize(GWidgetGetControl(cvlayers,CID_VGrid),&size);
    3430           0 :     layer_height = size.height;
    3431           0 :     int32 w = GDrawGetText8Width(cvlayers, "W", -1);
    3432           0 :     layerinfo.column_width = w+6;
    3433             : 
    3434           0 :     layerinfo.active = CVLayer(&cv->b); /* the index of the active layer */
    3435           0 :     layerinfo.mo_col   = -2; /* -2 forces this variable to be updated. afterwords it will be -1 for nothing, or >=0 */
    3436           0 :     layerinfo.mo_layer = -2;
    3437           0 :     layerinfo.offtop   = 0;
    3438           0 :     layerinfo.rename_active = 0;
    3439             : 
    3440           0 :     GVisibilityBoxSetToMinWH(GWidgetGetControl(cvlayers,CID_VGrid));
    3441           0 :     GVisibilityBoxSetToMinWH(GWidgetGetControl(cvlayers,CID_VBack));
    3442           0 :     GVisibilityBoxSetToMinWH(GWidgetGetControl(cvlayers,CID_VFore));
    3443             : 
    3444           0 : return( cvlayers );
    3445             : }
    3446             : 
    3447             : 
    3448             : /* ***************** CVTools and other common palette functions follow ************ */
    3449             : 
    3450           0 : static void CVPopupInvoked(GWindow v, GMenuItem *mi, GEvent *e) {
    3451           0 :     CharView *cv = (CharView *) GDrawGetUserData(v);
    3452             :     int pos;
    3453             : 
    3454           0 :     pos = mi->mid;
    3455           0 :     if ( pos==cvt_spiro ) {
    3456           0 :         CVChangeSpiroMode(cv);
    3457           0 :     } else if ( cv->had_control ) {
    3458           0 :         if ( cv->cb1_tool!=pos ) {
    3459           0 :             cv->cb1_tool = cv_cb1_tool = pos;
    3460           0 :             GDrawRequestExpose(cvtools,NULL,false);
    3461             :         }
    3462             :     } else {
    3463           0 :         if ( cv->b1_tool!=pos ) {
    3464           0 :             cv->b1_tool = cv_b1_tool = pos;
    3465           0 :             GDrawRequestExpose(cvtools,NULL,false);
    3466             :         }
    3467             :     }
    3468           0 :     CVToolsSetCursor(cv,cv->had_control?ksm_control:0,NULL);
    3469           0 : }
    3470             : 
    3471           0 : static void CVPopupLayerInvoked(GWindow v, GMenuItem *mi, GEvent *e) {
    3472           0 :     CharView *cv = (CharView *) GDrawGetUserData(v);
    3473           0 :     int layer = mi->mid==0 ? 1 : mi->mid==1 ? 0 : -1;
    3474             : 
    3475           0 :     if ( layerinfo.active!=layer )
    3476           0 :         CVLSelectLayer(cv, layer);
    3477           0 : }
    3478             : 
    3479           0 : static void CVPopupSelectInvoked(GWindow v, GMenuItem *mi, GEvent *e) {
    3480           0 :     CharView *cv = (CharView *) GDrawGetUserData(v);
    3481             : 
    3482           0 :     switch ( mi->mid ) {
    3483             :       case 0:
    3484           0 :         CVPGetInfo(cv);
    3485           0 :       break;
    3486             :       case 1:
    3487           0 :         if ( cv->p.ref!=NULL )
    3488           0 :             CharViewCreate(cv->p.ref->sc,(FontView *) (cv->b.fv),-1);
    3489           0 :       break;
    3490             :       case 2:
    3491           0 :         CVAddAnchor(cv);
    3492           0 :       break;
    3493             :       case 3:
    3494           0 :         CVMakeClipPath(cv);
    3495           0 :       break;
    3496             :     case MIDL_MakeLine: {
    3497           0 :         _CVMenuMakeLine((CharViewBase *) cv,mi->mid==MIDL_MakeArc, e!=NULL && (e->u.mouse.state&ksm_meta));
    3498           0 :         break;
    3499             :     }
    3500             :     case MIDL_MakeArc: {
    3501           0 :         _CVMenuMakeLine((CharViewBase *) cv,mi->mid==MIDL_MakeArc, e!=NULL && (e->u.mouse.state&ksm_meta));
    3502           0 :         break;
    3503             :     }
    3504             :     case MIDL_InsertPtOnSplineAt: {
    3505           0 :         _CVMenuInsertPt( cv );
    3506           0 :         break;
    3507             :     }
    3508             :     case MIDL_NamePoint: {
    3509           0 :         if ( cv->p.sp )
    3510           0 :             _CVMenuNamePoint( cv, cv->p.sp );
    3511           0 :         break;
    3512             :     }
    3513             :     case MIDL_NameContour: {
    3514           0 :         _CVMenuNameContour( cv );
    3515           0 :         break;
    3516             :     }
    3517             :       
    3518             :     }
    3519           0 : }
    3520             : 
    3521           0 : void CVToolsPopup(CharView *cv, GEvent *event) {
    3522             :     GMenuItem mi[125];
    3523           0 :     int i=0;
    3524           0 :     int j=0;
    3525           0 :     int anysel=0;
    3526             :     static char *selectables[] = { N_("Get Info..."), N_("Open Reference"), N_("Add Anchor"), NULL };
    3527             : 
    3528           0 :     memset(mi,'\0',sizeof(mi));
    3529           0 :     anysel = CVTestSelectFromEvent(cv,event);
    3530             : 
    3531           0 :     if( anysel )
    3532             :     {
    3533           0 :             mi[i].ti.text = (unichar_t *) _("Curve");
    3534           0 :             mi[i].ti.text_is_1byte = true;
    3535           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3536           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3537           0 :             mi[i].mid = MID_Curve;
    3538           0 :             mi[i].invoke = CVMenuPointType;
    3539           0 :             i++;
    3540           0 :             mi[i].ti.text = (unichar_t *) _("HVCurve");
    3541           0 :             mi[i].ti.text_is_1byte = true;
    3542           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3543           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3544           0 :             mi[i].mid = MID_HVCurve;
    3545           0 :             mi[i].invoke = CVMenuPointType;
    3546           0 :             i++;
    3547           0 :             mi[i].ti.text = (unichar_t *) _("Corner");
    3548           0 :             mi[i].ti.text_is_1byte = true;
    3549           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3550           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3551           0 :             mi[i].mid = MID_Corner;
    3552           0 :             mi[i].invoke = CVMenuPointType;
    3553           0 :             i++;
    3554           0 :             mi[i].ti.text = (unichar_t *) _("Tangent");
    3555           0 :             mi[i].ti.text_is_1byte = true;
    3556           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3557           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3558           0 :             mi[i].mid = MID_Tangent;
    3559           0 :             mi[i].invoke = CVMenuPointType;
    3560           0 :             i++;
    3561             : 
    3562           0 :             mi[i].ti.line = true;
    3563           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3564           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3565           0 :             i++;
    3566             : 
    3567           0 :             mi[i].ti.text = (unichar_t *) _("Merge");
    3568           0 :             mi[i].ti.text_is_1byte = true;
    3569           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3570           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3571           0 :             mi[i].mid = MID_Merge;
    3572           0 :             mi[i].invoke = CVMerge;
    3573           0 :             i++;
    3574           0 :             mi[i].ti.text = (unichar_t *) _("Merge to Line");
    3575           0 :             mi[i].ti.text_is_1byte = true;
    3576           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3577           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3578           0 :             mi[i].mid = MID_MergeToLine;
    3579           0 :             mi[i].invoke = CVMergeToLine;
    3580           0 :             i++;
    3581             : 
    3582           0 :             mi[i].ti.text = (unichar_t *) _("Align Points");
    3583           0 :             mi[i].ti.text_is_1byte = true;
    3584           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3585           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3586           0 :             mi[i].mid = MID_Average;
    3587           0 :             mi[i].invoke = CVMenuConstrain;
    3588           0 :             i++;
    3589             :         
    3590             :     }
    3591             :     
    3592             :     
    3593           0 :     if( !anysel )
    3594             :     {
    3595           0 :         for ( i=0;i<=cvt_skew; ++i ) {
    3596           0 :             char *msg = _(popupsres[i]);
    3597           0 :             if ( cv->b.sc->inspiro && hasspiro()) {
    3598           0 :                 if ( i==cvt_spirog2 )
    3599           0 :                     msg = _("Add a g2 curve point");
    3600           0 :                 else if ( i==cvt_spiroleft )
    3601           0 :                     msg = _("Add a left \"tangent\" point");
    3602           0 :                 else if ( i==cvt_spiroright )
    3603           0 :                     msg = _("Add a right \"tangent\" point");
    3604             :             }
    3605           0 :             mi[i].ti.text = (unichar_t *) msg;
    3606           0 :             mi[i].ti.text_is_1byte = true;
    3607           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3608           0 :             mi[i].ti.bg = COLOR_DEFAULT;
    3609           0 :             mi[i].mid = i;
    3610           0 :             mi[i].invoke = CVPopupInvoked;
    3611             :         }
    3612             :     }
    3613             :     
    3614           0 :     if( !anysel )
    3615             :     {
    3616           0 :         if ( cvlayers!=NULL && !cv->b.sc->parent->multilayer ) {
    3617           0 :             mi[i].ti.line = true;
    3618           0 :             mi[i].ti.fg = COLOR_DEFAULT;
    3619           0 :             mi[i++].ti.bg = COLOR_DEFAULT;
    3620           0 :             for ( j=0;j<3; ++j, ++i ) {
    3621           0 :                 mi[i].ti.text = (unichar_t *) _(editablelayers[j]);
    3622           0 :                 mi[i].ti.text_in_resource = true;
    3623           0 :                 mi[i].ti.text_is_1byte = true;
    3624           0 :                 mi[i].ti.fg = COLOR_DEFAULT;
    3625           0 :                 mi[i].ti.bg = COLOR_DEFAULT;
    3626           0 :                 mi[i].mid = j;
    3627           0 :                 mi[i].invoke = CVPopupLayerInvoked;
    3628             :             }
    3629             :         }
    3630             :     }
    3631             : 
    3632           0 :     if( i > 0 ) {
    3633           0 :         mi[i].ti.line = true;
    3634           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3635           0 :         mi[i++].ti.bg = COLOR_DEFAULT;
    3636             :     }
    3637             :     
    3638           0 :     for ( j=0; selectables[j]!=0; ++j )
    3639             :     {
    3640           0 :         if ( (!anysel && j!=2 ) ||
    3641           0 :                 ( j==0 && cv->p.spline ) ||
    3642           0 :                 ( j==1 && !cv->p.ref ))
    3643             :         {
    3644             :             // don't show them a disabled item
    3645           0 :             continue;
    3646             :             
    3647             :             // or, if the above "continue;" is commented then keep the entry
    3648             :             // but don't let them select it 
    3649             :             mi[i].ti.disabled = true; 
    3650             :         }
    3651           0 :         mi[i].ti.text = (unichar_t *) _(selectables[j]);
    3652           0 :         mi[i].ti.text_is_1byte = true;
    3653           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3654           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3655           0 :         mi[i].mid = j;
    3656           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3657           0 :         i++;
    3658             :     }
    3659             : 
    3660           0 :     if ( anysel ) {
    3661           0 :         mi[i].ti.text = (unichar_t *)_("Name Point...");
    3662           0 :         mi[i].ti.text_is_1byte = true;
    3663           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3664           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3665           0 :         mi[i].mid = MIDL_NamePoint;
    3666           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3667           0 :         i++;
    3668             :     }
    3669             : 
    3670           0 :     if ( cv->b.sc->parent->multilayer ) {
    3671           0 :         mi[i].ti.text = (unichar_t *) _("Make Clip Path");
    3672           0 :         mi[i].ti.text_is_1byte = true;
    3673           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3674           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3675           0 :         mi[i].mid = j;
    3676           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3677           0 :         i++; 
    3678             :     }
    3679             : 
    3680           0 :     int cnt = CVCountSelectedPoints(cv);
    3681           0 :     printf(".... count:%d\n", cnt );
    3682           0 :     if( cnt > 1 ) {
    3683           0 :         mi[i].ti.text = (unichar_t *) _("Make Line");
    3684           0 :         mi[i].ti.text_is_1byte = true;
    3685           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3686           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3687           0 :         mi[i].mid = MIDL_MakeLine;
    3688           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3689           0 :         i++;
    3690             : 
    3691           0 :         mi[i].ti.text = (unichar_t *) _("Make Arc");
    3692           0 :         mi[i].ti.text_is_1byte = true;
    3693           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3694           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3695           0 :         mi[i].mid = MIDL_MakeArc;
    3696           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3697           0 :         i++;
    3698             : 
    3699           0 :         mi[i].ti.text = (unichar_t *) _("Insert Point On Spline At...");
    3700           0 :         mi[i].ti.text_is_1byte = true;
    3701           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3702           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3703           0 :         mi[i].mid = MIDL_InsertPtOnSplineAt;
    3704           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3705           0 :         i++;
    3706             : 
    3707           0 :         mi[i].ti.text = (unichar_t *) _("Name Point");
    3708           0 :         mi[i].ti.text_is_1byte = true;
    3709           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3710           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3711           0 :         mi[i].mid = MIDL_NamePoint;
    3712           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3713           0 :         i++;
    3714             : 
    3715           0 :         mi[i].ti.text = (unichar_t *) _("Name Contour");
    3716           0 :         mi[i].ti.text_is_1byte = true;
    3717           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    3718           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    3719           0 :         mi[i].mid = MIDL_NameContour;
    3720           0 :         mi[i].invoke = CVPopupSelectInvoked;
    3721           0 :         i++;
    3722             :     }
    3723             : 
    3724           0 :     cv->had_control = (event->u.mouse.state&ksm_control)?1:0;
    3725           0 :     GMenuCreatePopupMenuWithName(cv->v,event, "Popup", mi);
    3726           0 : }
    3727             : 
    3728           0 : static void CVPaletteCheck(CharView *cv) {
    3729           0 :     if ( cvtools==NULL ) {
    3730           0 :         if ( palettes_fixed ) {
    3731           0 :             cvtoolsoff.x = 0; cvtoolsoff.y = 0;
    3732             :         }
    3733           0 :         CVMakeTools(cv);
    3734             :     }
    3735           0 :     if ( cv->b.sc->parent->multilayer && cvlayers2==NULL ) {
    3736           0 :         if ( palettes_fixed ) {
    3737           0 :             cvlayersoff.x = 0; cvlayersoff.y = getToolbarHeight(cv)+45/*25*/;   /* 45 is right if there's decor, 25 when none. twm gives none, kde gives decor */
    3738             :         }
    3739           0 :         CVMakeLayers2(cv);
    3740           0 :     } else if ( !cv->b.sc->parent->multilayer && cvlayers==NULL ) {
    3741           0 :         if ( palettes_fixed ) {
    3742           0 :             cvlayersoff.x = 0; cvlayersoff.y = getToolbarHeight(cv)+45/*25*/;   /* 45 is right if there's decor, 25 when none. twm gives none, kde gives decor */
    3743             :         }
    3744           0 :         CVMakeLayers(cv);
    3745             :     }
    3746           0 : }
    3747             : 
    3748           0 : int CVPaletteIsVisible(CharView *cv,int which) {
    3749           0 :     CVPaletteCheck(cv);
    3750           0 :     if ( which==1 )
    3751           0 : return( cvtools!=NULL && GDrawIsVisible(cvtools) );
    3752             : 
    3753           0 :     if ( cv->b.sc->parent->multilayer )
    3754           0 : return( cvlayers2!=NULL && GDrawIsVisible(cvlayers2));
    3755             : 
    3756           0 : return( cvlayers!=NULL && GDrawIsVisible(cvlayers) );
    3757             : }
    3758             : 
    3759           0 : void CVPaletteSetVisible(CharView *cv,int which,int visible) {
    3760           0 :     CVPaletteCheck(cv);
    3761           0 :     if ( which==1 && cvtools!=NULL)
    3762           0 :         GDrawSetVisible(cvtools,visible );
    3763           0 :     else if ( which==0 && cv->b.sc->parent->multilayer && cvlayers2!=NULL )
    3764           0 :         GDrawSetVisible(cvlayers2,visible );
    3765           0 :     else if ( which==0 && cvlayers!=NULL )
    3766           0 :         GDrawSetVisible(cvlayers,visible );
    3767           0 :     cvvisible[which] = visible;
    3768           0 :     SavePrefs(true);
    3769           0 : }
    3770             : 
    3771           0 : void CVPalettesRaise(CharView *cv) {
    3772           0 :     if ( cvtools!=NULL && GDrawIsVisible(cvtools))
    3773           0 :         GDrawRaise(cvtools);
    3774           0 :     if ( cvlayers!=NULL && GDrawIsVisible(cvlayers))
    3775           0 :         GDrawRaise(cvlayers);
    3776           0 :     if ( cvlayers2!=NULL && GDrawIsVisible(cvlayers2))
    3777           0 :         GDrawRaise(cvlayers2);
    3778           0 : }
    3779             : 
    3780           0 : void _CVPaletteActivate(CharView *cv,int force) {
    3781             :     CharView *old;
    3782             : 
    3783           0 :     CVPaletteCheck(cv);
    3784           0 :     if ( layers2_active!=-1 && layers2_active!=cv->b.sc->parent->multilayer ) {
    3785           0 :         if ( !cvvisible[0] ) {
    3786           0 :             if ( cvlayers2!=NULL ) GDrawSetVisible(cvlayers2,false);
    3787           0 :             if ( cvlayers !=NULL ) GDrawSetVisible(cvlayers,false);
    3788           0 :         } else if ( layers2_active && cvlayers!=NULL ) {
    3789           0 :             if ( cvlayers2!=NULL ) GDrawSetVisible(cvlayers2,false);
    3790           0 :             GDrawSetVisible(cvlayers,true);
    3791           0 :         } else if ( !layers2_active && cvlayers2!=NULL ) {
    3792           0 :             if ( cvlayers !=NULL ) GDrawSetVisible(cvlayers,false);
    3793           0 :             GDrawSetVisible(cvlayers2,true);
    3794             :         }
    3795             :     }
    3796           0 :     layers2_active = cv->b.sc->parent->multilayer;
    3797           0 :     if ( (old = GDrawGetUserData(cvtools))!=cv || force) {
    3798           0 :         if ( old!=NULL ) {
    3799           0 :             SaveOffsets(old->gw,cvtools,&cvtoolsoff);
    3800           0 :             if ( old->b.sc->parent->multilayer )
    3801           0 :                 SaveOffsets(old->gw,cvlayers2,&cvlayersoff);
    3802             :             else
    3803           0 :                 SaveOffsets(old->gw,cvlayers,&cvlayersoff);
    3804             :         }
    3805           0 :         GDrawSetUserData(cvtools,cv);
    3806           0 :         if ( cv->b.sc->parent->multilayer ) {
    3807           0 :             LayersSwitch(cv);
    3808           0 :             GDrawSetUserData(cvlayers2,cv);
    3809             :         } else {
    3810           0 :             GDrawSetUserData(cvlayers,cv);
    3811           0 :             CVLCheckLayerCount(cv,true);
    3812             :         }
    3813           0 :         if ( palettes_docked ) {
    3814           0 :             ReparentFixup(cvtools,cv->v,0,0,getToolbarWidth(cv),getToolbarHeight(cv));
    3815           0 :             if ( cv->b.sc->parent->multilayer )
    3816           0 :                 ReparentFixup(cvlayers2,cv->v,0,getToolbarHeight(cv)+2,0,0);
    3817             :             else
    3818           0 :                 ReparentFixup(cvlayers,cv->v,0,getToolbarHeight(cv)+2,0,0);
    3819             :         } else {
    3820           0 :             if ( cvvisible[0]) {
    3821           0 :                 if ( cv->b.sc->parent->multilayer )
    3822           0 :                     RestoreOffsets(cv->gw,cvlayers2,&cvlayersoff);
    3823             :                 else
    3824           0 :                     RestoreOffsets(cv->gw,cvlayers,&cvlayersoff);
    3825             :             }
    3826           0 :             if ( cvvisible[1])
    3827           0 :                 RestoreOffsets(cv->gw,cvtools,&cvtoolsoff);
    3828             :         }
    3829           0 :         GDrawSetVisible(cvtools,cvvisible[1]);
    3830           0 :         if ( cv->b.sc->parent->multilayer )
    3831           0 :             GDrawSetVisible(cvlayers2,cvvisible[0]);
    3832             :         else
    3833           0 :             GDrawSetVisible(cvlayers,cvvisible[0]);
    3834           0 :         if ( cvvisible[1]) {
    3835           0 :             cv->showing_tool = cvt_none;
    3836           0 :             CVToolsSetCursor(cv,0,NULL);
    3837           0 :             GDrawRequestExpose(cvtools,NULL,false);
    3838             :         }
    3839           0 :         if ( cvvisible[0])
    3840           0 :             CVLayersSet(cv);
    3841             :     }
    3842           0 :     if ( bvtools!=NULL ) {
    3843           0 :         BitmapView *bv = GDrawGetUserData(bvtools);
    3844           0 :         if ( bv!=NULL ) {
    3845           0 :             SaveOffsets(bv->gw,bvtools,&bvtoolsoff);
    3846           0 :             SaveOffsets(bv->gw,bvlayers,&bvlayersoff);
    3847           0 :             if ( !bv->shades_hidden )
    3848           0 :                 SaveOffsets(bv->gw,bvshades,&bvshadesoff);
    3849           0 :             GDrawSetUserData(bvtools,NULL);
    3850           0 :             GDrawSetUserData(bvlayers,NULL);
    3851           0 :             GDrawSetUserData(bvshades,NULL);
    3852             :         }
    3853           0 :         GDrawSetVisible(bvtools,false);
    3854           0 :         GDrawSetVisible(bvlayers,false);
    3855           0 :         GDrawSetVisible(bvshades,false);
    3856             :     }
    3857           0 : }
    3858             : 
    3859           0 : void CVPaletteActivate(CharView *cv) {
    3860           0 :     _CVPaletteActivate(cv,false);
    3861           0 : }
    3862             : 
    3863           0 : void CV_LayerPaletteCheck(SplineFont *sf) {
    3864             :     CharView *old;
    3865             : 
    3866           0 :     if ( cvlayers!=NULL ) {
    3867           0 :         if ( (old = GDrawGetUserData(cvlayers))!=NULL ) {
    3868           0 :             if ( old->b.sc->parent==sf )
    3869           0 :                 _CVPaletteActivate(old,true);
    3870             :         }
    3871             :     }
    3872           0 : }
    3873             : 
    3874             : /* make the charview point to the correct layer heads for the specified glyph */
    3875           0 : void SFLayerChange(SplineFont *sf) {
    3876             :     CharView *old, *cv;
    3877             :     int i;
    3878             : 
    3879           0 :     for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
    3880           0 :         SplineChar *sc = sf->glyphs[i];
    3881           0 :         for ( cv=(CharView *) (sc->views); cv!=NULL; cv=(CharView *) (cv->b.next) ) {
    3882           0 :             cv->b.layerheads[dm_back] = &sc->layers[ly_back];
    3883           0 :             cv->b.layerheads[dm_fore] = &sc->layers[ly_fore];
    3884           0 :             cv->b.layerheads[dm_grid] = &sf->grid;
    3885             :         }
    3886             :     }
    3887             : 
    3888           0 :     if ( cvtools==NULL )
    3889           0 : return;                                 /* No charviews open */
    3890           0 :     old = GDrawGetUserData(cvtools);
    3891           0 :     if ( old==NULL || old->b.sc->parent!=sf )     /* Irrelevant */
    3892           0 : return;
    3893           0 :     _CVPaletteActivate(old,true);
    3894             : }
    3895             : 
    3896           0 : void CVPalettesHideIfMine(CharView *cv) {
    3897           0 :     if ( cvtools==NULL )
    3898           0 : return;
    3899           0 :     if ( GDrawGetUserData(cvtools)==cv ) {
    3900           0 :         SaveOffsets(cv->gw,cvtools,&cvtoolsoff);
    3901           0 :         GDrawSetVisible(cvtools,false);
    3902           0 :         GDrawSetUserData(cvtools,NULL);
    3903           0 :         if ( cv->b.sc->parent->multilayer && cvlayers2!=NULL ) {
    3904           0 :             SaveOffsets(cv->gw,cvlayers2,&cvlayersoff);
    3905           0 :             GDrawSetVisible(cvlayers2,false);
    3906           0 :             GDrawSetUserData(cvlayers2,NULL);
    3907             :         } else {
    3908           0 :             SaveOffsets(cv->gw,cvlayers,&cvlayersoff);
    3909           0 :             GDrawSetVisible(cvlayers,false);
    3910           0 :             GDrawSetUserData(cvlayers,NULL);
    3911             :         }
    3912             :     }
    3913             : }
    3914             : 
    3915           0 : int CVPalettesWidth(void) {
    3916           0 : return( GGadgetScale(CV_LAYERS2_WIDTH));
    3917             : }
    3918             : 
    3919             : /* ************************************************************************** */
    3920             : /* **************************** Bitmap Palettes ***************************** */
    3921             : /* ************************************************************************** */
    3922             : 
    3923           0 : static void BVLayersSet(BitmapView *bv) {
    3924           0 :     GGadgetSetChecked(GWidgetGetControl(bvlayers,CID_VFore),bv->showfore);
    3925           0 :     GGadgetSetChecked(GWidgetGetControl(bvlayers,CID_VBack),bv->showoutline);
    3926           0 :     GGadgetSetChecked(GWidgetGetControl(bvlayers,CID_VGrid),bv->showgrid);
    3927           0 : }
    3928             : 
    3929           0 : static int bvlayers_e_h(GWindow gw, GEvent *event) {
    3930           0 :     BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
    3931             : 
    3932           0 :     if ( event->type==et_destroy ) {
    3933           0 :         bvlayers = NULL;
    3934           0 : return( true );
    3935             :     }
    3936             : 
    3937           0 :     if ( bv==NULL )
    3938           0 : return( true );
    3939             : 
    3940           0 :     switch ( event->type ) {
    3941             :       case et_close:
    3942           0 :         GDrawSetVisible(gw,false);
    3943           0 :       break;
    3944             :       case et_char: case et_charup:
    3945           0 :         PostCharToWindow(bv->gw,event);
    3946           0 :       break;
    3947             :       case et_controlevent:
    3948           0 :         if ( event->u.control.subtype == et_radiochanged ) {
    3949           0 :             switch(GGadgetGetCid(event->u.control.g)) {
    3950             :               case CID_VFore:
    3951           0 :                 BVShows.showfore = bv->showfore = GGadgetIsChecked(event->u.control.g);
    3952           0 :               break;
    3953             :               case CID_VBack:
    3954           0 :                 BVShows.showoutline = bv->showoutline = GGadgetIsChecked(event->u.control.g);
    3955           0 :               break;
    3956             :               case CID_VGrid:
    3957           0 :                 BVShows.showgrid = bv->showgrid = GGadgetIsChecked(event->u.control.g);
    3958           0 :               break;
    3959             :             }
    3960           0 :             GDrawRequestExpose(bv->v,NULL,false);
    3961             :         }
    3962           0 :       break;
    3963             :     }
    3964           0 : return( true );
    3965             : }
    3966             : 
    3967           0 : GWindow BVMakeLayers(BitmapView *bv) {
    3968             :     GRect r;
    3969             :     GWindowAttrs wattrs;
    3970             :     GGadgetCreateData gcd[8], boxes[2], *hvarray[5][3];
    3971             :     GTextInfo label[8];
    3972             :     static GBox radio_box = { bt_none, bs_rect, 0, 0, 0, 0, 0, 0, 0, 0, COLOR_DEFAULT, COLOR_DEFAULT, 0, 0, 0, 0, 0, 0, 0 };
    3973             :     FontRequest rq;
    3974             :     int i;
    3975             : 
    3976           0 :     if ( bvlayers!=NULL )
    3977           0 : return(bvlayers);
    3978           0 :     memset(&wattrs,0,sizeof(wattrs));
    3979           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
    3980           0 :     wattrs.event_masks = -1;
    3981           0 :     wattrs.cursor = ct_mypointer;
    3982           0 :     wattrs.positioned = true;
    3983           0 :     wattrs.is_dlg = true;
    3984           0 :     wattrs.utf8_window_title = _("Layers");
    3985             : 
    3986           0 :     r.width = GGadgetScale(BV_LAYERS_WIDTH); r.height = BV_LAYERS_HEIGHT;
    3987           0 :     r.x = -r.width-6; r.y = bv->mbh+BV_TOOLS_HEIGHT+45/*25*/;        /* 45 is right if there's decor, is in kde, not in twm. Sigh */
    3988           0 :     if ( palettes_docked ) {
    3989           0 :         r.x = 0; r.y = BV_TOOLS_HEIGHT+4;
    3990           0 :     } else if ( palettes_fixed ) {
    3991           0 :         r.x = 0; r.y = BV_TOOLS_HEIGHT+45;
    3992             :     }
    3993           0 :     bvlayers = CreatePalette( bv->gw, &r, bvlayers_e_h, bv, &wattrs, bv->v );
    3994             : 
    3995           0 :     memset(&label,0,sizeof(label));
    3996           0 :     memset(&gcd,0,sizeof(gcd));
    3997           0 :     memset(&boxes,0,sizeof(boxes));
    3998             : 
    3999           0 :     if ( layersfont==NULL ) {
    4000           0 :         memset(&rq,'\0',sizeof(rq));
    4001           0 :         rq.utf8_family_name = SANS_UI_FAMILIES;
    4002           0 :         rq.point_size = -12;
    4003           0 :         rq.weight = 400;
    4004           0 :         layersfont = GDrawInstanciateFont(cvlayers2,&rq);
    4005           0 :         layersfont = GResourceFindFont("LayersPalette.Font",layersfont);
    4006             :     }
    4007           0 :     for ( i=0; i<sizeof(label)/sizeof(label[0]); ++i )
    4008           0 :         label[i].font = layersfont;
    4009             : 
    4010             : /* GT: Abbreviation for "Visible" */
    4011           0 :     label[0].text = (unichar_t *) _("V");
    4012           0 :     label[0].text_is_1byte = true;
    4013           0 :     gcd[0].gd.label = &label[0];
    4014           0 :     gcd[0].gd.pos.x = 7; gcd[0].gd.pos.y = 5; 
    4015           0 :     gcd[0].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    4016           0 :     gcd[0].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    4017           0 :     gcd[0].creator = GLabelCreate;
    4018             : 
    4019           0 :     label[1].text = (unichar_t *) "Layer";
    4020           0 :     label[1].text_is_1byte = true;
    4021           0 :     gcd[1].gd.label = &label[1];
    4022           0 :     gcd[1].gd.pos.x = 23; gcd[1].gd.pos.y = 5; 
    4023           0 :     gcd[1].gd.flags = gg_enabled|gg_visible|gg_pos_in_pixels|gg_utf8_popup;
    4024           0 :     gcd[1].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    4025           0 :     gcd[1].creator = GLabelCreate;
    4026           0 :     hvarray[0][0] = &gcd[0]; hvarray[0][1] = &gcd[1]; hvarray[0][2] = NULL;
    4027             : 
    4028           0 :     gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = 21; 
    4029           0 :     gcd[2].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    4030           0 :     gcd[2].gd.cid = CID_VFore;
    4031           0 :     gcd[2].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    4032           0 :     gcd[2].gd.box = &radio_box;
    4033           0 :     gcd[2].creator = GCheckBoxCreate;
    4034           0 :     label[2].text = (unichar_t *) _("Bitmap");
    4035           0 :     label[2].text_is_1byte = true;
    4036           0 :     gcd[2].gd.label = &label[2];
    4037           0 :     hvarray[1][0] = &gcd[2]; hvarray[1][1] = GCD_ColSpan; hvarray[1][2] = NULL;
    4038             : 
    4039           0 :     gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 37; 
    4040           0 :     gcd[3].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    4041           0 :     gcd[3].gd.cid = CID_VBack;
    4042           0 :     gcd[3].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    4043           0 :     gcd[3].gd.box = &radio_box;
    4044           0 :     gcd[3].creator = GCheckBoxCreate;
    4045           0 :     label[3].text = (unichar_t *) _("Outline");
    4046           0 :     label[3].text_is_1byte = true;
    4047           0 :     gcd[3].gd.label = &label[3];
    4048           0 :     hvarray[2][0] = &gcd[3]; hvarray[2][1] = GCD_ColSpan; hvarray[2][2] = NULL;
    4049             : 
    4050           0 :     gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = 53; 
    4051           0 :     gcd[4].gd.flags = gg_enabled|gg_visible|gg_dontcopybox|gg_pos_in_pixels|gg_utf8_popup;
    4052           0 :     gcd[4].gd.cid = CID_VGrid;
    4053           0 :     gcd[4].gd.popup_msg = (unichar_t *) _("Is Layer Visible?");
    4054           0 :     gcd[4].gd.box = &radio_box;
    4055           0 :     gcd[4].creator = GCheckBoxCreate;
    4056           0 :     label[4].text = (unichar_t *) _("_Guide");
    4057           0 :     label[4].text_is_1byte = true;
    4058           0 :     label[4].text_in_resource = true;
    4059           0 :     gcd[4].gd.label = &label[4];
    4060           0 :     hvarray[3][0] = &gcd[4]; hvarray[3][1] = GCD_ColSpan; hvarray[3][2] = NULL;
    4061           0 :     hvarray[4][0] = NULL;
    4062             : 
    4063           0 :     if ( bv->showfore ) gcd[2].gd.flags |= gg_cb_on;
    4064           0 :     if ( bv->showoutline ) gcd[3].gd.flags |= gg_cb_on;
    4065           0 :     if ( bv->showgrid ) gcd[4].gd.flags |= gg_cb_on;
    4066             : 
    4067           0 :     boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
    4068           0 :     boxes[0].gd.flags = gg_enabled|gg_visible;
    4069           0 :     boxes[0].gd.u.boxelements = hvarray[0];
    4070           0 :     boxes[0].creator = GHVGroupCreate;
    4071             : 
    4072           0 :     GGadgetsCreate(bvlayers,boxes);
    4073           0 :     GHVBoxFitWindow(boxes[0].ret);
    4074             : 
    4075           0 :     if ( bvvisible[0] )
    4076           0 :         GDrawSetVisible(bvlayers,true);
    4077           0 : return( bvlayers );
    4078             : }
    4079             : 
    4080             : struct shades_layout {
    4081             :     int depth;
    4082             :     int div;
    4083             :     int cnt;            /* linear number of squares */
    4084             :     int size;
    4085             : };
    4086             : 
    4087           0 : static void BVShadesDecompose(BitmapView *bv, struct shades_layout *lay) {
    4088             :     GRect r;
    4089             :     int temp;
    4090             : 
    4091           0 :     GDrawGetSize(bvshades,&r);
    4092           0 :     lay->depth = BDFDepth(bv->bdf);
    4093           0 :     lay->div = 255/((1<<lay->depth)-1);
    4094           0 :     lay->cnt = lay->depth==8 ? 16 : lay->depth;
    4095           0 :     temp = r.width>r.height ? r.height : r.width;
    4096           0 :     lay->size = (temp-8+1)/lay->cnt - 1;
    4097           0 : }
    4098             : 
    4099           0 : static void BVShadesExpose(GWindow pixmap, BitmapView *bv, GRect *r) {
    4100             :     struct shades_layout lay;
    4101             :     GRect old;
    4102             :     int i,j,index;
    4103             :     GRect block;
    4104           0 :     Color bg = default_background;
    4105           0 :     int greybg = (3*COLOR_RED(bg)+6*COLOR_GREEN(bg)+COLOR_BLUE(bg))/10;
    4106             : 
    4107           0 :     GDrawSetLineWidth(pixmap,0);
    4108           0 :     BVShadesDecompose(bv,&lay);
    4109           0 :     GDrawPushClip(pixmap,r,&old);
    4110           0 :     for ( i=0; i<=lay.cnt; ++i ) {
    4111           0 :         int p = 3+i*(lay.size+1);
    4112           0 :         int m = 8+lay.cnt*(lay.size+1);
    4113           0 :         GDrawDrawLine(pixmap,p,0,p,m,bg);
    4114           0 :         GDrawDrawLine(pixmap,0,p,m,p,bg);
    4115             :     }
    4116           0 :     block.width = block.height = lay.size;
    4117           0 :     for ( i=0; i<lay.cnt; ++i ) {
    4118           0 :         block.y = 4 + i*(lay.size+1);
    4119           0 :         for ( j=0; j<lay.cnt; ++j ) {
    4120           0 :             block.x = 4 + j*(lay.size+1);
    4121           0 :             index = (i*lay.cnt+j)*lay.div;
    4122           0 :             if (( bv->color >= index - lay.div/2 &&
    4123           0 :                         bv->color <= index + lay.div/2 ) ||
    4124           0 :                  ( bv->color_under_cursor >= index - lay.div/2 &&
    4125           0 :                     bv->color_under_cursor <= index + lay.div/2 )) {
    4126             :                 GRect outline;
    4127           0 :                 outline.x = block.x-1; outline.y = block.y-1;
    4128           0 :                 outline.width = block.width+1; outline.height = block.height+1;
    4129           0 :                 GDrawDrawRect(pixmap,&outline,
    4130           0 :                     ( bv->color >= index - lay.div/2 &&
    4131           0 :                         bv->color <= index + lay.div/2 )?0x00ff00:0xffffff);
    4132             :             }
    4133           0 :             index = (255-index) * greybg / 255;
    4134           0 :             GDrawFillRect(pixmap,&block,0x010101*index);
    4135             :         }
    4136             :     }
    4137           0 : }
    4138             : 
    4139           0 : static void BVShadesMouse(BitmapView *bv, GEvent *event) {
    4140             :     struct shades_layout lay;
    4141             :     int i, j;
    4142             : 
    4143           0 :     GGadgetEndPopup();
    4144           0 :     if ( event->type == et_mousemove && !bv->shades_down )
    4145           0 : return;
    4146           0 :     BVShadesDecompose(bv,&lay);
    4147           0 :     if ( event->u.mouse.x<4 || event->u.mouse.y<4 ||
    4148           0 :             event->u.mouse.x>=4+lay.cnt*(lay.size+1) ||
    4149           0 :             event->u.mouse.y>=4+lay.cnt*(lay.size+1) )
    4150           0 : return;
    4151           0 :     i = (event->u.mouse.y-4)/(lay.size+1);
    4152           0 :     j = (event->u.mouse.x-4)/(lay.size+1);
    4153           0 :     if ( bv->color != (i*lay.cnt + j)*lay.div ) {
    4154           0 :         bv->color = (i*lay.cnt + j)*lay.div;
    4155           0 :         GDrawRequestExpose(bvshades,NULL,false);
    4156             :     }
    4157           0 :     if ( event->type == et_mousedown ) bv->shades_down = true;
    4158           0 :     else if ( event->type == et_mouseup ) bv->shades_down = false;
    4159           0 :     if ( event->type == et_mouseup )
    4160           0 :         GDrawRequestExpose(bv->gw,NULL,false);
    4161             : }
    4162             : 
    4163           0 : static int bvshades_e_h(GWindow gw, GEvent *event) {
    4164           0 :     BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
    4165             : 
    4166           0 :     if ( event->type==et_destroy ) {
    4167           0 :         bvshades = NULL;
    4168           0 : return( true );
    4169             :     }
    4170             : 
    4171           0 :     if ( bv==NULL )
    4172           0 : return( true );
    4173             : 
    4174           0 :     switch ( event->type ) {
    4175             :       case et_expose:
    4176           0 :         BVShadesExpose(gw,bv,&event->u.expose.rect);
    4177           0 :       break;
    4178             :       case et_mousemove:
    4179             :       case et_mouseup:
    4180             :       case et_mousedown:
    4181           0 :         BVShadesMouse(bv,event);
    4182           0 :       break;
    4183             :       case et_char: case et_charup:
    4184           0 :         PostCharToWindow(bv->gw,event);
    4185           0 :       break;
    4186             :       case et_destroy:
    4187           0 :       break;
    4188             :       case et_close:
    4189           0 :         GDrawSetVisible(gw,false);
    4190           0 :       break;
    4191             :     }
    4192           0 : return( true );
    4193             : }
    4194             : 
    4195           0 : static GWindow BVMakeShades(BitmapView *bv) {
    4196             :     GRect r;
    4197             :     GWindowAttrs wattrs;
    4198             : 
    4199           0 :     if ( bvshades!=NULL )
    4200           0 : return( bvshades );
    4201           0 :     memset(&wattrs,0,sizeof(wattrs));
    4202           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg/*|wam_backcol*/;
    4203           0 :     wattrs.event_masks = -1;
    4204           0 :     wattrs.cursor = ct_eyedropper;
    4205           0 :     wattrs.positioned = true;
    4206           0 :     wattrs.is_dlg = true;
    4207           0 :     wattrs.background_color = 0xffffff;
    4208           0 :     wattrs.utf8_window_title = _("Shades");
    4209             : 
    4210           0 :     r.width = BV_SHADES_HEIGHT; r.height = r.width;
    4211           0 :     r.x = -r.width-6; r.y = bv->mbh+225;
    4212           0 :     if ( palettes_docked ) {
    4213           0 :         r.x = 0; r.y = BV_TOOLS_HEIGHT+BV_LAYERS_HEIGHT+4;
    4214           0 :     } else if ( palettes_fixed ) {
    4215           0 :         r.x = 0; r.y = BV_TOOLS_HEIGHT+BV_LAYERS_HEIGHT+90;
    4216             :     }
    4217           0 :     bvshades = CreatePalette( bv->gw, &r, bvshades_e_h, bv, &wattrs, bv->v );
    4218           0 :     bv->shades_hidden = BDFDepth(bv->bdf)==1;
    4219           0 :     if ( bvvisible[2] && !bv->shades_hidden )
    4220           0 :         GDrawSetVisible(bvshades,true);
    4221           0 : return( bvshades );
    4222             : }
    4223             : 
    4224             : static char *bvpopups[] = { N_("Pointer"), N_("Magnify (Minify with alt)"),
    4225             :                                     N_("Set/Clear Pixels"), N_("Draw a Line"),
    4226             :                                     N_("Shift Entire Bitmap"), N_("Scroll Bitmap") };
    4227             : 
    4228           0 : static void BVToolsExpose(GWindow pixmap, BitmapView *bv, GRect *r) {
    4229             :     GRect old;
    4230             :     /* Note: If you change this ordering, change enum bvtools */
    4231             :     static GImage *buttons[][2] = { { &GIcon_pointer, &GIcon_magnify },
    4232             :                                     { &GIcon_pencil, &GIcon_line },
    4233             :                                     { &GIcon_shift, &GIcon_hand }};
    4234             :     int i,j,norm;
    4235           0 :     int tool = bv->cntrldown?bv->cb1_tool:bv->b1_tool;
    4236           0 :     int dither = GDrawSetDither(NULL,false);
    4237             : 
    4238           0 :     GDrawPushClip(pixmap,r,&old);
    4239           0 :     GDrawSetLineWidth(pixmap,0);
    4240           0 :     for ( i=0; i<sizeof(buttons)/sizeof(buttons[0]); ++i ) for ( j=0; j<2; ++j ) {
    4241           0 :         GDrawDrawImage(pixmap,buttons[i][j],NULL,j*27+1,i*27+1);
    4242           0 :         norm = (i*2+j!=tool);
    4243           0 :         GDrawDrawLine(pixmap,j*27,i*27,j*27+25,i*27,norm?0xe0e0e0:0x707070);
    4244           0 :         GDrawDrawLine(pixmap,j*27,i*27,j*27,i*27+25,norm?0xe0e0e0:0x707070);
    4245           0 :         GDrawDrawLine(pixmap,j*27,i*27+25,j*27+25,i*27+25,norm?0x707070:0xe0e0e0);
    4246           0 :         GDrawDrawLine(pixmap,j*27+25,i*27,j*27+25,i*27+25,norm?0x707070:0xe0e0e0);
    4247             :     }
    4248           0 :     GDrawPopClip(pixmap,&old);
    4249           0 :     GDrawSetDither(NULL,dither);
    4250           0 : }
    4251             : 
    4252           0 : void BVToolsSetCursor(BitmapView *bv, int state,char *device) {
    4253             :     int shouldshow;
    4254             :     static enum bvtools tools[bvt_max2+1] = { bvt_none };
    4255             :     int cntrl;
    4256             : 
    4257           0 :     if ( tools[0] == bvt_none ) {
    4258           0 :         tools[bvt_pointer] = ct_mypointer;
    4259           0 :         tools[bvt_magnify] = ct_magplus;
    4260           0 :         tools[bvt_pencil] = ct_pencil;
    4261           0 :         tools[bvt_line] = ct_line;
    4262           0 :         tools[bvt_shift] = ct_shift;
    4263           0 :         tools[bvt_hand] = ct_myhand;
    4264           0 :         tools[bvt_minify] = ct_magminus;
    4265           0 :         tools[bvt_eyedropper] = ct_eyedropper;
    4266           0 :         tools[bvt_setwidth] = ct_setwidth;
    4267           0 :         tools[bvt_setvwidth] = ct_updown;
    4268           0 :         tools[bvt_rect] = ct_rect;
    4269           0 :         tools[bvt_filledrect] = ct_filledrect;
    4270           0 :         tools[bvt_elipse] = ct_elipse;
    4271           0 :         tools[bvt_filledelipse] = ct_filledelipse;
    4272             :     }
    4273             : 
    4274           0 :     shouldshow = bvt_none;
    4275           0 :     if ( bv->active_tool!=bvt_none )
    4276           0 :         shouldshow = bv->active_tool;
    4277           0 :     else if ( bv->pressed_display!=bvt_none )
    4278           0 :         shouldshow = bv->pressed_display;
    4279           0 :     else if ( device==NULL || strcmp(device,"Mouse1")==0 ) {
    4280           0 :         if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button4))
    4281           0 :             shouldshow = bvt_magnify;
    4282           0 :         else if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button5))
    4283           0 :             shouldshow = bvt_minify;
    4284           0 :         else if ( (state&ksm_control) && (state&(ksm_button2|ksm_super)) )
    4285           0 :             shouldshow = bv->cb2_tool;
    4286           0 :         else if ( (state&(ksm_button2|ksm_super)) )
    4287           0 :             shouldshow = bv->b2_tool;
    4288           0 :         else if ( (state&ksm_control) )
    4289           0 :             shouldshow = bv->cb1_tool;
    4290             :         else
    4291           0 :             shouldshow = bv->b1_tool;
    4292           0 :     } else if ( strcmp(device,"eraser")==0 )
    4293           0 :         shouldshow = bv->er_tool;
    4294           0 :     else if ( strcmp(device,"stylus")==0 ) {
    4295           0 :         if ( (state&(ksm_button2|ksm_control|ksm_super)) )
    4296           0 :             shouldshow = bv->s2_tool;
    4297             :         else
    4298           0 :             shouldshow = bv->s1_tool;
    4299             :     }
    4300             :     
    4301           0 :     if ( shouldshow==bvt_magnify && (state&ksm_meta))
    4302           0 :         shouldshow = bvt_minify;
    4303           0 :     if ( (shouldshow==bvt_pencil || shouldshow==bvt_line) && (state&ksm_meta) && bv->bdf->clut!=NULL )
    4304           0 :         shouldshow = bvt_eyedropper;
    4305           0 :     if ( shouldshow!=bvt_none && shouldshow!=bv->showing_tool ) {
    4306           0 :         GDrawSetCursor(bv->v,tools[shouldshow]);
    4307           0 :         if ( bvtools != NULL )
    4308           0 :             GDrawSetCursor(bvtools,tools[shouldshow]);
    4309           0 :         bv->showing_tool = shouldshow;
    4310             :     }
    4311             : 
    4312           0 :     if ( device==NULL || strcmp(device,"stylus")==0 ) {
    4313           0 :         cntrl = (state&ksm_control)?1:0;
    4314           0 :         if ( device!=NULL && (state&ksm_button2))
    4315           0 :             cntrl = true;
    4316           0 :         if ( cntrl != bv->cntrldown ) {
    4317           0 :             bv->cntrldown = cntrl;
    4318           0 :             GDrawRequestExpose(bvtools,NULL,false);
    4319             :         }
    4320             :     }
    4321           0 : }
    4322             : 
    4323           0 : static void BVToolsMouse(BitmapView *bv, GEvent *event) {
    4324           0 :     int i = (event->u.mouse.y/27), j = (event->u.mouse.x/27);
    4325             :     int pos;
    4326           0 :     int isstylus = event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"stylus")==0;
    4327           0 :     int styluscntl = isstylus && (event->u.mouse.state&0x200);
    4328             : 
    4329           0 :     if(j >= 2)
    4330           0 : return;                 /* If the wm gave me a window the wrong size */
    4331             : 
    4332           0 :     pos = i*2 + j;
    4333           0 :     GGadgetEndPopup();
    4334           0 :     if ( pos<0 || pos>=bvt_max )
    4335           0 :         pos = bvt_none;
    4336           0 :     if ( event->type == et_mousedown ) {
    4337           0 :         if ( isstylus && event->u.mouse.button==2 )
    4338             :             /* Not a real button press, only touch counts. This is a modifier */;
    4339             :         else {
    4340           0 :             bv->pressed_tool = bv->pressed_display = pos;
    4341           0 :             bv->had_control = ((event->u.mouse.state&ksm_control) || styluscntl)?1:0;
    4342           0 :             event->u.chr.state |= (1<<(7+event->u.mouse.button));
    4343             :         }
    4344           0 :     } else if ( event->type == et_mousemove ) {
    4345           0 :         if ( bv->pressed_tool==bvt_none && pos!=bvt_none ) {
    4346             :             /* Not pressed */
    4347           0 :             if ( !bv->shades_hidden && strcmp(bvpopups[pos],"Set/Clear Pixels")==0 )
    4348           0 :                 GGadgetPreparePopup8(bvtools,_("Set/Clear Pixels\n(Eyedropper with alt)"));
    4349             :             else
    4350           0 :                 GGadgetPreparePopup8(bvtools,_(bvpopups[pos]));
    4351           0 :         } else if ( pos!=bv->pressed_tool || bv->had_control != (((event->u.mouse.state&ksm_control)||styluscntl)?1:0) )
    4352           0 :             bv->pressed_display = bvt_none;
    4353             :         else
    4354           0 :             bv->pressed_display = bv->pressed_tool;
    4355           0 :     } else if ( event->type == et_mouseup ) {
    4356           0 :         if ( pos!=bv->pressed_tool || bv->had_control != (((event->u.mouse.state&ksm_control)||styluscntl)?1:0) )
    4357           0 :             bv->pressed_tool = bv->pressed_display = bvt_none;
    4358             :         else {
    4359           0 :             if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"eraser")==0 )
    4360           0 :                 bv->er_tool = pos;
    4361           0 :             else if ( isstylus ) {
    4362           0 :                 if ( event->u.mouse.button==2 )
    4363             :                     /* Only thing that matters is touch which maps to button 1 */;
    4364           0 :                 else if ( bv->had_control )
    4365           0 :                     bv->s2_tool = pos;
    4366             :                 else
    4367           0 :                     bv->s1_tool = pos;
    4368           0 :             } else if ( bv->had_control && event->u.mouse.button==2 )
    4369           0 :                 bv->cb2_tool = pos;
    4370           0 :             else if ( event->u.mouse.button==2 )
    4371           0 :                 bv->b2_tool = pos;
    4372           0 :             else if ( bv->had_control ) {
    4373           0 :                 if ( bv->cb1_tool!=pos ) {
    4374           0 :                     bv->cb1_tool = pos;
    4375           0 :                     GDrawRequestExpose(bvtools,NULL,false);
    4376             :                 }
    4377             :             } else {
    4378           0 :                 if ( bv->b1_tool!=pos ) {
    4379           0 :                     bv->b1_tool = pos;
    4380           0 :                     GDrawRequestExpose(bvtools,NULL,false);
    4381             :                 }
    4382             :             }
    4383           0 :             bv->pressed_tool = bv->pressed_display = bvt_none;
    4384             :         }
    4385           0 :         event->u.mouse.state &= ~(1<<(7+event->u.mouse.button));
    4386             :     }
    4387           0 :     BVToolsSetCursor(bv,event->u.mouse.state,event->u.mouse.device);
    4388             : }
    4389             : 
    4390           0 : static int bvtools_e_h(GWindow gw, GEvent *event) {
    4391           0 :     BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
    4392             : 
    4393           0 :     if ( event->type==et_destroy ) {
    4394           0 :         bvtools = NULL;
    4395           0 : return( true );
    4396             :     }
    4397             : 
    4398           0 :     if ( bv==NULL )
    4399           0 : return( true );
    4400             : 
    4401           0 :     switch ( event->type ) {
    4402             :       case et_expose:
    4403           0 :         BVToolsExpose(gw,bv,&event->u.expose.rect);
    4404           0 :       break;
    4405             :       case et_mousedown:
    4406           0 :         BVToolsMouse(bv,event);
    4407           0 :       break;
    4408             :       case et_mousemove:
    4409           0 :         BVToolsMouse(bv,event);
    4410           0 :       break;
    4411             :       case et_mouseup:
    4412           0 :         BVToolsMouse(bv,event);
    4413           0 :       break;
    4414             :       case et_crossing:
    4415           0 :         bv->pressed_display = bvt_none;
    4416           0 :         BVToolsSetCursor(bv,event->u.mouse.state,event->u.mouse.device);
    4417           0 :       break;
    4418             :       case et_char: case et_charup:
    4419           0 :         if ( bv->had_control != ((event->u.chr.state&ksm_control)?1:0) )
    4420           0 :             bv->pressed_display = bvt_none;
    4421           0 :         PostCharToWindow(bv->gw,event);
    4422           0 :       break;
    4423             :       case et_close:
    4424           0 :         GDrawSetVisible(gw,false);
    4425           0 :       break;
    4426             :     }
    4427           0 : return( true );
    4428             : }
    4429             : 
    4430           0 : GWindow BVMakeTools(BitmapView *bv) {
    4431             :     GRect r;
    4432             :     GWindowAttrs wattrs;
    4433             : 
    4434           0 :     if ( bvtools!=NULL )
    4435           0 : return( bvtools );
    4436           0 :     memset(&wattrs,0,sizeof(wattrs));
    4437           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
    4438           0 :     wattrs.event_masks = -1;
    4439           0 :     wattrs.cursor = ct_mypointer;
    4440           0 :     wattrs.positioned = true;
    4441           0 :     wattrs.is_dlg = true;
    4442           0 :     wattrs.utf8_window_title = _("Tools");
    4443             : 
    4444           0 :     r.width = BV_TOOLS_WIDTH; r.height = BV_TOOLS_HEIGHT;
    4445           0 :     r.x = -r.width-6; r.y = bv->mbh+20;
    4446           0 :     if ( palettes_fixed || palettes_docked ) {
    4447           0 :         r.x = 0; r.y = 0;
    4448             :     }
    4449           0 :     bvtools = CreatePalette( bv->gw, &r, bvtools_e_h, bv, &wattrs, bv->v );
    4450           0 :     if ( bvvisible[1] )
    4451           0 :         GDrawSetVisible(bvtools,true);
    4452           0 : return( bvtools );
    4453             : }
    4454             : 
    4455           0 : static void BVPopupInvoked(GWindow v, GMenuItem *mi,GEvent *e) {
    4456           0 :     BitmapView *bv = (BitmapView *) GDrawGetUserData(v);
    4457             :     int pos;
    4458             : 
    4459           0 :     pos = mi->mid;
    4460           0 :     if ( bv->had_control ) {
    4461           0 :         if ( bv->cb1_tool!=pos ) {
    4462           0 :             bv->cb1_tool = pos;
    4463           0 :             GDrawRequestExpose(bvtools,NULL,false);
    4464             :         }
    4465             :     } else {
    4466           0 :         if ( bv->b1_tool!=pos ) {
    4467           0 :             bv->b1_tool = pos;
    4468           0 :             GDrawRequestExpose(bvtools,NULL,false);
    4469             :         }
    4470             :     }
    4471           0 :     BVToolsSetCursor(bv,bv->had_control?ksm_control:0,NULL);
    4472           0 : }
    4473             : 
    4474           0 : void BVToolsPopup(BitmapView *bv, GEvent *event) {
    4475             :     GMenuItem mi[21];
    4476             :     int i, j;
    4477             : 
    4478           0 :     memset(mi,'\0',sizeof(mi));
    4479           0 :     for ( i=0;i<6; ++i ) {
    4480           0 :         mi[i].ti.text = (unichar_t *) _(bvpopups[i]);
    4481           0 :         mi[i].ti.text_is_1byte = true;
    4482           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    4483           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    4484           0 :         mi[i].mid = i;
    4485           0 :         mi[i].invoke = BVPopupInvoked;
    4486             :     }
    4487             : 
    4488           0 :     mi[i].ti.text = (unichar_t *) _("Rectangle");
    4489           0 :     mi[i].ti.text_is_1byte = true;
    4490           0 :     mi[i].ti.fg = COLOR_DEFAULT;
    4491           0 :     mi[i].ti.bg = COLOR_DEFAULT;
    4492           0 :     mi[i].mid = bvt_rect;
    4493           0 :     mi[i++].invoke = BVPopupInvoked;
    4494           0 :     mi[i].ti.text = (unichar_t *) _("Filled Rectangle"); mi[i].ti.text_is_1byte = true;
    4495           0 :     mi[i].ti.fg = COLOR_DEFAULT;
    4496           0 :     mi[i].ti.bg = COLOR_DEFAULT;
    4497           0 :     mi[i].mid = bvt_filledrect;
    4498           0 :     mi[i++].invoke = BVPopupInvoked;
    4499           0 :     mi[i].ti.text = (unichar_t *) _("Ellipse"); mi[i].ti.text_is_1byte = true;
    4500           0 :     mi[i].ti.fg = COLOR_DEFAULT;
    4501           0 :     mi[i].ti.bg = COLOR_DEFAULT;
    4502           0 :     mi[i].mid = bvt_elipse;
    4503           0 :     mi[i++].invoke = BVPopupInvoked;
    4504           0 :     mi[i].ti.text = (unichar_t *) _("Filled Ellipse"); mi[i].ti.text_is_1byte = true;
    4505           0 :     mi[i].ti.fg = COLOR_DEFAULT;
    4506           0 :     mi[i].ti.bg = COLOR_DEFAULT;
    4507           0 :     mi[i].mid = bvt_filledelipse;
    4508           0 :     mi[i++].invoke = BVPopupInvoked;
    4509             : 
    4510           0 :     mi[i].ti.fg = COLOR_DEFAULT;
    4511           0 :     mi[i].ti.bg = COLOR_DEFAULT;
    4512           0 :     mi[i++].ti.line = true;
    4513           0 :     for ( j=0; j<6; ++j, ++i ) {
    4514           0 :         mi[i].ti.text = (unichar_t *) BVFlipNames[j];
    4515           0 :         mi[i].ti.text_is_1byte = true;
    4516           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    4517           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    4518           0 :         mi[i].mid = j;
    4519           0 :         mi[i].invoke = BVMenuRotateInvoked;
    4520             :     }
    4521           0 :     if ( bv->fv->b.sf->onlybitmaps ) {
    4522           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    4523           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    4524           0 :         mi[i++].ti.line = true;
    4525           0 :         mi[i].ti.text = (unichar_t *) _("Set _Width...");
    4526           0 :         mi[i].ti.text_is_1byte = true;
    4527           0 :         mi[i].ti.text_in_resource = true;
    4528           0 :         mi[i].ti.fg = COLOR_DEFAULT;
    4529           0 :         mi[i].ti.bg = COLOR_DEFAULT;
    4530           0 :         mi[i].mid = bvt_setwidth;
    4531           0 :         mi[i].invoke = BVPopupInvoked;
    4532             :     }
    4533           0 :     bv->had_control = (event->u.mouse.state&ksm_control)?1:0;
    4534           0 :     GMenuCreatePopupMenu(bv->v,event, mi);
    4535           0 : }
    4536             : 
    4537           0 : static void BVPaletteCheck(BitmapView *bv) {
    4538           0 :     if ( bvtools==NULL ) {
    4539           0 :         BVMakeTools(bv);
    4540           0 :         BVMakeLayers(bv);
    4541           0 :         BVMakeShades(bv);
    4542             :     }
    4543           0 : }
    4544             : 
    4545           0 : int BVPaletteIsVisible(BitmapView *bv,int which) {
    4546           0 :     BVPaletteCheck(bv);
    4547           0 :     if ( which==1 )
    4548           0 : return( bvtools!=NULL && GDrawIsVisible(bvtools) );
    4549           0 :     if ( which==2 )
    4550           0 : return( bvshades!=NULL && GDrawIsVisible(bvshades) );
    4551             : 
    4552           0 : return( bvlayers!=NULL && GDrawIsVisible(bvlayers) );
    4553             : }
    4554             : 
    4555           0 : void BVPaletteSetVisible(BitmapView *bv,int which,int visible) {
    4556           0 :     BVPaletteCheck(bv);
    4557           0 :     if ( which==1 && bvtools!=NULL)
    4558           0 :         GDrawSetVisible(bvtools,visible );
    4559           0 :     else if ( which==2 && bvshades!=NULL)
    4560           0 :         GDrawSetVisible(bvshades,visible );
    4561           0 :     else if ( which==0 && bvlayers!=NULL )
    4562           0 :         GDrawSetVisible(bvlayers,visible );
    4563           0 :     bvvisible[which] = visible;
    4564           0 :     SavePrefs(true);
    4565           0 : }
    4566             : 
    4567           0 : void BVPaletteActivate(BitmapView *bv) {
    4568             :     BitmapView *old;
    4569             : 
    4570           0 :     BVPaletteCheck(bv);
    4571           0 :     if ( (old = GDrawGetUserData(bvtools))!=bv ) {
    4572           0 :         if ( old!=NULL ) {
    4573           0 :             SaveOffsets(old->gw,bvtools,&bvtoolsoff);
    4574           0 :             SaveOffsets(old->gw,bvlayers,&bvlayersoff);
    4575           0 :             SaveOffsets(old->gw,bvshades,&bvshadesoff);
    4576             :         }
    4577           0 :         GDrawSetUserData(bvtools,bv);
    4578           0 :         GDrawSetUserData(bvlayers,bv);
    4579           0 :         GDrawSetUserData(bvshades,bv);
    4580           0 :         if ( palettes_docked ) {
    4581           0 :             ReparentFixup(bvtools,bv->v,0,0,BV_TOOLS_WIDTH,BV_TOOLS_HEIGHT);
    4582           0 :             ReparentFixup(bvlayers,bv->v,0,BV_TOOLS_HEIGHT+2,0,0);
    4583           0 :             ReparentFixup(bvshades,bv->v,0,BV_TOOLS_HEIGHT+BV_TOOLS_HEIGHT+4,0,0);
    4584             :         } else {
    4585           0 :             if ( bvvisible[0])
    4586           0 :                 RestoreOffsets(bv->gw,bvlayers,&bvlayersoff);
    4587           0 :             if ( bvvisible[1])
    4588           0 :                 RestoreOffsets(bv->gw,bvtools,&bvtoolsoff);
    4589           0 :             if ( bvvisible[2] && !bv->shades_hidden )
    4590           0 :                 RestoreOffsets(bv->gw,bvshades,&bvshadesoff);
    4591             :         }
    4592           0 :         GDrawSetVisible(bvtools,bvvisible[1]);
    4593           0 :         GDrawSetVisible(bvlayers,bvvisible[0]);
    4594           0 :         GDrawSetVisible(bvshades,bvvisible[2] && bv->bdf->clut!=NULL);
    4595           0 :         if ( bvvisible[1]) {
    4596           0 :             bv->showing_tool = bvt_none;
    4597           0 :             BVToolsSetCursor(bv,0,NULL);
    4598           0 :             GDrawRequestExpose(bvtools,NULL,false);
    4599             :         }
    4600           0 :         if ( bvvisible[0])
    4601           0 :             BVLayersSet(bv);
    4602           0 :         if ( bvvisible[2] && !bv->shades_hidden )
    4603           0 :             GDrawRequestExpose(bvtools,NULL,false);
    4604             :     }
    4605           0 :     if ( cvtools!=NULL ) {
    4606           0 :         CharView *cv = GDrawGetUserData(cvtools);
    4607           0 :         if ( cv!=NULL ) {
    4608           0 :             SaveOffsets(cv->gw,cvtools,&cvtoolsoff);
    4609           0 :             SaveOffsets(cv->gw,cvlayers,&cvlayersoff);
    4610           0 :             GDrawSetUserData(cvtools,NULL);
    4611           0 :             if ( cvlayers!=NULL )
    4612           0 :                 GDrawSetUserData(cvlayers,NULL);
    4613           0 :             if ( cvlayers2!=NULL )
    4614           0 :                 GDrawSetUserData(cvlayers2,NULL);
    4615             :         }
    4616           0 :         GDrawSetVisible(cvtools,false);
    4617           0 :         if ( cvlayers!=NULL )
    4618           0 :             GDrawSetVisible(cvlayers,false);
    4619           0 :         if ( cvlayers2!=NULL )
    4620           0 :             GDrawSetVisible(cvlayers2,false);
    4621             :     }
    4622           0 : }
    4623             : 
    4624           0 : void BVPalettesHideIfMine(BitmapView *bv) {
    4625           0 :     if ( bvtools==NULL )
    4626           0 : return;
    4627           0 :     if ( GDrawGetUserData(bvtools)==bv ) {
    4628           0 :         SaveOffsets(bv->gw,bvtools,&bvtoolsoff);
    4629           0 :         SaveOffsets(bv->gw,bvlayers,&bvlayersoff);
    4630           0 :         SaveOffsets(bv->gw,bvshades,&bvshadesoff);
    4631           0 :         GDrawSetVisible(bvtools,false);
    4632           0 :         GDrawSetVisible(bvlayers,false);
    4633           0 :         GDrawSetVisible(bvshades,false);
    4634           0 :         GDrawSetUserData(bvtools,NULL);
    4635           0 :         GDrawSetUserData(bvlayers,NULL);
    4636           0 :         GDrawSetUserData(bvshades,NULL);
    4637             :     }
    4638             : }
    4639             : 
    4640           0 : void CVPaletteDeactivate(void) {
    4641           0 :     if ( cvtools!=NULL ) {
    4642           0 :         CharView *cv = GDrawGetUserData(cvtools);
    4643           0 :         if ( cv!=NULL ) {
    4644           0 :             SaveOffsets(cv->gw,cvtools,&cvtoolsoff);
    4645           0 :             GDrawSetUserData(cvtools,NULL);
    4646           0 :             if ( cv->b.sc->parent->multilayer && cvlayers2!=NULL ) {
    4647           0 :                 SaveOffsets(cv->gw,cvlayers2,&cvlayersoff);
    4648           0 :                 GDrawSetUserData(cvlayers2,NULL);
    4649           0 :             } else if ( cvlayers!=NULL ) {
    4650           0 :                 SaveOffsets(cv->gw,cvlayers,&cvlayersoff);
    4651           0 :                 GDrawSetUserData(cvlayers,NULL);
    4652             :             }
    4653             :         }
    4654           0 :         GDrawSetVisible(cvtools,false);
    4655           0 :         if ( cvlayers!=NULL )
    4656           0 :             GDrawSetVisible(cvlayers,false);
    4657           0 :         if ( cvlayers2!=NULL )
    4658           0 :             GDrawSetVisible(cvlayers2,false);
    4659             :     }
    4660           0 :     if ( bvtools!=NULL ) {
    4661           0 :         BitmapView *bv = GDrawGetUserData(bvtools);
    4662           0 :         if ( bv!=NULL ) {
    4663           0 :             SaveOffsets(bv->gw,bvtools,&bvtoolsoff);
    4664           0 :             SaveOffsets(bv->gw,bvlayers,&bvlayersoff);
    4665           0 :             SaveOffsets(bv->gw,bvshades,&bvshadesoff);
    4666           0 :             GDrawSetUserData(bvtools,NULL);
    4667           0 :             GDrawSetUserData(bvlayers,NULL);
    4668           0 :             GDrawSetUserData(bvshades,NULL);
    4669             :         }
    4670           0 :         GDrawSetVisible(bvtools,false);
    4671           0 :         GDrawSetVisible(bvlayers,false);
    4672           0 :         GDrawSetVisible(bvshades,false);
    4673             :     }
    4674           0 : }
    4675             : 
    4676           0 : void BVPaletteColorChange(BitmapView *bv) {
    4677           0 :     if ( bvshades!=NULL )
    4678           0 :         GDrawRequestExpose(bvshades,NULL,false);
    4679           0 :     GDrawRequestExpose(bv->gw,NULL,false);
    4680           0 : }
    4681             : 
    4682           0 : void BVPaletteColorUnderChange(BitmapView *bv,int color_under) {
    4683           0 :     if ( bvshades!=NULL && color_under!=bv->color_under_cursor ) {
    4684           0 :         bv->color_under_cursor = color_under;
    4685           0 :         GDrawRequestExpose(bvshades,NULL,false);
    4686             :     }
    4687           0 : }
    4688             : 
    4689           0 : void BVPaletteChangedChar(BitmapView *bv) {
    4690           0 :     if ( bvshades!=NULL && bvvisible[2]) {
    4691           0 :         int hidden = bv->bdf->clut==NULL;
    4692           0 :         if ( hidden!=bv->shades_hidden ) {
    4693           0 :             GDrawSetVisible(bvshades,!hidden);
    4694           0 :             bv->shades_hidden = hidden;
    4695           0 :             GDrawRequestExpose(bv->gw,NULL,false);
    4696             :         } else
    4697           0 :             GDrawRequestExpose(bvshades,NULL,false);
    4698             :     }
    4699           0 : }
    4700             : 
    4701           0 : void PalettesChangeDocking() {
    4702             : 
    4703           0 :     palettes_docked = !palettes_docked;
    4704           0 :     if ( palettes_docked ) {
    4705           0 :         if ( cvtools!=NULL ) {
    4706           0 :             CharView *cv = GDrawGetUserData(cvtools);
    4707           0 :             if ( cv!=NULL ) {
    4708           0 :                 ReparentFixup(cvtools,cv->v,0,0,getToolbarWidth(cv),getToolbarHeight(cv));
    4709           0 :                 if ( cvlayers!=NULL )
    4710           0 :                     ReparentFixup(cvlayers,cv->v,0,getToolbarHeight(cv)+2,0,0);
    4711           0 :                 if ( cvlayers2!=NULL )
    4712           0 :                     ReparentFixup(cvlayers2,cv->v,0,getToolbarHeight(cv)+2,0,0);
    4713             :             }
    4714             :         }
    4715           0 :         if ( bvtools!=NULL ) {
    4716           0 :             BitmapView *bv = GDrawGetUserData(bvtools);
    4717           0 :             if ( bv!=NULL ) {
    4718           0 :                 ReparentFixup(bvtools,bv->v,0,0,BV_TOOLS_WIDTH,BV_TOOLS_HEIGHT);
    4719           0 :                 ReparentFixup(bvlayers,bv->v,0,BV_TOOLS_HEIGHT+2,0,0);
    4720           0 :                 ReparentFixup(bvshades,bv->v,0,BV_TOOLS_HEIGHT+BV_LAYERS_HEIGHT+4,0,0);
    4721             :             }
    4722             :         }
    4723             :     } else {
    4724           0 :         if ( cvtools!=NULL ) {
    4725           0 :             CharView *cv = GDrawGetUserData(cvtools);
    4726           0 :             GDrawReparentWindow(cvtools,GDrawGetRoot(NULL),0,0);
    4727           0 :             if ( cvlayers!=NULL )
    4728           0 :                 GDrawReparentWindow(cvlayers,GDrawGetRoot(NULL),0,getToolbarHeight(cv)+2+45);
    4729           0 :             if ( cvlayers2!=NULL )
    4730           0 :                 GDrawReparentWindow(cvlayers2,GDrawGetRoot(NULL),0,getToolbarHeight(cv)+2+45);
    4731             :         }
    4732           0 :         if ( bvtools!=NULL ) {
    4733           0 :             GDrawReparentWindow(bvtools,GDrawGetRoot(NULL),0,0);
    4734           0 :             GDrawReparentWindow(bvlayers,GDrawGetRoot(NULL),0,BV_TOOLS_HEIGHT+2+45);
    4735           0 :             GDrawReparentWindow(bvshades,GDrawGetRoot(NULL),0,BV_TOOLS_HEIGHT+BV_LAYERS_HEIGHT+4+90);
    4736             :         }
    4737             :     }
    4738           0 :     SavePrefs(true);
    4739           0 : }
    4740             : 
    4741           0 : int BVPalettesWidth(void) {
    4742           0 : return( GGadgetScale(BV_LAYERS_WIDTH));
    4743             : }

Generated by: LCOV version 1.10