1 /***************************************************************************
2 SCED - Schematic Capture Editor
3 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
4 Copyright 1990 Regents of the University of California. All rights reserved.
5 Authors: 1981 Giles C. Billingsley (parts of KIC layout editor)
6 1992 Stephen R. Whiteley
7 ****************************************************************************/
8
9 /*
10 * SCED copy and move selection operators.
11 */
12
13 #include "spice.h"
14 #include "sced.h"
15 #include "scedmacs.h"
16
17 #define MOVE 1
18 #define COPY 0
19
20 extern char *MenuCOPY;
21 extern char *MenuMOVE;
22 extern char *MenuUNDO;
23
24 #ifdef __STDC__
25 static void restore_color(void);
26 static void show_device(struct s*,struct ka*);
27 static void free_path(struct p*);
28 static void show_move(struct ka*,struct ka*);
29 static int copy_OK(long,long);
30 static void do_copy(long,long,long,long,struct ka*,int);
31 static char fix_xform(int);
32 static void do_copy_call(long,long,long,long,struct o*,struct o**);
33 #else
34 static void restore_color();
35 static void show_device();
36 static void free_path();
37 static void show_move();
38 static int copy_OK();
39 static void do_copy();
40 static char fix_xform();
41 static void do_copy_call();
42 #endif
43
44
45 void
Copy(LookedAhead)46 Copy(LookedAhead)
47
48 int *LookedAhead;
49 {
50 struct ka BB;
51 long RefX,RefY,CopX,CopY;
52 int i;
53 int Undo = False;
54 int FirstTime = True;
55 int GotOne = False;
56 int Modified = 0;
57
58 MenuSelect(MenuCOPY);
59
60 if (SelectQHead != NULL)
61 GotOne = True;
62 top:
63
64 if (Not GotOne) {
65 ShowPrompt("Point to object to copy.");
66 switch (PointLoop(LookedAhead)) {
67 case PL_ESC:
68 case PL_CMD:
69 case PL_UND:
70 goto quit;
71 case PL_PCW:
72 BB.kaLeft = BB.kaRight = SCursor.kcRawX;
73 BB.kaBottom = BB.kaTop = SCursor.kcRawY;
74 Selection(&BB);
75 if (SelectQHead == NULL)
76 goto top;
77 }
78 }
79
80 Next:
81 ShowPrompt("Point to the reference point.");
82
83 switch (PointLoop(LookedAhead)) {
84 case PL_ESC:
85 case PL_CMD:
86 goto quit;
87 case PL_UND:
88 if (Not GotOne) {
89 SQComputeBB();
90 SQDesel((char*)NULL);
91 EraseBox(&SelectQBB);
92 Redisplay(&SelectQBB);
93 goto top;
94 }
95 goto quit;
96 }
97
98 restore_color();
99 FBSetRubberBanding('m');
100 RefX = SCursor.kcX;
101 RefY = SCursor.kcY;
102 ShowPrompt("Point to locations where the selected items will be copied.");
103
104 loop {
105 switch (PointLoop(LookedAhead)) {
106 case PL_ESC:
107 case PL_CMD:
108 goto quit;
109 case PL_UND:
110 MenuSelect(MenuUNDO);
111 if (FirstTime) {
112 MenuDeselect(MenuUNDO);
113 FBSetRubberBanding(0);
114 goto Next;
115 }
116 if (Undo == False) {
117 SQRestore(True);
118 EraseBox(&BB);
119 Redisplay(&BB);
120 Modified--;
121 Undo = True;
122 }
123 else {
124 do_copy(RefX,RefY,CopX,CopY,&BB,COPY);
125 Redisplay(&BB);
126 Modified++;
127 Undo = False;
128 }
129 MenuDeselect(MenuUNDO);
130 continue;
131 case PL_PCW:
132 CopX = SCursor.kcX;
133 CopY = SCursor.kcY;
134 i = copy_OK(CopX-RefX,CopY-RefY);
135 if (i == -1) goto quit;
136 if (i == 0) continue;
137 SQRestore(False);
138 do_copy(RefX,RefY,CopX,CopY,&BB,COPY);
139 FirstTime = False;
140 Undo = False;
141 Modified++;
142 Redisplay(&BB);
143 continue;
144 }
145 }
146
147 quit:
148 FBSetRubberBanding(0);
149 SQRestore(False);
150 if (Not GotOne And AreTypesInQ((char*)NULL)) {
151 SQComputeBB();
152 SQDesel((char*)NULL);
153 EraseBox(&SelectQBB);
154 Redisplay(&SelectQBB);
155 }
156 if (Modified)
157 Parameters.kpModified = True;
158 ErasePrompt();
159 MenuDeselect(MenuUNDO);
160 MenuDeselect(MenuCOPY);
161 }
162
163
164 void
Move(LookedAhead)165 Move(LookedAhead)
166
167 int *LookedAhead;
168 {
169 struct ka OldBB,NewBB;
170 long LastRefX,LastRefY;
171 long RefX,RefY,MovX,MovY;
172 int FirstTime = True;
173 int GotOne = False;
174 int Modified = 0;
175 int Undo = False;
176
177 MenuSelect(MenuMOVE);
178
179 if (SelectQHead != NULL)
180 GotOne = True;
181
182 loop {
183 top:
184 if (Not GotOne) {
185 ShowPrompt("Point to object to move.");
186 switch (PointLoop(LookedAhead)) {
187 case PL_ESC:
188 case PL_CMD:
189 goto quit;
190 case PL_UND:
191 if (FirstTime) goto quit;
192 MenuSelect(MenuUNDO);
193 if (Undo == False) {
194 if (Parameters.kpShowTerminals)
195 DisplayTerminals(ERASE);
196 UndoReferenceTransform();
197 HYundoTransform();
198 SQRestore(True);
199 /* restored objects have Info = SQ_NEWSEL */
200 show_move(&NewBB,&OldBB);
201 if (Parameters.kpShowTerminals)
202 DisplayTerminals(DISPLAY);
203 Modified--;
204 Undo = True;
205 MenuDeselect(MenuUNDO);
206 break;
207 }
208 else {
209 if (Parameters.kpShowTerminals)
210 DisplayTerminals(ERASE);
211 /* should have only Info = SQ_NEW objects here */
212 do_copy(RefX,RefY,MovX,MovY,&NewBB,MOVE);
213 SQDesel((char*)NULL);
214 show_move(&OldBB,&NewBB);
215 if (Parameters.kpShowTerminals)
216 DisplayTerminals(DISPLAY);
217 Modified++;
218 Undo = False;
219 MenuDeselect(MenuUNDO);
220 continue;
221 }
222 case PL_PCW:
223 SelectTypes((char*)NULL);
224 if (Not AreTypesInQ((char*)NULL))
225 goto top;
226 }
227 }
228
229 next:
230 ShowPrompt("Point to the reference point.");
231 switch (PointLoop(LookedAhead)) {
232 case PL_ESC:
233 case PL_CMD:
234 goto quit;
235 case PL_UND:
236 MenuSelect(MenuUNDO);
237 if (Not GotOne) {
238 SQComputeBB();
239 SQDesel((char*)NULL);
240 /* newly selected objects deleted, restored objects
241 * have Info = SQ_NEW.
242 */
243 EraseBox(&SelectQBB);
244 Redisplay(&SelectQBB);
245 }
246 else {
247 if (FirstTime) {
248 MenuDeselect(MenuUNDO);
249 goto quit;
250 }
251 if (Undo == False) {
252 if (Parameters.kpShowTerminals)
253 DisplayTerminals(ERASE);
254 UndoReferenceTransform();
255 HYundoTransform();
256 SQRestore(True);
257 /* restored objects have Info = SQ_NEWSEL */
258 show_move(&OldBB,&NewBB);
259 if (Parameters.kpShowTerminals)
260 DisplayTerminals(DISPLAY);
261 Modified--;
262 Undo = True;
263 }
264 else {
265 if (Parameters.kpShowTerminals)
266 DisplayTerminals(ERASE);
267 /* should have only Info = SQ_NEWSEL objects here */
268 do_copy(RefX,RefY,MovX,MovY,&NewBB,MOVE);
269 show_move(&OldBB,&NewBB);
270 if (Parameters.kpShowTerminals)
271 DisplayTerminals(DISPLAY);
272 Modified++;
273 Undo = False;
274 }
275 }
276 MenuDeselect(MenuUNDO);
277 goto top;
278 }
279
280 restore_color();
281 FBSetRubberBanding('m');
282 LastRefX = RefX;
283 LastRefY = RefY;
284 RefX = SCursor.kcX;
285 RefY = SCursor.kcY;
286 ShowPrompt("Point to where the selected items will be moved.");
287
288 switch (PointLoop(LookedAhead)) {
289 case PL_ESC:
290 case PL_CMD:
291 goto quit;
292 case PL_UND:
293 MenuSelect(MenuUNDO);
294 RefX = LastRefX;
295 RefY = LastRefY;
296 MenuDeselect(MenuUNDO);
297 FBSetRubberBanding(0);
298 goto next;
299 }
300
301 FBSetRubberBanding(0);
302 SQComputeBB();
303 OldBB = SelectQBB;
304 MovX = SCursor.kcX;
305 MovY = SCursor.kcY;
306 SQRestore(False);
307 if (Parameters.kpShowTerminals) DisplayTerminals(ERASE);
308 do_copy(RefX,RefY,MovX,MovY,&NewBB,MOVE);
309 FirstTime = False;
310 Modified++;
311 Undo = False;
312 if (Not GotOne)
313 SQDesel((char*)NULL);
314 show_move(&OldBB,&NewBB);
315 if (Parameters.kpShowTerminals) DisplayTerminals(DISPLAY);
316 }
317 quit:
318 FBSetRubberBanding(0);
319 ClearReferenceUndoFlags();
320 HYclearUndoFlags();
321 SQRestore(False);
322 if (Not GotOne And AreTypesInQ((char*)NULL)) {
323 SQComputeBB();
324 SQDesel((char*)NULL);
325 EraseBox(&SelectQBB);
326 Redisplay(&SelectQBB);
327 }
328 if (Modified)
329 Parameters.kpModified = True;
330 ErasePrompt();
331 MenuDeselect(MenuUNDO);
332 MenuDeselect(MenuMOVE);
333 }
334
335
336 void
ShowGhost(NewX,NewY,RefX,RefY)337 ShowGhost(NewX,NewY,RefX,RefY)
338
339 /* Called from rubber banding routine. */
340 long NewX,NewY,RefX,RefY;
341 {
342 struct ks *SQDesc;
343 struct p *Path;
344 struct ka BB;
345 struct s *MasterDesc;
346 int Layer;
347 int NumX,NumY,Int1,Int2;
348 long Width;
349 long TFold[9], TFnew[9], TFtemp[9];
350 long DX,DY;
351 char *MasterName;
352
353
354 TCurrent(TFold);
355 TPush();
356 TIdentity();
357 SetNewTransform(RefX,RefY,NewX,NewY);
358 TCurrent(TFnew);
359 TPop();
360
361 for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
362 if (SQDesc->ksPointer->oInfo != SQ_OLDSEL &&
363 SQDesc->ksPointer->oInfo != SQ_NEWSEL) continue;
364 /* prevent drawing duplicate entries twice */
365 SQDesc->ksPointer->oInfo += 20;
366
367 switch (SQDesc->ksPointer->oType) {
368
369 case CDSYMBOLCALL:
370 CDCall(SQDesc->ksPointer,&MasterName,&NumX,&DX,&NumY,&DY);
371 if (IsCellInLib(MasterName)) {
372
373 if (OpenCell(MasterName,&MasterDesc)) break;
374
375 SetTransform(SQDesc->ksPointer);
376 SetNewTransform(RefX,RefY,NewX,NewY);
377 TPremultiply();
378
379 for (Int1 = NumY-1; Int1 >= 0; --Int1) {
380 for (Int2 = 0; Int2 < NumX; ++Int2 ){
381 TPush();
382 TIdentity();
383 TTranslate(Int2*DX,Int1*DY);
384 TPremultiply();
385 ShowTransformed(MasterDesc,View->kvCoarseWindow,
386 TFold);
387 TPop();
388 }
389 }
390 TPop();
391 break;
392 }
393
394 case CDLABEL:
395 if (SQDesc->ksPointer->oType == CDLABEL)
396 BBLabel(View->kvCoarseWindow,SQDesc->ksPointer,&BB);
397 else
398 CDStatusInt = CDBB(Parameters.kpCellDesc,
399 SQDesc->ksPointer,&BB.kaLeft,
400 &BB.kaBottom,&BB.kaRight,&BB.kaTop);
401 TLoadCurrent(TFnew);
402 TPoint(&BB.kaLeft,&BB.kaBottom);
403 TPoint(&BB.kaRight,&BB.kaTop);
404 TLoadCurrent(TFold);
405 ShowEmptyBox(HighlightingColor,&BB);
406 break;
407
408 case CDWIRE:
409 CDWire(SQDesc->ksPointer,&Layer,&Width,&Path);
410 TLoadCurrent(TFnew);
411 CopyPathWithXForm(&Path);
412 TLoadCurrent(TFold);
413 ShowWire(HighlightingColor,Width,Path);
414 free_path(Path);
415 break;
416
417 case CDPOLYGON:
418 CDPolygon(SQDesc->ksPointer,&Layer,&Path);
419 TLoadCurrent(TFnew);
420 CopyPathWithXForm(&Path);
421 TLoadCurrent(TFold);
422 ShowPath(HighlightingColor,Path,True);
423 free_path(Path);
424 break;
425 }
426 }
427 for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc)
428 if (SQDesc->ksPointer->oInfo > 20)
429 SQDesc->ksPointer->oInfo -= 20;
430 }
431
432
433 void
CopyPathWithXForm(Path)434 CopyPathWithXForm(Path)
435
436 struct p **Path;
437 {
438 struct p *OldPair,*NewPair;
439 /*
440 * Copy Path with transform and return pointer to new path
441 */
442 OldPair = *Path;
443 if ((NewPair = alloc(p)) == NULL)
444 MallocFailed();
445 *Path = NewPair;
446 NewPair->pX = OldPair->pX;
447 NewPair->pY = OldPair->pY;
448 TPoint(&NewPair->pX,&NewPair->pY);
449 NewPair->pSucc = NULL;
450 OldPair = OldPair->pSucc;
451 while(OldPair != NULL) {
452 if ((NewPair->pSucc = alloc(p)) == NULL)
453 MallocFailed();
454 NewPair = NewPair->pSucc;
455 NewPair->pX = OldPair->pX;
456 NewPair->pY = OldPair->pY;
457 NewPair->pSucc = NULL;
458 TPoint(&NewPair->pX,&NewPair->pY);
459 OldPair = OldPair->pSucc;
460 }
461 }
462
463
464 static void
restore_color()465 restore_color()
466
467 /* repaint with drawing color */
468 {
469 struct ks *SQDesc;
470 struct p *Path;
471 struct ka BB;
472 struct s *MasterDesc;
473 int Layer;
474 int NumX,NumY,Int1,Int2;
475 long Width;
476 long DX,DY;
477 char *MasterName;
478
479 for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
480 if (SQDesc->ksPointer->oInfo != SQ_OLDSEL &&
481 SQDesc->ksPointer->oInfo != SQ_NEWSEL) continue;
482
483 switch (SQDesc->ksPointer->oType) {
484
485 case CDSYMBOLCALL:
486 CDCall(SQDesc->ksPointer,&MasterName,&NumX,&DX,&NumY,&DY);
487 if (IsCellInLib(MasterName)) {
488
489 if (OpenCell(MasterName,&MasterDesc)) break;
490
491 SetTransform(SQDesc->ksPointer);
492 TPremultiply();
493
494 for (Int1 = NumY-1; Int1 >= 0; --Int1) {
495 for (Int2 = 0; Int2 < NumX; ++Int2 ){
496 TPush();
497 TIdentity();
498 TTranslate(Int2*DX,Int1*DY);
499 TPremultiply();
500 show_device(MasterDesc,View->kvCoarseWindow);
501 TPop();
502 }
503 }
504 TPop();
505 break;
506 }
507
508 case CDLABEL:
509 if (SQDesc->ksPointer->oType == CDLABEL)
510 BBLabel(View->kvCoarseWindow,SQDesc->ksPointer,&BB);
511 else
512 CDStatusInt = CDBB(Parameters.kpCellDesc,
513 SQDesc->ksPointer,&BB.kaLeft,
514 &BB.kaBottom,&BB.kaRight,&BB.kaTop);
515 ShowEmptyBox(DrawingColor,&BB);
516 break;
517
518 case CDWIRE:
519 CDWire(SQDesc->ksPointer,&Layer,&Width,&Path);
520 ShowWire(DrawingColor,Width,Path);
521 break;
522
523 case CDPOLYGON:
524 CDPolygon(SQDesc->ksPointer,&Layer,&Path);
525 ShowPath(DrawingColor,Path,True);
526 break;
527 }
528 }
529 }
530
531
532 static void
show_device(CellDesc,AOI)533 show_device(CellDesc,AOI)
534
535 struct s *CellDesc;
536 struct ka *AOI;
537 {
538 struct g *GenDesc;
539 struct o *Pointer;
540 struct p *Path;
541 int Layer;
542 long Width;
543
544 if (Not CDInitGen(CellDesc,1,AOI->kaLeft,AOI->kaBottom,
545 AOI->kaRight,AOI->kaTop,&GenDesc)) MallocFailed();
546
547 loop {
548 CDGen(CellDesc,GenDesc,&Pointer);
549 if (Pointer == NULL) break;
550 if (Pointer->oInfo == SQ_GONE) continue;
551
552 switch (Pointer->oType) {
553
554 case CDLABEL:
555 /*
556 BBLabel(View->kvCoarseWindow,Pointer,&BB);
557 ShowEmptyBox(BackgroundColor,&BB);
558 */
559 break;
560
561 case CDWIRE:
562 CDWire(Pointer,&Layer,&Width,&Path);
563 ShowWire(DrawingColor,Width,Path);
564 break;
565
566 case CDPOLYGON:
567 CDPolygon(Pointer,&Layer,&Path);
568 ShowPath(DrawingColor,Path,True);
569 break;
570 }
571 }
572 }
573
574
575 void
ShowTransformed(CellDesc,AOI,TFold)576 ShowTransformed(CellDesc,AOI,TFold)
577
578 struct s *CellDesc;
579 struct ka *AOI;
580 long *TFold;
581 {
582 struct g *GenDesc;
583 struct o *Pointer;
584 struct p *Path;
585 struct ka BB;
586 int Layer;
587 long Width;
588 long TFtmp[9];
589
590 if (Not CDInitGen(CellDesc,1,AOI->kaLeft,AOI->kaBottom,
591 AOI->kaRight,AOI->kaTop,&GenDesc)) MallocFailed();
592
593 TCurrent(TFtmp);
594 loop {
595 CDGen(CellDesc,GenDesc,&Pointer);
596 if (Pointer == NULL) break;
597 if (Pointer->oInfo == SQ_GONE) continue;
598
599 switch (Pointer->oType) {
600
601 case CDLABEL:
602 BBLabel(View->kvCoarseWindow,Pointer,&BB);
603 TPoint(&BB.kaLeft,&BB.kaBottom);
604 TPoint(&BB.kaRight,&BB.kaTop);
605 TLoadCurrent(TFold);
606 ShowEmptyBox(HighlightingColor,&BB);
607 TLoadCurrent(TFtmp);
608 break;
609
610 case CDWIRE:
611 CDWire(Pointer,&Layer,&Width,&Path);
612 CopyPathWithXForm(&Path);
613 TLoadCurrent(TFold);
614 ShowWire(HighlightingColor,Width,Path);
615 TLoadCurrent(TFtmp);
616 free_path(Path);
617 break;
618
619 case CDPOLYGON:
620 CDPolygon(Pointer,&Layer,&Path);
621 CopyPathWithXForm(&Path);
622 TLoadCurrent(TFold);
623 ShowPath(HighlightingColor,Path,True);
624 TLoadCurrent(TFtmp);
625 free_path(Path);
626 break;
627 }
628 }
629 }
630
631
632 static void
free_path(Path)633 free_path(Path)
634
635 struct p *Path;
636 {
637 struct p *Next;
638
639 for (; Path; Path = Next) {
640 Next = Path->pSucc;
641 free(Path);
642 }
643 }
644
645
646 static void
show_move(OBB,NBB)647 show_move(OBB,NBB)
648
649 struct ka *OBB,*NBB;
650 {
651 long L1,R1,B1,T1,L2,R2,B2,T2;
652 struct ka BB;
653
654 L1 = NBB->kaLeft;
655 R1 = NBB->kaRight;
656 B1 = NBB->kaBottom;
657 T1 = NBB->kaTop;
658 L2 = OBB->kaLeft;
659 R2 = OBB->kaRight;
660 B2 = OBB->kaBottom;
661 T2 = OBB->kaTop;
662 if (L1 > R1) SwapInts(L1,R1);
663 if (B1 > T1) SwapInts(B1,T1);
664 if (L2 > R2) SwapInts(L2,R2);
665 if (B2 > T2) SwapInts(B2,T2);
666 if (L1 > R2 Or L2 > R1 Or B1 > T2 Or B2 > T1) {
667 /*
668 * Old BB is not within the new BB
669 * So, redisplay twice.
670 */
671 EraseBox(OBB);
672 Redisplay(OBB);
673 EraseBox(NBB);
674 Redisplay(NBB);
675 return;
676 }
677 /*
678 * Old BB intersects new BB
679 */
680 BB.kaLeft = Min(L1,L2);
681 BB.kaRight = Max(R1,R2);
682 BB.kaBottom = Min(B1,B2);
683 BB.kaTop = Max(T1,T2);
684 EraseBox(&BB);
685 Redisplay(&BB);
686 }
687
688
689 static int
copy_OK(X,Y)690 copy_OK(X,Y)
691
692 long X,Y;
693 {
694 char *TypeIn;
695
696 if (Not Parameters.kpMX And Not Parameters.kpMY And
697 Parameters.kpRotationAngle == 0 And
698 X == 0 And Y == 0 ) {
699
700 ShowPrompt(
701 "This will copy objects directly over themselves. Continue(N)?");
702 TypeIn = FBEdit(NULL);
703 if (TypeIn == NULL) return (-1);
704 if ((TypeIn[0] != 'Y' And TypeIn[0] != 'y'))
705 return (0);
706 }
707 return (1);
708 }
709
710
711 static void
do_copy(RefX,RefY,NewX,NewY,NewBB,MoveOrCopy)712 do_copy(RefX,RefY,NewX,NewY,NewBB,MoveOrCopy)
713
714 long RefX,RefY,NewX,NewY;
715 struct ka *NewBB;
716 int MoveOrCopy;
717 {
718 struct ks *SQDesc;
719 struct p *Path;
720 struct ka BB;
721 struct o *Pointer;
722 struct prpty *PDesc;
723 long X,Y,Length,Width;
724 int Layer;
725 char *Label;
726 char Xform;
727
728 BB.kaLeft = BB.kaRight = NewX;
729 BB.kaTop = BB.kaBottom = NewY;
730 NewBB->kaLeft = NewBB->kaRight = NewX;
731 NewBB->kaTop = NewBB->kaBottom = NewY;
732
733 if (MoveOrCopy == COPY) {
734 /* identify mutual inductors */
735 PDesc = Parameters.kpCellDesc->sPrptyList;
736 for (; PDesc; PDesc = PDesc->prpty_Succ) {
737 if (PDesc->prpty_Value != P_MUT) continue;
738 if (MutSelected(PDesc)) {
739 CDCopyProperty(Parameters.kpCellDesc,(struct o*)NULL,
740 PDesc);
741 Parameters.kpCellDesc->sPrptyList->prpty_Info = "new";
742 }
743 }
744 }
745
746 TPush();
747 TIdentity();
748 SetNewTransform(RefX,RefY,NewX,NewY);
749
750 if (MoveOrCopy == COPY) {
751 /* transform mutual inductors */
752 PDesc = Parameters.kpCellDesc->sPrptyList;
753 for (; PDesc; PDesc = PDesc->prpty_Succ) {
754 if (PDesc->prpty_Value != P_MUT) break;
755 if (PDesc->prpty_Info && !strcmp(PDesc->prpty_Info,"new")) {
756 TPoint((long*)&PDesc->prpty_Data->p_mut.x1,
757 (long*)&PDesc->prpty_Data->p_mut.y1);
758 TPoint((long*)&PDesc->prpty_Data->p_mut.x2,
759 (long*)&PDesc->prpty_Data->p_mut.y2);
760 continue;
761 }
762 break;
763 }
764 }
765
766 for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
767 if (SQDesc->ksPointer->oInfo == SQ_GONE) continue;
768
769 switch (SQDesc->ksPointer->oType) {
770 case CDLABEL:
771
772 CDLabel(SQDesc->ksPointer,&Layer,&Label,&X,&Y,&Xform);
773 TPoint(&X,&Y);
774
775 if (Not CDMakeLabel(Parameters.kpCellDesc,Layer,Label,
776 X,Y,fix_xform(Xform),&Pointer)) MallocFailed();
777 break;
778
779 case CDWIRE:
780 CDWire(SQDesc->ksPointer,&Layer,&Width,&Path);
781 CopyPathWithXForm(&Path);
782 if (Not CDMakeWire(Parameters.kpCellDesc,Layer,Width,Path,
783 &Pointer)) MallocFailed();
784 AssignWireProperties(Pointer);
785 break;
786
787 case CDPOLYGON:
788 CDPolygon(SQDesc->ksPointer,&Layer,&Path);
789 CopyPathWithXForm(&Path);
790 if (Not CDMakePolygon(Parameters.kpCellDesc,Layer,Path,
791 &Pointer)) MallocFailed();
792 break;
793
794 case CDSYMBOLCALL:
795 do_copy_call(RefX,RefY,NewX,NewY,SQDesc->ksPointer,&Pointer);
796 break;
797
798 default:
799 continue;
800 }
801
802 if (SQDesc->ksPointer->oType == CDLABEL)
803 BBLabel(View->kvCoarseWindow,Pointer,&BB);
804 else
805 CDStatusInt = CDBB(Parameters.kpCellDesc,Pointer,&BB.kaLeft,
806 &BB.kaBottom,&BB.kaRight,&BB.kaTop);
807 if (MoveOrCopy == MOVE)
808 Pointer->oInfo = SQ_NEWSEL;
809 else
810 Pointer->oInfo = SQ_NEW;
811 SQInsert(Pointer);
812
813 if (BB.kaLeft < NewBB->kaLeft) NewBB->kaLeft = BB.kaLeft;
814 if (BB.kaRight > NewBB->kaRight) NewBB->kaRight = BB.kaRight;
815 if (BB.kaBottom < NewBB->kaBottom) NewBB->kaBottom = BB.kaBottom;
816 if (BB.kaTop > NewBB->kaTop) NewBB->kaTop = BB.kaTop;
817
818 if (MoveOrCopy == MOVE) {
819 TransformReferences(SQDesc->ksPointer);
820 HYtransform(SQDesc->ksPointer,Pointer);
821 SQDesc->ksPointer->oInfo = SQ_GONE;
822 }
823 }
824 TPop();
825 }
826
827
828 static char
fix_xform(Xform)829 fix_xform(Xform)
830
831 char Xform;
832 {
833 long TF[9];
834
835 TPush();
836 TIdentity();
837 if (Parameters.kpMX) TMX();
838 if (Parameters.kpMY) TMY();
839 if (Parameters.kpRotationAngle != 0) {
840 if (Parameters.kpRotationAngle == 180) TRotate(-1L,0L);
841 elif (Parameters.kpRotationAngle == 90) TRotate(0L,1L);
842 elif (Parameters.kpRotationAngle == 270) TRotate(0L,-1L);
843 }
844 if (Xform & 4) TMY();
845 if (Xform & 8) TMX();
846 Xform &= 3;
847 if (Xform != 0) {
848 if (Xform == 1) TRotate(0L,1L);
849 elif (Xform == 2) TRotate(-1L,0L);
850 elif (Xform == 3) TRotate(0L,-1L);
851 }
852 TCurrent(TF);
853 Xform = SetXform(TF);
854 TPop();
855 return (Xform);
856 }
857
858
859 static void
do_copy_call(RefX,RefY,NewX,NewY,OPointer,NPointer)860 do_copy_call(RefX,RefY,NewX,NewY,OPointer,NPointer)
861
862 long RefX,RefY,NewX,NewY;
863 struct o *OPointer;
864 struct o **NPointer;
865 {
866 char *SymbolName;
867 int NumX,NumY;
868 long DX,DY;
869 long TF[9];
870 struct o *Pointer;
871 struct prpty *PDesc;
872
873 CDCall(OPointer,&SymbolName,&NumX,&DX,&NumY,&DY);
874 /* only possible error is CDMALLOCFAILED */
875 if (Not CDBeginMakeCall(Parameters.kpCellDesc,SymbolName,
876 NumX,DX,NumY,DY,&Pointer))
877 MallocFailed();
878
879 SetTransform(OPointer);
880 SetNewTransform(RefX,RefY,NewX,NewY);
881 TCurrent(TF);
882 AddResultingTransform(Pointer,TF);
883 if (Not CDEndMakeCall(Parameters.kpCellDesc,Pointer))
884 MallocFailed();
885
886 /* remove any default user properties */
887 CDRemoveProperty(Parameters.kpCellDesc,Pointer,P_VALUE);
888 CDRemoveProperty(Parameters.kpCellDesc,Pointer,P_MODEL);
889 CDRemoveProperty(Parameters.kpCellDesc,Pointer,P_INITC);
890 CDRemoveProperty(Parameters.kpCellDesc,Pointer,P_OTHER);
891
892 /* add the user properties */
893 for (PDesc = OPointer->oPrptyList; PDesc; PDesc = PDesc->prpty_Succ) {
894 if (PDesc->prpty_Value == P_VALUE ||
895 PDesc->prpty_Value == P_MODEL ||
896 PDesc->prpty_Value == P_INITC ||
897 PDesc->prpty_Value == P_OTHER) {
898 CDCopyProperty(Parameters.kpCellDesc,Pointer,PDesc);
899 }
900 }
901
902 *NPointer = Pointer;
903 TPop();
904 }
905
906
907 void
SetNewTransform(RefX,RefY,NewX,NewY)908 SetNewTransform(RefX,RefY,NewX,NewY)
909
910 long RefX,RefY,NewX,NewY;
911 {
912 TTranslate(-RefX,-RefY);
913 if (Parameters.kpMX) TMX();
914 if (Parameters.kpMY) TMY();
915 if (Parameters.kpRotationAngle != 0) {
916 if (Parameters.kpRotationAngle == 90) TRotate(0L,1L);
917 elif (Parameters.kpRotationAngle == 180) TRotate(-1L,0L);
918 elif (Parameters.kpRotationAngle == 270) TRotate(0L,-1L);
919 }
920 TTranslate(NewX,NewY);
921 }
922
923
924 void
AddResultingTransform(Pointer,TF)925 AddResultingTransform(Pointer,TF)
926
927 struct o *Pointer;
928 long *TF;
929 {
930 long A,B,C,D,TX,TY;
931 int ret;
932 /*
933 * Take the transformation defined in TF and add
934 * it to the symbol call currently being created.
935 *
936 * | a c 0 |
937 * Transform = TM = | b d 0 |
938 * | TX TY 1 |
939 *
940 * A = TM[0][0] = TF[0];
941 * B = TM[1][0] = TF[3];
942 * C = TM[0][1] = TF[1];
943 * D = TM[1][1] = TF[4];
944 * TX = TM[2][0] = TF[6];
945 * TY = TM[2][1] = TF[7];
946 */
947 A = TF[0]; B = TF[3]; C = TF[1]; D = TF[4];
948 TX = TF[6]; TY = TF[7];
949 if (A == 0 And B == 1 And C == 1 And D == 0) {
950 /* MX R 0 -1 T tx,ty */
951 ret = CDT(Pointer,CDMIRRORX,0L,0L);
952 ret &= CDT(Pointer,CDROTATE,0L,-1L);
953 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
954 }
955 elif (A == 0 And B == -1 And C == -1 And D == 0) {
956 /* MX R 0 1 T tx,ty */
957 ret = CDT(Pointer,CDMIRRORX,0L,0L);
958 ret &= CDT(Pointer,CDROTATE,0L,1L);
959 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
960 }
961 elif (A == 0 And B == 1 And C == -1 And D == 0) {
962 /* R 0 -1 T tx,ty */
963 ret = CDT(Pointer,CDROTATE,0L,-1L);
964 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
965 }
966 elif (A == 0 And B == -1 And C == 1 And D == 0) {
967 /* R 0 1 T tx,ty */
968 ret = CDT(Pointer,CDROTATE,0L,1L);
969 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
970 }
971 elif (A == 1 And B == 0 And C == 0 And D == 1) {
972 /* T tx,ty */
973 ret = CDT(Pointer,CDTRANSLATE,TX,TY);
974 }
975 elif (A == -1 And B == 0 And C == 0 And D == -1) {
976 /* R -1 0 T tx,ty */
977 ret = CDT(Pointer,CDROTATE,-1L,0L);
978 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
979 }
980 elif (A == -1 And B == 0 And C == 0 And D == 1) {
981 /* MX T tx,ty */
982 ret = CDT(Pointer,CDMIRRORX,0L,0L);
983 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
984 }
985 else{
986 /* MY T tx,ty */
987 ret = CDT(Pointer,CDMIRRORY,0L,0L);
988 ret &= CDT(Pointer,CDTRANSLATE,TX,TY);
989 }
990 if (Not ret)
991 MallocFailed();
992 }
993
994