1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/shape.c,v 1.8 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_SHAPE_C_
22
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25
26 #include "arc.e"
27 #include "attr.e"
28 #include "auxtext.e"
29 #include "box.e"
30 #include "cmd.e"
31 #include "color.e"
32 #include "cursor.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "dup.e"
36 #include "grid.e"
37 #include "group.e"
38 #include "mainloop.e"
39 #include "menu.e"
40 #include "menuinfo.e"
41 #include "move.e"
42 #include "msg.e"
43 #include "navigate.e"
44 #include "obj.e"
45 #include "oval.e"
46 #include "page.e"
47 #include "pattern.e"
48 #include "poly.e"
49 #include "polygon.e"
50 #include "raster.e"
51 #include "ruler.e"
52 #include "select.e"
53 #include "setup.e"
54 #include "shape.e"
55 #include "spline.e"
56 #include "strtbl.e"
57 #include "text.e"
58 #include "util.e"
59
60 int numShapes=MAXSHAPES;
61 int curShape=(-1);
62 int shapeShadowInResource=FALSE;
63 int shapeShadowDx=0;
64 int shapeShadowDy=0;
65
66 /* ----------------------- String Functions ----------------------- */
67
68 static struct MouseStatusStrRec shapeDescMouseStatus[] = {
69 /*
70 * note: the m field is used for the localized strings
71 */
72 { N_("Create a box"), NULL, NULL },
73 { N_("Create a parallelegram"), NULL, NULL },
74 { N_("Create a trapezoid"), NULL, NULL },
75 { N_("Create a rhombus"), NULL, NULL },
76 { N_("Create a rounded-corner box"), NULL, NULL },
77 { N_("Create an octagon"), NULL, NULL },
78 { N_("Create a cross"), NULL, NULL },
79 { N_("Create an oval"), NULL, NULL },
80 { N_("Create a word box"), NULL, NULL },
81 { N_("Create a hexagon"), NULL, NULL },
82 { N_("Create a triangle"), NULL, NULL },
83 { N_("Create a blast box"), NULL, NULL },
84 { N_("Create a star"), NULL, NULL },
85 { N_("Create a disk"), NULL, NULL },
86 { N_("Create a right arrow"), NULL, NULL },
87 { N_("Create a up arrow"), NULL, NULL },
88 { N_("Create a fat right arrow"), NULL, NULL },
89 { N_("Create a fat up arrow"), NULL, NULL },
90 { N_("Create a right tab"), NULL, NULL },
91 { N_("Create a up tab"), NULL, NULL },
92 { NULL, NULL, NULL }
93 };
94
95 static
CleanUpShapeDescMouseStatusStrings()96 void CleanUpShapeDescMouseStatusStrings()
97 {
98 int index=0;
99
100 for (index=0; index < MAXCHOICES; index++) {
101 UtilFree(shapeDescMouseStatus[index].m);
102 shapeDescMouseStatus[index].m = NULL;
103 }
104 }
105
106 static
GetShapeDesc(index)107 char *GetShapeDesc(index)
108 int index;
109 /* returned string has been translated */
110 {
111 if (shapeDescMouseStatus[index].m == NULL) {
112 shapeDescMouseStatus[index].m =
113 UtilStrDup(_(shapeDescMouseStatus[index].l));
114 if (shapeDescMouseStatus[index].m == NULL) FailAllocMessage();
115 }
116 return shapeDescMouseStatus[index].m;
117 }
118
119 /* ----------------------- Create Shape Functions ----------------------- */
120
121 static IntPoint *gpVertices=NULL;
122 static int gnNumVs=0;
123
124 static XPoint *gpRubberVertices=NULL;
125 static int gnNumSplineVs=0;
126
127 static char *gpnSmooth=NULL;
128
129 static int gnOrigX=0, gnOrigY=0, gnEndX=0, gnEndY=0;
130 static struct BBRec gShapeBBox;
131
132 static
CreatePolygonShape(num_pts,has_smooth)133 int CreatePolygonShape(num_pts, has_smooth)
134 int num_pts, has_smooth;
135 {
136 gpVertices = (IntPoint*)malloc(num_pts*sizeof(IntPoint));
137 if (gpVertices == NULL) return FailAllocMessage();
138 memset(gpVertices, 0, num_pts*sizeof(IntPoint));
139 if (has_smooth) {
140 gpnSmooth = (char*)malloc(num_pts*sizeof(char));
141 if (gpnSmooth == NULL) {
142 free(gpVertices);
143 gpVertices = NULL;
144 return FailAllocMessage();
145 }
146 memset(gpnSmooth, 0, num_pts*sizeof(char));
147 }
148 gnNumVs = num_pts;
149 return TRUE;
150 }
151
152 static
CreateOvalShape()153 int CreateOvalShape()
154 {
155 gpVertices = NULL;
156 gpnSmooth = NULL;
157 gnNumVs = gnNumSplineVs = 0;
158
159 memset(&gShapeBBox, 0, sizeof(struct BBRec));
160 return TRUE;
161 }
162
163 static
CreateDiskShape()164 int CreateDiskShape()
165 {
166 gpVertices = NULL;
167 gpnSmooth = NULL;
168 gnNumVs = gnNumSplineVs = 0;
169
170 memset(&gShapeBBox, 0, sizeof(struct BBRec));
171 return TRUE;
172 }
173
174 static
StartCreateShape(orig_x,orig_y)175 int StartCreateShape(orig_x, orig_y)
176 int orig_x, orig_y;
177 {
178 gnOrigX = gnEndX = orig_x;
179 gnOrigY = gnEndY = orig_y;
180
181 switch (curShape) {
182 case SHAPE_BOX: return CreatePolygonShape(5, FALSE);
183 case SHAPE_PARALLEL: return CreatePolygonShape(5, FALSE);
184 case SHAPE_TRAPEZOID: return CreatePolygonShape(5, FALSE);
185 case SHAPE_RHOMBUS: return CreatePolygonShape(5, FALSE);
186 case SHAPE_RCBOX: return CreatePolygonShape(13, TRUE);
187 case SHAPE_OCTAGON: return CreatePolygonShape(9, FALSE);
188 case SHAPE_CROSS: return CreatePolygonShape(13, FALSE);
189 case SHAPE_OVAL: return CreateOvalShape();
190 case SHAPE_WORDS: return CreatePolygonShape(16, TRUE);
191 case SHAPE_HEXAGON: return CreatePolygonShape(7, FALSE);
192 case SHAPE_TRIANGLE: return CreatePolygonShape(4, FALSE);
193 case SHAPE_BLAST: return CreatePolygonShape(34, FALSE);
194 case SHAPE_STAR: return CreatePolygonShape(12, FALSE);
195 case SHAPE_DISK: return CreateDiskShape();
196 case SHAPE_RIGHTARROW: return CreatePolygonShape(8, FALSE);
197 case SHAPE_UPARROW: return CreatePolygonShape(8, FALSE);
198 case SHAPE_FATRIGHTARROW: return CreatePolygonShape(8, FALSE);
199 case SHAPE_FATUPARROW: return CreatePolygonShape(8, FALSE);
200 case SHAPE_RIGHTTAB: return CreatePolygonShape(6, FALSE);
201 case SHAPE_UPTAB: return CreatePolygonShape(6, FALSE);
202 }
203 return FALSE;
204 }
205
206 static
EndCreateShape()207 void EndCreateShape()
208 {
209 if (gpVertices != NULL) free(gpVertices);
210 gpVertices = NULL;
211 if (gpRubberVertices != NULL) free(gpRubberVertices);
212 gpRubberVertices = NULL;
213 if (gpnSmooth != NULL) free(gpnSmooth);
214 gpnSmooth = NULL;
215 gnNumVs = gnNumSplineVs = 0;
216 }
217
218 /* ----------------------- HighLight Calc Functions ----------------------- */
219
220 #define SHAPE_ANGLE (((double)15.0)*M_PI/((double)180.0))
221
222 static
TangentOfAngle()223 double TangentOfAngle()
224 {
225 static int nInitialized=FALSE;
226 static double dval=(double)0.0;
227
228 if (nInitialized) return dval;
229 nInitialized = TRUE;
230 dval = ((double)sin(SHAPE_ANGLE)) / ((double)cos(SHAPE_ANGLE));
231 return dval;
232 }
233
234 static
CalcRegularPolygonVs(sides,vertex_at_right,start_degree,scale,start_index,index_step)235 void CalcRegularPolygonVs(sides, vertex_at_right, start_degree, scale,
236 start_index, index_step)
237 int sides, vertex_at_right, start_degree, start_index, index_step;
238 double scale;
239 /* if (vertex_at_right), easy */
240 /* if (!vertex_at_right && start_degree == 0) self-determined */
241 /* if (!vertex_at_right && start_degree != 0) start_degree is the */
242 /* real start angle in degrees */
243 {
244 int i, w=gnEndX-gnOrigX, h=gnEndY-gnOrigY, index=start_index;
245 int xc=((gnEndX+gnOrigX)>>1), yc=((gnEndY+gnOrigY)>>1);
246 double inc=((double)2.0)*M_PI/((double)sides), radius, rx, ry;
247 double angle=(vertex_at_right ? (double)0.0 : inc/((double)2.0));
248
249 if (vertex_at_right) {
250 radius = (double)0.5;
251 angle = (double)0.0;
252 } else {
253 angle = inc/((double)2.0);
254 radius = (((sides%4)==0) ? (double)(cos(angle)/2.0) : (double)0.5);
255 if (start_degree != 0) {
256 angle = ((double)start_degree)*M_PI/((double)180.0);
257 }
258 }
259 rx = radius*((double)w)*scale;
260 ry = radius*((double)h)*scale;
261 for (i=0; i < sides; i++, angle += inc, index += index_step) {
262 double dw=rx*((double)cos(angle));
263 double dh=ry*((double)sin(angle));
264
265 gpVertices[index].x = xc + round(dw);
266 gpVertices[index].y = yc + round(dh);
267 }
268 gpVertices[index].x = gpVertices[start_index].x;
269 gpVertices[index].y = gpVertices[start_index].y;
270 gnNumVs = sides+1;
271 }
272
273 static
CalcBoxShapeVs()274 void CalcBoxShapeVs()
275 {
276 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY;
277 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
278 gpVertices[2].x = gnEndX; gpVertices[2].y = gnEndY;
279 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY;
280
281 gpVertices[4].x = gpVertices[0].x;
282 gpVertices[4].y = gpVertices[0].y;
283 }
284
285 static
CalcParallelShapeVs()286 void CalcParallelShapeVs()
287 {
288 int h=gnEndY-gnOrigY, dx;
289 double dval;
290
291 dval = ((double)h) * TangentOfAngle();
292 dx = (int)round(dval);
293 gpVertices[0].x = gnOrigX+dx; gpVertices[0].y = gnOrigY;
294 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
295 gpVertices[2].x = gnEndX-dx; gpVertices[2].y = gnEndY;
296 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY;
297
298 gpVertices[4].x = gpVertices[0].x;
299 gpVertices[4].y = gpVertices[0].y;
300 }
301
302 static
CalcTrapezoidShapeVs()303 void CalcTrapezoidShapeVs()
304 {
305 int h=gnEndY-gnOrigY, dx;
306 double dval;
307
308 dval = ((double)h) * TangentOfAngle();
309 dx = (int)round(dval);
310 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY;
311 gpVertices[1].x = gnOrigX+dx; gpVertices[1].y = gnEndY;
312 gpVertices[2].x = gnEndX-dx; gpVertices[2].y = gnEndY;
313 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY;
314
315 gpVertices[4].x = gpVertices[0].x;
316 gpVertices[4].y = gpVertices[0].y;
317 }
318
319 static
CalcRhombusShapeVs()320 void CalcRhombusShapeVs()
321 {
322 int cx=((gnOrigX+gnEndX)>>1), cy=((gnOrigY+gnEndY)>>1);
323
324 gpVertices[0].x = cx; gpVertices[0].y = gnOrigY;
325 gpVertices[1].x = gnOrigX; gpVertices[1].y = cy;
326 gpVertices[2].x = cx; gpVertices[2].y = gnEndY;
327 gpVertices[3].x = gnEndX; gpVertices[3].y = cy;
328
329 gpVertices[4].x = gpVertices[0].x;
330 gpVertices[4].y = gpVertices[0].y;
331 }
332
333 static
CalcRCBoxShapeVs()334 void CalcRCBoxShapeVs()
335 {
336 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
337
338 if (abs(w) >= (rcbRadius<<1) && abs(h) >= (rcbRadius<<1)) {
339 int dx=(w>0 ? rcbRadius : -rcbRadius), dy=(h>0 ? rcbRadius : -rcbRadius);
340
341 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
342 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY-dy;
343 gpVertices[2].x = gnOrigX; gpVertices[2].y = gnEndY;
344 gpVertices[3].x = gnOrigX+dx; gpVertices[3].y = gnEndY;
345 gpVertices[4].x = gnEndX-dx; gpVertices[4].y = gnEndY;
346 gpVertices[5].x = gnEndX; gpVertices[5].y = gnEndY;
347 gpVertices[6].x = gnEndX; gpVertices[6].y = gnEndY-dy;
348 gpVertices[7].x = gnEndX; gpVertices[7].y = gnOrigY+dy;
349 gpVertices[8].x = gnEndX; gpVertices[8].y = gnOrigY;
350 gpVertices[9].x = gnEndX-dx; gpVertices[9].y = gnOrigY;
351 gpVertices[10].x = gnOrigX+dx; gpVertices[10].y = gnOrigY;
352 gpVertices[11].x = gnOrigX; gpVertices[11].y = gnOrigY;
353
354 gpVertices[12].x = gpVertices[0].x;
355 gpVertices[12].y = gpVertices[0].y;
356 gnNumVs = 13;
357 memset(gpnSmooth, 0, gnNumVs*sizeof(char));
358 gpnSmooth[2] = gpnSmooth[5] = gpnSmooth[8] = gpnSmooth[11] = TRUE;
359 } else {
360 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY;
361 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
362 gpVertices[2].x = gnEndX; gpVertices[2].y = gnEndY;
363 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY;
364
365 gpVertices[4].x = gpVertices[0].x;
366 gpVertices[4].y = gpVertices[0].y;
367 gnNumVs = 5;
368 memset(gpnSmooth, 0, gnNumVs*sizeof(char));
369 }
370 }
371
372 static
CalcOctagonShapeVs()373 void CalcOctagonShapeVs()
374 {
375 CalcRegularPolygonVs(8, FALSE, 0, (double)1.0, 0, 1);
376 }
377
378 static
CalcCrossShapeVs()379 void CalcCrossShapeVs()
380 {
381 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
382 int dx=(int)(w/3), dy=(int)(h/3);
383
384 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
385 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY-dy;
386 gpVertices[2].x = gnOrigX+dx; gpVertices[2].y = gnEndY-dy;
387 gpVertices[3].x = gnOrigX+dx; gpVertices[3].y = gnEndY;
388 gpVertices[4].x = gnEndX-dx; gpVertices[4].y = gnEndY;
389 gpVertices[5].x = gnEndX-dx; gpVertices[5].y = gnEndY-dy;
390 gpVertices[6].x = gnEndX; gpVertices[6].y = gnEndY-dy;
391 gpVertices[7].x = gnEndX; gpVertices[7].y = gnOrigY+dy;
392 gpVertices[8].x = gnEndX-dx; gpVertices[8].y = gnOrigY+dy;
393 gpVertices[9].x = gnEndX-dx; gpVertices[9].y = gnOrigY;
394 gpVertices[10].x = gnOrigX+dx; gpVertices[10].y = gnOrigY;
395 gpVertices[11].x = gnOrigX+dx; gpVertices[11].y = gnOrigY+dy;
396
397 gpVertices[12].x = gpVertices[0].x;
398 gpVertices[12].y = gpVertices[0].y;
399 }
400
401 static
CalcOvalShapeVs()402 void CalcOvalShapeVs()
403 {
404 CalcBBox(gnOrigX, gnOrigY, gnEndX, gnEndY, &(gShapeBBox.ltx),
405 &(gShapeBBox.lty), &(gShapeBBox.rbx), &(gShapeBBox.rby));
406 }
407
408 static
CalcWordsShapeVs()409 void CalcWordsShapeVs()
410 {
411 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
412 int min_h=(rcbRadius<<1)+rcbRadius;
413 int min_w=min_h+(rcbRadius>>1);
414
415 if (abs(w) >= min_w && abs(h) >= min_h) {
416 int dx=(w>0 ? rcbRadius : -rcbRadius), dy=(h>0 ? rcbRadius : -rcbRadius);
417 int dy2=(dy<<1);
418
419 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
420 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY-dy2;
421 gpVertices[2].x = gnOrigX; gpVertices[2].y = gnEndY-dy;
422 gpVertices[3].x = gnOrigX+dx; gpVertices[3].y = gnEndY-dy;
423 gpVertices[4].x = gnOrigX+dx+(dx>>1); gpVertices[4].y = gnEndY-dy;
424 gpVertices[5].x = gnOrigX+dx+(dx>>1); gpVertices[5].y = gnEndY;
425 gpVertices[6].x = gnOrigX+(dx<<1)+(dx>>1); gpVertices[6].y = gnEndY-dy;
426 gpVertices[7].x = gnEndX-dx; gpVertices[7].y = gnEndY-dy;
427 gpVertices[8].x = gnEndX; gpVertices[8].y = gnEndY-dy;
428 gpVertices[9].x = gnEndX; gpVertices[9].y = gnEndY-dy2;
429 gpVertices[10].x = gnEndX; gpVertices[10].y = gnOrigY+dy;
430 gpVertices[11].x = gnEndX; gpVertices[11].y = gnOrigY;
431 gpVertices[12].x = gnEndX-dx; gpVertices[12].y = gnOrigY;
432 gpVertices[13].x = gnOrigX+dx; gpVertices[13].y = gnOrigY;
433 gpVertices[14].x = gnOrigX; gpVertices[14].y = gnOrigY;
434
435 gpVertices[15].x = gpVertices[0].x;
436 gpVertices[15].y = gpVertices[0].y;
437 gnNumVs = 16;
438 memset(gpnSmooth, 0, gnNumVs*sizeof(char));
439 gpnSmooth[2] = gpnSmooth[8] = gpnSmooth[11] = gpnSmooth[14] = TRUE;
440 } else {
441 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY;
442 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
443 gpVertices[2].x = gnEndX; gpVertices[2].y = gnEndY;
444 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY;
445
446 gpVertices[4].x = gpVertices[0].x;
447 gpVertices[4].y = gpVertices[0].y;
448 gnNumVs = 5;
449 memset(gpnSmooth, 0, gnNumVs*sizeof(char));
450 }
451 }
452
453 static
CalcHexagonShapeVs()454 void CalcHexagonShapeVs()
455 {
456 CalcRegularPolygonVs(6, TRUE, 0, (double)1.0, 0, 1);
457 }
458
459 static
CalcTriangleShapeVs()460 void CalcTriangleShapeVs()
461 {
462 gpVertices[0].x = ((gnOrigX+gnEndX)>>1); gpVertices[0].y = gnOrigY;
463 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
464 gpVertices[2].x = gnEndX; gpVertices[2].y = gnEndY;
465
466 gpVertices[3].x = gpVertices[0].x;
467 gpVertices[3].y = gpVertices[0].y;
468 }
469
470 static
CalcBlastShapeVs()471 void CalcBlastShapeVs()
472 {
473 CalcRegularPolygonVs(16, TRUE, 0, (double)1.0, 0, 2);
474 CalcRegularPolygonVs(16, FALSE, 0, (double)0.66, 1, 2);
475 gnNumVs = 33;
476 }
477
478 static
CalcStarShapeVs()479 void CalcStarShapeVs()
480 {
481 int i;
482 IntPoint vs[5];
483
484 CalcRegularPolygonVs(5, FALSE, -90, (double)1.0, 0, 2);
485 CalcRegularPolygonVs(5, FALSE, 90, (double)0.375, 1, 2);
486 for (i=0; i < 5; i++) {
487 memcpy(&vs[i], &gpVertices[((i<<1)+7) % 10], sizeof(IntPoint));
488 }
489 for (i=0; i < 5; i++) {
490 memcpy(&gpVertices[(i<<1)+1], &vs[i], sizeof(IntPoint));
491 }
492 gnNumVs = 11;
493 }
494
495 static
CalcDiskShapeVs()496 void CalcDiskShapeVs()
497 {
498 CalcBBox(gnOrigX, gnOrigY, gnEndX, gnEndY, &(gShapeBBox.ltx),
499 &(gShapeBBox.lty), &(gShapeBBox.rbx), &(gShapeBBox.rby));
500 }
501
502 static
CalcRightArrowShapeVs()503 void CalcRightArrowShapeVs()
504 {
505 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
506 int dx=(w>>1), dy=(h>>2);
507
508 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
509 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY-dy;
510 gpVertices[2].x = gnOrigX+dx; gpVertices[2].y = gnEndY-dy;
511 gpVertices[3].x = gnOrigX+dx; gpVertices[3].y = gnEndY;
512 gpVertices[4].x = gnEndX; gpVertices[4].y = gnOrigY+(h>>1);
513 gpVertices[5].x = gnOrigX+dx; gpVertices[5].y = gnOrigY;
514 gpVertices[6].x = gnOrigX+dx; gpVertices[6].y = gnOrigY+dy;
515
516 gpVertices[7].x = gpVertices[0].x;
517 gpVertices[7].y = gpVertices[0].y;
518 }
519
520 static
CalcUpArrowShapeVs()521 void CalcUpArrowShapeVs()
522 {
523 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
524 int dx=(w>>2), dy=(h>>1);
525
526 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnEndY-dy;
527 gpVertices[1].x = gnOrigX+dx; gpVertices[1].y = gnEndY-dy;
528 gpVertices[2].x = gnOrigX+dx; gpVertices[2].y = gnEndY;
529 gpVertices[3].x = gnEndX-dx; gpVertices[3].y = gnEndY;
530 gpVertices[4].x = gnEndX-dx; gpVertices[4].y = gnEndY-dy;
531 gpVertices[5].x = gnEndX; gpVertices[5].y = gnEndY-dy;
532 gpVertices[6].x = gnOrigX+(w>>1); gpVertices[6].y = gnOrigY;
533
534 gpVertices[7].x = gpVertices[0].x;
535 gpVertices[7].y = gpVertices[0].y;
536 }
537
538 static
CalcFatRightArrowShapeVs()539 void CalcFatRightArrowShapeVs()
540 {
541 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
542 int dx=(w>>1), dy=(h>>3);
543
544 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
545 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY-dy;
546 gpVertices[2].x = gnOrigX+dx; gpVertices[2].y = gnEndY-dy;
547 gpVertices[3].x = gnOrigX+dx; gpVertices[3].y = gnEndY;
548 gpVertices[4].x = gnEndX; gpVertices[4].y = gnOrigY+(h>>1);
549 gpVertices[5].x = gnOrigX+dx; gpVertices[5].y = gnOrigY;
550 gpVertices[6].x = gnOrigX+dx; gpVertices[6].y = gnOrigY+dy;
551
552 gpVertices[7].x = gpVertices[0].x;
553 gpVertices[7].y = gpVertices[0].y;
554 }
555
556 static
CalcFatUpArrowShapeVs()557 void CalcFatUpArrowShapeVs()
558 {
559 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
560 int dx=(w>>3), dy=(h>>1);
561
562 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnEndY-dy;
563 gpVertices[1].x = gnOrigX+dx; gpVertices[1].y = gnEndY-dy;
564 gpVertices[2].x = gnOrigX+dx; gpVertices[2].y = gnEndY;
565 gpVertices[3].x = gnEndX-dx; gpVertices[3].y = gnEndY;
566 gpVertices[4].x = gnEndX-dx; gpVertices[4].y = gnEndY-dy;
567 gpVertices[5].x = gnEndX; gpVertices[5].y = gnEndY-dy;
568 gpVertices[6].x = gnOrigX+(w>>1); gpVertices[6].y = gnOrigY;
569
570 gpVertices[7].x = gpVertices[0].x;
571 gpVertices[7].y = gpVertices[0].y;
572 }
573
574 static
CalcRightTabShapeVs()575 void CalcRightTabShapeVs()
576 {
577 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
578 int dx=(int)(w/3), dy=(h>>1);
579
580 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY;
581 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
582 gpVertices[2].x = gnEndX-dx; gpVertices[2].y = gnEndY;
583 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY+dy;
584 gpVertices[4].x = gnEndX-dx; gpVertices[4].y = gnOrigY;
585
586 gpVertices[5].x = gpVertices[0].x;
587 gpVertices[5].y = gpVertices[0].y;
588 }
589
590 static
CalcUpTabShapeVs()591 void CalcUpTabShapeVs()
592 {
593 int w=gnEndX-gnOrigX, h=gnEndY-gnOrigY;
594 int dx=(w>>1), dy=(int)(h/3);
595
596 gpVertices[0].x = gnOrigX; gpVertices[0].y = gnOrigY+dy;
597 gpVertices[1].x = gnOrigX; gpVertices[1].y = gnEndY;
598 gpVertices[2].x = gnEndX; gpVertices[2].y = gnEndY;
599 gpVertices[3].x = gnEndX; gpVertices[3].y = gnOrigY+dy;
600 gpVertices[4].x = gnOrigX+dx; gpVertices[4].y = gnOrigY;
601
602 gpVertices[5].x = gpVertices[0].x;
603 gpVertices[5].y = gpVertices[0].y;
604 }
605
606 /* ----------------------- HighLight Shape Functions ----------------------- */
607
608 static
CalcCreateShapeVs(end_x,end_y)609 int CalcCreateShapeVs(end_x, end_y)
610 int end_x, end_y;
611 {
612 gnEndX = end_x;
613 gnEndY = end_y;
614 if (gnEndX == gnOrigX || gnEndY == gnOrigY) return FALSE;
615
616 switch (curShape) {
617 case SHAPE_BOX: CalcBoxShapeVs(); break;
618 case SHAPE_PARALLEL: CalcParallelShapeVs(); break;
619 case SHAPE_TRAPEZOID: CalcTrapezoidShapeVs(); break;
620 case SHAPE_RHOMBUS: CalcRhombusShapeVs(); break;
621 case SHAPE_RCBOX: CalcRCBoxShapeVs(); break;
622 case SHAPE_OCTAGON: CalcOctagonShapeVs(); break;
623 case SHAPE_CROSS: CalcCrossShapeVs(); break;
624 case SHAPE_OVAL: CalcOvalShapeVs(); break;
625 case SHAPE_WORDS: CalcWordsShapeVs(); break;
626 case SHAPE_HEXAGON: CalcHexagonShapeVs(); break;
627 case SHAPE_TRIANGLE: CalcTriangleShapeVs(); break;
628 case SHAPE_BLAST: CalcBlastShapeVs(); break;
629 case SHAPE_STAR: CalcStarShapeVs(); break;
630 case SHAPE_DISK: CalcDiskShapeVs(); break;
631 case SHAPE_RIGHTARROW: CalcRightArrowShapeVs(); break;
632 case SHAPE_UPARROW: CalcUpArrowShapeVs(); break;
633 case SHAPE_FATRIGHTARROW: CalcFatRightArrowShapeVs(); break;
634 case SHAPE_FATUPARROW: CalcFatUpArrowShapeVs(); break;
635 case SHAPE_RIGHTTAB: CalcRightTabShapeVs(); break;
636 case SHAPE_UPTAB: CalcUpTabShapeVs(); break;
637 }
638 return TRUE;
639 }
640
641 #define NO_GENERATE 0
642 #define GENERATE 1
643
644 static
HighLightCreateShape(end_x,end_y,generate,pn_need_to_draw)645 void HighLightCreateShape(end_x, end_y, generate, pn_need_to_draw)
646 int end_x, end_y, generate, *pn_need_to_draw;
647 {
648 if (generate) {
649 *pn_need_to_draw = CalcCreateShapeVs(end_x, end_y);
650
651 if (*pn_need_to_draw && gpVertices != NULL) {
652 int saved_draw_orig_x=drawOrigX, saved_draw_orig_y=drawOrigY;
653 int saved_zoomed_in=zoomedIn, saved_zoom_scale=zoomScale;
654
655 if (gpRubberVertices != NULL) free(gpRubberVertices);
656 gnNumSplineVs = 0;
657 drawOrigX = drawOrigY = 0;
658 zoomedIn = FALSE;
659 zoomScale = 0;
660
661 if (gpnSmooth == NULL) {
662 gpRubberVertices = MakePolygonVertex(drawOrigX, drawOrigY,
663 gnNumVs, gpVertices);
664 gnNumSplineVs = gnNumVs;
665 } else {
666 gpRubberVertices = MakeMultiSplinePolygonVertex(LT_SPLINE,
667 &gnNumSplineVs, gpnSmooth, drawOrigX, drawOrigY, gnNumVs,
668 gpVertices);
669 }
670 if (gpRubberVertices == NULL) FailAllocMessage();
671 drawOrigX = saved_draw_orig_x;
672 drawOrigY = saved_draw_orig_y;
673 zoomedIn = saved_zoomed_in;
674 zoomScale = saved_zoom_scale;
675 }
676 }
677 if (*pn_need_to_draw) {
678 int w, h, diam_y, radius_y, side_h;
679
680 switch (curShape) {
681 case SHAPE_OVAL:
682 XDrawArc(mainDisplay, drawWindow, revDefaultGC,
683 gShapeBBox.ltx, gShapeBBox.lty,
684 gShapeBBox.rbx-gShapeBBox.ltx, gShapeBBox.rby-gShapeBBox.lty,
685 0, 360<<6);
686 break;
687 case SHAPE_DISK:
688 w = gShapeBBox.rbx-gShapeBBox.ltx;
689 h = gShapeBBox.rby-gShapeBBox.lty;
690 radius_y = (int)(h/6);
691 diam_y = (radius_y<<1);
692 side_h = h-diam_y;
693 XDrawArc(mainDisplay, drawWindow, revDefaultGC,
694 gShapeBBox.ltx, gShapeBBox.lty, w, diam_y, 0, 360<<6);
695 XDrawArc(mainDisplay, drawWindow, revDefaultGC,
696 gShapeBBox.ltx, gShapeBBox.rby-diam_y, w, diam_y,
697 180<<6, 180<<6);
698 XDrawLine(mainDisplay, drawWindow, revDefaultGC,
699 gShapeBBox.ltx, gShapeBBox.lty+radius_y,
700 gShapeBBox.ltx, gShapeBBox.rby-radius_y);
701 XDrawLine(mainDisplay, drawWindow, revDefaultGC,
702 gShapeBBox.rbx, gShapeBBox.lty+radius_y,
703 gShapeBBox.rbx, gShapeBBox.rby-radius_y);
704 break;
705 default:
706 if (gpVertices != NULL) {
707 XDrawLines(mainDisplay, drawWindow, revDefaultGC,
708 gpRubberVertices, gnNumSplineVs, CoordModeOrigin);
709 }
710 break;
711 }
712 }
713 }
714
715 /* ----------------------- Generate Object Functions ----------------------- */
716
717 static
GenerateInvisibleBox()718 struct AttrRec *GenerateInvisibleBox()
719 {
720 int w, h, saved_text_just=textJust, attr_w, attr_h, attr_ltx, attr_lty;
721 int saved_fill=objFill, saved_trans_pat=transPat;
722 struct BBRec bbox;
723 struct BoxRec *box_ptr;
724 struct AttrRec *attr_ptr, *label_attr=NULL;
725
726 textJust = JUST_C;
727 memcpy(&bbox, &gShapeBBox, sizeof(struct BBRec));
728 w = bbox.rbx-bbox.ltx;
729 h = bbox.rby-bbox.lty;
730
731 switch (curShape) {
732 case SHAPE_WORDS:
733 if (gnEndY >= gnOrigY) {
734 bbox.rby -= rcbRadius;
735 } else {
736 bbox.lty += rcbRadius;
737 }
738 break;
739 case SHAPE_TRIANGLE:
740 if (gnEndY >= gnOrigY) {
741 bbox.lty += (int)(h/3);
742 } else {
743 bbox.rby -= (int)(h/3);
744 }
745 break;
746 case SHAPE_DISK:
747 bbox.lty += (int)(h/3);
748 break;
749 case SHAPE_RIGHTARROW:
750 case SHAPE_FATRIGHTARROW:
751 case SHAPE_RIGHTTAB:
752 if (gnEndX >= gnOrigX) {
753 bbox.rbx -= (w>>2);
754 } else {
755 bbox.ltx += (w>>2);
756 }
757 break;
758 case SHAPE_UPARROW:
759 case SHAPE_FATUPARROW:
760 case SHAPE_UPTAB:
761 if (gnEndY >= gnOrigY) {
762 bbox.lty += (h>>2);
763 } else {
764 bbox.rby -= (h>>2);
765 }
766 break;
767 }
768 if (bbox.rbx-bbox.ltx >= 12) {
769 bbox.ltx += 4;
770 bbox.rbx -= 4;
771 }
772 if (bbox.rby-bbox.lty >= 12) {
773 bbox.lty += 4;
774 bbox.rby -= 4;
775 }
776 CreateBoxObj(bbox.ltx, bbox.lty, bbox.rbx, bbox.rby, FALSE);
777 box_ptr = topObj->detail.b;
778 box_ptr->fill = NONEPAT;
779 box_ptr->pen = NONEPAT;
780 objFill = NONEPAT;
781 transPat = FALSE;
782 AddAttrByNameAndValue(topObj, "", "auto_center_attr");
783 attr_ptr = topObj->fattr;
784 if (attr_ptr != NULL) {
785 attr_ptr->shown = FALSE;
786 UpdAttr(attr_ptr);
787 AdjObjBBox(attr_ptr->obj);
788 attr_w = attr_ptr->obj->obbox.rbx-attr_ptr->obj->obbox.ltx;
789 attr_h = attr_ptr->obj->bbox.rby-attr_ptr->obj->bbox.lty;
790 attr_ltx = ((topObj->obbox.ltx+topObj->obbox.rbx)>>1)-(attr_w>>1);
791 attr_lty = topObj->bbox.lty;
792 MoveObj(attr_ptr->obj, attr_ltx-attr_ptr->obj->obbox.ltx,
793 attr_lty-attr_ptr->obj->obbox.lty);
794 }
795 AddAttrByNameAndValue(topObj, "label=", "");
796 transPat = saved_trans_pat;
797 objFill = saved_fill;
798 label_attr = FindAttrWithName(topObj, "label=", NULL);
799 if (label_attr != NULL) {
800 label_attr->nameshown = FALSE;
801 label_attr->shown = TRUE;
802 UpdAttr(label_attr);
803 AdjObjBBox(label_attr->obj);
804 attr_w = label_attr->obj->obbox.rbx-label_attr->obj->obbox.ltx;
805 attr_h = label_attr->obj->bbox.rby-label_attr->obj->bbox.lty;
806 attr_ltx = ((topObj->obbox.ltx+topObj->obbox.rbx)>>1)-(attr_w>>1);
807 attr_lty = ((topObj->obbox.lty+topObj->obbox.rby)>>1)-(attr_h>>1);
808 MoveObj(label_attr->obj, attr_ltx-label_attr->obj->obbox.ltx,
809 attr_lty-label_attr->obj->obbox.lty);
810 }
811 AdjObjBBox(topObj);
812 textJust = saved_text_just;
813 return label_attr;
814 }
815
816 static
GenerateShadow()817 void GenerateShadow()
818 {
819 struct ObjRec *obj_ptr;
820 struct SelRec *tmp_top_sel=NULL, *tmp_bot_sel=NULL;
821
822 SelAllObj(FALSE, FALSE);
823
824 JustDupSelObj(&tmp_top_sel, &tmp_bot_sel);
825 /*
826 * At this point, the objects pointed by tmp_top_sel and
827 * tmp_bot_sel are dangling.
828 */
829 if (tmp_top_sel != tmp_bot_sel) {
830 CreateGroupObj(tmp_top_sel->obj, tmp_bot_sel->obj);
831 } else {
832 obj_ptr = tmp_top_sel->obj;
833 obj_ptr->next = topObj;
834 obj_ptr->prev = NULL;
835 if (topObj == NULL) {
836 botObj = obj_ptr;
837 } else {
838 topObj->prev = obj_ptr;
839 }
840 topObj = obj_ptr;
841 }
842 RemoveAllSel();
843 UpdSelBBox();
844
845 /* move the new object to the bottom */
846 obj_ptr = topObj;
847 UnlinkObj(topObj);
848 obj_ptr->next = NULL;
849 obj_ptr->prev = botObj;
850 if (botObj == NULL) {
851 topObj = obj_ptr;
852 } else {
853 botObj->next = obj_ptr;
854 }
855 botObj = obj_ptr;
856
857 ChangeObjTransPat(obj_ptr, NO_TRANSPAT_MODE);
858 ChangeObjFill(obj_ptr, SOLIDPAT);
859 ChangeObjPen(obj_ptr, SOLIDPAT);
860 MoveObj(obj_ptr, shapeShadowDx, shapeShadowDy);
861 }
862
863 static
GenerateShape()864 struct AttrRec *GenerateShape()
865 {
866 struct ObjRec *saved_top_obj, *saved_bot_obj, *tmp_top_obj, *tmp_bot_obj;
867 int w, h, diam_y, radius_y, side_h, saved_cur_spline, saved_line_style;
868 struct AttrRec *label_attr=NULL;
869 struct BBRec bbox;
870
871 saved_top_obj = topObj;
872 saved_bot_obj = botObj;
873 curPage->top = curPage->bot = topObj = botObj = NULL;
874
875 switch (curShape) {
876 case SHAPE_OVAL:
877 CreateOvalObj(&gShapeBBox, FALSE);
878 break;
879 case SHAPE_DISK:
880 saved_cur_spline = curSpline;
881 saved_line_style = lineStyle;
882
883 curSpline = LT_STRAIGHT;
884 lineStyle = LS_PLAIN;
885 w = gShapeBBox.rbx-gShapeBBox.ltx;
886 h = gShapeBBox.rby-gShapeBBox.lty;
887 radius_y = (int)(h/6);
888 diam_y = (radius_y<<1);
889 side_h = h-diam_y;
890 if (penPat != NONEPAT) {
891 int saved_pen=penPat;
892
893 penPat = NONEPAT;
894 CreateBoxObj(gShapeBBox.ltx, gShapeBBox.lty+radius_y,
895 gShapeBBox.rbx, gShapeBBox.rby-radius_y, FALSE);
896 penPat = saved_pen;
897 }
898 bbox.ltx = gShapeBBox.ltx;
899 bbox.lty = gShapeBBox.lty;
900 bbox.rbx = bbox.ltx+w;
901 bbox.rby = bbox.lty+diam_y;
902 CreateOvalObj(&bbox, FALSE);
903 CreateArcObj(gShapeBBox.ltx+(w>>1), gShapeBBox.rby-radius_y,
904 gShapeBBox.ltx, gShapeBBox.rby-radius_y,
905 gShapeBBox.ltx+w, gShapeBBox.rby-radius_y, ARC_CCW,
906 gShapeBBox.ltx, gShapeBBox.rby-diam_y, w, diam_y, 180<<6, 180<<6,
907 FALSE);
908 ResetCreatePoly();
909 AddPtToCreatePoly(gShapeBBox.ltx, gShapeBBox.lty+radius_y);
910 AddPtToCreatePoly(gShapeBBox.ltx, gShapeBBox.rby-radius_y);
911 CreatePolyObj(2, FALSE);
912 ResetCreatePoly();
913 AddPtToCreatePoly(gShapeBBox.rbx, gShapeBBox.lty+radius_y);
914 AddPtToCreatePoly(gShapeBBox.rbx, gShapeBBox.rby-radius_y);
915 CreatePolyObj(2, FALSE);
916
917 curSpline = saved_cur_spline;
918 lineStyle = saved_line_style;
919 break;
920 default:
921 CalcBBox(gnOrigX, gnOrigY, gnEndX, gnEndY, &(gShapeBBox.ltx),
922 &(gShapeBBox.lty), &(gShapeBBox.rbx), &(gShapeBBox.rby));
923 if (gpVertices != NULL) {
924 int i;
925
926 saved_cur_spline = curSpline;
927 curSpline = LT_STRAIGHT;
928 ResetCreatePolygon();
929 for (i=0; i < gnNumVs; i++) {
930 AddPtToCreatePolygon(gpVertices[i].x, gpVertices[i].y);
931 }
932 CreatePolygonObj(gnNumVs, FALSE);
933 if (gpnSmooth != NULL) {
934 struct PolygonRec *polygon_ptr=topObj->detail.g;
935
936 if (polygon_ptr->smooth == NULL) {
937 polygon_ptr->smooth = (char*)malloc((gnNumVs+1)*sizeof(char));
938 if (polygon_ptr->smooth == NULL) FailAllocMessage();
939 memset(polygon_ptr->smooth, 0, (gnNumVs+1)*sizeof(char));
940 }
941 for (i=0; i < gnNumVs; i++) {
942 polygon_ptr->smooth[i] = gpnSmooth[i];
943 }
944 AdjObjSplineVs(topObj);
945 UpdPolyBBox(topObj, polygon_ptr->n, polygon_ptr->vlist);
946 AdjObjBBox(topObj);
947 }
948 curSpline = saved_cur_spline;
949 }
950 break;
951 }
952 if (shapeShadowDx != 0 || shapeShadowDy != 0) {
953 GenerateShadow();
954 }
955 label_attr = GenerateInvisibleBox();
956
957 /*
958 * Use the next two functions to set selLtX, etc. to be used
959 * in CreateGroupObj().
960 */
961 SelAllObj(FALSE, FALSE);
962 RemoveAllSel();
963
964 tmp_top_obj = topObj;
965 tmp_bot_obj = botObj;
966 curPage->top = topObj = saved_top_obj;
967 curPage->bot = botObj = saved_bot_obj;
968 CreateGroupObj(tmp_top_obj, tmp_bot_obj);
969 return label_attr;
970 }
971
972 /* ----------------------- Event Loop ----------------------- */
973
974 #define START_SHOW 0
975 #define MOTION_SHOW 1
976 #define END_SHOW 2
977
978 static
DoCursor(x,y,w,h,which)979 void DoCursor(x, y, w, h, which)
980 int x, y, w, h, which;
981 {
982 char w_buf[80], h_buf[80], x_buf[80], y_buf[80];
983
984 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(w)));
985 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(h)));
986 PixelToMeasurementUnit(x_buf, ABS_X(x));
987 PixelToMeasurementUnit(y_buf, ABS_Y(y));
988 sprintf(gszMsgBox, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
989 switch (which) {
990 case START_SHOW: StartShowMeasureCursor(x, y, gszMsgBox, TRUE); break;
991 case MOTION_SHOW: ShowMeasureCursor(x, y, gszMsgBox, TRUE); break;
992 case END_SHOW: EndShowMeasureCursor(x, y, gszMsgBox, TRUE); break;
993 }
994 }
995
996 static
ContinueCreateShape(orig_x,orig_y)997 void ContinueCreateShape(orig_x, orig_y)
998 int orig_x, orig_y;
999 {
1000 int done=FALSE, something_created=FALSE, grid_x=orig_x, grid_y=orig_y;
1001 int need_to_draw=FALSE;
1002 struct AttrRec *label_attr=NULL;
1003
1004 BeginIntervalRulers(orig_x, orig_y, orig_x, orig_y);
1005 DoCursor(orig_x, orig_y, 0, 0, START_SHOW);
1006
1007 if (!debugNoPointerGrab) {
1008 XGrabPointer(mainDisplay, drawWindow, False,
1009 PointerMotionMask | ButtonReleaseMask | ButtonReleaseMask,
1010 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1011 }
1012 if (!StartCreateShape(orig_x, orig_y)) {
1013 Msg(TgLoadString(STID_CREATE_A_SHAPE_FAILED));
1014 return;
1015 }
1016 HighLightCreateShape(grid_x, grid_y, GENERATE, &need_to_draw);
1017 while (!done) {
1018 XEvent input, ev;
1019
1020 XNextEvent(mainDisplay, &input);
1021 switch (input.type) {
1022 case Expose: ExposeEventHandler(&input, TRUE); break;
1023 case VisibilityNotify: ExposeEventHandler(&input, TRUE); break;
1024 case MotionNotify:
1025 HighLightCreateShape(grid_x, grid_y, NO_GENERATE, &need_to_draw);
1026 DoCursor(grid_x, grid_y, grid_x-orig_x, grid_y-orig_y, MOTION_SHOW);
1027 GridXY(input.xmotion.x, input.xmotion.y, &grid_x, &grid_y);
1028 if (input.xmotion.state & (ShiftMask | ControlMask)) {
1029 int w=grid_x-orig_x, h=grid_y-orig_y, pos_w=TRUE, pos_h=TRUE;
1030
1031 if (w < 0) {
1032 w = (-w);
1033 pos_w = FALSE;
1034 }
1035 if (h < 0) {
1036 h = (-h);
1037 pos_h = FALSE;
1038 }
1039 if (w > h) {
1040 grid_x = (pos_w ? orig_x+h : orig_x-h);
1041 } else {
1042 grid_y = (pos_h ? orig_y+w : orig_y-w);
1043 }
1044 }
1045 DoCursor(grid_x, grid_y, grid_x-orig_x, grid_y-orig_y, MOTION_SHOW);
1046 HighLightCreateShape(grid_x, grid_y, GENERATE, &need_to_draw);
1047 DrawIntervalRulers(orig_x, orig_y, grid_x, grid_y, NULL);
1048 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1049 break;
1050 case KeyPress:
1051 if (KeyPressEventIsEscape(&input.xkey)) {
1052 done = TRUE;
1053 }
1054 break;
1055 case ButtonRelease:
1056 if (grid_x != orig_x && grid_y != orig_y) {
1057 something_created = TRUE;
1058 }
1059 done = TRUE;
1060 break;
1061 }
1062 }
1063 XUngrabPointer(mainDisplay, CurrentTime);
1064 XSync(mainDisplay, False);
1065 done = TRUE;
1066 DoCursor(grid_x, grid_y, grid_x-orig_x, grid_y-orig_y, END_SHOW);
1067 HighLightCreateShape(grid_x, grid_y, NO_GENERATE, &need_to_draw);
1068 EndIntervalRulers(grid_x, grid_y);
1069
1070 if (something_created) {
1071 label_attr = GenerateShape();
1072 numRedrawBBox = 0;
1073 topObj->tmp_parent = NULL;
1074 DrawObj(drawWindow, topObj);
1075 RecordNewObjCmd();
1076 SetFileModified(TRUE);
1077 justDupped = FALSE;
1078 }
1079 EndCreateShape();
1080 if (something_created && label_attr != NULL) {
1081 EditTextInAttr(label_attr);
1082 }
1083 }
1084
1085 static
DoCreateShape()1086 void DoCreateShape()
1087 {
1088 unsigned int button;
1089 int mouse_x=0, mouse_y=0;
1090
1091 Msg(TgLoadCachedString(CSTID_DRAG_MOUSE_CREATE_SHAPE_DOTS));
1092 SetMouseStatus(GetShapeDesc(curShape), TgLoadCachedString(CSTID_CANCEL),
1093 TgLoadCachedString(CSTID_CANCEL));
1094 button = DrawWindowLoop(&mouse_x, &mouse_y, cornerCursor, TRUE);
1095 if (button == Button1) {
1096 int grid_x=0, grid_y=0;
1097
1098 GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
1099 ContinueCreateShape(grid_x, grid_y);
1100 } else {
1101 Msg(TgLoadCachedString(CSTID_CREATE_A_SHAPE_ABORTED));
1102 }
1103 }
1104
1105 static
CreateShape()1106 void CreateShape()
1107 {
1108 int force_no_shadow=FALSE, saved_dx=shapeShadowDx, saved_dy=shapeShadowDy;
1109
1110 MakeQuiescent();
1111
1112 if ((objFill == NONEPAT || (objFill == BACKPAT && transPat)) &&
1113 (shapeShadowDx != 0 || shapeShadowDy != 0)) {
1114 sprintf(gszMsgBox, TgLoadString(objFill==NONEPAT ?
1115 STID_CREATE_SHADOW_SHAPE_NO_FILL :
1116 STID_CREATE_SHADOW_SHAPE_TRAN_FILL));
1117 switch (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)) {
1118 case MB_ID_YES: force_no_shadow = TRUE; break;
1119 case MB_ID_NO: break;
1120 default: return;
1121 }
1122 }
1123 if (force_no_shadow) {
1124 shapeShadowDx = shapeShadowDy = 0;
1125 }
1126 SaveStatusStrings();
1127 DoCreateShape();
1128 RestoreStatusStrings();
1129 if (force_no_shadow) {
1130 shapeShadowDx = saved_dx;
1131 shapeShadowDy = saved_dy;
1132 }
1133 }
1134
1135 /* ----------------------- Init and Clean Up ----------------------- */
1136
CleanUpShape()1137 void CleanUpShape()
1138 {
1139 CleanUpShapeDescMouseStatusStrings();
1140 }
1141
InitShape()1142 void InitShape()
1143 {
1144 char *c_ptr;
1145
1146 shapeShadowInResource = FALSE;
1147 shapeShadowDx = shapeShadowDy = 0;
1148 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ShapeShadowSpec")) != NULL) {
1149 if (ParseXYSpec(c_ptr, &shapeShadowDx, &shapeShadowDy)) {
1150 shapeShadowInResource = TRUE;
1151 }
1152 }
1153 }
1154
1155 /* ----------------------- Menu Functions ----------------------- */
1156
ShapeSubMenu(nIndex)1157 void ShapeSubMenu(nIndex)
1158 int nIndex;
1159 {
1160 if (nIndex < 0 || nIndex >= MAXSHAPES) return;
1161 curShape = nIndex;
1162 CreateShape();
1163 curShape = (-1);
1164 }
1165
RefreshShapeMenu(menu)1166 void RefreshShapeMenu(menu)
1167 TgMenu *menu;
1168 {
1169 }
1170
CreateShapeMenu(parent_menu,x,y,menu_info,status_str_xlated)1171 TgMenu *CreateShapeMenu(parent_menu, x, y, menu_info, status_str_xlated)
1172 TgMenu *parent_menu;
1173 int x, y;
1174 TgMenuInfo *menu_info;
1175 int status_str_xlated; /* ignored, always 0 */
1176 {
1177 int i=0;
1178 TgMenu *menu=NULL;
1179 TgMenuInfo stMenuInfo;
1180 TgMenuItemInfo *item_info=NULL;
1181
1182 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
1183 stMenuInfo.items = (TgMenuItemInfo*)malloc(
1184 (MAXSHAPES+1)*sizeof(TgMenuItemInfo));
1185 if (stMenuInfo.items == NULL) FailAllocMessage();
1186 memset(stMenuInfo.items, 0, (MAXSHAPES+1)*sizeof(TgMenuItemInfo));
1187 for (item_info=stMenuInfo.items, i=0; i < MAXSHAPES; item_info++, i++) {
1188 item_info->menu_str = (char*)(Pixmap*)(&shapePixmap[i]);
1189 item_info->shortcut_str = NULL;
1190 sprintf(gszMsgBox, "%s", GetShapeDesc(i));
1191 item_info->status_str = UtilStrDup(gszMsgBox);
1192 if (item_info->status_str == NULL) FailAllocMessage();
1193 item_info->submenu_info = NULL;
1194 item_info->cmdid = CMDID_CREATESHAPE;
1195 }
1196 stMenuInfo.items[MAXSHAPES].cmdid = INVALID;
1197
1198 /* the status_str has been translated in GetShapeDesc() */
1199 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
1200 for (item_info=stMenuInfo.items, i=0; i < MAXSHAPES; item_info++, i++) {
1201 UtilFree(item_info->status_str);
1202 }
1203 memset(stMenuInfo.items, 0, (MAXSHAPES+1)*sizeof(TgMenuItemInfo));
1204 free(stMenuInfo.items);
1205 stMenuInfo.items = NULL;
1206 if (menu != NULL) {
1207 menu->track_menubar = TRUE;
1208 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, 8);
1209 }
1210 return menu;
1211 }
1212
ShapeMenu(X,Y,TrackMenubar)1213 int ShapeMenu(X, Y, TrackMenubar)
1214 int X, Y, TrackMenubar;
1215 {
1216 int rc=INVALID;
1217 TgMenu *menu=(shapeMenuInfo. create_proc)(NULL, X, Y, &shapeMenuInfo,
1218 INVALID);
1219
1220 activeMenu = MENU_SHAPE;
1221 if (menu != NULL) {
1222 menu->track_menubar = TrackMenubar;
1223
1224 rc = TgMenuLoop(menu);
1225 TgDestroyMenu(menu, TRUE);
1226 }
1227 return rc;
1228 }
1229
1230 /* ----------------------- Public Functions ----------------------- */
1231
SetShapeShadow()1232 void SetShapeShadow()
1233 {
1234 char spec[MAXSTRING+1];
1235
1236 *spec = '\0';
1237 sprintf(gszMsgBox, TgLoadString(STID_ENTER_XY_OFFSET_FOR_SHP_SHDW),
1238 shapeShadowDx, shapeShadowDy);
1239 Dialog(gszMsgBox, NULL, spec);
1240 if (ParseXYSpec(spec, &shapeShadowDx, &shapeShadowDy)) {
1241 sprintf(gszMsgBox, TgLoadString(STID_SHAPE_SHDW_XY_OFFSETS_SET_TO),
1242 shapeShadowDx, shapeShadowDy);
1243 Msg(gszMsgBox);
1244 }
1245 }
1246
1247