PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/fontforgeexe/cvpalettes.c

https://github.com/tshinnic/fontforge
C | 4443 lines | 3820 code | 433 blank | 190 comment | 983 complexity | 8f7bb73147e3a5162aad5752bd1dd8bc MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0, Unlicense

Large files files are truncated, but you can click here to view the full file

  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. #include "collabclientui.h"
  25. int palettes_docked=1;
  26. int rectelipse=0, polystar=0, regular_star=1;
  27. int center_out[2] = { false, true };
  28. float rr_radius=0;
  29. int ps_pointcnt=6;
  30. float star_percent=1.7320508; /* Regular 6 pointed star */
  31. extern int interpCPsOnMotion;
  32. #include <gkeysym.h>
  33. #include <math.h>
  34. #include "splinefont.h"
  35. #include <ustring.h>
  36. #include <utype.h>
  37. #include <gresource.h>
  38. #include "charview_private.h"
  39. #include "gdraw/hotkeys.h"
  40. static void CVLCheckLayerCount(CharView *cv, int resize);
  41. extern void CVDebugFree(DebugView *dv);
  42. extern GBox _ggadget_Default_Box;
  43. #define ACTIVE_BORDER (_ggadget_Default_Box.active_border)
  44. #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
  45. extern GDevEventMask input_em[];
  46. extern const int input_em_cnt;
  47. int cvvisible[2] = { 1, 1}, bvvisible[3]= { 1,1,1 };
  48. static GWindow cvlayers, cvtools, bvlayers, bvtools, bvshades;
  49. static GWindow cvlayers2=NULL;
  50. #define LSHOW_CUBIC 1
  51. #define LSHOW_FG 2
  52. #define LSHOW_PREVIEW 4
  53. static int layerscols = LSHOW_CUBIC|LSHOW_FG|LSHOW_PREVIEW; /* which columns to show in layers1 palette */
  54. static int layer_height = 0; /* height of each layer row in layers1 palette */
  55. static int layer_header_height = 0; /* height of initial stuff in layers1 palette */
  56. static int layer_footer_height = 0; /* height of +/- buttons at bottom of layers1 palette */
  57. static int layers_max = 2; /* Maximum number of layers for which widgets have been allocated in layers1 palette */
  58. struct l2 {
  59. int active; /* index of the active layer */
  60. int offtop; /* first layer to show at the top line in layers palette */
  61. int visible_layers; /* number of layers apart from the guides layer to show before using a scrollbar */
  62. int current_layers; /* number of layers for the current character, and the number used in l2.layers */
  63. int max_layers; /* maximum number of layers for which layer controls and previews have been allocated */
  64. BDFChar **layers; /* layer thumbnail previews */
  65. int sb_start; /* x pixel position of the scrollbar */
  66. int column_width; /* width of various indicator columns */
  67. int mo_col, mo_layer; /* mouse over column and layer */
  68. int rename_active; /* If >=2, layer number for which the edit box for layer names is active */
  69. GClut *clut;
  70. GFont *font; /* font to draw text in the palette with */
  71. } layerinfo = { /* info about the current layers in the layers palette */
  72. 2, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, NULL, NULL
  73. };
  74. struct l2 layer2 = { 2, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, NULL, NULL };
  75. static int layers2_active = -1;
  76. static GPoint cvtoolsoff = { -9999, -9999 }, cvlayersoff = { -9999, -9999 }, bvlayersoff = { -9999, -9999 }, bvtoolsoff = { -9999, -9999 }, bvshadesoff = { -9999, -9999 };
  77. int palettes_fixed=1;
  78. static GCursor tools[cvt_max+1] = { ct_pointer }, spirotools[cvt_max+1];
  79. enum cvtools cv_b1_tool = cvt_pointer, cv_cb1_tool = cvt_pointer,
  80. cv_b2_tool = cvt_magnify, cv_cb2_tool = cvt_ruler;
  81. static GFont *toolsfont=NULL, *layersfont=NULL;
  82. #define CV_TOOLS_WIDTH 53
  83. #define CV_TOOLS_HEIGHT (10*27+4*12+2)
  84. #define CV_LAYERS_WIDTH 104
  85. #define CV_LAYERS_HEIGHT 100
  86. #define CV_LAYERS_INITIALCNT 6
  87. #define CV_LAYERS_LINE_HEIGHT 25
  88. #define CV_LAYERS2_WIDTH 120
  89. #define CV_LAYERS2_HEIGHT 196
  90. #define CV_LAYERS2_LINE_HEIGHT 25
  91. #define CV_LAYERS2_HEADER_HEIGHT 20
  92. #define CV_LAYERS2_VISLAYERS ( (CV_LAYERS2_HEIGHT-CV_LAYERS2_HEADER_HEIGHT-2*CV_LAYERS2_LINE_HEIGHT)/CV_LAYERS2_LINE_HEIGHT )
  93. #define BV_TOOLS_WIDTH 53
  94. #define BV_TOOLS_HEIGHT 80
  95. #define BV_LAYERS_HEIGHT 73
  96. #define BV_LAYERS_WIDTH 73
  97. #define BV_SHADES_HEIGHT (8+9*16)
  98. /* These are control ids for the layers palette controls */
  99. #define CID_VBase 1000
  100. #define CID_VGrid (CID_VBase+ly_grid)
  101. #define CID_VBack (CID_VBase+ly_back)
  102. #define CID_VFore (CID_VBase+ly_fore)
  103. #define CID_EBase 3000
  104. #define CID_EGrid (CID_EBase+ly_grid)
  105. #define CID_EBack (CID_EBase+ly_back)
  106. #define CID_EFore (CID_EBase+ly_fore)
  107. #define CID_QBase 5000
  108. #define CID_QGrid (CID_QBase+ly_grid)
  109. #define CID_QBack (CID_QBase+ly_back)
  110. #define CID_QFore (CID_QBase+ly_fore)
  111. #define CID_FBase 7000
  112. #define CID_SB 8000
  113. #define CID_Edit 8001
  114. #define CID_AddLayer 9000
  115. #define CID_RemoveLayer 9001
  116. #define CID_RenameLayer 9002
  117. #define CID_LayersMenu 9003
  118. static void ReparentFixup(GWindow child,GWindow parent, int x, int y, int width, int height ) {
  119. /* This is so nice */
  120. /* KDE does not honor my request for a border for top level windows */
  121. /* KDE does not honor my request for size (for narrow) top level windows */
  122. /* Gnome gets very confused by reparenting */
  123. /* If we've got a top level window, then reparenting it removes gnome's */
  124. /* decoration window, but sets the new parent to root (rather than what */
  125. /* we asked for */
  126. /* I have tried reparenting it twice, unmapping & reparenting. Nothing works */
  127. GWidgetReparentWindow(child,parent,x,y);
  128. if ( width!=0 )
  129. GDrawResize(child,width,height);
  130. GDrawSetWindowBorder(child,1,GDrawGetDefaultForeground(NULL));
  131. }
  132. void onCollabSessionStateChanged( GObject* gobj, FontViewBase* fv )
  133. {
  134. bool inCollab = collabclient_inSessionFV( fv );
  135. if (cvlayers != NULL) {
  136. GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_AddLayer), !inCollab );
  137. GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_RemoveLayer), !inCollab );
  138. GGadgetSetEnabled(GWidgetGetControl(cvlayers,CID_RenameLayer), !inCollab );
  139. } else if (cvlayers2 != NULL && 0) {
  140. // These controls seem not to exist in cvlayers2. We can look deeper into this later.
  141. GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_AddLayer), !inCollab );
  142. GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_RemoveLayer), !inCollab );
  143. GGadgetSetEnabled(GWidgetGetControl(cvlayers2,CID_RenameLayer), !inCollab );
  144. }
  145. }
  146. /* Initialize a window that is to be used for a palette. Specific widgets and other functionality are added elsewhere. */
  147. static GWindow CreatePalette(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs, GWindow v) {
  148. GWindow gw;
  149. GPoint pt, base;
  150. GRect newpos;
  151. GWindow root;
  152. GRect ownerpos, screensize;
  153. pt.x = pos->x; pt.y = pos->y;
  154. if ( !palettes_fixed ) {
  155. root = GDrawGetRoot(NULL);
  156. GDrawGetSize(w,&ownerpos);
  157. GDrawGetSize(root,&screensize);
  158. GDrawTranslateCoordinates(w,root,&pt);
  159. base.x = base.y = 0;
  160. GDrawTranslateCoordinates(w,root,&base);
  161. if ( pt.x<0 ) {
  162. if ( base.x+ownerpos.width+20+pos->width+20 > screensize.width )
  163. pt.x=0;
  164. else
  165. pt.x = base.x+ownerpos.width+20;
  166. }
  167. if ( pt.y<0 ) pt.y=0;
  168. if ( pt.x+pos->width>screensize.width )
  169. pt.x = screensize.width-pos->width;
  170. if ( pt.y+pos->height>screensize.height )
  171. pt.y = screensize.height-pos->height;
  172. }
  173. wattrs->mask |= wam_bordcol|wam_bordwidth;
  174. wattrs->border_width = 1;
  175. wattrs->border_color = GDrawGetDefaultForeground(NULL);
  176. newpos.x = pt.x; newpos.y = pt.y; newpos.width = pos->width; newpos.height = pos->height;
  177. wattrs->mask|= wam_positioned;
  178. wattrs->positioned = true;
  179. gw = GDrawCreateTopWindow(NULL,&newpos,eh,user_data,wattrs);
  180. if ( palettes_docked )
  181. ReparentFixup(gw,v,0,pos->y,pos->width,pos->height);
  182. collabclient_addSessionJoiningCallback( onCollabSessionStateChanged );
  183. collabclient_addSessionLeavingCallback( onCollabSessionStateChanged );
  184. return( gw );
  185. }
  186. /* Return screen coordinates of the palette in off, relative to the root window origin. */
  187. static void SaveOffsets(GWindow main, GWindow palette, GPoint *off) {
  188. if ( !palettes_docked && !palettes_fixed && GDrawIsVisible(palette)) {
  189. GRect mr, pr;
  190. GWindow root, temp;
  191. root = GDrawGetRoot(NULL);
  192. while ( (temp=GDrawGetParentWindow(main))!=root )
  193. main = temp;
  194. GDrawGetSize(main,&mr);
  195. GDrawGetSize(palette,&pr);
  196. off->x = pr.x-mr.x;
  197. off->y = pr.y-mr.y;
  198. if ( off->x<0 ) off->x = 0;
  199. if ( off->y<0 ) off->y = 0;
  200. }
  201. }
  202. /* Set the palette window position to off, a point in the root window space. */
  203. static void RestoreOffsets(GWindow main, GWindow palette, GPoint *off) {
  204. GPoint pt;
  205. GWindow root,temp;
  206. GRect screensize, pos;
  207. if ( palettes_fixed )
  208. return;
  209. pt = *off;
  210. root = GDrawGetRoot(NULL);
  211. GDrawGetSize(root,&screensize);
  212. GDrawGetSize(palette,&pos);
  213. while ( (temp=GDrawGetParentWindow(main))!=root )
  214. main = temp;
  215. GDrawTranslateCoordinates(main,root,&pt);
  216. if ( pt.x<0 ) pt.x=0;
  217. if ( pt.y<0 ) pt.y=0;
  218. if ( pt.x+pos.width>screensize.width )
  219. pt.x = screensize.width-pos.width;
  220. if ( pt.y+pos.height>screensize.height )
  221. pt.y = screensize.height-pos.height;
  222. GDrawTrueMove(palette,pt.x,pt.y);
  223. GDrawRaise(palette);
  224. }
  225. static void CVMenuTool(GWindow gw,struct gmenuitem *mi,GEvent *e) {
  226. CharView *cv = (CharView *) GDrawGetUserData(gw);
  227. cv->b1_tool = mi->mid;
  228. if ( cvtools!=NULL )
  229. GDrawRequestExpose(cvtools,NULL,false);
  230. CVToolsSetCursor(cv,0,NULL);
  231. }
  232. static void CVChangeSpiroMode(CharView *cv);
  233. static void CVMenuSpiroSet(GWindow gw,struct gmenuitem *mi,GEvent *e) {
  234. CharView *cv = (CharView *) GDrawGetUserData(gw);
  235. CVChangeSpiroMode(cv);
  236. }
  237. void cvtoollist_check(GWindow gw,struct gmenuitem *mi,GEvent *e) {
  238. CharView *cv = (CharView *) GDrawGetUserData(gw);
  239. int order2 = cv->b.layerheads[cv->b.drawmode]->order2;
  240. for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
  241. mi->ti.checked = mi->mid==cv->b1_tool;
  242. switch ( mi->mid ) {
  243. case cvt_freehand:
  244. mi->ti.disabled = order2;
  245. break;
  246. case cvt_spiro:
  247. mi->ti.disabled = !hasspiro();
  248. break;
  249. }
  250. }
  251. }
  252. /* Note: If you change this ordering, change enum cvtools */
  253. static char *popupsres[] = {
  254. N_("Pointer"), N_("Magnify (Minify with alt)"),
  255. N_("Draw a freehand curve"), N_("Scroll by hand"),
  256. N_("Cut splines in two"), N_("Measure distance, angle between points"),
  257. N_("Add a point, then drag out its control points"), N_("Change whether spiro is active or not"),
  258. N_("Add a curve point"), N_("Add a curve point always either horizontal or vertical"),
  259. N_("Add a corner point"), N_("Add a tangent point"),
  260. N_("Scale the selection"), N_("Rotate the selection"),
  261. N_("Flip the selection"), N_("Skew the selection"),
  262. N_("Rotate the selection in 3D and project back to plain"), N_("Perform a perspective transformation on the selection"),
  263. N_("Rectangle or Ellipse"), N_("Polygon or Star"),
  264. N_("Rectangle or Ellipse"), N_("Polygon or Star")};
  265. GMenuItem2 cvtoollist[] = {
  266. { { (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 },
  267. { { (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 },
  268. { { (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 },
  269. { { (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 },
  270. { { (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 },
  271. { { (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 },
  272. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  273. { { (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 },
  274. { { (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 },
  275. { { (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 },
  276. { { (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 },
  277. { { (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 },
  278. { { (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 },
  279. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  280. { { (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 },
  281. { { (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 },
  282. { { (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 },
  283. { { (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 },
  284. { { (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 },
  285. { { (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 },
  286. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  287. { { (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 },
  288. { { (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 },
  289. { { (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 },
  290. { { (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 },
  291. GMENUITEM2_EMPTY
  292. };
  293. GMenuItem2 cvspirotoollist[] = {
  294. { { (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 },
  295. { { (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 },
  296. { { (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 },
  297. { { (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 },
  298. { { (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 },
  299. { { (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 },
  300. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  301. { { (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 },
  302. { { (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 },
  303. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  304. { { (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 },
  305. { { (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 },
  306. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  307. { { (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 },
  308. { { (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 },
  309. { { (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 },
  310. { { (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 },
  311. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  312. { { (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 },
  313. { { (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 },
  314. { { (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 },
  315. { { (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 },
  316. { { (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 },
  317. { { (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 },
  318. { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
  319. { { (unichar_t *) N_("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 },
  320. { { (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 },
  321. { { (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 },
  322. { { (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 },
  323. GMENUITEM2_EMPTY
  324. };
  325. static char *editablelayers[] = {
  326. /* GT: Foreground, make it short */
  327. N_("F_ore"),
  328. /* GT: Background, make it short */
  329. N_("_Back"),
  330. /* GT: Guide layer, make it short */
  331. N_("_Guide")
  332. };
  333. static real raddiam_x = 20, raddiam_y = 20, rotate_by=0;
  334. static StrokeInfo expand = {
  335. 25, lj_round, lc_butt, si_centerline,
  336. false, /* removeexternal */
  337. false, /* removeinternal */
  338. false, /* leave users */
  339. 3.1415926535897932/4, 25, NULL, 50,
  340. 0.0, 0, 0, NULL, NULL
  341. };
  342. real CVRoundRectRadius(void) {
  343. return( rr_radius );
  344. }
  345. int CVRectElipseCenter(void) {
  346. return( center_out[rectelipse] );
  347. }
  348. int CVPolyStarPoints(void) {
  349. return( ps_pointcnt );
  350. }
  351. real CVStarRatio(void) {
  352. if ( regular_star )
  353. return( sin(3.1415926535897932/ps_pointcnt)*tan(2*3.1415926535897932/ps_pointcnt)+cos(3.1415926535897932/ps_pointcnt) );
  354. return( star_percent );
  355. }
  356. StrokeInfo *CVFreeHandInfo(void) {
  357. return( &expand );
  358. }
  359. struct ask_info {
  360. GWindow gw;
  361. int done;
  362. int ret;
  363. float *val;
  364. int *co;
  365. GGadget *rb1;
  366. GGadget *reg;
  367. GGadget *pts;
  368. int ispolystar;
  369. int haspos;
  370. char *lab;
  371. CharView *cv;
  372. };
  373. #define CID_ValText 1001
  374. #define CID_PointPercent 1002
  375. #define CID_CentCornLab 1003
  376. #define CID_CentCornX 1004
  377. #define CID_CentCornY 1005
  378. #define CID_RadDiamLab 1006
  379. #define CID_RadDiamX 1007
  380. #define CID_RadDiamY 1008
  381. #define CID_Angle 1009
  382. static void FakeShapeEvents(CharView *cv) {
  383. GEvent event;
  384. real trans[6];
  385. cv->active_tool = rectelipse ? cvt_elipse : cvt_rect;
  386. if ( cv->b.sc->inspiro && hasspiro() ) {
  387. GDrawSetCursor(cv->v,spirotools[cv->active_tool]);
  388. GDrawSetCursor(cvtools,spirotools[cv->active_tool]);
  389. } else {
  390. GDrawSetCursor(cv->v,tools[cv->active_tool]);
  391. GDrawSetCursor(cvtools,tools[cv->active_tool]);
  392. }
  393. cv->showing_tool = cv->active_tool;
  394. memset(&event,0,sizeof(event));
  395. event.type = et_mousedown;
  396. CVMouseDownShape(cv,&event);
  397. cv->info.x += raddiam_x;
  398. cv->info.y += raddiam_y;
  399. CVMouseMoveShape(cv);
  400. CVMouseUpShape(cv);
  401. if ( raddiam_x!=0 && raddiam_y!=0 && rotate_by!=0 ) {
  402. trans[0] = trans[3] = cos ( rotate_by*3.1415926535897932/180. );
  403. trans[1] = sin( rotate_by*3.1415926535897932/180. );
  404. trans[2] = -trans[1];
  405. trans[4] = -cv->p.x*trans[0] - cv->p.y*trans[2] + cv->p.x;
  406. trans[5] = -cv->p.x*trans[1] - cv->p.y*trans[3] + cv->p.y;
  407. SplinePointListTransform(cv->b.layerheads[cv->b.drawmode]->splines,trans,
  408. interpCPsOnMotion?tpt_OnlySelectedInterpCPs:tpt_OnlySelected);
  409. SCUpdateAll(cv->b.sc);
  410. }
  411. cv->active_tool = cvt_none;
  412. }
  413. static int TA_OK(GGadget *g, GEvent *e) {
  414. if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
  415. struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
  416. real val, val2=0;
  417. int err=0;
  418. int re = !GGadgetIsChecked(d->rb1);
  419. if ( d->ispolystar ) {
  420. val = GetInt8(d->gw,CID_ValText,d->lab,&err);
  421. if ( !(regular_star = GGadgetIsChecked(d->reg)))
  422. val2 = GetReal8(d->gw,CID_PointPercent,_("Size of Points"),&err);
  423. } else {
  424. val = GetReal8(d->gw,CID_ValText,d->lab,&err);
  425. d->co[re] = !GGadgetIsChecked(d->reg);
  426. }
  427. if ( err )
  428. return( true );
  429. if ( d->haspos ) {
  430. real x,y, radx,rady, ang;
  431. x = GetInt8(d->gw,CID_CentCornX,_("_X"),&err);
  432. y = GetInt8(d->gw,CID_CentCornY,_("_Y"),&err);
  433. radx = GetInt8(d->gw,CID_RadDiamX,_("Radius: "),&err);
  434. rady = GetInt8(d->gw,CID_RadDiamY,_("Radius: "),&err);
  435. ang = GetInt8(d->gw,CID_Angle,_("Angle:"),&err);
  436. if ( err )
  437. return( true );
  438. d->cv->p.x = d->cv->info.x = x;
  439. d->cv->p.y = d->cv->info.y = y;
  440. raddiam_x = radx; raddiam_y = rady;
  441. rotate_by = ang;
  442. rectelipse = re;
  443. *d->val = val;
  444. FakeShapeEvents(d->cv);
  445. }
  446. *d->val = val;
  447. d->ret = re;
  448. d->done = true;
  449. if ( !regular_star && d->ispolystar )
  450. star_percent = val2/100;
  451. SavePrefs(true);
  452. }
  453. return( true );
  454. }
  455. static int TA_Cancel(GGadget *g, GEvent *e) {
  456. if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
  457. struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
  458. d->done = true;
  459. }
  460. return( true );
  461. }
  462. static int TA_CenRadChange(GGadget *g, GEvent *e) {
  463. if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
  464. struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
  465. int is_bb = GGadgetIsChecked(d->reg);
  466. GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_CentCornLab),
  467. is_bb ? _("Corner") : _("C_enter"));
  468. GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_RadDiamLab),
  469. is_bb ? _("Diameter:") : _("Radius: "));
  470. }
  471. return( true );
  472. }
  473. static int TA_RadChange(GGadget *g, GEvent *e) {
  474. if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
  475. struct ask_info *d = GDrawGetUserData(GGadgetGetWindow(g));
  476. int is_ellipse = !GGadgetIsChecked(d->rb1);
  477. GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_ValText), !is_ellipse );
  478. GGadgetSetChecked(d->reg,!center_out[is_ellipse]);
  479. GGadgetSetChecked(d->pts,center_out[is_ellipse]);
  480. if ( d->haspos )
  481. TA_CenRadChange(g,e);
  482. }
  483. return( true );
  484. }
  485. static int toolask_e_h(GWindow gw, GEvent *event) {
  486. if ( event->type==et_close ) {
  487. struct ask_info *d = GDrawGetUserData(gw);
  488. d->done = true;
  489. } else if ( event->type == et_map ) {
  490. /* Above palettes */
  491. GDrawRaise(gw);
  492. }
  493. return( event->type!=et_char );
  494. }
  495. static int Ask(char *rb1, char *rb2, int rb, char *lab, float *val, int *co,
  496. int ispolystar, CharView *cv ) {
  497. struct ask_info d;
  498. char buffer[20], buf[20];
  499. char cenx[20], ceny[20], radx[20], rady[20], angle[20];
  500. GRect pos;
  501. GWindowAttrs wattrs;
  502. GGadgetCreateData gcd[19];
  503. GTextInfo label[19];
  504. int off = ((ispolystar&1)?15:0) + ((ispolystar&2)?84:0);
  505. int haspos = (ispolystar&2)?1:0;
  506. ispolystar &= 1;
  507. d.done = false;
  508. d.ret = rb;
  509. d.val = val;
  510. d.co = co;
  511. d.ispolystar = ispolystar;
  512. d.haspos = haspos;
  513. d.lab = lab;
  514. d.cv = cv;
  515. memset(&wattrs,0,sizeof(wattrs));
  516. wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
  517. wattrs.event_masks = ~(1<<et_charup);
  518. wattrs.restrict_input_to_me = 1;
  519. wattrs.undercursor = 1;
  520. wattrs.cursor = ct_pointer;
  521. wattrs.utf8_window_title = _("Shape Type");
  522. wattrs.is_dlg = true;
  523. pos.x = pos.y = 0;
  524. pos.width = GGadgetScale(GDrawPointsToPixels(NULL,190));
  525. pos.height = GDrawPointsToPixels(NULL,120+off);
  526. d.gw = GDrawCreateTopWindow(NULL,&pos,toolask_e_h,&d,&wattrs);
  527. memset(&label,0,sizeof(label));
  528. memset(&gcd,0,sizeof(gcd));
  529. label[0].text = (unichar_t *) rb1;
  530. label[0].text_is_1byte = true;
  531. gcd[0].gd.label = &label[0];
  532. gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5;
  533. gcd[0].gd.flags = gg_enabled|gg_visible | (rb==0?gg_cb_on:0);
  534. gcd[0].creator = GRadioCreate;
  535. label[1].text = (unichar_t *) rb2;
  536. label[1].text_is_1byte = true;
  537. gcd[1].gd.label = &label[1];
  538. gcd[1].gd.pos.x = ispolystar?65:75; gcd[1].gd.pos.y = 5;
  539. gcd[1].gd.flags = gg_enabled|gg_visible | (rb==1?gg_cb_on:0);
  540. gcd[1].creator = GRadioCreate;
  541. label[2].text = (unichar_t *) lab;
  542. label[2].text_is_1byte = true;
  543. gcd[2].gd.label = &label[2];
  544. gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = 25;
  545. gcd[2].gd.flags = gg_enabled|gg_visible ;
  546. gcd[2].creator = GLabelCreate;
  547. sprintf( buffer, "%g", *val );
  548. label[3].text = (unichar_t *) buffer;
  549. label[3].text_is_1byte = true;
  550. gcd[3].gd.label = &label[3];
  551. gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 40;
  552. gcd[3].gd.flags = gg_enabled|gg_visible ;
  553. gcd[3].gd.cid = CID_ValText;
  554. gcd[3].creator = GTextFieldCreate;
  555. gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = 85+off;
  556. gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
  557. gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
  558. label[4].text = (unichar_t *) _("_OK");
  559. label[4].text_is_1byte = true;
  560. label[4].text_in_resource = true;
  561. gcd[4].gd.mnemonic = 'O';
  562. gcd[4].gd.label = &label[4];
  563. gcd[4].gd.handle_controlevent = TA_OK;
  564. gcd[4].creator = GButtonCreate;
  565. gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = 85+3+off;
  566. gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
  567. gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
  568. label[5].text = (unichar_t *) _("_Cancel");
  569. label[5].text_is_1byte = true;
  570. label[5].text_in_resource = true;
  571. gcd[5].gd.label = &label[5];
  572. gcd[5].gd.mnemonic = 'C';
  573. gcd[5].gd.handle_controlevent = TA_Cancel;
  574. gcd[5].creator = GButtonCreate;
  575. if ( ispolystar ) {
  576. label[6].text = (unichar_t *) _("Regular");
  577. label[6].text_is_1byte = true;
  578. gcd[6].gd.label = &label[6];
  579. gcd[6].gd.pos.x = 5; gcd[6].gd.pos.y = 70;
  580. gcd[6].gd.flags = gg_enabled|gg_visible | (rb==0?gg_cb_on:0);
  581. gcd[6].creator = GRadioCreate;
  582. label[7].text = (unichar_t *) _("Points:");
  583. label[7].text_is_1byte = true;
  584. gcd[7].gd.label = &label[7];
  585. gcd[7].gd.pos.x = 65; gcd[7].gd.pos.y = 70;
  586. gcd[7].gd.flags = gg_enabled|gg_visible | (rb==1?gg_cb_on:0);
  587. gcd[7].creator = GRadioCreate;
  588. sprintf( buf, "%4g", star_percent*100 );
  589. label[8].text = (unichar_t *) buf;
  590. label[8].text_is_1byte = true;
  591. gcd[8].gd.label = &label[8];
  592. gcd[8].gd.pos.x = 125; gcd[8].gd.pos.y = 70; gcd[8].gd.pos.width=50;
  593. gcd[8].gd.flags = gg_enabled|gg_visible ;
  594. gcd[8].gd.cid = CID_PointPercent;
  595. gcd[8].creator = GTextFieldCreate;
  596. label[9].text = (unichar_t *) "%";
  597. label[9].text_is_1byte = true;
  598. gcd[9].gd.label = &label[9];
  599. gcd[9].gd.pos.x = 180; gcd[9].gd.pos.y = 70;
  600. gcd[9].gd.flags = gg_enabled|gg_visible ;
  601. gcd[9].creator = GLabelCreate;
  602. } else {
  603. label[6].text = (unichar_t *) _("Bounding Box");
  604. label[6].text_is_1byte = true;
  605. gcd[6].gd.label = &label[6];
  606. gcd[6].gd.pos.x = 5; gcd[6].gd.pos.y = 65;
  607. gcd[6].gd.flags = gg_enabled|gg_visible | (co[rb]==0?gg_cb_on:0);
  608. gcd[6].creator = GRadioCreate;
  609. label[7].text = (unichar_t *) _("Center Out");
  610. label[7].text_is_1byte = true;
  611. gcd[7].gd.label = &label[7];
  612. gcd[7].gd.pos.x = 90; gcd[7].gd.pos.y = 65;
  613. gcd[7].gd.flags = gg_enabled|gg_visible | (co[rb]==1?gg_cb_on:0);
  614. gcd[7].creator = GRadioCreate;
  615. if ( rb )
  616. gcd[3].gd.flags = gg_visible;
  617. gcd[0].gd.handle_controlevent = TA_RadChange;
  618. gcd[1].gd.handle_controlevent = TA_RadChange;
  619. if ( haspos ) {
  620. gcd[6].gd.handle_controlevent = TA_CenRadChange;
  621. gcd[7].gd.handle_controlevent = TA_CenRadChange;
  622. label[8].text = (unichar_t *) _("_X");
  623. label[8].text_is_1byte = true;
  624. label[8].text_in_resource = true;
  625. gcd[8].gd.label = &label[8];
  626. gcd[8].gd.pos.x = 70; gcd[8].gd.pos.y = gcd[7].gd.pos.y+15;
  627. gcd[8].gd.flags = gg_enabled|gg_visible;
  628. gcd[8].creator = GLabelCreate;
  629. label[9].text = (unichar_t *) _("_Y");
  630. label[9].text_is_1byte = true;
  631. label[9].text_in_resource = true;
  632. gcd[9].gd.label = &label[9];
  633. gcd[9].gd.pos.x = 120; gcd[9].gd.pos.y = gcd[8].gd.pos.y;
  634. gcd[9].gd.flags = gg_enabled|gg_visible;
  635. gcd[9].creator = GLabelCreate;
  636. label[10].text = (unichar_t *) (co[rb] ? _("C_enter") : _("C_orner") );
  637. label[10].text_is_1byte = true;
  638. label[10].text_in_resource = true;
  639. gcd[10].gd.label = &label[10];
  640. gcd[10].gd.pos.x = 5; gcd[10].gd.pos.y = gcd[8].gd.pos.y+17;
  641. gcd[10].gd.flags = gg_enabled|gg_visible;
  642. gcd[10].gd.cid = CID_CentCornLab;
  643. gcd[10].creator = GLabelCreate;
  644. sprintf( cenx, "%g", (double) cv->info.x );
  645. label[11].text = (unichar_t *) cenx;
  646. label[11].text_is_1byte = true;
  647. gcd[11].gd.label = &label[11];
  648. gcd[11].gd.pos.x = 60; gcd[11].gd.pos.y = gcd[10].gd.pos.y-4;
  649. gcd[11].gd.pos.width = 40;
  650. gcd[11].gd.flags = gg_enabled|gg_visible;
  651. gcd[11].gd.cid = CID_CentCornX;
  652. gcd[11].creator = GTextFieldCreate;
  653. sprintf( ceny, "%g", (double) cv->info.y );
  654. label[12].text = (unichar_t *) ceny;
  655. label[12].text_is_1byte = true;
  656. gcd[12].gd.label = &label[12];
  657. gcd[12].gd.pos.x = 110; gcd[12].gd.pos.y = gcd[11].gd.pos.y;
  658. gcd[12].gd.pos.width = gcd[11].gd.pos.width;
  659. gcd[12].gd.flags = gg_enabled|gg_visible;
  660. gcd[12].gd.cid = CID_CentCornY;
  661. gcd[12].creator = GTextFieldCreate;
  662. label[13].text = (unichar_t *) (co[rb] ? _("Radius: ") : _("Diameter:") );
  663. label[13].text_is_1byte = true;
  664. gcd[13].gd.label = &label[13];
  665. gcd[13].gd.pos.x = 5; gcd[13].gd.pos.y = gcd[10].gd.pos.y+24;
  666. gcd[13].gd.flags = gg_enabled|gg_visible;
  667. gcd[13].gd.cid = CID_RadDiamLab;
  668. gcd[13].creator = GLabelCreate;
  669. sprintf( radx, "%g", (double) raddiam_x );
  670. label[14].text = (unichar_t *) radx;
  671. label[14].text_is_1byte = true;
  672. gcd[14].gd.label = &label[14];
  673. gcd[14].gd.pos.x = gcd[11].gd.pos.x; gcd[14].gd.pos.y = gcd[13].gd.pos.y-4;
  674. gcd[14].gd.pos.width = gcd[11].gd.pos.width;
  675. gcd[14].gd.flags = gg_enabled|gg_visible;
  676. gcd[14].gd.cid = CID_RadDiamX;
  677. gcd[14].creator = GTextFieldCreate;
  678. sprintf( rady, "%g", (double) raddiam_y );
  679. label[15].text = (unichar_t *) rady;
  680. label[15].text_is_1byte = true;
  681. gcd[15].gd.label = &label[15];
  682. gcd[15].gd.pos.x = gcd[12].gd.pos.x; gcd[15].gd.pos.y = gcd[14].gd.pos.y;
  683. gcd[15].gd.pos.width = gcd[11].gd.pos.width;
  684. gcd[15].gd.flags = gg_enabled|gg_visible;
  685. gcd[15].gd.cid = CID_RadDiamY;
  686. gcd[15].creator = GTextFieldCreate;
  687. label[16].text = (unichar_t *) _("Angle:");
  688. label[16].text_is_1byte = true;
  689. gcd[16].gd.label = &label[16];
  690. gcd[16].gd.pos.x = 5; gcd[16].gd.pos.y = gcd[13].gd.pos.y+24;
  691. gcd[16].gd.flags = gg_enabled|gg_visible;
  692. gcd[16].creator = GLabelCreate;
  693. sprintf( angle, "%g", (double) rotate_by );
  694. label[17].text = (unichar_t *) angle;
  695. label[17].text_is_1byte = true;
  696. gcd[17].gd.label = &label[17];
  697. gcd[17].gd.pos.x = 60; gcd[17].gd.pos.y = gcd[16].gd.pos.y-4;
  698. gcd[17].gd.pos.width = gcd[11].gd.pos.width;
  699. gcd[17].gd.flags = gg_enabled|gg_visible;
  700. gcd[17].gd.cid = CID_Angle;
  701. gcd[17].creator = GTextFieldCreate;
  702. }
  703. }
  704. GGadgetsCreate(d.gw,gcd);
  705. d.rb1 = gcd[0].ret;
  706. d.reg = gcd[6].ret;
  707. d.pts = gcd[7].ret;
  708. GWidgetHidePalettes();
  709. GDrawSetVisible(d.gw,true);
  710. while ( !d.done )
  711. GDrawProcessOneEvent(NULL);
  712. GDrawDestroyWindow(d.gw);
  713. return( d.ret );
  714. }
  715. static void CVRectElipse(CharView *cv) {
  716. rectelipse = Ask(_("Rectangle"),_("Ellipse"),rectelipse,
  717. _("Round Rectangle Radius"),&rr_radius,center_out,false, cv);
  718. GDrawRequestExpose(cvtools,NULL,false);
  719. }
  720. void CVRectEllipsePosDlg(CharView *cv) {
  721. rectelipse = Ask(_("Rectangle"),_("Ellipse"),rectelipse,
  722. _("Round Rectangle Radius"),&rr_radius,center_out,2, cv);
  723. GDrawRequestExpose(cvtools,NULL,false);
  724. }
  725. static void CVPolyStar(CharView *cv) {
  726. float temp = ps_pointcnt;
  727. int foo[2];
  728. polystar = Ask(_("Polygon"),_("Star"),polystar,
  729. _("Number of star points/Polygon vertices"),&temp,foo,true, cv);
  730. ps_pointcnt = temp;
  731. }
  732. static void ToolsExpose(GWindow pixmap, CharView *cv, GRect *r) {
  733. GRect old;
  734. /* Note: If you change this ordering, change enum cvtools */
  735. static GImage *normbuttons[][2] = { { &GIcon_pointer, &GIcon_magnify },
  736. { &GIcon_freehand, &GIcon_hand },
  737. { &GIcon_knife, &GIcon_ruler },
  738. { &GIcon_pen, &GIcon_spirodisabled },
  739. { &GIcon_curve, &GIcon_hvcurve },
  740. { &GIcon_corner, &GIcon_tangent},
  741. { &GIcon_scale, &GIcon_rotate },
  742. { &GIcon_flip, &GIcon_skew },
  743. { &GIcon_3drotate, &GIcon_perspective },
  744. { &GIcon_rect, &GIcon_poly},
  745. { &GIcon_elipse, &GIcon_star}};
  746. static GImage *spirobuttons[][2] = { { &GIcon_pointer, &GIcon_magnify },
  747. { &GIcon_freehand, &GIcon_hand },
  748. { &GIcon_knife, &GIcon_ruler },
  749. { &GIcon_spiroright, &GIcon_spirodown },
  750. { &GIcon_spirocurve, &GIcon_spirog2curve },
  751. { &GIcon_spirocorner, &GIcon_spiroleft },
  752. { &GIcon_scale, &GIcon_rotate },
  753. { &GIcon_flip, &GIcon_skew },
  754. { &GIcon_3drotate, &GIcon_perspective },
  755. { &GIcon_rect, &GIcon_poly},
  756. { &GIcon_elipse, &GIcon_star}};
  757. static GImage *normsmalls[] = { &GIcon_smallpointer, &GIcon_smallmag,
  758. &GIcon_smallpencil, &GIcon_smallhand,
  759. &GIcon_smallknife, &GIcon_smallruler,
  760. &GIcon_smallpen, NULL,
  761. &GIcon_smallcurve, &GIcon_smallhvcurve,
  762. &GIcon_smallcorner, &GIcon_smalltangent,
  763. &GIcon_smallscale, &GIcon_smallrotate,
  764. &GIcon_smallflip, &GIcon_smallskew,
  765. &GIcon_small3drotate, &GIcon_smallperspective,
  766. &GIcon_smallrect, &GIcon_smallpoly,
  767. &GIcon_smallelipse, &GIcon_smallstar };
  768. static GImage *spirosmalls[] = { &GIcon_smallpointer, &GIcon_smallmag,
  769. &GIcon_smallpencil, &GIcon_smallhand,
  770. &GIcon_smallknife, &GIcon_smallruler,
  771. &GIcon_smallspiroright, NULL,
  772. &GIcon_smallspirocurve, &GIcon_smallspirog2curve,
  773. &GIcon_smallspirocorner, &GIcon_smallspiroleft,
  774. &GIcon_smallscale, &GIcon_smallrotate,
  775. &GIcon_smallflip, &GIcon_smallskew,
  776. &GIcon_small3drotate, &GIcon_smallperspective,
  777. &GIcon_smallrect, &GIcon_smallpoly,
  778. &GIcon_smallelipse, &GIcon_smallstar };
  779. static const unichar_t _Mouse[][9] = {
  780. { 'M', 's', 'e', '1', '\0' },
  781. { '^', 'M', 's', 'e', '1', '\0' },
  782. { 'M', 's', 'e', '2', '\0' },
  783. { '^', 'M', 's', 'e', '2', '\0' }};
  784. int i,j,norm, mi;
  785. int tool = cv->cntrldown?cv->cb1_tool:cv->b1_tool;
  786. int dither = GDrawSetDither(NULL,false);
  787. GRect temp;
  788. int canspiro = hasspiro(), inspiro = canspiro && cv->b.sc->inspiro;
  789. GImage *(*buttons)[2] = inspiro ? spirobuttons : normbuttons;
  790. GImage **smalls = inspiro ? spirosmalls : normsmalls;
  791. normbuttons[3][1] = canspiro ? &GIcon_spiroup : &GIcon_spirodisabled;
  792. GDrawPushClip(pixmap,r,&old);
  793. GDrawFillRect(pixmap,r,GDrawGetDefaultBackground(NULL));
  794. GDrawSetLineWidth(pixmap,0);
  795. for ( i=0; i<sizeof(normbuttons)/sizeof(normbuttons[0])-1; ++i ) for ( j=0; j<2; ++j ) {
  796. mi = i;
  797. if ( i==(cvt_rect)/2 && ((j==0 && rectelipse) || (j==1 && polystar)) )
  798. ++mi;
  799. /* if ( cv->b.sc->parent->order2 && buttons[mi][j]==&GIcon_freehand ) */
  800. /* GDrawDrawImage(pixmap,&GIcon_greyfree,NULL,j*27+1,i*27+1); */
  801. /* else */
  802. GDrawDrawImage(pixmap,buttons[mi][j],NULL,j*27+1,i*27+1);
  803. norm = (mi*2+j!=tool);
  804. {
  805. // These are from charview.c.
  806. extern int cvbutton3d; // Default 1.
  807. extern Color cvbutton3dedgelightcol; // Default 0xe0e0e0.
  808. extern Color cvbutton3dedgedarkcol; // Default 0x707070.
  809. if (cvbutton3d) {
  810. GDrawDrawLine(pixmap,j*27,i*27,j*27+25,i*27,norm?cvbutton3dedgelightcol:cvbutton3dedgedarkcol);
  811. GDrawDrawLine(pixmap,j*27,i*27,j*27,i*27+25,norm?cvbutton3dedgelightcol:cvbutton3dedgedarkcol);
  812. GDrawDrawLine(pixmap,j*27,i*27+25,j*27+25,i*27+25,norm?cvbutton3dedgedarkcol:cvbutton3dedgelightcol);
  813. GDrawDrawLine(pixmap,j*27+25,i*27,j*27+25,i*27+25,norm?cvbutton3dedgedarkcol:cvbutton3dedgelightcol);
  814. }
  815. }
  816. }
  817. GDrawSetFont(pixmap,toolsfont);
  818. temp.x = 52-16; temp.y = i*27; temp.width = 16; temp.height = 4*12;
  819. GDrawFillRect(pixmap,&temp,GDrawGetDefaultBackground(NULL));
  820. for ( j=0; j<4; ++j ) {
  821. GDrawDrawText(pixmap,2,i*27+j*12+10,(unichar_t *) _Mouse[j],-1,GDrawGetDefaultForeground(NULL));
  822. if ( (&cv->b1_tool)[j]!=cvt_none && smalls[(&cv->b1_tool)[j]])
  823. GDrawDrawImage(pixmap,smalls[(&cv->b1_tool)[j]],NULL,52-16,i*27+j*12);
  824. }
  825. GDrawPopClip(pixmap,&old);
  826. GDrawSetDither(NULL,dither);
  827. }
  828. int TrueCharState(GEvent *event) {
  829. int bit = 0;
  830. /* X doesn't set the state until after the event. I want the state to */
  831. /* reflect whatever key just got depressed/released */
  832. int keysym = event->u.chr.keysym;
  833. if ( keysym == GK_Caps_Lock || keysym == GK_Shift_Lock ) {
  834. static int set_on_last_down = false;
  835. /* caps lock is sticky and doesn't work like the other modifiers */
  836. /* but it is even worse. the bit seems to be set on key down, but */
  837. /* unset on key up. In other words on key up, the bit will always */
  838. /* set and we have no idea which way it will go. So we guess, and */
  839. /* if they haven't messed with the key outside ff we should be right */
  840. if ( event->type == et_char ) {
  841. set_on_last_down = (event->u.chr.state ^ ksm_capslock)& ksm_capslock;
  842. return( event->u.chr.state ^ ksm_capslock );
  843. } else if ( !(event->u.chr.state & ksm_capslock) || set_on_last_down )
  844. return( event->u.chr.state );
  845. else
  846. return( event->u.chr.state & ~ksm_capslock );
  847. }
  848. if ( keysym == GK_Meta_L || keysym == GK_Meta_R ||
  849. keysym == GK_Alt_L || keysym == GK_Alt_R )
  850. bit = ksm_meta;
  851. else if ( keysym == GK_Shift_L || keysym == GK_Shift_R )
  852. bit = ksm_shift;
  853. else if ( keysym == GK_Control_L || keysym == GK_Control_R )
  854. bit = ksm_control;
  855. else if ( keysym == GK_Super_L || keysym == GK_Super_L )
  856. bit = ksm_super;
  857. else if ( keysym == GK_Hyper_L || keysym == GK_Hyper_L )
  858. bit = ksm_hyper;
  859. else
  860. return( event->u.chr.state );
  861. if ( event->type == et_char )
  862. return( event->u.chr.state | bit );
  863. else
  864. return( event->u.chr.state & ~bit );
  865. }
  866. void CVToolsSetCursor(CharView *cv, int state, char *device) {
  867. int shouldshow;
  868. int cntrl;
  869. if ( tools[0] == ct_pointer ) {
  870. tools[cvt_pointer] = ct_mypointer;
  871. tools[cvt_magnify] = ct_magplus;
  872. tools[cvt_freehand] = ct_pencil;
  873. tools[cvt_hand] = ct_myhand;
  874. tools[cvt_curve] = ct_circle;
  875. tools[cvt_hvcurve] = ct_hvcircle;
  876. tools[cvt_corner] = ct_square;
  877. tools[cvt_tangent] = ct_triangle;
  878. tools[cvt_pen] = ct_pen;
  879. tools[cvt_knife] = ct_knife;
  880. tools[cvt_ruler] = ct_ruler;
  881. tools[cvt_scale] = ct_scale;
  882. tools[cvt_flip] = ct_flip;
  883. tools[cvt_rotate] = ct_rotate;
  884. tools[cvt_skew] = ct_skew;
  885. tools[cvt_3d_rotate] = ct_3drotate;
  886. tools[cvt_perspective] = ct_perspective;
  887. tools[cvt_rect] = ct_rect;
  888. tools[cvt_poly] = ct_poly;
  889. tools[cvt_elipse] = ct_elipse;
  890. tools[cvt_star] = ct_star;
  891. tools[cvt_minify] = ct_magminus;
  892. memcpy(spirotools,tools,sizeof(tools));
  893. spirotools[cvt_spirog2] = ct_g2circle;
  894. spirotools[cvt_spiroleft] = ct_spiroleft;
  895. spirotools[cvt_spiroright] = ct_spiroright;
  896. }
  897. shouldshow = cvt_none;
  898. if ( cv->active_tool!=cvt_none )
  899. shouldshow = cv->active_tool;
  900. else if ( cv->pressed_display!=cvt_none )
  901. shouldshow = cv->pressed_display;
  902. else if ( device==NULL || strcmp(device,"Mouse1")==0 ) {
  903. if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button4))
  904. shouldshow = cvt_magnify;
  905. else if ( (state&(ksm_shift|ksm_control)) && (state&ksm_button5))
  906. shouldshow = cvt_minify;
  907. else if ( (state&ksm_control) && (state&(ksm_button2|ksm_super)) )
  908. shouldshow = cv->cb2_tool;
  909. else if ( (state&(ksm_button2|ksm_super)) )
  910. shouldshow = cv->b2_tool;
  911. else if ( (state&ksm_control) )
  912. shouldshow = cv->cb1_tool;
  913. else
  914. shouldshow = cv->b1_tool;
  915. } else if ( strcmp(device,"eraser")==0 )
  916. shouldshow = cv->er_tool;
  917. else if ( strcmp(device,"stylus")==0 ) {
  918. if ( (state&(ksm_button2|ksm_control|ksm_super)) )
  919. shouldshow = cv->s2_tool;
  920. else
  921. shouldshow = cv->s1_tool;
  922. }
  923. if ( shouldshow==cvt_magnify && (state&ksm_meta))
  924. shouldshow = cvt_minify;
  925. if ( shouldshow!=cv->showing_tool ) {
  926. CPEndInfo(cv);
  927. if ( cv->b.sc->inspiro && hasspiro()) {
  928. GDrawSetCursor(cv->v,spirotools[shouldshow]);
  929. if ( cvtools!=NULL ) /* Might happen if window owning docked palette destroyed */
  930. GDrawSetCursor(cvtools,spirotools[shouldshow]);
  931. } else {
  932. GDrawSetCursor(cv->v,tools[shouldshow]);
  933. if ( cvtools!=NULL ) /* Might happen if window owning docked palette destroyed */
  934. GDrawSetCursor(cvtools,tools[shouldshow]);
  935. }
  936. cv->showing_tool = shouldshow;
  937. }
  938. if ( device==NULL || strcmp(device,"stylus")==0 ) {
  939. cntrl = (state&ksm_control)?1:0;
  940. if ( device!=NULL && (state&ksm_button2))
  941. cntrl = true;
  942. if ( cntrl != cv->cntrldown ) {
  943. cv->cntrldown = cntrl;
  944. GDrawRequestExpose(cvtools,NULL,false);
  945. }
  946. }
  947. }
  948. static int CVCurrentTool(CharView *cv, GEvent *event) {
  949. if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"eraser")==0 )
  950. return( cv->er_tool );
  951. else if ( event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"stylus")==0 ) {
  952. if ( event->u.mouse.button==2 )
  953. /* Only thing that matters is touch which maps to button 1 */;
  954. else if ( cv->had_control )
  955. return( cv->s2_tool );
  956. else
  957. return( cv->s1_tool );
  958. }
  959. if ( cv->had_control && event->u.mouse.button==2 )
  960. return( cv->cb2_tool );
  961. else if ( event->u.mouse.button==2 )
  962. return( cv->b2_tool );
  963. else if ( cv->had_control ) {
  964. return( cv->cb1_tool );
  965. } else {
  966. return( cv->b1_tool );
  967. }
  968. }
  969. static void SCCheckForSSToOptimize(SplineChar *sc, SplineSet *ss,int order2) {
  970. for ( ; ss!=NULL ; ss = ss->next ) {
  971. if ( ss->beziers_need_optimizer ) {
  972. SplineSetAddExtrema(sc,ss,ae_only_good,sc->parent->ascent+sc->parent->descent);
  973. ss->beziers_need_optimizer = false;
  974. }
  975. if ( order2 && ss->first->next!=NULL && !ss->first->next->order2 ) {
  976. SplineSet *temp = SSttfApprox(ss), foo;
  977. foo = *ss;
  978. ss->first = temp->first; ss->last = temp->last;
  979. temp->first = foo.first; temp->last = foo.last;
  980. SplinePointListFree(temp);
  981. }
  982. }
  983. }
  984. static void CVChangeSpiroMode(CharView *cv) {
  985. if ( hasspiro() ) {
  986. cv->b.sc->inspiro = !cv->b.sc->inspiro;
  987. cv->showing_tool = cvt_none;
  988. CVClearSel(cv);
  989. if ( !cv->b.sc->inspiro )
  990. SCCheckForSSToOptimize(cv->b.sc,cv->b.layerheads[cv->b.drawmode]->splines,
  991. cv->b.layerheads[cv->b.drawmode]->order2);
  992. GDrawRequestExpose(cvtools,NULL,false);
  993. SCUpdateAll(cv->b.sc);
  994. } else
  995. #ifdef _NO_LIBSPIRO
  996. 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."));
  997. #else
  998. ff_post_error(_("You may not use spiros"),_("FontForge was unable to load libspiro, spiros are not available for use."));
  999. #endif
  1000. }
  1001. char* HKTextInfoToUntranslatedTextFromTextInfo( GTextInfo* ti ); // From ../gdraw/gmenu.c.
  1002. static void ToolsMouse(CharView *cv, GEvent *event) {
  1003. int i = (event->u.mouse.y/27), j = (event->u.mouse.x/27), mi=i;
  1004. int pos;
  1005. int isstylus = event->u.mouse.device!=NULL && strcmp(event->u.mouse.device,"stylus")==0;
  1006. int styluscntl = isstylus && (event->u.mouse.state&0x200);
  1007. static int settings[2];
  1008. if(j >= 2)
  1009. return; /* If the wm gave me a window the wrong size */
  1010. if ( i==(cvt_rect)/2 ) {
  1011. int current = CVCurrentTool(cv,event);
  1012. int changed = false;
  1013. if ( event->type == et_mousedown && event->u.mouse.clicks>=2 ) {
  1014. rectelipse = settings[0];
  1015. polystar = settings[1];
  1016. } else if ( event->type == et_mousedown ) {
  1017. settings[0] = rectelipse; settings[1] = polystar;
  1018. /* A double click will change the type twice, which leaves it where it was, which is desired */
  1019. if ( j==0 && ((!rectelipse && current==cvt_rect) || (rectelipse && current==cvt_elipse)) ) {
  1020. rectelipse = !rectelipse;
  1021. changed = true;
  1022. } else if (j==1 && ((!polystar && current==cvt_poly) || (polystar && current==cvt_star)) ) {
  1023. polystar = !polystar;
  1024. changed = true;
  1025. }
  1026. if ( changed ) {
  1027. SavePrefs(true);
  1028. GDrawRequestExpose(cvtools,NULL,false);
  1029. }
  1030. }

Large files files are truncated, but you can click here to view the full file