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/align.c,v 1.25 2011/05/16 16:21:56 william Exp $
19 */
20
21 #define _INCLUDE_FROM_ALIGN_C_
22
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25
26 #include "align.e"
27 #include "auxtext.e"
28 #include "button.e"
29 #include "choice.e"
30 #include "cmd.e"
31 #include "color.e"
32 #include "dialog.e"
33 #include "drawing.e"
34 #include "dup.e"
35 #include "grid.e"
36 #include "mark.e"
37 #include "mainmenu.e"
38 #include "menu.e"
39 #include "menuinfo.e"
40 #include "move.e"
41 #include "msg.e"
42 #include "obj.e"
43 #include "poly.e"
44 #include "raster.e"
45 #include "rect.e"
46 #include "select.e"
47 #include "setup.e"
48 #include "stretch.e"
49 #include "strtbl.e"
50 #include "util.e"
51
52 typedef struct DistrVRec {
53 struct ObjRec *obj;
54 struct VSelRec *vsel;
55 int index, vindex, x, y;
56 struct DistrVRec *next, *prev;
57 } * DistrVRecPtr;
58
59 int horiAlign=ALIGN_L;
60 int vertAlign=ALIGN_T;
61
62 int alignDirectType=INVALID;
63
64 static
SetSSSIForDistr(obj_ptr,vsel_ptr,update_pmvi)65 void SetSSSIForDistr(obj_ptr, vsel_ptr, update_pmvi)
66 struct ObjRec *obj_ptr;
67 struct VSelRec *vsel_ptr;
68 int update_pmvi;
69 {
70 IntPoint *vlist=NULL;
71 int i=0, n=0;
72 StretchStructuredSplineInfo *psssi=NULL;
73
74 switch (obj_ptr->type) {
75 case OBJ_POLY:
76 vlist = obj_ptr->detail.p->vlist;
77 n = obj_ptr->detail.p->n;
78 if (obj_ptr->userdata == NULL &&
79 obj_ptr->detail.p->curved == LT_STRUCT_SPLINE) {
80 psssi = (StretchStructuredSplineInfo*)malloc(
81 sizeof(StretchStructuredSplineInfo));
82 if (psssi == NULL) FailAllocMessage();
83 memset(psssi, 0, sizeof(StretchStructuredSplineInfo));
84
85 SetIPTInfoForStretchPoly(vsel_ptr->v_index[0], n, vlist, psssi);
86
87 psssi->orig_abs_x = psssi->new_abs_x = vlist[vsel_ptr->v_index[0]].x;
88 psssi->orig_abs_y = psssi->new_abs_y = vlist[vsel_ptr->v_index[0]].y;
89 obj_ptr->userdata = psssi;
90 if (obj_ptr->ctm != NULL) {
91 psssi->rotated_orig_abs_x = psssi->rotated_new_abs_x =
92 vsel_ptr->x[0];
93 psssi->rotated_orig_abs_y = psssi->rotated_new_abs_y =
94 vsel_ptr->y[0];
95 }
96 }
97 if (update_pmvi && vsel_ptr->pmvi == NULL &&
98 obj_ptr->detail.p->curved != LT_STRUCT_SPLINE) {
99 vsel_ptr->pmvi = (MoveVertexInfo*)malloc(
100 vsel_ptr->n*sizeof(MoveVertexInfo));
101 memset(vsel_ptr->pmvi, 0, vsel_ptr->n*sizeof(MoveVertexInfo));
102
103 for (i=0; i < vsel_ptr->n; i++) {
104 vsel_ptr->pmvi[i].orig_abs_x = vsel_ptr->pmvi[i].new_abs_x =
105 vlist[vsel_ptr->v_index[i]].x;
106 vsel_ptr->pmvi[i].orig_abs_y = vsel_ptr->pmvi[i].new_abs_y =
107 vlist[vsel_ptr->v_index[i]].y;
108 if (obj_ptr->ctm != NULL) {
109 vsel_ptr->pmvi[i].rotated_orig_abs_x =
110 vsel_ptr->pmvi[i].rotated_new_abs_x = vsel_ptr->x[i];
111 vsel_ptr->pmvi[i].rotated_orig_abs_y =
112 vsel_ptr->pmvi[i].rotated_new_abs_y = vsel_ptr->y[i];
113 }
114 }
115 }
116 break;
117 case OBJ_POLYGON:
118 vlist = obj_ptr->detail.g->vlist;
119 n = obj_ptr->detail.g->n;
120 if (obj_ptr->userdata == NULL &&
121 obj_ptr->detail.g->curved == LT_STRUCT_SPLINE) {
122 psssi = (StretchStructuredSplineInfo*)malloc(
123 sizeof(StretchStructuredSplineInfo));
124 if (psssi == NULL) FailAllocMessage();
125 memset(psssi, 0, sizeof(StretchStructuredSplineInfo));
126
127 SetIPTInfoForStretchPoly(vsel_ptr->v_index[0], n, vlist, psssi);
128
129 psssi->orig_abs_x = psssi->new_abs_x = vlist[vsel_ptr->v_index[0]].x;
130 psssi->orig_abs_y = psssi->new_abs_y = vlist[vsel_ptr->v_index[0]].y;
131 obj_ptr->userdata = psssi;
132 if (obj_ptr->ctm != NULL) {
133 psssi->rotated_orig_abs_x = psssi->rotated_new_abs_x =
134 vsel_ptr->x[0];
135 psssi->rotated_orig_abs_y = psssi->rotated_new_abs_y =
136 vsel_ptr->y[0];
137 }
138 }
139 if (update_pmvi && vsel_ptr->pmvi == NULL &&
140 obj_ptr->detail.g->curved != LT_STRUCT_SPLINE) {
141 vsel_ptr->pmvi = (MoveVertexInfo*)malloc(
142 vsel_ptr->n*sizeof(MoveVertexInfo));
143 memset(vsel_ptr->pmvi, 0, vsel_ptr->n*sizeof(MoveVertexInfo));
144
145 for (i=0; i < vsel_ptr->n; i++) {
146 vsel_ptr->pmvi[i].orig_abs_x = vsel_ptr->pmvi[i].new_abs_x =
147 vlist[vsel_ptr->v_index[i]].x;
148 vsel_ptr->pmvi[i].orig_abs_y = vsel_ptr->pmvi[i].new_abs_y =
149 vlist[vsel_ptr->v_index[i]].y;
150 if (obj_ptr->ctm != NULL) {
151 vsel_ptr->pmvi[i].rotated_orig_abs_x =
152 vsel_ptr->pmvi[i].rotated_new_abs_x = vsel_ptr->x[i];
153 vsel_ptr->pmvi[i].rotated_orig_abs_y =
154 vsel_ptr->pmvi[i].rotated_new_abs_y = vsel_ptr->y[i];
155 }
156 }
157 }
158 break;
159 }
160 }
161
DistrSelObjs()162 void DistrSelObjs()
163 {
164 int i=0, dx=0, dy=0, ltx, lty, rbx, rby, count, w, h;
165 struct SelRec *sel_ptr=NULL, *next_sel=NULL;
166 struct ObjRec *obj_ptr=NULL;
167 struct VSelRec *vsel_ptr=NULL;
168 double x=0.0, y=0.0, h_dist=0.0, v_dist=0.0;
169
170 if ((topSel==NULL && topVSel==NULL) ||
171 (horiAlign==ALIGN_N && vertAlign==ALIGN_N)) {
172 return;
173 }
174 if (numObjLocked != 0) {
175 MsgBox(TgLoadString(STID_CANNOT_DISTRIBUTE_LOCKED_OBJS),
176 TOOL_NAME, INFO_MB);
177 return;
178 }
179 if (curChoice == VERTEXMODE) {
180 int start=0, vertices_count=0;
181 struct DistrVRec *dv_ptr=NULL, *left_dv=NULL, *right_dv=NULL;
182 struct DistrVRec *top_dv=NULL, *bottom_dv=NULL;
183 struct DistrVRec *ptr=NULL, *hori_dv=NULL, *vert_dv=NULL;
184 struct SelRec *tmp_top_sel=NULL, *tmp_bot_sel=NULL, *tmp_sel_ptr=NULL;
185 StretchStructuredSplineInfo *psssi=NULL;
186
187 if ((vertices_count=CountSelectedVertices()) <= 2) return;
188
189 HighLightReverse();
190
191 dv_ptr = (struct DistrVRec *)malloc(
192 2*vertices_count*sizeof(struct DistrVRec));
193 if (dv_ptr == NULL) FailAllocMessage();
194
195 start = 1;
196
197 ptr = dv_ptr;
198 ptr->obj = topVSel->obj;
199 ptr->vsel = topVSel;
200 ptr->index = topVSel->v_index[0];
201 ptr->vindex = 0;
202 ptr->x = topVSel->x[0];
203 ptr->y = topVSel->y[0];
204 ptr->next = ptr->prev = NULL;
205 left_dv = right_dv = ptr;
206
207 ptr++;
208 ptr->obj = topVSel->obj;
209 ptr->vsel = topVSel;
210 ptr->index = topVSel->v_index[0];
211 ptr->vindex = 0;
212 ptr->x = topVSel->x[0];
213 ptr->y = topVSel->y[0];
214 ptr->next = ptr->prev = NULL;
215 top_dv = bottom_dv = ptr;
216
217 ptr++;
218 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
219 sel_ptr->obj->marked = FALSE;
220 sel_ptr->obj->userdata = NULL;
221 }
222 for (vsel_ptr=topVSel; vsel_ptr != NULL; vsel_ptr=vsel_ptr->next) {
223 int obj_type=vsel_ptr->obj->type, last_index=0, n=0;
224
225 if (obj_type == OBJ_POLYGON) {
226 last_index = vsel_ptr->obj->detail.g->n-1;
227 }
228 obj_ptr = vsel_ptr->obj;
229 n = vsel_ptr->n;
230 for (i=start; i < n; i++) {
231 if (!(obj_type==OBJ_POLYGON && vsel_ptr->v_index[i]==last_index)) {
232 for (hori_dv=left_dv; hori_dv!=NULL; hori_dv=hori_dv->next) {
233 if (hori_dv->x > vsel_ptr->x[i] ||
234 (hori_dv->x == vsel_ptr->x[i] &&
235 hori_dv->y > vsel_ptr->y[i])) {
236 break;
237 }
238 }
239 ptr->obj = obj_ptr;
240 ptr->vsel = vsel_ptr;
241 ptr->index = vsel_ptr->v_index[i];
242 ptr->vindex = i;
243 ptr->x = vsel_ptr->x[i];
244 ptr->y = vsel_ptr->y[i];
245
246 ptr->next = hori_dv;
247 if (hori_dv == NULL) {
248 ptr->prev = right_dv;
249 right_dv->next = ptr;
250 right_dv = ptr;
251 } else {
252 ptr->prev = hori_dv->prev;
253 if (hori_dv->prev == NULL) {
254 left_dv = ptr;
255 } else {
256 hori_dv->prev->next = ptr;
257 }
258 hori_dv->prev = ptr;
259 }
260 ptr++;
261
262 for (vert_dv=top_dv; vert_dv!=NULL; vert_dv=vert_dv->next) {
263 if (vert_dv->y > vsel_ptr->y[i] ||
264 (vert_dv->y == vsel_ptr->y[i] &&
265 vert_dv->x > vsel_ptr->x[i])) {
266 break;
267 }
268 }
269 ptr->obj = obj_ptr;
270 ptr->vsel = vsel_ptr;
271 ptr->index = vsel_ptr->v_index[i];
272 ptr->vindex = i;
273 ptr->x = vsel_ptr->x[i];
274 ptr->y = vsel_ptr->y[i];
275
276 ptr->next = vert_dv;
277 if (vert_dv == NULL) {
278 ptr->prev = bottom_dv;
279 bottom_dv->next = ptr;
280 bottom_dv = ptr;
281 } else {
282 ptr->prev = vert_dv->prev;
283 if (vert_dv->prev == NULL) {
284 top_dv = ptr;
285 } else {
286 vert_dv->prev->next = ptr;
287 }
288 vert_dv->prev = ptr;
289 }
290 ptr++;
291 }
292 }
293 start = 0;
294 }
295
296 if (horiAlign != ALIGN_N) {
297 for (ptr=left_dv; ptr->next!=right_dv; ptr=ptr->next) {
298 obj_ptr = ptr->next->obj;
299 vsel_ptr = ptr->next->vsel;
300 if (!(obj_ptr->type==OBJ_POLYGON &&
301 ptr->next->index==obj_ptr->detail.g->n-1)) {
302 obj_ptr->marked = TRUE;
303 SetSSSIForDistr(obj_ptr, vsel_ptr, TRUE);
304 }
305 }
306 }
307 if (vertAlign != ALIGN_N) {
308 for (ptr=top_dv; ptr->next!=bottom_dv; ptr=ptr->next) {
309 obj_ptr = ptr->next->obj;
310 vsel_ptr = ptr->next->vsel;
311 if (!(obj_ptr->type==OBJ_POLYGON &&
312 ptr->next->index==obj_ptr->detail.g->n-1)) {
313 obj_ptr->marked = TRUE;
314 SetSSSIForDistr(obj_ptr, vsel_ptr, TRUE);
315 }
316 }
317 }
318
319 tmp_top_sel = tmp_bot_sel = NULL;
320 count = 0;
321 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
322 obj_ptr = sel_ptr->obj;
323 if (obj_ptr->marked) {
324 count++;
325 AddObjIntoSel(obj_ptr, tmp_bot_sel, NULL, &tmp_top_sel,
326 &tmp_bot_sel);
327 }
328 }
329 if (count != 0) {
330 PrepareToRecord(CMD_REPLACE, tmp_top_sel, tmp_bot_sel, count);
331 }
332 if (horiAlign != ALIGN_N) {
333 x = (double)(left_dv->x);
334 h_dist = ((double)(right_dv->x-x))/((double)(vertices_count-1));
335 for (ptr=left_dv; ptr->next!=right_dv; ptr=ptr->next) {
336 int new_x=0;
337
338 obj_ptr = ptr->next->obj;
339 vsel_ptr = ptr->next->vsel;
340
341 if (obj_ptr->type==OBJ_POLYGON &&
342 ptr->next->index==obj_ptr->detail.g->n-1) {
343 continue;
344 }
345 obj_ptr->marked = TRUE;
346 new_x = round(x+h_dist);
347
348 if (obj_ptr->userdata != NULL) {
349 psssi = (StretchStructuredSplineInfo *)obj_ptr->userdata;
350
351 if (obj_ptr->ctm == NULL) {
352 psssi->new_abs_x = new_x;
353 psssi->abs_dx = new_x - psssi->orig_abs_x;
354 } else {
355 psssi->rotated_new_abs_x = new_x;
356 psssi->rotated_abs_dx = new_x - psssi->rotated_orig_abs_x;
357 }
358 } else {
359 int vindex=ptr->next->vindex;
360 MoveVertexInfo *pmvi=vsel_ptr->pmvi;
361
362 if (obj_ptr->ctm == NULL) {
363 pmvi[vindex].new_abs_x = new_x;
364 pmvi[vindex].abs_dx = new_x - pmvi[vindex].orig_abs_x;
365 } else {
366 pmvi[vindex].rotated_new_abs_x = new_x;
367 pmvi[vindex].rotated_abs_dx = new_x -
368 pmvi[vindex].rotated_orig_abs_x;
369 }
370 }
371 vsel_ptr->x[ptr->next->vindex] = new_x;
372 x += h_dist;
373 }
374 }
375 if (vertAlign != ALIGN_N) {
376 y = (double)(top_dv->y);
377 v_dist = ((double)(bottom_dv->y-y))/((double)(vertices_count-1));
378 for (ptr=top_dv; ptr->next!=bottom_dv; ptr=ptr->next) {
379 int new_y=0;
380
381 obj_ptr = ptr->next->obj;
382 vsel_ptr = ptr->next->vsel;
383
384 if (obj_ptr->type==OBJ_POLYGON &&
385 ptr->next->index==obj_ptr->detail.g->n-1) {
386 continue;
387 }
388 obj_ptr->marked = TRUE;
389 new_y = round(y+v_dist);
390
391 if (obj_ptr->userdata != NULL) {
392 psssi = (StretchStructuredSplineInfo *)obj_ptr->userdata;
393
394 if (obj_ptr->ctm == NULL) {
395 psssi->new_abs_y = new_y;
396 psssi->abs_dy = new_y - psssi->orig_abs_y;
397 } else {
398 psssi->rotated_new_abs_y = new_y;
399 psssi->rotated_abs_dy = new_y - psssi->rotated_orig_abs_y;
400 }
401 } else {
402 int vindex=ptr->next->vindex;
403 MoveVertexInfo *pmvi=vsel_ptr->pmvi;
404
405 if (obj_ptr->ctm == NULL) {
406 pmvi[vindex].new_abs_y = new_y;
407 pmvi[vindex].abs_dy = new_y - pmvi[vindex].orig_abs_y;
408 } else {
409 pmvi[vindex].rotated_new_abs_y = new_y;
410 pmvi[vindex].rotated_abs_dy = new_y -
411 pmvi[vindex].rotated_orig_abs_y;
412 }
413 }
414 vsel_ptr->y[ptr->next->vindex] = new_y;
415 y += v_dist;
416 }
417 }
418 for (vsel_ptr=topVSel; vsel_ptr != NULL; vsel_ptr=vsel_ptr->next) {
419 obj_ptr = vsel_ptr->obj;
420 if (obj_ptr->marked) {
421 IntPoint *vlist=NULL;
422
423 switch (obj_ptr->type) {
424 case OBJ_POLY: vlist = obj_ptr->detail.p->vlist; break;
425 case OBJ_POLYGON: vlist = obj_ptr->detail.g->vlist; break;
426 }
427 if (obj_ptr->type==OBJ_POLYGON) {
428 struct PolygonRec *polygon_ptr=obj_ptr->detail.g;
429
430 polygon_ptr->vlist[polygon_ptr->n-1].x = polygon_ptr->vlist[0].x;
431 polygon_ptr->vlist[polygon_ptr->n-1].y = polygon_ptr->vlist[0].y;
432 }
433 if (obj_ptr->userdata != NULL) {
434 StretchStructuredSplineInfo *psssi=
435 (StretchStructuredSplineInfo *)obj_ptr->userdata;
436
437 if (obj_ptr->ctm == NULL) {
438 FinishMoveVertexForStretchStructSpline(vsel_ptr,
439 psssi->abs_dx, psssi->abs_dy, psssi);
440 } else {
441 FinishMoveVertexForStretchStructSpline(vsel_ptr,
442 psssi->rotated_abs_dx, psssi->rotated_abs_dy, psssi);
443 }
444 free(psssi);
445 obj_ptr->userdata = NULL;
446 } else {
447 MoveVertexInfo *pmvi=vsel_ptr->pmvi;
448
449 if (obj_ptr->ctm == NULL) {
450 for (i=0; i < vsel_ptr->n; i++) {
451 if (pmvi[i].abs_dx != 0 || pmvi[i].abs_dy != 0) {
452 vlist[vsel_ptr->v_index[i]].x += pmvi[i].abs_dx;
453 vlist[vsel_ptr->v_index[i]].y += pmvi[i].abs_dy;
454 }
455 }
456 } else {
457 for (i=0; i < vsel_ptr->n; i++) {
458 if (pmvi[i].rotated_abs_dx != 0 ||
459 pmvi[i].rotated_abs_dy != 0) {
460 int tmp_x=0, tmp_y=0;
461
462 ReverseTransformPointThroughCTM(
463 pmvi[i].rotated_new_abs_x-obj_ptr->x,
464 pmvi[i].rotated_new_abs_y-obj_ptr->y,
465 obj_ptr->ctm, &tmp_x, &tmp_y);
466 vlist[vsel_ptr->v_index[i]].x = tmp_x + obj_ptr->x;
467 vlist[vsel_ptr->v_index[i]].y = tmp_y + obj_ptr->y;
468 }
469 }
470 }
471 free(pmvi);
472 vsel_ptr->pmvi = NULL;
473 }
474 AdjObjSplineVs(obj_ptr);
475 UpdPolyOrPolygonBBox(obj_ptr);
476 }
477 }
478 if (count != 0) {
479 RecordCmd(CMD_REPLACE, NULL, tmp_top_sel, tmp_bot_sel, count);
480 }
481 for (tmp_sel_ptr=tmp_top_sel; tmp_sel_ptr!=NULL; tmp_sel_ptr=next_sel) {
482 next_sel = tmp_sel_ptr->next;
483 free(tmp_sel_ptr);
484 }
485 free(dv_ptr);
486
487 if (horiAlign != ALIGN_N) {
488 sprintf(gszMsgBox, TgLoadString(STID_VERTICES_HORI_APART),
489 round(h_dist));
490 Msg(gszMsgBox);
491 }
492 if (vertAlign != ALIGN_N) {
493 sprintf(gszMsgBox, TgLoadString(STID_VERTICES_VERT_APART),
494 round(v_dist));
495 Msg(gszMsgBox);
496 }
497 } else {
498 struct SelRec *left_sel=NULL, *right_sel=NULL;
499 struct SelRec *top_sel=NULL, *bottom_sel=NULL;
500 struct SelRec *vert_sel=NULL, *hori_sel=NULL, *new_sel=NULL;
501 struct SubCmdRec *sub_cmd=NULL;
502 struct SelRec *tmp_sel_ptr=NULL;
503
504 if (topSel==botSel || topSel->next==botSel) return;
505
506 tmp_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
507 if (tmp_sel_ptr == NULL) FailAllocMessage();
508 tmp_sel_ptr->next = tmp_sel_ptr->prev = NULL;
509
510 sub_cmd = (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
511 if (sub_cmd == NULL) FailAllocMessage();
512 memset(sub_cmd, 0, sizeof(struct SubCmdRec));
513
514 StartCompositeCmd();
515 HighLightReverse();
516
517 left_sel = right_sel = (struct SelRec *)malloc(sizeof(struct SelRec));
518 top_sel = bottom_sel = (struct SelRec *)malloc(sizeof(struct SelRec));
519 if (left_sel == NULL || right_sel == NULL ||
520 top_sel == NULL || bottom_sel == NULL) {
521 FailAllocMessage();
522 }
523 left_sel->obj = right_sel->obj = botSel->obj;
524 top_sel->obj = bottom_sel->obj = botSel->obj;
525 left_sel->prev = right_sel->next = NULL;
526 top_sel->prev = bottom_sel->next = NULL;
527
528 count = 1;
529 w = left_sel->obj->obbox.rbx - left_sel->obj->obbox.ltx;
530 h = left_sel->obj->obbox.rby - left_sel->obj->obbox.lty;
531 for (sel_ptr=botSel->prev; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
532 count++;
533 obj_ptr = sel_ptr->obj;
534 w += obj_ptr->obbox.rbx - obj_ptr->obbox.ltx;
535 h += obj_ptr->obbox.rby - obj_ptr->obbox.lty;
536 switch (horiAlign) {
537 case ALIGN_N:
538 case ALIGN_L:
539 case ALIGN_S:
540 for (hori_sel=left_sel; hori_sel!=NULL; hori_sel=hori_sel->next) {
541 if (hori_sel->obj->obbox.ltx > obj_ptr->obbox.ltx ||
542 (hori_sel->obj->obbox.ltx == obj_ptr->obbox.ltx &&
543 hori_sel->obj->obbox.lty > obj_ptr->obbox.lty)) {
544 break;
545 }
546 }
547 break;
548 case ALIGN_C:
549 for (hori_sel=left_sel; hori_sel!=NULL; hori_sel=hori_sel->next) {
550 if (hori_sel->obj->obbox.ltx+hori_sel->obj->obbox.rbx >
551 obj_ptr->obbox.ltx+obj_ptr->obbox.rbx ||
552 (hori_sel->obj->obbox.ltx+hori_sel->obj->obbox.rbx ==
553 obj_ptr->obbox.ltx+obj_ptr->obbox.rbx &&
554 hori_sel->obj->obbox.lty+hori_sel->obj->obbox.rby >
555 obj_ptr->obbox.lty+obj_ptr->obbox.rby)) {
556 break;
557 }
558 }
559 break;
560 case ALIGN_R:
561 for (hori_sel=left_sel; hori_sel!=NULL; hori_sel=hori_sel->next) {
562 if (hori_sel->obj->obbox.rbx > obj_ptr->obbox.rbx ||
563 (hori_sel->obj->obbox.rbx == obj_ptr->obbox.rbx &&
564 hori_sel->obj->obbox.rby > obj_ptr->obbox.rby)) {
565 break;
566 }
567 }
568 break;
569 }
570 new_sel = (struct SelRec *)malloc(sizeof(struct SelRec));
571 if (new_sel == NULL) FailAllocMessage();
572 new_sel->obj = obj_ptr;
573 new_sel->next = hori_sel;
574 if (hori_sel == NULL) {
575 new_sel->prev = right_sel;
576 right_sel->next = new_sel;
577 right_sel = new_sel;
578 } else {
579 new_sel->prev = hori_sel->prev;
580 if (hori_sel->prev == NULL) {
581 left_sel = new_sel;
582 } else {
583 hori_sel->prev->next = new_sel;
584 }
585 hori_sel->prev = new_sel;
586 }
587 switch (vertAlign) {
588 case ALIGN_N:
589 case ALIGN_T:
590 case ALIGN_S:
591 for (vert_sel=top_sel; vert_sel!=NULL; vert_sel=vert_sel->next) {
592 if (vert_sel->obj->obbox.lty > obj_ptr->obbox.lty ||
593 (vert_sel->obj->obbox.lty == obj_ptr->obbox.lty &&
594 vert_sel->obj->obbox.ltx > obj_ptr->obbox.ltx)) {
595 break;
596 }
597 }
598 break;
599 case ALIGN_M:
600 for (vert_sel=top_sel; vert_sel!=NULL; vert_sel=vert_sel->next) {
601 if (vert_sel->obj->obbox.lty+vert_sel->obj->obbox.rby >
602 obj_ptr->obbox.lty+obj_ptr->obbox.rby ||
603 (vert_sel->obj->obbox.lty+vert_sel->obj->obbox.rby ==
604 obj_ptr->obbox.lty+obj_ptr->obbox.rby &&
605 vert_sel->obj->obbox.ltx+vert_sel->obj->obbox.rbx >
606 obj_ptr->obbox.ltx+obj_ptr->obbox.rbx)) {
607 break;
608 }
609 }
610 break;
611 case ALIGN_B:
612 for (vert_sel=top_sel; vert_sel!=NULL; vert_sel=vert_sel->next) {
613 if (vert_sel->obj->obbox.rby > obj_ptr->obbox.rby ||
614 (vert_sel->obj->obbox.rby == obj_ptr->obbox.rby &&
615 vert_sel->obj->obbox.rbx > obj_ptr->obbox.rbx)) {
616 break;
617 }
618 }
619 break;
620 }
621 new_sel = (struct SelRec *)malloc(sizeof(struct SelRec));
622 if (new_sel == NULL) FailAllocMessage();
623 new_sel->obj = obj_ptr;
624 new_sel->next = vert_sel;
625 if (vert_sel == NULL)
626 {
627 new_sel->prev = bottom_sel;
628 bottom_sel->next = new_sel;
629 bottom_sel = new_sel;
630 } else {
631 new_sel->prev = vert_sel->prev;
632 if (vert_sel->prev == NULL) {
633 top_sel = new_sel;
634 } else {
635 vert_sel->prev->next = new_sel;
636 }
637 vert_sel->prev = new_sel;
638 }
639 }
640 switch (horiAlign) {
641 case ALIGN_N:
642 case ALIGN_L:
643 x = (double)(left_sel->obj->obbox.ltx);
644 h_dist = ((double)(right_sel->obj->obbox.ltx-x))/((double)(count-1));
645 break;
646 case ALIGN_C:
647 x = (double)(left_sel->obj->obbox.rbx+left_sel->obj->obbox.ltx);
648 h_dist = ((double)(right_sel->obj->obbox.rbx +
649 right_sel->obj->obbox.ltx - x)) / ((double)(count-1));
650 break;
651 case ALIGN_R:
652 x = (double)(left_sel->obj->obbox.rbx);
653 h_dist = ((double)(right_sel->obj->obbox.rbx-x))/((double)(count-1));
654 break;
655 case ALIGN_S:
656 x = (double)(left_sel->obj->obbox.rbx);
657 h_dist = ((double)(right_sel->obj->obbox.rbx -
658 left_sel->obj->obbox.ltx - w)) / ((double)(count-1));
659 break;
660 }
661 switch (vertAlign) {
662 case ALIGN_N:
663 case ALIGN_T:
664 y = (double)(top_sel->obj->obbox.lty);
665 v_dist = ((double)(bottom_sel->obj->obbox.lty-y))/((double)(count-1));
666 break;
667 case ALIGN_M:
668 y = (double)(top_sel->obj->obbox.rby+top_sel->obj->obbox.lty);
669 v_dist = ((double)(bottom_sel->obj->obbox.rby +
670 bottom_sel->obj->obbox.lty - y)) / ((double)(count-1));
671 break;
672 case ALIGN_B:
673 y = (double)(top_sel->obj->obbox.rby);
674 v_dist = ((double)(bottom_sel->obj->obbox.rby-y))/((double)(count-1));
675 break;
676 case ALIGN_S:
677 y = (double)(top_sel->obj->obbox.rby);
678 v_dist = ((double)(bottom_sel->obj->obbox.rby -
679 top_sel->obj->obbox.lty - h)) / ((double)(count-1));
680 break;
681 }
682 for (sel_ptr=left_sel; sel_ptr->next!=right_sel; sel_ptr=next_sel) {
683 switch (horiAlign) {
684 case ALIGN_N: dx = 0; break;
685 case ALIGN_L:
686 dx = round(x+h_dist-sel_ptr->next->obj->obbox.ltx);
687 break;
688 case ALIGN_C:
689 dx = round((x + h_dist - sel_ptr->next->obj->obbox.rbx -
690 sel_ptr->next->obj->obbox.ltx) / ((double)2.0));
691 break;
692 case ALIGN_R:
693 dx = round(x+h_dist-sel_ptr->next->obj->obbox.rbx);
694 break;
695 case ALIGN_S:
696 dx = round(x+h_dist-sel_ptr->next->obj->obbox.ltx);
697 break;
698 }
699 if (dx != 0) {
700 sub_cmd->detail.move.dx = dx;
701 sub_cmd->detail.move.dy = 0;
702 tmp_sel_ptr->obj = sel_ptr->next->obj;
703 PrepareToRecord(CMD_MOVE, tmp_sel_ptr, tmp_sel_ptr, 1);
704 RecordCmd(CMD_MOVE, sub_cmd, NULL, NULL, 0);
705
706 MoveObj(sel_ptr->next->obj, dx, 0);
707 }
708
709 x += h_dist;
710 if (horiAlign == ALIGN_S) {
711 x += sel_ptr->next->obj->obbox.rbx - sel_ptr->next->obj->obbox.ltx;
712 }
713 next_sel = sel_ptr->next;
714 free(sel_ptr);
715 }
716 free(sel_ptr);
717 free(right_sel);
718
719 for (sel_ptr=top_sel; sel_ptr->next!=bottom_sel; sel_ptr=next_sel) {
720 switch (vertAlign) {
721 case ALIGN_N: dy = 0; break;
722 case ALIGN_T:
723 dy = round(y+v_dist-sel_ptr->next->obj->obbox.lty);
724 break;
725 case ALIGN_M:
726 dy = round((y + v_dist - sel_ptr->next->obj->obbox.rby -
727 sel_ptr->next->obj->obbox.lty) / ((double)2.0));
728 break;
729 case ALIGN_B:
730 dy = round(y+v_dist-sel_ptr->next->obj->obbox.rby);
731 break;
732 case ALIGN_S:
733 dy = round(y+v_dist-sel_ptr->next->obj->obbox.lty);
734 break;
735 }
736 if (dy != 0) {
737 sub_cmd->detail.move.dx = 0;
738 sub_cmd->detail.move.dy = dy;
739 tmp_sel_ptr->obj = sel_ptr->next->obj;
740 PrepareToRecord(CMD_MOVE, tmp_sel_ptr, tmp_sel_ptr, 1);
741 RecordCmd(CMD_MOVE, sub_cmd, NULL, NULL, 0);
742
743 MoveObj(sel_ptr->next->obj, 0, dy);
744 }
745
746 y += v_dist;
747 if (vertAlign == ALIGN_S) {
748 y += sel_ptr->next->obj->obbox.rby - sel_ptr->next->obj->obbox.lty;
749 }
750 next_sel = sel_ptr->next;
751 free(sel_ptr);
752 }
753 free(sel_ptr);
754 free(bottom_sel);
755
756 EndCompositeCmd();
757 free(sub_cmd);
758 free(tmp_sel_ptr);
759
760 switch (horiAlign) {
761 case ALIGN_L:
762 sprintf(gszMsgBox, TgLoadString(STID_LEFT_SIDES_APART), round(h_dist));
763 Msg(gszMsgBox);
764 break;
765 case ALIGN_C:
766 sprintf(gszMsgBox, TgLoadString(STID_CENTERS_APART),
767 round(h_dist/((double)2.0)));
768 Msg(gszMsgBox);
769 break;
770 case ALIGN_R:
771 sprintf(gszMsgBox, TgLoadString(STID_RIGHT_SIDES_APART),
772 round(h_dist));
773 Msg(gszMsgBox);
774 break;
775 case ALIGN_S:
776 sprintf(gszMsgBox, TgLoadString(STID_SPACED_APART_HORI),
777 round(h_dist));
778 Msg(gszMsgBox);
779 break;
780 }
781 switch (vertAlign) {
782 case ALIGN_T:
783 sprintf(gszMsgBox, TgLoadString(STID_TOP_SIDES_APART),
784 round(v_dist));
785 Msg(gszMsgBox);
786 break;
787 case ALIGN_M:
788 sprintf(gszMsgBox, TgLoadString(STID_MIDDLES_APART),
789 round(v_dist/((double)2.0)));
790 Msg(gszMsgBox);
791 break;
792 case ALIGN_B:
793 sprintf(gszMsgBox, TgLoadString(STID_BOTTOM_SIDES_APART),
794 round(v_dist));
795 Msg(gszMsgBox);
796 break;
797 case ALIGN_S:
798 sprintf(gszMsgBox, TgLoadString(STID_SPACED_APART_VERT),
799 round(v_dist));
800 Msg(gszMsgBox);
801 break;
802 }
803 }
804 ltx = selLtX; lty = selLtY; rbx = selRbX, rby = selRbY;
805 UpdSelBBox();
806 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
807 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
808 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
809 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
810 HighLightForward();
811 SetFileModified(TRUE);
812 justDupped = FALSE;
813 }
814
DistributeDirect(alignment)815 void DistributeDirect(alignment)
816 int alignment;
817 {
818 int saved_h_align=horiAlign, saved_v_align=vertAlign;
819 int v_mode=(alignment%MAXALIGNS);
820 int h_mode=((alignment-v_mode)/MAXALIGNS);
821
822 horiAlign = h_mode;
823 vertAlign = v_mode;
824 DistrSelObjs();
825 horiAlign = saved_h_align;
826 vertAlign = saved_v_align;
827 }
828
829 static
GetDistrDirectMenuStr(i)830 char *GetDistrDirectMenuStr(i)
831 int i;
832 /* returned string has been translated */
833 {
834 char *psz=NULL, *msg=NULL;
835
836 if (curChoice == VERTEXMODE) {
837 int v_mode=(i%MAXALIGNS);
838 int h_mode=((i-v_mode)/MAXALIGNS);
839
840 if (v_mode == ALIGN_N) {
841 if (h_mode == ALIGN_N) {
842 msg = TgLoadCachedString(CSTID_PARANED_NONE);
843 } else {
844 msg = TgLoadString(STID_DISTR_VERTEX_HORI);
845 }
846 } else {
847 if (h_mode == ALIGN_N) {
848 msg = TgLoadString(STID_DISTR_VERTEX_VERT);
849 } else {
850 msg = TgLoadString(STID_DISTR_VERTEX_VERT_AND_HORI);
851 }
852 }
853 } else {
854 msg = DistrDirectLoadString(i);
855 }
856 psz = UtilStrDup(msg);
857 if (psz == NULL) FailAllocMessage();
858 return psz;
859 }
860
CreateDistributeDirectMenu(parent_menu,x,y,menu_info,status_str_xlated)861 TgMenu *CreateDistributeDirectMenu(parent_menu, x, y, menu_info,
862 status_str_xlated)
863 TgMenu *parent_menu;
864 int x, y;
865 TgMenuInfo *menu_info;
866 int status_str_xlated; /* ignored, always 0 */
867 {
868 int i=0, num_entries=(MAXALIGNS*MAXALIGNS);
869 TgMenu *menu=NULL;
870 TgMenuInfo stMenuInfo;
871 TgMenuItemInfo *item_info=NULL;
872
873 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
874 stMenuInfo.items = (TgMenuItemInfo*)malloc(
875 (num_entries+1)*sizeof(TgMenuItemInfo));
876 if (stMenuInfo.items == NULL) FailAllocMessage();
877 memset(stMenuInfo.items, 0,
878 (num_entries+1)*sizeof(TgMenuItemInfo));
879 for (item_info=stMenuInfo.items, i=0; i < num_entries; item_info++, i++) {
880 item_info->menu_str = (char*)(Pixmap*)(&distrDirectPixmap[i]);
881 item_info->shortcut_str = NULL;
882 item_info->status_str = GetDistrDirectMenuStr(i);
883 item_info->submenu_info = NULL;
884 item_info->cmdid = CMDID_DISTRIBUTEDIRECT;
885 }
886 stMenuInfo.items[num_entries].cmdid = INVALID;
887
888 /* the status_str has been translated in GetDistrDirectMenuStr() */
889 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
890 for (item_info=stMenuInfo.items, i=0; i < num_entries; item_info++, i++) {
891 UtilFree(item_info->status_str);
892 }
893 memset(stMenuInfo.items, 0, (num_entries+1)*sizeof(TgMenuItemInfo));
894 free(stMenuInfo.items);
895 stMenuInfo.items = NULL;
896 if (menu != NULL) {
897 menu->track_menubar = TRUE;
898 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, MAXALIGNS);
899 }
900 return menu;
901 }
902
903 static
AutoJustifiable(obj_ptr)904 int AutoJustifiable(obj_ptr)
905 struct ObjRec *obj_ptr;
906 {
907 struct TextRec *text_ptr;
908 int auto_justifiable=TRUE, just;
909
910 if (obj_ptr->type!=OBJ_TEXT || obj_ptr->detail.t->lines!=1) return FALSE;
911 if (obj_ptr->ctm != NULL) return FALSE;
912
913 text_ptr = obj_ptr->detail.t;
914 just = text_ptr->minilines.just;
915
916 if ((horiAlign==ALIGN_L && just==JUST_L) ||
917 (horiAlign==ALIGN_C && just==JUST_C) ||
918 (horiAlign==ALIGN_R && just==JUST_R)) {
919 auto_justifiable = FALSE;
920 }
921 return auto_justifiable;
922 }
923
924 static
AutoJustify(obj_ptr)925 void AutoJustify(obj_ptr)
926 struct ObjRec *obj_ptr;
927 {
928 struct TextRec *text_ptr;
929 int new_ltx, new_lty, dx, dy, ltx, lty;
930
931 text_ptr = obj_ptr->detail.t;
932
933 ltx = obj_ptr->obbox.ltx; lty = obj_ptr->obbox.lty;
934 switch (horiAlign) {
935 case ALIGN_L: text_ptr->minilines.just = JUST_L; break;
936 case ALIGN_C: text_ptr->minilines.just = JUST_C; break;
937 case ALIGN_R: text_ptr->minilines.just = JUST_R; break;
938 }
939 UpdTextBBox(obj_ptr);
940 dx = dy = 0;
941 new_ltx = obj_ptr->obbox.ltx; new_lty = obj_ptr->obbox.lty;
942 dx = ltx-new_ltx;
943
944 if (text_ptr->cached_bitmap != None) {
945 XFreePixmap(mainDisplay, text_ptr->cached_bitmap);
946 }
947 text_ptr->cached_zoom = 0;
948 text_ptr->cached_bitmap = None;
949
950 MoveObj(obj_ptr, dx, dy);
951 }
952
AlignSelObjs()953 void AlignSelObjs()
954 {
955 register int x=0, y=0, i;
956 struct SelRec *sel_ptr=NULL;
957 struct ObjRec *obj_ptr=NULL;
958 struct VSelRec *vsel_ptr=NULL;
959 int pivot_x=0, pivot_y=0, auto_justifiable=FALSE;
960 int dx=0, dy=0, ltx=0, lty=0, rbx=0, rby=0;
961
962 if (topSel == NULL && topVSel == NULL) return;
963
964 if (curChoice == VERTEXMODE) {
965 int changed=FALSE, n=0, first_time=TRUE, start;
966 IntPoint *vlist=NULL;
967
968 if (topVSel!=NULL && (topVSel->next!=NULL || topVSel->n>=3 ||
969 (topVSel->n==2 &&
970 !(topVSel->obj->type==OBJ_POLYGON && topVSel->v_index[0]==0))) &&
971 horiAlign!=ALIGN_N && horiAlign!=ALIGN_S &&
972 vertAlign!=ALIGN_N && vertAlign!=ALIGN_S) {
973 if (MsgBox(TgLoadString(STID_MOVE_ALL_VERTICES_YNC),
974 TOOL_NAME, YNC_MB) != MB_ID_YES) {
975 return;
976 }
977 }
978 StartCompositeCmd();
979 HighLightReverse();
980 for (vsel_ptr = topVSel; vsel_ptr != NULL; vsel_ptr = vsel_ptr->next) {
981 if (first_time) {
982 first_time = FALSE;
983 ltx = vsel_ptr->x[0]; lty = vsel_ptr->y[0];
984 rbx = vsel_ptr->x[0]; rby = vsel_ptr->y[0];
985 start = 1;
986 } else {
987 start = 0;
988 }
989 for (i = start; i < vsel_ptr->n; i++) {
990 if (vsel_ptr->x[i] < ltx) ltx = vsel_ptr->x[i];
991 if (vsel_ptr->y[i] < lty) lty = vsel_ptr->y[i];
992 if (vsel_ptr->x[i] > rbx) rbx = vsel_ptr->x[i];
993 if (vsel_ptr->y[i] > rby) rby = vsel_ptr->y[i];
994 }
995 }
996 switch (horiAlign) {
997 case ALIGN_L: pivot_x = ltx; break;
998 case ALIGN_C: pivot_x = (ltx + rbx) / 2; break;
999 case ALIGN_R: pivot_x = rbx; break;
1000 }
1001 switch (vertAlign) {
1002 case ALIGN_T: pivot_y = lty; break;
1003 case ALIGN_M: pivot_y = (lty + rby) / 2; break;
1004 case ALIGN_B: pivot_y = rby; break;
1005 }
1006
1007 for (vsel_ptr = topVSel; vsel_ptr != NULL; vsel_ptr = vsel_ptr->next) {
1008 StretchStructuredSplineInfo sssi;
1009 int curved=(-1), ssn=(-1);
1010 IntPoint *ssvlist=NULL;
1011 struct PolyRec *poly_ptr=NULL;
1012 struct PolygonRec *polygon_ptr=NULL;
1013
1014 memset(&sssi, 0, sizeof(StretchStructuredSplineInfo));
1015 obj_ptr = vsel_ptr->obj;
1016 switch (obj_ptr->type) {
1017 case OBJ_POLY:
1018 poly_ptr = obj_ptr->detail.p;
1019 curved = poly_ptr->curved;
1020 n = poly_ptr->n;
1021 vlist = poly_ptr->vlist;
1022 if (curved == LT_STRUCT_SPLINE) {
1023 ssn = poly_ptr->ssn;
1024 ssvlist = poly_ptr->ssvlist;
1025 SetIPTInfoForStretchPoly(vsel_ptr->v_index[0], n, vlist, &sssi);
1026 }
1027 break;
1028 case OBJ_POLYGON:
1029 polygon_ptr = obj_ptr->detail.g;
1030 curved = polygon_ptr->curved;
1031 n = polygon_ptr->n;
1032 vlist = polygon_ptr->vlist;
1033 if (curved == LT_STRUCT_SPLINE) {
1034 ssn = polygon_ptr->ssn;
1035 ssvlist = polygon_ptr->ssvlist;
1036 SetIPTInfoForStretchPolygon(vsel_ptr->v_index[0], n, vlist,
1037 &sssi);
1038 }
1039 break;
1040 }
1041 PrepareToReplaceAnObj(obj_ptr);
1042 for (i=0; i < vsel_ptr->n; i++) {
1043 int abs_dx=0, abs_dy=0;
1044
1045 if (horiAlign!=ALIGN_N && horiAlign!=ALIGN_S &&
1046 vsel_ptr->x[i]!=pivot_x) {
1047 changed = TRUE;
1048 abs_dx = pivot_x - vsel_ptr->x[i];
1049 }
1050 if (vertAlign!=ALIGN_N && vertAlign!=ALIGN_S &&
1051 vsel_ptr->y[i]!=pivot_y) {
1052 changed = TRUE;
1053 abs_dy = pivot_y - vsel_ptr->y[i];
1054 }
1055 if (changed) {
1056 if (obj_ptr->ctm == NULL) {
1057 vsel_ptr->x[i] = pivot_x;
1058 vsel_ptr->y[i] = pivot_y;
1059 if (curved == LT_STRUCT_SPLINE) {
1060 /*
1061 * don't do anything here, will be handled in
1062 * FinishMoveVertexForStretchStructSpline();
1063 */
1064 } else {
1065 vlist[vsel_ptr->v_index[i]].x = pivot_x;
1066 vlist[vsel_ptr->v_index[i]].y = pivot_y;
1067 }
1068 } else {
1069 int tmp_x=0, tmp_y=0, tmp_x2=0, tmp_y2=0;
1070
1071 ReverseTransformPointThroughCTM(
1072 pivot_x-obj_ptr->x, pivot_y-obj_ptr->y, obj_ptr->ctm,
1073 &tmp_x, &tmp_y);
1074 if (curved == LT_STRUCT_SPLINE) {
1075 /*
1076 * don't do anything here, will be handled in
1077 * FinishMoveVertexForStretchStructSpline();
1078 */
1079 } else {
1080 dx = tmp_x + obj_ptr->x - vlist[vsel_ptr->v_index[i]].x;
1081 dy = tmp_y + obj_ptr->y - vlist[vsel_ptr->v_index[i]].y;
1082 vlist[vsel_ptr->v_index[i]].x = tmp_x + obj_ptr->x;
1083 vlist[vsel_ptr->v_index[i]].y = tmp_y + obj_ptr->y;
1084 }
1085 TransformPointThroughCTM(tmp_x, tmp_y, obj_ptr->ctm,
1086 &tmp_x2, &tmp_y2);
1087 vsel_ptr->x[i] = tmp_x2 + obj_ptr->x;
1088 vsel_ptr->y[i] = tmp_y2 + obj_ptr->y;
1089 }
1090 }
1091 if (curved == LT_STRUCT_SPLINE) {
1092 FinishMoveVertexForStretchStructSpline(vsel_ptr, abs_dx, abs_dy,
1093 &sssi);
1094 }
1095 }
1096 if (changed) {
1097 AdjObjSplineVs(obj_ptr);
1098 UpdNonIntSplinePolyBBox(obj_ptr, n, vlist);
1099 RecordReplaceAnObj(obj_ptr);
1100 } else {
1101 AbortPrepareCmd(CMD_REPLACE);
1102 }
1103 }
1104 EndCompositeCmd();
1105 } else {
1106 struct SubCmdRec *sub_cmd=NULL;
1107 struct SelRec *tmp_sel_ptr=NULL;
1108 struct ObjRec *locked_obj=NULL;
1109 char *psz=NULL;
1110
1111 if (numObjLocked > 1) {
1112 MsgBox(TgLoadString(STID_CANNOT_ALIGN_OBJS_TOO_MANY), TOOL_NAME,
1113 INFO_MB);
1114 return;
1115 } else if (numObjLocked == 1) {
1116 for (sel_ptr=topSel; sel_ptr!=NULL; sel_ptr=sel_ptr->next) {
1117 if (sel_ptr->obj->locked) {
1118 locked_obj = sel_ptr->obj;
1119 break;
1120 }
1121 }
1122 }
1123 tmp_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1124 if (tmp_sel_ptr == NULL) FailAllocMessage();
1125 tmp_sel_ptr->next = tmp_sel_ptr->prev = NULL;
1126
1127 sub_cmd = (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
1128 if (sub_cmd == NULL) FailAllocMessage();
1129 memset(sub_cmd, 0, sizeof(struct SubCmdRec));
1130
1131 StartCompositeCmd();
1132 HighLightReverse();
1133 switch (horiAlign) {
1134 case ALIGN_L:
1135 pivot_x = (locked_obj==NULL) ? selObjLtX : locked_obj->obbox.ltx;
1136 break;
1137 case ALIGN_C:
1138 pivot_x = (locked_obj==NULL) ? ((selObjLtX+selObjRbX)>>1) :
1139 ((locked_obj->obbox.ltx+locked_obj->obbox.rbx)>>1);
1140 break;
1141 case ALIGN_R:
1142 pivot_x = (locked_obj==NULL) ? selObjRbX : locked_obj->obbox.rbx;
1143 break;
1144 }
1145 switch (vertAlign) {
1146 case ALIGN_T:
1147 pivot_y = (locked_obj==NULL) ? selObjLtY : locked_obj->obbox.lty;
1148 break;
1149 case ALIGN_M:
1150 pivot_y = (locked_obj==NULL) ? ((selObjLtY+selObjRbY)>>1) :
1151 ((locked_obj->obbox.lty+locked_obj->obbox.rby)>>1);
1152 break;
1153 case ALIGN_B:
1154 pivot_y = (locked_obj==NULL) ? selObjRbY : locked_obj->obbox.rby;
1155 break;
1156 }
1157
1158 for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next) {
1159 obj_ptr = sel_ptr->obj;
1160 if (obj_ptr->locked) continue;
1161
1162 if ((auto_justifiable = AutoJustifiable(obj_ptr))) {
1163 PrepareToReplaceAnObj(obj_ptr);
1164 AutoJustify(obj_ptr);
1165 }
1166 switch (horiAlign) {
1167 case ALIGN_L: x = obj_ptr->obbox.ltx; break;
1168 case ALIGN_C: x = (obj_ptr->obbox.ltx+obj_ptr->obbox.rbx)/2; break;
1169 case ALIGN_R: x = obj_ptr->obbox.rbx; break;
1170 }
1171 switch (vertAlign) {
1172 case ALIGN_T: y = obj_ptr->obbox.lty; break;
1173 case ALIGN_M: y = (obj_ptr->obbox.lty+obj_ptr->obbox.rby)/2; break;
1174 case ALIGN_B: y = obj_ptr->obbox.rby; break;
1175 }
1176 if (horiAlign==ALIGN_N || horiAlign==ALIGN_S) x = pivot_x;
1177 if (vertAlign==ALIGN_N || vertAlign==ALIGN_S) y = pivot_y;
1178
1179 dx = pivot_x - x;
1180 dy = pivot_y - y;
1181 if (dx != 0 || dy != 0) {
1182 if (auto_justifiable) {
1183 MoveObj(obj_ptr, dx, dy);
1184 RecordReplaceAnObj(obj_ptr);
1185 } else {
1186 sub_cmd->detail.move.dx = dx;
1187 sub_cmd->detail.move.dy = dy;
1188 tmp_sel_ptr->obj = obj_ptr;
1189 PrepareToRecord(CMD_MOVE, tmp_sel_ptr, tmp_sel_ptr, 1);
1190 RecordCmd(CMD_MOVE, sub_cmd, NULL, NULL, 0);
1191
1192 MoveObj(obj_ptr, dx, dy);
1193 }
1194 } else if (auto_justifiable) {
1195 RecordReplaceAnObj(obj_ptr);
1196 }
1197 }
1198 EndCompositeCmd();
1199
1200 free(sub_cmd);
1201 free(tmp_sel_ptr);
1202
1203 psz = AlignedLoadString(horiAlign, vertAlign);
1204 if (psz != NULL) Msg(psz);
1205 }
1206 ltx = selLtX; lty = selLtY; rbx = selRbX, rby = selRbY;
1207 UpdSelBBox();
1208 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1209 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1210 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1211 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1212 HighLightForward();
1213 SetFileModified(TRUE);
1214 justDupped = FALSE;
1215 }
1216
AlignSelToPage()1217 void AlignSelToPage()
1218 {
1219 int i=0;
1220 struct SelRec *sel_ptr=NULL;
1221 struct ObjRec *obj_ptr=NULL;
1222 struct VSelRec *vsel_ptr=NULL;
1223 int pivot_x=0, pivot_y=0, dx=0, dy=0, ltx=0, lty=0, rbx=0, rby=0;
1224
1225 if (topSel == NULL && topVSel == NULL) return;
1226
1227 if (curChoice == VERTEXMODE) {
1228 int changed=FALSE, n=0;
1229 IntPoint *vlist=NULL;
1230
1231 if (topVSel!=NULL && (topVSel->next!=NULL || topVSel->n>=3 ||
1232 (topVSel->n==2 &&
1233 !(topVSel->obj->type==OBJ_POLYGON && topVSel->v_index[0]==0))) &&
1234 horiAlign!=ALIGN_N && horiAlign!=ALIGN_S &&
1235 vertAlign!=ALIGN_N && vertAlign!=ALIGN_S) {
1236 if (MsgBox(TgLoadString(STID_MOVE_ALL_VERTICES_YNC), TOOL_NAME,
1237 YNC_MB) != MB_ID_YES) {
1238 return;
1239 }
1240 }
1241 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
1242 sel_ptr->obj->userdata = NULL;
1243 }
1244 StartCompositeCmd();
1245 HighLightReverse();
1246
1247 switch (horiAlign) {
1248 case ALIGN_L: pivot_x = 0; break;
1249 case ALIGN_C: pivot_x = paperWidth / 2; break;
1250 case ALIGN_R: pivot_x = paperWidth; break;
1251 }
1252 switch (vertAlign) {
1253 case ALIGN_T: pivot_y = 0; break;
1254 case ALIGN_M: pivot_y = paperHeight / 2; break;
1255 case ALIGN_B: pivot_y = paperHeight; break;
1256 }
1257 for (vsel_ptr=topVSel; vsel_ptr != NULL; vsel_ptr=vsel_ptr->next) {
1258 obj_ptr = vsel_ptr->obj;
1259 SetSSSIForDistr(obj_ptr, vsel_ptr, FALSE);
1260
1261 switch (obj_ptr->type) {
1262 case OBJ_POLY:
1263 n = obj_ptr->detail.p->n;
1264 vlist = obj_ptr->detail.p->vlist;
1265 break;
1266 case OBJ_POLYGON:
1267 n = obj_ptr->detail.g->n;
1268 vlist = obj_ptr->detail.g->vlist;
1269 break;
1270 }
1271 PrepareToReplaceAnObj(obj_ptr);
1272 for (i = 0; i < vsel_ptr->n; i++) {
1273 if (horiAlign!=ALIGN_N && horiAlign!=ALIGN_S &&
1274 vsel_ptr->x[i]!=pivot_x) {
1275 changed = TRUE;
1276 if (obj_ptr->userdata != NULL) {
1277 StretchStructuredSplineInfo *psssi=
1278 (StretchStructuredSplineInfo *)obj_ptr->userdata;
1279
1280 if (obj_ptr->ctm == NULL) {
1281 psssi->new_abs_x = pivot_x;
1282 psssi->abs_dx = pivot_x - psssi->orig_abs_x;
1283 } else {
1284 psssi->rotated_new_abs_x = pivot_x;
1285 psssi->rotated_abs_dx = pivot_x -
1286 psssi->rotated_orig_abs_x;
1287 }
1288 } else {
1289 vlist[vsel_ptr->v_index[i]].x = pivot_x;
1290 }
1291 vsel_ptr->x[i] = pivot_x;
1292 }
1293 if (vertAlign!=ALIGN_N && vertAlign!=ALIGN_S &&
1294 vsel_ptr->y[i]!=pivot_y) {
1295 changed = TRUE;
1296 if (obj_ptr->userdata != NULL) {
1297 StretchStructuredSplineInfo *psssi=
1298 (StretchStructuredSplineInfo *)obj_ptr->userdata;
1299
1300 if (obj_ptr->ctm == NULL) {
1301 psssi->new_abs_y = pivot_y;
1302 psssi->abs_dy = pivot_y - psssi->orig_abs_y;
1303 } else {
1304 psssi->rotated_new_abs_y = pivot_y;
1305 psssi->rotated_abs_dy = pivot_y -
1306 psssi->rotated_orig_abs_y;
1307 }
1308 } else {
1309 vlist[vsel_ptr->v_index[i]].y = pivot_y;
1310 }
1311 vsel_ptr->y[i] = pivot_y;
1312 }
1313 if (obj_ptr->userdata != NULL) {
1314 StretchStructuredSplineInfo *psssi=
1315 (StretchStructuredSplineInfo *)obj_ptr->userdata;
1316
1317 if (changed) {
1318 if (obj_ptr->ctm == NULL) {
1319 FinishMoveVertexForStretchStructSpline(vsel_ptr,
1320 psssi->abs_dx, psssi->abs_dy, psssi);
1321 } else {
1322 FinishMoveVertexForStretchStructSpline(vsel_ptr,
1323 psssi->rotated_abs_dx, psssi->rotated_abs_dy, psssi);
1324 }
1325 }
1326 free(psssi);
1327 obj_ptr->userdata = NULL;
1328 }
1329 }
1330 if (changed) {
1331 AdjObjSplineVs(obj_ptr);
1332 UpdNonIntSplinePolyBBox(obj_ptr, n, vlist);
1333 RecordReplaceAnObj(obj_ptr);
1334 } else {
1335 AbortPrepareCmd(CMD_REPLACE);
1336 }
1337 }
1338 EndCompositeCmd();
1339 } else {
1340 HighLightReverse();
1341 dx = dy = 0;
1342 switch (horiAlign) {
1343 case ALIGN_L: dx = 0 - selLtX; break;
1344 case ALIGN_C: dx = (paperWidth>>1) - ((selRbX+selLtX)>>1); break;
1345 case ALIGN_R: dx = paperWidth - selRbX; break;
1346 }
1347 switch (vertAlign) {
1348 case ALIGN_T: dy = 0 - selLtY; break;
1349 case ALIGN_M: dy = (paperHeight>>1) - ((selRbY+selLtY)>>1); break;
1350 case ALIGN_B: dy = paperHeight - selRbY; break;
1351 }
1352 if (dx != 0 || dy != 0) {
1353 struct SubCmdRec *sub_cmd=NULL;
1354
1355 sub_cmd = (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
1356 if (sub_cmd == NULL) FailAllocMessage();
1357 memset(sub_cmd, 0, sizeof(struct SubCmdRec));
1358
1359 sub_cmd->detail.move.dx = dx;
1360 sub_cmd->detail.move.dy = dy;
1361
1362 PrepareToRecord(CMD_MOVE, topSel, botSel, numObjSelected);
1363 RecordCmd(CMD_MOVE, sub_cmd, NULL, NULL, 0);
1364 for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next) {
1365 if (!sel_ptr->obj->locked) {
1366 MoveObj(sel_ptr->obj, dx, dy);
1367 }
1368 }
1369 free(sub_cmd);
1370 }
1371 }
1372 ltx = selLtX; lty = selLtY; rbx = selRbX, rby = selRbY;
1373 UpdSelBBox();
1374 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1375 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1376 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1377 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1378 HighLightForward();
1379 SetFileModified(TRUE);
1380 justDupped = FALSE;
1381 }
1382
AlignSelToGrid()1383 void AlignSelToGrid()
1384 {
1385 int x=0, y=0, i;
1386 struct ObjRec *obj_ptr=NULL;
1387 struct SelRec *sel_ptr=NULL;
1388 struct VSelRec *vsel_ptr=NULL;
1389 int grid_x, grid_y, dx, dy, ltx, lty, rbx, rby, auto_justifiable;
1390 int saved_draw_orig_x=0, saved_draw_orig_y=0;
1391
1392 if (topSel == NULL && topVSel == NULL) return;
1393
1394 StartCompositeCmd();
1395 HighLightReverse();
1396 if (curChoice == VERTEXMODE) {
1397 for (vsel_ptr = topVSel; vsel_ptr != NULL; vsel_ptr = vsel_ptr->next) {
1398 int changed=FALSE, n=0, ssn=(-1), curved=(-1);
1399 IntPoint *vlist=NULL, *ssvlist=NULL;
1400 struct PolyRec *poly_ptr=NULL;
1401 struct PolygonRec *polygon_ptr=NULL;
1402 StretchStructuredSplineInfo sssi;
1403
1404 memset(&sssi, 0, sizeof(StretchStructuredSplineInfo));
1405
1406 obj_ptr = vsel_ptr->obj;
1407 switch (obj_ptr->type) {
1408 case OBJ_POLY:
1409 poly_ptr = obj_ptr->detail.p;
1410 curved = poly_ptr->curved;
1411 n = poly_ptr->n;
1412 vlist = poly_ptr->vlist;
1413 if (curved == LT_STRUCT_SPLINE) {
1414 ssn = poly_ptr->ssn;
1415 ssvlist = poly_ptr->ssvlist;
1416 SetIPTInfoForStretchPoly(vsel_ptr->v_index[0], n, vlist, &sssi);
1417 }
1418 break;
1419 case OBJ_POLYGON:
1420 polygon_ptr = obj_ptr->detail.g;
1421 curved = polygon_ptr->curved;
1422 n = polygon_ptr->n;
1423 vlist = polygon_ptr->vlist;
1424 if (curved == LT_STRUCT_SPLINE) {
1425 ssn = polygon_ptr->ssn;
1426 ssvlist = polygon_ptr->ssvlist;
1427 SetIPTInfoForStretchPolygon(vsel_ptr->v_index[0], n, vlist,
1428 &sssi);
1429 }
1430 break;
1431 }
1432 PrepareToReplaceAnObj(obj_ptr);
1433
1434 saved_draw_orig_x = drawOrigX;
1435 saved_draw_orig_y = drawOrigY;
1436
1437 drawOrigX = drawOrigY = 0;
1438
1439 for (i = 0; i < vsel_ptr->n; i++) {
1440 if (horiAlign!=ALIGN_N && horiAlign!=ALIGN_S) x = vsel_ptr->x[i];
1441 if (vertAlign!=ALIGN_N && vertAlign!=ALIGN_S) y = vsel_ptr->y[i];
1442 if (zoomedIn) {
1443 GridXY(ZOOMED_SIZE(x), ZOOMED_SIZE(y), &grid_x, &grid_y);
1444 if (horiAlign==ALIGN_N || horiAlign==ALIGN_S) {
1445 x = ABS_SIZE(grid_x);
1446 }
1447 if (vertAlign==ALIGN_N || vertAlign==ALIGN_S) {
1448 y = ABS_SIZE(grid_y);
1449 }
1450 dx = ABS_SIZE(grid_x) - x;
1451 dy = ABS_SIZE(grid_y) - y;
1452 } else {
1453 GridXY(ZOOMED_SIZE(x), ZOOMED_SIZE(y), &grid_x, &grid_y);
1454 if (horiAlign==ALIGN_N || horiAlign==ALIGN_S) x = grid_x;
1455 if (vertAlign==ALIGN_N || vertAlign==ALIGN_S) y = grid_y;
1456
1457 dx = ABS_SIZE(grid_x) - x;
1458 dy = ABS_SIZE(grid_y) - y;
1459 }
1460 if (dx != 0 || dy != 0) {
1461 changed = TRUE;
1462 if (ssvlist != NULL) {
1463 /* LT_STRUCT_SPLINE */
1464 if (obj_ptr->ctm == NULL) {
1465 vsel_ptr->x[i] += dx;
1466 vsel_ptr->y[i] += dy;
1467 } else {
1468 int tmp_x=0, tmp_y=0, tmp_x2=0, tmp_y2=0;
1469
1470 /*
1471 * looks like of silly here, but it's to fix round-off
1472 * errors
1473 */
1474 ReverseTransformPointThroughCTM(
1475 vsel_ptr->x[i]+dx-obj_ptr->x,
1476 vsel_ptr->y[i]+dy-obj_ptr->y, obj_ptr->ctm,
1477 &tmp_x, &tmp_y);
1478 TransformPointThroughCTM(tmp_x, tmp_y, obj_ptr->ctm,
1479 &tmp_x2, &tmp_y2);
1480 vsel_ptr->x[i] = tmp_x2 + obj_ptr->x;
1481 vsel_ptr->y[i] = tmp_y2 + obj_ptr->y;
1482 }
1483 FinishMoveVertexForStretchStructSpline(vsel_ptr, dx, dy,
1484 &sssi);
1485 } else {
1486 if (obj_ptr->ctm == NULL) {
1487 vlist[vsel_ptr->v_index[i]].x += dx;
1488 vlist[vsel_ptr->v_index[i]].y += dy;
1489 vsel_ptr->x[i] += dx;
1490 vsel_ptr->y[i] += dy;
1491 } else {
1492 int tmp_x=0, tmp_y=0, tmp_x2=0, tmp_y2=0;
1493
1494 ReverseTransformPointThroughCTM(
1495 vsel_ptr->x[i]+dx-obj_ptr->x,
1496 vsel_ptr->y[i]+dy-obj_ptr->y, obj_ptr->ctm,
1497 &tmp_x, &tmp_y);
1498 vlist[vsel_ptr->v_index[i]].x = tmp_x+obj_ptr->x;
1499 vlist[vsel_ptr->v_index[i]].y = tmp_y+obj_ptr->y;
1500
1501 TransformPointThroughCTM(tmp_x, tmp_y, obj_ptr->ctm,
1502 &tmp_x2, &tmp_y2);
1503 vsel_ptr->x[i] = tmp_x2 + obj_ptr->x;
1504 vsel_ptr->y[i] = tmp_y2 + obj_ptr->y;
1505 }
1506 }
1507 }
1508 }
1509 drawOrigX = saved_draw_orig_x;
1510 drawOrigY = saved_draw_orig_y;
1511
1512 if (changed) {
1513 AdjObjSplineVs(obj_ptr);
1514 UpdNonIntSplinePolyBBox(obj_ptr, n, vlist);
1515 RecordReplaceAnObj(obj_ptr);
1516 } else {
1517 AbortPrepareCmd(CMD_REPLACE);
1518 }
1519 }
1520 } else {
1521 struct SubCmdRec *sub_cmd=NULL;
1522 struct SelRec *tmp_sel_ptr=NULL;
1523
1524 tmp_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1525 if (tmp_sel_ptr == NULL) FailAllocMessage();
1526 tmp_sel_ptr->next = tmp_sel_ptr->prev = NULL;
1527
1528 sub_cmd = (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
1529 if (sub_cmd == NULL) FailAllocMessage();
1530 memset(sub_cmd, 0, sizeof(struct SubCmdRec));
1531
1532 for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next) {
1533 obj_ptr = sel_ptr->obj;
1534 if (obj_ptr->locked) continue;
1535
1536 if ((auto_justifiable=AutoJustifiable(obj_ptr))) {
1537 PrepareToReplaceAnObj(obj_ptr);
1538 AutoJustify(obj_ptr);
1539 }
1540 switch (horiAlign) {
1541 case ALIGN_L: x = obj_ptr->obbox.ltx; break;
1542 case ALIGN_C: x = (obj_ptr->obbox.ltx+obj_ptr->obbox.rbx)/2; break;
1543 case ALIGN_R: x = obj_ptr->obbox.rbx; break;
1544 }
1545 switch (vertAlign) {
1546 case ALIGN_T: y = obj_ptr->obbox.lty; break;
1547 case ALIGN_M: y = (obj_ptr->obbox.lty+obj_ptr->obbox.rby)/2; break;
1548 case ALIGN_B: y = obj_ptr->obbox.rby; break;
1549 }
1550 saved_draw_orig_x = drawOrigX;
1551 saved_draw_orig_y = drawOrigY;
1552
1553 drawOrigX = drawOrigY = 0;
1554
1555 if (zoomedIn) {
1556 GridXY(ZOOMED_SIZE(x), ZOOMED_SIZE(y), &grid_x, &grid_y);
1557 if (horiAlign==ALIGN_N || horiAlign==ALIGN_S) x = ABS_SIZE(grid_x);
1558 if (vertAlign==ALIGN_N || vertAlign==ALIGN_S) y = ABS_SIZE(grid_y);
1559
1560 dx = ABS_SIZE(grid_x) - x;
1561 dy = ABS_SIZE(grid_y) - y;
1562 } else {
1563 GridXY(ZOOMED_SIZE(x), ZOOMED_SIZE(y), &grid_x, &grid_y);
1564 if (horiAlign==ALIGN_N || horiAlign==ALIGN_S) x = grid_x;
1565 if (vertAlign==ALIGN_N || vertAlign==ALIGN_S) y = grid_y;
1566
1567 dx = ABS_SIZE(grid_x) - x;
1568 dy = ABS_SIZE(grid_y) - y;
1569 }
1570 drawOrigX = saved_draw_orig_x;
1571 drawOrigY = saved_draw_orig_y;
1572
1573 if (dx != 0 || dy != 0) {
1574 if (auto_justifiable) {
1575 MoveObj(obj_ptr, dx, dy);
1576 RecordReplaceAnObj(obj_ptr);
1577 } else {
1578 sub_cmd->detail.move.dx = dx;
1579 sub_cmd->detail.move.dy = dy;
1580 tmp_sel_ptr->obj = obj_ptr;
1581 PrepareToRecord(CMD_MOVE, tmp_sel_ptr, tmp_sel_ptr, 1);
1582 RecordCmd(CMD_MOVE, sub_cmd, NULL, NULL, 0);
1583
1584 MoveObj(obj_ptr, dx, dy);
1585 }
1586 } else if (auto_justifiable) {
1587 RecordReplaceAnObj(obj_ptr);
1588 }
1589 }
1590 free(sub_cmd);
1591 free(tmp_sel_ptr);
1592 }
1593 EndCompositeCmd();
1594
1595 ltx = selLtX; lty = selLtY; rbx = selRbX, rby = selRbY;
1596 UpdSelBBox();
1597 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1598 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1599 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1600 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1601 HighLightForward();
1602 SetFileModified(TRUE);
1603 justDupped = FALSE;
1604 }
1605
HoriAlignSubMenu(index)1606 void HoriAlignSubMenu(index)
1607 int index;
1608 {
1609 char *psz=NULL;
1610
1611 horiAlign = index;
1612 psz = HoriAlignLoadString(horiAlign);
1613 if (psz != NULL) Msg(psz);
1614 ShowHoriAlign();
1615 UpdatePinnedMenu(MENU_HORIALIGN);
1616 }
1617
RefreshHoriAlignMenu(menu)1618 void RefreshHoriAlignMenu(menu)
1619 TgMenu *menu;
1620 {
1621 int i, num_items=menu->num_items;
1622 TgMenuItem *menuitems=menu->menuitems;
1623
1624 for (i=0; i < num_items; i++) {
1625 TgMenuItem *menu_item=(&menuitems[i]);
1626 TgMenuItem stMenuItem;
1627
1628 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1629 stMenuItem.state = TGBS_NORMAL;
1630 stMenuItem.checked = (i == horiAlign);
1631 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
1632 &stMenuItem);
1633 }
1634 }
1635
CreateHoriAlignMenu(parent_menu,x,y,menu_info,status_str_xlated)1636 TgMenu *CreateHoriAlignMenu(parent_menu, x, y, menu_info, status_str_xlated)
1637 TgMenu *parent_menu;
1638 int x, y;
1639 TgMenuInfo *menu_info;
1640 int status_str_xlated; /* ignored, always 0 */
1641 {
1642 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1643
1644 if (menu != NULL) {
1645 TgMenuItem *menu_item=NULL;
1646 TgMenuItem stMenuItem;
1647
1648 menu->track_menubar = TRUE;
1649 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, MAXALIGNS);
1650 menu_item = (&menu->menuitems[horiAlign]);
1651
1652 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1653 stMenuItem.checked = TRUE;
1654 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
1655 return TgDestroyMenu(menu, TRUE);
1656 }
1657 menu->refresh_proc = ((RefreshMenuFunc*)RefreshHoriAlignMenu);
1658 }
1659 return menu;
1660 }
1661
HoriAlignMenu(X,Y,TrackMenubar)1662 int HoriAlignMenu(X, Y, TrackMenubar)
1663 int X, Y, TrackMenubar;
1664 {
1665 int rc=INVALID;
1666 TgMenu *menu=(horiAlignMenuInfo.create_proc)(NULL, X, Y, &horiAlignMenuInfo,
1667 INVALID);
1668
1669 activeMenu = MENU_HORIALIGN;
1670 if (menu != NULL) {
1671 menu->track_menubar = TrackMenubar;
1672
1673 rc = TgMenuLoop(menu);
1674 TgDestroyMenu(menu, TRUE);
1675 }
1676 return rc;
1677 }
1678
VertAlignSubMenu(index)1679 void VertAlignSubMenu(index)
1680 int index;
1681 {
1682 char *psz=NULL;
1683
1684 vertAlign = index;
1685 psz = VertAlignLoadString(vertAlign);
1686 if (psz != NULL) Msg(psz);
1687 ShowVertAlign();
1688 UpdatePinnedMenu(MENU_VERTALIGN);
1689 }
1690
RefreshVertAlignMenu(menu)1691 void RefreshVertAlignMenu(menu)
1692 TgMenu *menu;
1693 {
1694 int i, num_items=menu->num_items;
1695 TgMenuItem *menuitems=menu->menuitems;
1696
1697 for (i=0; i < num_items; i++) {
1698 TgMenuItem *menu_item=(&menuitems[i]);
1699 TgMenuItem stMenuItem;
1700
1701 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1702 stMenuItem.state = TGBS_NORMAL;
1703 stMenuItem.checked = (i == vertAlign);
1704 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
1705 &stMenuItem);
1706 }
1707 }
1708
CreateVertAlignMenu(parent_menu,x,y,menu_info,status_str_xlated)1709 TgMenu *CreateVertAlignMenu(parent_menu, x, y, menu_info, status_str_xlated)
1710 TgMenu *parent_menu;
1711 int x, y;
1712 TgMenuInfo *menu_info;
1713 int status_str_xlated; /* ignored, always 0 */
1714 {
1715 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1716
1717 if (menu != NULL) {
1718 TgMenuItem *menu_item=NULL;
1719 TgMenuItem stMenuItem;
1720
1721 menu->track_menubar = TRUE;
1722 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, MAXALIGNS);
1723 menu_item = (&menu->menuitems[vertAlign]);
1724
1725 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1726 stMenuItem.checked = TRUE;
1727 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
1728 return TgDestroyMenu(menu, TRUE);
1729 }
1730 menu->refresh_proc = ((RefreshMenuFunc*)RefreshVertAlignMenu);
1731 }
1732 return menu;
1733 }
1734
VertAlignMenu(X,Y,TrackMenubar)1735 int VertAlignMenu(X, Y, TrackMenubar)
1736 int X, Y, TrackMenubar;
1737 {
1738 int rc=INVALID;
1739 TgMenu *menu=(vertAlignMenuInfo.create_proc)(NULL, X, Y, &vertAlignMenuInfo,
1740 INVALID);
1741
1742 activeMenu = MENU_VERTALIGN;
1743 if (menu != NULL) {
1744 menu->track_menubar = TrackMenubar;
1745
1746 rc = TgMenuLoop(menu);
1747 TgDestroyMenu(menu, TRUE);
1748 }
1749 return rc;
1750 }
1751
AlignDirect(alignment)1752 void AlignDirect(alignment)
1753 int alignment;
1754 {
1755 int saved_h_align=horiAlign, saved_v_align=vertAlign;
1756 int v_align=(alignment%(MAXALIGNS-1));
1757 int h_align=((alignment-v_align)/(MAXALIGNS-1));
1758
1759 horiAlign = h_align;
1760 vertAlign = v_align;
1761 switch (alignDirectType) {
1762 case ALIGN_OBJS_DIRECT: AlignSelObjs(); break;
1763 case ALIGN_TO_GRID_DIRECT: AlignSelToGrid(); break;
1764 case ALIGN_TO_PAGE_DIRECT: AlignSelToPage(); break;
1765 }
1766 horiAlign = saved_h_align;
1767 vertAlign = saved_v_align;
1768 }
1769
1770 static
GetAlignDirectMenuStr(i)1771 char *GetAlignDirectMenuStr(i)
1772 int i;
1773 /* returned string has been translated */
1774 {
1775 char *psz=NULL, *msg=NULL;
1776
1777 if (curChoice == VERTEXMODE) {
1778 if (alignDirectType == ALIGN_TO_PAGE_DIRECT) {
1779 if (i == 0) {
1780 msg = TgLoadCachedString(CSTID_PARANED_NONE);
1781 } else {
1782 msg = AlignVerticesDirectToPageLoadString(i);
1783 }
1784 } else {
1785 int v_align=(i%(MAXALIGNS-1));
1786 int h_align=((i-v_align)/(MAXALIGNS-1));
1787
1788 if (v_align == ALIGN_N) {
1789 if (h_align == ALIGN_N) {
1790 msg = TgLoadCachedString(CSTID_PARANED_NONE);
1791 } else {
1792 msg = (alignDirectType==ALIGN_TO_GRID_DIRECT ?
1793 TgLoadString(STID_ALIGN_VERTICES_HORI_TO_GRID) :
1794 TgLoadString(STID_ALIGN_VERTICES_VERT));
1795 }
1796 } else {
1797 if (h_align == ALIGN_N) {
1798 msg = (alignDirectType==ALIGN_TO_GRID_DIRECT ?
1799 TgLoadString(STID_ALIGN_VERTICES_VERT_TO_GRID) :
1800 TgLoadString(STID_ALIGN_VERTICES_HORI));
1801 } else {
1802 msg = (alignDirectType==ALIGN_TO_GRID_DIRECT ?
1803 TgLoadString(STID_ALIGN_VERTICES_TO_GRID) :
1804 TgLoadString(STID_ALIGN_VERTICES));
1805 }
1806 }
1807 }
1808 } else {
1809 if (alignDirectType == ALIGN_TO_PAGE_DIRECT) {
1810 if (i == 0) {
1811 msg = TgLoadCachedString(CSTID_PARANED_NONE);
1812 } else {
1813 msg = AlignDirectToPageLoadString(i);
1814 }
1815 } else {
1816 if (i == 0) {
1817 msg = TgLoadCachedString(CSTID_PARANED_NONE);
1818 } else if (alignDirectType == ALIGN_TO_GRID_DIRECT) {
1819 msg = AlignDirectToGridLoadString(i);
1820 } else {
1821 msg = AlignDirectLoadString(i);
1822 }
1823 }
1824 }
1825 psz = UtilStrDup(msg);
1826 if (psz == NULL) FailAllocMessage();
1827 return psz;
1828 }
1829
1830 static
CreateAlignDirectMenu(parent_menu,x,y,menu_info)1831 TgMenu *CreateAlignDirectMenu(parent_menu, x, y, menu_info)
1832 TgMenu *parent_menu;
1833 int x, y;
1834 TgMenuInfo *menu_info;
1835 {
1836 int i=0, num_entries=((MAXALIGNS-1)*(MAXALIGNS-1));
1837 TgMenu *menu=NULL;
1838 TgMenuInfo stMenuInfo;
1839 TgMenuItemInfo *item_info=NULL;
1840
1841 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
1842 stMenuInfo.items = (TgMenuItemInfo*)malloc(
1843 (num_entries+1)*sizeof(TgMenuItemInfo));
1844 if (stMenuInfo.items == NULL) FailAllocMessage();
1845 memset(stMenuInfo.items, 0, (num_entries+1)*sizeof(TgMenuItemInfo));
1846 for (item_info=stMenuInfo.items, i=0; i < num_entries; item_info++, i++) {
1847 item_info->menu_str = (char*)(Pixmap*)(&alignDirectPixmap[i]);
1848 item_info->shortcut_str = NULL;
1849 item_info->status_str = GetAlignDirectMenuStr(i);
1850 item_info->submenu_info = NULL;
1851 item_info->cmdid = CMDID_ALIGNDIRECT;
1852 }
1853 stMenuInfo.items[num_entries].cmdid = INVALID;
1854
1855 /* the status_str has been translated in GetAlignDirectMenuStr() */
1856 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
1857 for (item_info=stMenuInfo.items, i=0; i < num_entries; item_info++, i++) {
1858 UtilFree(item_info->status_str);
1859 }
1860 memset(stMenuInfo.items, 0, (num_entries+1)*sizeof(TgMenuItemInfo));
1861 free(stMenuInfo.items);
1862 stMenuInfo.items = NULL;
1863 if (menu != NULL) {
1864 menu->track_menubar = TRUE;
1865 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, (MAXALIGNS-1));
1866 }
1867 return menu;
1868 }
1869
CreateAlignObjsDirectMenu(parent_menu,x,y,menu_info,status_str_xlated)1870 TgMenu *CreateAlignObjsDirectMenu(parent_menu, x, y, menu_info,
1871 status_str_xlated)
1872 TgMenu *parent_menu;
1873 int x, y;
1874 TgMenuInfo *menu_info;
1875 int status_str_xlated; /* ignored, always 0 */
1876 {
1877 alignDirectType = ALIGN_OBJS_DIRECT;
1878 return CreateAlignDirectMenu(parent_menu, x, y, menu_info);
1879 }
1880
CreateAlignToGridDirectMenu(parent_menu,x,y,menu_info,status_str_xlated)1881 TgMenu *CreateAlignToGridDirectMenu(parent_menu, x, y, menu_info,
1882 status_str_xlated)
1883 TgMenu *parent_menu;
1884 int x, y;
1885 TgMenuInfo *menu_info;
1886 int status_str_xlated; /* ignored, always 0 */
1887 {
1888 alignDirectType = ALIGN_TO_GRID_DIRECT;
1889 return CreateAlignDirectMenu(parent_menu, x, y, menu_info);
1890 }
1891
CreateAlignToPageDirectMenu(parent_menu,x,y,menu_info,status_str_xlated)1892 TgMenu *CreateAlignToPageDirectMenu(parent_menu, x, y, menu_info,
1893 status_str_xlated)
1894 TgMenu *parent_menu;
1895 int x, y;
1896 TgMenuInfo *menu_info;
1897 int status_str_xlated; /* ignored, always 0 */
1898 {
1899 alignDirectType = ALIGN_TO_PAGE_DIRECT;
1900 return CreateAlignDirectMenu(parent_menu, x, y, menu_info);
1901 }
1902
CenterAnEndPoint()1903 void CenterAnEndPoint()
1904 {
1905 struct ObjRec *other_obj=NULL, *poly_obj=NULL;
1906 IntPoint *v;
1907 int cx, cy, x1, y1, xn, yn, d1, dn, n=0, index, x, y, tmp_x, tmp_y;
1908
1909 if (curChoice != NOTHING) return;
1910 if (topSel == NULL) {
1911 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
1912 return;
1913 }
1914 if (numObjSelected != 2 ||
1915 (!((topSel->obj->type == OBJ_POLY && botSel->obj->type != OBJ_POLY) ||
1916 (topSel->obj->type != OBJ_POLY && botSel->obj->type == OBJ_POLY)))) {
1917 MsgBox(TgLoadString(STID_SELECT_ONE_POLY_ONE_NON_POLY), TOOL_NAME,
1918 INFO_MB);
1919 return;
1920 }
1921 if (topSel->obj->type == OBJ_POLY) {
1922 poly_obj = topSel->obj;
1923 other_obj = botSel->obj;
1924 } else {
1925 poly_obj = botSel->obj;
1926 other_obj = topSel->obj;
1927 }
1928 if (poly_obj->locked) {
1929 MsgBox(TgLoadString(STID_CANNOT_MOVE_A_VERTEX_LOCKED), TOOL_NAME,
1930 INFO_MB);
1931 return;
1932 }
1933 cx = (other_obj->obbox.ltx+other_obj->obbox.rbx)>>1;
1934 cy = (other_obj->obbox.lty+other_obj->obbox.rby)>>1;
1935 n = poly_obj->detail.p->n;
1936 v = poly_obj->detail.p->vlist;
1937 if (poly_obj->ctm == NULL) {
1938 x1 = v[0].x;
1939 y1 = v[0].y;
1940 xn = v[n-1].x;
1941 yn = v[n-1].y;
1942 } else {
1943 TransformPointThroughCTM(v[0].x-poly_obj->x, v[0].y-poly_obj->y,
1944 poly_obj->ctm, &tmp_x, &tmp_y);
1945 x1 = tmp_x+poly_obj->x;
1946 y1 = tmp_y+poly_obj->y;
1947 TransformPointThroughCTM(v[n-1].x-poly_obj->x,
1948 v[n-1].y-poly_obj->y, poly_obj->ctm, &tmp_x, &tmp_y);
1949 xn = tmp_x+poly_obj->x;
1950 yn = tmp_y+poly_obj->y;
1951 }
1952 d1 = (x1-cx)*(x1-cx)+(y1-cy)*(y1-cy);
1953 dn = (xn-cx)*(xn-cx)+(yn-cy)*(yn-cy);
1954 if (d1 <= dn) {
1955 index = 0;
1956 x = x1;
1957 y = y1;
1958 } else {
1959 index = n-1;
1960 x = xn;
1961 y = yn;
1962 }
1963 if (cx != x || cy != y) {
1964 int ltx=0, lty=0, rbx=0, rby=0;
1965
1966 HighLightReverse();
1967 PrepareToReplaceAnObj(poly_obj);
1968 if (poly_obj->ctm == NULL) {
1969 v[index].x = cx;
1970 v[index].y = cy;
1971 } else {
1972 ReverseTransformPointThroughCTM(cx-poly_obj->x, cy-poly_obj->y,
1973 poly_obj->ctm, &tmp_x, &tmp_y);
1974 v[index].x = tmp_x+poly_obj->x;
1975 v[index].y = tmp_y+poly_obj->y;
1976 }
1977 AdjObjSplineVs(poly_obj);
1978 switch (poly_obj->detail.p->curved) {
1979 case LT_STRAIGHT:
1980 case LT_SPLINE:
1981 case LT_STRUCT_SPLINE:
1982 UpdPolyBBox(poly_obj, n, v);
1983 break;
1984 case LT_INTSPLINE:
1985 UpdPolyBBox(poly_obj, poly_obj->detail.p->intn,
1986 poly_obj->detail.p->intvlist);
1987 break;
1988 }
1989 RecordReplaceAnObj(poly_obj);
1990 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1991 UpdSelBBox();
1992 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1993 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1994 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1995 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1996 HighLightForward();
1997 SetFileModified(TRUE);
1998 justDupped = FALSE;
1999 }
2000 }
2001