-- Compiler Caret/n
-- Tiberi October 31, 1979  8:47 PM

DIRECTORY
	CaretDefs: FROM "CaretDefs",
	ScreenDefs: FROM "ScreenDefs",
	PointDefs: FROM "PointDefs",
	ProcessDefs: FROM "ProcessDefs";

Caret: MONITOR IMPORTS ProcessDefs, ScreenDefs EXPORTS CaretDefs =
BEGIN OPEN CaretDefs, ProcessDefs, PointDefs;
caretOn: BOOLEAN ← FALSE;
process: PROCESS;
done: CONDITION;
caretShowing: BOOLEAN ← FALSE;
caretPatch: ARRAY [0..6) OF CARDINAL ←
	[010000B, 024000B, 024000B, 042000B, 042000B, 101000B];
caretPoint: PointDefs.ScrPt;
bitmap: ScreenDefs.Bitmap
	← [bank:0, nWords:1, nBits:7, nLines:6, bits:@caretPatch];
block: ScreenDefs.Block
	← [bitmap:@bitmap, w:7, h:5, lx:0, ty:0];

CaretAt: PUBLIC PROCEDURE[pt: PointDefs.ScrPt] =
BEGIN
SetCaretPt: PROCEDURE = BEGIN caretPoint ← [pt[X]-4, pt[Y]] END;
IF ~caretOn THEN
	BEGIN
	caretOn ← TRUE;
	caretShowing ← FALSE;
	process ← FORK BlinkCaret[];
	ProcessDefs.Detach[process];
	END;
WithCaretOff[do: SetCaretPt];
END;

CaretOff: PUBLIC ENTRY PROCEDURE =
BEGIN
caretOn ← FALSE;
NOTIFY done;
WAIT done;
END;

BlinkCaret: ENTRY PROCEDURE =
BEGIN
SetTimeout[@done, MsecToTicks[500]];
WHILE caretOn
	DO
	WAIT done;
	caretShowing ← ~caretShowing;
	IF caretShowing
		THEN SetTimeout[@done, MsecToTicks[800]]
		ELSE SetTimeout[@done, MsecToTicks[200]];
	InvertCaret;
	ENDLOOP;
IF caretShowing THEN InvertCaret;
NOTIFY done;
END;

WithCaretOff: PUBLIC ENTRY PROCEDURE [do: PROCEDURE] =
BEGIN
IF caretShowing THEN InvertCaret;
do[];
IF caretShowing THEN InvertCaret;
END;

InvertCaret: PROCEDURE =
BEGIN
ScreenDefs.BLTBlockInScreen [@block, caretPoint, invert];
END;

END.