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 display control code.
11  */
12 
13 #include "spice.h"
14 #include "sced.h"
15 #include "scedmacs.h"
16 
17 
18 
19 /***********************************************************************
20  *
21  * Window manipulation menu commands.
22  *
23  ***********************************************************************/
24 
25 extern char *MenuPAN;
26 extern char *MenuZOOM;
27 extern char *MenuWINDO;
28 extern char *MenuLAST;
29 
30 void
Pan(LookedAhead)31 Pan(LookedAhead)
32 
33 int *LookedAhead;
34 {
35     MenuSelect(MenuPAN);
36     ShowPrompt("Point to center of new window.");
37     loop {
38         switch (PointLoopSafe(LookedAhead)) {
39             case PL_ESC:
40             case PL_CMD:
41                 MenuDeselect(MenuPAN);
42                 ErasePrompt();
43                 return;
44             case PL_PCW:
45                 SaveLastView();
46                 InitCoarseWindow(SCursor.kcX,SCursor.kcY,
47                     (long)View->kvCoarseWindow->kaWidth);
48                 InitFineWindow(SCursor.kcX, SCursor.kcY);
49                 EraseLargeCoarseViewport();
50                 Redisplay(View->kvCoarseWindow);
51         }
52     }
53 }
54 
55 
56 void
Zoom(LookedAhead)57 Zoom(LookedAhead)
58 
59 int *LookedAhead;
60 {
61     char *TypeIn;
62     long NewWindowWidth;
63     long X,Y;
64 
65     MenuSelect(MenuZOOM);
66     sprintf(TypeOut,
67         "Enter window width (now %g) or RETURN for %s display: ",
68         View->kvCoarseWindow->kaWidth/RESOLUTION,
69         View->kvControl == SPLITSCREEN ? "full screen" : "split screen");
70     ShowPrompt(TypeOut);
71     TypeIn = FBEdit(NULL);
72     if (TypeIn == NULL) { /* esc entered */
73         MenuDeselect(MenuZOOM);
74         ErasePrompt();
75         return;
76     }
77     SaveLastView();
78     if ((sscanf(TypeIn,"%ld",&NewWindowWidth) < 1) Or NewWindowWidth <= 0) {
79         if (View->kvControl != FULLSCREEN) {
80             View->kvControl = FULLSCREEN;
81             Parameters.kpRedisplayControl = COARSEVIEWPORTONLY;
82             NewWindowWidth = View->kvFineWindow->kaWidth;
83             View->kvCoarseWindow->kaX = View->kvFineWindow->kaX;
84             View->kvCoarseWindow->kaY = View->kvFineWindow->kaY;
85             InitCoarseWindow(View->kvCoarseWindow->kaX,
86                 View->kvCoarseWindow->kaY,NewWindowWidth);
87             SetPositioning();
88         }
89         else {
90             View->kvControl = SPLITSCREEN;
91             Parameters.kpRedisplayControl = SPLITSCREEN;
92             X = View->kvCoarseWindow->kaX;
93             Y = View->kvCoarseWindow->kaY;
94             NewWindowWidth = View->kvCoarseWindow->kaWidth;
95             SetPositioning();
96             CenterFullView();
97             if (NewWindowWidth > View->kvCoarseWindow->kaWidth)
98                 NewWindowWidth = 3*View->kvCoarseWindow->kaWidth/4;
99             View->kvFineWindow->kaWidth = NewWindowWidth;
100             InitFineWindow(X,Y);
101         }
102     }
103     else {
104         NewWindowWidth *= RESOLUTION;
105         if (View->kvControl == FULLSCREEN)
106             InitCoarseWindow(View->kvCoarseWindow->kaX,
107                 View->kvCoarseWindow->kaY,NewWindowWidth);
108         else
109             /* zoom from fine window position */
110             InitCoarseWindow(View->kvFineWindow->kaX,
111                 View->kvFineWindow->kaY,NewWindowWidth);
112         SetPositioning();
113     }
114     EraseLargeCoarseViewport();
115     if (View->kvControl == FULLSCREEN)
116         Redisplay(View->kvCoarseWindow);
117     else {
118         /* make sure fine window is shown, if out of coarse clip range */
119         Parameters.kpRedisplayControl = COARSEVIEWPORTONLY;
120         Redisplay(View->kvCoarseWindow);
121         ShowEmptyBox(HighlightingColor,View->kvFineWindow);
122         Parameters.kpRedisplayControl = FINEVIEWPORTONLY;
123         Redisplay(View->kvFineWindow);
124         Parameters.kpRedisplayControl = SPLITSCREEN;
125     }
126     MenuDeselect(MenuZOOM);
127     *LookedAhead = False;
128     ErasePrompt();
129     return;
130 }
131 
132 
133 void
Windo(LookedAhead)134 Windo(LookedAhead)
135 
136 int *LookedAhead;
137 {
138     long NewWindowWidth, Width, Height, Tmp;
139     MenuSelect(MenuWINDO);
140     loop{
141         ShowPrompt("Point to endpoints of diagonal.");
142         switch (PointLoopSafe(LookedAhead)) {
143             case PL_ESC:
144             case PL_CMD:
145                 goto quit;
146             case PL_PCW:
147                 break;
148         }
149         FBSetRubberBanding('R');
150         switch (PointLoopSafe(LookedAhead)) {
151             case PL_ESC:
152             case PL_CMD:
153                 FBSetRubberBanding(0);
154                 goto quit;
155             case PL_PCW:
156                 FBSetRubberBanding(0);
157                 break;
158         }
159         SaveLastView();
160         /*
161          * Coarse window height is smaller than its width.
162          * When user points to endpoints of diagonal to define new window,
163          * he expects to see everything in this window after redisplay.
164          * To make this happen, we have to EXPAND the width enough so that
165          * the height that InitCoarseWindow computes is equal to the height
166          * the user wants.
167          * The following lines compute the multiplier that expands the
168          * width by the right amount.
169          */
170 
171         Width = SCursor.kcX - SCursor.kcPredX;
172         Height = SCursor.kcY - SCursor.kcPredY;
173         if (Width < 0) Width = -Width;
174         if (Height < 0) Height = -Height;
175 
176         Tmp = Height * View->kvCoarseViewport->kaWidth/
177             View->kvCoarseViewport->kaHeight;
178         NewWindowWidth = Max(Width,Tmp);
179 
180         Height /= 2;
181         Width /= 2;
182 
183         if (NewWindowWidth <= 0)    NewWindowWidth = RESOLUTION;
184         InitCoarseWindow( Min(SCursor.kcX,SCursor.kcPredX)+Width,
185             Min(SCursor.kcY,SCursor.kcPredY)+Height,NewWindowWidth);
186 
187         InitFineWindow(Min(SCursor.kcX,SCursor.kcPredX)+Width,
188             Min(SCursor.kcY,SCursor.kcPredY)+Height);
189 
190         SetPositioning();
191         EraseLargeCoarseViewport();
192         Redisplay(View->kvCoarseWindow);
193     }
194 quit:
195     MenuDeselect(MenuWINDO);
196     ErasePrompt();
197 }
198 
199 
200 void
LastView()201 LastView()
202 
203 {
204     int  i;
205     struct kw Last;
206     struct kw *Tmp;
207     char OldMenu;
208     int  EscWasReturned = 0;
209 
210     Last.kwLastWindowX           = View->kvCoarseWindow->kaX;
211     Last.kwLastWindowY           = View->kvCoarseWindow->kaY;
212     Last.kwLastFineWindowX       = View->kvFineWindow->kaX;
213     Last.kwLastFineWindowY       = View->kvFineWindow->kaY;
214     Last.kwLastWindowWidth       = View->kvCoarseWindow->kaWidth;
215     Last.kwLastFineWindowWidth   = View->kvFineWindow->kaWidth;
216     (Last.kwName)[5]             = View->kvFineViewportOnBottom;
217     (Last.kwName)[6]             = View->kvControl;
218 
219     i = 0;
220     for (Tmp = Parameters.kpWindowStack; Tmp; Tmp = Tmp->kwNext)
221         AmbiguityMenu[i++].mEntry = Tmp->kwName;
222     AmbiguityMenu[i].mEntry = NULL;
223     FixMenuPrefix(AmbiguityMenu);
224 
225     if (i > 1) {
226         /* Show ambiguity menu. */
227         OldMenu = Parameters.kpMenu;
228         Parameters.kpMenu = AMBIGUITYMENU;
229         ShowMenu(AmbiguityMenu);
230 
231         /* Which viewport is user interested in? */
232         ShowPrompt("Point to the name of the desired view.");
233         loop {
234             int dummy;
235             switch (PointLoopSafe(&dummy)) {
236                 case PL_ESC:
237                     EscWasReturned = 1;
238                     break;
239                 case PL_CMD:
240                     break;
241                 case PL_PCW:
242                     ShowPrompt("You aren't pointing at the menu.");
243                     continue;
244             }
245             break;
246         }
247         Parameters.kpMenu = OldMenu;
248         ShowCommandMenu();
249         if (EscWasReturned) goto quit;
250 
251         /* find new view */
252         for (Tmp = Parameters.kpWindowStack; Tmp; Tmp = Tmp->kwNext)
253             if (strncmp(Tmp->kwName,Parameters.kpCommand,
254                 MenuViewport.kaRight-MenuViewport.kaLeft+1) == 0){
255                 break;
256             }
257     }
258     else
259         Tmp = Parameters.kpWindowStack;
260 
261     /* The status of the fine window positioning is stored in
262      * the name field, as is full screen mode flag.
263      */
264     View->kvFineViewportOnBottom = (Tmp->kwName)[5];
265     View->kvControl = (Tmp->kwName)[6];
266 
267     InitViewport();
268 
269     /* change to new viewport */
270     InitCoarseWindow(Tmp->kwLastWindowX,Tmp->kwLastWindowY,
271         Tmp->kwLastWindowWidth);
272 
273     SetPositioning();
274 
275     InitFineWindow(Tmp->kwLastFineWindowX,Tmp->kwLastFineWindowY);
276 
277     Parameters.kpWindowStack->kwLastWindowX         = Last.kwLastWindowX;
278     Parameters.kpWindowStack->kwLastWindowY         = Last.kwLastWindowY;
279     Parameters.kpWindowStack->kwLastFineWindowX     = Last.kwLastFineWindowX;
280     Parameters.kpWindowStack->kwLastFineWindowY     = Last.kwLastFineWindowY;
281     Parameters.kpWindowStack->kwLastWindowWidth     = Last.kwLastWindowWidth;
282     Parameters.kpWindowStack->kwLastFineWindowWidth = Last.kwLastFineWindowWidth;
283     Parameters.kpWindowStack->kwExpand              = Last.kwExpand;
284     Parameters.kpWindowStack->kwExpandFineOnly      = Last.kwExpandFineOnly;
285     (Parameters.kpWindowStack->kwName)[5]           = (Last.kwName)[5];
286     (Parameters.kpWindowStack->kwName)[6]           = (Last.kwName)[6];
287 
288     EraseLargeCoarseViewport();
289     Redisplay(View->kvCoarseWindow);
290 quit:
291     MenuDeselect(MenuLAST);
292     ErasePrompt();
293 }
294 
295 
296 void
SaveLastView()297 SaveLastView()
298 
299 {
300     /*
301      * Parameters.kpWindowStack is always the last view.
302      */
303     if (Parameters.kpWindowStack == NULL) {
304         if ((Parameters.kpWindowStack = alloc(kw)) == NULL)
305             MallocFailed();
306         strcpy(Parameters.kpWindowStack->kwName,"prev");
307         Parameters.kpWindowStack->kwNext = NULL;
308     }
309     Parameters.kpWindowStack->kwLastWindowX     = View->kvCoarseWindow->kaX;
310     Parameters.kpWindowStack->kwLastWindowY     = View->kvCoarseWindow->kaY;
311     Parameters.kpWindowStack->kwLastFineWindowX = View->kvFineWindow->kaX;
312     Parameters.kpWindowStack->kwLastFineWindowY = View->kvFineWindow->kaY;
313     Parameters.kpWindowStack->kwLastWindowWidth =
314         View->kvCoarseWindow->kaWidth;
315     Parameters.kpWindowStack->kwLastFineWindowWidth =
316         View->kvFineWindow->kaWidth;
317     (Parameters.kpWindowStack->kwName)[5] = View->kvFineViewportOnBottom;
318     (Parameters.kpWindowStack->kwName)[6] = View->kvControl;
319 }
320 
321 
322 void
SaveViewOnStack()323 SaveViewOnStack()
324 
325 {
326     int i = 0;
327     char c, buf[32];
328     struct kw *New, *Tmp;
329 
330     New = alloc(kw);
331     if (New == NULL) MallocFailed();
332 
333     New->kwLastWindowX         = View->kvCoarseWindow->kaX;
334     New->kwLastWindowY         = View->kvCoarseWindow->kaY;
335     New->kwLastFineWindowX     = View->kvFineWindow->kaX;
336     New->kwLastFineWindowY     = View->kvFineWindow->kaY;
337     New->kwLastWindowWidth     = View->kvCoarseWindow->kaWidth;
338     New->kwLastFineWindowWidth = View->kvFineWindow->kaWidth;
339     (New->kwName)[5]           = View->kvFineViewportOnBottom;
340     (New->kwName)[6]           = View->kvControl;
341 
342     if (Parameters.kpWindowStack == NULL)
343         SaveLastView();
344 
345     New->kwNext = NULL;
346     for (Tmp = Parameters.kpWindowStack; Tmp->kwNext; i++,Tmp = Tmp->kwNext) ;
347     Tmp->kwNext = New;
348     sprintf(buf,"Current view assigned to: %c",'A'+i);
349     ShowPrompt(buf);
350     New->kwName[0] = 'a'+ i;
351     New->kwName[1] = '\0';
352 }
353 
354 
355 
356 /***********************************************************************
357  *
358  * Redisplay control code.
359  *
360  ***********************************************************************/
361 
362 static int DisplayDepth, HierarchyLevel;
363 
364 #ifdef __STDC__
365 static void redisplay_layer(struct s*,struct ka*);
366 #else
367 static void redisplay_layer();
368 #endif
369 
370 #define ka_copy(BB1,BB2) BB1.kaLeft = BB2->kaLeft; \
371     BB1.kaRight = BB2->kaRight; \
372     BB1.kaBottom = BB2->kaBottom; \
373     BB1.kaTop = BB2->kaTop; \
374     TPoint(&BB1.kaLeft,&BB1.kaBottom); \
375     TPoint(&BB1.kaRight,&BB1.kaTop); \
376     if(BB.kaLeft > BB.kaRight) \
377         SwapInts(BB1.kaLeft,BB1.kaRight); \
378     if(BB.kaBottom > BB.kaTop) \
379         SwapInts(BB1.kaBottom,BB1.kaTop);
380 
381 
382 void
Redisplay(AOI)383 Redisplay(AOI)
384 
385 struct ka *AOI;
386 {
387     struct s *CellDesc = Parameters.kpTopDesc;
388 
389     SetCurrentAOI(AOI);
390 
391     if (CurrentAOI.aInCoarse == 0 And CurrentAOI.aInFine == 0)
392         goto quit;
393 
394     Parameters.kpNumGeometries = 0;
395 
396     if (!Parameters.kpGridOnTop)
397         ShowGrid();
398 
399     if (Parameters.kpCellDesc != NULL) {
400 
401         TPush();
402         TLoad();
403 
404         DisplayDepth = 0;
405         HierarchyLevel = 0;
406         if (CellDesc)
407             redisplay_layer(CellDesc,AOI);
408 
409         TPop();
410     }
411 
412     if (Parameters.kpGridOnTop)
413         ShowGrid();
414 
415     /*
416      * Show fine positioning window in coarse window.
417      */
418     DevSetColor(HighlightingColor);
419     if (Parameters.kpRedisplayControl != COARSEVIEWPORTONLY) {
420 
421         if (Parameters.kpRedisplayControl == SPLITSCREEN)
422             ShowEmptyBox(HighlightingColor,View->kvFineWindow);
423         OutlineBox(View->kvFineViewport);
424     }
425     else if (!Parameters.kpDoingHardcopy &&
426             View->kvControl == FULLSCREEN)
427         OutlineBox(View->kvLargeCoarseViewport);
428 
429     /*
430      * Highlight selected objects.
431      */
432     SQShow();
433 
434     /* SRW ** show markers */
435     ShowMarker(DISPLAY,HighlightingColor,0L,0L,0,0,0);
436 
437 quit:
438     SetCurrentAOI(View->kvCoarseWindow);
439 }
440 
441 
442 static void
redisplay_layer(CellDesc,AOI)443 redisplay_layer(CellDesc,AOI)
444 
445 struct s *CellDesc;
446 struct ka *AOI;
447 {
448     struct g *GenDesc;
449     struct o *Pointer;
450     struct p *Path;
451     struct ka BB;
452     struct ka MasterBB;
453     struct s *MasterDesc;
454     char Xform;
455     char *MasterName;
456     char *TypeIn;
457     char *Label;
458     int NumX,NumY;
459     int Int1,Int2;
460     int Layer;
461     int Expand;
462     long X,Y;
463     long Width;
464     long DX,DY;
465 
466     if (Not CDInitGen(CellDesc,1,AOI->kaLeft,AOI->kaBottom,
467         AOI->kaRight,AOI->kaTop,&GenDesc)) MallocFailed();
468     loop {
469         /* Test for user interrupt */
470         if (Parameters.kpSIGINTERRUPT) return;
471 
472         CDGen(CellDesc,GenDesc,&Pointer);
473         if (Pointer == NULL) break;
474         if (Pointer->oInfo == SQ_GONE) continue;
475 
476         ++Parameters.kpNumGeometries;
477 
478         if (Pointer->oType == CDWIRE) {
479             CDWire(Pointer,&Layer,&Width,&Path);
480             if (Pointer->oInfo == SQ_INCMPLT)
481                 ShowPath(DrawingColor,Path,False);
482             else
483                 ShowWire(DrawingColor,Width,Path);
484             continue;
485         }
486         if (Pointer->oType == CDPOLYGON) {
487             if (Parameters.kpShowDots) {
488                 CDPolygon(Pointer,&Layer,&Path);
489                 if (Pointer->oInfo == SQ_INCMPLT)
490                     ShowPath(DrawingColor,Path,False);
491                 else
492                     ShowPolygon(DrawingColor,Path);
493             }
494             continue;
495         }
496         if (Pointer->oType == CDLABEL) {
497             CDLabel(Pointer,&Layer,&Label,&X,&Y,&Xform);
498             ShowLabel(DrawingColor,Label,X,Y,Xform,True);
499             continue;
500         }
501     }
502     if (TCheck()) return;
503 
504     if (Not CDInitGen(CellDesc,0,AOI->kaLeft,AOI->kaBottom,AOI->kaRight,
505         AOI->kaTop,&GenDesc)) MallocFailed();
506 
507     loop {
508         /* Test for user interrupt */
509         if (Parameters.kpSIGINTERRUPT) break;
510 
511         CDGen(CellDesc,GenDesc,&Pointer);
512         if (Pointer == NULL) break;
513         if (Pointer->oInfo == SQ_GONE) continue;
514         CDCall(Pointer,&MasterName,&NumX,&DX,&NumY,&DY);
515 
516         if (IsCellInLib(MasterName)) {
517 
518             if (OpenCell(MasterName,&MasterDesc)) break;
519 
520             if (Not CDBB(MasterDesc,(struct o *)NULL,&MasterBB.kaLeft,
521                 &MasterBB.kaBottom,&MasterBB.kaRight,&MasterBB.kaTop))
522                 MallocFailed();
523 
524             SetTransform(Pointer);
525             TPremultiply();
526 
527             for (Int1 = NumY-1; Int1 >= 0; --Int1) {
528                 for (Int2 = 0; Int2 < NumX; ++Int2 ){
529                     TPush();
530                     TIdentity();
531                     TTranslate(Int2*DX,Int1*DY);
532                     TPremultiply();
533                     /*
534                      * Box test instance array element with AOI.
535                      */
536                     ka_copy(BB,(&MasterBB));
537                     if (Not (BB.kaLeft > AOI->kaRight Or
538                         BB.kaRight  < AOI->kaLeft Or
539                         BB.kaBottom > AOI->kaTop Or
540                         BB.kaTop    < AOI->kaBottom))
541                         redisplay_layer(MasterDesc,AOI);
542                     TPop();
543                 }
544             }
545             TPop();
546         }
547     }
548 
549     if (Not CDInitGen(CellDesc,0,AOI->kaLeft,AOI->kaBottom,AOI->kaRight,
550         AOI->kaTop,&GenDesc)) MallocFailed();
551 
552     loop {
553         /* Test for user interrupt */
554         if (Parameters.kpSIGINTERRUPT) break;
555 
556         CDGen(CellDesc,GenDesc,&Pointer);
557         if (Pointer == NULL) break;
558         if (Pointer->oInfo == SQ_GONE) continue;
559         CDCall(Pointer,&MasterName,&NumX,&DX,&NumY,&DY);
560         if (IsCellInLib(MasterName)) continue;
561 
562         if (OpenCell(MasterName,&MasterDesc)) break;
563 
564         if (CellDesc != Parameters.kpCellDesc ||
565             Parameters.kpExpandInstances) {
566 
567             if (Not CDBB(MasterDesc,(struct o *)NULL,&MasterBB.kaLeft,
568                 &MasterBB.kaBottom,&MasterBB.kaRight,&MasterBB.kaTop))
569                 MallocFailed();
570 
571             SetTransform(Pointer);
572             TPremultiply();
573 
574             for (Int1 = NumY-1; Int1 >= 0; --Int1) {
575                 for (Int2 = 0; Int2 < NumX; ++Int2 ){
576                     TPush();
577                     TIdentity();
578                     TTranslate(Int2*DX,Int1*DY);
579                     TPremultiply();
580                     /*
581                      * Box test instance array element with AOI.
582                      */
583                     ka_copy(BB,(&MasterBB));
584                     if (Not (BB.kaLeft > AOI->kaRight Or
585                         BB.kaRight  < AOI->kaLeft Or
586                         BB.kaBottom > AOI->kaTop Or
587                         BB.kaTop    < AOI->kaBottom))
588                         redisplay_layer(MasterDesc,AOI);
589                     TPop();
590                 }
591             }
592             TPop();
593         }
594         else {
595             /*
596              * Unexpanded form of an instance array is its BB with the
597              * name of its master shown in its center.
598              * If it is not 1 by 1, tell the user its dimensions.
599              * CDBB will always return True if Pointer != NULL.
600              */
601             CDStatusInt = CDBB(CellDesc,Pointer,&BB.kaLeft,&BB.kaBottom,
602                 &BB.kaRight,&BB.kaTop);
603 
604             if (BB.kaRight < BB.kaLeft) SwapInts(BB.kaLeft,BB.kaRight);
605             if (BB.kaTop < BB.kaBottom) SwapInts(BB.kaBottom,BB.kaTop);
606 
607             /*
608              * Outline BB of Instance.
609              */
610             ShowEmptyBox(InstanceBBColor,&BB);
611 
612             if (NumX != 1 Or NumY != 1)
613                 sprintf(TypeOut,"%d/%d %s",NumX,NumY,MasterName);
614             else sprintf(TypeOut,"%s",MasterName);
615             ShowLabel(InstanceNameColor,TypeOut,BB.kaLeft,
616                 BB.kaBottom + (BB.kaTop-BB.kaBottom)/2,0,True);
617         }
618     }
619 }
620 
621 
622 void
RedisplayAfterInterrupt()623 RedisplayAfterInterrupt()
624 
625 {
626     TInit();
627     ShowPrompt("Interrupted.  Type Ctrl A to abort.");
628     InitSignals();
629     ShowCommandMenu();
630 }
631 
632 
633 int
TCheck()634 TCheck()
635 
636 {
637     char *TypeIn;
638 
639     if (TFull()) {
640         ShowPrompt("Cell hierarchy is too deep. MORE");
641         (void)FBGetchar(ERASE);
642         ShowPrompt("Probably you have a recursive hierarchy.");
643         TInit();
644         return (True);
645     }
646     return (False);
647 }
648 
649 
650 void
SetTransform(Pointer)651 SetTransform(Pointer)
652 
653 struct o *Pointer;
654 {
655     struct t *TGen;
656     long X,Y;
657     char Type;
658 
659     TPush();
660     TIdentity();
661     CDInitTGen(Pointer,&TGen);
662     loop {
663         CDTGen(&TGen,&Type,&X,&Y);
664         if (TGen == NULL) break;
665 
666         if   (Type == CDROTATE)    TRotate(X,Y);
667         elif (Type == CDTRANSLATE) TTranslate(X,Y);
668         elif (Type == CDMIRRORX)   TMX();
669         elif (Type == CDMIRRORY)   TMY();
670     }
671 }
672 
673