Jspice3
choose.c
Go to the documentation of this file.
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  * The SCED selection code.
11  *
12  *
13  * The Selection code extensively uses the CD Info field. The following
14  * convention is used:
15  *
16  * Info = SQ_OLD (0) Object is unselected.
17  * *Info = SQ_OLDSEL (1) Object is selected and in SelectionQ.
18  * Info = SQ_GONE (2) Object is conditionally deleted and in SelectionQ.
19  * Info = SQ_NEW (3) Object is conditionally created and in SelectionQ.
20  * *Info = SQ_NEWSEL (4) Object is conditionally created and in SelectionQ.
21  * Info = SQ_INCMPLT (5) Object is being created.
22  *
23  * Info = 6-11 Reserved.
24  * *Info = 11-255 Object has conditionally new layer and is in
25  * SelectionQ. OldLayer = Info - 10.
26  *
27  * * means that SQShow will highlight these objects.
28  *
29  */
30 
31 #include "spice.h"
32 #include "sced.h"
33 #include <string.h>
34 
35 
36 
37 /***********************************************************************
38  *
39  * Current transform code.
40  *
41  ***********************************************************************/
42 
43 extern char *MenuMX;
44 extern char *MenuMY;
45 extern char *Menu0;
46 extern char *Menu90;
47 extern char *Menu180;
48 extern char *Menu270;
49 
50 
51 void
52 MX()
53 
54 {
55  if (Parameters.kpMX) {
58  }
59  else {
62  }
63 }
64 
65 
66 void
67 MY()
68 
69 {
70  if (Parameters.kpMY) {
73  }
74  else {
77  }
78 }
79 
80 
81 void
83 
84 {
88 }
89 
90 
91 void
93 
94 {
98 }
99 
100 
101 void
103 
104 {
108 }
109 
110 
111 void
113 
114 {
118 }
119 
120 
121 
122 /***********************************************************************
123  *
124  * Selection operator code.
125  *
126  ***********************************************************************/
127 
128 extern char *MenuAREA;
129 extern char *MenuDESEL;
130 extern char *MenuSELEC;
131 extern char *MenuUNDO;
132 
133 #ifdef __STDC__
134 static struct ks *select_items(struct ka*,int);
135 static void sl_free(struct ks*);
136 static void sl_bb(struct ks*,struct ka*);
137 static void get_BB(struct o*,struct ka*);
138 static int is_BB_visible(struct o*);
139 static void redisplay_edges(struct ka*);
140 static struct ks *which_cell(struct ks*);
141 static void sq_set_NEW(struct o*);
142 static void sq_delete_dups(void);
143 static void sq_display_selected(struct o*);
144 static int overlap_path(struct p*,struct ka*);
145 static int overlap_line(struct ka*,struct ka*);
146 static int cross_line(struct ka*,struct ka*);
147 static int point_in_poly(int,struct p*,long,long);
148 #else
149 static struct ks *select_items();
150 static void sl_free();
151 static void sl_bb();
152 static void get_BB();
153 static int is_BB_visible();
154 static void redisplay_edges();
155 static struct ks *which_cell();
156 static void sq_set_NEW();
157 static void sq_delete_dups();
158 static void sq_display_selected();
159 static int overlap_path();
160 static int overlap_line();
161 static int cross_line();
162 static int point_in_poly();
163 #endif
164 
165 #define UpdateBB(BB2,BB1) \
166  if (BB1.kaLeft < BB2.kaLeft) BB2.kaLeft = BB1.kaLeft; \
167  if (BB1.kaBottom < BB2.kaBottom) BB2.kaBottom = BB1.kaBottom; \
168  if (BB1.kaRight > BB2.kaRight) BB2.kaRight = BB1.kaRight; \
169  if (BB1.kaTop > BB2.kaTop) BB2.kaTop = BB1.kaTop;
170 
171 
172 
173 void
174 Sel(LookedAhead)
175 
176 int *LookedAhead;
177 {
178  struct ka AOI;
179  int FirstTime = True;
180 
182  ShowPrompt("Point to select.");
183  loop {
184  switch (PointLoop(LookedAhead)) {
185  case PL_CMD:
186  case PL_ESC:
187  goto quit;
188  case PL_UND:
189  if (FirstTime == True) goto quit;
191  Selection(&AOI);
193  continue;
194  case PL_PCW:
195  AOI.kaLeft = AOI.kaRight = SCursor.kcRawX;
196  AOI.kaBottom = AOI.kaTop = SCursor.kcRawY;
197  ErasePrompt();
198  Selection(&AOI);
199  FirstTime = False;
200  }
201  }
202 quit:
204  ErasePrompt();
205 }
206 
207 
208 void
209 Area(LookedAhead)
210 
211 int *LookedAhead;
212 {
213  struct ka AOI;
214  long OldRawX,OldRawY;
215  int FirstTime = True;
216 
218 top:
219  loop {
220  ShowPrompt("Point to endpoints of diagonal.");
221  switch (PointLoop(LookedAhead)) {
222  case PL_ESC:
223  case PL_CMD:
224  goto quit;
225  case PL_UND:
226  if (FirstTime == True) goto quit;
228  Selection(&AOI);
230  goto top;
231  case PL_PCW:
232  FBSetRubberBanding('R');
233  OldRawX = SCursor.kcRawX;
234  OldRawY = SCursor.kcRawY;
235  }
236  ShowPrompt("Point to second endpoint.");
237  switch (PointLoop(LookedAhead)) {
238  case PL_ESC:
239  case PL_CMD:
240  goto quit;
241  case PL_UND:
243  goto top;
244  case PL_PCW:
246  break;
247  }
248  AOI.kaLeft = Min(OldRawX,SCursor.kcRawX);
249  AOI.kaBottom = Min(OldRawY,SCursor.kcRawY);
250  AOI.kaRight = Max(OldRawX,SCursor.kcRawX);
251  AOI.kaTop = Max(OldRawY,SCursor.kcRawY);
252  Selection(&AOI);
253  FirstTime = False;
254  }
255 
256 quit:
259  ErasePrompt();
260 }
261 
262 
263 void
265 
266 {
268  SQComputeBB();
269  if (SelectQHead != NULL) {
270  SQClear();
271  /* Take care of Instance markers */
272  OversizeBox(&SelectQBB,200);
275  }
277 }
278 
279 
280 void
282 
283 /* Select items and link into SelectionQ, compute BB. */
284 struct ka *AOI;
285 {
286  struct ks *SList, *S;
287  struct ka BB,OldSelectQBB;
288 
289  if (AOI->kaLeft == AOI->kaRight) {
290  /* Point selection. */
291 
292  SList = select_items(AOI,True);
293  if (SList == NULL) return;
294  if (SList->ksPointer->oType == CDSYMBOLCALL) {
295  /* no geometry found, get one symbol */
296  S = which_cell(SList);
297  if (S) {
298  if (S->ksPointer->oInfo == SQ_OLDSEL) {
299  /* already selected, deselect and break */
300  S->ksPointer->oInfo = SQ_OLD;
301  SQDelete(S->ksPointer);
302  get_BB(S->ksPointer,&BB);
303  redisplay_edges(&BB);
304  }
305  else {
306  /* add to select Q */
307  S->ksPointer->oInfo = SQ_OLDSEL;
308  SQInsert(S->ksPointer);
310  }
311  }
312  SQComputeBB();
313  sl_free(SList);
314  return;
315  }
316  for (S = SList; S != NULL; S = S->ksSucc) {
317  /* keep only geometry */
318  if (S->ksPointer->oType == CDSYMBOLCALL) break;
319 
320  if (S->ksPointer->oInfo == SQ_OLDSEL) {
321  /* already selected, deselect and break */
322  S->ksPointer->oInfo = SQ_OLD;
323  SQDelete(S->ksPointer);
324  get_BB(S->ksPointer,&BB);
325  EraseBox(&BB);
326  Redisplay(&BB);
327  DevUpdate();
328  break;
329  }
330  else {
331  /* add to select Q */
332  S->ksPointer->oInfo = SQ_OLDSEL;
333  SQInsert(S->ksPointer);
335  }
336  }
337  SQComputeBB();
338  }
339  else {
340 
341  /* Area select. */
342  SList = select_items(AOI,False);
343  if (SList == NULL) return;
344  SQComputeBB();
345  OldSelectQBB = SelectQBB;
346 
347  for (S = SList; S != NULL; S = S->ksSucc) {
348  if (S->ksPointer->oType == CDSYMBOLCALL &&
349  !is_BB_visible(S->ksPointer)) continue;
350 
351  if (S->ksPointer->oInfo == SQ_OLDSEL) {
352  /* already selected, deselect */
353  S->ksPointer->oInfo = SQ_OLD;
354  SQDelete(S->ksPointer);
355  }
356  else {
357  /* add to select Q */
358  S->ksPointer->oInfo = SQ_OLDSEL;
359  SQInsert(S->ksPointer);
360  }
361  }
362  SQComputeBB();
363  UpdateBB(SelectQBB,OldSelectQBB);
364  if (SelectQBB.kaLeft == CDINFINITY) return;
367  DevUpdate();
368  }
369  sl_free(SList);
370 }
371 
372 
373 static struct ks *
374 select_items(AOI,PointSelect)
375 
376 /* Return a list of visible objects in the neighborhood of AOI as returned
377  * from the generator. Only types in Parameters.kpSelectTypes are listed,
378  * all are listed if this is NULL. The flag PointSelect is set for
379  * a point selection.
380  */
381 struct ka *AOI;
382 int PointSelect;
383 {
384  struct g *GenDesc;
385  struct o *Pointer;
386  struct ka BB;
387  struct ks *SPointer = NULL, *S;
388  struct p *Path;
389  long Width;
390  int Delta,Layer;
391 
392  if (PointSelect) {
393  /* expand the point to finite size */
394  if (SCursor.kcInFine == True)
395  Delta = 3.0/View->kvFineRatio;
396  else
397  Delta = 3.0/View->kvCoarseRatio;
398  OversizeBox(AOI,Delta);
399  }
400 
401  if (Not CDInitGen(Parameters.kpCellDesc,1,AOI->kaLeft,AOI->kaBottom,
402  AOI->kaRight,AOI->kaTop,&GenDesc)) MallocFailed();
403  loop {
404  CDGen(Parameters.kpCellDesc,GenDesc,&Pointer);
405  if (Pointer == NULL) break;
406  if (Pointer->oInfo == SQ_GONE) continue;
408  !strchr(Parameters.kpSelectTypes,Pointer->oType)) continue;
409 
410  switch (Pointer->oType) {
411  case CDWIRE:
412  CDWire(Pointer,&Layer,&Width,&Path);
413  if (PointSelect) {
414  if (InPath(Delta+(int)Width/2,Path,
415  AOI->kaLeft+Delta,AOI->kaBottom+Delta) != NULL)
416  break;
417  }
418  else {
419  if (overlap_path(Path,AOI)) break;
420  if (InBox(Path->pX,Path->pY,AOI)) break;
421  }
422  continue;
423 
424  case CDPOLYGON:
425  CDPolygon(Pointer,&Layer,&Path);
426  if (PointSelect) {
427  if (point_in_poly(Delta,Path,
428  AOI->kaLeft+Delta,AOI->kaBottom+Delta))
429  break;
430  }
431  else {
432  if (point_in_poly(0,Path,AOI->kaLeft,AOI->kaBottom))
433  break;
434  if (overlap_path(Path,AOI)) break;
435  if (InBox(Path->pX,Path->pY,AOI)) break;
436  }
437  continue;
438 
439  case CDLABEL:
440  case CDBOX:
441  break;
442 
443  default:
444  continue;
445  }
446  if (SPointer == NULL)
447  S = SPointer = alloc(ks);
448  else {
449  S->ksSucc = alloc(ks);
450  S = S->ksSucc;
451  }
452  if (S == NULL) MallocFailed();
453  S->ksPointer = Pointer;
454  S->ksSucc = NULL;
455  }
456 
457 
458  /* Now for the instances... */
459 
462  if (PointSelect) OversizeBox(AOI,-Delta);
463  return (SPointer);
464  }
465 
466  if (Not CDInitGen(Parameters.kpCellDesc,0,AOI->kaLeft,AOI->kaBottom,
467  AOI->kaRight,AOI->kaTop,&GenDesc)) MallocFailed();
468  loop {
469  CDGen(Parameters.kpCellDesc,GenDesc,&Pointer);
470  if (Pointer == NULL) break;
471 
472  if (Pointer->oInfo == SQ_GONE) continue;
473  if (SPointer == NULL)
474  S = SPointer = alloc(ks);
475  else {
476  S->ksSucc = alloc(ks);
477  S = S->ksSucc;
478  }
479  if (S == NULL) MallocFailed();
480  S->ksPointer = Pointer;
481  S->ksSucc = NULL;
482  }
483  if (PointSelect) OversizeBox(AOI,-Delta);
484  return (SPointer);
485 }
486 
487 
488 static void
489 sl_free(SList)
490 
491 /* Free a list as returned from select_items(). */
492 struct ks *SList;
493 {
494  struct ks *SQDesc,*SQNext;
495 
496  for (SQDesc = SList; SQDesc; SQDesc = SQNext) {
497  SQNext = SQDesc->ksSucc;
498  tfree(SQDesc);
499  }
500 }
501 
502 
503 static void
504 sl_bb(SList,BB)
505 
506 /* Compute the BB of the objects in SList. */
507 struct ks *SList;
508 struct ka *BB;
509 {
510  struct ks *S;
511  struct ka NBB,OBB;
512 
513  NBB.kaLeft = CDINFINITY;
514  NBB.kaBottom = CDINFINITY;
515  NBB.kaRight = -CDINFINITY;
516  NBB.kaTop = -CDINFINITY;
517 
518  for (S = SList; S != NULL; S = S->ksSucc) {
519  get_BB(S->ksPointer,&OBB);
520  UpdateBB(NBB,OBB);
521  }
522  *BB = NBB;
523 }
524 
525 
526 static void
528 
529 struct o *Pointer;
530 struct ka *BB;
531 {
532  if (Pointer->oType == CDLABEL)
533  BBLabel(View->kvCoarseWindow,Pointer,BB);
534  else
536  &BB->kaBottom,&BB->kaRight,&BB->kaTop);
537 }
538 
539 
540 static int
542 
543 struct o *Pointer;
544 {
545  struct ka BB;
546 
547  /* will edges show in coarse window? */
549  &BB.kaLeft,&BB.kaBottom,&BB.kaRight,&BB.kaTop);
550  if (BB.kaLeft <= View->kvCoarseWindow->kaLeft &&
553  BB.kaTop >= View->kvCoarseWindow->kaTop)
554  return (False);
555  return (True);
556 }
557 
558 
559 static void
561 
562 /* redisplay the edges of BB */
563 struct ka *BB;
564 {
565  struct ka EdgeOfBB;
566 
567  /* Left edge. */
568  EdgeOfBB.kaLeft = BB->kaLeft-300;
569  EdgeOfBB.kaRight = BB->kaLeft+300;
570  EdgeOfBB.kaTop = BB->kaTop+300;
571  EdgeOfBB.kaBottom = BB->kaBottom-300;
572  EraseBox(&EdgeOfBB);
573  Redisplay(&EdgeOfBB);
574 
575  /* Right edge. */
576  EdgeOfBB.kaRight = BB->kaRight+300;
577  EdgeOfBB.kaLeft = BB->kaRight-300;
578  EdgeOfBB.kaTop = BB->kaTop+300;
579  EdgeOfBB.kaBottom = BB->kaBottom-300;
580  EraseBox(&EdgeOfBB);
581  Redisplay(&EdgeOfBB);
582 
583  /* Bottom edge. */
584  EdgeOfBB.kaBottom = BB->kaBottom-300;
585  EdgeOfBB.kaTop = BB->kaBottom+300;
586  EdgeOfBB.kaRight = BB->kaRight;
587  EdgeOfBB.kaLeft = BB->kaLeft;
588  EraseBox(&EdgeOfBB);
589  Redisplay(&EdgeOfBB);
590 
591  /* Top edge. */
592  EdgeOfBB.kaBottom = BB->kaTop-300;
593  EdgeOfBB.kaTop = BB->kaTop+300;
594  EdgeOfBB.kaRight = BB->kaRight;
595  EdgeOfBB.kaLeft = BB->kaLeft;
596  EraseBox(&EdgeOfBB);
597  Redisplay(&EdgeOfBB);
598 
599  DevUpdate();
600 }
601 
602 
603 static struct ks *
605 
606 /* Resolve ambiguity (multiple instances selected) */
607 struct ks *SList;
608 {
609  struct ks *S,*Sret;
610  char *SymbolName;
611  struct ka BB;
612  double A,Area;
613 
614  /* find the smallest cell */
615  sl_bb(SList,&BB);
616  Area = BB.kaRight - BB.kaLeft;
617  Area *= BB.kaTop - BB.kaBottom;
618  Sret = SList;
619  for (S = SList; S != NULL; S = S->ksSucc) {
621  &BB.kaLeft,&BB.kaBottom,&BB.kaRight,&BB.kaTop);
622  A = BB.kaRight - BB.kaLeft;
623  A *= BB.kaTop - BB.kaBottom;
624  if (A < Area) {
625  Sret = S;
626  Area = A;
627  }
628  }
629  if (!is_BB_visible(Sret->ksPointer)) return (NULL);
630 
631  SymbolName = ((struct c *)Sret->ksPointer->oRep)->cMaster->mName;
632  sprintf(TypeOut,"You have selected an instance of %s.",SymbolName);
634  return (Sret);
635 }
636 
637 
638 int
640 
641 /* Returns True if one of Types is in SelectionQ and is selected,
642  * or of anything selected is in the Q if Types is NULL.
643  */
644 char *Types;
645 {
646  struct ks *SQDesc;
647 
648  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
649  if (Types == NULL || strchr(Types,SQDesc->ksPointer->oType))
650  if (SQDesc->ksPointer->oInfo == SQ_OLDSEL) return (True);
651  }
652  return (False);
653 }
654 
655 
656 void
658 
659 /* Perform a point select, selecting only Types, or anything if
660  * Types is NULL.
661  */
662 char *Types;
663 {
664  struct ka BB;
665  char TTmp[8];
666 
667  BB.kaLeft = BB.kaRight = SCursor.kcRawX;
668  BB.kaBottom = BB.kaTop = SCursor.kcRawY;
669  if (Types == NULL) {
670  Selection(&BB);
671  return;
672  }
674  strncpy(Parameters.kpSelectTypes,Types,8);
675  Parameters.kpSelectTypes[7] = '\0';
676  Selection(&BB);
678 }
679 
680 
681 void
683 
684 {
685  SelectQHead = NULL;
686 }
687 
688 
689 void
691 
692 /* Clear the SelectionQ. */
693 {
694  struct ks *SQDesc,*SQNext;
695 
696  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQNext) {
697  SQNext = SQDesc->ksSucc;
698  SQDesc->ksPointer->oInfo = SQ_OLD;
699  tfree(SQDesc);
700  }
701  SelectQHead = NULL;
702 }
703 
704 
705 void
707 
708 /* Insert Pointer into the SelectionQ (no checking for duplication). */
709 struct o *Pointer;
710 {
711  struct ks *SQDesc;
712 
713  if ((SQDesc = alloc(ks)) == NULL) MallocFailed();
714 
715  /* SelectQHead is most recent addition */
716  SQDesc->ksPointer = Pointer;
717  SQDesc->ksSucc = SelectQHead;
718  SelectQHead = SQDesc;
719 }
720 
721 
722 void
724 
725 /* Delete Pointer from SelectionQ if it is there. */
726 struct o *Pointer;
727 {
728  struct ks *SQDesc,*SQPrev,*SQNext;
729 
730  SQPrev = NULL;
731 
732  for (SQDesc = SelectQHead; SQDesc; SQPrev = SQDesc,SQDesc = SQNext) {
733  SQNext = SQDesc->ksSucc;
734 
735  if (SQDesc->ksPointer != Pointer) continue;
736  Pointer->oInfo = SQ_OLD;
737 
738  if (SQPrev == NULL)
739  SelectQHead = SQNext;
740  else
741  SQPrev->ksSucc = SQNext;
742  tfree(SQDesc);
743  return;
744  }
745 }
746 
747 
748 void
750 
751 /* Compute the BB of the queued and selected objects. */
752 {
753  struct ks *SQDesc;
754  struct ka BB;
755  int Info;
756 
761 
762  for (SQDesc = SelectQHead; SQDesc != NULL; SQDesc = SQDesc->ksSucc) {
763  Info = SQDesc->ksPointer->oInfo;
764  if (Info == SQ_OLDSEL || Info == SQ_NEWSEL ||
765  (Info > 10 && Info <= 255)) {
766  get_BB(SQDesc->ksPointer,&BB);
767  UpdateBB(SelectQBB,BB);
768  }
769  }
770 }
771 
772 
773 /* Theory behind SQRestore() and SQDesel();
774  *
775  * In commands which modify objects such as Move, the original object(s)
776  * are conditionally deleted, and new objects are conditionally created.
777  * All objects are left in the SelectionQ for a time to allow Undo.
778  * For example, suppose the SelectionQ is empty, and the user points at
779  * an object.
780  *
781  * operation: SelectionQ:
782  * select OLD (Info = SQ_OLDSEL)
783  * move NEW (Info = SQ_NEW), OLD (Info = SQ_GONE)
784  * User now selects newly moved object (the complicated case):
785  * select NEW NEW (Info = SQ_OLDSEL), NEW (Info = SQ_OLDSEL),
786  * OLD (Info = SQ_GONE)
787  * Now undo undoes the selection
788  * Undo (SQDesel()) NEW (Info = SQ_NEW), OLD (Info = SQ_GONE)
789  * Next undo undoes the move, leaving original item selected (conditionally).
790  * Undo (SQRestore(1)) OLD (Info = SQ_NEWSEL)
791  * Next undo undoes the selection
792  * Undo (SQDesel()) OLD (Info = SQ_NEW)
793  * The next undo repeats the move, etc.
794  *
795  * SQRestore(0) unsets the conditionality of objects in the SelectionQ
796  * and should be called when things are "final," i.e., before function
797  * exit or next operation.
798  */
799 
800 
801 void
803 
804 /* Restore the conditionally created objects in the SelectionQ
805  * and delete duplicates if Undo is False. Otherwise undo the
806  * last operation.
807  */
808 
809 /* If Undo is True:
810  * Previously deleted objects become conditionally selected:
811  * Info = SQ_GONE -> Info = SQ_NEWSEL.
812  * New objects are deleted from SelectionQ and database:
813  * Info = SQ_NEW deleted from queue and database.
814  * Info = SQ_NEWSEL deleted from queue and database.
815  * Else
816  * Conditionally deleted objects are really deleted:
817  * Info = SQ_GONE deleted from queue and database.
818  * New objects are now Old objects, selected or otherwise:
819  * Info = SQ_NEW -> Info = SQ_OLD, deleted from queue.
820  * Info = SQ_NEWSEL -> Info = SQ_OLDSEL.
821  */
822 
823 int Undo;
824 {
825  struct ks *SQDesc,*SQNext;
826  struct prpty *PDesc;
827  int Info;
828  struct o *Pointer;
829 
830  /* Properties added have the Info field set to "new", so we can
831  * remove them during Undo.
832  */
834  if (Undo == True) {
835  while (PDesc) {
836  if (PDesc->prpty_Info &&
837  !strcmp(PDesc->prpty_Info,"new")) {
839  PDesc->prpty_Succ;
840  free(PDesc->prpty_Data);
841  free(PDesc);
843  continue;
844  }
845  break;
846  }
847  }
848  else {
849  while (PDesc) {
850  if (PDesc->prpty_Info &&
851  !strcmp(PDesc->prpty_Info,"new")) {
852  PDesc->prpty_Info = NULL;
853  PDesc = PDesc->prpty_Succ;
854  continue;
855  }
856  break;
857  }
858  }
859 
860  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQNext) {
861  SQNext = SQDesc->ksSucc;
862  Pointer = SQDesc->ksPointer;
863  Info = Pointer->oInfo;
864 
865  if (Info == SQ_GONE) {
866  if (Undo == True)
867  Pointer->oInfo = SQ_NEWSEL;
868  else {
869  SQDelete(Pointer);
870  CDDelete(Parameters.kpCellDesc,Pointer);
871  }
872  continue;
873  }
874  if (Info == SQ_NEW) {
875  SQDelete(Pointer);
876  if (Undo == True) {
877  Pointer->oInfo = SQ_GONE;
878  CDDelete(Parameters.kpCellDesc,Pointer);
879  }
880  else
881  Pointer->oInfo = SQ_OLD;
882  continue;
883  }
884  if (Info == SQ_NEWSEL) {
885  if (Undo == True) {
886  SQDelete(Pointer);
887  Pointer->oInfo = SQ_GONE;
888  CDDelete(Parameters.kpCellDesc,Pointer);
889  }
890  else
891  Pointer->oInfo = SQ_OLDSEL;
892  }
893  }
894  if (Undo == False)
895  sq_delete_dups();
896 }
897 
898 
899 void
900 SQDesel(Types)
901 
902 /* Undo a selection operation. */
903 
904 /* Info = SQ_OLDSEL deleted from queue, and duplicates set to Info = SQ_NEW.
905  * Info = SQ_NEWSEL -> Info = SQ_NEW.
906  * Ignores objects with type not listed in Types.
907  */
908 
909 char *Types;
910 {
911  struct ks *SQDesc, *SQNext;
912  struct o *Pointer;
913  int Info;
914  char Type;
915 
916  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQNext) {
917  SQNext = SQDesc->ksSucc;
918  Type = SQDesc->ksPointer->oType;
919  if (Types And !strchr(Types,Type)) continue;
920  Info = SQDesc->ksPointer->oInfo;
921 
922  /* Have to be careful here. If selected object is already
923  * in queue have to reset Info of second entry to SQ_NEW.
924  */
925 
926  if (Info == SQ_OLDSEL) {
927  Pointer = SQDesc->ksPointer;
928  Pointer->oInfo = SQ_OLD;
929  SQDelete(Pointer);
930  sq_set_NEW(Pointer);
931  continue;
932  }
933  if (Info == SQ_NEWSEL)
934  SQDesc->ksPointer->oInfo = SQ_NEW;
935  }
936 }
937 
938 
939 void
941 
942 /* Show selected objects by highlighting their BBs. */
943 {
944  struct ks *SQDesc;
945  int Info;
946 
948  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
949  Info = SQDesc->ksPointer->oInfo;
950  /* Test for user interrupt */
953  return;
954  }
955  if (Info == SQ_OLDSEL || Info == SQ_NEWSEL ||
956  (Info > 10 && Info <= 255)) {
957  /* Show Selected Objects */
959  }
960  }
961 }
962 
963 
964 static void
966 
967 /* If object is in queue, set Info to SQ_NEW. */
968 struct o *Pointer;
969 {
970  struct ks *SQDesc;
971  int Info;
972 
973  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
974  if (SQDesc->ksPointer == Pointer) {
975  SQDesc->ksPointer->oInfo = SQ_NEW;
976  return;
977  }
978  }
979 }
980 
981 
982 static void
984 
985 /* Delete duplicate entries in selection queue. */
986 {
987  struct ks *SQDesc,*SQDesc1,*SQNext;
988  int Info;
989 
990  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQNext) {
991  SQNext = SQDesc->ksSucc;
992  Info = SQDesc->ksPointer->oInfo;
993  for (SQDesc1 = SQDesc->ksSucc; SQDesc1; SQDesc1 = SQDesc1->ksSucc)
994  if (SQDesc->ksPointer == SQDesc1->ksPointer) {
995  SQDelete(SQDesc->ksPointer);
996  /* SQDelete sets Info to SQ_OLD, have to undo this */
997  SQDesc1->ksPointer->oInfo = Info;
998  break;
999  }
1000  }
1001 }
1002 
1003 
1004 static void
1006 
1007 struct o *Pointer;
1008 {
1009  int Layer;
1010  struct p *Path;
1011  long Width;
1012  char OldRD;
1013  struct ka BB;
1014 
1015  if (Pointer->oType == CDWIRE) {
1016  CDWire(Pointer,&Layer,&Width,&Path);
1017  ShowWire(HighlightingColor,Width,Path);
1018  return;
1019  }
1020  if (Pointer->oType == CDSYMBOLCALL) {
1022  &BB.kaLeft,&BB.kaBottom,&BB.kaRight,&BB.kaTop);
1024  return;
1025  }
1026  if (Pointer->oType == CDLABEL) {
1027 
1028  /* BB of labels must be special-cased. Can't use CDBB. */
1029 
1031  if (OldRD != FINEVIEWPORTONLY) {
1033  BBLabel(View->kvCoarseWindow,Pointer,&BB);
1035  }
1036  if (OldRD != COARSEVIEWPORTONLY) {
1038  BBLabel(View->kvFineWindow,Pointer,&BB);
1040  }
1042  return;
1043  }
1044  if (Pointer->oType == CDPOLYGON) {
1045  CDPolygon(Pointer,&Layer,&Path);
1047  return;
1048  }
1049  if (Pointer->oType == CDBOX) {
1051  &BB.kaLeft,&BB.kaBottom,&BB.kaRight,&BB.kaTop);
1053  return;
1054  }
1055 }
1056 
1057 
1058 long *
1059 InPath(Delta,Path,X,Y)
1060 
1061 /* Is (X,Y) on the path described by <Path>?
1062  * If yes, return a pointer to x,y that are exactly in path.
1063  */
1064 int Delta;
1065 struct p *Path;
1066 long X,Y;
1067 {
1068  struct p *Pair;
1069  struct ka BB;
1070  double x1,x2,y1,y2,d0,d1,d2,d3,w;
1071  static long xy[2];
1072 
1073  if (Delta < 10) Delta = 10;
1074 
1075  if (Path == NULL) return (False);
1076  for (Pair = Path; Pair->pSucc != NULL; Pair = Pair->pSucc) {
1077 
1078  if (Pair->pX < Pair->pSucc->pX) {
1079  BB.kaLeft = Pair->pX;
1080  BB.kaRight = Pair->pSucc->pX;
1081  }
1082  else {
1083  BB.kaRight = Pair->pX;
1084  BB.kaLeft = Pair->pSucc->pX;
1085  }
1086  if (Pair->pY < Pair->pSucc->pY) {
1087  BB.kaBottom = Pair->pY;
1088  BB.kaTop = Pair->pSucc->pY;
1089  }
1090  else {
1091  BB.kaBottom = Pair->pSucc->pY;
1092  BB.kaTop = Pair->pY;
1093  }
1094  OversizeBox(&BB,Delta);
1095  if (!InBox(X,Y,&BB)) continue;
1096 
1097  x1 = Pair->pX - Pair->pSucc->pX;
1098  y1 = Pair->pY - Pair->pSucc->pY;
1099  d0 = x1*x1 + y1*y1;
1100 
1101  x1 = Pair->pX - X;
1102  y1 = Pair->pY - Y;
1103  d1 = x1*x1 + y1*y1;
1104  x2 = Pair->pSucc->pX - X;
1105  y2 = Pair->pSucc->pY - Y;
1106  d2 = x2*x2 + y2*y2;
1107 
1108  d3 = (d2 - d1)/(2*sqrt(d0));
1109  w = (d1+d2)/2 - d0/4 - d3*d3;
1110 
1111  if (w <= (long)Delta*Delta) {
1112  /* should be positive, fabs() just in case */
1113  d1 = sqrt(fabs(d1-w)/d0);
1114  xy[0] = Pair->pX + (Pair->pSucc->pX - Pair->pX)*d1;
1115  xy[1] = Pair->pY + (Pair->pSucc->pY - Pair->pY)*d1;
1116  return (xy);
1117  }
1118  }
1119  return (NULL);
1120 }
1121 
1122 
1123 static int
1124 point_in_poly(Delta,Path,X,Y)
1125 
1126 /* Return True if point is enclosed in polygon, or within Delta of a vertex.
1127  * Algorithm is to sum angle differences to reference point around
1128  * path. If the reference point is inside, the sum is 2*PI, otherwise
1129  * the sum is zero.
1130  */
1131 int Delta;
1132 struct p *Path;
1133 long X,Y;
1134 {
1135  struct p *p;
1136  double Xp,Yp,R,Theta,ThetaLast,Sum,zz;
1137 
1138  Sum = 0;
1139 
1140  for (p = Path; p != NULL; p = p->pSucc) {
1141 
1142  Xp = p->pX - X;
1143  Yp = p->pY - Y;
1144  R = sqrt(Xp*Xp + Yp*Yp);
1145  if (R <= Delta) return (True);
1146  Theta = asin(Yp/R);
1147  if (Xp >= 0) {
1148  if (Yp < 0)
1149  Theta = 2*M_PI + Theta;
1150  }
1151  else
1152  Theta = M_PI - Theta;
1153  if (p != Path) {
1154  zz = (Theta - ThetaLast);
1155  if (zz > M_PI) zz -= 2*M_PI;
1156  if (zz < -M_PI) zz += 2*M_PI;
1157  Sum += zz;
1158  }
1159  ThetaLast = Theta;
1160  }
1161  if (fabs(Sum) >= 1.99*M_PI) return (True);
1162  return (False);
1163 }
1164 
1165 
1166 static int
1168 
1169 /* return True if the path intersects the BB */
1170 struct p *Path;
1171 struct ka *BB;
1172 {
1173  struct ka Line;
1174 
1175  Line.kaLeft = Path->pX;
1176  Line.kaBottom = Path->pY;
1177  Path = Path->pSucc;
1178  for (; Path != NULL; Path = Path->pSucc) {
1179  Line.kaRight = Path->pX;
1180  Line.kaTop = Path->pY;
1181  if (overlap_line(&Line,BB)) return (True);
1182  Line.kaLeft = Line.kaRight;
1183  Line.kaBottom = Line.kaTop;
1184  }
1185  return (False);
1186 }
1187 
1188 
1189 static int
1191 
1192 /* return True if Line intersects BB */
1193 struct ka *Line,*BB;
1194 {
1195  struct ka LBB;
1196 
1197  LBB.kaLeft = BB->kaLeft;
1198  LBB.kaRight = BB->kaLeft;
1199  LBB.kaBottom = BB->kaBottom;
1200  LBB.kaTop = BB->kaTop;
1201  if (cross_line(Line,&LBB)) return (True);
1202 
1203  LBB.kaRight = BB->kaRight;
1204  LBB.kaBottom = BB->kaTop;
1205  if (cross_line(Line,&LBB)) return (True);
1206 
1207  LBB.kaLeft = BB->kaRight;
1208  LBB.kaBottom = BB->kaBottom;
1209  if (cross_line(Line,&LBB)) return (True);
1210 
1211  LBB.kaLeft = BB->kaLeft;
1212  LBB.kaTop = BB->kaBottom;
1213  if (cross_line(Line,&LBB)) return (True);
1214 
1215  return (False);
1216 }
1217 
1218 
1219 static int
1220 cross_line(Line,BB)
1221 
1222 /* return True if line segments stored as diagonal of BB, Line
1223  * intersect. The line in BB is Manhattan.
1224  */
1225 struct ka *Line,*BB;
1226 {
1227  struct ka LineBB,MBB;
1228  long X,Y;
1229 
1230  MBB = *BB;
1231  if (MBB.kaTop < MBB.kaBottom)
1232  SwapInts(MBB.kaTop,MBB.kaBottom);
1233  if (MBB.kaRight < MBB.kaLeft)
1234  SwapInts(MBB.kaRight,MBB.kaLeft);
1235  LineBB = *Line;
1236  if (LineBB.kaTop < LineBB.kaBottom)
1237  SwapInts(LineBB.kaTop,LineBB.kaBottom);
1238  if (LineBB.kaRight < LineBB.kaLeft)
1239  SwapInts(LineBB.kaRight,LineBB.kaLeft);
1240 
1241  /* return False if BB's don't overlap */
1242  if (LineBB.kaLeft > MBB.kaRight ||
1243  LineBB.kaRight < MBB.kaLeft ||
1244  LineBB.kaBottom > MBB.kaTop ||
1245  LineBB.kaTop < MBB.kaBottom)
1246  return (False);
1247 
1248  /* if Line is Manhattan, return True */
1249  if (Line->kaLeft == Line->kaRight || Line->kaBottom == Line->kaTop)
1250  return (True);
1251 
1252  if (BB->kaBottom == BB->kaTop) {
1253 
1254  X = (BB->kaBottom - Line->kaBottom)*
1255  ((double)(Line->kaRight - Line->kaLeft)/
1256  (Line->kaTop - Line->kaBottom)) +
1257  Line->kaLeft;
1258  if (X < BB->kaLeft || X > BB->kaRight) return (False);
1259  }
1260  else {
1261 
1262  Y = (BB->kaLeft - Line->kaLeft)*
1263  ((double)(Line->kaTop - Line->kaBottom)/
1264  (Line->kaRight - Line->kaLeft))
1265  + Line->kaBottom;
1266  if (Y < BB->kaBottom || Y > BB->kaTop) return (False);
1267  }
1268  return (True);
1269 }
struct prpty * sPrptyList
Definition: cddefs.h:133
void SQRestore(int Undo)
Definition: choose.c:802
#define PL_ESC
Definition: sced.h:62
void ErasePrompt()
Definition: viewport.c:538
void MX()
Definition: choose.c:52
#define loop
Definition: cdmacs.h:11
void SQInsert(struct o *Pointer)
Definition: choose.c:706
void Redisplay()
int struct o * Pointer
Definition: cd.c:1311
void Selection(struct ka *AOI)
Definition: choose.c:281
char * prpty_Info
Definition: cdprpty.h:64
#define SQ_GONE
Definition: sced.h:347
static struct ks * select_items()
long kcRawY
Definition: sced.h:103
struct ka * kvCoarseWindow
Definition: sced.h:149
static void redisplay_edges()
char * MenuUNDO
Definition: scedintr.c:108
#define PL_UND
Definition: sced.h:63
#define SQ_OLD
Definition: sced.h:341
long kaRight
Definition: sced.h:112
#define CDINFINITY
Definition: cddefs.h:70
long kcRawX
Definition: sced.h:103
char * strcpy()
struct o * ksPointer
Definition: sced.h:335
double kvFineRatio
Definition: sced.h:154
if(TDesc==NULL)
Definition: cd.c:1326
int PointLoop()
struct kc SCursor
Definition: init.c:21
char oType
Definition: cddefs.h:148
long kaBottom
Definition: sced.h:112
double kvCoarseRatio
Definition: sced.h:155
#define COARSEVIEWPORTONLY
Definition: sced.h:51
struct s * kpCellDesc
Definition: sced.h:207
#define Not
Definition: cdmacs.h:16
#define M_PI
Definition: spice.h:132
#define Max(Dragon, Eagle)
Definition: cdmacs.h:17
int CDStatusInt
Definition: cd.c:75
void BBLabel()
#define PL_PCW
Definition: sced.h:65
#define CDDelete
Definition: cddefs.h:19
FILE * p
Definition: proc2mod.c:48
void CDPolygon()
void CDGen()
int InBox()
void Rotat180()
Definition: choose.c:102
#define Min(Dragon, Eagle)
Definition: cdmacs.h:18
Definition: cddefs.h:169
Definition: sced.h:111
char kpRedisplayControl
Definition: sced.h:312
void CDWire()
static struct ks * which_cell()
Definition: cddefs.h:215
#define alloc(type)
Definition: cdmacs.h:21
void SQInit()
Definition: choose.c:682
#define FINEVIEWPORTONLY
Definition: sced.h:50
void ShowWire()
long * InPath(int Delta, struct p *Path, long X, long Y)
Definition: choose.c:1059
union prp_data * prpty_Data
Definition: cdprpty.h:65
void Undo()
Definition: bascmd.c:43
long pY
Definition: cddefs.h:216
char * Menu90
Definition: scedintr.c:54
char * Menu180
Definition: scedintr.c:55
void MallocFailed()
Definition: scedintr.c:857
#define CDSYMBOLCALL
Definition: cddefs.h:43
long X
Definition: actions.c:450
#define SQ_NEW
Definition: sced.h:350
static void sq_set_NEW()
void MenuDeselect()
int kpMY
Definition: sced.h:284
#define tfree(x)
Definition: cdmacs.h:22
static void get_BB()
int CDInitGen()
#define R
Definition: parse.c:444
void SQComputeBB()
Definition: choose.c:749
struct ks * ksSucc
Definition: sced.h:334
#define NULL
Definition: spdefs.h:121
char TypeOut[200]
Definition: init.c:23
struct kp Parameters
Definition: init.c:19
void SelectTypes(char *Types)
Definition: choose.c:657
long kaTop
Definition: sced.h:112
static int overlap_path()
void ShowEmptyBox()
void ShowPath()
struct ka * kvFineWindow
Definition: sced.h:147
void SQShow()
Definition: choose.c:940
#define True
Definition: scedstub.c:16
void SQClear()
Definition: choose.c:690
void RedisplayAfterInterrupt()
Definition: display.c:623
static int overlap_line()
#define UpdateBB(BB2, BB1)
Definition: choose.c:165
char * MenuMY
Definition: scedintr.c:91
static void sq_display_selected()
char * MenuAREA
Definition: scedintr.c:64
char * MenuSELEC
Definition: scedintr.c:103
struct kv * View
Definition: init.c:17
int kpRotationAngle
Definition: sced.h:282
void EraseBox()
void Sel(int *LookedAhead)
Definition: choose.c:174
struct o * oRep
Definition: cddefs.h:144
void Rotat0()
Definition: choose.c:82
long kaLeft
Definition: sced.h:112
Definition: cddefs.h:142
static int is_BB_visible()
void DevUpdate()
Definition: display.c:359
void Rotat90()
Definition: choose.c:92
char * MenuMX
Definition: scedintr.c:90
static void sq_delete_dups()
Definition: choose.c:983
struct ks * SelectQHead
Definition: scedext.h:64
long pX
Definition: cddefs.h:216
Definition: cddefs.h:177
int Layer
Definition: cd.c:1908
static void sl_free()
#define CDWIRE
Definition: cddefs.h:47
static void sl_bb()
int kpEnableSelectQRedisplay
Definition: sced.h:249
struct prpty * prpty_Succ
Definition: cdprpty.h:66
void MY()
Definition: choose.c:67
int kpMX
Definition: sced.h:283
#define And
Definition: cdmacs.h:14
char * Menu270
Definition: scedintr.c:56
void FBSetRubberBanding()
static int point_in_poly()
void Area(int *LookedAhead)
Definition: choose.c:209
Definition: sced.h:333
int CDBB()
void Desel()
Definition: choose.c:264
Definition: cddefs.h:227
#define SQ_NEWSEL
Definition: sced.h:353
int AreTypesInQ(char *Types)
Definition: choose.c:639
int char Type
Definition: actions.c:449
#define False
Definition: scedstub.c:15
void AlterMenuEntries()
void OversizeBox()
static int cross_line()
#define PL_CMD
Definition: sced.h:64
int kcInFine
Definition: sced.h:105
char * MenuDESEL
Definition: scedintr.c:72
void SQDelete(struct o *Pointer)
Definition: choose.c:723
void SQDesel(char *Types)
Definition: choose.c:900
void MenuSelect()
struct p * pSucc
Definition: cddefs.h:217
long Y
Definition: actions.c:450
Definition: cdprpty.h:62
void ShowPrompt(char *str)
Definition: scedstub.c:71
#define CDPOLYGON
Definition: cddefs.h:44
short oInfo
Definition: cddefs.h:147
struct ka SelectQBB
Definition: scedext.h:65
void Rotat270()
Definition: choose.c:112
#define SQ_OLDSEL
Definition: sced.h:344
void free()
#define SwapInts(Dragon, Eagle)
Definition: cdmacs.h:20
char * Menu0
Definition: scedintr.c:53
char kpSelectTypes[8]
Definition: sced.h:273
#define HighlightingColor
Definition: sced.h:74
#define CDLABEL
Definition: cddefs.h:46
int kpSIGINTERRUPT
Definition: sced.h:267
#define CDBOX
Definition: cddefs.h:48