<> <> <> <> <> DIRECTORY Atom, CD, CDBasics, CDDefaultProcs, CDDrawQueue, CDCells, CDEnvironment, CDEvents, CDInstances, CDOps, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer, CDViewerBackdoor, CDViewerInternals, CDVPrivate, CDVScale, Imager, ImagerSample USING [MapFromFrameBuffer, Move, nullFunction], InterminalBackdoor USING [terminal], IO, PopUpSelection, Process, Rope, SF USING [Vec], Terminal, TerminalIO, UserProfile, VFonts, ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer, GetViewer, SetViewer, OpenIcon, BlinkIcon]; CDVCommands: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDDefaultProcs, CDDrawQueue, CDCells, CDEnvironment, CDEvents, CDInstances, CDOps, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer, CDViewerBackdoor, CDVPrivate, CDVScale, Imager, ImagerSample, InterminalBackdoor, IO, PopUpSelection, Process, Rope, Terminal, TerminalIO, UserProfile, ViewerOps, VFonts EXPORTS CDViewerInternals SHARES CDVPrivate = BEGIN VRef: TYPE = CDVPrivate.VRef; <<--Utilities and public>> DoWithVRef: PROC [comm: CDSequencer.Command, proc: PROC[vRef: VRef]] = { v: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF v=NIL THEN TerminalIO.PutRope["failed: no viewer\n"] ELSE WITH v.data SELECT FROM vRef: VRef => IF ~vRef.viewer.destroyed THEN proc[vRef]; ENDCASE => NULL; }; AddCR: PROC [r: Rope.ROPE] RETURNS [Rope.ROPE] = { <<--if r does not already has a CR >> ml: INT _ Rope.Length[r]; IF Rope.Fetch[r, ml-1]#'\n THEN RETURN[Rope.Concat[r, "\n"]]; RETURN [r]; }; MsgAndVRef: PROC [comm: CDSequencer.Command, msg: Rope.ROPE] RETURNS [vRef: VRef_NIL] = { v: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; TerminalIO.PutRope[AddCR[msg]]; IF v=NIL THEN TerminalIO.PutRope[" failed: no viewer\n"] ELSE WITH v.data SELECT FROM vr: VRef => IF ~vr.viewer.destroyed THEN vRef _ vr ELSE TerminalIO.PutRope[" failed: viewer destroyed\n"]; ENDCASE => TerminalIO.PutRope[" failed: no ChipNDale viewer\n"]; }; Repaint: PROC [v: REF] = { WITH v SELECT FROM vRef: VRef => { CDDrawQueue.Flush[vRef.ct]; CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]]; CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]]; }; viewer: ViewerClasses.Viewer => Repaint[viewer.data]; comm: CDSequencer.Command => Repaint[comm.ref]; ENDCASE => NULL; }; SaveScale: PUBLIC PROC [viewer: ViewerClasses.Viewer] = { IF viewer#NIL THEN WITH viewer.data SELECT FROM vRef: VRef => CDProperties.PutProp[vRef.properties, $CDxSavedScale, NEW[CDVScale.ScaleRec _ vRef.scale]]; ENDCASE => NULL; }; RestoreScale: PUBLIC PROC [viewer: ViewerClasses.Viewer] = { IF viewer#NIL THEN WITH viewer.data SELECT FROM vRef: VRef => { GetScale: PROC [key: ATOM] RETURNS [CDVScale.ScaleRec] = { WITH CDProperties.GetProp[vRef.properties, key] SELECT FROM sr: REF CDVScale.ScaleRec => RETURN [sr^]; ENDCASE => RETURN [CDVScale.MakeScale[]]; }; scale: CDVScale.ScaleRec _ GetScale[$CDxSavedScale]; CDDrawQueue.Flush[vRef.ct]; <<--NO SaveScale[viewer]; it is better to have one fixed point>> IF vRef.scale.off=scale.off AND vRef.scale.nscale=scale.nscale THEN scale _ GetScale[$CDxSecondaryScale]; CDProperties.PutProp[vRef.properties, $CDxSecondaryScale, NEW[CDVScale.ScaleRec _ vRef.scale]]; vRef.intendedScale _ CDVScale.MakeScale[off: scale.off, nscale: scale.nscale, grid: vRef.scale.grid]; Repaint[vRef]; }; ENDCASE => NULL; }; WriteLnScale: PROC [v: REF] = { TerminalIO.PutRope["\n"]; <> <> <> < TerminalIO.PutF1[" (scale: %g)\n", IO.int[vRef.scale.nscale]];>> < WriteLnScale[viewer.data];>> < WriteLnScale[comm.ref];>> < TerminalIO.PutRope["\n"];>> }; ChangeScale: PROC [vRef: VRef, newScale: INT] = { newScale _ MIN[MAX[0, newScale], CDVScale.scaleNum-1]; IF vRef.scale.nscale = newScale THEN TerminalIO.PutRope["no scale change"] ELSE { oldDesignCenterOffset, newDesignCenterOffset: CD.Position; viewerCenterOffset: CD.Position _ [vRef.viewer.cw/2, vRef.viewer.ch/2]; off: CD.Position _ vRef.scale.off; dscale: CDVScale.ScaleRec; CDDrawQueue.Flush[vRef.ct]; TerminalIO.PutRope["change scale"]; dscale _ CDVScale.MakeScale[nscale: vRef.scale.nscale, grid: vRef.scale.grid]; oldDesignCenterOffset _ CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset]; dscale _ CDVScale.MakeScale[nscale: newScale, grid: vRef.scale.grid]; newDesignCenterOffset _ CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset]; off _ CDBasics.SubPoints[ CDBasics.AddPoints[off, oldDesignCenterOffset], newDesignCenterOffset ]; dscale _ CDVScale.MakeScale[off: off, nscale: newScale, grid: vRef.scale.grid]; vRef.intendedScale _ dscale; Repaint[vRef]; }; WriteLnScale[vRef.viewer]; }; ScaleUp: PROC [comm: CDSequencer.Command] = { Do: PROC[vRef: VRef] = { i: INT _ vRef.scale.nscale; i _ IF i>0 THEN i-1 ELSE 0; ChangeScale[vRef, i]; }; DoWithVRef[comm, Do] }; ScaleDown: PROC [comm: CDSequencer.Command] = { Do: PROC[vRef: VRef] = {ChangeScale[vRef, vRef.scale.nscale+1]}; DoWithVRef[comm, Do] }; <> <> <> <> <> <> <> <> <<};>> <> <> <<};>> <<>> MoveScreenCmd: PROC [comm: CDSequencer.Command] ~ { <> Do: PROC[vRef: VRef] = { CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$fastMoveScreen, [x1: comm.pos.x-comm.sPos.x, y1: comm.pos.y-comm.sPos.y, x2: 0, y2: 0]]]; }; TerminalIO.PutRope["move window\n"]; DoWithVRef[comm, Do] }; GCD: PROC [ m, n: INT ] RETURNS [ INT ] = { r: INT; SELECT m FROM <0 => m _ -m; ENDCASE => NULL; SELECT n FROM <0 => n _ -n; >0 => NULL; ENDCASE => RETURN[m]; r _ m MOD n; WHILE r>0 DO m _ n; n _ r; r _ m MOD n; ENDLOOP; RETURN[n]; }; DoMoveScreen: CDViewerBackdoor.FurtherPaintProc ~ { <> <<- Flush the queue (required because of ordering problems....)>> <<- Under VRef monitor, do:>> <<- check that the scale did not change and the offset is non-null. Quit if so.>> <<- compute offset in viewer coordinates>> <<- compute area of viewer that is part of the old and new view as the intersection between the viewer's client area and the same offsetted (dstBltRect), translate result back by the offset to get srcBltRect>> <<- Blit the right area (under Terminal lock to suppress cursor if color display)>> <<- Enumerate the rectangles of the viewer client space that need repaint, convert them back conservatively to CD coordinates>> <<- If the move could not be done fast, re-queue a regular redraw (a null move results in a full repaint to undo any wedging that might occur) and return>> <<- Set the new scale in effect>> <<- For each rectangle that needs repaint, erase it and queue a redraw command. The erasing is done first to make the display look cleaner to the user... The rectangles are erased twice, but this is necessary to avoid some wedging (pop out of cell and move fast immediately) >> ProtectedAction: PROC [vRef: VRef] ~ { <> FrameBaseOfViewerRect: PROC [r: CD.Rect] RETURNS [SF.Vec] ~ INLINE { <> RETURN [[ s: vRef.frame.height-vRef.viewer.wy-r.y2, f: vRef.viewer.wx+r.x1 ]]; }; Blit: PROC [] ~ { -- Move bits around ImagerSample.Move[ map: ImagerSample.MapFromFrameBuffer[vRef.frame], dstMin: FrameBaseOfViewerRect[dstBltRect], srcMin: FrameBaseOfViewerRect[srcBltRect], size: [s: srcBltRect.y2-srcBltRect.y1, f: srcBltRect.x2-srcBltRect.x1], function: ImagerSample.nullFunction]; }; WillRepaint: PROC [vr: CD.Rect--viewer coordinates--] ~ { <> toRepaint _ CONS [CD.Rect[ x1: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.x1]+vRef.intendedScale.off.x-1, y1: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.y1]+vRef.intendedScale.off.y-1, x2: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.x2]+vRef.intendedScale.off.x+1, y2: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.y2]+vRef.intendedScale.off.y+1 ], toRepaint]; }; clientRect, srcBltRect, dstBltRect: CD.Rect; offset: CD.Position; <<>> <> IF vRef.scale.nscale#vRef.intendedScale.nscale OR vRef.scale.off=vRef.intendedScale.off THEN RETURN; -- do a regular redraw <> clientRect _ [x1: vRef.viewer.cx, y1: vRef.viewer.cy, x2: vRef.viewer.cx+vRef.viewer.cw, y2: vRef.viewer.cy+vRef.viewer.ch]; -- viewer client rect in viewer coords offset _ CDVScale.DesignToViewerPosition[vRef.intendedScale, vRef.scale.off]; dstBltRect _ CDBasics.Intersection[clientRect, CDBasics.MoveRect[clientRect, offset]]; srcBltRect _ CDBasics.MoveRect[dstBltRect, CDBasics.NegOffset[offset]]; <> IF vRef.display=bw THEN Blit[] ELSE Terminal.ModifyColorFrame[vt: InterminalBackdoor.terminal, action: Blit]; <> CDBasics.DecomposeRect[r: clientRect, test: dstBltRect, outside: WillRepaint]; }; -- End of ProtectedAction toRepaint: LIST OF CD.Rect _ NIL; -- when NIL, means repaint all, erase and paint each rect req: REF CDDrawQueue.Request _ NARROW[key]; scale: CDVScale.ScaleRec _ me.scale; off: CD.Position; mod: CD.Number; <> mod _ MAX[CDVScale.ViewerToDesignScalar[scale, 4], 1]; IF scale.grid>1 THEN mod _ mod/GCD[mod, scale.grid]*scale.grid; off _ [scale.off.x-req.rect.x1/mod*mod, scale.off.y-req.rect.y1/mod*mod]; me.intendedScale _ CDVScale.MakeScale[off: off, nscale: scale.nscale, grid: scale.grid]; CDDrawQueue.Flush[me.ct]; CDVPrivate.DoInsideMonitor[ProtectedAction, me]; IF toRepaint=NIL THEN { -- cannot do a fast move, do a repaint and quit. CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]]; RETURN; }; <> CDVPrivate.ResetDrawScale[me]; <> WHILE toRepaint#NIL DO CDVPrivate.RepaintBackground[me, toRepaint.first, TRUE]; --immediate CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, toRepaint.first]];--delayed toRepaint _ toRepaint.rest; ENDLOOP; }; GetViewerInt: PROC [viewer: ViewerClasses.Viewer, at: ATOM] RETURNS [i: INT _ -1] = { WITH ViewerOps.GetViewer[viewer, at] SELECT FROM ri: REF INT => i _ ri^; ENDCASE => NULL; }; GridComm: PROC [comm: CDSequencer.Command] = { GridRope: PROC [v: ViewerClasses.Viewer] RETURNS [r: Rope.ROPE] = { r _ CDOps.LambdaRope[GetViewerInt[viewer, $Grid], lambda] }; g: INT _ -1; lambda: INT _ comm.design.technology.lambda; viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF viewer=NIL THEN TerminalIO.PutRope["no viewer\n"] ELSE { IF comm.key=$GridDouble THEN g _ GetViewerInt[viewer, $Grid]*2 ELSE IF comm.key=$GridHalf THEN g _ GetViewerInt[viewer, $Grid]/2 ELSE { TerminalIO.PutF1["grid command (current grid = %g)\n", [rope[GridRope[viewer]]]]; SELECT PopUpSelection.Request[ choice: LIST[" 1", " 2", " 4", " 8", "16", "1/2", "default", "type lambda", "type int", "move selected to grid", "TICKS"], header: "grid", headerDoc: "grid = distance used for snapping the cursor"] FROM 1 => g _ lambda; 2 => g _ 2*lambda; 3 => g _ 4*lambda; 4 => g _ 8*lambda; 5 => g _ 16*lambda; 6 => g _ lambda/2; 7 => g _ CDValue.FetchInt[boundTo: CDViewer.DesignOf[viewer], key: $CDxInitGrid, propagation: global]; 8 => g _ MIN[INT[2600/lambda], TerminalIO.RequestInt["grid: "]]*lambda; 9 => g _ MIN[INT[2600], TerminalIO.RequestInt["grid: "]]; 10 => {MoveToGridComm[comm]; RETURN}; 11 => {CDSequencer.ExecuteCommand[key: $TicksInfo, comm: comm]; RETURN}; ENDCASE => g _ -1; }; IF g>0 AND g<=2600 THEN { ViewerOps.SetViewer[viewer: viewer, data: NEW[INT_g], op: $Grid]; TerminalIO.PutF1[" grid set to %g \n", IO.rope[CDOps.LambdaRope[g, lambda]]]; } ELSE TerminalIO.PutRope[" failed \n"]; }; }; ChangeGridComm: PROC [comm: CDSequencer.Command] = { viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; }; SetSimplificationComm: PROC[comm: CDSequencer.Command] = { Do: PROC[vRef: VRef] = { n: INT; CDDrawQueue.Flush[vRef.ct]; n _ PopUpSelection.Request[ choice: LIST["very simplified", "simplified", "standard", "detailed", "very detailed", "show all"], header: "viewer simplification treshold", headerDoc: "the viewer simplification treshold is multiplied with the cell simplification treshold" ]; SELECT n FROM 1 => vRef.suppressFactorForCells _ 0.4; 2 => vRef.suppressFactorForCells _ 0.7; 3 => vRef.suppressFactorForCells _ 1; 4 => vRef.suppressFactorForCells _ 1.6; 5 => vRef.suppressFactorForCells _ 2.6; 6 => vRef.suppressFactorForCells _ 0; ENDCASE => RETURN; Repaint[vRef] }; TerminalIO.PutRope["set viewer simplification threshold\n"]; DoWithVRef[comm, Do] }; InstanceNames: PROC [comm: CDSequencer.Command] = { v: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm]; TerminalIO.PutRope["display instance names\n"]; IF v#NIL THEN ViewerOps.PaintViewer[v, client, FALSE, $DrawInstanceNames] }; SignalNames: PROC [comm: CDSequencer.Command] = { v: ViewerClasses.Viewer = CDViewer.GetViewer[comm]; TerminalIO.PutRope["display signal names\n"]; IF v#NIL THEN ViewerOps.PaintViewer[v, client, FALSE, $DrawSignalNames] }; GetOppositViewer: PROC [comm: CDSequencer.Command] RETURNS [ViewerClasses.Viewer] = { <<--gets viewer on different screen if possible,>> <<--else different viewer, if possible...>> vl: CDViewer.ViewerList = CDViewer.ViewersOf[comm.design]; viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm]; onColor: BOOL = (viewer=NIL OR viewer.column=color); FOR l: CDViewer.ViewerList _ vl, l.rest WHILE l#NIL DO IF ~l.first.iconic THEN IF (l.first.column=color)#onColor THEN RETURN [l.first]; ENDLOOP; FOR l: CDViewer.ViewerList _ vl, l.rest WHILE l#NIL DO IF ~l.first.iconic THEN IF l.first.column#viewer.column THEN RETURN [l.first]; ENDLOOP; FOR l: CDViewer.ViewerList _ vl, l.rest WHILE l#NIL DO IF ~l.first.iconic THEN IF l.first#viewer THEN RETURN [l.first]; ENDLOOP; RETURN [viewer]; }; ShowRectX: PROC [comm: CDSequencer.Command] = { SmallScale: PROC [comm: CDSequencer.Command] RETURNS [BOOL] = { min: CD.Number = 30; RETURN [min>ABS[comm.pos.x-comm.sPos.x] AND min>ABS[comm.pos.y-comm.sPos.y]] }; viewer: ViewerClasses.Viewer ~ GetOppositViewer[comm]; TerminalIO.PutRope["position a viewer\n"]; IF viewer#NIL THEN IF SmallScale[comm] THEN CDViewer.ShowPosition[viewer: viewer, pos: comm.sPos] ELSE CDViewer.ShowAndScale[viewer: viewer, rect: CDBasics.ToRect[comm.pos, comm.sPos]]; }; RestoreViewComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["restore previous scale\n"]; RestoreScale[CDViewer.GetViewer[comm]]; }; ShowRect: PROC [comm: CDSequencer.Command] = { viewer: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm]; TerminalIO.PutRope["scale viewer"]; SaveScale[viewer]; IF comm.pos=comm.sPos THEN CDViewer.ShowPosition[viewer, comm.pos] ELSE CDViewer.ShowAndScale[viewer, CDBasics.ToRect[comm.pos, comm.sPos]]; WriteLnScale[viewer]; }; ResetScaleComm: PROC [comm: CDSequencer.Command] = { ResetScaleAll: PROC [viewer: ViewerClasses.Viewer] = { b: CD.Rect; TerminalIO.PutRope["reset scale (view all)"]; b _ CDOps.BoundingBox[CDViewer.DesignOf[viewer]]; IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b]; WriteLnScale[viewer]; }; viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF viewer#NIL THEN { SaveScale[viewer]; ResetScaleAll[viewer]; }; }; ResetScaleToSelectedComm: PROC [comm: CDSequencer.Command] = { viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm]; TerminalIO.PutRope["reset scale to selection"]; IF viewer#NIL THEN { b: CD.Rect _ CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: TRUE]; IF CDBasics.NonEmpty[b] THEN { SaveScale[viewer]; CDViewer.ShowAndScale[viewer: viewer, rect: b]; WriteLnScale[viewer]; RETURN; }; }; TerminalIO.PutRope[" no selection\n"]; }; ResetScaleToPushedComm: PROC [comm: CDSequencer.Command] = { viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm]; IF viewer#NIL THEN { b: CD.Rect; SaveScale[viewer]; TerminalIO.PutRope["reset scale (to view all of pushed cell)"]; b _ CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: FALSE]; IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b]; WriteLnScale[viewer]; }; }; ShowViewersComm: PROC [comm: CDSequencer.Command] = { Do: PROC[vRef: VRef] = { CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$ShowViewers, CDBasics.universe]]; }; TerminalIO.PutRope["show viewers\n"]; DoWithVRef[comm, Do] }; SplitViewer: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["split viewer\n"]; [] _ CDViewer.CreateViewer[comm.design, FALSE] }; SetCellSimplification: PROC [comm: CDSequencer.Command] = { Do: PROC[vRef: VRef] = { scale: CDVScale.ScaleRec _ vRef.scale; FOR l: CD.InstanceList _ CDOps.InstList[comm.design], l.rest WHILE l#NIL DO IF l.first.selected AND CDCells.IsCell[l.first.ob] THEN { simplifyOn: CD.Number _ CDVScale.DesignToViewerScalar[scale, l.first.ob.bbox.y2-l.first.ob.bbox.y1]; CDCells.SetSimplificationTreshhold[l.first.ob, simplifyOn, TRUE]; CDOps.RedrawInstance[comm.design, l.first]; }; ENDLOOP; }; TerminalIO.PutRope["put visibility threshold to current scale\n"]; DoWithVRef[comm, Do] }; EnforcePanel: PROC [comm: CDSequencer.Command] = { v: ViewerClasses.Viewer; TerminalIO.PutRope["enforce a control panel\n"]; v _ CDPanel.Create[comm.design]; IF v#NIL THEN { IF v.iconic THEN ViewerOps.OpenIcon[v] ELSE ViewerOps.BlinkIcon[v, 1, 1, 200] }; }; FontSubstOnComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: substitute tioga fonts"]; IF vRef#NIL THEN { vRef.fontSubstitution _ TRUE; CDProperties.PutProp[comm.design, $CDxSubstituteFonts, $TRUE]; Repaint[vRef]; }; }; FontSubstOffComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: don't substitute tioga fonts"]; IF vRef#NIL THEN { vRef.fontSubstitution _ FALSE; CDProperties.PutProp[comm.design, $CDxSubstituteFonts, NIL]; Repaint[vRef]; }; }; DrawEnvComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: draw environment of pushed cells"]; IF vRef#NIL THEN { vRef.environment _ TRUE; CDProperties.PutProp[comm.design, $CDxDrawEnvironment, NIL]; Repaint[vRef]; }; }; DontDrawEnvComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: don't draw environment of pushed cells"]; IF vRef#NIL THEN { vRef.environment _ FALSE; CDProperties.PutProp[comm.design, $CDxDrawEnvironment, $FALSE]; Repaint[vRef]; }; }; DrawSymbolicsComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: draw symbolic objects"]; IF vRef#NIL THEN { vRef.symbolics _ TRUE; CDProperties.PutProp[comm.design, $CDxDrawSymbolics, NIL]; Repaint[vRef]; }; }; DontDrawSymbolicsComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: don't draw symbolic objects"]; IF vRef#NIL THEN { vRef.symbolics _ FALSE; CDProperties.PutProp[comm.design, $CDxDrawSymbolics, $FALSE]; Repaint[vRef]; }; }; DrawBordersComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: draw with borders"]; IF vRef#NIL THEN { vRef.borders _ TRUE; CDProperties.PutProp[comm.design, $CDxSkipBorder, $FALSE]; Repaint[vRef]; }; }; DontDrawBordersComm: PROC [comm: CDSequencer.Command] = { vRef: VRef _ MsgAndVRef[comm, "viewer drawmode: don't draw borders"]; IF vRef#NIL THEN { vRef.borders _ FALSE; CDProperties.PutProp[comm.design, $CDxSkipBorder, NIL]; Repaint[vRef]; }; }; CheckEdited: PROC [design: CD.Design] = { IF design#NIL THEN { edited: BOOL _ design.edited; FOR vl: CDViewer.ViewerList _ CDViewer.ViewersOf[design], vl.rest WHILE vl#NIL DO IF vl.first.newVersion#edited THEN { vl.first.newVersion _ edited; ViewerOps.PaintViewer[vl.first, caption] }; ENDLOOP } }; CheckEditedEvent: CDEvents.EventProc = { TRUSTED {Process.Detach[FORK CheckEdited[design]]}; }; NoteProfileChange: UserProfile.ProfileChangedProc = { IF reason=edit THEN { FOR vl: CDViewer.ViewerList _ CDViewer.ViewersOf[NIL], vl.rest WHILE vl#NIL DO d: CD.Design _ CDViewer.DesignOf[vl.first]; IF d#NIL THEN vl.first.tipTable _ CDEnvironment.GetTipTable[d]; ENDLOOP }; }; MoveToGridComm: PROC [comm: CDSequencer.Command] = { selCnt, movCnt: INT _ 0; grid: CD.Number _ CDOps.GetGrid[comm.design, comm]; TerminalIO.PutRope["move (interest rect) to grid positions;"]; IF grid<1 THEN {TerminalIO.PutRope["failed: bad grid value"]; RETURN}; FOR l: CD.InstanceList _ CDOps.InstList[comm.design], l.rest WHILE l#NIL DO IF l.first.selected THEN { pos: CD.Position _ CDBasics.BaseOfRect[CDInstances.InstRectI[l.first]]; gridded: CD.Position _ [(pos.x)/grid*grid, (pos.y)/grid*grid]; selCnt _ selCnt+1; IF gridded#pos THEN { CDSequencer.MarkChanged[comm.design]; CDOps.RedrawInstance[comm.design, l.first]; l.first.trans.off _ CDBasics.AddPoints[l.first.trans.off, CDBasics.SubPoints[gridded, pos]]; CDOps.RedrawInstance[comm.design, l.first, FALSE]; movCnt _ movCnt+1; }; }; ENDLOOP; TerminalIO.PutF[" %g selected, %g moved objects\n", [integer[selCnt]], [integer[movCnt]]]; }; ShowViewers: CDViewerBackdoor.FurtherPaintProc = { <<--monitored by ProtectedRepaint>> OutlineViewer: PROC [me: CDVPrivate.VRef, other: ViewerClasses.Viewer] = { otherMe: CDVPrivate.VRef = NARROW[other.data]; r: CD.Rect = otherMe.dClip; p1: CD.Position = CDVScale.DesignToViewerPosition[me.scale, [r.x1, r.y1]]; p2: CD.Position = CDVScale.DesignToViewerPosition[me.scale, [r.x2, r.y2]]; CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x+1, p2.y]; CDVPrivate.InvertArea[me, p1.x, p2.y, p2.x, p2.y+1]; CDVPrivate.InvertArea[me, p2.x, p2.y, p2.x+1, p1.y]; CDVPrivate.InvertArea[me, p2.x, p1.y, p1.x, p1.y+1]; }; FOR l: CDViewer.ViewerList _ CDViewer.ViewersOf[me.actualDesign], l.rest WHILE l#NIL DO IF ~l.first.iconic AND l.first#me.viewer THEN OutlineViewer[me: me, other: l.first]; ENDLOOP }; PaintSignalNames: CDViewerBackdoor.FurtherPaintProc = { <<--monitored by ProtectedRepaint>> PaintProperties[me, $SignalName] }; PaintInstanceNames: CDViewerBackdoor.FurtherPaintProc = { <<--monitored by ProtectedRepaint>> PaintProperties[me, $InstanceName] }; IgnoreContext: CD.DrawContextProc = {}; PaintProperties: PROC [me: CDVPrivate.VRef, key: ATOM] = { nameDevice: REF NameDevice _ NEW[NameDevice_[propKey: key, vPriv: me]]; internalPr: CD.DrawRef = CD.CreateDrawRef[[ design: me.actualDesign, interestClip: me.dClip, devicePrivate: nameDevice, drawChild: NamedDrawChild, drawRect: CDDefaultProcs.IgnoreRect, drawContext: IgnoreContext, stopFlag: me.stoprequest ]]; Imager.SetColor[me.viewContext, Imager.black]; Imager.SetFont[me.viewContext, defaultFont]; CDOps.DrawDesign[me.actualDesign, internalPr]; }; <<>> NameDevice: TYPE = RECORD [propKey: ATOM, vPriv: CDVPrivate.VRef]; defaultFont: Imager.Font = VFonts.DefaultFont[]; NamedDrawChild: CD.DrawProc = { dev: REF NameDevice = NARROW[pr.devicePrivate]; text: Rope.ROPE _ NIL; ob.class.drawMe[pr, ob, trans, readOnlyInstProps]; WITH CDProperties.GetListProp[readOnlyInstProps, dev.propKey] SELECT FROM r: Rope.ROPE => text _ r; a: ATOM => text _ Atom.GetPName[a]; ENDCASE => NULL; IF text#NIL THEN { r: CD.Rect _ CDBasics.MapRect[CD.InterestRect[ob], trans]; p: CD.Position _ CDVScale.DesignToViewerPosition[dev.vPriv.scale, CDBasics.BaseOfRect[r]]; Imager.SetXY[dev.vPriv.viewContext, [p.x+1, p.y+1]]; Imager.SetColor[dev.vPriv.viewContext, Imager.black]; Imager.SetFont[dev.vPriv.viewContext, defaultFont]; Imager.ShowRope[dev.vPriv.viewContext, text]; }; }; DrawSignalNames: CDViewerBackdoor.FurtherPaintProc = { <<-- called from anywhere, not monitored>> CDDrawQueue.QueueInsertDrawCommand[me.ct, [$SignalNames, CDBasics.universe]]; }; DrawInstanceNames: CDViewerBackdoor.FurtherPaintProc = { <<-- called from anywhere, not monitored>> CDDrawQueue.QueueInsertDrawCommand[me.ct, [$InstanceNames, CDBasics.universe]]; }; UserProfile.CallWhenProfileChanges[NoteProfileChange]; CDPanel.Button[tech: NIL, button: [text: "stop"], command: $AbortCommand, queue: dontQueue, topLine: TRUE]; CDPanel.Button[tech: NIL, button: [text: "split"], proc: SplitViewer, queue: dontQueue, topLine: TRUE]; CDSequencer.ImplementCommand[$ScaleLessDetail, ScaleDown,, dontQueue]; CDSequencer.ImplementCommand[$ScaleMoreDetail, ScaleUp,, dontQueue]; CDSequencer.ImplementCommand[$MoveScreen, MoveScreenCmd,, dontQueue]; CDSequencer.ImplementCommand[$DisplayNames, SignalNames,, doQueue]; CDSequencer.ImplementCommand[$DisplayInstanceNames, InstanceNames,, doQueue]; CDSequencer.ImplementCommand[$ShowRectX, ShowRectX,, dontQueue]; CDSequencer.ImplementCommand[$ShowRect, ShowRect,, dontQueue]; CDSequencer.ImplementCommand[$ResetScaleAll, ResetScaleComm,, dontQueue]; CDSequencer.ImplementCommand[$ResetScaleTop, ResetScaleToPushedComm,, dontQueue]; CDSequencer.ImplementCommand[$ResetScaleSel, ResetScaleToSelectedComm,, dontQueue]; CDSequencer.ImplementCommand[$DisplayViewers, ShowViewersComm,, doQueue]; CDSequencer.ImplementCommand[$SplitViewer, SplitViewer,, dontQueue]; CDSequencer.ImplementCommand[$GridInfo, GridComm,, doQueue]; CDSequencer.ImplementCommand[$GridDouble, GridComm,, doQueue]; CDSequencer.ImplementCommand[$GridHalf, GridComm,, doQueue]; CDSequencer.ImplementCommand[$SetSimplification, SetSimplificationComm,, dontQueue]; CDSequencer.ImplementCommand[$RestoreScale, RestoreViewComm,, dontQueue]; CDSequencer.ImplementCommand[$SetCellSimplification, SetCellSimplification]; CDSequencer.ImplementCommand[$EnforcePanel, EnforcePanel,, doQueue]; CDSequencer.ImplementCommand[$ViewFSub, FontSubstOnComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewNFSub, FontSubstOffComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewEnv, DrawEnvComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewNEnv, DontDrawEnvComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewSym, DrawSymbolicsComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewNSym, DontDrawSymbolicsComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewBord, DrawBordersComm,, dontQueue]; CDSequencer.ImplementCommand[$ViewNBord, DontDrawBordersComm,, dontQueue]; CDSequencer.ImplementCommand[$MoveToGrid, MoveToGridComm, NIL, doQueue]; CDEvents.RegisterEventProc[event: $AfterOutput, proc: CheckEditedEvent]; CDEvents.RegisterEventProc[event: $CheckEdited, proc: CheckEditedEvent]; <<--protected procedures>> CDViewerBackdoor.InstallFurtherPaint[keyValue: $ShowViewers, proc: ShowViewers]; CDViewerBackdoor.InstallFurtherPaint[keyValue: $SignalNames, proc: PaintSignalNames]; CDViewerBackdoor.InstallFurtherPaint[keyValue: $InstanceNames, proc: PaintInstanceNames]; <<--unprotected procedures>> CDViewerBackdoor.InstallFurtherPaint[keyValue: $DrawSignalNames, proc: DrawSignalNames]; CDViewerBackdoor.InstallFurtherPaint[keyValue: $DrawInstanceNames, proc: DrawInstanceNames]; CDViewerBackdoor.InstallFurtherPaint[keyValue: $fastMoveScreen, proc: DoMoveScreen]; END.