CaretsImpl.mesa
Copyright © 1983, 1984 Xerox Corporation. All rights reserved.
Edited by McGregor on May 31, 1983 11:18 am
Last Edited by: Maxwell, May 19, 1983 1:24 pm
Last Edited by: Paul Rovner, June 15, 1983 4:57 pm
Doug Wyatt, September 4, 1984 11:54:07 am PDT
DIRECTORY
Carets,
CaretsExtras USING [],
Imager USING [Context, MaskPixel, PixelArray, SetColor],
ImagerOps USING [XOR],
Process USING [Detach, MsecToTicks, SetTimeout],
ViewerClasses USING [Viewer],
ViewerExtras USING [PaintClient];
CaretsImpl: CEDAR MONITOR
IMPORTS Imager, ImagerOps, Process, ViewerExtras
EXPORTS Carets, CaretsExtras
= BEGIN OPEN Carets;
timeOut: CONDITION;
caretH: INTEGER = 6;
caretW: INTEGER = 16;
caretXOffset: CARDINAL = 8;
CaretArray: TYPE = ARRAY [0..caretH) OF WORD;
pCaretArray: CaretArray ← [
000400B, -- 0000000100000000
001600B, -- 0000001110000000
003700B, -- 0000011111000000
003300B, -- 0000011011000000
006140B, -- 0000110001100000
004040B -- 0000100000100000
];
sCaretArray: CaretArray ← [
000400B, -- 0000000100000000
001200B, -- 0000001010000000
002100B, -- 0000010001000000
002100B, -- 0000010001000000
004040B, -- 0000100000100000
004040B -- 0000100000100000
];
pCaret: Imager.PixelArray ← NIL;
sCaret: Imager.PixelArray ← NIL;
TRUSTED { Imager.MaskBits[context: context, x: pX-caretXOffset, y: pY,
base: @pCaret, wpl: 1, fMin: 0, sMin: 0, fSize: caretW, sSize: caretH] };
pX, pY, sX, sY: INTEGER;
pDark, sDark: BOOLEANFALSE;
pCaretViewer, sCaretViewer: PUBLIC ViewerClasses.Viewer;
StartCaret: PUBLIC ENTRY PROC[viewer: ViewerClasses.Viewer, x, y: INTEGER, id: CaretId] = {
ENABLE UNWIND => NULL;
IF viewer = NIL THEN RETURN;
InvertCaret[id, TRUE]; -- kill off old visible caret
IF x =-10000 AND y =-10000 THEN SELECT id FROM -- special reset for ViewerBLTImpl to move viewers
primary => {x ← pX; y ← pY};
secondary => {x ← sX; y ← sY};
ENDCASE;
x ← MIN[x, viewer.cw];
SELECT id FROM
primary => { pX ← x; pY ← y; pCaretViewer ← viewer; };
secondary => { sX ← x; sY ← y; sCaretViewer ← viewer; };
ENDCASE;
Screw the NOTIFY; CaretProcess will eventually wake up and notice new caret
};
StopCaret: PUBLIC ENTRY PROC [id: CaretId] = BEGIN
ENABLE UNWIND => NULL;
InvertCaret[id, TRUE];
END;
caretHoldCount: INTEGER ← 0; -- number of requests pending to suspend caret
SuspendCarets: PUBLIC ENTRY PROC = BEGIN
ENABLE UNWIND => NULL;
IF pDark AND pCaretViewer#NIL THEN InvertCaret[primary];
IF sDark AND sCaretViewer#NIL THEN InvertCaret[secondary];
caretHoldCount ← caretHoldCount+1;
END;
SuspendVisibleCarets: PUBLIC ENTRY PROC = BEGIN -- exported to CaretsExtras
ENABLE UNWIND => NULL;
IF NOT pDark AND pCaretViewer#NIL THEN InvertCaret[primary];
IF NOT sDark AND sCaretViewer#NIL THEN InvertCaret[secondary];
caretHoldCount ← caretHoldCount+1;
END;
ResumeCarets: PUBLIC ENTRY PROC = BEGIN
ENABLE UNWIND => NULL;
caretHoldCount ← MAX[0, caretHoldCount-1];
END;
InvertCaret: INTERNAL PROC [id: CaretId, kill: BOOLFALSE] = BEGIN
SELECT id FROM
primary => {
IF (~kill OR pDark) AND pCaretViewer#NIL THEN {
action: PROC[context: Imager.Context] ~ {
Imager.SetColor[context, ImagerOps.XOR];
Imager.MaskPixel[context, pCaret];
};
ViewerExtras.PaintClient[pCaretViewer, action];
pDark ← ~pDark;
};
IF kill THEN pCaretViewer ← NIL;
};
secondary => {
action: PROC[context: Imager.Context] ~ {
Imager.SetColor[context, ImagerOps.XOR];
Imager.MaskPixel[context, sCaret];
};
IF (~kill OR sDark) AND sCaretViewer#NIL THEN {
ViewerExtras.PaintClient[sCaretViewer, action];
sDark ← ~sDark;
};
IF kill THEN sCaretViewer ← NIL;
};
ENDCASE;
END;
CaretProcess: ENTRY PROC = BEGIN
ENABLE UNWIND => NULL;
TRUSTED {Process.SetTimeout[@timeOut, Process.MsecToTicks[500]]};
DO WAIT timeOut;
IF caretHoldCount#0 THEN LOOP; -- suspended
IF pCaretViewer#NIL THEN InvertCaret[primary];
IF sCaretViewer#NIL THEN InvertCaret[secondary];
ENDLOOP;
END;
TRUSTED {Process.Detach[FORK CaretProcess]}; -- start the blinker
END.