CDVTicksImpl.mesa (part of ChipNDale)
Copyright © 1984, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, August 30, 1984 10:21:27 am PDT
Last edited by Christian Jacobi, March 3, 1987 2:44:39 pm PST
DIRECTORY
Basics USING [bitsPerWord, LongMult],
CD,
CDBasics,
CDDrawQueue,
CDOps,
CDProperties,
CDSequencer,
CDViewer,
CDViewerBackdoor,
CDVPrivate,
CDVScale,
CDVTicks,
InterminalBackdoor USING [terminal],
IO,
PrincOps USING [BBptr, BitAddress, BitBltFlags, SrcDesc, GrayParm],
PrincOpsUtils USING [BITBLT],
RuntimeError USING [UNCAUGHT],
Terminal,
TerminalIO,
ViewerClasses,
ViewerOps;
CDVTicksImpl:
CEDAR
MONITOR
IMPORTS Basics, CDDrawQueue, CDBasics, CDOps, CDProperties, CDSequencer, CDViewer, CDViewerBackdoor, CDVPrivate, CDVScale, InterminalBackdoor, IO, PrincOpsUtils, RuntimeError, Terminal, TerminalIO, ViewerOps
EXPORTS CDVTicks =
BEGIN
-- implement ticks for ChipNDale viewers
black: REF CARDINAL = NEW[CARDINAL←LAST[CARDINAL]];
virtual: Terminal.Virtual = InterminalBackdoor.terminal;
ModUp:
PROC [x, md:
CD.Number]
RETURNS [
CD.Number] =
INLINE {
RETURN [( IF x>0 THEN (x+md-1) ELSE (x) ) / md * md]
}; -- division rounds towards 0
ModDown:
PROC [x, md:
CD.Number]
RETURNS [
CD.Number] =
INLINE {
RETURN [( IF x>=0 THEN (x) ELSE (x-md+1) ) / md * md]
}; -- division rounds towards 0
PaintTicks: CDVPrivate.PainterProc = {
-- PROC [me: VRef, paintRef: REF PainterRec, interrestRect: CD.Rect];
ENABLE RuntimeError.
UNCAUGHT => {
IF CDVPrivate.ShallContinue[me, FALSE, "PaintTicks"] THEN GOTO oops
};
dTicks: CD.Number = NARROW[paintRef.data, REF CD.Number]^;
IF dTicks>0
THEN {
--action in procedure to make sure catching errors works
DrawTicks:
PROC [] =
BEGIN
vTicks: CD.Number = CDVScale.DesignToViewerScalar[me.scale, dTicks];
IF vTicks>6
AND vTicks<=512
THEN
TRUSTED {
x, xStop, xMod, xInc: INT;
yStart, yStop, yInc, yCur: LONG CARDINAL;
dr: CD.Rect = CDBasics.Intersection[me.deviceDrawRef.interestClip, paintRef.rect]; -- design coords
vr:
CD.Rect ← CDVScale.DesignToViewerRect[me.scale,
CD.Rect[
-- viewer coords
x1: ModDown[dr.x1, dTicks],
y1: ModDown[dr.y1, dTicks],
x2: ModUp[dr.x2, dTicks],
y2: ModUp[dr.y2, dTicks]
]];
vx1, vy1, vx2, vy2: CARDINAL; -- rect in V-coords; snapped to tick positions
vx1 ← IF vr.x1>=0 THEN vr.x1 ELSE vr.x1 + ModUp[-vr.x1, vTicks];
vy1 ← IF vr.y1>=0 THEN vr.y1 ELSE vr.y1 + ModUp[-vr.y1, vTicks];
vx2 ← IF vr.x2<=me.viewer.cw THEN vr.x2 ELSE vr.x2-ModUp[vr.x2-me.viewer.cw, vTicks];
vy2 ← IF vr.y2<=me.viewer.ch THEN vr.y2 ELSE vr.y2-ModUp[vr.y2-me.viewer.ch, vTicks];
-- Now v.. denotes area for ticks; vTicks denote increment; in viewer coordinates
me.xBBptr.width ← me.bpp;
me.xBBptr.height ← 1;
me.xBBptr.src ← [LOOPHOLE[black],,0];
me.xBBptr.srcDesc ← PrincOps.SrcDesc[gray[PrincOps.GrayParm[
yOffset: 0,
widthMinusOne: 0, --words
heightMinusOne: 0 --lines
]]];
me.xBBptr.flags ← PrincOps.BitBltFlags[
direction: forward,
disjoint: TRUE,
disjointItems: TRUE,
gray: TRUE,
srcFunc: null,
dstFunc: or
];
xInc ← vTicks*me.bpp;
x ← Basics.LongMult[vx1+me.vx, me.bpp]; --x start
xStop ← Basics.LongMult[vx2+me.vx, me.bpp];
yInc ← vTicks*me.scWidthWords;
yStart ← LOOPHOLE[me.screen + Basics.LongMult[(me.vy-vy2), me.scWidthWords] ];
yStop ← LOOPHOLE[me.screen + Basics.LongMult[(me.vy-vy1), me.scWidthWords] + xStop/Basics.bitsPerWord];
BEGIN
DoIt:
PROC [] =
TRUSTED {
WHILE x<=xStop
DO
yCur ← yStart+LOOPHOLE[(x/Basics.bitsPerWord), LONG CARDINAL];
xMod ← x MOD Basics.bitsPerWord;
WHILE yCur<=yStop
DO
me.xBBptr.dst ← [LOOPHOLE[yCur],, xMod];
PrincOpsUtils.BITBLT[me.xBBptr];
yCur ← yCur+yInc
ENDLOOP;
x ← x+xInc;
ENDLOOP;
};
IF me.bpp=1 THEN DoIt[] ELSE Terminal.ModifyColorFrame[virtual, DoIt];
END;
};
END;--DrawTicks
DrawTicks[];
}
EXITS oops => NULL
};
ShowTicks:
PUBLIC
PROC [onto:
REF, value:
INT𡤀] = {
--called from client
me: CDVPrivate.VRef;
WITH onto
SELECT
FROM
x: CDVPrivate.VRef => me ← x;
c: CDSequencer.Command => {ShowTicks[onto: c.ref, value: value]; RETURN};
v: ViewerClasses.Viewer => {ShowTicks[onto: v.data, value: value]; RETURN};
ENDCASE => RETURN;
IF me#
NIL
THEN {
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
value ← MIN[4096, MAX[0, value]];
pr.data ← NEW[CD.Number←value];
IF value=0 THEN CDVPrivate.RemoveAPainterRec[me, pr]
ELSE CDVPrivate.IncludeAPainterRec[me, pr];
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]]
}
};
GetAPainterRec:
ENTRY
PROC [me: CDVPrivate.VRef, create:
BOOL ←
TRUE]
RETURNS [pr:
REF CDVPrivate.PainterRec←
NIL] = {
ENABLE UNWIND => NULL;
x: REF = CDProperties.GetListProp[me.properties^, $CDxTickProc];
IF x#NIL THEN pr ← NARROW[x]
ELSE
IF create
THEN {
pr ← NEW[CDVPrivate.PainterRec←[proc: PaintTicks, rect: CDBasics.universe]];
CDProperties.PutProp[me.properties, $CDxTickProc, pr];
}
};
ToInt:
PROC [ref:
REF]
RETURNS [i:
INT𡤀] =
INLINE {
WITH ref
SELECT
FROM
ri: REF INT => i ← ri^
ENDCASE => NULL
};
GetTicks: ViewerClasses.GetProc = {
ticks: REF INT ← NEW[INT𡤀];
me: CDVPrivate.VRef = NARROW[self.data];
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
IF pr#NIL THEN ticks^ ← ToInt[pr.data];
data ← ticks
};
SetTicks: ViewerClasses.SetProc = {
ShowTicks[self, ToInt[data]]
};
TicksComm:
PROC[comm: CDSequencer.Command] = {
ticks, n: INT ← -2;
lambda: INT ← comm.design.technology.lambda;
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer=NIL THEN TerminalIO.PutRope["no viewer\n"]
ELSE {
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;
};
ticks ← GetViewerInt[viewer, $Ticks];
TerminalIO.PutF1["tick command (current ticks%g)\n", IO.rope[CDOps.LambdaRope[ticks, lambda]]];
n ← TerminalIO.RequestSelection[
choice: LIST["off", " 4", " 8", " 16", " 32", "type", "type int", "GRID"],
header: "Ticks",
headerDoc: "ticks = dots to help positioning",
dontLog: TRUE
];
ticks ← -2;
SELECT n
FROM
1 => ticks ← 0;
2 => ticks ← 4*lambda;
3 => ticks ← 8*lambda;
4 => ticks ← 16*lambda;
5 => ticks ← 32*lambda;
6 => {
n: INT ← TerminalIO.RequestInt["ticks: "];
IF n>=0 AND n<=LAST[INTEGER]/lambda-1 THEN ticks ← n*lambda
};
7 => {
n: INT ← TerminalIO.RequestInt["ticks (int): "];
IF n>=0 AND n<=LAST[INTEGER]-1 THEN ticks ← n
};
8 => {CDSequencer.ExecuteCommand[key: $GridInfo, comm: comm]; RETURN};
ENDCASE => NULL;
ViewerOps.SetViewer[viewer: viewer, data: NEW[INT←ticks], op: $Ticks];
IF ticks<-1 THEN TerminalIO.PutRope[" failed\n"]
ELSE IF ticks<=0 THEN TerminalIO.PutRope[" ticks off\n"]
ELSE TerminalIO.PutF1[" ticks set to %g \n", IO.rope[CDOps.LambdaRope[ticks, lambda]]]
};
};
CDViewerBackdoor.InstallGetProc[$Ticks, GetTicks];
CDViewerBackdoor.InstallSetProc[$Ticks, SetTicks];
CDSequencer.ImplementCommand[$TicksInfo, TicksComm,, doQueue];
END.