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/pattern.c,v 1.26 2011/05/16 16:21:58 william Exp $
19 */
20
21 #define _INCLUDE_FROM_PATTERN_C_
22
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25
26 #include "arc.e"
27 #include "choice.e"
28 #include "color.e"
29 #include "cmd.e"
30 #include "cutpaste.e"
31 #include "dialog.e"
32 #include "drawing.e"
33 #include "file.e"
34 #include "font.e"
35 #include "mainmenu.e"
36 #include "mark.e"
37 #include "menu.e"
38 #include "menuinfo.e"
39 #include "miniline.e"
40 #include "msg.e"
41 #include "navigate.e"
42 #include "obj.e"
43 #include "pattern.e"
44 #include "poly.e"
45 #include "raster.e"
46 #include "select.e"
47 #include "setup.e"
48 #include "spline.e"
49 #include "strtbl.e"
50 #include "text.e"
51 #include "util.e"
52
53 int objFill=NONEPAT;
54 int transPat=FALSE;
55 int lineStyle=LS_RIGHT;
56 int lineWidth=0;
57 int penPat=SOLIDPAT;
58 int curSpline=LT_STRAIGHT;
59 int curDash=0;
60 int rcbRadius=DEF_RCB_RADIUS;
61 int useGray=FALSE;
62 char patternStr[]="8 1 0 72 300 32 div div tgifsetpattern";
63
64 int stickyMenuSelection=FALSE;
65
66 static int tileAsGrayDetected=FALSE;
67 static int canFakeGray=FALSE;
68 static char *grayStr[9] =
69 {
70 "0.995", "0.94", "0.868", "0.779", "0.763", "0.55", "0.41", "0.253", "0.079"
71 };
72
ResetGrayDetection()73 void ResetGrayDetection()
74 {
75 tileAsGrayDetected = FALSE;
76 canFakeGray = FALSE;
77 }
78
GrayStr(index)79 char *GrayStr(index)
80 int index;
81 /* this routine should only be called when useGray == TRUE */
82 {
83 if (index <= 2) {
84 fprintf(stderr, "%s\n",
85 TgLoadCachedString(CSTID_GRAYSTR_CALLED_WITH_IDX_2));
86 return("");
87 } else if (index >= 12) {
88 if (!tileAsGrayDetected) {
89 char buf[MAXSTRING];
90
91 tileAsGrayDetected = TRUE;
92 strcpy(buf, TgLoadCachedString(CSTID_GRAY_SCALE_USED_FOR_PAT));
93 if (PRTGIF) {
94 fprintf(stderr, "%s.\n", buf);
95 } else {
96 MsgBox(buf, TOOL_NAME, INFO_MB);
97 }
98 }
99 switch (index) {
100 case 12: index = 5; break;
101 case 13: index = 4; break;
102 case 14: index = 7; break;
103 case 15: index = 6; break;
104 case 16: index = 7; break;
105 case 17: index = 6; break;
106 case 18: index = 6; break;
107 case 19: index = 6; break;
108 case 20: index = 5; break;
109 case 21: index = 6; break;
110 case 22: index = 8; break;
111 case 23: index = 7; break;
112 case 24: index = 9; break;
113 case 25: index = 8; break;
114 case 26: index = 5; break;
115 case 27: index = 6; break;
116 case 28: index = 8; break;
117 case 29: index = 7; break;
118 case 30: index = 9; break;
119 case 31: index = 8; break;
120 }
121 }
122 return (grayStr[index-3]);
123 }
124
GrayCheck(index)125 void GrayCheck(index)
126 int index;
127 /* this routine should only be called when useGray == FALSE */
128 {
129 if (index > BACKPAT) {
130 if (index >= 12) {
131 tileAsGrayDetected = TRUE;
132 } else {
133 canFakeGray = TRUE;
134 }
135 }
136 }
137
EndGrayDetection()138 void EndGrayDetection()
139 /* this routine should only be called when useGray == FALSE */
140 {
141 int num_msgs = 1;
142 char msg1[MAXSTRING], msg2[MAXSTRING];
143
144 if (colorDump) return;
145
146 if (useGray) {
147 if (!tileAsGrayDetected && !canFakeGray) return;
148
149 strcpy(msg1, TgLoadString(STID_GRAY_SCALE_USED_IN_PRINT_PAT));
150 } else if (tileAsGrayDetected) {
151 strcpy(msg1, TgLoadString(STID_NOTE_SLOW_PRINT_DUE_USE_PAT));
152 } else if (canFakeGray) {
153 num_msgs = 2;
154 strcpy(msg1, TgLoadString(STID_NOTE_SLOW_PRINT_DUE_USE_PAT));
155 sprintf(msg2, " %s",
156 TgLoadString(STID_SUGGEST_USEGRAYSCALE_TO_SPEED));
157 } else {
158 return;
159 }
160 if (PRTGIF) {
161 fprintf(stderr, "%s.\n", msg1);
162 if (num_msgs==2) fprintf(stderr, "%s.\n", msg2);
163 } else {
164 if (num_msgs==1) {
165 Msg(msg1);
166 } else {
167 TwoLineMsg(msg1, msg2);
168 }
169 }
170 }
171
RefreshModeMenu(menu)172 int RefreshModeMenu(menu)
173 TgMenu *menu;
174 {
175 int i, num_items=menu->num_items, rc=TRUE;
176 TgMenuItem *menuitems=menu->menuitems;
177
178 for (i=0; i < num_items; i++) {
179 TgMenuItem *menu_item=(&menuitems[i]);
180 TgMenuItem stMenuItem;
181
182 memset(&stMenuItem, 0, sizeof(TgMenuItem));
183 stMenuItem.state = TGBS_NORMAL;
184 stMenuItem.checked = (i == curChoice);
185 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
186 &stMenuItem)) {
187 rc = FALSE;
188 }
189 }
190 if (inSlideShow && !goHyperSpaceInSlideShow) {
191 TgEnableMenuItemByIndex(menu, NOTHING, FALSE);
192 TgEnableMenuItemByIndex(menu, VERTEXMODE, FALSE);
193 TgEnableMenuItemByIndex(menu, ROTATEMODE, FALSE);
194 }
195 return rc;
196 }
197
CreateModeMenu(parent_menu,x,y,menu_info,status_str_xlated)198 TgMenu *CreateModeMenu(parent_menu, x, y, menu_info, status_str_xlated)
199 TgMenu *parent_menu;
200 int x, y;
201 TgMenuInfo *menu_info;
202 int status_str_xlated; /* ignored, always 0 */
203 {
204 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
205
206 if (menu != NULL) {
207 TgMenuItem *menu_item=NULL;
208 TgMenuItem stMenuItem;
209
210 menu->track_menubar = FALSE;
211 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, MAXCHOICES);
212 menu_item = (&menu->menuitems[curChoice]);
213
214 memset(&stMenuItem, 0, sizeof(TgMenuItem));
215 stMenuItem.checked = TRUE;
216 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
217 return TgDestroyMenu(menu, TRUE);
218 }
219 if (!RefreshModeMenu(menu)) {
220 return TgDestroyMenu(menu, TRUE);
221 }
222 menu->refresh_proc = ((RefreshMenuFunc*)RefreshModeMenu);
223 }
224 return menu;
225 }
226
ModeMenu(X,Y,TrackMenubar)227 int ModeMenu(X, Y, TrackMenubar)
228 int X, Y, TrackMenubar;
229 {
230 int rc=INVALID;
231 TgMenu *menu=(modeMenuInfo.create_proc)(NULL, X, Y, &modeMenuInfo, INVALID);
232
233 activeMenu = MENU_MODE;
234 if (menu != NULL) {
235 menu->track_menubar = TrackMenubar;
236
237 rc = TgMenuLoop(menu);
238 TgDestroyMenu(menu, TRUE);
239 }
240 return rc;
241 }
242
243 /* ------------------ TransPat Functions ------------------ */
244
ChangeObjTransPat(ObjPtr,TransPat)245 int ChangeObjTransPat(ObjPtr, TransPat)
246 struct ObjRec *ObjPtr;
247 int TransPat;
248 {
249 if (ObjPtr->trans_pat != TransPat) {
250 ObjPtr->trans_pat = TransPat;
251 return TRUE;
252 }
253 return FALSE;
254 }
255
ChangeAllSelTransPat(TransPat,HighLight)256 void ChangeAllSelTransPat(TransPat, HighLight)
257 int TransPat, HighLight;
258 {
259 struct SelRec *sel_ptr=NULL;
260 int changed=FALSE, ltx=selLtX, lty=selLtY, rbx=selRbX, rby=selRbY;
261
262 if (topSel == NULL || stickyMenuSelection) {
263 if (!(curChoice == DRAWTEXT && textCursorShown)) {
264 TieLooseEnds();
265 }
266 transPat = TransPat;
267 if (curChoice == DRAWTEXT && textCursorShown) {
268 if (ChangeObjTransPat(curTextObj, TransPat)) {
269 curTextModified = TRUE;
270 UpdCurTextBBox();
271 RedrawCurText();
272 SetFileModified(TRUE);
273 if (cycleThroughChoice) {
274 SetPushedFontValue(PUSH_TRANSPAT, transPat);
275 }
276 }
277 } else {
278 textCursorShown = FALSE;
279 }
280 if (topSel == NULL) {
281 switch (transPat) {
282 case NO_TRANSPAT_MODE:
283 Msg(TgLoadString(STID_FILL_PEN_PAT_OPAQUE));
284 break;
285 case TRANSPAT_MODE:
286 Msg(TgLoadString(STID_FILL_PEN_PAT_TRANSPARENT));
287 break;
288 }
289 }
290 ShowTransPatMode();
291 UpdatePinnedMenu(MENU_TRANSPAT);
292 if (topSel == NULL) return;
293 }
294
295 if (HighLight) HighLightReverse();
296 StartCompositeCmd();
297 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
298 PrepareToReplaceAnObj(sel_ptr->obj);
299 if (ChangeObjTransPat(sel_ptr->obj, TransPat)) {
300 changed = TRUE;
301 RecordReplaceAnObj(sel_ptr->obj);
302 } else {
303 AbortPrepareCmd(CMD_REPLACE);
304 }
305 }
306 EndCompositeCmd();
307
308 if (changed) {
309 SetFileModified(TRUE);
310 UpdSelBBox();
311 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
312 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
313 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
314 selRbY+GRID_ABS_SIZE(1));
315 }
316 if (HighLight) HighLightForward();
317 }
318
319 /* ------------------ Fill Functions ------------------ */
320
ChangeObjFill(ObjPtr,FillIndex)321 int ChangeObjFill(ObjPtr, FillIndex)
322 struct ObjRec *ObjPtr;
323 int FillIndex;
324 {
325 register struct ObjRec *obj_ptr;
326 int changed=FALSE;
327
328 switch (ObjPtr->type) {
329 case OBJ_TEXT:
330 if (ObjPtr->detail.t->fill != FillIndex) {
331 ObjPtr->detail.t->fill = FillIndex;
332 changed = TRUE;
333 }
334 break;
335 case OBJ_BOX:
336 if (ObjPtr->detail.b->fill != FillIndex) {
337 ObjPtr->detail.b->fill = FillIndex;
338 changed = TRUE;
339 }
340 break;
341 case OBJ_OVAL:
342 if (ObjPtr->detail.o->fill != FillIndex) {
343 ObjPtr->detail.o->fill = FillIndex;
344 changed = TRUE;
345 }
346 break;
347 case OBJ_POLY:
348 if (ObjPtr->detail.p->fill != FillIndex) {
349 ObjPtr->detail.p->fill = FillIndex;
350 changed = TRUE;
351 }
352 break;
353 case OBJ_POLYGON:
354 if (ObjPtr->detail.g->fill != FillIndex) {
355 ObjPtr->detail.g->fill = FillIndex;
356 changed = TRUE;
357 }
358 break;
359 case OBJ_ARC:
360 if (ObjPtr->detail.a->fill != FillIndex) {
361 if (ObjPtr->detail.a->fill == NONEPAT || FillIndex == NONEPAT) {
362 ObjPtr->detail.a->fill = FillIndex;
363 AdjObjBBox(ObjPtr);
364 } else {
365 ObjPtr->detail.a->fill = FillIndex;
366 }
367 changed = TRUE;
368 }
369 break;
370 case OBJ_RCBOX:
371 if (ObjPtr->detail.rcb->fill != FillIndex) {
372 ObjPtr->detail.rcb->fill = FillIndex;
373 changed = TRUE;
374 }
375 break;
376 case OBJ_XBM:
377 if (ObjPtr->detail.xbm->fill != FillIndex) {
378 ObjPtr->detail.xbm->fill = FillIndex;
379 changed = TRUE;
380 }
381 break;
382 case OBJ_XPM:
383 if (ObjPtr->detail.xpm->fill != FillIndex) {
384 ObjPtr->detail.xpm->fill = FillIndex;
385 changed = TRUE;
386 }
387 break;
388
389 case OBJ_SYM:
390 case OBJ_GROUP:
391 for (obj_ptr = ObjPtr->detail.r->last; obj_ptr != NULL;
392 obj_ptr = obj_ptr->prev) {
393 if (ChangeObjFill(obj_ptr, FillIndex)) {
394 changed = TRUE;
395 }
396 }
397 break;
398 }
399 if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
400 struct AttrRec *attr_ptr=ObjPtr->fattr;
401
402 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
403 changed |= ChangeObjFill(attr_ptr->obj, FillIndex);
404 }
405 }
406 return changed;
407 }
408
ChangeAllSelFill(FillIndex,HighLight)409 void ChangeAllSelFill(FillIndex, HighLight)
410 int FillIndex, HighLight;
411 {
412 register struct SelRec *sel_ptr;
413 int changed=FALSE, ltx, lty, rbx, rby;
414
415 if (topSel == NULL || stickyMenuSelection) {
416 if (!(curChoice == DRAWTEXT && textCursorShown)) {
417 TieLooseEnds();
418 }
419 objFill = FillIndex;
420 if (curChoice == DRAWTEXT && textCursorShown) {
421 if (ChangeObjFill(curTextObj, FillIndex)) {
422 curTextModified = TRUE;
423 UpdCurTextBBox();
424 RedrawCurText();
425 SetFileModified(TRUE);
426 if (cycleThroughChoice) {
427 SetPushedFontValue(PUSH_FILL, objFill);
428 }
429 }
430 } else {
431 textCursorShown = FALSE;
432 }
433 ShowFill();
434 UpdatePinnedMenu(MENU_FILL);
435 if (topSel == NULL) return;
436 }
437
438 if (HighLight) HighLightReverse();
439 StartCompositeCmd();
440 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
441 PrepareToReplaceAnObj(sel_ptr->obj);
442 if (ChangeObjFill(sel_ptr->obj, FillIndex)) {
443 changed = TRUE;
444 RecordReplaceAnObj(sel_ptr->obj);
445 } else {
446 AbortPrepareCmd(CMD_REPLACE);
447 }
448 }
449 EndCompositeCmd();
450
451 if (changed) {
452 SetFileModified(TRUE);
453 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
454 UpdSelBBox();
455 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
456 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
457 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
458 selRbY+GRID_ABS_SIZE(1));
459 }
460 if (HighLight) HighLightForward();
461 }
462
RefreshFillMenu(menu)463 void RefreshFillMenu(menu)
464 TgMenu *menu;
465 {
466 int i, num_items=menu->num_items;
467 TgMenuItem *menuitems=menu->menuitems;
468
469 for (i=0; i < num_items; i++) {
470 TgMenuItem *menu_item=(&menuitems[i]);
471 TgMenuItem stMenuItem;
472
473 memset(&stMenuItem, 0, sizeof(TgMenuItem));
474 stMenuItem.state = TGBS_NORMAL;
475 stMenuItem.checked = (i == objFill);
476 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
477 &stMenuItem);
478 }
479 }
480
CreateFillMenu(parent_menu,x,y,menu_info,status_str_xlated)481 TgMenu *CreateFillMenu(parent_menu, x, y, menu_info, status_str_xlated)
482 TgMenu *parent_menu;
483 int x, y;
484 TgMenuInfo *menu_info;
485 int status_str_xlated; /* ignored, always 0 */
486 {
487 int i=0;
488 TgMenu *menu=NULL;
489 TgMenuInfo stMenuInfo;
490 TgMenuItemInfo *item_info=NULL;
491
492 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
493 stMenuInfo.items = (TgMenuItemInfo*)malloc(
494 (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
495 if (stMenuInfo.items == NULL) FailAllocMessage();
496 memset(stMenuInfo.items, 0, (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
497 for (item_info=stMenuInfo.items, i=0; i < MAXPATTERNS; item_info++, i++) {
498 item_info->menu_str = (char*)(Pixmap*)(&patPixmap[i]);
499 item_info->shortcut_str = NULL;
500 switch (i) {
501 case NONEPAT:
502 strcpy(gszMsgBox, TgLoadCachedString(CSTID_SET_FILL_TO_NONE));
503 break;
504 case SOLIDPAT:
505 strcpy(gszMsgBox, TgLoadCachedString(CSTID_SET_FILL_TO_SOLID));
506 break;
507 case BACKPAT:
508 strcpy(gszMsgBox, TgLoadCachedString(CSTID_SET_FILL_TO_BACKGROUND));
509 break;
510 default:
511 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_FILL_TO_PAT_NUMBER),
512 i);
513 break;
514 }
515 item_info->status_str = UtilStrDup(gszMsgBox);
516 if (item_info->status_str == NULL) FailAllocMessage();
517 item_info->submenu_info = NULL;
518 item_info->cmdid = CMDID_CHANGEALLSELFILL;
519 }
520 stMenuInfo.items[MAXPATTERNS].cmdid = INVALID;
521
522 /* the status_str has been translated in TgLoadCachedString() */
523 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
524 for (item_info=stMenuInfo.items, i=0; i < MAXPATTERNS; item_info++, i++) {
525 UtilFree(item_info->status_str);
526 }
527 memset(stMenuInfo.items, 0, (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
528 free(stMenuInfo.items);
529 stMenuInfo.items = NULL;
530 if (menu != NULL) {
531 TgMenuItem *menu_item=NULL;
532 TgMenuItem stMenuItem;
533
534 menu->track_menubar = TRUE;
535 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, 8);
536 menu_item = (&menu->menuitems[objFill]);
537
538 memset(&stMenuItem, 0, sizeof(TgMenuItem));
539 stMenuItem.checked = TRUE;
540 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
541 return TgDestroyMenu(menu, TRUE);
542 }
543 }
544 return menu;
545 }
546
FillMenu(X,Y,TrackMenubar)547 int FillMenu(X, Y, TrackMenubar)
548 int X, Y, TrackMenubar;
549 {
550 int rc=INVALID;
551 TgMenu *menu=(fillMenuInfo.create_proc)(NULL, X, Y, &fillMenuInfo, INVALID);
552
553 activeMenu = MENU_FILL;
554 if (menu != NULL) {
555 menu->track_menubar = TrackMenubar;
556
557 rc = TgMenuLoop(menu);
558 TgDestroyMenu(menu, TRUE);
559 }
560 return rc;
561 }
562
563 /* ------------------ LineStyle Functions ------------------ */
564
565 static
ChangeObjLineStyle(ObjPtr,StyleIndex)566 int ChangeObjLineStyle(ObjPtr, StyleIndex)
567 struct ObjRec *ObjPtr;
568 int StyleIndex;
569 {
570 register struct ObjRec *obj_ptr;
571 register int changed=FALSE;
572
573 switch (ObjPtr->type) {
574 case OBJ_POLY:
575 if (ObjPtr->detail.p->style != StyleIndex) {
576 ObjPtr->detail.p->style = StyleIndex;
577 changed = TRUE;
578 AdjObjSplineVs(ObjPtr);
579 if (ObjPtr->detail.p->curved != LT_INTSPLINE) {
580 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->n,
581 ObjPtr->detail.p->vlist);
582 } else {
583 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->intn,
584 ObjPtr->detail.p->intvlist);
585 }
586 }
587 break;
588 case OBJ_ARC:
589 if (ObjPtr->detail.a->style != StyleIndex) {
590 ObjPtr->detail.a->style = StyleIndex;
591 changed = TRUE;
592 AdjObjSplineVs(ObjPtr);
593 }
594 break;
595 case OBJ_GROUP:
596 case OBJ_SYM:
597 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
598 obj_ptr=obj_ptr->prev) {
599 if (ChangeObjLineStyle(obj_ptr, StyleIndex)) {
600 changed = TRUE;
601 }
602 }
603 break;
604 }
605 if (changed) AdjObjBBox(ObjPtr);
606 return changed;
607 }
608
ChangeAllSelLineStyle(StyleIndex,HighLight)609 void ChangeAllSelLineStyle(StyleIndex, HighLight)
610 int StyleIndex, HighLight;
611 {
612 register struct SelRec *sel_ptr;
613 int ltx, lty, rbx, rby, changed=FALSE;
614
615 if (topSel == NULL || stickyMenuSelection) {
616 lineStyle = StyleIndex;
617 ShowLineStyle();
618 UpdatePinnedMenu(MENU_LINESTYLE);
619 if (topSel == NULL) return;
620 }
621
622 if (HighLight) HighLightReverse();
623 StartCompositeCmd();
624 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
625 PrepareToReplaceAnObj(sel_ptr->obj);
626 if (ChangeObjLineStyle(sel_ptr->obj, StyleIndex)) {
627 changed = TRUE;
628 RecordReplaceAnObj(sel_ptr->obj);
629 } else {
630 AbortPrepareCmd(CMD_REPLACE);
631 }
632 }
633 EndCompositeCmd();
634
635 if (changed) {
636 SetFileModified(TRUE);
637 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
638 UpdSelBBox();
639 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
640 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
641 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
642 selRbY+GRID_ABS_SIZE(1));
643 }
644 if (HighLight) HighLightForward();
645 }
646
RefreshLineStyleMenu(menu)647 void RefreshLineStyleMenu(menu)
648 TgMenu *menu;
649 {
650 int i, num_items=menu->num_items;
651 TgMenuItem *menuitems=menu->menuitems;
652
653 for (i=0; i < num_items; i++) {
654 TgMenuItem *menu_item=(&menuitems[i]);
655 TgMenuItem stMenuItem;
656
657 memset(&stMenuItem, 0, sizeof(TgMenuItem));
658 stMenuItem.state = TGBS_NORMAL;
659 stMenuItem.checked = (i == lineStyle);
660 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
661 &stMenuItem);
662 }
663 }
664
CreateLineStyleMenu(parent_menu,x,y,menu_info,status_str_xlated)665 TgMenu *CreateLineStyleMenu(parent_menu, x, y, menu_info, status_str_xlated)
666 TgMenu *parent_menu;
667 int x, y;
668 TgMenuInfo *menu_info;
669 int status_str_xlated; /* ignored, always 0 */
670 {
671 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
672
673 if (menu != NULL) {
674 TgMenuItem *menu_item=NULL;
675 TgMenuItem stMenuItem;
676
677 menu->track_menubar = TRUE;
678 TgAdjustMenuGeometry(menu, menuImageW, menuImageH, MAXLINESTYLES);
679 menu_item = (&menu->menuitems[lineStyle]);
680
681 memset(&stMenuItem, 0, sizeof(TgMenuItem));
682 stMenuItem.checked = TRUE;
683 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
684 return TgDestroyMenu(menu, TRUE);
685 }
686 }
687 return menu;
688 }
689
LineStyleMenu(X,Y,TrackMenubar)690 int LineStyleMenu(X, Y, TrackMenubar)
691 int X, Y, TrackMenubar;
692 {
693 int rc=INVALID;
694 TgMenu *menu=(lineStyleMenuInfo.create_proc)(NULL, X, Y, &lineStyleMenuInfo,
695 INVALID);
696
697 activeMenu = MENU_LINESTYLE;
698 if (menu != NULL) {
699 menu->track_menubar = TrackMenubar;
700
701 rc = TgMenuLoop(menu);
702 TgDestroyMenu(menu, TRUE);
703 }
704 return rc;
705 }
706
707 /* ------------------ LineType Functions ------------------ */
708
GetPolyOrPolygonControlPoints(obj_ptr,pp_poly,pp_polygon,pn_curved,pn_num_pts,pp_ip,ppsz_smooth)709 int GetPolyOrPolygonControlPoints(obj_ptr, pp_poly, pp_polygon, pn_curved,
710 pn_num_pts, pp_ip, ppsz_smooth)
711 struct ObjRec *obj_ptr;
712 struct PolyRec **pp_poly;
713 struct PolygonRec **pp_polygon;
714 int *pn_curved, *pn_num_pts;
715 IntPoint **pp_ip;
716 char **ppsz_smooth;
717 {
718 struct PolyRec *poly_ptr=NULL;
719 struct PolygonRec *polygon_ptr=NULL;
720
721 switch (obj_ptr->type) {
722 case OBJ_POLY:
723 poly_ptr = obj_ptr->detail.p;
724 *pn_curved = poly_ptr->curved;
725 if ((*pn_curved) == LT_STRUCT_SPLINE) {
726 *pn_num_pts = poly_ptr->ssn;
727 *pp_ip = poly_ptr->ssvlist;
728 *ppsz_smooth = poly_ptr->ssmooth;
729 } else {
730 *pn_num_pts = poly_ptr->n;
731 *pp_ip = poly_ptr->vlist;
732 *ppsz_smooth = poly_ptr->smooth;
733 }
734 break;
735 case OBJ_POLYGON:
736 polygon_ptr = obj_ptr->detail.g;
737 *pn_curved = polygon_ptr->curved;
738 if ((*pn_curved) == LT_STRUCT_SPLINE) {
739 *pn_num_pts = polygon_ptr->ssn;
740 *pp_ip = polygon_ptr->ssvlist;
741 *ppsz_smooth = polygon_ptr->ssmooth;
742 } else {
743 *pn_num_pts = polygon_ptr->n;
744 *pp_ip = polygon_ptr->vlist;
745 *ppsz_smooth = polygon_ptr->smooth;
746 }
747 break;
748 default: return FALSE;
749 }
750 if (pp_poly != NULL) *pp_poly = poly_ptr;
751 if (pp_polygon != NULL) *pp_polygon = polygon_ptr;
752
753 return TRUE;
754 }
755
756 static
CanConvertSplineToStructuredSpline(ObjPtr,pn_hinge_count,vlist_updated)757 int CanConvertSplineToStructuredSpline(ObjPtr, pn_hinge_count, vlist_updated)
758 struct ObjRec *ObjPtr;
759 int *pn_hinge_count;
760 IntPoint *vlist_updated;
761 /*
762 * returns TRUE means that conversion will be made (and something
763 * will change)
764 */
765 {
766 int i=0, last_hinge_index=0, hinge_count=1, num_ss_pts=0;
767 struct PolyRec *poly_ptr=NULL;
768 int curved=(-1), n=0, earlier_smooth=FALSE;
769 IntPoint *vs=NULL;
770 char *smooth=NULL;
771
772 if (!GetPolyOrPolygonControlPoints(ObjPtr, &poly_ptr, NULL, &curved, &n, &vs,
773 &smooth)) {
774 return FALSE;
775 }
776 if (vlist_updated != NULL) {
777 num_ss_pts = ((*pn_hinge_count)*3)-2;
778 vlist_updated[0].x = vs[0].x;
779 vlist_updated[0].y = vs[0].y;
780 vlist_updated[num_ss_pts-1].x = vs[n-1].x;
781 vlist_updated[num_ss_pts-1].y = vs[n-1].y;
782 }
783 for (i=1; i < n; i++) {
784 if (smooth == NULL || !smooth[i]) {
785 int idx=0;
786
787 hinge_count++;
788
789 switch (i-last_hinge_index) {
790 case 3:
791 if (last_hinge_index == 0) {
792 /* the first point can be anything, so still okay */
793 if (vlist_updated != NULL) {
794 vlist_updated[1].x = vs[1].x;
795 vlist_updated[1].y = vs[1].y;
796 }
797 } else if (earlier_smooth) {
798 if ((vs[last_hinge_index].x<<1) ==
799 (vs[last_hinge_index-1].x+vs[last_hinge_index+1].x) &&
800 (vs[last_hinge_index].y<<1) ==
801 (vs[last_hinge_index-1].y+vs[last_hinge_index+1].y)) {
802 /* still okay */
803 if (vlist_updated != NULL) {
804 idx = (hinge_count-2)*3;
805 #ifdef _TGIF_DBG /* debug, do not translate */
806 TgAssert(
807 vlist_updated[idx-1].x==vs[last_hinge_index-1].x &&
808 vlist_updated[idx-1].y==vs[last_hinge_index-1].y &&
809 vlist_updated[idx].x==vs[last_hinge_index].x &&
810 vlist_updated[idx].y==vs[last_hinge_index].y,
811 "check #1 failed in CanConvertSplineToStructuredSpline()",
812 NULL);
813 #endif /* _TGIF_DBG */
814 vlist_updated[idx+1].x = vs[last_hinge_index+1].x;
815 vlist_updated[idx+1].y = vs[last_hinge_index+1].y;
816 }
817 } else {
818 return FALSE;
819 }
820 } else {
821 return FALSE;
822 }
823 earlier_smooth = TRUE;
824 if (vlist_updated != NULL) {
825 idx = (hinge_count-1)*3;
826 vlist_updated[idx-1].x = vs[i-1].x;
827 vlist_updated[idx-1].y = vs[i-1].y;
828 vlist_updated[idx].x = vs[i].x;
829 vlist_updated[idx].y = vs[i].y;
830 }
831 break;
832 case 2:
833 if (last_hinge_index == 0) {
834 /* it can go either way */
835 if (i == n-1) {
836 /* still can go either way */
837 earlier_smooth = TRUE;
838 if (vlist_updated != NULL) {
839 vlist_updated[1].x = vs[0].x;
840 vlist_updated[1].y = vs[0].y;
841 }
842 } else if (smooth != NULL && smooth[i+1]) {
843 if ((vs[i].x<<1) == (vs[i-1].x+vs[i+1].x) &&
844 (vs[i].y<<1) == (vs[i-1].y+vs[i+1].y)) {
845 /* still okay */
846 earlier_smooth = TRUE;
847 if (vlist_updated != NULL) {
848 vlist_updated[1].x = vs[0].x;
849 vlist_updated[1].y = vs[0].y;
850 }
851 } else {
852 /* still okay */
853 earlier_smooth = FALSE;
854 }
855 } else {
856 /* still okay */
857 earlier_smooth = FALSE;
858 }
859 if (vlist_updated != NULL) {
860 idx = (hinge_count-2)*3;
861 if (!earlier_smooth) {
862 vlist_updated[idx+1].x = vs[i-1].x;
863 vlist_updated[idx+1].y = vs[i-1].y;
864 }
865 }
866 } else if (earlier_smooth) {
867 if ((vs[last_hinge_index].x<<1) ==
868 (vs[last_hinge_index-1].x+vs[last_hinge_index+1].x) &&
869 (vs[last_hinge_index].y<<1) ==
870 (vs[last_hinge_index-1].y+vs[last_hinge_index+1].y)) {
871 /* still okay */
872 earlier_smooth = FALSE;
873 if (vlist_updated != NULL) {
874 idx = (hinge_count-2)*3;
875 #ifdef _TGIF_DBG /* debug, do not translate */
876 TgAssert(
877 vlist_updated[idx-1].x==vs[last_hinge_index-1].x &&
878 vlist_updated[idx-1].y==vs[last_hinge_index-1].y &&
879 vlist_updated[idx].x==vs[last_hinge_index].x &&
880 vlist_updated[idx].y==vs[last_hinge_index].y,
881 "check #2 failed in CanConvertSplineToStructuredSpline()",
882 NULL);
883 #endif /* _TGIF_DBG */
884 vlist_updated[idx+1].x = vs[last_hinge_index+1].x;
885 vlist_updated[idx+1].y = vs[last_hinge_index+1].y;
886 }
887 } else {
888 return FALSE;
889 }
890 } else {
891 /* still okay */
892 if (vlist_updated != NULL) {
893 idx = (hinge_count-2)*3;
894 vlist_updated[idx+1].x = vlist_updated[idx].x;
895 vlist_updated[idx+1].y = vlist_updated[idx].y;
896 }
897 earlier_smooth = TRUE;
898 }
899 if (vlist_updated != NULL) {
900 idx = (hinge_count-1)*3;
901 if (earlier_smooth) {
902 vlist_updated[idx-1].x = vs[i-1].x;
903 vlist_updated[idx-1].y = vs[i-1].y;
904 } else {
905 vlist_updated[idx-1].x = vs[i].x;
906 vlist_updated[idx-1].y = vs[i].y;
907 }
908 vlist_updated[idx].x = vs[i].x;
909 vlist_updated[idx].y = vs[i].y;
910 }
911 break;
912 case 1:
913 if (earlier_smooth) {
914 return FALSE;
915 }
916 if (vlist_updated != NULL) {
917 idx = (hinge_count-2)*3;
918 vlist_updated[idx+1].x = vs[last_hinge_index].x;
919 vlist_updated[idx+1].y = vs[last_hinge_index].y;
920
921 idx = (hinge_count-1)*3;
922 vlist_updated[idx-1].x = vs[i].x;
923 vlist_updated[idx-1].y = vs[i].y;
924 vlist_updated[idx].x = vs[i].x;
925 vlist_updated[idx].y = vs[i].y;
926 }
927 break;
928 default: /* too many consecutive smooth points */ return FALSE;
929 }
930 last_hinge_index = i;
931 }
932 }
933 if (pn_hinge_count != NULL && vlist_updated == NULL) {
934 *pn_hinge_count = hinge_count;
935 }
936 return TRUE;
937 }
938
939 static
CanConvertClosedSplineToStructuredSpline(ObjPtr,pn_hinge_count,vlist_updated)940 int CanConvertClosedSplineToStructuredSpline(ObjPtr, pn_hinge_count,
941 vlist_updated)
942 struct ObjRec *ObjPtr;
943 int *pn_hinge_count;
944 IntPoint *vlist_updated;
945 /*
946 * returns TRUE means that conversion will be made (and something
947 * will change)
948 */
949 {
950 int i=0, last_hinge_index=0, hinge_count=1, num_ss_pts=0;
951 struct PolygonRec *polygon_ptr=NULL;
952 int curved=(-1), n=0, earlier_smooth=FALSE;
953 IntPoint *vs=NULL;
954 char *smooth=NULL;
955
956 if (!GetPolyOrPolygonControlPoints(ObjPtr, NULL, &polygon_ptr, &curved, &n,
957 &vs, &smooth)) {
958 return FALSE;
959 }
960 if (vlist_updated != NULL) {
961 num_ss_pts = ((*pn_hinge_count)*3)-2;
962 vlist_updated[0].x = vs[0].x;
963 vlist_updated[0].y = vs[0].y;
964 vlist_updated[num_ss_pts-1].x = vs[n-1].x;
965 vlist_updated[num_ss_pts-1].y = vs[n-1].y;
966 }
967 for (i=1; i < n; i++) {
968 if (smooth == NULL || !smooth[i]) {
969 int idx=0;
970
971 hinge_count++;
972
973 switch (i-last_hinge_index) {
974 case 3:
975 if (last_hinge_index == 0) {
976 if (smooth != NULL && smooth[n-2]) {
977 if ((vs[0].x<<1) == (vs[n-2].x+vs[1].x) &&
978 (vs[0].y<<1) == (vs[n-2].y+vs[1].y)) {
979 /* still okay */
980 if (vlist_updated != NULL) {
981 idx = (*pn_hinge_count)*3-3;
982 vlist_updated[1].x = vs[1].x;
983 vlist_updated[1].y = vs[1].y;
984 vlist_updated[idx-1].x = vs[n-2].x;
985 vlist_updated[idx-1].y = vs[n-2].y;
986 }
987 } else {
988 return FALSE;
989 }
990 } else {
991 return FALSE;
992 }
993 } else if (earlier_smooth) {
994 if ((vs[last_hinge_index].x<<1) ==
995 (vs[last_hinge_index-1].x+vs[last_hinge_index+1].x) &&
996 (vs[last_hinge_index].y<<1) ==
997 (vs[last_hinge_index-1].y+vs[last_hinge_index+1].y)) {
998 /* still okay */
999 if (vlist_updated != NULL) {
1000 idx = (hinge_count-2)*3;
1001 #ifdef _TGIF_DBG /* debug, do not translate */
1002 TgAssert(
1003 vlist_updated[idx-1].x==vs[last_hinge_index-1].x &&
1004 vlist_updated[idx-1].y==vs[last_hinge_index-1].y &&
1005 vlist_updated[idx].x==vs[last_hinge_index].x &&
1006 vlist_updated[idx].y==vs[last_hinge_index].y,
1007 "check #1 failed in CanConvertClosedSplineToStructuredSpline()",
1008 NULL);
1009 #endif /* _TGIF_DBG */
1010 vlist_updated[idx+1].x = vs[last_hinge_index+1].x;
1011 vlist_updated[idx+1].y = vs[last_hinge_index+1].y;
1012 }
1013 } else {
1014 return FALSE;
1015 }
1016 } else {
1017 return FALSE;
1018 }
1019 earlier_smooth = TRUE;
1020 if (vlist_updated != NULL) {
1021 idx = (hinge_count-1)*3;
1022 vlist_updated[idx-1].x = vs[i-1].x;
1023 vlist_updated[idx-1].y = vs[i-1].y;
1024 vlist_updated[idx].x = vs[i].x;
1025 vlist_updated[idx].y = vs[i].y;
1026 }
1027 if (i == n-1) {
1028 if (smooth != NULL && smooth[1]) {
1029 if ((vs[0].x<<1) == (vs[n-2].x+vs[1].x) &&
1030 (vs[0].y<<1) == (vs[n-2].y+vs[1].y)) {
1031 /* still okay */
1032 } else {
1033 return FALSE;
1034 }
1035 } else {
1036 return FALSE;
1037 }
1038 }
1039 break;
1040 case 2:
1041 if (last_hinge_index == 0) {
1042 /* it can go either way */
1043 if (smooth != NULL && smooth[i+1]) {
1044 if ((vs[i].x<<1) == (vs[i-1].x+vs[i+1].x) &&
1045 (vs[i].y<<1) == (vs[i-1].y+vs[i+1].y)) {
1046 /* still okay */
1047 earlier_smooth = TRUE;
1048 if (vlist_updated != NULL) {
1049 vlist_updated[1].x = vs[0].x;
1050 vlist_updated[1].y = vs[0].y;
1051
1052 idx = (hinge_count-1)*3;
1053 vlist_updated[idx-1].x = vs[i-1].x;
1054 vlist_updated[idx-1].y = vs[i-1].y;
1055 vlist_updated[idx].x = vs[i].x;
1056 vlist_updated[idx].y = vs[i].y;
1057 }
1058 } else {
1059 /* still okay */
1060 if (smooth != NULL && smooth[n-2]) {
1061 if ((vs[0].x<<1) == (vs[n-2].x+vs[1].x) &&
1062 (vs[0].y<<1) == (vs[n-2].y+vs[1].y)) {
1063 /* still okay */
1064 } else {
1065 return FALSE;
1066 }
1067 } else {
1068 return FALSE;
1069 }
1070 earlier_smooth = FALSE;
1071 }
1072 } else {
1073 /* still okay */
1074 earlier_smooth = FALSE;
1075 }
1076 } else if (earlier_smooth) {
1077 if ((vs[last_hinge_index].x<<1) ==
1078 (vs[last_hinge_index-1].x+vs[last_hinge_index+1].x) &&
1079 (vs[last_hinge_index].y<<1) ==
1080 (vs[last_hinge_index-1].y+vs[last_hinge_index+1].y)) {
1081 /* still okay */
1082 earlier_smooth = FALSE;
1083 } else {
1084 return FALSE;
1085 }
1086 } else {
1087 /* still okay */
1088 earlier_smooth = TRUE;
1089 if (i == n-1) {
1090 if (smooth != NULL && smooth[1]) {
1091 if ((vs[0].x<<1) == (vs[n-2].x+vs[1].x) &&
1092 (vs[0].y<<1) == (vs[n-2].y+vs[1].y)) {
1093 /* still okay */
1094 } else {
1095 return FALSE;
1096 }
1097 } else {
1098 return FALSE;
1099 }
1100 }
1101 }
1102 if (vlist_updated != NULL) {
1103 idx = (hinge_count-1)*3;
1104 if (earlier_smooth) {
1105 vlist_updated[idx-1].x = vs[i-1].x;
1106 vlist_updated[idx-1].y = vs[i-1].y;
1107 } else {
1108 vlist_updated[idx-1].x = vs[i].x;
1109 vlist_updated[idx-1].y = vs[i].y;
1110 }
1111 vlist_updated[idx].x = vs[i].x;
1112 vlist_updated[idx].y = vs[i].y;
1113 }
1114 break;
1115 case 1:
1116 if (earlier_smooth) {
1117 return FALSE;
1118 }
1119 if (vlist_updated != NULL) {
1120 idx = (hinge_count-2)*3;
1121 vlist_updated[idx+1].x = vs[last_hinge_index].x;
1122 vlist_updated[idx+1].y = vs[last_hinge_index].y;
1123
1124 idx = (hinge_count-1)*3;
1125 vlist_updated[idx-1].x = vs[i].x;
1126 vlist_updated[idx-1].y = vs[i].y;
1127 vlist_updated[idx].x = vs[i].x;
1128 vlist_updated[idx].y = vs[i].y;
1129 }
1130 break;
1131 default: /* too many consecutive smooth points */ return FALSE;
1132 }
1133 last_hinge_index = i;
1134 }
1135 }
1136 if (last_hinge_index == 0) {
1137 return FALSE;
1138 }
1139 if (pn_hinge_count != NULL && vlist_updated == NULL) {
1140 *pn_hinge_count = hinge_count;
1141 }
1142 return TRUE;
1143 }
1144
1145 static
CanConvertObjLineType(ObjPtr,TypeIndex,pn_failed_count,pn_hinge_count)1146 int CanConvertObjLineType(ObjPtr, TypeIndex, pn_failed_count, pn_hinge_count)
1147 struct ObjRec *ObjPtr;
1148 int TypeIndex, *pn_failed_count, *pn_hinge_count;
1149 /*
1150 * returns FALSE if ObjPtr has the same line type as TypeIndex or
1151 * if there is no way to make the conversion (for example,
1152 * from spline to structured spline where the smooth vertices
1153 * are not all at the right places); this object will not change
1154 * in this case
1155 * returns TRUE means that conversion will be made (and something
1156 * will change)
1157 */
1158 {
1159 int i=0;
1160 int curved=(-1), n=0;
1161 IntPoint *vs=NULL;
1162 char *smooth=NULL;
1163
1164 if (!GetPolyOrPolygonControlPoints(ObjPtr, NULL, NULL, &curved, &n, &vs,
1165 &smooth)) {
1166 return FALSE;
1167 }
1168 switch (TypeIndex) {
1169 case LT_STRAIGHT:
1170 if (curved == LT_INTSPLINE) return TRUE;
1171 if (curved == LT_STRUCT_SPLINE) return TRUE;
1172 if (curved == LT_STRAIGHT && smooth == NULL) return FALSE;
1173 if (curved == LT_SPLINE && smooth == NULL) return TRUE;
1174 switch (ObjPtr->type) {
1175 case OBJ_POLY:
1176 for (i=1; i < n-1; i++) if (smooth[i]) return TRUE;
1177 break;
1178 case OBJ_POLYGON:
1179 for (i=0; i < n; i++) if (smooth[i]) return TRUE;
1180 break;
1181 }
1182 return FALSE;
1183 case LT_SPLINE:
1184 if (curved == LT_INTSPLINE) return TRUE;
1185 if (curved == LT_STRUCT_SPLINE) return TRUE;
1186 if (curved == LT_STRAIGHT && smooth == NULL) return TRUE;
1187 if (curved == LT_SPLINE && smooth == NULL) return FALSE;
1188 switch (ObjPtr->type) {
1189 case OBJ_POLY:
1190 for (i=1; i < n-1; i++) if (!smooth[i]) return TRUE;
1191 break;
1192 case OBJ_POLYGON:
1193 for (i=0; i < n; i++) if (!smooth[i]) return TRUE;
1194 break;
1195 }
1196 return FALSE;
1197 case LT_INTSPLINE:
1198 if (curved == LT_INTSPLINE) return FALSE;
1199 if (curved == LT_STRUCT_SPLINE) {
1200 int min_num_vertices=0, max_vs_to_check=n, count=1;
1201
1202 if (ObjPtr->type == OBJ_POLY) {
1203 min_num_vertices = 2;
1204 } else { /* ObjPtr->type is OBJ_POLYGON */
1205 min_num_vertices = 4;
1206 }
1207 if (smooth == NULL) {
1208 if (n < min_num_vertices) {
1209 (*pn_failed_count)++;
1210 return FALSE;
1211 }
1212 } else {
1213 for (i=1; i < max_vs_to_check; i++) {
1214 if (!smooth[i]) count++;
1215 }
1216 if (count < min_num_vertices) {
1217 (*pn_failed_count)++;
1218 return FALSE;
1219 }
1220 }
1221 }
1222 return TRUE;
1223 case LT_STRUCT_SPLINE:
1224 if (curved == LT_INTSPLINE) {
1225 if (pn_hinge_count != NULL) *pn_hinge_count = n;
1226 return TRUE;
1227 }
1228 if (curved == LT_STRUCT_SPLINE) return FALSE;
1229 if (curved == LT_STRAIGHT && smooth == NULL) {
1230 if (pn_hinge_count != NULL) *pn_hinge_count = n;
1231 return TRUE;
1232 }
1233 if (curved == LT_SPLINE && smooth == NULL) return FALSE;
1234 switch (ObjPtr->type) {
1235 case OBJ_POLY:
1236 if (!CanConvertSplineToStructuredSpline(ObjPtr, pn_hinge_count,
1237 NULL)) {
1238 (*pn_failed_count)++;
1239 return FALSE;
1240 }
1241 break;
1242 case OBJ_POLYGON:
1243 if (!CanConvertClosedSplineToStructuredSpline(ObjPtr, pn_hinge_count,
1244 NULL)) {
1245 (*pn_failed_count)++;
1246 return FALSE;
1247 }
1248 break;
1249 }
1250 break;
1251 }
1252 return TRUE;
1253 }
1254
1255 static
GetNumUsableStraightVs(pn_num_usable_vs,num_pts,vs)1256 IntPoint *GetNumUsableStraightVs(pn_num_usable_vs, num_pts, vs)
1257 int *pn_num_usable_vs, num_pts;
1258 IntPoint *vs;
1259 {
1260 int i=0, index=1, x=0, y=0;
1261 IntPoint *pv=(IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
1262
1263 if (pv == NULL) FailAllocMessage();
1264 memset(pv, 0, num_pts*sizeof(IntPoint));
1265 x = pv[0].x = vs[0].x;
1266 y = pv[0].y = vs[0].y;
1267 for (i=1; i < num_pts; i++) {
1268 if (vs[i].x != x || vs[i].y != y) {
1269 x = pv[index].x = vs[i].x;
1270 y = pv[index].y = vs[i].y;
1271 index++;
1272 }
1273 }
1274 if (index == 1) {
1275 *pn_num_usable_vs = 0;
1276 free(pv);
1277 return NULL;
1278 }
1279 *pn_num_usable_vs = index;
1280
1281 return pv;
1282 }
1283
1284 static
GetNumUsableSplineVs(pn_num_usable_vs,ppsz_smooth,num_pts,vs,smooth)1285 IntPoint *GetNumUsableSplineVs(pn_num_usable_vs, ppsz_smooth, num_pts, vs,
1286 smooth)
1287 int *pn_num_usable_vs, num_pts;
1288 char **ppsz_smooth, *smooth;
1289 IntPoint *vs;
1290 {
1291 int i=0, index=1, x=0, y=0;
1292 IntPoint *pv=(IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
1293 char *psz_smooth=(char*)malloc((num_pts+1)*sizeof(char));
1294
1295 if (pv == NULL || psz_smooth == NULL) FailAllocMessage();
1296 memset(pv, 0, num_pts*sizeof(IntPoint));
1297 memset(psz_smooth, 0, num_pts*sizeof(char));
1298 x = pv[0].x = vs[0].x;
1299 y = pv[0].y = vs[0].y;
1300 psz_smooth[0] = FALSE;
1301 for (i=1; i < num_pts; i++) {
1302 if (vs[i].x != x || vs[i].y != y) {
1303 psz_smooth[index] = smooth[i];
1304 x = pv[index].x = vs[i].x;
1305 y = pv[index].y = vs[i].y;
1306 index++;
1307 }
1308 }
1309 psz_smooth[index] = FALSE;
1310
1311 if (index == 1) {
1312 *pn_num_usable_vs = 0;
1313 *ppsz_smooth = NULL;
1314 free(pv);
1315 free(psz_smooth);
1316 return NULL;
1317 }
1318 *pn_num_usable_vs = index;
1319 *ppsz_smooth = psz_smooth;
1320
1321 return pv;
1322 }
1323
1324 static
GetNumUsableIntSplineVsFromStructuredSpline(pn_num_usable_vs,num_pts,vs)1325 IntPoint *GetNumUsableIntSplineVsFromStructuredSpline(pn_num_usable_vs, num_pts,
1326 vs)
1327 int *pn_num_usable_vs, num_pts;
1328 IntPoint *vs;
1329 {
1330 int j=0, index=1, x=0, y=0;
1331 IntPoint *pv=(IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
1332
1333 if (pv == NULL) FailAllocMessage();
1334 memset(pv, 0, num_pts*sizeof(IntPoint));
1335 x = pv[0].x = vs[0].x;
1336 y = pv[0].y = vs[0].y;
1337 for (j=3; j < num_pts; j+=3) {
1338 if (abs(vs[j].x-x) > 1 || abs(vs[j].y-y) > 1) {
1339 x = pv[index].x = vs[j].x;
1340 y = pv[index].y = vs[j].y;
1341 index++;
1342 }
1343 }
1344 if (index == 1) {
1345 *pn_num_usable_vs = 0;
1346 free(pv);
1347 return NULL;
1348 }
1349 *pn_num_usable_vs = index;
1350
1351 return pv;
1352 }
1353
1354 static
GetNumUsableIntSplineVs(pn_num_usable_vs,num_pts,vs,smooth)1355 IntPoint *GetNumUsableIntSplineVs(pn_num_usable_vs, num_pts, vs, smooth)
1356 int *pn_num_usable_vs, num_pts;
1357 IntPoint *vs;
1358 char *smooth;
1359 {
1360 int i=0, index=1, x=0, y=0;
1361 IntPoint *pv=(IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
1362
1363 if (pv == NULL) FailAllocMessage();
1364 memset(pv, 0, num_pts*sizeof(IntPoint));
1365 x = pv[0].x = vs[0].x;
1366 y = pv[0].y = vs[0].y;
1367 for (i=1; i < num_pts; i++) {
1368 if (abs(vs[i].x-x) > 1 || abs(vs[i].y-y) > 1) {
1369 x = pv[index].x = vs[i].x;
1370 y = pv[index].y = vs[i].y;
1371 index++;
1372 }
1373 }
1374 if (index == 1) {
1375 *pn_num_usable_vs = 0;
1376 free(pv);
1377 return NULL;
1378 }
1379 *pn_num_usable_vs = index;
1380
1381 return pv;
1382 }
1383
1384 static
GetNumUsableStructuredSplineVs(pn_num_usable_vs,ppsz_smooth,obj_type,n,vs,intn,intvs)1385 IntPoint *GetNumUsableStructuredSplineVs(pn_num_usable_vs, ppsz_smooth,
1386 obj_type, n, vs, intn, intvs)
1387 int *pn_num_usable_vs, obj_type, n, intn;
1388 char **ppsz_smooth;
1389 IntPoint *vs, *intvs;
1390 {
1391 int i=0, j=0, k=0, index=1, x=0, y=0, num_ss_pts=(n*3)-2;
1392 IntPoint *pv=(IntPoint*)malloc((num_ss_pts+2)*sizeof(IntPoint));
1393 char *psz_smooth=(char*)malloc((num_ss_pts+2)*sizeof(char));
1394
1395 if (pv == NULL || psz_smooth == NULL) FailAllocMessage();
1396 memset(pv, 0, (num_ss_pts+1)*sizeof(IntPoint));
1397 memset(psz_smooth, 0, (num_ss_pts+1)*sizeof(char));
1398 x = pv[0].x = vs[0].x;
1399 y = pv[0].y = vs[0].y;
1400 psz_smooth[0] = psz_smooth[num_ss_pts-1] = FALSE;
1401 if (obj_type == OBJ_POLY) {
1402 pv[1].x = vs[0].x;
1403 pv[1].y = vs[0].y;
1404 psz_smooth[1] = psz_smooth[num_ss_pts-2] = FALSE;
1405 } else { /* obj_type == OBJ_POLYGON */
1406 pv[1].x = intvs[0].x;
1407 pv[1].y = intvs[0].y;
1408 psz_smooth[1] = psz_smooth[num_ss_pts-2] = TRUE;
1409 }
1410 for (i=1; i < n; i++) {
1411 if (abs(vs[i].x-x) > 3 || abs(vs[i].y-y) > 3) {
1412 j = (index*3);
1413 k = (i<<1)-1;
1414 pv[j-1].x = intvs[k].x;
1415 pv[j-1].y = intvs[k].y;
1416 x = pv[j].x = vs[i].x;
1417 y = pv[j].y = vs[i].y;
1418 pv[j+1].x = (x<<1) - pv[j-1].x;
1419 pv[j+1].y = (y<<1) - pv[j-1].y;
1420 if (pv[j-1].x == pv[j+1].x && pv[j-1].y == pv[j+1].y) {
1421 psz_smooth[j-1] = psz_smooth[j+1] = FALSE;
1422 } else {
1423 psz_smooth[j-1] = psz_smooth[j+1] = TRUE;
1424 }
1425 psz_smooth[j] = FALSE;
1426 index++;
1427 }
1428 }
1429 if (index == 1) {
1430 *pn_num_usable_vs = 0;
1431 *ppsz_smooth = NULL;
1432 free(pv);
1433 free(psz_smooth);
1434 return NULL;
1435 }
1436 j = (index-1)*3;
1437 pv[j].x = x;
1438 pv[j].y = y;
1439 psz_smooth[j] = FALSE;
1440 if (obj_type == OBJ_POLY) {
1441 pv[j-1].x = x;
1442 pv[j-1].y = y;
1443 psz_smooth[j-1] = FALSE;
1444 } else { /* obj_type == OBJ_POLYGON */
1445 if (x != pv[0].x || y != pv[0].y) {
1446 /*
1447 * need to add more vertices?
1448 * let's assume this cannot happen for now
1449 */
1450 if (index == n) {
1451 x = pv[j].x = pv[0].x;
1452 y = pv[j].y = pv[0].y;
1453 } else {
1454 psz_smooth[j-1] = psz_smooth[j] = psz_smooth[j+1] = FALSE;
1455 pv[j-1].x = pv[j+1].x = pv[j].x;
1456 pv[j-1].y = pv[j+1].y = pv[j].y;
1457 j += 3;
1458 x = pv[j-1].x = pv[j].x = pv[0].x;
1459 y = pv[j-1].y = pv[j].y = pv[0].y;
1460 psz_smooth[j-1] = psz_smooth[j] = FALSE;
1461 }
1462 } else {
1463 pv[j-1].x = (x<<1) - pv[1].x;
1464 pv[j-1].y = (y<<1) - pv[1].y;
1465 psz_smooth[j-1] = TRUE;
1466 }
1467 }
1468 *pn_num_usable_vs = j+1;
1469 *ppsz_smooth = psz_smooth;
1470
1471 return pv;
1472 }
1473
1474 static
SetObjSmooth(ObjPtr,TypeIndex,hinge_count)1475 void SetObjSmooth(ObjPtr, TypeIndex, hinge_count)
1476 struct ObjRec *ObjPtr;
1477 int TypeIndex, hinge_count;
1478 {
1479 int i=0, n=0, num_ss_pts=0;
1480 char *smooth=NULL, *usable_smooth=NULL;
1481 struct PolyRec *poly_ptr=NULL;
1482 struct PolygonRec *polygon_ptr=NULL;
1483 IntPoint *vlist=NULL, *usable_vlist=NULL;
1484
1485 switch (ObjPtr->type) {
1486 case OBJ_POLY:
1487 poly_ptr = ObjPtr->detail.p;
1488 smooth = poly_ptr->smooth;
1489 n = poly_ptr->n;
1490 switch (TypeIndex) {
1491 case LT_STRAIGHT:
1492 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
1493 usable_vlist = GetNumUsableStraightVs(&n, poly_ptr->ssn,
1494 poly_ptr->ssvlist);
1495 }
1496 if (usable_vlist != NULL) {
1497 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
1498 poly_ptr->n = n;
1499 poly_ptr->vlist = usable_vlist;
1500 }
1501 if (smooth == NULL) smooth = (char*)malloc((n+1)*sizeof(char));
1502 if (smooth == NULL) FailAllocMessage();
1503 for (i=0; i < n; i++) smooth[i] = FALSE;
1504 poly_ptr->smooth = smooth;
1505 return;
1506 case LT_SPLINE:
1507 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
1508 usable_vlist = GetNumUsableSplineVs(&n, &usable_smooth,
1509 poly_ptr->ssn, poly_ptr->ssvlist, poly_ptr->ssmooth);
1510 }
1511 if (usable_vlist != NULL) {
1512 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
1513 if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
1514 poly_ptr->n = n;
1515 poly_ptr->vlist = usable_vlist;
1516 poly_ptr->smooth = usable_smooth;
1517 } else {
1518 if (smooth == NULL) smooth = (char*)malloc((n+1)*sizeof(char));
1519 if (smooth == NULL) FailAllocMessage();
1520 smooth[0] = smooth[n-1] = FALSE;
1521 for (i=1; i < n-1; i++) smooth[i] = TRUE;
1522 poly_ptr->smooth = smooth;
1523 }
1524 return;
1525 case LT_INTSPLINE:
1526 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
1527 usable_vlist = GetNumUsableIntSplineVsFromStructuredSpline(&n,
1528 poly_ptr->n, poly_ptr->vlist);
1529 } else {
1530 usable_vlist = GetNumUsableIntSplineVs(&n, poly_ptr->n,
1531 poly_ptr->vlist, poly_ptr->smooth);
1532 }
1533 if (usable_vlist != NULL) {
1534 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
1535 poly_ptr->n = n;
1536 poly_ptr->vlist = usable_vlist;
1537 }
1538 if (smooth != NULL) {
1539 free(smooth);
1540 poly_ptr->smooth = NULL;
1541 }
1542 return;
1543 case LT_STRUCT_SPLINE:
1544 if (poly_ptr->curved == LT_INTSPLINE) {
1545 usable_vlist = GetNumUsableStructuredSplineVs(&n, &usable_smooth,
1546 OBJ_POLY, poly_ptr->n, poly_ptr->vlist, poly_ptr->intn,
1547 poly_ptr->intvlist);
1548 }
1549 if (usable_vlist != NULL) {
1550 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
1551 poly_ptr->n = n;
1552 poly_ptr->vlist = usable_vlist;
1553 if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
1554 poly_ptr->smooth = usable_smooth;
1555 } else {
1556 num_ss_pts = (hinge_count*3)-2;
1557 vlist = (IntPoint*)malloc((num_ss_pts+1)*sizeof(IntPoint));
1558 if (vlist == NULL) FailAllocMessage();
1559 memset(vlist, 0, (num_ss_pts+1)*sizeof(IntPoint));
1560 if (!CanConvertSplineToStructuredSpline(ObjPtr, &hinge_count,
1561 vlist)) {
1562 #ifdef _TGIF_DBG /* debug, do not translate */
1563 TgAssert(FALSE, "conversion failed in SetObjSmooth()", NULL);
1564 #endif /* _TGIF_DBG */
1565 return;
1566 }
1567 if (smooth != NULL) free(smooth);
1568 free(poly_ptr->vlist);
1569 poly_ptr->vlist = vlist;
1570 poly_ptr->n = num_ss_pts;
1571 poly_ptr->smooth = NULL;
1572 }
1573 return;
1574 }
1575 break;
1576 case OBJ_POLYGON:
1577 polygon_ptr = ObjPtr->detail.g;
1578 smooth = polygon_ptr->smooth;
1579 n = polygon_ptr->n;
1580 switch (TypeIndex) {
1581 case LT_STRAIGHT:
1582 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
1583 usable_vlist = GetNumUsableStraightVs(&n, polygon_ptr->ssn,
1584 polygon_ptr->ssvlist);
1585 }
1586 if (usable_vlist != NULL) {
1587 if (polygon_ptr->vlist != NULL) free(polygon_ptr->vlist);
1588 polygon_ptr->n = n;
1589 polygon_ptr->vlist = usable_vlist;
1590 }
1591 if (smooth == NULL) smooth = (char*)malloc((n+1)*sizeof(char));
1592 if (smooth == NULL) FailAllocMessage();
1593 for (i=0; i < n; i++) smooth[i] = FALSE;
1594 polygon_ptr->smooth = smooth;
1595 return;
1596 case LT_SPLINE:
1597 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
1598 usable_vlist = GetNumUsableSplineVs(&n, &usable_smooth,
1599 polygon_ptr->ssn, polygon_ptr->ssvlist, polygon_ptr->ssmooth);
1600 }
1601 if (usable_vlist != NULL) {
1602 if (polygon_ptr->vlist != NULL) free(polygon_ptr->vlist);
1603 if (polygon_ptr->smooth != NULL) free(polygon_ptr->smooth);
1604 polygon_ptr->n = n;
1605 polygon_ptr->vlist = usable_vlist;
1606 polygon_ptr->smooth = usable_smooth;
1607 } else {
1608 if (smooth == NULL) smooth = (char*)malloc((n+1)*sizeof(char));
1609 if (smooth == NULL) FailAllocMessage();
1610 for (i=0; i < n; i++) smooth[i] = TRUE;
1611 polygon_ptr->smooth = smooth;
1612 }
1613 return;
1614 case LT_INTSPLINE:
1615 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
1616 usable_vlist = GetNumUsableIntSplineVsFromStructuredSpline(&n,
1617 polygon_ptr->n, polygon_ptr->vlist);
1618 } else {
1619 usable_vlist = GetNumUsableIntSplineVs(&n, polygon_ptr->n,
1620 polygon_ptr->vlist, polygon_ptr->smooth);
1621 }
1622 if (usable_vlist != NULL) {
1623 if (polygon_ptr->vlist != NULL) free(polygon_ptr->vlist);
1624 polygon_ptr->n = n;
1625 polygon_ptr->vlist = usable_vlist;
1626 }
1627 if (smooth != NULL) {
1628 free(smooth);
1629 polygon_ptr->smooth = NULL;
1630 }
1631 return;
1632 case LT_STRUCT_SPLINE:
1633 if (polygon_ptr->curved == LT_INTSPLINE) {
1634 usable_vlist = GetNumUsableStructuredSplineVs(&n, &usable_smooth,
1635 OBJ_POLYGON, polygon_ptr->n, polygon_ptr->vlist,
1636 polygon_ptr->intn, polygon_ptr->intvlist);
1637 }
1638 if (usable_vlist != NULL) {
1639 if (polygon_ptr->vlist != NULL) free(polygon_ptr->vlist);
1640 polygon_ptr->n = n;
1641 polygon_ptr->vlist = usable_vlist;
1642 if (polygon_ptr->smooth != NULL) free(polygon_ptr->smooth);
1643 polygon_ptr->smooth = usable_smooth;
1644 } else {
1645 num_ss_pts = (hinge_count*3)-2;
1646 vlist = (IntPoint*)malloc((num_ss_pts+2)*sizeof(IntPoint));
1647 if (vlist == NULL) FailAllocMessage();
1648 memset(vlist, 0, (num_ss_pts+2)*sizeof(IntPoint));
1649 if (!CanConvertSplineToStructuredSpline(ObjPtr, &hinge_count,
1650 vlist)) {
1651 #ifdef _TGIF_DBG /* debug, do not translate */
1652 TgAssert(FALSE, "conversion failed in SetObjSmooth()", NULL);
1653 #endif /* _TGIF_DBG */
1654 return;
1655 }
1656 if (smooth != NULL) free(smooth);
1657 free(polygon_ptr->vlist);
1658 polygon_ptr->vlist = vlist;
1659 polygon_ptr->n = num_ss_pts;
1660 polygon_ptr->smooth = NULL;
1661 }
1662 return;
1663 }
1664 break;
1665 }
1666 }
1667
1668 static
ChangeObjLineType(ObjPtr,TypeIndex,pn_failed_count)1669 int ChangeObjLineType(ObjPtr, TypeIndex, pn_failed_count)
1670 struct ObjRec *ObjPtr;
1671 int TypeIndex, *pn_failed_count;
1672 {
1673 struct ObjRec *obj_ptr=NULL;
1674 int changed=FALSE, hinge_count=0;
1675
1676 switch (ObjPtr->type) {
1677 case OBJ_POLY:
1678 if (CanConvertObjLineType(ObjPtr, TypeIndex, pn_failed_count,
1679 &hinge_count)) {
1680 /* hinge_count is only valid if TypeIndex is LT_STRUCT_SPLINE */
1681 SetObjSmooth(ObjPtr, TypeIndex, hinge_count);
1682 ObjPtr->detail.p->curved = TypeIndex;
1683 changed = TRUE;
1684 AdjObjSplineVs(ObjPtr);
1685 if (ObjPtr->detail.p->curved != LT_INTSPLINE) {
1686 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->n,
1687 ObjPtr->detail.p->vlist);
1688 } else {
1689 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->intn,
1690 ObjPtr->detail.p->intvlist);
1691 }
1692 }
1693 break;
1694 case OBJ_POLYGON:
1695 /* hinge_count is only valid if TypeIndex is LT_STRUCT_SPLINE */
1696 if (CanConvertObjLineType(ObjPtr, TypeIndex, pn_failed_count,
1697 &hinge_count)) {
1698 SetObjSmooth(ObjPtr, TypeIndex, hinge_count);
1699 ObjPtr->detail.g->curved = TypeIndex;
1700 changed = TRUE;
1701 AdjObjSplineVs(ObjPtr);
1702 if (ObjPtr->detail.g->curved != LT_INTSPLINE) {
1703 UpdPolyBBox(ObjPtr, ObjPtr->detail.g->n,
1704 ObjPtr->detail.g->vlist);
1705 } else {
1706 UpdPolyBBox(ObjPtr, ObjPtr->detail.g->intn,
1707 ObjPtr->detail.g->intvlist);
1708 }
1709 }
1710 break;
1711
1712 case OBJ_GROUP:
1713 case OBJ_SYM:
1714 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
1715 obj_ptr=obj_ptr->prev) {
1716 if (ChangeObjLineType(obj_ptr, TypeIndex, pn_failed_count)) {
1717 changed = TRUE;
1718 }
1719 }
1720 break;
1721 }
1722 if (changed) AdjObjBBox(ObjPtr);
1723 return changed;
1724 }
1725
ChangeAllSelLineType(TypeIndex,HighLight)1726 void ChangeAllSelLineType(TypeIndex, HighLight)
1727 int TypeIndex, HighLight;
1728 {
1729 struct SelRec *sel_ptr=NULL;
1730 int ltx, lty, rbx, rby, changed=FALSE, dont_do_obj=FALSE, failed_count=0;
1731
1732 if (topSel == NULL || stickyMenuSelection) {
1733 curSpline = TypeIndex;
1734 ShowLineType();
1735 UpdatePinnedMenu(MENU_LINETYPE);
1736 if (topSel == NULL) dont_do_obj = TRUE;
1737 }
1738 *gszMsgBox = '\0';
1739 switch (curSpline) {
1740 case LT_STRAIGHT:
1741 sprintf(gszMsgBox, TgLoadString(STID_LINE_TYPE_IS_STRAIGHT));
1742 break;
1743 case LT_SPLINE:
1744 sprintf(gszMsgBox, TgLoadString(STID_LINE_TYPE_IS_SPLINE));
1745 break;
1746 case LT_INTSPLINE:
1747 sprintf(gszMsgBox, TgLoadString(STID_LINE_TYPE_IS_INTSPLINE));
1748 break;
1749 case LT_STRUCT_SPLINE:
1750 sprintf(gszMsgBox, TgLoadString(STID_LINE_TYPE_IS_STRUCT_SPLINE));
1751 break;
1752 }
1753 Msg(gszMsgBox);
1754 if (dont_do_obj) return;
1755
1756 if (HighLight) HighLightReverse();
1757 StartCompositeCmd();
1758 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1759 PrepareToReplaceAnObj(sel_ptr->obj);
1760 if (ChangeObjLineType(sel_ptr->obj, TypeIndex, &failed_count)) {
1761 changed = TRUE;
1762 RecordReplaceAnObj(sel_ptr->obj);
1763 } else {
1764 AbortPrepareCmd(CMD_REPLACE);
1765 }
1766 }
1767 EndCompositeCmd();
1768
1769 if (changed) {
1770 SetFileModified(TRUE);
1771 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1772 UpdSelBBox();
1773 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1774 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
1775 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
1776 selRbY+GRID_ABS_SIZE(1));
1777 }
1778 if (HighLight) HighLightForward();
1779 if (failed_count > 0) {
1780 if (HighLight && failed_count == numObjSelected) {
1781 MsgBox(TgLoadString(STID_CANNOT_CONVERT_SEL_LINETYPE), TOOL_NAME,
1782 INFO_MB);
1783 } else {
1784 Msg(TgLoadString(STID_SOME_LT_FAILED_TO_CONVERT));
1785 }
1786 }
1787 }
1788
RefreshLineTypeMenu(menu)1789 void RefreshLineTypeMenu(menu)
1790 TgMenu *menu;
1791 {
1792 int i, num_items=menu->num_items;
1793 TgMenuItem *menuitems=menu->menuitems;
1794
1795 for (i=0; i < num_items; i++) {
1796 TgMenuItem *menu_item=(&menuitems[i]);
1797 TgMenuItem stMenuItem;
1798
1799 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1800 stMenuItem.state = TGBS_NORMAL;
1801 stMenuItem.checked = (i == curSpline);
1802 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
1803 &stMenuItem);
1804 }
1805 }
1806
CreateLineTypeMenu(parent_menu,x,y,menu_info,status_str_xlated)1807 TgMenu *CreateLineTypeMenu(parent_menu, x, y, menu_info, status_str_xlated)
1808 TgMenu *parent_menu;
1809 int x, y;
1810 TgMenuInfo *menu_info;
1811 int status_str_xlated; /* ignored, always 0 */
1812 {
1813 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1814
1815 if (menu != NULL) {
1816 TgMenuItem *menu_item=NULL;
1817 TgMenuItem stMenuItem;
1818
1819 menu->track_menubar = TRUE;
1820 TgAdjustMenuGeometry(menu, menuImageW, menuImageH, MAXLINETYPES);
1821 menu_item = (&menu->menuitems[curSpline]);
1822
1823 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1824 stMenuItem.checked = TRUE;
1825 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
1826 return TgDestroyMenu(menu, TRUE);
1827 }
1828 }
1829 return menu;
1830 }
1831
LineTypeMenu(X,Y,TrackMenubar)1832 int LineTypeMenu(X, Y, TrackMenubar)
1833 int X, Y, TrackMenubar;
1834 {
1835 int rc=INVALID;
1836 TgMenu *menu=(lineTypeMenuInfo.create_proc)(NULL, X, Y, &lineTypeMenuInfo,
1837 INVALID);
1838
1839 activeMenu = MENU_LINETYPE;
1840 if (menu != NULL) {
1841 menu->track_menubar = TrackMenubar;
1842
1843 rc = TgMenuLoop(menu);
1844 TgDestroyMenu(menu, TRUE);
1845 }
1846 return rc;
1847 }
1848
1849 /* ------------------ LineWidth Functions ------------------ */
1850
1851 static
ChangeObjLineWidth(ObjPtr,nMask,W,AW,AH,width_spec,aw_spec,ah_spec)1852 int ChangeObjLineWidth(ObjPtr, nMask, W, AW, AH, width_spec, aw_spec, ah_spec)
1853 struct ObjRec *ObjPtr;
1854 int nMask, W, AW, AH;
1855 char *width_spec, *aw_spec, *ah_spec;
1856 {
1857 register struct ObjRec *obj_ptr;
1858 register int changed=FALSE;
1859
1860 switch (ObjPtr->type) {
1861 case OBJ_POLY:
1862 if ((((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) &&
1863 (ObjPtr->detail.p->width != W ||
1864 strcmp(ObjPtr->detail.p->width_spec, width_spec) != 0)) ||
1865 (AW != (-1) && ((nMask & CHANGE_AW) == CHANGE_AW) &&
1866 (ObjPtr->detail.p->aw != AW ||
1867 strcmp(ObjPtr->detail.p->aw_spec, aw_spec) != 0)) ||
1868 (AH != (-1) && ((nMask & CHANGE_AH) == CHANGE_AH) &&
1869 (ObjPtr->detail.p->ah != AH ||
1870 strcmp(ObjPtr->detail.p->ah_spec, ah_spec) != 0))) {
1871 if (((nMask & CHANGE_WIDTH) == CHANGE_WIDTH)) {
1872 ObjPtr->detail.p->width = W;
1873 UtilStrCpyN(ObjPtr->detail.p->width_spec,
1874 sizeof(ObjPtr->detail.p->width_spec), width_spec);
1875 }
1876 if (AW != (-1) && ((nMask & CHANGE_AW) == CHANGE_AW)) {
1877 ObjPtr->detail.p->aw = AW;
1878 UtilStrCpyN(ObjPtr->detail.p->aw_spec,
1879 sizeof(ObjPtr->detail.p->aw_spec), aw_spec);
1880 }
1881 if (AH != (-1) && ((nMask & CHANGE_AH) == CHANGE_AH)) {
1882 ObjPtr->detail.p->ah = AH;
1883 UtilStrCpyN(ObjPtr->detail.p->ah_spec,
1884 sizeof(ObjPtr->detail.p->ah_spec), ah_spec);
1885 }
1886 changed = TRUE;
1887 AdjObjSplineVs(ObjPtr);
1888 if (ObjPtr->detail.p->curved != LT_INTSPLINE) {
1889 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->n,
1890 ObjPtr->detail.p->vlist);
1891 } else {
1892 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->intn,
1893 ObjPtr->detail.p->intvlist);
1894 }
1895 }
1896 break;
1897 case OBJ_BOX:
1898 if ((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) {
1899 if (ObjPtr->detail.b->width != W ||
1900 strcmp(ObjPtr->detail.b->width_spec, width_spec) != 0) {
1901 ObjPtr->detail.b->width = W;
1902 UtilStrCpyN(ObjPtr->detail.b->width_spec,
1903 sizeof(ObjPtr->detail.b->width_spec), width_spec);
1904 changed = TRUE;
1905 }
1906 }
1907 break;
1908 case OBJ_OVAL:
1909 if ((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) {
1910 if (ObjPtr->detail.o->width != W ||
1911 strcmp(ObjPtr->detail.o->width_spec, width_spec) != 0) {
1912 ObjPtr->detail.o->width = W;
1913 UtilStrCpyN(ObjPtr->detail.o->width_spec,
1914 sizeof(ObjPtr->detail.o->width_spec), width_spec);
1915 changed = TRUE;
1916 }
1917 }
1918 break;
1919 case OBJ_POLYGON:
1920 if ((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) {
1921 if (ObjPtr->detail.g->width != W ||
1922 strcmp(ObjPtr->detail.g->width_spec, width_spec) != 0) {
1923 ObjPtr->detail.g->width = W;
1924 UtilStrCpyN(ObjPtr->detail.g->width_spec,
1925 sizeof(ObjPtr->detail.g->width_spec), width_spec);
1926 changed = TRUE;
1927 }
1928 }
1929 break;
1930 case OBJ_ARC:
1931 if ((((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) &&
1932 (ObjPtr->detail.a->width != W ||
1933 strcmp(ObjPtr->detail.a->width_spec, width_spec) != 0)) ||
1934 (AW != (-1) && ((nMask & CHANGE_AW) == CHANGE_AW) &&
1935 (ObjPtr->detail.a->aw != AW ||
1936 strcmp(ObjPtr->detail.a->aw_spec, aw_spec) != 0)) ||
1937 (AH != (-1) && ((nMask & CHANGE_AH) == CHANGE_AH) &&
1938 (ObjPtr->detail.a->ah != AH ||
1939 strcmp(ObjPtr->detail.a->ah_spec, ah_spec) != 0))) {
1940 if (((nMask & CHANGE_WIDTH) == CHANGE_WIDTH)) {
1941 ObjPtr->detail.a->width = W;
1942 UtilStrCpyN(ObjPtr->detail.a->width_spec,
1943 sizeof(ObjPtr->detail.a->width_spec), width_spec);
1944 }
1945 if (AW != (-1) && ((nMask & CHANGE_AW) == CHANGE_AW)) {
1946 ObjPtr->detail.a->aw = AW;
1947 UtilStrCpyN(ObjPtr->detail.a->aw_spec,
1948 sizeof(ObjPtr->detail.a->aw_spec), aw_spec);
1949 }
1950 if (AH != (-1) && ((nMask & CHANGE_AH) == CHANGE_AH)) {
1951 ObjPtr->detail.a->ah = AH;
1952 UtilStrCpyN(ObjPtr->detail.a->ah_spec,
1953 sizeof(ObjPtr->detail.a->ah_spec), ah_spec);
1954 }
1955 changed = TRUE;
1956 AdjObjSplineVs(ObjPtr);
1957 }
1958 break;
1959 case OBJ_RCBOX:
1960 if ((nMask & CHANGE_WIDTH) == CHANGE_WIDTH) {
1961 if (ObjPtr->detail.rcb->width != W ||
1962 strcmp(ObjPtr->detail.rcb->width_spec, width_spec) != 0) {
1963 ObjPtr->detail.rcb->width = W;
1964 UtilStrCpyN(ObjPtr->detail.rcb->width_spec,
1965 sizeof(ObjPtr->detail.rcb->width_spec), width_spec);
1966 changed = TRUE;
1967 }
1968 }
1969 break;
1970
1971 case OBJ_GROUP:
1972 case OBJ_SYM:
1973 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
1974 obj_ptr=obj_ptr->prev) {
1975 if (ChangeObjLineWidth(obj_ptr, nMask, W, AW, AH, width_spec, aw_spec,
1976 ah_spec)) {
1977 changed = TRUE;
1978 }
1979 }
1980 break;
1981 }
1982 if (changed) AdjObjBBox(ObjPtr);
1983 return changed;
1984 }
1985
ChangeAllSelLineWidth(WidthIndex,HighLight)1986 void ChangeAllSelLineWidth(WidthIndex, HighLight)
1987 int WidthIndex, HighLight;
1988 {
1989 struct SelRec *sel_ptr;
1990 int ltx, lty, rbx, rby, changed=FALSE, w, aw, ah, dont_do_obj=FALSE;
1991 char *width_spec, *aw_spec, *ah_spec;
1992
1993 if (topSel == NULL || stickyMenuSelection) {
1994 lineWidth = WidthIndex;
1995 ShowLineWidth();
1996 UpdatePinnedMenu(MENU_LINEWIDTH);
1997 if (topSel == NULL) dont_do_obj = TRUE;
1998 }
1999 sprintf(gszMsgBox, TgLoadString(STID_LINE_WIDTH_SET_TO_GIVEN_STR),
2000 curWidthOfLineSpec[WidthIndex]);
2001 Msg(gszMsgBox);
2002 if (dont_do_obj) return;
2003
2004 w = curWidthOfLine[WidthIndex];
2005 aw = curArrowHeadW[WidthIndex];
2006 ah = curArrowHeadH[WidthIndex];
2007 width_spec = curWidthOfLineSpec[WidthIndex];
2008 aw_spec = curArrowHeadWSpec[WidthIndex];
2009 ah_spec = curArrowHeadHSpec[WidthIndex];
2010
2011 if (HighLight) HighLightReverse();
2012 StartCompositeCmd();
2013 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2014 PrepareToReplaceAnObj(sel_ptr->obj);
2015 if (ChangeObjLineWidth(sel_ptr->obj, CHANGE_LINE_ALL, w, aw, ah,
2016 width_spec, aw_spec, ah_spec)) {
2017 changed = TRUE;
2018 RecordReplaceAnObj(sel_ptr->obj);
2019 } else {
2020 AbortPrepareCmd(CMD_REPLACE);
2021 }
2022 }
2023 EndCompositeCmd();
2024
2025 if (changed) {
2026 SetFileModified(TRUE);
2027 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
2028 UpdSelBBox();
2029 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2030 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
2031 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
2032 selRbY+GRID_ABS_SIZE(1));
2033 }
2034 if (HighLight) HighLightForward();
2035 }
2036
2037 static
GetLineWidthMatch(index,width,aw,ah)2038 int GetLineWidthMatch(index, width, aw, ah)
2039 int index, width, aw, ah;
2040 {
2041 int diff=0;
2042
2043 if (width != INVALID && width != curWidthOfLine[index]) {
2044 diff += 10*abs(width-curWidthOfLine[index]);
2045 }
2046 if (aw != INVALID && aw != curArrowHeadW[index]) {
2047 diff += abs(aw-curArrowHeadW[index]);
2048 }
2049 if (ah != INVALID && ah != curArrowHeadH[index]) {
2050 diff += abs(ah-curArrowHeadH[index]);
2051 }
2052 return diff;
2053 }
2054
GetBestLineWidthIndex(width,aw,ah)2055 int GetBestLineWidthIndex(width, aw, ah)
2056 int width, aw, ah;
2057 {
2058 int min_diff=0, min_index=0, index=0;
2059
2060 min_diff = GetLineWidthMatch(0, width, aw, ah);
2061 for (index=1; index < maxLineWidths; index++) {
2062 int diff=GetLineWidthMatch(index, width, aw, ah);
2063
2064 if (diff < min_diff) {
2065 min_diff = diff;
2066 min_index = index;
2067 }
2068 }
2069 return min_index;
2070 }
2071
RefreshLineWidthMenu(menu)2072 void RefreshLineWidthMenu(menu)
2073 TgMenu *menu;
2074 {
2075 int i, num_items=menu->num_items;
2076 TgMenuItem *menuitems=menu->menuitems;
2077
2078 for (i=0; i < num_items; i++) {
2079 TgMenuItem *menu_item=(&menuitems[i]);
2080 TgMenuItem stMenuItem;
2081
2082 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2083 stMenuItem.state = TGBS_NORMAL;
2084 stMenuItem.checked = (i == lineWidth);
2085 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
2086 &stMenuItem);
2087 }
2088 }
2089
CreateLineWidthMenu(parent_menu,x,y,menu_info,status_str_xlated)2090 TgMenu *CreateLineWidthMenu(parent_menu, x, y, menu_info, status_str_xlated)
2091 TgMenu *parent_menu;
2092 int x, y;
2093 TgMenuInfo *menu_info;
2094 int status_str_xlated; /* ignored, always 0 */
2095 {
2096 int i=0;
2097 TgMenu *menu=NULL;
2098 TgMenuInfo stMenuInfo;
2099 TgMenuItemInfo *item_info=NULL;
2100
2101 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
2102 stMenuInfo.items = (TgMenuItemInfo*)malloc(
2103 (maxLineWidths+1)*sizeof(TgMenuItemInfo));
2104 if (stMenuInfo.items == NULL) FailAllocMessage();
2105 memset(stMenuInfo.items, 0, (maxLineWidths+1)*sizeof(TgMenuItemInfo));
2106 for (item_info=stMenuInfo.items, i=0; i < maxLineWidths; item_info++, i++) {
2107 item_info->menu_str = (char*)(Pixmap*)(&lineWidthPixmap[i]);
2108 item_info->shortcut_str = NULL;
2109 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_LINE_WIDTH_TO_GIVEN_S),
2110 curWidthOfLineSpec[i]);
2111 item_info->status_str = UtilStrDup(gszMsgBox);
2112 if (item_info->status_str == NULL) FailAllocMessage();
2113 item_info->submenu_info = NULL;
2114 item_info->cmdid = CMDID_CHANGEALLSELLINEWIDTH;
2115 }
2116 stMenuInfo.items[maxLineWidths].cmdid = INVALID;
2117
2118 /* the status_str has been translated in TgLoadCachedString() */
2119 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
2120 for (item_info=stMenuInfo.items, i=0; i < maxLineWidths; item_info++, i++) {
2121 UtilFree(item_info->status_str);
2122 }
2123 memset(stMenuInfo.items, 0, (maxLineWidths+1)*sizeof(TgMenuItemInfo));
2124 free(stMenuInfo.items);
2125 stMenuInfo.items = NULL;
2126 if (menu != NULL) {
2127 TgMenuItem *menu_item=NULL;
2128 TgMenuItem stMenuItem;
2129
2130 menu->track_menubar = TRUE;
2131 TgAdjustMenuGeometry(menu, menuImageW, menuImageH, maxLineWidths);
2132 menu_item = (&menu->menuitems[lineWidth]);
2133
2134 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2135 stMenuItem.checked = TRUE;
2136 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
2137 return TgDestroyMenu(menu, TRUE);
2138 }
2139 }
2140 return menu;
2141 }
2142
LineWidthMenu(X,Y,TrackMenubar)2143 int LineWidthMenu(X, Y, TrackMenubar)
2144 int X, Y, TrackMenubar;
2145 {
2146 int rc=INVALID;
2147 TgMenu *menu=(lineWidthMenuInfo.create_proc)(NULL, X, Y, &lineWidthMenuInfo,
2148 INVALID);
2149
2150 activeMenu = MENU_LINEWIDTH;
2151 if (menu != NULL) {
2152 menu->track_menubar = TrackMenubar;
2153
2154 rc = TgMenuLoop(menu);
2155 TgDestroyMenu(menu, TRUE);
2156 }
2157 return rc;
2158 }
2159
2160 /* ------------------ LineDash Functions ------------------ */
2161
2162 static
ChangeObjLineDash(ObjPtr,DashIndex)2163 int ChangeObjLineDash(ObjPtr, DashIndex)
2164 struct ObjRec *ObjPtr;
2165 int DashIndex;
2166 {
2167 register struct ObjRec *obj_ptr;
2168 int changed=FALSE;
2169
2170 switch (ObjPtr->type) {
2171 case OBJ_POLY:
2172 if (ObjPtr->detail.p->dash != DashIndex) {
2173 ObjPtr->detail.p->dash = DashIndex;
2174 changed = TRUE;
2175 }
2176 break;
2177 case OBJ_BOX:
2178 if (ObjPtr->detail.b->dash != DashIndex) {
2179 ObjPtr->detail.b->dash = DashIndex;
2180 changed = TRUE;
2181 }
2182 break;
2183 case OBJ_OVAL:
2184 if (ObjPtr->detail.o->dash != DashIndex) {
2185 ObjPtr->detail.o->dash = DashIndex;
2186 changed = TRUE;
2187 }
2188 break;
2189 case OBJ_POLYGON:
2190 if (ObjPtr->detail.g->dash != DashIndex) {
2191 ObjPtr->detail.g->dash = DashIndex;
2192 changed = TRUE;
2193 }
2194 break;
2195 case OBJ_ARC:
2196 if (ObjPtr->detail.a->dash != DashIndex) {
2197 ObjPtr->detail.a->dash = DashIndex;
2198 changed = TRUE;
2199 }
2200 break;
2201 case OBJ_RCBOX:
2202 if (ObjPtr->detail.rcb->dash != DashIndex) {
2203 ObjPtr->detail.rcb->dash = DashIndex;
2204 changed = TRUE;
2205 }
2206 break;
2207
2208 case OBJ_GROUP:
2209 case OBJ_SYM:
2210 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
2211 obj_ptr=obj_ptr->prev) {
2212 if (ChangeObjLineDash(obj_ptr, DashIndex)) {
2213 changed = TRUE;
2214 }
2215 }
2216 break;
2217 }
2218 return changed;
2219 }
2220
ChangeAllSelLineDash(DashIndex,HighLight)2221 void ChangeAllSelLineDash(DashIndex, HighLight)
2222 int DashIndex, HighLight;
2223 {
2224 register struct SelRec *sel_ptr;
2225 int changed=FALSE;
2226
2227 if (topSel == NULL || stickyMenuSelection) {
2228 curDash = DashIndex;
2229 ShowDash();
2230 UpdatePinnedMenu(MENU_LINEDASH);
2231 if (topSel == NULL) return;
2232 }
2233
2234 if (HighLight) HighLightReverse();
2235 StartCompositeCmd();
2236 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2237 PrepareToReplaceAnObj(sel_ptr->obj);
2238 if (ChangeObjLineDash(sel_ptr->obj, DashIndex)) {
2239 changed = TRUE;
2240 RecordReplaceAnObj(sel_ptr->obj);
2241 } else {
2242 AbortPrepareCmd(CMD_REPLACE);
2243 }
2244 }
2245 EndCompositeCmd();
2246
2247 if (changed) {
2248 SetFileModified(TRUE);
2249 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2250 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2251 }
2252 if (HighLight) HighLightForward();
2253 }
2254
RefreshLineDashMenu(menu)2255 void RefreshLineDashMenu(menu)
2256 TgMenu *menu;
2257 {
2258 int i, num_items=menu->num_items;
2259 TgMenuItem *menuitems=menu->menuitems;
2260
2261 for (i=0; i < num_items; i++) {
2262 TgMenuItem *menu_item=(&menuitems[i]);
2263 TgMenuItem stMenuItem;
2264
2265 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2266 stMenuItem.state = TGBS_NORMAL;
2267 stMenuItem.checked = (i == curDash);
2268 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
2269 &stMenuItem);
2270 }
2271 }
2272
CreateLineDashMenu(parent_menu,x,y,menu_info,status_str_xlated)2273 TgMenu *CreateLineDashMenu(parent_menu, x, y, menu_info, status_str_xlated)
2274 TgMenu *parent_menu;
2275 int x, y;
2276 TgMenuInfo *menu_info;
2277 int status_str_xlated; /* ignored, always 0 */
2278 {
2279 int i=0;
2280 TgMenu *menu=NULL;
2281 TgMenuInfo stMenuInfo;
2282 TgMenuItemInfo *item_info=NULL;
2283
2284 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
2285 stMenuInfo.items = (TgMenuItemInfo*)malloc(
2286 (MAXDASHES+1)*sizeof(TgMenuItemInfo));
2287 if (stMenuInfo.items == NULL) FailAllocMessage();
2288 memset(stMenuInfo.items, 0, (MAXDASHES+1)*sizeof(TgMenuItemInfo));
2289 for (item_info=stMenuInfo.items, i=0; i < MAXDASHES; item_info++, i++) {
2290 item_info->menu_str = (char*)(Pixmap*)(&lineDashPixmap[i]);
2291 item_info->shortcut_str = NULL;
2292 if (i == 0) {
2293 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_DASH_PAT_NO_DASH));
2294 } else {
2295 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_DASH_PAT_PAT_NUM),
2296 i);
2297 }
2298 item_info->status_str = UtilStrDup(gszMsgBox);
2299 if (item_info->status_str == NULL) FailAllocMessage();
2300 item_info->submenu_info = NULL;
2301 item_info->cmdid = CMDID_CHANGEALLSELLINEDASH;
2302 }
2303 stMenuInfo.items[MAXDASHES].cmdid = INVALID;
2304
2305 /* the status_str has been translated in TgLoadCachedString() */
2306 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
2307 for (item_info=stMenuInfo.items, i=0; i < MAXDASHES; item_info++, i++) {
2308 UtilFree(item_info->status_str);
2309 }
2310 memset(stMenuInfo.items, 0, (MAXDASHES+1)*sizeof(TgMenuItemInfo));
2311 free(stMenuInfo.items);
2312 stMenuInfo.items = NULL;
2313 if (menu != NULL) {
2314 TgMenuItem *menu_item=NULL;
2315 TgMenuItem stMenuItem;
2316
2317 menu->track_menubar = TRUE;
2318 TgAdjustMenuGeometry(menu, menuImageW, menuImageH, MAXDASHES);
2319 menu_item = (&menu->menuitems[curDash]);
2320
2321 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2322 stMenuItem.checked = TRUE;
2323 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
2324 return TgDestroyMenu(menu, TRUE);
2325 }
2326 }
2327 return menu;
2328 }
2329
LineDashMenu(X,Y,TrackMenubar)2330 int LineDashMenu(X, Y, TrackMenubar)
2331 int X, Y, TrackMenubar;
2332 {
2333 int rc=INVALID;
2334 TgMenu *menu=(lineDashMenuInfo.create_proc)(NULL, X, Y, &lineDashMenuInfo,
2335 INVALID);
2336
2337 activeMenu = MENU_LINEDASH;
2338 if (menu != NULL) {
2339 menu->track_menubar = TrackMenubar;
2340
2341 rc = TgMenuLoop(menu);
2342 TgDestroyMenu(menu, TRUE);
2343 }
2344 return rc;
2345 }
2346
2347 /* ------------------ Pen Functions ------------------ */
2348
ChangeObjPen(ObjPtr,PenIndex)2349 int ChangeObjPen(ObjPtr, PenIndex)
2350 struct ObjRec *ObjPtr;
2351 int PenIndex;
2352 {
2353 register struct ObjRec *obj_ptr;
2354 int changed=FALSE;
2355
2356 switch (ObjPtr->type) {
2357 case OBJ_POLY:
2358 if (ObjPtr->detail.p->pen != PenIndex) {
2359 ObjPtr->detail.p->pen = PenIndex;
2360 changed = TRUE;
2361 }
2362 break;
2363 case OBJ_TEXT:
2364 if (ObjPtr->detail.t->pen != PenIndex) {
2365 ObjPtr->detail.t->pen = PenIndex;
2366 AdjObjCache(ObjPtr);
2367 changed = TRUE;
2368 }
2369 break;
2370 case OBJ_BOX:
2371 if (ObjPtr->detail.b->pen != PenIndex) {
2372 ObjPtr->detail.b->pen = PenIndex;
2373 changed = TRUE;
2374 }
2375 break;
2376 case OBJ_OVAL:
2377 if (ObjPtr->detail.o->pen != PenIndex) {
2378 ObjPtr->detail.o->pen = PenIndex;
2379 changed = TRUE;
2380 }
2381 break;
2382 case OBJ_POLYGON:
2383 if (ObjPtr->detail.g->pen != PenIndex) {
2384 ObjPtr->detail.g->pen = PenIndex;
2385 changed = TRUE;
2386 }
2387 break;
2388 case OBJ_ARC:
2389 if (ObjPtr->detail.a->pen != PenIndex) {
2390 ObjPtr->detail.a->pen = PenIndex;
2391 changed = TRUE;
2392 }
2393 break;
2394 case OBJ_RCBOX:
2395 if (ObjPtr->detail.rcb->pen != PenIndex) {
2396 ObjPtr->detail.rcb->pen = PenIndex;
2397 changed = TRUE;
2398 }
2399 break;
2400
2401 case OBJ_GROUP:
2402 case OBJ_SYM:
2403 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
2404 obj_ptr=obj_ptr->prev) {
2405 if (ChangeObjPen(obj_ptr, PenIndex)) {
2406 changed = TRUE;
2407 }
2408 }
2409 break;
2410 }
2411 if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
2412 struct AttrRec *attr_ptr=ObjPtr->fattr;
2413
2414 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
2415 changed |= ChangeObjPen(attr_ptr->obj, PenIndex);
2416 }
2417 }
2418 return changed;
2419 }
2420
ChangeAllSelPen(PenIndex,HighLight)2421 void ChangeAllSelPen(PenIndex, HighLight)
2422 int PenIndex, HighLight;
2423 {
2424 register struct SelRec *sel_ptr;
2425 int changed=FALSE;
2426
2427 if (topSel == NULL || stickyMenuSelection) {
2428 if (!(curChoice == DRAWTEXT && textCursorShown)) {
2429 TieLooseEnds();
2430 }
2431 penPat = PenIndex;
2432 if (curChoice == DRAWTEXT && textCursorShown) {
2433 if (ChangeObjPen(curTextObj, PenIndex)) {
2434 curTextModified = TRUE;
2435 UpdCurTextBBox();
2436 RedrawCurText();
2437 SetFileModified(TRUE);
2438 if (cycleThroughChoice) {
2439 SetPushedFontValue(PUSH_PEN, penPat);
2440 }
2441 }
2442 } else {
2443 textCursorShown = FALSE;
2444 }
2445 ShowPen();
2446 UpdatePinnedMenu(MENU_PEN);
2447 if (topSel == NULL) return;
2448 }
2449
2450 if (HighLight) HighLightReverse();
2451 StartCompositeCmd();
2452 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2453 PrepareToReplaceAnObj(sel_ptr->obj);
2454 if (ChangeObjPen(sel_ptr->obj, PenIndex)) {
2455 changed = TRUE;
2456 RecordReplaceAnObj(sel_ptr->obj);
2457 } else {
2458 AbortPrepareCmd(CMD_REPLACE);
2459 }
2460 }
2461 EndCompositeCmd();
2462
2463 if (changed) {
2464 SetFileModified(TRUE);
2465 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2466 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2467 }
2468 if (HighLight) HighLightForward();
2469 }
2470
RefreshPenMenu(menu)2471 void RefreshPenMenu(menu)
2472 TgMenu *menu;
2473 {
2474 int i, num_items=menu->num_items;
2475 TgMenuItem *menuitems=menu->menuitems;
2476
2477 for (i=0; i < num_items; i++) {
2478 TgMenuItem *menu_item=(&menuitems[i]);
2479 TgMenuItem stMenuItem;
2480
2481 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2482 stMenuItem.state = TGBS_NORMAL;
2483 stMenuItem.checked = (i == penPat);
2484 TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
2485 &stMenuItem);
2486 }
2487 }
2488
CreatePenMenu(parent_menu,x,y,menu_info,status_str_xlated)2489 TgMenu *CreatePenMenu(parent_menu, x, y, menu_info, status_str_xlated)
2490 TgMenu *parent_menu;
2491 int x, y;
2492 TgMenuInfo *menu_info;
2493 int status_str_xlated; /* ignored, always 0 */
2494 {
2495 int i=0;
2496 TgMenu *menu=NULL;
2497 TgMenuInfo stMenuInfo;
2498 TgMenuItemInfo *item_info=NULL;
2499
2500 memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
2501 stMenuInfo.items = (TgMenuItemInfo*)malloc(
2502 (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
2503 if (stMenuInfo.items == NULL) FailAllocMessage();
2504 memset(stMenuInfo.items, 0, (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
2505 for (item_info=stMenuInfo.items, i=0; i < MAXPATTERNS; item_info++, i++) {
2506 item_info->menu_str = (char*)(Pixmap*)(&patPixmap[i]);
2507 item_info->shortcut_str = NULL;
2508 switch (i) {
2509 case NONEPAT:
2510 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_TO_NONE));
2511 break;
2512 case SOLIDPAT:
2513 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_TO_SOLID));
2514 break;
2515 case BACKPAT:
2516 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_TO_BACKGROUND));
2517 break;
2518 default:
2519 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_PEN_TO_PAT_NUM), i);
2520 break;
2521 }
2522 item_info->status_str = UtilStrDup(gszMsgBox);
2523 if (item_info->status_str == NULL) FailAllocMessage();
2524 item_info->submenu_info = NULL;
2525 item_info->cmdid = CMDID_CHANGEALLSELPEN;
2526 }
2527 stMenuInfo.items[MAXPATTERNS].cmdid = INVALID;
2528
2529 /* the status_str has been translated in TgLoadCachedString() */
2530 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
2531 for (item_info=stMenuInfo.items, i=0; i < MAXPATTERNS; item_info++, i++) {
2532 UtilFree(item_info->status_str);
2533 }
2534 memset(stMenuInfo.items, 0, (MAXPATTERNS+1)*sizeof(TgMenuItemInfo));
2535 free(stMenuInfo.items);
2536 stMenuInfo.items = NULL;
2537 if (menu != NULL) {
2538 TgMenuItem *menu_item=NULL;
2539 TgMenuItem stMenuItem;
2540
2541 menu->track_menubar = TRUE;
2542 TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH, 8);
2543 menu_item = (&menu->menuitems[penPat]);
2544
2545 memset(&stMenuItem, 0, sizeof(TgMenuItem));
2546 stMenuItem.checked = TRUE;
2547 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
2548 return TgDestroyMenu(menu, TRUE);
2549 }
2550 }
2551 return menu;
2552 }
2553
PenMenu(X,Y,TrackMenubar)2554 int PenMenu(X, Y, TrackMenubar)
2555 int X, Y, TrackMenubar;
2556 {
2557 int rc=INVALID;
2558 TgMenu *menu=(penMenuInfo.create_proc)(NULL, X, Y, &penMenuInfo, INVALID);
2559
2560 activeMenu = MENU_PEN;
2561 if (menu != NULL) {
2562 menu->track_menubar = TrackMenubar;
2563
2564 rc = TgMenuLoop(menu);
2565 TgDestroyMenu(menu, TRUE);
2566 }
2567 return rc;
2568 }
2569
2570 /* ------------------ Toggling and Changing Functions ------------------ */
2571
2572 static
ToggleObjLineType(ObjPtr)2573 int ToggleObjLineType(ObjPtr)
2574 struct ObjRec *ObjPtr;
2575 {
2576 register struct ObjRec *obj_ptr;
2577 register int changed=FALSE;
2578
2579 switch (ObjPtr->type) {
2580 case OBJ_POLY:
2581 ObjPtr->detail.p->curved = (ObjPtr->detail.p->curved+1) % MAXLINETYPES;
2582 changed = TRUE;
2583 AdjObjSplineVs(ObjPtr);
2584 if (ObjPtr->detail.p->curved != LT_INTSPLINE) {
2585 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->n,
2586 ObjPtr->detail.p->vlist);
2587 } else {
2588 UpdPolyBBox(ObjPtr, ObjPtr->detail.p->intn,
2589 ObjPtr->detail.p->intvlist);
2590 }
2591 break;
2592 case OBJ_POLYGON:
2593 ObjPtr->detail.g->curved = (ObjPtr->detail.g->curved+1) % MAXLINETYPES;
2594 changed = TRUE;
2595 AdjObjSplineVs(ObjPtr);
2596 if (ObjPtr->detail.g->curved != LT_INTSPLINE) {
2597 UpdPolyBBox(ObjPtr, ObjPtr->detail.g->n,
2598 ObjPtr->detail.g->vlist);
2599 } else {
2600 UpdPolyBBox(ObjPtr, ObjPtr->detail.g->intn,
2601 ObjPtr->detail.g->intvlist);
2602 }
2603 break;
2604
2605 case OBJ_GROUP:
2606 case OBJ_SYM:
2607 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
2608 obj_ptr=obj_ptr->prev) {
2609 if (ToggleObjLineType(obj_ptr)) {
2610 changed = TRUE;
2611 }
2612 }
2613 break;
2614 }
2615 if (changed) AdjObjBBox(ObjPtr);
2616 return changed;
2617 }
2618
ToggleAllSelLineType()2619 void ToggleAllSelLineType()
2620 {
2621 register struct SelRec *sel_ptr;
2622 register int changed=FALSE;
2623
2624 if (topSel == NULL) {
2625 curSpline = (curSpline+1) % MAXLINETYPES;
2626 ShowLineType();
2627 UpdatePinnedMenu(MENU_LINETYPE);
2628 return;
2629 }
2630
2631 HighLightReverse();
2632 StartCompositeCmd();
2633 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2634 PrepareToReplaceAnObj(sel_ptr->obj);
2635 if (ToggleObjLineType(sel_ptr->obj)) {
2636 changed = TRUE;
2637 RecordReplaceAnObj(sel_ptr->obj);
2638 } else {
2639 AbortPrepareCmd(CMD_REPLACE);
2640 }
2641 }
2642 EndCompositeCmd();
2643
2644 if (changed) {
2645 SetFileModified(TRUE);
2646 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2647 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2648 }
2649 HighLightForward();
2650 }
2651
2652 static
ChangeObjRCBRadius(ObjPtr,Radius)2653 int ChangeObjRCBRadius(ObjPtr, Radius)
2654 struct ObjRec *ObjPtr;
2655 int Radius;
2656 {
2657 register struct ObjRec *obj_ptr;
2658 int changed=FALSE;
2659
2660 switch (ObjPtr->type) {
2661 case OBJ_RCBOX:
2662 if (ObjPtr->detail.rcb->radius != Radius) {
2663 ObjPtr->detail.rcb->radius = Radius;
2664 AdjObjCache(ObjPtr);
2665 changed = TRUE;
2666 }
2667 break;
2668
2669 case OBJ_GROUP:
2670 case OBJ_SYM:
2671 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
2672 obj_ptr=obj_ptr->prev) {
2673 if (ChangeObjRCBRadius(obj_ptr, Radius)) {
2674 changed = TRUE;
2675 }
2676 }
2677 break;
2678 }
2679 return changed;
2680 }
2681
ChangeAllSelRCBRadius(Radius)2682 void ChangeAllSelRCBRadius(Radius)
2683 int Radius;
2684 {
2685 register struct SelRec *sel_ptr;
2686 int changed=FALSE;
2687
2688 if (topSel == NULL) {
2689 rcbRadius = Radius;
2690 ShowRCBRadius();
2691 return;
2692 }
2693
2694 HighLightReverse();
2695 StartCompositeCmd();
2696 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2697 PrepareToReplaceAnObj(sel_ptr->obj);
2698 if (ChangeObjRCBRadius(sel_ptr->obj, Radius)) {
2699 changed = TRUE;
2700 RecordReplaceAnObj(sel_ptr->obj);
2701 } else {
2702 AbortPrepareCmd(CMD_REPLACE);
2703 }
2704 }
2705 EndCompositeCmd();
2706
2707 if (changed) {
2708 SetFileModified(TRUE);
2709 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2710 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2711 }
2712 HighLightForward();
2713 }
2714
UpdateSelObjs()2715 void UpdateSelObjs()
2716 {
2717 struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
2718
2719 if (topSel == NULL) {
2720 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2721 return;
2722 }
2723 BackupCopiedProperties();
2724 HighLightReverse();
2725
2726 topSel = botSel = NULL;
2727 CopyProperties(FALSE);
2728
2729 topSel = saved_top_sel;
2730 botSel = saved_bot_sel;
2731 PasteProperties(FALSE);
2732
2733 HighLightForward();
2734 RestoreCopiedProperties();
2735 }
2736
ChangeAllSelRealLineWidth(nMask,Width,AW,AH,width_spec,aw_spec,ah_spec,HighLight)2737 void ChangeAllSelRealLineWidth(nMask, Width, AW, AH,
2738 width_spec, aw_spec, ah_spec, HighLight)
2739 int nMask, Width, AW, AH, HighLight;
2740 char *width_spec, *aw_spec, *ah_spec;
2741 {
2742 register struct SelRec *sel_ptr;
2743 int changed=FALSE;
2744
2745 if (topSel == NULL) {
2746 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2747 return;
2748 }
2749 if (HighLight) HighLightReverse();
2750 StartCompositeCmd();
2751 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2752 PrepareToReplaceAnObj(sel_ptr->obj);
2753 if (ChangeObjLineWidth(sel_ptr->obj, nMask, Width, AW, AH,
2754 width_spec, aw_spec, ah_spec)) {
2755 changed = TRUE;
2756 RecordReplaceAnObj(sel_ptr->obj);
2757 } else {
2758 AbortPrepareCmd(CMD_REPLACE);
2759 }
2760 }
2761 EndCompositeCmd();
2762
2763 if (changed) {
2764 int ltx=selLtX, lty=selLtY, rbx=selRbX, rby=selRbY;
2765
2766 SetFileModified(TRUE);
2767 UpdSelBBox();
2768 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2769 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
2770 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
2771 selRbY+GRID_ABS_SIZE(1));
2772 }
2773 if (HighLight) HighLightForward();
2774 }
2775
SetSelLineWidth(pszBuf)2776 void SetSelLineWidth(pszBuf)
2777 char *pszBuf;
2778 {
2779 char spec[MAXSTRING+1], *w_str=NULL, *aw_str=NULL, *ah_str=NULL, *c_ptr=NULL;
2780 int w=(-1), aw=(-1), ah=(-1), mult_set=FALSE;
2781 char width_spec[40], aw_spec[40], ah_spec[40];
2782 float fw, faw, fah, mult=((float)1.0);
2783
2784 if (topSel == NULL) {
2785 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2786 return;
2787 }
2788 *spec = '\0';
2789 if (pszBuf == NULL) {
2790 Dialog(TgLoadString(STID_ENTER_LINE_WIDTH_OPT_AW_AH),
2791 TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), spec);
2792 } else {
2793 UtilStrCpyN(spec, sizeof(spec), pszBuf);
2794 }
2795 UtilTrimBlanks(spec);
2796 if (*spec == '\0') return;
2797 *width_spec = *aw_spec = *ah_spec = '\0';
2798 if ((w_str=strtok(spec, ", \t\n\r")) == NULL) return;
2799 UtilTrimBlanks(w_str);
2800 if ((c_ptr=strstr(w_str, "in")) != NULL ||
2801 (c_ptr=strstr(w_str, "In")) != NULL ||
2802 (c_ptr=strstr(w_str, "IN")) != NULL) {
2803 *c_ptr = '\0';
2804 mult = (float)PIX_PER_INCH;
2805 mult_set = TRUE;
2806 } else if ((c_ptr=strstr(w_str, "cm")) != NULL ||
2807 (c_ptr=strstr(w_str, "Cm")) != NULL ||
2808 (c_ptr=strstr(w_str, "CM")) != NULL) {
2809 *c_ptr = '\0';
2810 mult = (float)ONE_CM;
2811 mult_set = TRUE;
2812 }
2813 if (sscanf(w_str, "%f", &fw) != 1 || fw < (float)0.0) {
2814 sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_STR_WIDTH), w_str);
2815 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2816 return;
2817 }
2818 if (mult_set) {
2819 fw *= mult;
2820 sprintf(width_spec, "%.3f", fw);
2821 } else {
2822 UtilStrCpyN(width_spec, sizeof(width_spec), w_str);
2823 }
2824 w = round(fw);
2825
2826 if ((aw_str=strtok(NULL, ", \t\n\r")) != NULL &&
2827 (ah_str=strtok(NULL, ", \t\n\r")) != NULL) {
2828 int aw_mult_set=FALSE, ah_mult_set=FALSE;
2829 float aw_mult=((float)1.0), ah_mult=((float)1.0);
2830
2831 UtilTrimBlanks(aw_str);
2832 UtilTrimBlanks(ah_str);
2833
2834 if ((c_ptr=strstr(aw_str, "in")) != NULL ||
2835 (c_ptr=strstr(aw_str, "In")) != NULL ||
2836 (c_ptr=strstr(aw_str, "IN")) != NULL) {
2837 *c_ptr = '\0';
2838 aw_mult = (float)PIX_PER_INCH;
2839 aw_mult_set = TRUE;
2840 } else if ((c_ptr=strstr(aw_str, "cm")) != NULL ||
2841 (c_ptr=strstr(aw_str, "Cm")) != NULL ||
2842 (c_ptr=strstr(aw_str, "CM")) != NULL) {
2843 *c_ptr = '\0';
2844 aw_mult = (float)ONE_CM;
2845 aw_mult_set = TRUE;
2846 }
2847 if ((c_ptr=strstr(ah_str, "in")) != NULL ||
2848 (c_ptr=strstr(ah_str, "In")) != NULL ||
2849 (c_ptr=strstr(ah_str, "IN")) != NULL) {
2850 *c_ptr = '\0';
2851 ah_mult = (float)PIX_PER_INCH;
2852 ah_mult_set = TRUE;
2853 } else if ((c_ptr=strstr(ah_str, "cm")) != NULL ||
2854 (c_ptr=strstr(ah_str, "Cm")) != NULL ||
2855 (c_ptr=strstr(ah_str, "CM")) != NULL) {
2856 *c_ptr = '\0';
2857 ah_mult = (float)ONE_CM;
2858 ah_mult_set = TRUE;
2859 }
2860 if (sscanf(aw_str, "%f", &faw) != 1 || faw < (float)0.0 ||
2861 sscanf(ah_str, "%f", &fah) != 1 || fah < (float)0.0) {
2862 sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_STR_AW_AH),
2863 aw_str, ah_str);
2864 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2865 return;
2866 }
2867 if (aw_mult_set) {
2868 faw *= aw_mult;
2869 sprintf(aw_spec, "%.3f", faw);
2870 } else {
2871 UtilStrCpyN(aw_spec, sizeof(aw_spec), aw_str);
2872 }
2873 aw = round(faw);
2874
2875 if (ah_mult_set) {
2876 fah *= ah_mult;
2877 sprintf(ah_spec, "%.3f", fah);
2878 } else {
2879 UtilStrCpyN(ah_spec, sizeof(ah_spec), ah_str);
2880 }
2881 ah = round(fah);
2882 }
2883 ChangeAllSelRealLineWidth(CHANGE_LINE_ALL, w, aw, ah,
2884 width_spec, aw_spec, ah_spec, TRUE);
2885 }
2886
2887