CDVCursor.mesa
by Christian Jacobi August 5, 1983 11:07 am
last edited by Christian Jacobi October 14, 1983 6:03 pm
DIRECTORY
CD,
CDTechnology,
CDVPrivate,
Graphics,
RuntimeError,
PrincOpsUtils,
TerminalExtras,
Basics,
Terminal,
ViewerClasses;
CDVCursor: CEDAR MONITOR
IMPORTS CDTechnology, CDVPrivate, Graphics, RuntimeError, PrincOpsUtils, TerminalExtras, Terminal
EXPORTS CDVPrivate =
BEGIN
lambda: CD.DesignNumber = CD.lambda;
MyGraphicRef: TYPE = CDVPrivate.MyGraphicRef;
ViewerPos2:
PROC [me: MyGraphicRef]
RETURNS [
CD.Position] =
INLINE {
RETURN [CDVPrivate.DesignToViewerPosition[me, me.stopVC]];
};
ViewerPos1:
PROC [me: MyGraphicRef]
RETURNS [
CD.Position] =
INLINE {
RETURN [CDVPrivate.DesignToViewerPosition[me, me.startVC]];
};
SetModeInvertBlack:
PROC[me: MyGraphicRef] =
INLINE {
Graphics.SetColor[me.viewerContext, Graphics.black];
[] ← Graphics.SetPaintMode[me.viewerContext, invert];
};
PosCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
p2: CD.Position~ViewerPos2[me];
SetModeInvertBlack[me];
Graphics.SetCP[me.viewerContext, p2.x-8, p2.y-8];
Graphics.DrawTo[me.viewerContext, p2.x+8, p2.y+8];
Graphics.SetCP[me.viewerContext, p2.x+8, p2.y-8];
Graphics.DrawTo[me.viewerContext, p2.x-8, p2.y+8];
END;
ShadowCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
p2: CD.Position~ViewerPos2[me];
CDVPrivate.InvertArea[me, p2.x-3, p2.y, p2.x+3, p2.y];
CDVPrivate.InvertArea[me, p2.x, p2.y-3, p2.x, p2.y+3];
END;
DontCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
p2: CD.Position~ViewerPos2[me];
CDVPrivate.InvertArea[me, p2.x-8, p2.y, p2.x+8, p2.y];
CDVPrivate.InvertArea[me, p2.x, p2.y-8, p2.x, p2.y+8];
END;
LineCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
p1: CD.Position~ViewerPos1[me];
p2: CD.Position~ViewerPos2[me];
SetModeInvertBlack[me];
Graphics.SetCP[me.viewerContext, p1.x, p1.y];
Graphics.DrawTo[me.viewerContext, p2.x, p2.y];
END;
BoxCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
ENABLE RuntimeError.
UNCAUGHT => {
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO SomeError ELSE REJECT;
};
p1: CD.Position~ViewerPos1[me];
p2: CD.Position~ViewerPos2[me];
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x, p2.y];
CDVPrivate.InvertArea[me, p1.x, p2.y, p2.x, p2.y];
CDVPrivate.InvertArea[me, p2.x, p2.y, p2.x, p1.y];
CDVPrivate.InvertArea[me, p2.x, p1.y, p1.x, p1.y];
END;
LCursor:
PUBLIC
PROC[me: MyGraphicRef] =
BEGIN
ENABLE RuntimeError.
UNCAUGHT => {
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO SomeError ELSE REJECT;
};
yi, yo, xi, xo: INT; --i=inner, o=outer, if p1 considered center
wireWidth:
CD.Number =
MAX[CDVPrivate.ScaleDesignToViewer[me, me.defaultWidthVC], 1];
p1: CD.Position = ViewerPos1[me];
p2: CD.Position = ViewerPos2[me];
IF me.firstHorizontalVC
THEN {
IF p2.x<=p1.x
AND p2.x>=p1.x-wireWidth
AND (p2.y<p1.y OR p2.y>p1.y+wireWidth) THEN { -- sorry, only vertical, p2.x ignored
CDVPrivate.InvertArea[me, p1.x, p2.y, p1.x, p1.y];
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x+wireWidth, p1.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p1.y, p1.x+wireWidth, p2.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p2.y, p1.x, p2.y];
RETURN
};
IF p2.x>=p1.x THEN {xi ← p2.x; xo ← xi+wireWidth}
ELSE {xo ← p2.x; xi ← xo+wireWidth};
IF p2.y<p1.y
THEN {
-- L shaped, down
CDVPrivate.InvertArea[me, p1.x, p1.y, xi, p1.y];
CDVPrivate.InvertArea[me, xi, p1.y, xi, p2.y];
CDVPrivate.InvertArea[me, xi, p2.y, xo, p2.y];
CDVPrivate.InvertArea[me, xo, p2.y, xo, p1.y+wireWidth];
CDVPrivate.InvertArea[me, xo, p1.y+wireWidth, p1.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p1.x, p1.y+wireWidth, p1.x, p1.y];
RETURN
};
IF p2.y>p1.y+wireWidth
THEN {
-- L shaped, up
CDVPrivate.InvertArea[me, p1.x, p1.y, xo, p1.y];
CDVPrivate.InvertArea[me, xo, p1.y, xo, p2.y];
CDVPrivate.InvertArea[me, xo, p2.y, xi, p2.y];
CDVPrivate.InvertArea[me, xi, p2.y, xi, p1.y+wireWidth];
CDVPrivate.InvertArea[me, xi, p1.y+wireWidth, p1.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p1.x, p1.y+wireWidth, p1.x, p1.y];
RETURN
};
-- only horizontal
CDVPrivate.InvertArea[me, p1.x, p1.y, p2.x, p1.y];
CDVPrivate.InvertArea[me, p2.x, p1.y, p2.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p2.x, p1.y+wireWidth, p1.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p1.x, p1.y+wireWidth, p1.x, p1.y];
}
ELSE
-- NOT me.firstHorizontalVC -- {
IF p2.y<=p1.y
AND p2.y>=p1.y-wireWidth
AND (p2.x<p1.x OR p2.x>p1.x+wireWidth) THEN { -- sorry, only horizontal, p2.y ignored
CDVPrivate.InvertArea[me, p2.x, p1.y, p1.x, p1.y];
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p1.x, p1.y+wireWidth, p2.x, p1.y+wireWidth];
CDVPrivate.InvertArea[me, p2.x, p1.y+wireWidth, p2.x, p1.y];
RETURN
};
IF p2.y>=p1.y THEN {yi ← p2.y; yo ← yi+wireWidth}
ELSE {yo ← p2.y; yi ← yo+wireWidth};
IF p2.x<p1.x
THEN {
-- L shaped, left
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x, yi];
CDVPrivate.InvertArea[me, p1.x, yi, p2.x, yi];
CDVPrivate.InvertArea[me, p2.x, yi, p2.x, yo];
CDVPrivate.InvertArea[me, p2.x, yo, p1.x+wireWidth, yo];
CDVPrivate.InvertArea[me, p1.x+wireWidth, yo, p1.x+wireWidth, p1.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p1.y, p1.x, p1.y];
RETURN
};
IF p2.x>p1.x+wireWidth
THEN {
-- L shaped, right
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x, yo];
CDVPrivate.InvertArea[me, p1.x, yo, p2.x, yo];
CDVPrivate.InvertArea[me, p2.x, yo, p2.x, yi];
CDVPrivate.InvertArea[me, p2.x, yi, p1.x+wireWidth, yi];
CDVPrivate.InvertArea[me, p1.x+wireWidth, yi, p1.x+wireWidth, p1.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p1.y, p1.x, p1.y];
RETURN
};
-- only vertical
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x, p2.y];
CDVPrivate.InvertArea[me, p1.x, p2.y, p1.x+wireWidth, p2.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p2.y, p1.x+wireWidth, p1.y];
CDVPrivate.InvertArea[me, p1.x+wireWidth, p1.y, p1.x, p1.y];
};
END;
SetCursorMode:
PUBLIC
PROC[me: MyGraphicRef, mode: CDVPrivate.CursorMode] =
--sets modeLC, outlineProcLC
BEGIN
me.designRec.modeLC ← mode;
SELECT mode
FROM
cLBox => {
l: CD.Level = CDTechnology.CurrentLevel[me.actualDesign];
w: CD.DesignNumber = CDTechnology.LevelWidth[me.actualDesign, l];
me.designRec.outlineProcLC ← IF w>0 THEN LCursor ELSE BoxCursor
};
cBox => me.designRec.outlineProcLC ← BoxCursor;
cArrow => me.designRec.outlineProcLC ← LineCursor;
cPos => me.designRec.outlineProcLC ← PosCursor;
cDont => me.designRec.outlineProcLC ← DontCursor;
ENDCASE => me.designRec.outlineProcLC ← ShadowCursor;
END;
virtual: Terminal.Virtual = Terminal.Current[];
InvertArea:
PUBLIC
PROC[me: MyGraphicRef, x1, y1, x2, y2:
INT] =
--x1, y1, x2, y2 in viewers coordinates; inverts all the border points
TRUSTED BEGIN
ENABLE RuntimeError.
UNCAUGHT => {
errrorReport.text ← "InvertArea";
errrorReport.me ← me;
errrorReport.r←[x1: x1, x2: x2, y1: y1, y2: y2];
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO SomeError ELSE REJECT;
};
xBit: CARDINAL;
coordSys: ViewerClasses.CoordSys = bottom;
xc1: CARDINAL ← MIN[MAX[x1, 0], LONG[me.vwminus1]];
yc1: CARDINAL ← MIN[MAX[y1, 0], LONG[me.vhminus1]];
xc2: CARDINAL ← MIN[MAX[x2, 0], LONG[me.vwminus1]];
yc2: CARDINAL ← MIN[MAX[y2, 0], LONG[me.vhminus1]];
IF xc1>xc2 THEN {t: CARDINAL=xc1; xc1←xc2; xc2←t};
IF yc1>yc2 THEN {t: CARDINAL=yc1; yc1←yc2; yc2←t};
me.bBLT.width ← PrincOpsUtils.BITSHIFT[(xc2+1-xc1), me.logbpp];
me.bBLT.height ← (yc2+1-yc1);
xBit ← PrincOpsUtils.BITSHIFT[(xc1+me.vx), me.logbpp];
yc1 ← IF coordSys=top THEN yc1+me.vy ELSE me.vy-yc2;
me.bBLT.dst ← [
me.screen
+ (LONG[yc1]*LONG[me.scWidthWords])
+ LONG[(xBit/Basics.bitsPerWord)],,
xBit MOD Basics.bitsPerWord
];
me.bBLT.flags.dstFunc ← xor; -- cursoring is monitored; no drawing!
IF me.bpp=1
THEN
PrincOpsUtils.BITBLT[me.bBLT]
ELSE {
TerminalExtras.LockColorFrame[vt: virtual,
xmin: xc1+me.vx,
ymin: yc1,
xmax: xc2+me.vx+1,
ymax: yc1+me.bBLT.height
];
PrincOpsUtils.BITBLT[me.bBLT];
TerminalExtras.UnlockColorFrame[virtual]
};
me.bBLT.flags.dstFunc ← null;
END;
END.