PageRenderTime 78ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/fontforgeexe/cvpalettes.c

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