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/special.c,v 1.19 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_SPECIAL_C_
22
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25
26 #include "animate.e"
27 #include "attr.e"
28 #include "auxtext.e"
29 #include "choice.e"
30 #include "cmd.e"
31 #include "color.e"
32 #include "cutpaste.e"
33 #include "cursor.e"
34 #include "dialog.e"
35 #include "drawing.e"
36 #include "dup.e"
37 #include "edit.e"
38 #include "exec.e"
39 #include "file.e"
40 #include "font.e"
41 #include "grid.e"
42 #include "group.e"
43 #include "list.e"
44 #include "mainloop.e"
45 #include "mainmenu.e"
46 #include "mark.e"
47 #include "menu.e"
48 #include "menuinfo.e"
49 #include "miniline.e"
50 #include "msg.e"
51 #include "move.e"
52 #include "names.e"
53 #include "obj.e"
54 #include "page.e"
55 #include "pattern.e"
56 #include "poly.e"
57 #include "raster.e"
58 #include "rect.e"
59 #include "remote.e"
60 #include "ruler.e"
61 #include "scroll.e"
62 #include "select.e"
63 #include "setup.e"
64 #include "special.e"
65 #include "stk.e"
66 #include "stretch.e"
67 #include "strtbl.e"
68 #include "tangram2.e"
69 #include "text.e"
70 #include "util.e"
71 #include "version.e"
72 #include "wb.e"
73
74 int placingTopObj=FALSE;
75 int connectingPortsByWire=FALSE;
76 int connectingPortsFromInternalCommand=TRUE;
77
78 char gszAttrSeparator[]=
79 "// -------- attribute separator (please do not modify or delete) -------- //";
80
81 static int showWireSignalName=TRUE;
82 static int gnPinWarning=FALSE;
83
84 static
CreatePinObj(obj_ptr1,obj_ptr2,sym_count)85 struct ObjRec *CreatePinObj(obj_ptr1, obj_ptr2, sym_count)
86 struct ObjRec *obj_ptr1, *obj_ptr2;
87 int sym_count;
88 {
89 struct ObjRec *obj_ptr=NULL;
90 struct ObjRec *saved_top_obj=topObj;
91 struct ObjRec *saved_bot_obj=botObj;
92 int cx1, cy1, cx2, cy2;
93
94 curPage->top = topObj = NULL;
95 curPage->bot = botObj = NULL;
96 if (sym_count == 1) {
97 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
98 if (topSel == NULL) FailAllocMessage();
99 topObj = botObj = obj_ptr1;
100 topSel->obj = obj_ptr1;
101 topSel->next = topSel->prev = NULL;
102 numObjSelected = 1;
103
104 GroupSingleObj(TRUE);
105 obj_ptr = topSel->obj;
106 RemoveAllSel();
107 } else {
108 if (obj_ptr2->fattr != NULL) {
109 obj_ptr = obj_ptr2;
110 obj_ptr2 = obj_ptr1;
111 obj_ptr1 = obj_ptr;
112 }
113 cx1 = ((obj_ptr1->obbox.ltx+obj_ptr1->obbox.rbx)>>1);
114 cy1 = ((obj_ptr1->obbox.lty+obj_ptr1->obbox.rby)>>1);
115 cx2 = ((obj_ptr2->obbox.ltx+obj_ptr2->obbox.rbx)>>1);
116 cy2 = ((obj_ptr2->obbox.lty+obj_ptr2->obbox.rby)>>1);
117 MoveObj(obj_ptr2, cx1-cx2, cy1-cy2);
118 obj_ptr1->next = obj_ptr2;
119 obj_ptr1->prev = NULL;
120 obj_ptr2->next = NULL;
121 obj_ptr2->prev = obj_ptr1;
122 CreateGroupObj(obj_ptr1, obj_ptr2);
123 obj_ptr = topObj;
124 }
125 AdjObjBBox(obj_ptr);
126 obj_ptr->type = OBJ_PIN;
127
128 curPage->top = topObj = saved_top_obj;
129 curPage->bot = botObj = saved_bot_obj;
130
131 if (!gnPinWarning) {
132 gnPinWarning = TRUE;
133 strcpy(gszMsgBox, TgLoadString(STID_WARN_PIN_NOT_SUPPORTED));
134 if (PRTGIF) {
135 fprintf(stderr, "%s\n", gszMsgBox);
136 } else {
137 MsgBox(gszMsgBox, TOOL_NAME, STOP_MB);
138 }
139 }
140 return obj_ptr;
141 }
142
ReadSymbol(FP,FileType)143 struct ObjRec *ReadSymbol(FP, FileType)
144 FILE *FP;
145 int FileType;
146 {
147 register struct AttrRec *attr_ptr;
148 struct ObjRec *obj_ptr, *obj_ptr1=NULL, *obj_ptr2=NULL;
149 int read_status, sym_count=0;
150
151 SetWatchCursor(drawWindow);
152 SetWatchCursor(mainWindow);
153
154 importingFile = TRUE; /* ignore 'state' info but set fileVersion */
155 readingPageNum = loadedCurPageNum = 0;
156 foundGoodStateObject = FALSE;
157 while ((read_status=ReadObj(FP, &obj_ptr)) == TRUE) {
158 if (obj_ptr != NULL) {
159 if (obj_ptr->type == OBJ_SYM) {
160 int done=FALSE;
161
162 UnlockAnObj(obj_ptr);
163 obj_ptr->type = OBJ_ICON;
164
165 attr_ptr = obj_ptr->lattr;
166 for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->prev) {
167 attr_ptr->inherited = TRUE;
168 }
169 if (FileType == SYM_FILE_TYPE) {
170 done = TRUE;
171 } else {
172 if (obj_ptr1 == NULL) {
173 obj_ptr1 = obj_ptr;
174 } else if (obj_ptr2 == NULL) {
175 obj_ptr2 = obj_ptr;
176 }
177 if (++sym_count >= 2) {
178 obj_ptr = CreatePinObj(obj_ptr1, obj_ptr2, sym_count);
179 done = TRUE;
180 }
181 }
182 if (done) {
183 importingFile = FALSE;
184 SetDefaultCursor(mainWindow);
185 ShowCursor();
186 return obj_ptr;
187 }
188 } else {
189 FreeObj(obj_ptr);
190 }
191 }
192 }
193 importingFile = FALSE;
194 if (!PRTGIF && colorLayers && needToRedrawColorWindow) {
195 RedrawColorWindow();
196 }
197 obj_ptr = NULL;
198 if (read_status == INVALID) {
199 sprintf(gszMsgBox, TgLoadString(STID_FILE_VER_ABORT_READ_SYMBOL),
200 fileVersion, TOOL_NAME, homePageURL);
201 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
202 } else if (FileType == PIN_FILE_TYPE && sym_count == 1) {
203 obj_ptr = CreatePinObj(obj_ptr1, obj_ptr2, sym_count);
204 }
205 SetDefaultCursor(mainWindow);
206 ShowCursor();
207 return obj_ptr;
208 }
209
GetObjRepresentation(PathName,SymName,FileType)210 struct ObjRec *GetObjRepresentation(PathName, SymName, FileType)
211 char *PathName, *SymName;
212 int FileType;
213 {
214 char file_name[MAXPATHLENGTH], *rest=NULL;
215 char tmp_filename[MAXPATHLENGTH], tmp_filefullpath[MAXPATHLENGTH];
216 int short_name, tmp_linenum;
217 struct ObjRec *obj_ptr;
218 FILE *fp;
219
220 sprintf(file_name, "%s%c%s.%s", PathName, DIR_SEP, SymName, SYM_FILE_EXT);
221 if ((short_name=IsPrefix(bootDir, file_name, &rest))) ++rest;
222
223 if ((fp=fopen(file_name, "r")) == NULL) {
224 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
225 (short_name ? rest : file_name));
226 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
227 return NULL;
228 }
229
230 strcpy(tmp_filefullpath, scanFileFullPath);
231 strcpy(tmp_filename, scanFileName);
232 tmp_linenum = scanLineNum;
233 UtilStrCpyN(scanFileFullPath, sizeof(scanFileFullPath), file_name);
234 strcpy(scanFileName, (short_name ? rest : file_name));
235 scanLineNum = 0;
236
237 if ((obj_ptr=ReadSymbol(fp, FileType)) != NULL) {
238 obj_ptr->id = objId++;
239 obj_ptr->dirty = FALSE;
240 strcpy(obj_ptr->detail.r->s, SymName);
241 obj_ptr->detail.r->rotate = ROTATE0;
242 obj_ptr->detail.r->flip = NO_FLIP;
243 obj_ptr->detail.r->deck_index = (-1);
244 obj_ptr->detail.r->pin_connected = 0;
245 obj_ptr->detail.r->first_conn = obj_ptr->detail.r->last_conn = NULL;
246 AdjObjBBox(obj_ptr);
247 }
248
249 strcpy(scanFileFullPath, tmp_filefullpath);
250 strcpy(scanFileName, tmp_filename);
251 scanLineNum = tmp_linenum;
252
253 fclose(fp);
254 return obj_ptr;
255 }
256
PlaceTopObj(ObjPtr,savedTopObj,savedBotObj)257 unsigned int PlaceTopObj(ObjPtr, savedTopObj, savedBotObj)
258 struct ObjRec *ObjPtr, *savedTopObj, *savedBotObj;
259 {
260 int x, y, grid_x, grid_y, dx, dy, placing=TRUE;
261 int cursor_x, cursor_y, orig_x, orig_y, obj_ltx, obj_lty, obj_rbx, obj_rby;
262 int grid_obj_ltx, grid_obj_lty, grid_dx=0, grid_dy=0;
263 Window root_win, child_win;
264 int root_x, root_y, first_time=TRUE;
265 unsigned int status, button_pressed=Button1;
266 XEvent input, ev;
267
268 RedrawMsg(TRUE);
269
270 XFlush(mainDisplay);
271 XSync(mainDisplay, False);
272
273 placingTopObj = TRUE;
274 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev) ||
275 XCheckMaskEvent(mainDisplay, VisibilityChangeMask, &ev)) {
276 ExposeEventHandler(&ev, TRUE);
277 }
278 obj_ltx = OFFSET_X(ObjPtr->obbox.ltx); obj_lty = OFFSET_Y(ObjPtr->obbox.lty);
279 obj_rbx = OFFSET_X(ObjPtr->obbox.rbx); obj_rby = OFFSET_Y(ObjPtr->obbox.rby);
280 GridXY(obj_ltx, obj_lty, &grid_obj_ltx, &grid_obj_lty);
281
282 dx = dy = 0;
283 if (!debugNoPointerGrab) {
284 XGrabPointer(mainDisplay, drawWindow, False,
285 PointerMotionMask | ButtonPressMask,
286 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
287 }
288 if (XCheckMaskEvent(mainDisplay, PointerMotionMask, &input)) {
289 first_time = FALSE;
290
291 cursor_x = input.xmotion.x;
292 cursor_y = input.xmotion.y;
293 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &input)) {
294 cursor_x = input.xmotion.x;
295 cursor_y = input.xmotion.y;
296 }
297 GridXY(cursor_x, cursor_y, &orig_x, &orig_y);
298 grid_dx = orig_x-grid_obj_ltx; grid_dy = orig_y-grid_obj_lty;
299 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx, obj_lty+grid_dy,
300 obj_rbx+grid_dx, obj_rby+grid_dy);
301 }
302
303 while (placing) {
304 XNextEvent(mainDisplay, &input);
305
306 if (first_time) {
307 first_time = FALSE;
308
309 XQueryPointer(mainDisplay, drawWindow, &root_win, &child_win,
310 &root_x, &root_y, &cursor_x, &cursor_y, &status);
311
312 GridXY(cursor_x, cursor_y, &orig_x, &orig_y);
313 grid_dx = orig_x-grid_obj_ltx; grid_dy = orig_y-grid_obj_lty;
314 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx, obj_lty+grid_dy,
315 obj_rbx+grid_dx, obj_rby+grid_dy);
316 }
317
318 if (input.type == Expose || input.type == VisibilityNotify) {
319 /* SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx, obj_lty+grid_dy,
320 obj_rbx+grid_dx, obj_rby+grid_dy); */
321 if (savedTopObj != NULL && savedBotObj != NULL) {
322 struct ObjRec *saved_top_obj=topObj, *saved_bot_obj=botObj;
323
324 curPage->top = topObj = NULL;
325 curPage->bot = botObj = NULL;
326 curPage->top = topObj = savedTopObj;
327 curPage->bot = botObj = savedBotObj;
328 placingTopObj = FALSE;
329 RedrawDrawWindow(botObj);
330 placingTopObj = TRUE;
331 curPage->top = topObj = saved_top_obj;
332 curPage->bot = botObj = saved_bot_obj;
333 }
334 ExposeEventHandler(&input, TRUE);
335 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx, obj_lty+grid_dy,
336 obj_rbx+grid_dx, obj_rby+grid_dy);
337 } else if (input.type == ButtonPress) {
338 XUngrabPointer(mainDisplay, CurrentTime);
339 button_pressed = input.xbutton.button;
340 placing = FALSE;
341 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx+dx,
342 obj_lty+grid_dy+dy, obj_rbx+grid_dx+dx, obj_rby+grid_dy+dy);
343 grid_dx = ABS_SIZE(grid_dx+dx);
344 grid_dy = ABS_SIZE(grid_dy+dy);
345 MoveObj(ObjPtr, grid_dx, grid_dy);
346 numRedrawBBox = 0;
347 ShowInterrupt(1);
348 placingTopObj = FALSE;
349 ObjPtr->tmp_parent = NULL;
350 DrawObj(drawWindow, ObjPtr);
351 HideInterrupt();
352 } else if (input.type == MotionNotify) {
353 int anywhere=(input.xmotion.state & (ShiftMask | ControlMask));
354 int saved_snap=snapOn;
355
356 x = input.xmotion.x;
357 y = input.xmotion.y;
358 if (anywhere) snapOn = FALSE;
359 GridXY(x, y, &grid_x, &grid_y);
360 if (anywhere) snapOn = saved_snap;
361 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx+dx,
362 obj_lty+grid_dy+dy, obj_rbx+grid_dx+dx, obj_rby+grid_dy+dy);
363 dx = grid_x - orig_x;
364 dy = grid_y - orig_y;
365 SelBox(drawWindow, revDefaultGC, obj_ltx+grid_dx+dx,
366 obj_lty+grid_dy+dy, obj_rbx+grid_dx+dx, obj_rby+grid_dy+dy);
367 MarkRulers(grid_x, grid_y);
368 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
369 }
370 }
371 XSync(mainDisplay, True);
372 placingTopObj = FALSE;
373 return button_pressed;
374 }
375
376 static
UnMakeIconicOnInstantiate(obj_ptr)377 int UnMakeIconicOnInstantiate(obj_ptr)
378 struct ObjRec *obj_ptr;
379 {
380 register struct AttrRec *attr_ptr;
381
382 for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=attr_ptr->prev) {
383 if (*attr_ptr->attr_name.s=='\0' &&
384 (strcmp(attr_ptr->attr_value.s, "unmakeiconic_on_instantiate")==0 ||
385 strcmp(attr_ptr->attr_value.s,
386 "unmakeiconic_on_instantiate_delete_attrs")==0)) {
387 return TRUE;
388 }
389 }
390 return FALSE;
391 }
392
393 static
UnMakeIconicOnInstantiateDeleteAttrs(obj_ptr)394 int UnMakeIconicOnInstantiateDeleteAttrs(obj_ptr)
395 struct ObjRec *obj_ptr;
396 {
397 register struct AttrRec *attr_ptr;
398
399 for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=attr_ptr->prev) {
400 if (*attr_ptr->attr_name.s=='\0' && strcmp(attr_ptr->attr_value.s,
401 "unmakeiconic_on_instantiate_delete_attrs")==0) {
402 return TRUE;
403 }
404 }
405 return FALSE;
406 }
407
408 static
DeleteUnMakeIconicOnInstantiateText()409 void DeleteUnMakeIconicOnInstantiateText()
410 {
411 struct SelRec *sel_ptr;
412 struct ObjRec *text_obj_ptr=NULL;
413
414 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
415 if (sel_ptr->obj->type == OBJ_TEXT) {
416 struct DynStrRec *dyn_str_ptr=GetTextFirstDynStr(sel_ptr->obj);
417
418 if (strcmp(dyn_str_ptr->s, "unmakeiconic_on_instantiate") == 0) {
419 text_obj_ptr = sel_ptr->obj;
420 break;
421 }
422 }
423 }
424 if (text_obj_ptr == NULL) {
425 sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_NAMED_OBJ_IN_FUNC),
426 "unmakeiconic_on_instantiate",
427 "DeleteUnMakeIconicOnInstantiateText()");
428 TgAssert(FALSE, gszMsgBox, NULL);
429 XFlush(mainDisplay);
430 XSync(mainDisplay, False);
431 return;
432 }
433 MakeQuiescent();
434 topSel = (struct SelRec *)malloc(sizeof(struct SelRec));
435 if (topSel == NULL) FailAllocMessage();
436 topSel->next = NULL;
437 topSel->obj = text_obj_ptr;
438 topSel->prev = NULL;
439 botSel = topSel;
440 UpdSelBBox();
441 HighLightForward();
442 DelAllSelObj();
443 }
444
Instantiate()445 void Instantiate()
446 {
447 char file_name[MAXPATHLENGTH], *rest=NULL, msg[MAXSTRING];
448 char sym_name[MAXPATHLENGTH], path_name[MAXPATHLENGTH];
449 char ext_str[MAXPATHLENGTH];
450 char tmp_filename[MAXPATHLENGTH], tmp_filefullpath[MAXPATHLENGTH];
451 int short_name=FALSE, file_type=INVALID, tmp_linenum=0, len=0, ext_len=0;
452 struct ObjRec *obj_ptr=NULL;
453 FILE *fp=NULL;
454 XEvent ev;
455
456 MakeQuiescent();
457
458 if (*curDomainName == '\0') {
459 strcpy(msg, TgLoadString(STID_SEL_A_SYM_TO_INSTAN_IN_NONE));
460 } else {
461 sprintf(msg, TgLoadString(STID_SEL_A_SYM_TO_INSTAN_IN_DOMAIN),
462 curDomainName);
463 }
464 if (SelectFromLibrary(msg, SYM_FILE_EXT, sym_name, path_name) == INVALID) {
465 return;
466 }
467 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev) ||
468 XCheckMaskEvent(mainDisplay, VisibilityChangeMask, &ev)) {
469 ExposeEventHandler(&ev, TRUE);
470 }
471 sprintf(file_name, "%s%c%s", path_name, DIR_SEP, sym_name);
472
473 len = strlen(sym_name);
474 sprintf(ext_str, ".%s", SYM_FILE_EXT);
475 ext_len = strlen(ext_str);
476 if (len > ext_len && strcmp(ext_str, &sym_name[len-ext_len]) == 0) {
477 sym_name[len-ext_len] = '\0';
478 file_type = SYM_FILE_TYPE;
479 } else {
480 sprintf(ext_str, ".%s", PIN_FILE_EXT);
481 ext_len = strlen(ext_str);
482 if (len > ext_len && strcmp(ext_str, &sym_name[len-ext_len]) == 0) {
483 sym_name[len-ext_len] = '\0';
484 file_type = PIN_FILE_TYPE;
485 }
486 }
487 if ((short_name=IsPrefix(bootDir, file_name, &rest))) ++rest;
488
489 if (file_type == INVALID) {
490 sprintf(gszMsgBox, TgLoadString(STID_CANT_INSTAN_FILE_UNKNOWN_EXT),
491 (short_name ? rest : file_name));
492 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
493 return;
494 }
495 if ((fp=fopen(file_name, "r")) == NULL) {
496 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
497 (short_name ? rest : file_name));
498 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
499 return;
500 }
501 strcpy(tmp_filefullpath, scanFileFullPath);
502 strcpy(tmp_filename, scanFileName);
503 tmp_linenum = scanLineNum;
504 UtilStrCpyN(scanFileFullPath, sizeof(scanFileFullPath), file_name);
505 strcpy(scanFileName, (short_name ? rest : file_name));
506 scanLineNum = 0;
507
508 SetWatchCursor(drawWindow);
509 SetWatchCursor(mainWindow);
510 if ((obj_ptr=ReadSymbol(fp, file_type)) != NULL) {
511 char *psz=NULL;
512 struct AttrRec *name_attr=NULL;
513
514 sprintf(msg, TgLoadCachedString(CSTID_INSTANTIATING_FILE_DOTS),
515 (short_name ? rest : file_name));
516 SetStringStatus(msg);
517 obj_ptr->id = objId++;
518 obj_ptr->dirty = FALSE;
519 strcpy(obj_ptr->detail.r->s, sym_name);
520 obj_ptr->detail.r->rotate = ROTATE0;
521 obj_ptr->detail.r->flip = NO_FLIP;
522 obj_ptr->detail.r->deck_index = (-1);
523 obj_ptr->detail.r->pin_connected = 0;
524 obj_ptr->detail.r->first_conn = obj_ptr->detail.r->last_conn = NULL;
525 name_attr = FindAttrWithName(obj_ptr, "name=", NULL);
526 if (name_attr != NULL &&
527 (psz=strstr(name_attr->attr_value.s, "%d")) != NULL &&
528 (strstr(++psz, "%d")) == NULL) {
529 sprintf(gszMsgBox, name_attr->attr_value.s, obj_ptr->id-1);
530 DynStrSet(&name_attr->attr_value, gszMsgBox);
531 UpdAttr(name_attr);
532 UpdTextBBox(name_attr->obj);
533 }
534 AssignNewObjIds(obj_ptr);
535 AddObj(NULL, topObj, obj_ptr);
536 AdjObjBBox(obj_ptr);
537 PlaceTopObj(obj_ptr, NULL, NULL);
538
539 SelectTopObj();
540 if (UnMakeIconicOnInstantiate(obj_ptr)) {
541 StartCompositeCmd();
542 RecordNewObjCmd();
543 UnMakeIconic();
544 if (UnMakeIconicOnInstantiateDeleteAttrs(obj_ptr)) {
545 gnDeleteAttrsWhileUngrouping = TRUE;
546 UngroupSelObj(TRUE, TRUE);
547 gnDeleteAttrsWhileUngrouping = FALSE;
548 } else {
549 UngroupSelObj(TRUE, TRUE);
550 DeleteUnMakeIconicOnInstantiateText();
551 }
552 EndCompositeCmd();
553 } else {
554 RecordNewObjCmd();
555 }
556 SetFileModified(TRUE);
557 justDupped = FALSE;
558 } else {
559 sprintf(gszMsgBox, TgLoadString(STID_CANT_FND_SYM_IN_NAMED_TO_INST),
560 (short_name ? rest : file_name));
561 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
562 }
563 fclose(fp);
564
565 strcpy(scanFileFullPath, tmp_filefullpath);
566 strcpy(scanFileName, tmp_filename);
567 scanLineNum = tmp_linenum;
568
569 SetDefaultCursor(mainWindow);
570 SetDefaultCursor(drawWindow);
571 Msg("");
572
573 if (topSel != NULL && topSel == botSel && topSel->obj->type == OBJ_ICON) {
574 /* something has been instantiated */
575 char *psz=NULL;
576 struct AttrRec *name_attr=NULL, *exec_attr=NULL;
577
578 name_attr = FindAttrWithName(topSel->obj, "name=", NULL);
579 if (name_attr != NULL &&
580 (psz=strstr(name_attr->attr_value.s, "%d")) != NULL &&
581 (strstr(++psz, "%d")) == NULL) {
582 sprintf(gszMsgBox, name_attr->attr_value.s, obj_ptr->id-1);
583 DynStrSet(&name_attr->attr_value, gszMsgBox);
584 UpdAttr(name_attr);
585 UpdTextBBox(name_attr->obj);
586 AdjObjBBox(name_attr->obj);
587 AdjObjCache(name_attr->obj);
588 }
589 exec_attr = FindAttrWithName(topSel->obj, "on_instantiate=", NULL);
590 if (exec_attr != NULL) {
591 DoExecLoop(topSel->obj, exec_attr);
592 }
593 }
594 /*
595 * Need to check for pins.
596 */
597 }
598
ObjIsAPort(obj_ptr)599 int ObjIsAPort(obj_ptr)
600 struct ObjRec *obj_ptr;
601 {
602 struct AttrRec *attr_ptr=NULL;
603
604 attr_ptr = FindAttrWithName(obj_ptr, "type=", NULL);
605 if (attr_ptr != NULL && strcmp(attr_ptr->attr_value.s, "port") == 0) {
606 /*
607 * if this is not called from ConnectTwoPortsByAWire() but from
608 * an internal command, "type=port" is enough for a point
609 */
610 if (connectingPortsFromInternalCommand) return TRUE;
611
612 if (FindAttrWithName(obj_ptr, "signal_name=", NULL) != NULL &&
613 FindAttrWithName(obj_ptr, "name=", NULL) != NULL) {
614 struct ObjRec *owner_obj=obj_ptr->tmp_parent, *tmp_obj=NULL;
615
616 owner_obj = obj_ptr->tmp_parent;
617 if (owner_obj == NULL) {
618 /* obj_ptr is a top-level object */
619 return (obj_ptr->type == OBJ_ICON || obj_ptr->type == OBJ_SYM);
620 } else {
621 if (owner_obj->type == OBJ_ICON || owner_obj->type == OBJ_SYM) {
622 if (FindAttrWithName(owner_obj, "name=", NULL) == NULL) {
623 return FALSE;
624 }
625 } else {
626 if (owner_obj->type == OBJ_GROUP) {
627 attr_ptr = FindAttrWithName(owner_obj, "type=", NULL);
628 if (attr_ptr != NULL && strcmp(attr_ptr->attr_value.s,
629 "tgBroadcastWire") == 0) {
630 return TRUE;
631 }
632 }
633 return FALSE;
634 }
635 }
636 for (tmp_obj=owner_obj->tmp_parent; tmp_obj != NULL;
637 tmp_obj=tmp_obj->tmp_parent) {
638 if (tmp_obj->type == OBJ_ICON || tmp_obj->type == OBJ_SYM) {
639 return FALSE;
640 }
641 }
642 return TRUE;
643 }
644 }
645 return FALSE;
646 }
647
648 static
DoConnectTwoPorts()649 int DoConnectTwoPorts()
650 {
651 int poly_created=FALSE;
652 XGCValues values;
653
654 MakeQuiescent();
655
656 ResetWiringNodeInfo();
657 connectingPortsByWire = TRUE;
658 connectingPortsFromInternalCommand = FALSE;
659 UseWireMenuItemInModeItem(TRUE);
660
661 values.line_width = 3;
662 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
663 SetCurChoice(DRAWPOLY);
664 gstWiringInfo.num_ports_to_connect = 2;
665 drawPolyHighlightedNode = NULL;
666 SetStringStatus(TgLoadString(STID_DRAW_AN_EDGE_BETWEEN_PORTS));
667 polyDrawn = FALSE;
668 for (;;) {
669 XEvent input;
670
671 XNextEvent(mainDisplay, &input);
672 if (input.type == Expose || input.type == VisibilityNotify) {
673 ExposeEventHandler(&input, TRUE);
674 } else if (input.type == ConfigureNotify) {
675 Reconfigure(FALSE);
676 } else if (input.xany.window == drawWindow) {
677 polyDrawn = FALSE;
678 DrawingEventHandler(&input);
679 if (curChoice == DRAWPOLY) {
680 if (polyDrawn) {
681 break;
682 } else if (gstWiringInfo.num_ports_to_connect == (-1)) {
683 break;
684 }
685 } else {
686 polyDrawn = FALSE;
687 break;
688 }
689 }
690 }
691 gstWiringInfo.num_ports_to_connect = 0;
692 poly_created = polyDrawn;
693 values.line_width = 1;
694 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
695 connectingPortsByWire = FALSE;
696 connectingPortsFromInternalCommand = TRUE;
697 SetCurChoice(NOTHING);
698 RedrawModeWindow();
699 UseWireMenuItemInModeItem(FALSE);
700 UpdatePinnedMenu(MENU_MODE);
701
702 return poly_created;
703 }
704
705 static
AddWireAttributes(poly_obj_ptr,signal_name,p_obbox,auto_center)706 void AddWireAttributes(poly_obj_ptr, signal_name, p_obbox, auto_center)
707 struct ObjRec *poly_obj_ptr;
708 char *signal_name;
709 struct BBRec *p_obbox;
710 int auto_center;
711 {
712 struct ObjRec *text_obj_ptr=NULL;
713
714 PrepareToReplaceAnObj(poly_obj_ptr);
715
716 AddAttrByNameAndValue(poly_obj_ptr, "signal_name=", signal_name);
717 poly_obj_ptr->fattr->shown = TRUE;
718 poly_obj_ptr->fattr->nameshown = FALSE;
719 UpdAttr(poly_obj_ptr->fattr);
720 text_obj_ptr = poly_obj_ptr->fattr->obj;
721 if (auto_center) {
722 CenterObjInOBBox(text_obj_ptr, *p_obbox, NULL);
723 memcpy(p_obbox, &text_obj_ptr->obbox, sizeof(struct BBRec));
724 poly_obj_ptr->fattr->shown = FALSE;
725 } else {
726 MoveObj(text_obj_ptr, p_obbox->ltx-text_obj_ptr->obbox.ltx,
727 p_obbox->lty-text_obj_ptr->obbox.lty);
728 }
729 AddAttrByNameAndValue(poly_obj_ptr, "type=", "tgWire");
730 text_obj_ptr = poly_obj_ptr->fattr->obj;
731 MoveObj(text_obj_ptr, p_obbox->ltx-text_obj_ptr->obbox.ltx,
732 p_obbox->rby-text_obj_ptr->obbox.lty);
733
734 AdjObjBBox(poly_obj_ptr);
735
736 RecordReplaceAnObj(poly_obj_ptr);
737 }
738
739 typedef struct tagChangeConnectionViewInfo {
740 /* only change view if do_change_view is TRUE */
741 int do_change_view;
742 int change_to_connect_view;
743 struct ObjRec *conn_view_obj, *disconn_view_obj;
744 int conn_fill, conn_pen, disconn_fill, disconn_pen;
745 /* _TANGRAM_II stuff */
746 struct ObjRec *port_obj;
747 char *signal_name;
748 } ChangeConnectionViewInfo;
749
750 static
ChangeConnectionView(pravci)751 int ChangeConnectionView(pravci)
752 ReplAttrValueCallbackInfo *pravci;
753 {
754 ChangeConnectionViewInfo *pccvi=(
755 (ChangeConnectionViewInfo*)pravci->pv_userdata);
756
757 if (pccvi == NULL) return FALSE;
758
759 if (pccvi->do_change_view) {
760 if (pccvi->change_to_connect_view) {
761 ChangeObjFill(pccvi->disconn_view_obj, NONEPAT);
762 ChangeObjPen(pccvi->disconn_view_obj, NONEPAT);
763 ChangeObjFill(pccvi->conn_view_obj, pccvi->conn_fill);
764 ChangeObjPen(pccvi->conn_view_obj, pccvi->conn_pen);
765 } else {
766 ChangeObjFill(pccvi->conn_view_obj, NONEPAT);
767 ChangeObjPen(pccvi->conn_view_obj, NONEPAT);
768 ChangeObjFill(pccvi->disconn_view_obj, pccvi->disconn_fill);
769 ChangeObjPen(pccvi->disconn_view_obj, pccvi->disconn_pen);
770 }
771 }
772 if (cmdLineTgrm2) {
773 Tangram2UpdateInitAttr(pccvi->port_obj, pccvi->signal_name);
774 }
775 return TRUE;
776 }
777
778 static
HasConnAndDisConnViewObjSubObjs(obj_ptr,pccvi)779 int HasConnAndDisConnViewObjSubObjs(obj_ptr, pccvi)
780 struct ObjRec *obj_ptr;
781 ChangeConnectionViewInfo *pccvi;
782 {
783 struct ObjRec *subobj=NULL;
784
785 if (obj_ptr == NULL) return FALSE;
786 if (obj_ptr->type != OBJ_SYM && obj_ptr->type != OBJ_ICON &&
787 obj_ptr->type != OBJ_GROUP) {
788 return FALSE;
789 }
790 for (subobj=obj_ptr->detail.r->first; subobj != NULL; subobj=subobj->next) {
791 struct AttrRec *attr_ptr=FindAttrWithName(subobj, "view=", NULL);
792
793 if (attr_ptr != NULL) {
794 char *psz_fill=NULL, *psz_pen=NULL, buf[MAXSTRING];
795
796 UtilStrCpyN(buf, sizeof(buf), attr_ptr->attr_value.s);
797 psz_fill = strchr(buf, ',');
798 if (psz_fill != NULL) {
799 *psz_fill++ = '\0';
800 psz_pen = strchr(psz_fill, ',');
801 if (psz_pen != NULL) *psz_pen++ = '\0';
802 }
803 if (psz_fill != NULL && psz_pen != NULL) {
804 int fill=0, pen=0, ok=TRUE;
805
806 UtilTrimBlanks(buf);
807 UtilTrimBlanks(psz_fill);
808 UtilTrimBlanks(psz_pen);
809 if (sscanf(psz_fill, "%d", &fill) != 1) ok = FALSE;
810 if (sscanf(psz_pen, "%d", &pen) != 1) ok = FALSE;
811 if (ok) {
812 fill = fill % MAXPATTERNS;
813 pen = pen % MAXPATTERNS;
814 if (ok && UtilStrICmp(buf, "conn") == 0) {
815 pccvi->conn_fill = fill;
816 pccvi->conn_pen = pen;
817 pccvi->conn_view_obj = subobj;
818 } else if (ok && UtilStrICmp(buf, "disconn") == 0) {
819 pccvi->disconn_fill = fill;
820 pccvi->disconn_pen = pen;
821 pccvi->disconn_view_obj = subobj;
822 }
823 }
824 }
825 }
826 }
827 return (pccvi->conn_view_obj != NULL && pccvi->disconn_view_obj != NULL);
828 }
829
830 static
SetPortSignalName(port_obj,attr_ptr,attr_owner_obj,new_signal_name)831 int SetPortSignalName(port_obj, attr_ptr, attr_owner_obj, new_signal_name)
832 struct ObjRec *port_obj, *attr_owner_obj;
833 struct AttrRec *attr_ptr;
834 char *new_signal_name;
835 {
836 if (attr_ptr != NULL &&
837 strcmp(new_signal_name, attr_ptr->attr_value.s) != 0) {
838 char *old_signal_name=attr_ptr->attr_value.s;
839 ChangeConnectionViewInfo ccvi;
840
841 memset(&ccvi, 0, sizeof(ChangeConnectionViewInfo));
842 if ((*old_signal_name == '\0' || *new_signal_name == '\0') &&
843 HasConnAndDisConnViewObjSubObjs(attr_ptr->owner, &ccvi)) {
844 ccvi.do_change_view = TRUE;
845 if (*old_signal_name == '\0') {
846 /* the port will become connected */
847 ccvi.change_to_connect_view = TRUE;
848 } else {
849 /* the port will become disconnected */
850 ccvi.change_to_connect_view = FALSE;
851 }
852 }
853 ccvi.port_obj = port_obj;
854 ccvi.signal_name = new_signal_name;
855 SetReplaceAttrValueCallback(
856 (ReplAttrValueCallback*)ChangeConnectionView, &ccvi);
857
858 ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, new_signal_name);
859 SetReplaceAttrValueCallback(NULL, NULL);
860 RecursivelyAdjObjBBox(attr_ptr->owner, attr_ptr->owner,
861 attr_owner_obj);
862 return TRUE;
863 }
864 return FALSE;
865 }
866
867 static
DoNameWire(automatic)868 void DoNameWire(automatic)
869 int automatic;
870 {
871 struct AttrRec *first_attr_ptr=NULL, *last_attr_ptr=NULL;
872 struct ObjRec *first_attr_owner_obj=NULL, *last_attr_owner_obj=NULL;
873 struct BBRec bbox;
874 char signal_name[MAXSTRING], *existing_signal_name=NULL;
875 int need_to_clear=FALSE, need_to_redraw=FALSE;
876 int do_prompt=TRUE, must_prompt=FALSE;
877
878 memcpy(&bbox, &topObj->bbox, sizeof(struct BBRec));
879 first_attr_ptr = FindAttrWithName(gstWiringInfo.first_port_obj,
880 "signal_name=", &first_attr_owner_obj);
881 while (first_attr_owner_obj != NULL &&
882 first_attr_owner_obj->tmp_parent != NULL) {
883 first_attr_owner_obj = first_attr_owner_obj->tmp_parent;
884 }
885 last_attr_ptr = FindAttrWithName(gstWiringInfo.last_port_obj,
886 "signal_name=", &last_attr_owner_obj);
887 while (last_attr_owner_obj != NULL &&
888 last_attr_owner_obj->tmp_parent != NULL) {
889 last_attr_owner_obj = last_attr_owner_obj->tmp_parent;
890 }
891 if (first_attr_ptr == NULL && last_attr_ptr == NULL) return;
892 if (first_attr_ptr != NULL && last_attr_ptr != NULL) {
893 if (strcmp(first_attr_ptr->attr_value.s, last_attr_ptr->attr_value.s) !=
894 0) {
895 if (*first_attr_ptr->attr_value.s == '\0' &&
896 *last_attr_ptr->attr_value.s == '\0') {
897 must_prompt = TRUE;
898 } else if (*first_attr_ptr->attr_value.s == '\0') {
899 existing_signal_name = last_attr_ptr->attr_value.s;
900 } else if (*last_attr_ptr->attr_value.s == '\0') {
901 existing_signal_name = first_attr_ptr->attr_value.s;
902 } else {
903 sprintf(gszMsgBox, TgLoadString(STID_Q_CNFLCT_SIG_NAME_OKAY_TO_CLR),
904 first_attr_ptr->attr_value.s, gstWiringInfo.first_port_name,
905 last_attr_ptr->attr_value.s, gstWiringInfo.last_port_name);
906 switch (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)) {
907 case MB_ID_YES:
908 need_to_clear = TRUE;
909 must_prompt = TRUE;
910 break;
911 case MB_ID_NO:
912 case MB_ID_CANCEL:
913 return;
914 }
915 }
916 } else {
917 existing_signal_name = first_attr_ptr->attr_value.s;
918 }
919 } else if (first_attr_ptr == NULL) {
920 if (*last_attr_ptr->attr_value.s != '\0') {
921 existing_signal_name = last_attr_ptr->attr_value.s;
922 }
923 } else {
924 if (*first_attr_ptr->attr_value.s != '\0') {
925 existing_signal_name = first_attr_ptr->attr_value.s;
926 }
927 }
928 StartCompositeCmd();
929 if (need_to_clear) {
930 if (SetPortSignalName(gstWiringInfo.first_port_obj, first_attr_ptr,
931 first_attr_owner_obj, "")) {
932 UnionRect(&bbox, &first_attr_owner_obj->bbox, &bbox);
933 need_to_redraw = TRUE;
934 }
935 if (SetPortSignalName(gstWiringInfo.last_port_obj, last_attr_ptr,
936 last_attr_owner_obj, "")) {
937 UnionRect(&bbox, &last_attr_owner_obj->bbox, &bbox);
938 need_to_redraw = TRUE;
939 }
940 }
941 if (do_prompt) {
942 struct ObjRec *signal_name_obj=NULL;
943 struct BBRec obbox;
944 XEvent ev;
945 int show_wire_signal_name=(!automatic && showWireSignalName);
946
947 *signal_name = '\0';
948 if (existing_signal_name != NULL) {
949 UtilStrCpyN(signal_name, sizeof(signal_name), existing_signal_name);
950 }
951 UtilTrimBlanks(signal_name);
952 if (must_prompt || !automatic) {
953 Dialog(TgLoadString(STID_PLS_ENT_SIG_NAME), NULL, signal_name);
954 UtilTrimBlanks(signal_name);
955 }
956 if (*signal_name == '\0') {
957 if (need_to_clear) {
958 sprintf(gszMsgBox, TgLoadString(STID_SIGNAL_NAMES_CLEARED),
959 gstWiringInfo.first_port_name, gstWiringInfo.last_port_name);
960 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
961 }
962 EndCompositeCmd();
963
964 if (need_to_redraw) {
965 SetFileModified(TRUE);
966 justDupped = FALSE;
967 RedrawAnArea(botObj,
968 bbox.ltx-QUARTER_INCH-GRID_ABS_SIZE(1),
969 bbox.lty-QUARTER_INCH-GRID_ABS_SIZE(1),
970 bbox.rbx+QUARTER_INCH+GRID_ABS_SIZE(1),
971 bbox.rby+QUARTER_INCH+GRID_ABS_SIZE(1));
972 }
973 return;
974 }
975 if (show_wire_signal_name) {
976 unsigned int button_pressed=Button1;
977
978 SaveStatusStrings();
979 sprintf(gszMsgBox, TgLoadString(STID_PLACING_NAMED_SIGNAL),
980 signal_name);
981 SetStringStatus(gszMsgBox);
982 button_pressed = PasteString(signal_name, FALSE, FALSE);
983 RestoreStatusStrings();
984
985 if (button_pressed != Button1) show_wire_signal_name = FALSE;
986
987 memcpy(&obbox, &topObj->obbox, sizeof(struct BBRec));
988 signal_name_obj = topObj;
989 UnlinkObj(signal_name_obj);
990 FreeObj(signal_name_obj);
991
992 XSync(mainDisplay, False);
993 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
994 ExposeEventHandler(&ev, TRUE);
995 }
996 } else {
997 memcpy(&obbox, &topObj->obbox, sizeof(struct BBRec));
998 }
999 AddWireAttributes(topObj, signal_name, &obbox, !show_wire_signal_name);
1000 UnionRect(&bbox, &topObj->bbox, &bbox);
1001 if (SetPortSignalName(gstWiringInfo.first_port_obj, first_attr_ptr,
1002 first_attr_owner_obj, signal_name)) {
1003 UnionRect(&bbox, &first_attr_owner_obj->bbox, &bbox);
1004 need_to_redraw = TRUE;
1005 }
1006 if (SetPortSignalName(gstWiringInfo.last_port_obj, last_attr_ptr,
1007 last_attr_owner_obj, signal_name)) {
1008 UnionRect(&bbox, &last_attr_owner_obj->bbox, &bbox);
1009 need_to_redraw = TRUE;
1010 }
1011 }
1012 EndCompositeCmd();
1013
1014 if (need_to_redraw) {
1015 SetFileModified(TRUE);
1016 justDupped = FALSE;
1017 RedrawAnArea(botObj,
1018 bbox.ltx-QUARTER_INCH-GRID_ABS_SIZE(1),
1019 bbox.lty-QUARTER_INCH-GRID_ABS_SIZE(1),
1020 bbox.rbx+QUARTER_INCH+GRID_ABS_SIZE(1),
1021 bbox.rby+QUARTER_INCH+GRID_ABS_SIZE(1));
1022 if (topSel!=NULL) HighLightForward();
1023 }
1024 }
1025
ConnectTwoPortsByAWire()1026 void ConnectTwoPortsByAWire()
1027 {
1028 StartCompositeCmd();
1029 if (DoConnectTwoPorts()) {
1030 DoNameWire(FALSE);
1031 }
1032 EndCompositeCmd();
1033 }
1034
RepeatConnectTwoPortsByAWire()1035 void RepeatConnectTwoPortsByAWire()
1036 {
1037 StartCompositeCmd();
1038 while (DoConnectTwoPorts()) {
1039 DoNameWire(TRUE);
1040
1041 if (topSel!=NULL) { HighLightReverse(); RemoveAllSel(); }
1042 }
1043 EndCompositeCmd();
1044 }
1045
1046 static
AddObjToAnchor(anchor,obj_ptr)1047 void AddObjToAnchor(anchor, obj_ptr)
1048 struct ObjRec *anchor, *obj_ptr;
1049 {
1050 obj_ptr->prev = NULL;
1051 obj_ptr->next = anchor->detail.r->first;
1052
1053 anchor->detail.r->first->prev = obj_ptr;
1054 anchor->detail.r->first = obj_ptr;
1055 AdjObjOBBox(anchor);
1056 }
1057
1058 static
AddBroadcastWireAttributes(poly_obj_ptr,signal_name,p_obbox,auto_center)1059 void AddBroadcastWireAttributes(poly_obj_ptr, signal_name, p_obbox, auto_center)
1060 struct ObjRec *poly_obj_ptr;
1061 char *signal_name;
1062 struct BBRec *p_obbox;
1063 int auto_center;
1064 {
1065 struct ObjRec *text_obj_ptr=NULL;
1066
1067 PrepareToReplaceAnObj(poly_obj_ptr);
1068
1069 AddAttrByNameAndValue(poly_obj_ptr, "broadcast_signal_name=", signal_name);
1070 poly_obj_ptr->fattr->shown = TRUE;
1071 poly_obj_ptr->fattr->nameshown = FALSE;
1072 UpdAttr(poly_obj_ptr->fattr);
1073 text_obj_ptr = poly_obj_ptr->fattr->obj;
1074 if (auto_center) {
1075 CenterObjInOBBox(text_obj_ptr, *p_obbox, NULL);
1076 memcpy(p_obbox, &text_obj_ptr->obbox, sizeof(struct BBRec));
1077 poly_obj_ptr->fattr->shown = FALSE;
1078 } else {
1079 MoveObj(text_obj_ptr, p_obbox->ltx-text_obj_ptr->obbox.ltx,
1080 p_obbox->lty-text_obj_ptr->obbox.lty);
1081 }
1082 AdjObjBBox(poly_obj_ptr);
1083
1084 RecordReplaceAnObj(poly_obj_ptr);
1085 }
1086
1087 static
DoNameBroadcastWire(signal_name,signal_name_diff)1088 void DoNameBroadcastWire(signal_name, signal_name_diff)
1089 char *signal_name;
1090 int signal_name_diff;
1091 {
1092 struct ObjRec *obj_ptr=NULL, *signal_name_obj=NULL;
1093 struct AttrRec *attr_ptr=NULL;
1094 struct BBRec bbox, obbox;
1095 int show_wire_signal_name=showWireSignalName;
1096 int already_has_broadcast_signal_name=FALSE;
1097 XEvent ev;
1098
1099 memset(&obbox, 0, sizeof(obbox));
1100 memcpy(&bbox, &topObj->bbox, sizeof(struct BBRec));
1101
1102 StartCompositeCmd();
1103
1104 attr_ptr = FindAttrWithName(topObj, "broadcast_signal_name=", NULL);
1105 if (attr_ptr != NULL) {
1106 already_has_broadcast_signal_name = TRUE;
1107 if (strcmp(attr_ptr->attr_value.s, signal_name) != 0) {
1108 ReplaceAttrFirstValue(topObj, attr_ptr, signal_name);
1109 UnionRect(&bbox, &topObj->bbox, &bbox);
1110 }
1111 }
1112 for (obj_ptr=topObj->detail.r->last; obj_ptr != NULL;
1113 obj_ptr=obj_ptr->prev) {
1114 if (ObjIsAPort(obj_ptr)) {
1115 struct ObjRec *attr_owner_obj=NULL;
1116
1117 attr_ptr = FindAttrWithName(obj_ptr, "signal_name=", &attr_owner_obj);
1118 while (attr_owner_obj != NULL && attr_owner_obj->tmp_parent != NULL) {
1119 attr_owner_obj = attr_owner_obj->tmp_parent;
1120 }
1121 if (SetPortSignalName(obj_ptr, attr_ptr, attr_owner_obj, "")) {
1122 UnionRect(&bbox, &attr_owner_obj->bbox, &bbox);
1123 }
1124 }
1125 }
1126 if (show_wire_signal_name && !already_has_broadcast_signal_name) {
1127 unsigned int button_pressed=Button1;
1128
1129 SaveStatusStrings();
1130 sprintf(gszMsgBox, TgLoadString(STID_PLACING_NAMED_SIGNAL),
1131 signal_name);
1132 SetStringStatus(gszMsgBox);
1133 button_pressed = PasteString(signal_name, FALSE, FALSE);
1134 RestoreStatusStrings();
1135
1136 if (button_pressed != Button1) show_wire_signal_name = FALSE;
1137
1138 memcpy(&obbox, &topObj->obbox, sizeof(struct BBRec));
1139 signal_name_obj = topObj;
1140 UnlinkObj(signal_name_obj);
1141 FreeObj(signal_name_obj);
1142
1143 XSync(mainDisplay, False);
1144 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
1145 ExposeEventHandler(&ev, TRUE);
1146 }
1147 } else {
1148 memcpy(&obbox, &topObj->obbox, sizeof(struct BBRec));
1149 }
1150 if (!already_has_broadcast_signal_name) {
1151 AddBroadcastWireAttributes(topObj, signal_name, &obbox,
1152 !show_wire_signal_name);
1153 UnionRect(&bbox, &topObj->bbox, &bbox);
1154 }
1155 for (obj_ptr=topObj->detail.r->last; obj_ptr != NULL;
1156 obj_ptr=obj_ptr->prev) {
1157 if (ObjIsAPort(obj_ptr)) {
1158 struct ObjRec *attr_owner_obj=NULL;
1159 struct AttrRec *attr_ptr=NULL;
1160
1161 attr_ptr = FindAttrWithName(obj_ptr, "signal_name=", &attr_owner_obj);
1162 while (attr_owner_obj != NULL && attr_owner_obj->tmp_parent != NULL) {
1163 attr_owner_obj = attr_owner_obj->tmp_parent;
1164 }
1165 if (SetPortSignalName(obj_ptr, attr_ptr, attr_owner_obj,
1166 signal_name)) {
1167 UnionRect(&bbox, &attr_owner_obj->bbox, &bbox);
1168 }
1169 }
1170 }
1171 EndCompositeCmd();
1172
1173 SetFileModified(TRUE);
1174 justDupped = FALSE;
1175 RedrawAnArea(botObj,
1176 bbox.ltx-QUARTER_INCH-GRID_ABS_SIZE(1),
1177 bbox.lty-QUARTER_INCH-GRID_ABS_SIZE(1),
1178 bbox.rbx+QUARTER_INCH+GRID_ABS_SIZE(1),
1179 bbox.rby+QUARTER_INCH+GRID_ABS_SIZE(1));
1180 if (topSel!=NULL) HighLightForward();
1181 }
1182
1183 static
TrySetCommonSignalName(attr_ptr,pszSignalName,szSignalName,pnSignalNameDiff)1184 void TrySetCommonSignalName(attr_ptr, pszSignalName, szSignalName,
1185 pnSignalNameDiff)
1186 struct AttrRec *attr_ptr;
1187 char *pszSignalName;
1188 int szSignalName, *pnSignalNameDiff;
1189 {
1190 if (*pnSignalNameDiff) {
1191 /* already see multiple signal names */
1192 } else if (*attr_ptr->attr_value.s == '\0') {
1193 /* nothing to do */
1194 } else if (*pszSignalName == '\0') {
1195 UtilStrCpyN(pszSignalName, szSignalName, attr_ptr->attr_value.s);
1196 } else if (strcmp(pszSignalName, attr_ptr->attr_value.s) != 0) {
1197 (*pnSignalNameDiff) = TRUE;
1198 *pszSignalName = '\0';
1199 }
1200 }
1201
1202 static
CheckPortsAndBroadcastObj(ppAnchor,pnAnchorIsPoly,pnNumPorts,pszSignalName,szSignalName,pnSignalNameDiff,pnAlreadyHasBroadcastSignalName)1203 int CheckPortsAndBroadcastObj(ppAnchor, pnAnchorIsPoly, pnNumPorts,
1204 pszSignalName, szSignalName, pnSignalNameDiff,
1205 pnAlreadyHasBroadcastSignalName)
1206 struct ObjRec **ppAnchor;
1207 int *pnAnchorIsPoly, *pnNumPorts, szSignalName, *pnSignalNameDiff;
1208 int *pnAlreadyHasBroadcastSignalName;
1209 char *pszSignalName;
1210 {
1211 int num_ports=0, anchor_is_poly=FALSE, ok=TRUE, signal_name_diff=FALSE;
1212 int already_has_broadcast_signal_name=FALSE;
1213 struct ObjRec *anchor=NULL;
1214 struct SelRec *sel_ptr=NULL;
1215
1216 *pszSignalName = '\0';
1217 for (sel_ptr=botSel; ok && sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1218 struct AttrRec *attr_ptr=NULL;
1219
1220 switch (sel_ptr->obj->type) {
1221 case OBJ_GROUP:
1222 case OBJ_SYM:
1223 case OBJ_ICON:
1224 case OBJ_PIN:
1225 if ((attr_ptr=FindAttrWithName(sel_ptr->obj, "type=", NULL)) != NULL) {
1226 if (strcmp(attr_ptr->attr_value.s, "port") == 0) {
1227 if ((attr_ptr=FindAttrWithName(sel_ptr->obj, "signal_name=",
1228 NULL)) != NULL) {
1229 TrySetCommonSignalName(attr_ptr, pszSignalName, szSignalName,
1230 &signal_name_diff);
1231 num_ports++;
1232 }
1233 } else if (strcmp(attr_ptr->attr_value.s, "tgBroadcastWire") == 0) {
1234 anchor = sel_ptr->obj;
1235 anchor_is_poly = FALSE;
1236 if ((attr_ptr=FindAttrWithName(sel_ptr->obj,
1237 "broadcast_signal_name=", NULL)) != NULL) {
1238 TrySetCommonSignalName(attr_ptr, pszSignalName, szSignalName,
1239 &signal_name_diff);
1240 already_has_broadcast_signal_name = TRUE;
1241 }
1242 } else {
1243 return FALSE;
1244 }
1245 } else {
1246 return FALSE;
1247 }
1248 break;
1249 case OBJ_POLY:
1250 if (anchor == NULL) {
1251 anchor = sel_ptr->obj;
1252 anchor_is_poly = TRUE;
1253 } else {
1254 return FALSE;
1255 }
1256 break;
1257 default:
1258 return FALSE;
1259 break;
1260 }
1261 }
1262 if (anchor == NULL || num_ports == 0) {
1263 return FALSE;
1264 }
1265 *pnNumPorts = num_ports;
1266 *ppAnchor = anchor;
1267 *pnAnchorIsPoly = anchor_is_poly;
1268 *pnSignalNameDiff = signal_name_diff;
1269 *pnAlreadyHasBroadcastSignalName = already_has_broadcast_signal_name;
1270
1271 return TRUE;
1272 }
1273
ConnectPortsToBroadcastWire()1274 void ConnectPortsToBroadcastWire()
1275 {
1276 struct ObjRec *anchor=NULL;
1277 struct SelRec *sel_ptr=NULL;
1278 int num_ports=0, anchor_is_poly=FALSE, signal_name_diff=FALSE;
1279 int sel_ltx=selLtX, sel_lty=selLtY, sel_rbx=selRbX, sel_rby=selRbY;
1280 int already_has_broadcast_signal_name=FALSE;
1281 char existing_signal_name[MAXSTRING], new_signal_name[MAXSTRING];
1282
1283 *existing_signal_name = '\0';
1284 if (!CheckPortsAndBroadcastObj(&anchor, &anchor_is_poly, &num_ports,
1285 existing_signal_name, sizeof(existing_signal_name),
1286 &signal_name_diff, &already_has_broadcast_signal_name)) {
1287 MsgBox(TgLoadString(STID_SEL_ONE_NONE_PORT_PLUS_BRDCST), TOOL_NAME,
1288 INFO_MB);
1289 return;
1290 }
1291 *new_signal_name = '\0';
1292 if (*existing_signal_name == '\0') {
1293 if (signal_name_diff) {
1294 /* conflicting signal names */
1295 sprintf(gszMsgBox, TgLoadString(STID_CONFLICT_SIG_NAME_ENT_NEW));
1296 } else {
1297 /* all ports have no signal names */
1298 sprintf(gszMsgBox, TgLoadString(STID_PLS_ENT_SIG_NAME));
1299 }
1300 } else {
1301 UtilStrCpyN(new_signal_name, sizeof(new_signal_name),
1302 existing_signal_name);
1303 sprintf(gszMsgBox, TgLoadString(STID_PLS_ENT_SIG_NAME));
1304 }
1305 if (!(*new_signal_name != '\0' && already_has_broadcast_signal_name)) {
1306 UtilTrimBlanks(new_signal_name);
1307 Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL),
1308 new_signal_name);
1309 UtilTrimBlanks(new_signal_name);
1310 if (*new_signal_name == '\0') {
1311 return;
1312 }
1313 }
1314 StartCompositeCmd();
1315
1316 HighLightReverse();
1317 if (anchor_is_poly) {
1318 struct SelRec *saved_top_sel=NULL, *saved_bot_sel=NULL;
1319 struct ObjRec *text_obj_ptr=NULL;
1320 struct BBRec obbox;
1321 int saved_num_obj_selected=0;
1322 char name[40];
1323
1324 PrepareToReplaceAnObj(anchor);
1325 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1326 if (sel_ptr->obj == anchor) {
1327 UnlinkSel(sel_ptr, &topSel, &botSel);
1328 numObjSelected--;
1329 break;
1330 }
1331 }
1332 saved_top_sel = topSel;
1333 saved_bot_sel = botSel;
1334 saved_num_obj_selected = numObjSelected;
1335 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
1336 if (topSel == NULL) FailAllocMessage();
1337 topSel->obj = anchor;
1338 topSel->next = topSel->prev = NULL;
1339 numObjSelected = 1;
1340 GroupSingleObj(FALSE);
1341 topSel = saved_top_sel;
1342 botSel = saved_bot_sel;
1343 numObjSelected = saved_num_obj_selected;
1344 AddObjIntoSel(topObj, NULL, topSel, &topSel, &botSel);
1345 numObjSelected++;
1346 anchor = topObj;
1347
1348 memcpy(&obbox, &anchor->obbox, sizeof(struct BBRec));
1349 AddAttrByNameAndValue(anchor, "type=", "tgBroadcastWire");
1350 text_obj_ptr = anchor->fattr->obj;
1351 MoveObj(text_obj_ptr, obbox.ltx-text_obj_ptr->obbox.ltx,
1352 obbox.rby-text_obj_ptr->obbox.lty);
1353 AdjObjBBox(anchor);
1354
1355 sprintf(name, "tgAutoObj%d", anchor->id);
1356 memcpy(&obbox, &anchor->obbox, sizeof(struct BBRec));
1357 AddAttrByNameAndValue(anchor, "name=", name);
1358 text_obj_ptr = anchor->fattr->obj;
1359 MoveObj(text_obj_ptr, obbox.ltx-text_obj_ptr->obbox.ltx,
1360 obbox.rby-text_obj_ptr->obbox.lty);
1361 AdjObjBBox(anchor);
1362
1363 RecordReplaceAnObj(anchor);
1364 }
1365 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
1366
1367 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1368 if (sel_ptr->obj != anchor) {
1369 UnlinkObj(sel_ptr->obj);
1370 AddObjToAnchor(anchor, sel_ptr->obj);
1371 }
1372 }
1373 RemoveAllSel();
1374 UnlinkObj(anchor);
1375 AddObj(NULL, topObj, anchor);
1376 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
1377 if (topSel == NULL) FailAllocMessage();
1378 topSel->obj = anchor;
1379 topSel->prev = NULL;
1380 botSel->next = NULL;
1381 AdjObjBBox(anchor);
1382 UpdSelBBox();
1383 RecordCmd(CMD_MANY_TO_ONE, NULL, topSel, botSel, 1);
1384 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1), sel_lty-GRID_ABS_SIZE(1),
1385 sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
1386 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1387 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1388 HighLightForward();
1389 SetFileModified(TRUE);
1390 justDupped = FALSE;
1391
1392 DoNameBroadcastWire(new_signal_name, signal_name_diff);
1393 EndCompositeCmd();
1394 }
1395
1396 #define DO_RENAME_SIGNAL_NAME 99
1397 #define DO_CLEAR_SIGNAL_NAME 999
1398
1399 static
DoNameOrClearAPort(which)1400 void DoNameOrClearAPort(which)
1401 int which;
1402 {
1403 struct AttrRec *first_attr_ptr=NULL;
1404 struct ObjRec *first_attr_owner_obj=NULL;
1405 int ltx=0, lty=0, rbx=0, rby=0;
1406 char signal_name[MAXSTRING];
1407 ChangeConnectionViewInfo ccvi;
1408
1409 memset(&ccvi, 0, sizeof(ChangeConnectionViewInfo));
1410 first_attr_ptr = FindAttrWithName(gstWiringInfo.first_port_obj,
1411 "signal_name=", &first_attr_owner_obj);
1412 while (first_attr_owner_obj != NULL &&
1413 first_attr_owner_obj->tmp_parent != NULL) {
1414 first_attr_owner_obj = first_attr_owner_obj->tmp_parent;
1415 }
1416 if (first_attr_ptr == NULL) {
1417 #ifdef _TGIF_DBG /* debug, do not translate */
1418 TgAssert(FALSE,
1419 "first_attr_ptr is NULL in DoNameOrClearAPort()", NULL);
1420 return;
1421 #endif /* _TGIF_DBG */
1422 }
1423 *signal_name = '\0';
1424 if (which == DO_CLEAR_SIGNAL_NAME && *first_attr_ptr->attr_value.s == '\0') {
1425 /* already cleared */
1426 return;
1427 }
1428 if (which == DO_RENAME_SIGNAL_NAME) {
1429 UtilStrCpyN(signal_name, sizeof(signal_name),
1430 first_attr_ptr->attr_value.s);
1431 sprintf(gszMsgBox, TgLoadString(STID_PLS_ENT_SIG_NAME_FOR_PORT),
1432 gstWiringInfo.first_port_name);
1433 if (Dialog(gszMsgBox, NULL, signal_name) == INVALID) return;
1434 UtilTrimBlanks(signal_name);
1435 }
1436 if (strcmp(signal_name, first_attr_ptr->attr_value.s) == 0) {
1437 return;
1438 }
1439 ltx = first_attr_owner_obj->bbox.ltx;
1440 lty = first_attr_owner_obj->bbox.lty;
1441 rbx = first_attr_owner_obj->bbox.rbx;
1442 rby = first_attr_owner_obj->bbox.rby;
1443
1444 if (HasConnAndDisConnViewObjSubObjs(first_attr_ptr->owner, &ccvi)) {
1445 ccvi.do_change_view = TRUE;
1446 if (*signal_name != '\0') {
1447 /* the port will become connected */
1448 ccvi.change_to_connect_view = TRUE;
1449 } else {
1450 /* the port will become disconnected */
1451 ccvi.change_to_connect_view = FALSE;
1452 }
1453 }
1454 ccvi.port_obj = gstWiringInfo.first_port_obj;
1455 ccvi.signal_name = signal_name;
1456 SetReplaceAttrValueCallback(
1457 (ReplAttrValueCallback*)ChangeConnectionView, &ccvi);
1458
1459 ReplaceAttrFirstValue(first_attr_owner_obj, first_attr_ptr,
1460 signal_name);
1461 SetReplaceAttrValueCallback(NULL, NULL);
1462 RecursivelyAdjObjBBox(first_attr_ptr->owner, first_attr_ptr->owner,
1463 first_attr_owner_obj);
1464
1465 SetFileModified(TRUE);
1466 justDupped = FALSE;
1467 RedrawAreas(botObj,
1468 ltx-QUARTER_INCH-GRID_ABS_SIZE(1), lty-QUARTER_INCH-GRID_ABS_SIZE(1),
1469 rbx+QUARTER_INCH+GRID_ABS_SIZE(1), rby+QUARTER_INCH+GRID_ABS_SIZE(1),
1470 first_attr_owner_obj->bbox.ltx-QUARTER_INCH-GRID_ABS_SIZE(1),
1471 first_attr_owner_obj->bbox.lty-QUARTER_INCH-GRID_ABS_SIZE(1),
1472 first_attr_owner_obj->bbox.rbx+QUARTER_INCH+GRID_ABS_SIZE(1),
1473 first_attr_owner_obj->bbox.rby+QUARTER_INCH+GRID_ABS_SIZE(1));
1474 }
1475
1476 static
DoRenameOrClearSignalNameForAPort(which)1477 void DoRenameOrClearSignalNameForAPort(which)
1478 int which;
1479 {
1480 int naming=TRUE;
1481
1482 ShowCurChoiceMouseStatus(DRAWPOLY, 0, FALSE);
1483 SetHandCursor(drawWindow);
1484 while (naming) {
1485 XEvent input;
1486
1487 XNextEvent(mainDisplay, &input);
1488 if (input.type == Expose || input.type == VisibilityNotify) {
1489 ExposeEventHandler(&input, TRUE);
1490 } else if (input.type == ConfigureNotify) {
1491 Reconfigure(FALSE);
1492 } else if (input.xany.window == drawWindow && input.type == ButtonPress) {
1493 if (input.xbutton.button == Button1) {
1494 if (drawPolyHighlightedNode != NULL) {
1495 HandlePressForPortInDrawWindow(FALSE);
1496 DoNameOrClearAPort(which);
1497 drawPolyHighlightedNode = NULL;
1498 SetWiringNodeInfo(NULL, NULL, NULL, TRUE);
1499 SetHandCursor(drawWindow);
1500 ShowCurChoiceMouseStatus(DRAWPOLY, 0, FALSE);
1501 }
1502 } else {
1503 XUngrabPointer(mainDisplay, CurrentTime);
1504 naming = FALSE;
1505 HandlePressForPortInDrawWindow(TRUE);
1506 }
1507 } else if (input.xany.window == drawWindow &&
1508 input.type == MotionNotify) {
1509 XEvent ev;
1510
1511 HandleMotionForPortInDrawWindow(input.xmotion.x, input.xmotion.y);
1512 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1513 } else if (input.type == KeyPress) {
1514 if (KeyPressEventIsEscape(&input.xkey)) {
1515 XUngrabPointer(mainDisplay, CurrentTime);
1516 naming = FALSE;
1517 HandlePressForPortInDrawWindow(TRUE);
1518 }
1519 }
1520 }
1521 SetDefaultCursor(drawWindow);
1522 }
1523
1524 static
RenameOrClearSignalNameForAPort(which)1525 void RenameOrClearSignalNameForAPort(which)
1526 int which;
1527 {
1528 XGCValues values;
1529
1530 MakeQuiescent();
1531
1532 ResetWiringNodeInfo();
1533 connectingPortsByWire = TRUE;
1534 connectingPortsFromInternalCommand = FALSE;
1535 gstWiringInfo.num_ports_to_connect = which;
1536 drawPolyHighlightedNode = NULL;
1537
1538 values.line_width = 3;
1539 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
1540
1541 SaveStatusStrings();
1542 DoRenameOrClearSignalNameForAPort(which);
1543 RestoreStatusStrings();
1544
1545 values.line_width = 1;
1546 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
1547
1548 gstWiringInfo.num_ports_to_connect = 0;
1549 connectingPortsByWire = FALSE;
1550 connectingPortsFromInternalCommand = TRUE;
1551 ResetWiringNodeInfo();
1552 drawPolyHighlightedNode = NULL;
1553 }
1554
RenameSignalNameForAPort()1555 void RenameSignalNameForAPort()
1556 {
1557 RenameOrClearSignalNameForAPort(DO_RENAME_SIGNAL_NAME);
1558 }
1559
ClearSignalNameForAPort()1560 void ClearSignalNameForAPort()
1561 {
1562 RenameOrClearSignalNameForAPort(DO_CLEAR_SIGNAL_NAME);
1563 }
1564
1565 static
CheckPortsAndObj(ppAnchor,pnNumPorts)1566 int CheckPortsAndObj(ppAnchor, pnNumPorts)
1567 struct ObjRec **ppAnchor;
1568 int *pnNumPorts;
1569 {
1570 int num_ports=0, ok=TRUE;
1571 struct ObjRec *anchor=NULL;
1572 struct SelRec *sel_ptr=NULL;
1573
1574 for (sel_ptr=botSel; ok && sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1575 struct AttrRec *attr_ptr=NULL;
1576
1577 switch (sel_ptr->obj->type) {
1578 case OBJ_GROUP:
1579 case OBJ_SYM:
1580 case OBJ_ICON:
1581 case OBJ_PIN:
1582 if ((attr_ptr=FindAttrWithName(sel_ptr->obj, "type=", NULL)) != NULL) {
1583 if (strcmp(attr_ptr->attr_value.s, "port") == 0 &&
1584 FindAttrWithName(sel_ptr->obj, "signal_name=",
1585 NULL) != NULL) {
1586 num_ports++;
1587 } else if (anchor == NULL) {
1588 anchor = sel_ptr->obj;
1589 } else {
1590 return FALSE;
1591 }
1592 } else if (anchor == NULL) {
1593 anchor = sel_ptr->obj;
1594 } else {
1595 return FALSE;
1596 }
1597 break;
1598 default:
1599 return FALSE;
1600 break;
1601 }
1602 }
1603 if (anchor == NULL || num_ports == 0) {
1604 return FALSE;
1605 }
1606 *pnNumPorts = num_ports;
1607 *ppAnchor = anchor;
1608
1609 return TRUE;
1610 }
1611
MergePortsWithAnObject()1612 void MergePortsWithAnObject()
1613 {
1614 int num_ports=0;
1615 int sel_ltx=selLtX, sel_lty=selLtY, sel_rbx=selRbX, sel_rby=selRbY;
1616 struct ObjRec *anchor=NULL;
1617 struct SelRec *sel_ptr=NULL;
1618
1619 if (!CheckPortsAndObj(&anchor, &num_ports)) {
1620 MsgBox(TgLoadString(STID_SEL_ONE_NONE_PORT_PLUS_COMP), TOOL_NAME,
1621 INFO_MB);
1622 return;
1623 }
1624 HighLightReverse();
1625 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
1626
1627 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1628 if (sel_ptr->obj != anchor) {
1629 UnlinkObj(sel_ptr->obj);
1630 AddObjToAnchor(anchor, sel_ptr->obj);
1631 }
1632 }
1633 RemoveAllSel();
1634 UnlinkObj(anchor);
1635 AddObj(NULL, topObj, anchor);
1636 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
1637 if (topSel == NULL) FailAllocMessage();
1638 topSel->obj = anchor;
1639 topSel->prev = NULL;
1640 botSel->next = NULL;
1641 AdjObjBBox(anchor);
1642 UpdSelBBox();
1643 RecordCmd(CMD_MANY_TO_ONE, NULL, topSel, botSel, 1);
1644 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1), sel_lty-GRID_ABS_SIZE(1),
1645 sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
1646 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1647 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1648 HighLightForward();
1649 SetFileModified(TRUE);
1650 justDupped = FALSE;
1651 }
1652
1653 static
RenumberObjId(obj_ptr)1654 void RenumberObjId(obj_ptr)
1655 struct ObjRec *obj_ptr;
1656 {
1657 struct AttrRec *attr_ptr=NULL;
1658 struct ObjRec *sub_obj=NULL;
1659
1660 obj_ptr->id = objId++;
1661
1662 switch (obj_ptr->type) {
1663 case OBJ_GROUP:
1664 case OBJ_ICON:
1665 case OBJ_SYM:
1666 case OBJ_PIN:
1667 for (sub_obj=obj_ptr->detail.r->last; sub_obj != NULL;
1668 sub_obj=sub_obj->prev) {
1669 RenumberObjId(sub_obj);
1670 }
1671 break;
1672 }
1673 for (attr_ptr=obj_ptr->lattr; attr_ptr != NULL; attr_ptr=attr_ptr->prev) {
1674 RenumberObjId(attr_ptr->obj);
1675 }
1676 }
1677
RenumberObjectIds()1678 void RenumberObjectIds()
1679 {
1680 struct PageRec *page_ptr=NULL;
1681
1682 if (gstWBInfo.do_whiteboard) {
1683 MsgBox(TgLoadString(STID_RENUMBER_OBJ_IDS_IN_WB), TOOL_NAME, INFO_MB);
1684 return;
1685 }
1686 if (!OkToFlushUndoBuffer(TgLoadString(STID_RENUMBER_OBJ_IDS_CAUSE_FLUSH))) {
1687 return;
1688 }
1689 MakeQuiescent();
1690 CleanUpCmds();
1691
1692 objId = 0;
1693 for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
1694 struct ObjRec *obj_ptr=NULL;
1695
1696 for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1697 RenumberObjId(obj_ptr);
1698 }
1699 }
1700 MsgBox(TgLoadString(STID_RENUMBER_OBJ_IDS_DONE), TOOL_NAME, INFO_MB);
1701 SetFileModified(TRUE);
1702 }
1703
MakeSymbolic()1704 void MakeSymbolic()
1705 {
1706 int ltx=selLtX, lty=selLtY, rbx=selRbX, rby=selRbY;
1707 struct ObjRec *obj_ptr=NULL;
1708
1709 if (curChoice == VERTEXMODE) {
1710 MsgBox(TgLoadString(STID_CANT_MAKESYMBOLIC_VERTEX_MODE), TOOL_NAME,
1711 INFO_MB);
1712 return;
1713 } else if (topSel == NULL || topSel != botSel) {
1714 MsgBox(TgLoadString(STID_SEL_ONLY_ONE_FOR_MAKESYMBOLIC), TOOL_NAME,
1715 INFO_MB);
1716 return;
1717 }
1718 obj_ptr = topSel->obj;
1719 if (obj_ptr->type == OBJ_SYM) return;
1720 if (obj_ptr->type == OBJ_PIN) {
1721 MsgBox(TgLoadString(STID_PIN_CANT_MADE_INTO_SYMBOL), TOOL_NAME, INFO_MB);
1722 return;
1723 }
1724 HighLightReverse();
1725 PrepareToReplaceAnObj(obj_ptr);
1726 /*
1727 * Need to check for pins.
1728 */
1729 if (obj_ptr->type != OBJ_GROUP && obj_ptr->type != OBJ_ICON) {
1730 GroupSingleObj(FALSE);
1731 obj_ptr = topSel->obj;
1732 if (obj_ptr->fattr != NULL) {
1733 Msg(TgLoadCachedString(CSTID_ATTR_PROMOTED_TO_NEW_SYMBOL));
1734 }
1735 }
1736 obj_ptr->type = OBJ_SYM;
1737 AdjObjBBox(obj_ptr);
1738 UpdSelBBox();
1739 RecordReplaceAnObj(obj_ptr);
1740
1741 UpdSelBBox();
1742 RedrawAnArea(botObj,
1743 ltx-QUARTER_INCH-GRID_ABS_SIZE(1), lty-QUARTER_INCH-GRID_ABS_SIZE(1),
1744 rbx+QUARTER_INCH+GRID_ABS_SIZE(1), rby+QUARTER_INCH+GRID_ABS_SIZE(1));
1745 HighLightForward();
1746 SetFileModified(TRUE);
1747 justDupped = FALSE;
1748
1749 Msg(TgLoadString(STID_SEL_OBJ_IS_NOW_SYMBOLIC));
1750 }
1751
UnMakeSymbolic()1752 void UnMakeSymbolic()
1753 {
1754 register struct ObjRec *obj_ptr;
1755 register int ltx=0, lty=0, rbx=0, rby=0;
1756 struct SelRec *sel_ptr=topSel;
1757 int modified=FALSE;
1758
1759 StartCompositeCmd();
1760 for ( ; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
1761 obj_ptr = sel_ptr->obj;
1762 if (obj_ptr->type == OBJ_SYM) {
1763 PrepareToReplaceAnObj(obj_ptr);
1764 obj_ptr->type = OBJ_GROUP;
1765 AdjObjBBox(obj_ptr);
1766 RecordReplaceAnObj(obj_ptr);
1767 if (modified) {
1768 if (obj_ptr->bbox.ltx < ltx) ltx = obj_ptr->bbox.ltx;
1769 if (obj_ptr->bbox.lty < lty) lty = obj_ptr->bbox.lty;
1770 if (obj_ptr->bbox.rbx > rbx) rbx = obj_ptr->bbox.rbx;
1771 if (obj_ptr->bbox.rby > rby) rby = obj_ptr->bbox.rby;
1772 } else {
1773 ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
1774 rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
1775 modified = TRUE;
1776 }
1777 }
1778 }
1779 EndCompositeCmd();
1780 if (modified) {
1781 HighLightReverse();
1782 UpdSelBBox();
1783 RedrawAnArea(botObj, ltx-QUARTER_INCH-GRID_ABS_SIZE(1),
1784 lty-QUARTER_INCH-GRID_ABS_SIZE(1),rbx+QUARTER_INCH+GRID_ABS_SIZE(1),
1785 rby+QUARTER_INCH+GRID_ABS_SIZE(1));
1786 HighLightForward();
1787 SetFileModified(TRUE);
1788 justDupped = FALSE;
1789 }
1790 }
1791
MakeIconic(sym_path,record_cmd)1792 int MakeIconic(sym_path, record_cmd)
1793 char *sym_path;
1794 int record_cmd;
1795 {
1796 char icon_name[MAXPATHLENGTH], file_name[MAXPATHLENGTH];
1797 char icon_full_name[MAXPATHLENGTH], *rest=NULL, *psz=NULL;
1798 char sym_ext_str[MAXSTRING];
1799 FILE *fp=NULL;
1800 int len, short_name, sym_ext_len, ltx, lty, rbx, rby, no_name=FALSE;
1801
1802 if (topSel == NULL || topSel != botSel) {
1803 MsgBox(TgLoadString(STID_SEL_ONLY_ONE_FOR_MAKEICONIC), TOOL_NAME,
1804 INFO_MB);
1805 return FALSE;
1806 }
1807 if (sym_path == NULL) {
1808 *icon_name = '\0';
1809 Dialog(TgLoadString(STID_ENTER_NAME_FOR_THE_ICON), NULL, icon_name);
1810 len = strlen(icon_name);
1811 if (*icon_name == '\0') {
1812 Msg(TgLoadString(STID_NAME_NOT_SPEC_ICON_NOT_CREATE));
1813 return FALSE;
1814 }
1815 } else {
1816 strncpy(icon_name, sym_path, sizeof(icon_name)-1);
1817 icon_name[sizeof(icon_name)-1] = '\0';
1818 len = strlen(icon_name);
1819 }
1820 sprintf(sym_ext_str, ".%s", SYM_FILE_EXT);
1821 sym_ext_len = strlen(sym_ext_str);
1822
1823 if (FileNameHasExtension(icon_name, OBJ_FILE_TYPE, NULL, NULL)) {
1824 MsgBox(TgLoadString(STID_CANT_SAVE_OBJ_ICON_NOT_CREATE), TOOL_NAME,
1825 INFO_MB);
1826 return FALSE;
1827 } else if (FileNameHasExtension(icon_name, SYM_FILE_TYPE, NULL, NULL)) {
1828 strcpy(icon_full_name, icon_name);
1829 if ((psz=UtilStrRChr(icon_name, '.')) != NULL) {
1830 *psz = '\0';
1831 } else {
1832 TgAssert(FALSE, TgLoadString(STID_CANT_FIND_DOT_IN_ICON_NAME_MI),
1833 NULL);
1834 return FALSE;
1835 }
1836 } else if (FileNameHasExtension(icon_name, PIN_FILE_TYPE, NULL, NULL)) {
1837 MsgBox(TgLoadString(STID_CANT_SAVE_PIN_ICON_NOT_CREATE), TOOL_NAME,
1838 INFO_MB);
1839 return FALSE;
1840 } else {
1841 strcpy(icon_full_name, icon_name);
1842 strcat(icon_full_name, sym_ext_str);
1843 }
1844 if (no_name) {
1845 MsgBox(TgLoadString(STID_NO_FILE_NAME_FILE_NOT_SAVED), TOOL_NAME,
1846 INFO_MB);
1847 return FALSE;
1848 }
1849 if (sym_path == NULL) {
1850 sprintf(file_name, "%s%c%s", curDir, DIR_SEP, icon_full_name);
1851 } else {
1852 strcpy(file_name, icon_full_name);
1853 }
1854 if (!OkayToCreateFile(file_name)) return FALSE;
1855 if ((short_name=IsPrefix(bootDir, file_name, &rest))) ++rest;
1856
1857 if ((fp=fopen(file_name, "w")) == NULL) {
1858 sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FOR_WRITE_ICON_CRET),
1859 (short_name ? rest : file_name));
1860 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1861 return FALSE;
1862 }
1863 if (sym_path == NULL) {
1864 if (!DirInSymPath(curDir)) UpdateSymInfo();
1865 }
1866 sprintf(gszMsgBox, TgLoadCachedString(CSTID_CREATING_FILE_DOTS),
1867 (short_name ? rest : file_name));
1868 Msg(gszMsgBox);
1869 SetStringStatus(gszMsgBox);
1870
1871 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1872
1873 if (record_cmd) {
1874 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
1875 }
1876 if (topSel->obj->type == OBJ_GROUP || topSel->obj->type == OBJ_SYM ||
1877 topSel->obj->type == OBJ_ICON || topSel->obj->type == OBJ_PIN) {
1878 JustMoveSelToTop();
1879 } else {
1880 GroupSingleObj(FALSE);
1881 if (topSel->obj->fattr != NULL) {
1882 Msg(TgLoadCachedString(CSTID_ATTR_PROMOTED_TO_NEW_ICON));
1883 }
1884 }
1885
1886 topSel->obj->type = OBJ_SYM;
1887 strcpy(topSel->obj->detail.r->s, icon_name);
1888 topSel->obj->detail.r->rotate = ROTATE0;
1889 topSel->obj->detail.r->flip = NO_FLIP;
1890 topSel->obj->detail.r->deck_index = (-1);
1891 /*
1892 * Need to check for pins.
1893 * Need to handle the case where connection objects need to be dupped!
1894 */
1895 topSel->obj->detail.r->pin_connected = 0;
1896 topSel->obj->detail.r->first_conn = topSel->obj->detail.r->last_conn =
1897 NULL;
1898
1899 writeFileFailed = FALSE;
1900 Save(fp, topSel->obj, 0, 1);
1901
1902 if (writeFileFailed) {
1903 writeFileFailed = FALSE;
1904 FailToWriteFileMessage(file_name);
1905 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1906 unlink(file_name);
1907 } else {
1908 sprintf(gszMsgBox, TgLoadCachedString(CSTID_NAMED_FILE_CREATED),
1909 (short_name ? rest : file_name));
1910 Msg(gszMsgBox);
1911 }
1912 fclose(fp);
1913
1914 if (record_cmd) {
1915 HighLightReverse();
1916 }
1917 topSel->obj->type = OBJ_ICON;
1918 topSel->obj->id = objId++;
1919 Msg(TgLoadString(STID_SEL_OBJ_IS_NOW_ICONIC));
1920 AdjObjBBox(topSel->obj);
1921 UpdSelBBox();
1922 if (record_cmd) {
1923 RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
1924 ltx = min(ltx,selLtX); lty = min(lty,selLtY);
1925 rbx = max(rbx,selRbX); rby = max(rby,selRbY);
1926 RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1927 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
1928 HighLightForward();
1929 SetFileModified(TRUE);
1930 justDupped = FALSE;
1931 }
1932 return TRUE;
1933 }
1934
UnMakeIconic()1935 void UnMakeIconic()
1936 {
1937 register struct ObjRec *obj_ptr;
1938 struct SelRec *sel_ptr;
1939 struct AttrRec *attr_ptr;
1940 int modified=FALSE;
1941
1942 HighLightReverse();
1943 StartCompositeCmd();
1944 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
1945 obj_ptr = sel_ptr->obj;
1946 /*
1947 * Need to check for pins.
1948 */
1949 if (obj_ptr->type == OBJ_ICON) {
1950 modified = TRUE;
1951 PrepareToReplaceAnObj(obj_ptr);
1952 obj_ptr->type = OBJ_GROUP;
1953 attr_ptr = obj_ptr->fattr;
1954 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
1955 attr_ptr->inherited = FALSE;
1956 }
1957 AdjObjBBox(obj_ptr);
1958 RecordReplaceAnObj(obj_ptr);
1959 }
1960 }
1961 EndCompositeCmd();
1962 if (modified) {
1963 Msg(TgLoadString(STID_SEL_OBJS_ARE_NOW_GROUP));
1964 UpdSelBBox();
1965 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1966 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1967 SetFileModified(TRUE);
1968 justDupped = FALSE;
1969 }
1970 HighLightForward();
1971 }
1972
1973 typedef struct ImportAttrLineRec {
1974 char *s;
1975 struct ImportAttrLineRec *next, *prev;
1976 } *ImportAttrLineRecPtr;
1977
1978 static struct ImportAttrLineRec *firstLine=NULL, *lastLine=NULL;
1979 static int numLines=0, nextX=0, nextY=0;
1980 static CVList gLineList;
1981
1982 static
AddLine(buf)1983 void AddLine(buf)
1984 char *buf;
1985 {
1986 struct ImportAttrLineRec *line_ptr;
1987
1988 line_ptr = (struct ImportAttrLineRec *)malloc(
1989 sizeof(struct ImportAttrLineRec));
1990 if (line_ptr == NULL) FailAllocMessage();
1991 line_ptr->s = buf;
1992 line_ptr->next = NULL;
1993 line_ptr->prev = lastLine;
1994 if (lastLine == NULL) {
1995 firstLine = line_ptr;
1996 } else {
1997 lastLine->next = line_ptr;
1998 }
1999 lastLine = line_ptr;
2000 numLines++;
2001 }
2002
2003 static
FreeImportLines()2004 void FreeImportLines()
2005 {
2006 struct ImportAttrLineRec *next_line=NULL;
2007
2008 for ( ; firstLine != NULL; firstLine=next_line) {
2009 next_line = firstLine->next;
2010 if (firstLine->s != NULL) free(firstLine->s);
2011 free(firstLine);
2012 }
2013 lastLine = NULL;
2014 numLines = 0;
2015 }
2016
2017 static
ImportAnAttr(obj_ptr,attr_line_num,fname)2018 void ImportAnAttr(obj_ptr, attr_line_num, fname)
2019 struct ObjRec *obj_ptr;
2020 int attr_line_num;
2021 char *fname;
2022 {
2023 int ok=TRUE;
2024 char *c_ptr;
2025
2026 if (firstLine == NULL) return;
2027 if ((c_ptr=strchr(firstLine->s, '=')) == NULL) {
2028 sprintf(gszMsgBox, TgLoadString(STID_GIVEN_LINE_SKIP_NOT_AN_ATTR),
2029 attr_line_num, fname);
2030 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2031 ok = FALSE;
2032 } else {
2033 *c_ptr = '\0';
2034 if (strchr(firstLine->s, '!') != NULL ||
2035 strchr(firstLine->s, '.') != NULL) {
2036 sprintf(gszMsgBox, TgLoadString(STID_GIVEN_LINE_SKIP_ILLEGAL_CHAR),
2037 attr_line_num, fname);
2038 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2039 ok = FALSE;
2040 }
2041 *c_ptr = '=';
2042 }
2043 if (ok) {
2044 char saved_ch='\0', *attr_name=NULL;
2045 struct AttrRec *attr_ptr=NULL;
2046 struct TextRec *text_ptr=NULL;
2047 MiniLineInfo *pMiniLine=NULL, *pFirstMiniLine=NULL, *pLastMiniLine=NULL;
2048 struct ImportAttrLineRec *line_ptr;
2049 int move_next_y=FALSE, underline_on=FALSE, single_font_text=FALSE;
2050 int sz_unit=INVALID, double_byte=INVALID, font=INVALID, style=INVALID;
2051 int color_index=INVALID, saved_color_index=INVALID, overline_on=FALSE;
2052
2053 c_ptr++;
2054 saved_ch = (*c_ptr);
2055 *c_ptr = '\0';
2056 attr_name = UtilStrDup(firstLine->s);
2057 if (attr_name == NULL) FailAllocMessage();
2058 *c_ptr = saved_ch;
2059
2060 if ((attr_ptr=FindAttrWithName(obj_ptr, attr_name, NULL)) == NULL) {
2061 attr_ptr = AddAttrByNameAndValue(obj_ptr, attr_name, c_ptr);
2062 attr_ptr->shown = TRUE;
2063 attr_ptr->obj->color = colorIndex;
2064 if (mainDisplay != NULL) {
2065 UtilStrCpyN(attr_ptr->obj->color_str,
2066 sizeof(attr_ptr->obj->color_str), colorMenuItems[colorIndex]);
2067 }
2068 MoveObj(attr_ptr->obj, nextX-attr_ptr->obj->x, nextY-attr_ptr->obj->y);
2069 text_ptr = attr_ptr->obj->detail.t;
2070 pFirstMiniLine = pLastMiniLine = text_ptr->minilines.first;
2071 move_next_y = TRUE;
2072 } else {
2073 MiniLineInfo *pNextMiniLine=NULL;
2074
2075 single_font_text = SingleFontText(attr_ptr->obj->detail.t, &sz_unit,
2076 &double_byte, &font, &style, &underline_on, &overline_on) &&
2077 SingleColorText(attr_ptr->obj->detail.t, &color_index);
2078 if (single_font_text) {
2079 saved_color_index = colorIndex;
2080
2081 PushCurFont();
2082 colorIndex = color_index;
2083 curFont = font;
2084 curSzUnit = sz_unit;
2085 curStyle = style;
2086 SetCanvasFont();
2087 }
2088 DynStrSet(&attr_ptr->attr_value, c_ptr);
2089 text_ptr = attr_ptr->obj->detail.t;
2090 text_ptr->cached_zoom = 0;
2091 if (text_ptr->cached_bitmap != None) {
2092 XFreePixmap(mainDisplay, text_ptr->cached_bitmap);
2093 }
2094 text_ptr->cached_bitmap = None;
2095 for (pMiniLine=text_ptr->minilines.first->next; pMiniLine != NULL;
2096 pMiniLine=pNextMiniLine) {
2097 pNextMiniLine = pMiniLine->next;
2098 FreeMiniLine(pMiniLine);
2099 }
2100 pFirstMiniLine = pLastMiniLine = text_ptr->minilines.last =
2101 text_ptr->minilines.first;
2102 text_ptr->minilines.first->next = text_ptr->minilines.first->prev =
2103 NULL;
2104 text_ptr->lines = 1;
2105 UpdAttr(attr_ptr);
2106 }
2107 free(attr_name);
2108 for (line_ptr=firstLine->next; line_ptr!=NULL; line_ptr=line_ptr->next) {
2109 CreateMiniLineFromString(line_ptr->s, &pFirstMiniLine, &pLastMiniLine);
2110 text_ptr->lines++;
2111 }
2112 if (single_font_text) {
2113 colorIndex = saved_color_index;
2114 PopCurFont();
2115 }
2116 text_ptr->minilines.first = pFirstMiniLine;
2117 text_ptr->minilines.last = pLastMiniLine;
2118 text_ptr->baseline_y = attr_ptr->obj->y+pFirstMiniLine->asc;
2119 RecalcTextMetrics(text_ptr, attr_ptr->obj->x, text_ptr->baseline_y);
2120 UpdTextBBox(attr_ptr->obj);
2121 if (move_next_y) {
2122 nextY += attr_ptr->obj->obbox.rby-attr_ptr->obj->obbox.lty;
2123 }
2124 }
2125 FreeImportLines();
2126 }
2127
ImportAttrs()2128 void ImportAttrs()
2129 {
2130 char fname[MAXPATHLENGTH+1], *rest, *buf;
2131 XEvent ev;
2132 int short_name, ltx, lty, rbx, rby, line_num=0, attr_line_num=1;
2133 int empty_line=TRUE;
2134 FILE *fp;
2135 struct ObjRec *obj_ptr;
2136
2137 if (topSel == NULL || topSel != botSel) {
2138 MsgBox(TgLoadString(STID_SEL_ONE_OBJ_FOR_IMPORTATTRS), TOOL_NAME,
2139 INFO_MB);
2140 return;
2141 }
2142 if (SelectFileNameToImport(TgLoadString(STID_SEL_TEXT_FILE_OF_ATTR_TO_IMP),
2143 TEXT_FILE_EXT, fname) == INVALID) {
2144 return;
2145 } else if (FileIsRemote(fname)) {
2146 MsgBox(TgLoadString(STID_CANT_IMPORT_REMOTE_TEXT_FILE), TOOL_NAME,
2147 INFO_MB);
2148 return;
2149 }
2150 XSync(mainDisplay, False);
2151 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
2152 ExposeEventHandler(&ev, TRUE);
2153 }
2154 if ((short_name=IsPrefix(bootDir, fname, &rest))) ++rest;
2155 if ((fp=fopen(fname, "r")) == NULL) {
2156 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
2157 (short_name ? rest : fname));
2158 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2159 return;
2160 }
2161 obj_ptr = topSel->obj;
2162 ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
2163 rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
2164
2165 SetWatchCursor(drawWindow);
2166 SetWatchCursor(mainWindow);
2167
2168 HighLightReverse();
2169 PrepareToReplaceAnObj(obj_ptr);
2170
2171 nextX = obj_ptr->obbox.ltx;
2172 nextY = obj_ptr->obbox.rby;
2173 while ((buf=UtilGetALine(fp)) != NULL) {
2174 line_num++;
2175 if (empty_line) {
2176 empty_line = FALSE;
2177 attr_line_num = line_num;
2178 }
2179 if (*buf == '\0') {
2180 ImportAnAttr(obj_ptr, attr_line_num, fname);
2181 empty_line = TRUE;
2182 } else {
2183 AddLine(buf);
2184 }
2185 }
2186 ImportAnAttr(obj_ptr, attr_line_num, fname);
2187 fclose(fp);
2188
2189 AdjObjBBox(obj_ptr);
2190
2191 RecordReplaceAnObj(obj_ptr);
2192
2193 SetDefaultCursor(mainWindow);
2194 ShowCursor();
2195
2196 UpdSelBBox();
2197 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2198 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2199 obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
2200 obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
2201 obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
2202 obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
2203 HighLightForward();
2204 SetFileModified(TRUE);
2205 justDupped = FALSE;
2206 }
2207
2208 #define INA_SKIP 0 /* skip this attribute */
2209 #define INA_OK 1 /* import this attribute */
2210 #define INA_MALFORMED 2 /* illegal attribute */
2211 #define INA_NEW 3 /* import this new attribute */
2212
2213 static
OkayToImportNamedAttr(num_restricted,ppsz_restricted)2214 int OkayToImportNamedAttr(num_restricted, ppsz_restricted)
2215 int num_restricted;
2216 char **ppsz_restricted;
2217 {
2218 int i=0, found=FALSE, rc=INA_OK;
2219 char *psz=NULL, saved_ch='\0';
2220
2221 if (firstLine == NULL || firstLine->s == NULL) return INA_SKIP;
2222
2223 psz = strchr(firstLine->s, '=');
2224 if (psz == NULL) {
2225 sprintf(gszMsgBox, TgLoadString(STID_BAD_LINE_MAY_HAVE_DEL_EQUAL),
2226 firstLine->s);
2227 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2228 return INA_MALFORMED;
2229 }
2230 saved_ch = *(++psz);
2231 *psz = '\0';
2232 for (i=0; i < num_restricted; i++) {
2233 char *attr_name=ppsz_restricted[i];
2234
2235 if (strcmp(attr_name, firstLine->s) == 0) {
2236 found = TRUE;
2237 break;
2238 }
2239 }
2240 *psz = saved_ch;
2241
2242 if (!found) {
2243 rc = INA_SKIP;
2244 *psz = '\0';
2245 sprintf(gszMsgBox, TgLoadString(STID_ATTR_NAME_CHANGED_IMPORT_Q),
2246 firstLine->s);
2247 switch (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)) {
2248 case MB_ID_YES: rc = INA_NEW; break;
2249 case MB_ID_NO: break;
2250 case MB_ID_CANCEL: break;
2251 }
2252 *psz = saved_ch;
2253 }
2254 return rc;
2255 }
2256
2257 typedef struct tagLineInfo {
2258 int status;
2259 int attr_line_num;
2260 int num_lines;
2261 struct ImportAttrLineRec *first, *last;
2262 } LineInfo;
2263
2264 static
CreateLineInfo(status,attr_line_num)2265 void CreateLineInfo(status, attr_line_num)
2266 int status, attr_line_num;
2267 {
2268 LineInfo *pli=(LineInfo*)malloc(sizeof(LineInfo));
2269
2270 if (pli == NULL) FailAllocMessage();
2271 memset(pli, 0, sizeof(LineInfo));
2272
2273 pli->status = status;
2274 pli->attr_line_num = attr_line_num;
2275 pli->num_lines = numLines;
2276 pli->first = firstLine;
2277 pli->last = lastLine;
2278
2279 firstLine = lastLine = NULL;
2280 numLines = 0;
2281
2282 ListAppend(&gLineList, pli);
2283 }
2284
2285 static
DoImportNamedAttrs(fp,num_restricted,ppsz_restricted,pn_ok_count,pn_skip_count,pn_bad_count)2286 void DoImportNamedAttrs(fp, num_restricted, ppsz_restricted, pn_ok_count,
2287 pn_skip_count, pn_bad_count)
2288 FILE *fp;
2289 int num_restricted, *pn_ok_count, *pn_skip_count, *pn_bad_count;
2290 char **ppsz_restricted;
2291 {
2292 char *buf=NULL;
2293 int bad_count=0, skip_count=0, ok_count=0, status=0;
2294 int line_num=0, attr_line_num=1, just_read_separator=TRUE;
2295
2296 CVListInit(&gLineList);
2297
2298 while ((buf=UtilGetALine(fp)) != NULL) {
2299 line_num++;
2300 if (just_read_separator) {
2301 just_read_separator = FALSE;
2302 attr_line_num = line_num;
2303 }
2304 if (strstr(buf, gszAttrSeparator) != NULL) {
2305 status = OkayToImportNamedAttr(num_restricted, ppsz_restricted);
2306
2307 switch (status) {
2308 case INA_SKIP: skip_count++; FreeImportLines(); break;
2309 case INA_OK: ok_count++; CreateLineInfo(status, attr_line_num); break;
2310 case INA_MALFORMED: bad_count++; FreeImportLines(); break;
2311 case INA_NEW: ok_count++; CreateLineInfo(status, attr_line_num); break;
2312 }
2313 just_read_separator = TRUE;
2314 } else {
2315 AddLine(buf);
2316 }
2317 }
2318 if (!just_read_separator) {
2319 status = OkayToImportNamedAttr(num_restricted, ppsz_restricted);
2320
2321 switch (status) {
2322 case INA_SKIP: skip_count++; FreeImportLines(); break;
2323 case INA_OK: ok_count++; CreateLineInfo(status, attr_line_num); break;
2324 case INA_MALFORMED: bad_count++; FreeImportLines(); break;
2325 case INA_NEW: ok_count++; CreateLineInfo(status, attr_line_num); break;
2326 }
2327 }
2328 if (pn_ok_count != NULL) *pn_ok_count = ok_count;
2329 if (pn_skip_count != NULL) *pn_skip_count = skip_count;
2330 if (pn_bad_count != NULL) *pn_bad_count = bad_count;
2331 }
2332
ImportNamedAttrs(fp,obj_ptr,num_restricted,ppsz_restricted,fname)2333 int ImportNamedAttrs(fp, obj_ptr, num_restricted, ppsz_restricted, fname)
2334 FILE *fp;
2335 struct ObjRec *obj_ptr;
2336 int num_restricted;
2337 char **ppsz_restricted, *fname;
2338 {
2339 int ltx=0, lty=0, rbx=0, rby=0, bad_count=0, skip_count=0, ok_count=0;
2340 CVListElem *elem=NULL;
2341
2342 ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
2343 rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
2344
2345 DoImportNamedAttrs(fp, num_restricted, ppsz_restricted, &ok_count,
2346 &skip_count, &bad_count);
2347
2348 if (bad_count > 0) {
2349 sprintf(gszMsgBox, TgLoadString(STID_CANT_IMPORT_ATTR_GROUP_RETRY),
2350 TOOL_NAME);
2351 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2352 return FALSE;
2353 }
2354 if (ListEmpty(&gLineList)) return TRUE;
2355
2356 SetWatchCursor(drawWindow);
2357 SetWatchCursor(mainWindow);
2358
2359 HighLightReverse();
2360 PrepareToReplaceAnObj(obj_ptr);
2361
2362 nextX = obj_ptr->obbox.ltx;
2363 nextY = obj_ptr->obbox.rby;
2364
2365 for (elem=ListFirst(&gLineList); elem != NULL;
2366 elem=ListNext(&gLineList, elem)) {
2367 LineInfo *pli=(LineInfo*)(elem->obj);
2368
2369 if (pli != NULL) {
2370 int attr_line_num=pli->attr_line_num;
2371
2372 firstLine = pli->first;
2373 lastLine = pli->last;
2374 numLines = pli->num_lines;
2375
2376 ImportAnAttr(obj_ptr, attr_line_num, fname);
2377 }
2378 elem->obj = NULL;
2379 }
2380 ListUnlinkAll(&gLineList);
2381
2382 AdjObjBBox(obj_ptr);
2383
2384 RecordReplaceAnObj(obj_ptr);
2385
2386 SetDefaultCursor(mainWindow);
2387 ShowCursor();
2388
2389 UpdSelBBox();
2390 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2391 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2392 obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
2393 obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
2394 obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
2395 obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
2396 HighLightForward();
2397 SetFileModified(TRUE);
2398 justDupped = FALSE;
2399
2400 return TRUE;
2401 }
2402
ExportAttrs()2403 void ExportAttrs()
2404 {
2405 char fname[MAXPATHLENGTH+1], full_fname[MAXPATHLENGTH+1];
2406 char *c_ptr, *dot_ptr, *rest;
2407 int short_name;
2408 FILE *fp;
2409 struct AttrRec *attr_ptr;
2410
2411 if (topSel == NULL || topSel != botSel) {
2412 MsgBox(TgLoadString(STID_SEL_ONE_OBJ_FOR_EXPORTATTRS), TOOL_NAME,
2413 INFO_MB);
2414 return;
2415 } else if (topSel->obj->lattr == NULL) {
2416 MsgBox(TgLoadString(STID_SEL_OBJ_HAS_NO_ATTR_TO_EXPORT), TOOL_NAME,
2417 INFO_MB);
2418 return;
2419 }
2420 sprintf(gszMsgBox, TgLoadString(STID_WORKING_DIRECTORY_IS),
2421 (curDirIsLocal ? curDir : curLocalDir));
2422 *fname = '\0';
2423 Dialog(TgLoadString(STID_ENTER_TXT_FILE_TO_EXPORT_CRES), gszMsgBox, fname);
2424 if (*fname == '\0') return;
2425 if (*fname == DIR_SEP) {
2426 strcpy(full_fname, fname);
2427 } else {
2428 sprintf(full_fname, "%s%c%s", curDirIsLocal ? curDir : curLocalDir,
2429 DIR_SEP, fname);
2430 }
2431 if ((c_ptr=UtilStrRChr(full_fname, (int)DIR_SEP)) == NULL) {
2432 if ((dot_ptr=UtilStrRChr(full_fname, (int)'.')) == NULL) {
2433 sprintf(&full_fname[strlen(full_fname)], ".%s", TEXT_FILE_EXT);
2434 } else {
2435 if (strcmp(&dot_ptr[1], TEXT_FILE_EXT) != 0) {
2436 sprintf(&dot_ptr[strlen(dot_ptr)], ".%s", TEXT_FILE_EXT);
2437 }
2438 }
2439 } else {
2440 if ((dot_ptr=UtilStrRChr(c_ptr, (int)'.')) == NULL) {
2441 sprintf(&c_ptr[strlen(c_ptr)], ".%s", TEXT_FILE_EXT);
2442 } else {
2443 if (strcmp(&dot_ptr[1], TEXT_FILE_EXT) != 0) {
2444 sprintf(&dot_ptr[strlen(dot_ptr)], ".%s", TEXT_FILE_EXT);
2445 }
2446 }
2447 }
2448 if (!OkayToCreateFile(full_fname)) return;
2449
2450 if ((short_name=IsPrefix(bootDir, full_fname, &rest))) ++rest;
2451 if ((fp=fopen(full_fname, "w")) == NULL) {
2452 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
2453 (short_name ? rest : full_fname));
2454 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2455 return;
2456 }
2457 sprintf(gszMsgBox, TgLoadCachedString(CSTID_WRITING_ATTR_TO_NAMED_FILE),
2458 (short_name ? rest : full_fname));
2459 Msg(gszMsgBox);
2460 writeFileFailed = FALSE;
2461
2462 for (attr_ptr=topSel->obj->lattr; !writeFileFailed && attr_ptr != NULL;
2463 attr_ptr=attr_ptr->prev) {
2464 MiniLineInfo *pMiniLine=NULL;
2465
2466 if (attr_ptr != topSel->obj->lattr) fprintf(fp, "\n");
2467 if (fprintf(fp, "%s%s\n", attr_ptr->attr_name.s,
2468 attr_ptr->attr_value.s) == EOF) {
2469 writeFileFailed = TRUE;
2470 }
2471 if (!writeFileFailed &&
2472 (pMiniLine=attr_ptr->obj->detail.t->minilines.first) != NULL) {
2473 for (pMiniLine=pMiniLine->next; !writeFileFailed && pMiniLine != NULL;
2474 pMiniLine=pMiniLine->next) {
2475 int need_to_free_tmp_buf=FALSE;
2476 char *tmp_buf=ConvertMiniLineToString(pMiniLine,
2477 &need_to_free_tmp_buf);
2478
2479 if (fprintf(fp, "%s\n", tmp_buf) == EOF) {
2480 writeFileFailed = TRUE;
2481 }
2482 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
2483 if (writeFileFailed) break;
2484 }
2485 }
2486 }
2487 if (writeFileFailed) {
2488 writeFileFailed = FALSE;
2489 FailToWriteFileMessage(full_fname);
2490 } else {
2491 sprintf(gszMsgBox, TgLoadString(STID_ATTR_EXPORTED_TO_NAMED_FILE),
2492 (short_name ? rest : full_fname));
2493 Msg(gszMsgBox);
2494 }
2495 fclose(fp);
2496 }
2497
2498 static
GetMergeSpec(obj_ptr,attr_name,pn_val,distance)2499 int GetMergeSpec(obj_ptr, attr_name, pn_val, distance)
2500 struct ObjRec *obj_ptr;
2501 char *attr_name;
2502 int *pn_val, distance;
2503 {
2504 struct AttrRec *attr_ptr=FindAttrWithName(obj_ptr, attr_name, NULL);
2505 char *c_ptr;
2506 double val;
2507
2508 if (attr_ptr == NULL) {
2509 sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_ATTR_FOR_MERGEWTBL),
2510 attr_name);
2511 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2512 return FALSE;
2513 }
2514 if (distance && ((c_ptr=strstr(attr_ptr->attr_value.s, "in")) != NULL ||
2515 (c_ptr=strstr(attr_ptr->attr_value.s, "In")) != NULL ||
2516 (c_ptr=strstr(attr_ptr->attr_value.s, "IN")) != NULL)) {
2517 char saved_ch=(*c_ptr);
2518
2519 *c_ptr = '\0';
2520 if (sscanf(attr_ptr->attr_value.s, "%lf", &val) != 1) {
2521 *c_ptr = saved_ch;
2522 sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_ATTR_FOR_MERGEWTBL),
2523 attr_name);
2524 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2525 return FALSE;
2526 }
2527 *c_ptr = saved_ch;
2528 val = val * ((double)PIX_PER_INCH);
2529 *pn_val = round(val);
2530 } else if (distance &&
2531 ((c_ptr=strstr(attr_ptr->attr_value.s, "cm")) != NULL ||
2532 (c_ptr=strstr(attr_ptr->attr_value.s, "Cm")) != NULL ||
2533 (c_ptr=strstr(attr_ptr->attr_value.s, "CM")) != NULL)) {
2534 char saved_ch=(*c_ptr);
2535
2536 *c_ptr = '\0';
2537 if (sscanf(attr_ptr->attr_value.s, "%lf", &val) != 1) {
2538 *c_ptr = saved_ch;
2539 sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_ATTR_FOR_MERGEWTBL),
2540 attr_name);
2541 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2542 return FALSE;
2543 }
2544 *c_ptr = saved_ch;
2545 val = val * ((double)ONE_CM);
2546 *pn_val = round(val);
2547 } else {
2548 if (sscanf(attr_ptr->attr_value.s, "%d", pn_val) != 1) {
2549 sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_ATTR_FOR_MERGEWTBL),
2550 attr_name);
2551 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2552 return FALSE;
2553 }
2554 }
2555 return TRUE;
2556 }
2557
MergeWithTable()2558 void MergeWithTable()
2559 {
2560 char fname[MAXPATHLENGTH+1], *rest, paper_size_spec[80], *spec, **col_names;
2561 char *buf, *c_ptr, *val_ptr;
2562 XEvent ev;
2563 int i, short_name, columns_in_file, ok=TRUE, line_num, user_placement;
2564 int left_margin=0, top_margin=0, v_pitch=0, h_pitch=0, strip_double_quotes;
2565 int num_cols=0, num_rows=0, paper_w=0, paper_h=0, x, y, r, c;
2566 int tab_separated=TRUE;
2567 FILE *fp;
2568 struct ObjRec *template_obj;
2569
2570 if (topSel == NULL || topSel != botSel) {
2571 MsgBox(TgLoadString(STID_SEL_ONE_OBJ_FOR_MERGEWTBL), TOOL_NAME, INFO_MB);
2572 return;
2573 }
2574 /* do not translate -- program constants */
2575 template_obj = topSel->obj;
2576 user_placement = (FindAttrWithName(template_obj, "USER_PLACEMENT", NULL) !=
2577 NULL);
2578 strip_double_quotes = (FindAttrWithName(template_obj, "STRIP_DOUBLE_QUOTES",
2579 NULL) != NULL);
2580 if (!user_placement) {
2581 /* do not translate -- program constants */
2582 if (!(GetMergeSpec(template_obj, "LEFT_MARGIN=", &left_margin, TRUE) &&
2583 GetMergeSpec(template_obj, "TOP_MARGIN=", &top_margin, TRUE) &&
2584 GetMergeSpec(template_obj, "V_PITCH=", &v_pitch, TRUE) &&
2585 GetMergeSpec(template_obj, "H_PITCH=", &h_pitch, TRUE) &&
2586 GetMergeSpec(template_obj, "NUM_COLS=", &num_cols, FALSE) &&
2587 GetMergeSpec(template_obj, "NUM_ROWS=", &num_rows, FALSE) &&
2588 GetMergeSpec(template_obj, "PAPER_WIDTH=", &paper_w, TRUE) &&
2589 GetMergeSpec(template_obj, "PAPER_HEIGHT=", &paper_h, TRUE))) {
2590 return;
2591 }
2592 }
2593 while (!DirIsRemote(curDir) && fileModified && !IsFiletUnSavable()) {
2594 XBell(mainDisplay, 0);
2595 switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_MERGE), TOOL_NAME,
2596 YNC_MB)) {
2597 case MB_ID_YES: SaveFile(); break;
2598 case MB_ID_NO: SetFileModified(FALSE); break;
2599 case MB_ID_CANCEL: return;
2600 }
2601 }
2602 if (firstCmd != NULL) {
2603 if (MsgBox(TgLoadString(STID_Q_MERGEWTBL_CANT_UNDO_PROCEED), TOOL_NAME,
2604 YNC_MB) != MB_ID_YES) {
2605 return;
2606 }
2607 CleanUpCmds();
2608 }
2609 if (SelectFileNameToImport(TgLoadString(STID_SEL_TEXT_FILE_FOR_MERGEWTBL),
2610 TEXT_FILE_EXT, fname) == INVALID) {
2611 return;
2612 } else if (FileIsRemote(fname)) {
2613 MsgBox(TgLoadString(STID_CANT_MERGE_W_REMOTE_TEXT_FILE), TOOL_NAME,
2614 INFO_MB);
2615 return;
2616 }
2617 XSync(mainDisplay, False);
2618 if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
2619 ExposeEventHandler(&ev, TRUE);
2620 }
2621 if ((short_name=IsPrefix(bootDir, fname, &rest))) ++rest;
2622 if ((fp=fopen(fname, "r")) == NULL) {
2623 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
2624 (short_name ? rest : fname));
2625 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2626 return;
2627 }
2628 if ((spec=UtilGetALine(fp)) == NULL) {
2629 fclose(fp);
2630 sprintf(gszMsgBox, TgLoadString(STID_FIND_COL_NAMES_IN_FILE_ABORT),
2631 (short_name ? rest : fname));
2632 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2633 return;
2634 }
2635 columns_in_file = 1;
2636 val_ptr = spec;
2637 c_ptr = strchr(val_ptr, '\t');
2638 if (c_ptr == NULL && (c_ptr=strchr(val_ptr, ';')) != NULL) {
2639 tab_separated = FALSE;
2640 Msg(TgLoadCachedString(CSTID_SEMICOLON_USED_AS_SEPARATOR));
2641 } else {
2642 Msg(TgLoadCachedString(CSTID_TAB_USED_AS_SEPARATOR));
2643 }
2644 while (val_ptr != NULL) {
2645 if (c_ptr != NULL) *c_ptr = '\0';
2646 if (*val_ptr == '\0') {
2647 free(spec);
2648 fclose(fp);
2649 sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_COL_NAMES_ABORT_MRG),
2650 (short_name ? rest : fname));
2651 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2652 return;
2653 }
2654 if (c_ptr == NULL) break;
2655 *c_ptr++ = (tab_separated ? '\t' : ';');
2656 val_ptr = c_ptr;
2657 c_ptr = strchr(val_ptr, tab_separated ? '\t' : ';');
2658
2659 columns_in_file++;
2660 }
2661 col_names = (char**)malloc((columns_in_file+1)*sizeof(char*));
2662 if (col_names == NULL) {
2663 free(spec);
2664 fclose(fp);
2665 FailAllocMessage();
2666 return;
2667 }
2668 col_names[columns_in_file] = NULL;
2669 i = 0;
2670 val_ptr = spec;
2671 for (c_ptr=strchr(val_ptr, tab_separated ? '\t' : ';'); val_ptr != NULL;
2672 i++) {
2673 int len;
2674
2675 if (c_ptr != NULL) *c_ptr = '\0';
2676 if (!tab_separated) {
2677 UtilTrimBlanks(val_ptr);
2678 if (strip_double_quotes && *val_ptr == '"') {
2679 len = strlen(val_ptr);
2680
2681 if (val_ptr[len-1] == '"') {
2682 val_ptr[len-1] = '\0';
2683 val_ptr++;
2684 }
2685 }
2686 }
2687 len = strlen(val_ptr);
2688 if ((col_names[i]=(char*)malloc((len+2)*sizeof(char))) == NULL) {
2689 FailAllocMessage();
2690 columns_in_file = i;
2691 for (i=0; i < columns_in_file; i++) {
2692 if (col_names[i] != NULL) {
2693 free(col_names[i]);
2694 }
2695 }
2696 free(col_names);
2697 free(spec);
2698 fclose(fp);
2699 return;
2700 }
2701 sprintf(col_names[i], "%s=", val_ptr);
2702 if (FindAttrWithName(template_obj, col_names[i], NULL) == NULL) {
2703 free(col_names[i]);
2704 col_names[i] = NULL;
2705 }
2706 if (c_ptr == NULL) break;
2707 *c_ptr++ = (tab_separated ? '\t' : ';');
2708 val_ptr = c_ptr;
2709 c_ptr = strchr(val_ptr, tab_separated ? '\t' : ';');
2710 }
2711 free(spec);
2712
2713 MakeQuiescent();
2714 UnlinkObj(template_obj);
2715 NewProc();
2716 if (pageLayoutMode == PAGE_TILE) {
2717 PageLayoutSubMenu(PAGE_STACK);
2718 while (lastPageNum > 1) {
2719 DeleteCurPage();
2720 }
2721 }
2722 if (!user_placement) {
2723 sprintf(paper_size_spec, "%1d x %1d", paper_w, paper_h);
2724 if (!SetPaperSize(paper_size_spec)) {
2725 return;
2726 }
2727 printMag = (float)100.0;
2728 UpdPageStyle(PORTRAIT);
2729 }
2730 UpdDrawWinBBox();
2731 AdjSplineVs();
2732 RedrawScrollBars();
2733 RedrawRulers();
2734 RedrawTitleWindow();
2735
2736 SaveStatusStrings();
2737 if (user_placement) {
2738 strcpy(gszMsgBox, TgLoadString(STID_LF_BTN_PLACE_MRG_OTHER_CANCEL));
2739 Msg(gszMsgBox);
2740 SetStringStatus(gszMsgBox);
2741 }
2742 line_num = 1;
2743 x = left_margin;
2744 y = top_margin;
2745 r = c = 0;
2746 while (ok && (buf=UtilGetALine(fp)) != NULL) {
2747 struct ObjRec *obj_ptr=DupObj(template_obj);
2748
2749 if (obj_ptr == NULL) {
2750 ok = FALSE;
2751 free(buf);
2752 break;
2753 }
2754 sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROCESSING_OBJ_NUMBER),
2755 line_num);
2756 SetStringStatus(gszMsgBox);
2757 XSync(mainDisplay, False);
2758
2759 AddObj(NULL, topObj, obj_ptr);
2760 AdjObjBBox(obj_ptr);
2761 MoveObj(obj_ptr, x-obj_ptr->obbox.ltx, y-obj_ptr->obbox.lty);
2762
2763 line_num++;
2764 i = 0;
2765 val_ptr = buf;
2766 replaceAttrFirstValueRedraw = FALSE;
2767 for (c_ptr=strchr(val_ptr, tab_separated ? '\t' : ';'); val_ptr != NULL;
2768 i++) {
2769 struct AttrRec *attr_ptr;
2770
2771 if (c_ptr != NULL) *c_ptr = '\0';
2772
2773 if (col_names[i] != NULL && (attr_ptr=FindAttrWithName(obj_ptr,
2774 col_names[i], NULL)) != NULL) {
2775 if (!tab_separated) UtilTrimBlanks(val_ptr);
2776 if (strip_double_quotes && *val_ptr == '"') {
2777 int len=strlen(val_ptr);
2778
2779 if (val_ptr[len-1] == '"') {
2780 val_ptr[len-1] = '\0';
2781 ReplaceAttrFirstValue(obj_ptr, attr_ptr, &val_ptr[1]);
2782 val_ptr[len-1] = '"';
2783 } else {
2784 ReplaceAttrFirstValue(obj_ptr, attr_ptr, val_ptr);
2785 }
2786 } else {
2787 ReplaceAttrFirstValue(obj_ptr, attr_ptr, val_ptr);
2788 }
2789 }
2790 if (c_ptr == NULL) break;
2791 *c_ptr++ = (tab_separated ? '\t' : ';');
2792 val_ptr = c_ptr;
2793 c_ptr = strchr(val_ptr, tab_separated ? '\t' : ';');
2794 }
2795 replaceAttrFirstValueRedraw = TRUE;
2796 UnlinkObj(obj_ptr);
2797 if (firstCmd != NULL) CleanUpCmds();
2798 if (i+1 != columns_in_file) {
2799 ok = FALSE;
2800 sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_TBL_LINE_ABORT_MRG),
2801 line_num, (short_name ? rest : fname));
2802 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2803 FreeObj(obj_ptr);
2804 ClearAndRedrawDrawWindow();
2805 } else {
2806 struct AttrRec *attr_ptr=NULL;
2807 int saved_history_depth=historyDepth;
2808
2809 AdjObjBBox(obj_ptr);
2810 AddObj(NULL, topObj, obj_ptr);
2811 if (user_placement) {
2812 if ((attr_ptr=FindAttrWithName(obj_ptr, "name=",
2813 NULL)) != NULL) {
2814 sprintf(gszMsgBox, TgLoadCachedString(CSTID_PLACING_NAMED_OBJ),
2815 attr_ptr->attr_value.s);
2816 SetStringStatus(gszMsgBox);
2817 XSync(mainDisplay, False);
2818 }
2819 if (PlaceTopObj(obj_ptr, NULL, NULL) == Button3) {
2820 Msg(TgLoadString(STID_OPERATION_CANCEL_BY_USER));
2821 ok = FALSE;
2822 }
2823 AssignNewObjIds(obj_ptr);
2824 }
2825 numRedrawBBox = 0;
2826 obj_ptr->tmp_parent = NULL;
2827 DrawObj(drawWindow, obj_ptr);
2828 /* do not translate -- program constants */
2829 if ((attr_ptr=FindAttrWithName(obj_ptr, "EXEC_AFTER_MERGE=",
2830 NULL)) != NULL) {
2831 char name[MAXSTRING+1];
2832 struct AttrRec *next_attr_ptr=NULL;
2833
2834 if (*attr_ptr->attr_value.s != '\0') {
2835 sprintf(name, "%s=", attr_ptr->attr_value.s);
2836 if ((next_attr_ptr=FindAttrWithName(obj_ptr, name, NULL)) !=
2837 NULL) {
2838 int saved_intr_check_interval=intrCheckInterval;
2839
2840 intrCheckInterval = 1;
2841 ShowInterrupt(1);
2842 if (!DoExec(next_attr_ptr, obj_ptr)) {
2843 ok = FALSE;
2844 }
2845 while (HideInterrupt() > 0) ;
2846 intrCheckInterval = saved_intr_check_interval;
2847 } else {
2848 sprintf(gszMsgBox,
2849 TgLoadString(STID_CANT_FND_NAMED_ATTR_ABORT_MRG),
2850 attr_ptr->attr_value.s);
2851 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2852 ok = FALSE;
2853 }
2854 }
2855 attr_ptr = next_attr_ptr;
2856 } else if ((attr_ptr=FindAttrWithName(obj_ptr, EXEC_ATTR, NULL)) !=
2857 NULL) {
2858 int saved_intr_check_interval=intrCheckInterval;
2859
2860 intrCheckInterval = 1;
2861 ShowInterrupt(1);
2862 if (!DoExec(attr_ptr, obj_ptr)) {
2863 ok = FALSE;
2864 }
2865 while (HideInterrupt() > 0) ;
2866 intrCheckInterval = saved_intr_check_interval;
2867 }
2868 if (saved_history_depth != historyDepth) RestoreDefaultHistoryDepth();
2869 if (firstCmd != NULL) CleanUpCmds();
2870 if (ok && !user_placement) {
2871 c++;
2872 if (c >= num_cols) {
2873 c = 0;
2874 x = left_margin;
2875 r++;
2876 if (r >= num_rows) {
2877 r = 0;
2878 y = top_margin;
2879 AddPageAfter();
2880 } else {
2881 y += v_pitch;
2882 }
2883 } else {
2884 x += h_pitch;
2885 }
2886 }
2887 }
2888 free(buf);
2889 }
2890 fclose(fp);
2891
2892 RestoreStatusStrings();
2893 sprintf(gszMsgBox, TgLoadString(STID_NUM_OBJECTS_GENERATED), line_num-1);
2894 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2895
2896 FreeObj(template_obj);
2897 for (i=0; i < columns_in_file; i++) {
2898 if (col_names[i] != NULL) {
2899 free(col_names[i]);
2900 }
2901 }
2902 free(col_names);
2903 if (firstCmd != NULL) CleanUpCmds();
2904 SetFileModified(TRUE);
2905 justDupped = FALSE;
2906 }
2907
ExportToTable()2908 void ExportToTable()
2909 {
2910 char msg[MAXSTRING+1], fname[MAXPATHLENGTH+1], full_fname[MAXPATHLENGTH+1];
2911 char *c_ptr, *dot_ptr, *rest=NULL, *spec, *spec_copy, **col_names=NULL, *buf;
2912 int short_name, total, i, num_exported, buf_sz, ok=TRUE;
2913 FILE *fp;
2914 struct AttrRec *spec_attr=NULL;
2915 MiniLineInfo *pMiniLine=NULL;
2916 struct SelRec *sel_ptr=NULL;
2917
2918 if (topSel == NULL) {
2919 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2920 return;
2921 }
2922 /* do not translate -- program constants */
2923 strcpy(msg, "!.TABLE_ATTRS=");
2924 spec_attr = FindAttrWithName(NULL, msg, NULL);
2925 if (spec_attr == NULL) {
2926 MsgBox(TgLoadString(STID_CANT_FND_TABLE_ATTRS_FILE_ATT), TOOL_NAME,
2927 INFO_MB);
2928 return;
2929 }
2930 sprintf(gszMsgBox, TgLoadString(STID_WORKING_DIRECTORY_IS),
2931 (curDirIsLocal ? curDir : curLocalDir));
2932 *fname = '\0';
2933 Dialog(TgLoadString(STID_ENTER_TXT_FILE_TO_EXPORT_CRES), gszMsgBox, fname);
2934
2935 if (*fname == '\0') return;
2936
2937 if (*fname == DIR_SEP) {
2938 strcpy(full_fname, fname);
2939 } else {
2940 sprintf(full_fname, "%s%c%s", curDirIsLocal ? curDir : curLocalDir,
2941 DIR_SEP, fname);
2942 }
2943 if ((c_ptr=UtilStrRChr(full_fname, (int)DIR_SEP)) == NULL) {
2944 if ((dot_ptr=UtilStrRChr(full_fname, (int)'.')) == NULL) {
2945 sprintf(&full_fname[strlen(full_fname)], ".%s", TEXT_FILE_EXT);
2946 } else {
2947 if (strcmp(&dot_ptr[1], TEXT_FILE_EXT) != 0) {
2948 sprintf(&dot_ptr[strlen(dot_ptr)], ".%s", TEXT_FILE_EXT);
2949 }
2950 }
2951 } else {
2952 if ((dot_ptr=UtilStrRChr(c_ptr, (int)'.')) == NULL) {
2953 sprintf(&c_ptr[strlen(c_ptr)], ".%s", TEXT_FILE_EXT);
2954 } else {
2955 if (strcmp(&dot_ptr[1], TEXT_FILE_EXT) != 0) {
2956 sprintf(&dot_ptr[strlen(dot_ptr)], ".%s", TEXT_FILE_EXT);
2957 }
2958 }
2959 }
2960 if (!OkayToCreateFile(full_fname)) return;
2961
2962 if ((short_name=IsPrefix(bootDir, full_fname, &rest))) ++rest;
2963 if ((fp=fopen(full_fname, "w")) == NULL) {
2964 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
2965 (short_name ? rest : full_fname));
2966 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2967 return;
2968 }
2969 sprintf(gszMsgBox, TgLoadCachedString(CSTID_WRITING_ATTRS_IN_TBL_FORM_TO),
2970 (short_name ? rest : full_fname));
2971 Msg(gszMsgBox);
2972 writeFileFailed = FALSE;
2973
2974 total = 0;
2975 for (pMiniLine=spec_attr->obj->detail.t->minilines.first; pMiniLine != NULL;
2976 pMiniLine=pMiniLine->next) {
2977 int need_to_free_tmp_buf=FALSE;
2978 char *tmp_buf=ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
2979
2980 total += strlen(tmp_buf)+1;
2981 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
2982 }
2983 if ((spec=(char*)malloc((total+1)*sizeof(char))) == NULL) {
2984 FailAllocMessage();
2985 fclose(fp);
2986 return;
2987 }
2988 c_ptr = spec;
2989 for (pMiniLine=spec_attr->obj->detail.t->minilines.first; pMiniLine != NULL;
2990 pMiniLine=pMiniLine->next) {
2991 int len=0, need_to_free_tmp_buf=FALSE;
2992 char *tmp_buf=NULL;
2993
2994 if (pMiniLine == spec_attr->obj->detail.t->minilines.first) {
2995 char *attr_value=NULL;
2996
2997 tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
2998 attr_value = UtilStrDup(tmp_buf);
2999 if (attr_value == NULL) FailAllocMessage();
3000 ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
3001 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3002 need_to_free_tmp_buf = TRUE;
3003 tmp_buf = attr_value;
3004 } else {
3005 tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3006 }
3007 len = strlen(tmp_buf);
3008 strcpy(c_ptr, tmp_buf);
3009 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3010 c_ptr += len;
3011 *c_ptr++ = ',';
3012 }
3013 *c_ptr = '\0';
3014 if ((spec_copy=UtilStrDup(spec)) == NULL) {
3015 FailAllocMessage();
3016 free(spec);
3017 fclose(fp);
3018 return;
3019 }
3020 total = 0;
3021 for (c_ptr=strtok(spec_copy, " ,;\t\n\r"); c_ptr != NULL;
3022 c_ptr=strtok(NULL, " ,;\t\n\r")) {
3023 total++;
3024 }
3025 free(spec_copy);
3026
3027 buf_sz = 0x400;
3028 spec_copy = UtilStrDup(spec);
3029 col_names = (char**)malloc((total+1)*sizeof(char*));
3030 buf = (char*)malloc((buf_sz+2)*sizeof(char));
3031 if (spec_copy == NULL || col_names == NULL || buf == NULL) {
3032 FailAllocMessage();
3033 if (col_names != NULL) free(col_names);
3034 if (spec_copy != NULL) free(spec_copy);
3035 if (buf != NULL) free(buf);
3036 free(spec);
3037 fclose(fp);
3038 return;
3039 }
3040 col_names[total] = NULL;
3041 i = 0;
3042 for (c_ptr=strtok(spec_copy, " ,;\t\n\r"); c_ptr != NULL && !writeFileFailed;
3043 c_ptr=strtok(NULL, " ,;\t\n\r"), i++) {
3044 int len=strlen(c_ptr);
3045
3046 if ((col_names[i]=(char*)malloc((len+2)*sizeof(char))) == NULL) {
3047 FailAllocMessage();
3048 for (total=0; total < i; total++) free(col_names[i]);
3049 free(col_names);
3050 free(spec_copy);
3051 free(buf);
3052 free(spec);
3053 fclose(fp);
3054 return;
3055 }
3056 if (fprintf(fp, "%s%s", (i==0 ? "" : "\t"), c_ptr) == EOF) {
3057 writeFileFailed = TRUE;
3058 }
3059 sprintf(col_names[i], "%s=", c_ptr);
3060 }
3061 fprintf(fp, "\n");
3062
3063 num_exported = 0;
3064 SaveStatusStrings();
3065 for (sel_ptr=botSel; ok && sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
3066 int percent=(i*10000/numObjSelected)/100, col;
3067 int something_exported=FALSE, cur_len=0;
3068
3069 sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT), percent);
3070 SetStringStatus(gszMsgBox);
3071 XSync(mainDisplay, False);
3072
3073 for (col=0; ok && col < total; col++) {
3074 int len;
3075 struct AttrRec *attr_ptr=FindAttrWithName(sel_ptr->obj,
3076 col_names[col], NULL);
3077
3078 if (attr_ptr != NULL) something_exported = TRUE;
3079
3080 sprintf(gszMsgBox, "%s%s", (col==0 ? "" : "\t"),
3081 (attr_ptr==NULL ? "": attr_ptr->attr_value.s));
3082 len = strlen(gszMsgBox);
3083 while (len+cur_len >= buf_sz) {
3084 buf_sz += 0x400;
3085 buf = (char*)realloc(buf, (buf_sz+2)*sizeof(char));
3086 if (buf == NULL) {
3087 FailAllocMessage();
3088 ok = FALSE;
3089 break;
3090 }
3091 }
3092 if (ok) {
3093 sprintf(&buf[cur_len], gszMsgBox);
3094 cur_len += len;
3095 }
3096 }
3097 buf[cur_len] = '\0';
3098 if (something_exported) {
3099 num_exported++;
3100 if (fprintf(fp, "%s\n", buf) == EOF) {
3101 writeFileFailed = TRUE;
3102 ok = FALSE;
3103 }
3104 }
3105 }
3106 RestoreStatusStrings();
3107 sprintf(gszMsgBox, TgLoadString(STID_NUM_OBJECTS_EXPORTED), num_exported);
3108 Msg(gszMsgBox);
3109
3110 for (i=0; i < total; i++) free(col_names[i]);
3111 free(col_names);
3112 free(spec_copy);
3113 if (buf != NULL) free(buf);
3114 free(spec);
3115 fclose(fp);
3116
3117 if (writeFileFailed) {
3118 writeFileFailed = FALSE;
3119 FailToWriteFileMessage(full_fname);
3120 } else {
3121 sprintf(gszMsgBox, TgLoadString(STID_ATTRS_EXPORTED_TO_TBL_FILE),
3122 (short_name ? rest : full_fname));
3123 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3124 }
3125 }
3126
ToggleShowWireSignalName()3127 void ToggleShowWireSignalName()
3128 {
3129 showWireSignalName = !showWireSignalName;
3130 sprintf(gszMsgBox, TgLoadString(showWireSignalName ?
3131 STID_WILL_SHOW_WIRE_SIGNAL_NAME : STID_WILL_HIDE_WIRE_SIGNAL_NAME));
3132 Msg(gszMsgBox);
3133 }
3134
RefreshPortMenu(menu)3135 int RefreshPortMenu(menu)
3136 TgMenu *menu;
3137 {
3138 int ok=TRUE;
3139
3140 /* Show Wire Signal Name */
3141 ok &= TgSetMenuItemCheckById(menu, CMDID_TOGGLESHOWWIRESIGNALNAME,
3142 showWireSignalName);
3143
3144 return ok;
3145 }
3146
CreatePortMenu(parent_menu,x,y,menu_info,status_str_xlated)3147 TgMenu *CreatePortMenu(parent_menu, x, y, menu_info, status_str_xlated)
3148 TgMenu *parent_menu;
3149 int x, y;
3150 TgMenuInfo *menu_info;
3151 int status_str_xlated; /* ignored, always 0 */
3152 {
3153 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
3154
3155 if (menu != NULL) {
3156 if (!RefreshPortMenu(menu)) {
3157 return TgDestroyMenu(menu, TRUE);
3158 }
3159 menu->refresh_proc = ((RefreshMenuFunc*)RefreshPortMenu);
3160 }
3161 return menu;
3162 }
3163
RefreshSpecialMenu(menu)3164 void RefreshSpecialMenu(menu)
3165 TgMenu *menu;
3166 {
3167 }
3168
SpecialMenu(X,Y,TrackMenubar)3169 int SpecialMenu(X, Y, TrackMenubar)
3170 int X, Y, TrackMenubar;
3171 {
3172 int rc=INVALID;
3173 TgMenu *menu=(specialMenuInfo.create_proc)(NULL, X, Y, &specialMenuInfo,
3174 FALSE);
3175
3176 activeMenu = MENU_SPECIAL;
3177 if (menu != NULL) {
3178 menu->track_menubar = TrackMenubar;
3179
3180 rc = TgMenuLoop(menu);
3181 TgDestroyMenu(menu, TRUE);
3182 }
3183 return rc;
3184 }
3185
CleanUpSpecial()3186 void CleanUpSpecial()
3187 {
3188 }
3189
InitSpecial()3190 int InitSpecial()
3191 {
3192 char *c_ptr=NULL;
3193
3194 showWireSignalName = TRUE;
3195 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ShowWireSignalName")) !=
3196 NULL && UtilStrICmp(c_ptr, "false") == 0) {
3197 showWireSignalName = FALSE;
3198 }
3199 return TRUE;
3200 }
3201