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/box.c,v 1.13 2011/06/09 16:11:41 cvsps Exp $
19 */
20
21 #define _INCLUDE_FROM_BOX_C_
22
23 #include "tgifdefs.h"
24
25 #include "attr.e"
26 #include "auxtext.e"
27 #include "box.e"
28 #include "choice.e"
29 #include "cmd.e"
30 #include "color.e"
31 #include "cursor.e"
32 #include "cutpaste.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "dup.e"
36 #include "file.e"
37 #include "grid.e"
38 #include "mainloop.e"
39 #include "mark.e"
40 #include "msg.e"
41 #include "obj.e"
42 #include "pattern.e"
43 #include "poly.e"
44 #include "ps.e"
45 #include "raster.e"
46 #include "rect.e"
47 #include "ruler.e"
48 #include "select.e"
49 #include "setup.e"
50 #include "strtbl.e"
51 #include "util.e"
52 #include "xpixmap.e"
53
54 int boxDrawn=FALSE;
55
56 static XPoint bv[5];
57
MyBox(window,gc,x1,y1,x2,y2)58 void MyBox(window, gc, x1, y1, x2, y2)
59 /* Hollow box, solid outline with width=1 */
60 Window window;
61 GC gc;
62 int x1, y1, x2, y2;
63 {
64 bv[0].x = (short)x1; bv[0].y = (short)y1;
65 bv[1].x = (short)x1; bv[1].y = (short)y2;
66 bv[2].x = (short)x2; bv[2].y = (short)y2;
67 bv[3].x = (short)x2; bv[3].y = (short)y1;
68 bv[4].x = (short)x1; bv[4].y = (short)y1;
69 XDrawLines(mainDisplay, window, gc, bv, 5, CoordModeOrigin);
70 }
71
72 static
DumpBoxPath(FP,ObjPtr,LtX,LtY,RbX,RbY,Width,Pen,Dash,TransPat)73 void DumpBoxPath(FP, ObjPtr, LtX, LtY, RbX, RbY, Width, Pen, Dash, TransPat)
74 FILE *FP;
75 struct ObjRec *ObjPtr;
76 int LtX, LtY, RbX, RbY, Width, Pen, Dash, TransPat;
77 {
78 register int i;
79 int w_is_int=TRUE;
80 char *width_spec=ObjPtr->detail.b->width_spec;
81 double dw=GetWidthInDouble(Width, width_spec, &w_is_int);
82
83 fprintf(FP, " %s\n", gPsCmd[PS_GSAVE]);
84 if (!colorDump && useGray && Pen > BACKPAT) {
85 GrayCheck(Pen);
86 fprintf(FP, " %s %s\n", GrayStr(Pen), gPsCmd[PS_SETGRAY]);
87 }
88 DumpRectPath(FP, LtX, LtY, RbX, RbY, 6, TRUE);
89
90 if (ObjPtr->ctm != NULL) {
91 fprintf(FP, " %s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]);
92 }
93 if (w_is_int) {
94 if (Width != 1) {
95 fprintf(FP, " %1d %s\n", Width, gPsCmd[PS_SETLINEWIDTH]);
96 }
97 } else {
98 fprintf(FP, " %.3f %s\n", dw, gPsCmd[PS_SETLINEWIDTH]);
99 }
100 if (Dash != 0) {
101 fprintf(FP, " [");
102 for (i = 0; i < dashListLength[Dash]-1; i++) {
103 fprintf(FP, "%1d ", (int)(dashList[Dash][i]));
104 }
105 fprintf(FP, "%1d] 0 %s\n",
106 (int)(dashList[Dash][dashListLength[Dash]-1]), gPsCmd[PS_SETDASH]);
107 }
108
109 switch (Pen) {
110 case SOLIDPAT: fprintf(FP, " %s\n", gPsCmd[PS_STROKE]); break;
111 case BACKPAT:
112 if (!TransPat) {
113 fprintf(FP, " 1 %s %s 0 %s\n",
114 gPsCmd[PS_SETGRAY], gPsCmd[PS_STROKE], gPsCmd[PS_SETGRAY]);
115 }
116 break;
117 default:
118 if (colorDump || !useGray) {
119 if (preDumpSetup) PSUseColorPattern();
120 fprintf(FP, " %s\n", gPsCmd[PS_FLATTENPATH]);
121 DumpPatFill(FP, Pen, ObjPtr->bbox, 6, TRUE);
122 } else {
123 fprintf(FP, " %s\n", gPsCmd[PS_STROKE]);
124 }
125 break;
126 }
127 fprintf(FP, " %s\n", gPsCmd[PS_GRESTORE]);
128 }
129
DumpBoxObj(FP,ObjPtr)130 void DumpBoxObj(FP, ObjPtr)
131 FILE *FP;
132 struct ObjRec *ObjPtr;
133 {
134 int ltx, lty, rbx, rby, fill, width, pen, dash, color_index, trans_pat;
135
136 if (ObjPtr->ctm == NULL) {
137 ltx = ObjPtr->obbox.ltx;
138 lty = ObjPtr->obbox.lty;
139 rbx = ObjPtr->obbox.rbx;
140 rby = ObjPtr->obbox.rby;
141 } else {
142 ltx = ObjPtr->orig_obbox.ltx;
143 lty = ObjPtr->orig_obbox.lty;
144 rbx = ObjPtr->orig_obbox.rbx;
145 rby = ObjPtr->orig_obbox.rby;
146 }
147 trans_pat = ObjPtr->trans_pat;
148 fill = ObjPtr->detail.b->fill;
149 pen = ObjPtr->detail.b->pen;
150 width = ObjPtr->detail.b->width;
151 dash = ObjPtr->detail.b->dash;
152
153 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
154 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
155 return;
156 }
157 fprintf(FP, "%% BOX\n");
158 if (ObjPtr->ctm != NULL) {
159 float m[6];
160
161 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
162 m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
163 m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
164 m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
165 m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
166 fprintf(FP, " %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
167 gPsCmd[PS_TRANSLATE]);
168 fprintf(FP, " [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
169 m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
170 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
171 fprintf(FP, " %1d %s %1d %s %s\n",
172 ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG],
173 gPsCmd[PS_TRANSLATE]);
174 }
175 color_index = ObjPtr->color;
176 DumpRGBColorLine(FP, color_index, 0, TRUE);
177
178 switch (fill) {
179 case NONEPAT: break;
180 case SOLIDPAT:
181 /* solid black object */
182 DumpRectPath(FP, ltx, lty, rbx, rby, 0, FALSE);
183 fprintf(FP, "%s\n", gPsCmd[PS_FILL]);
184 break;
185 case BACKPAT:
186 if (!trans_pat) {
187 /* solid white object */
188 DumpRectPath(FP, ltx, lty, rbx, rby, 0, FALSE);
189 fprintf(FP, "1 %s %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
190 DumpRGBColorLine(FP, color_index, 3, TRUE);
191 }
192 break;
193 default:
194 /* patterned */
195 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
196 if (colorDump || !useGray) {
197 if (preDumpSetup) PSUseColorPattern();
198 if (!trans_pat) {
199 DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
200 fprintf(FP, "1 %s %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
201 DumpRGBColorLine(FP, color_index, 3, TRUE);
202 }
203 DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
204 fprintf(FP, "%s %s\n", gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
205 DumpPatFill(FP, fill, ObjPtr->bbox, 3, TRUE);
206 } else {
207 GrayCheck(fill);
208 fprintf(FP, " %s %s\n", GrayStr(fill), gPsCmd[PS_SETGRAY]);
209 DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
210 fprintf(FP, "%s\n", gPsCmd[PS_FILL]);
211 }
212 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
213 break;
214 }
215
216 if (pen == NONEPAT) {
217 if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
218 fprintf(FP, "\n");
219 return;
220 }
221
222 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
223 fprintf(FP, " 10 %s\n", gPsCmd[PS_SETMITERLIMIT]);
224
225 if ((colorDump || !useGray) && pen > BACKPAT) {
226 DumpBoxPath(FP, ObjPtr, ltx, lty, rbx, rby, width, BACKPAT, 0, trans_pat);
227 DumpRGBColorLine(FP, color_index, 3, TRUE);
228 }
229 DumpBoxPath(FP, ObjPtr, ltx, lty, rbx, rby, width, pen, dash, trans_pat);
230
231 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
232 if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
233 fprintf(FP, "\n");
234 }
235
DrawBoxObj(win,XOff,YOff,ObjPtr)236 void DrawBoxObj(win, XOff, YOff, ObjPtr)
237 Window win;
238 int XOff, YOff;
239 struct ObjRec *ObjPtr;
240 {
241 struct BoxRec *box_ptr=ObjPtr->detail.b;
242 int fill, pen, pixel, ltx, lty, rbx, rby, width, dash, trans_pat;
243 int real_x_off, real_y_off;
244 XGCValues values;
245
246 trans_pat = ObjPtr->trans_pat;
247 pen = box_ptr->pen;
248 fill = box_ptr->fill;
249 width = box_ptr->width;
250 dash = box_ptr->dash;
251 pixel = colorPixels[ObjPtr->color];
252
253 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
254 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
255 return;
256 }
257 real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
258 real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
259 ltx = ZOOMED_SIZE(ObjPtr->obbox.ltx - real_x_off);
260 lty = ZOOMED_SIZE(ObjPtr->obbox.lty - real_y_off);
261 rbx = ZOOMED_SIZE(ObjPtr->obbox.rbx - real_x_off);
262 rby = ZOOMED_SIZE(ObjPtr->obbox.rby - real_y_off);
263
264 if (fill != NONEPAT) {
265 values.foreground = GetDrawingBgPixel(fill, pixel);
266 values.function = GXcopy;
267 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
268 values.stipple = patPixmap[fill];
269 XChangeGC(mainDisplay, drawGC,
270 GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
271 if (ObjPtr->ctm != NULL) {
272 XFillPolygon(mainDisplay, win, drawGC, ObjPtr->rotated_obbox, 5,
273 Convex, CoordModeOrigin);
274 } else {
275 XFillRectangle(mainDisplay, win, drawGC, ltx, lty, rbx-ltx, rby-lty);
276 }
277 }
278
279 if (pen != NONEPAT) {
280 values.foreground = GetDrawingBgPixel(pen, pixel);
281 values.function = GXcopy;
282 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
283 values.stipple = patPixmap[pen];
284 values.line_width = ZOOMED_SIZE(width);
285 #ifdef NO_THIN_LINE
286 if (values.line_width < 1) values.line_width = 1;
287 #endif
288 values.join_style = JoinMiter;
289 if (dash != 0) {
290 XSetDashes(mainDisplay, drawGC, 0, dashList[dash],
291 dashListLength[dash]);
292 values.line_style = LineOnOffDash;
293 } else {
294 values.line_style = LineSolid;
295 }
296 XChangeGC(mainDisplay, drawGC,
297 GCForeground | GCFunction | GCFillStyle | GCStipple | GCLineWidth |
298 GCLineStyle | GCJoinStyle, &values);
299 if (ObjPtr->ctm != NULL) {
300 XDrawLines(mainDisplay, win, drawGC, ObjPtr->rotated_obbox, 5,
301 CoordModeOrigin);
302 } else {
303 XDrawRectangle(mainDisplay, win, drawGC, ltx, lty, rbx-ltx, rby-lty);
304 }
305 }
306 }
307
CreateBoxObj(X1,Y1,X2,Y2,CreateAbsolute)308 int CreateBoxObj(X1, Y1, X2, Y2, CreateAbsolute)
309 int X1, Y1, X2, Y2, CreateAbsolute;
310 {
311 struct BoxRec *box_ptr;
312 struct ObjRec *obj_ptr;
313 int width=0, w, ltx, lty, rbx, rby;
314
315 if (X1 == X2 && Y1 == Y2) return FALSE;
316 box_ptr = (struct BoxRec *)malloc(sizeof(struct BoxRec));
317 if (box_ptr == NULL) FailAllocMessage();
318 memset(box_ptr, 0, sizeof(struct BoxRec));
319 if (mainDisplay != NULL) {
320 box_ptr->fill = objFill;
321 box_ptr->width = width = curWidthOfLine[lineWidth];
322 UtilStrCpyN(box_ptr->width_spec, sizeof(box_ptr->width_spec),
323 curWidthOfLineSpec[lineWidth]);
324 box_ptr->pen = penPat;
325 box_ptr->dash = curDash;
326 }
327 obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
328 if (obj_ptr == NULL) FailAllocMessage();
329 memset(obj_ptr, 0, sizeof(struct ObjRec));
330
331 if (X1 < X2) {
332 if (Y1 < Y2) {
333 ltx = X1; lty = Y1; rbx = X2; rby = Y2;
334 } else {
335 ltx = X1; lty = Y2; rbx = X2; rby = Y1;
336 }
337 } else {
338 if (Y1 < Y2) {
339 ltx = X2; lty = Y1; rbx = X1; rby = Y2;
340 } else {
341 ltx = X2; lty = Y2; rbx = X1; rby = Y1;
342 }
343 }
344 if (CreateAbsolute) {
345 obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ltx;
346 obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = lty;
347 obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = rbx;
348 obj_ptr->bbox.rby = obj_ptr->obbox.rby = rby;
349 } else {
350 obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ABS_X(ltx);
351 obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = ABS_Y(lty);
352 obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = ABS_X(rbx);
353 obj_ptr->bbox.rby = obj_ptr->obbox.rby = ABS_Y(rby);
354 }
355 w = HALF_W(width);
356 obj_ptr->bbox.ltx -= w;
357 obj_ptr->bbox.lty -= w;
358 obj_ptr->bbox.rbx += w;
359 obj_ptr->bbox.rby += w;
360 obj_ptr->type = OBJ_BOX;
361 obj_ptr->color = colorIndex;
362 if (mainDisplay != NULL) {
363 UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
364 colorMenuItems[colorIndex]);
365 }
366 obj_ptr->id = objId++;
367 obj_ptr->dirty = FALSE;
368 obj_ptr->rotation = 0;
369 obj_ptr->locked = FALSE;
370 obj_ptr->detail.b = box_ptr;
371 obj_ptr->fattr = obj_ptr->lattr = NULL;
372 obj_ptr->ctm = NULL;
373 obj_ptr->invisible = FALSE;
374 obj_ptr->trans_pat = transPat;
375
376 AddObj(NULL, topObj, obj_ptr);
377
378 return TRUE;
379 }
380
381 static
ContinueBox(OrigX,OrigY)382 void ContinueBox(OrigX, OrigY)
383 int OrigX, OrigY;
384 {
385 int end_x, end_y, grid_x, grid_y, saved_x, saved_y;
386 int done=FALSE, abort=FALSE;
387 char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80];
388 XEvent input, ev;
389 XMotionEvent *motion_ev;
390
391 SetXorDrawGC(xorColorPixels[colorIndex]);
392
393 saved_x = grid_x = OrigX;
394 saved_y = grid_y = OrigY;
395 PixelToMeasurementUnit(w_buf, 0);
396 PixelToMeasurementUnit(h_buf, 0);
397 PixelToMeasurementUnit(x_buf, ABS_X(grid_x));
398 PixelToMeasurementUnit(y_buf, ABS_Y(grid_y));
399 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
400 StartShowMeasureCursor(grid_x, grid_y, buf, TRUE);
401 BeginIntervalRulers(grid_x, grid_y, grid_x, grid_y);
402 if (!debugNoPointerGrab) {
403 XGrabPointer(mainDisplay, drawWindow, FALSE,
404 PointerMotionMask | ButtonReleaseMask,
405 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
406 }
407 while (!done) {
408 XNextEvent(mainDisplay, &input);
409
410 if (input.type == Expose || input.type == VisibilityNotify) {
411 ExposeEventHandler(&input, TRUE);
412 SetXorDrawGC(xorColorPixels[colorIndex]);
413 } else if (input.type == ButtonRelease) {
414 XUngrabPointer(mainDisplay, CurrentTime);
415 MyBox(drawWindow, drawGC, OrigX, OrigY, saved_x, saved_y);
416 EndIntervalRulers(grid_x, grid_y);
417 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
418 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
419 PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
420 PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
421 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
422 EndShowMeasureCursor(saved_x, saved_y, buf, TRUE);
423 done = TRUE;
424 } else if (input.type == MotionNotify) {
425 motion_ev = &(input.xmotion);
426 end_x = motion_ev->x;
427 end_y = motion_ev->y;
428 GridXY(end_x, end_y, &grid_x, &grid_y);
429 if (motion_ev->state & (ShiftMask | ControlMask)) {
430 int w, h, pos_w=TRUE, pos_h=TRUE;
431
432 w = grid_x - OrigX;
433 h = grid_y - OrigY;
434 if (w < 0) {
435 w = (-w);
436 pos_w = FALSE;
437 }
438 if (h < 0) {
439 h = (-h);
440 pos_h = FALSE;
441 }
442 if (w > h) {
443 grid_x = (pos_w ? (OrigX+h) : (OrigX-h));
444 } else {
445 grid_y = (pos_h ? (OrigY+w) : (OrigY-w));
446 }
447 }
448 if (grid_x != saved_x || grid_y != saved_y) {
449 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
450 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
451 PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
452 PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
453 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
454 ShowMeasureCursor(saved_x, saved_y, buf, TRUE);
455 MyBox(drawWindow, drawGC, OrigX, OrigY, saved_x, saved_y);
456 saved_x = grid_x;
457 saved_y = grid_y;
458 MyBox(drawWindow, drawGC, OrigX, OrigY, saved_x, saved_y);
459 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
460 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
461 PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
462 PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
463 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
464 ShowMeasureCursor(saved_x, saved_y, buf, TRUE);
465 }
466 DrawIntervalRulers(OrigX, OrigY, grid_x, grid_y, NULL);
467 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
468 } else if (input.type == KeyPress) {
469 if (KeyPressEventIsEscape(&input.xkey)) {
470 XUngrabPointer(mainDisplay, CurrentTime);
471 MyBox(drawWindow, drawGC, OrigX, OrigY, saved_x, saved_y);
472 EndIntervalRulers(grid_x, grid_y);
473 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
474 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
475 PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
476 PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
477 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
478 EndShowMeasureCursor(saved_x, saved_y, buf, TRUE);
479 abort = TRUE;
480 done = TRUE;
481 }
482 }
483 }
484 if (!abort && OrigX != grid_x && OrigY != grid_y) {
485 CreateBoxObj(OrigX, OrigY, grid_x, grid_y, FALSE);
486 RecordNewObjCmd();
487 DrawBoxObj(drawWindow, drawOrigX, drawOrigY, topObj);
488 boxDrawn = TRUE;
489 SetFileModified(TRUE);
490 }
491 XSync(mainDisplay, False);
492 }
493
DrawBox(input)494 void DrawBox(input)
495 XEvent *input;
496 {
497 XButtonEvent *button_ev;
498 int mouse_x, mouse_y, grid_x, grid_y;
499
500 if (input->type != ButtonPress) return;
501
502 button_ev = &(input->xbutton);
503 if (button_ev->button == Button1) {
504 mouse_x = button_ev->x;
505 mouse_y = button_ev->y;
506 GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
507 ContinueBox(grid_x, grid_y);
508 }
509 }
510
MakeBoxObjFromBoundingBox()511 void MakeBoxObjFromBoundingBox()
512 {
513 if (topSel == NULL) {
514 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
515 return;
516 }
517 if (curChoice == VERTEXMODE) SetCurChoice(NOTHING);
518
519 HighLightReverse();
520 CreateBoxObj(selObjLtX, selObjLtY, selObjRbX, selObjRbY, TRUE);
521 SelectTopObj();
522 RecordNewObjCmd();
523 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
524 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
525 HighLightForward();
526 justDupped = FALSE;
527 SetFileModified(TRUE);
528 }
529
SaveBoxObj(FP,ObjPtr)530 void SaveBoxObj(FP, ObjPtr)
531 FILE *FP;
532 struct ObjRec *ObjPtr;
533 {
534 struct BoxRec *box_ptr=ObjPtr->detail.b;
535
536 if (fprintf(FP, "box('%s','',", colorMenuItems[ObjPtr->color]) == EOF) {
537 writeFileFailed = TRUE;
538 }
539 if (fprintf(FP,
540 "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,'%s',%1d,",
541 ObjPtr->obbox.ltx, ObjPtr->obbox.lty, ObjPtr->obbox.rbx,
542 ObjPtr->obbox.rby, box_ptr->fill, box_ptr->width, box_ptr->pen,
543 ObjPtr->id, box_ptr->dash, ObjPtr->rotation, ObjPtr->locked,
544 ObjPtr->ctm!=NULL, ObjPtr->invisible, box_ptr->width_spec,
545 ObjPtr->trans_pat) == EOF) {
546 writeFileFailed = TRUE;
547 }
548 if (ObjPtr->ctm != NULL && fprintf(FP,
549 "[\n %1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
550 ObjPtr->x, ObjPtr->y,
551 ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
552 ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
553 ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
554 ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
555 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
556 writeFileFailed = TRUE;
557 }
558 if (serializingFile) SaveCreatorID(FP, ObjPtr, " ");
559 SaveAttrs(FP, ObjPtr->lattr);
560 if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
561 }
562
ReadBoxObj(FP,Inbuf,ObjPtr)563 void ReadBoxObj(FP, Inbuf, ObjPtr)
564 FILE *FP;
565 char *Inbuf;
566 struct ObjRec **ObjPtr;
567 {
568 struct BoxRec *box_ptr;
569 char color_str[40], bg_color_str[40], *s, width_spec[40];
570 int ltx, lty, rbx, rby, fill, width, pen, dash, w, id=0, trans_pat=FALSE;
571 int new_alloc, rotation, locked=FALSE, transformed=FALSE, invisible=FALSE;
572
573 *ObjPtr = NULL;
574
575 s = FindChar((int)'(', Inbuf);
576 s = ParseStr(s, (int)',', color_str, sizeof(color_str));
577 if (fileVersion >= 37) {
578 s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str));
579 }
580 InitScan(s, "\t\n, ");
581
582 dash = 0;
583 rotation = 0;
584 *width_spec = '\0';
585 if (fileVersion <= 5) {
586 if (GETINT("box", ltx, "ltx") == INVALID ||
587 GETINT("box", lty, "lty") == INVALID ||
588 GETINT("box", rbx, "rbx") == INVALID ||
589 GETINT("box", rby, "rby") == INVALID ||
590 GETINT("box", fill, "fill") == INVALID ||
591 GETINT("box", width, "width") == INVALID ||
592 GETINT("box", pen, "pen") == INVALID)
593 {
594 return;
595 }
596 switch (width) {
597 case 1: width = 3; break;
598 case 2: width = 6; break;
599 }
600 id = objId++;
601 } else if (fileVersion <= 7) {
602 if (GETINT("box", ltx, "ltx") == INVALID ||
603 GETINT("box", lty, "lty") == INVALID ||
604 GETINT("box", rbx, "rbx") == INVALID ||
605 GETINT("box", rby, "rby") == INVALID ||
606 GETINT("box", fill, "fill") == INVALID ||
607 GETINT("box", width, "width") == INVALID ||
608 GETINT("box", pen, "pen") == INVALID)
609 {
610 return;
611 }
612 id = objId++;
613 } else if (fileVersion <= 8) {
614 if (GETINT("box", ltx, "ltx") == INVALID ||
615 GETINT("box", lty, "lty") == INVALID ||
616 GETINT("box", rbx, "rbx") == INVALID ||
617 GETINT("box", rby, "rby") == INVALID ||
618 GETINT("box", fill, "fill") == INVALID ||
619 GETINT("box", width, "width") == INVALID ||
620 GETINT("box", pen, "pen") == INVALID ||
621 GETINT("box", id, "id") == INVALID)
622 {
623 return;
624 }
625 if (id >= objId) objId = id+1;
626 } else if (fileVersion <= 13) {
627 if (GETINT("box", ltx, "ltx") == INVALID ||
628 GETINT("box", lty, "lty") == INVALID ||
629 GETINT("box", rbx, "rbx") == INVALID ||
630 GETINT("box", rby, "rby") == INVALID ||
631 GETINT("box", fill, "fill") == INVALID ||
632 GETINT("box", width, "width") == INVALID ||
633 GETINT("box", pen, "pen") == INVALID ||
634 GETINT("box", id, "id") == INVALID ||
635 GETINT("box", dash, "dash") == INVALID)
636 {
637 return;
638 }
639 if (id >= objId) objId = id+1;
640 } else if (fileVersion <= 25) {
641 if (GETINT("box", ltx, "ltx") == INVALID ||
642 GETINT("box", lty, "lty") == INVALID ||
643 GETINT("box", rbx, "rbx") == INVALID ||
644 GETINT("box", rby, "rby") == INVALID ||
645 GETINT("box", fill, "fill") == INVALID ||
646 GETINT("box", width, "width") == INVALID ||
647 GETINT("box", pen, "pen") == INVALID ||
648 GETINT("box", id, "id") == INVALID ||
649 GETINT("box", dash, "dash") == INVALID ||
650 GETINT("box", rotation, "rotation") == INVALID)
651 {
652 return;
653 }
654 if (id >= objId) objId = id+1;
655 } else if (fileVersion <= 32) {
656 if (GETINT("box", ltx, "ltx") == INVALID ||
657 GETINT("box", lty, "lty") == INVALID ||
658 GETINT("box", rbx, "rbx") == INVALID ||
659 GETINT("box", rby, "rby") == INVALID ||
660 GETINT("box", fill, "fill") == INVALID ||
661 GETINT("box", width, "width") == INVALID ||
662 GETINT("box", pen, "pen") == INVALID ||
663 GETINT("box", id, "id") == INVALID ||
664 GETINT("box", dash, "dash") == INVALID ||
665 GETINT("box", rotation, "rotation") == INVALID ||
666 GETINT("box", locked, "locked") == INVALID)
667 {
668 return;
669 }
670 if (id >= objId) objId = id+1;
671 } else if (fileVersion <= 34) {
672 if (GETINT("box", ltx, "ltx") == INVALID ||
673 GETINT("box", lty, "lty") == INVALID ||
674 GETINT("box", rbx, "rbx") == INVALID ||
675 GETINT("box", rby, "rby") == INVALID ||
676 GETINT("box", fill, "fill") == INVALID ||
677 GETINT("box", width, "width") == INVALID ||
678 GETINT("box", pen, "pen") == INVALID ||
679 GETINT("box", id, "id") == INVALID ||
680 GETINT("box", dash, "dash") == INVALID ||
681 GETINT("box", rotation, "rotation") == INVALID ||
682 GETINT("box", locked, "locked") == INVALID ||
683 GETINT("box", transformed, "transformed") == INVALID ||
684 GETINT("box", invisible, "invisible") == INVALID ||
685 GETSTR("box", width_spec, "width_spec") == INVALID)
686 {
687 return;
688 }
689 if (id >= objId) objId = id+1;
690 UtilRemoveQuotes(width_spec);
691 } else {
692 if (GETINT("box", ltx, "ltx") == INVALID ||
693 GETINT("box", lty, "lty") == INVALID ||
694 GETINT("box", rbx, "rbx") == INVALID ||
695 GETINT("box", rby, "rby") == INVALID ||
696 GETINT("box", fill, "fill") == INVALID ||
697 GETINT("box", width, "width") == INVALID ||
698 GETINT("box", pen, "pen") == INVALID ||
699 GETINT("box", id, "id") == INVALID ||
700 GETINT("box", dash, "dash") == INVALID ||
701 GETINT("box", rotation, "rotation") == INVALID ||
702 GETINT("box", locked, "locked") == INVALID ||
703 GETINT("box", transformed, "transformed") == INVALID ||
704 GETINT("box", invisible, "invisible") == INVALID ||
705 GETSTR("box", width_spec, "width_spec") == INVALID ||
706 GETINT("box", trans_pat, "trans_pat") == INVALID)
707 {
708 return;
709 }
710 if (id >= objId) objId = id+1;
711 UtilRemoveQuotes(width_spec);
712 }
713 if (fileVersion <= 16 && width <= 6) width = origWidthOfLine[width];
714 if (fileVersion <= 32) {
715 sprintf(width_spec, "%1d", width);
716 }
717 fill = UpgradePenFill(fill);
718 pen = UpgradePenFill(pen);
719
720 *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
721 if (*ObjPtr == NULL) FailAllocMessage();
722 memset(*ObjPtr, 0, sizeof(struct ObjRec));
723 box_ptr = (struct BoxRec *)malloc(sizeof(struct BoxRec));
724 if (box_ptr == NULL) FailAllocMessage();
725 memset(box_ptr, 0, sizeof(struct BoxRec));
726
727 if (ltx > rbx || lty > rby) {
728 int tmp_ltx, tmp_lty, tmp_rbx, tmp_rby;
729
730 if (!PRTGIF) {
731 Msg(TgLoadCachedString(CSTID_BAD_BOX_BBOX_ADJUSTED));
732 }
733 CalcBBox(ltx, lty, rbx, rby, &tmp_ltx, &tmp_lty, &tmp_rbx, &tmp_rby);
734 ltx = tmp_ltx; lty = tmp_lty; rbx = tmp_rbx; rby = tmp_rby;
735 }
736
737 (*ObjPtr)->trans_pat = trans_pat;
738 box_ptr->fill = fill;
739 box_ptr->width = width;
740 UtilStrCpyN(box_ptr->width_spec, sizeof(box_ptr->width_spec), width_spec);
741 box_ptr->pen = pen;
742 box_ptr->dash = dash;
743 (*ObjPtr)->x = ltx;
744 (*ObjPtr)->y = lty;
745 (*ObjPtr)->color = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE);
746 UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str), color_str);
747 (*ObjPtr)->dirty = FALSE;
748 (*ObjPtr)->id = id;
749 (*ObjPtr)->rotation = rotation;
750 (*ObjPtr)->locked = locked;
751 (*ObjPtr)->type = OBJ_BOX;
752 (*ObjPtr)->obbox.ltx = ltx;
753 (*ObjPtr)->obbox.lty = lty;
754 (*ObjPtr)->obbox.rbx = rbx;
755 (*ObjPtr)->obbox.rby = rby;
756 w = HALF_W(width);
757 (*ObjPtr)->bbox.ltx = ltx - w;
758 (*ObjPtr)->bbox.lty = lty - w;
759 (*ObjPtr)->bbox.rbx = rbx + w;
760 (*ObjPtr)->bbox.rby = rby + w;
761 (*ObjPtr)->detail.b = box_ptr;
762 (*ObjPtr)->ctm = NULL;
763 (*ObjPtr)->invisible = invisible;
764
765 if (fileVersion >= 33 && transformed) {
766 int real_x=0, real_y=0;
767 struct BBRec orig_obbox;
768 char inbuf[MAXSTRING+1];
769 struct XfrmMtrxRec *ctm;
770
771 (void)fgets(inbuf, MAXSTRING, FP);
772 scanLineNum++;
773 InitScan(inbuf, "\t\n, ");
774
775 ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
776 if (ctm == NULL) FailAllocMessage();
777 if (GETINT("box", real_x, "real_x") == INVALID ||
778 GETINT("box", real_y, "real_y") == INVALID ||
779 GETINT("box", orig_obbox.ltx, "orig_obbox.ltx") == INVALID ||
780 GETINT("box", orig_obbox.lty, "orig_obbox.lty") == INVALID ||
781 GETINT("box", orig_obbox.rbx, "orig_obbox.rbx") == INVALID ||
782 GETINT("box", orig_obbox.rby, "orig_obbox.rby") == INVALID ||
783 GETDBL("box", ctm->m[CTM_SX], "CTM_SX") == INVALID ||
784 GETDBL("box", ctm->m[CTM_SIN], "CTM_SIN") == INVALID ||
785 GETDBL("box", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
786 GETDBL("box", ctm->m[CTM_SY], "CTM_SY") == INVALID ||
787 GETINT("box", ctm->t[CTM_TX], "CTM_TX") == INVALID ||
788 GETINT("box", ctm->t[CTM_TY], "CTM_TY") == INVALID) {
789 return;
790 }
791 (*ObjPtr)->ctm = ctm;
792 if (ctm != NULL) {
793 memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
794 (*ObjPtr)->x = real_x;
795 (*ObjPtr)->y = real_y;
796 GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
797 }
798 }
799 }
800
SetBoxPropMask(ObjPtr,plMask,plSkip,pProp)801 void SetBoxPropMask(ObjPtr, plMask, plSkip, pProp)
802 struct ObjRec *ObjPtr;
803 long *plMask, *plSkip;
804 struct PropertiesRec *pProp;
805 {
806 struct BoxRec *box_ptr=ObjPtr->detail.b;
807
808 SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
809
810 SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
811 colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
812 SetIntPropertyMask(PROP_MASK_WIDTH, box_ptr->width, box_ptr->width_spec,
813 plMask, plSkip, pProp);
814
815 SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL,
816 plMask, plSkip, pProp);
817 SetIntPropertyMask(PROP_MASK_FILL, box_ptr->fill, NULL,
818 plMask, plSkip, pProp);
819 SetIntPropertyMask(PROP_MASK_PEN, box_ptr->pen, NULL,
820 plMask, plSkip, pProp);
821 SetIntPropertyMask(PROP_MASK_DASH, box_ptr->dash, NULL,
822 plMask, plSkip, pProp);
823 }
824
FreeBoxObj(ObjPtr)825 void FreeBoxObj(ObjPtr)
826 struct ObjRec *ObjPtr;
827 {
828 free(ObjPtr->detail.b);
829 free(ObjPtr);
830 }
831