-- File: ExecKeyboard.mesa
-- edited by Levin, January 20, 1981 5:16 PM
-- edited by Brotz, December 1, 1980 11:30 AM.

DIRECTORY
csD: FROM "CoreStreamDefs",
Editor,
exD: FROM "ExceptionDefs",
inD: FROM "InteractorDefs",
Inline,
intCommon: FROM "intCommon",
KeyPrivate,
LaurelExecImpDefs,
ovD: FROM "OverviewDefs",
StreamDefs,
vmD: FROM "VirtualMgrDefs";

ExecKeyboard: MONITOR LOCKS KeyPrivate.monitor
IMPORTS csD, Editor, exD, Inline, intC: intCommon, KeyPrivate,
LaurelExecImpDefs, vmD
EXPORTS LaurelExecImpDefs
SHARES StreamDefs = PUBLIC

BEGIN

OPEN LaurelExecImpDefs;

selectionCS: csD.StreamHandle ← NIL;

InitSourceSelection: PROCEDURE =
BEGIN
selection: inD.TextSelection ← intC.source;
intC.source ← inD.TextSelection[cmMnp, 0, 0, 0, char, FALSE];
IF selection.start = selection.end THEN exD.SysBug[];
IF ~StuffIntoKeystream[@selection] THEN
BEGIN
oldPosition: csD.Position;
IF selectionCS = NIL THEN selectionCS ← csD.Open[NIL, byte, write, 1];
oldPosition ← csD.GetPosition[selectionCS];
csD.SetPosition[selectionCS, csD.GetLength[selectionCS]];
FOR i: ovD.CharIndex IN [selection.start .. selection.end-1) DO
csD.Write[selectionCS, Inline.BITAND
[vmD.GetMessageChar [selection.mnp.message, i], ovD.CharMask]];
ENDLOOP;
csD.Write[selectionCS, Inline.BITOR
[vmD.GetMessageChar[selection.mnp.message, selection.end-1],
ovD.LineBreakValue]];
csD.SetPosition[selectionCS, oldPosition];
PutCharIntoKeystream[takeFromSecondaryChar];
END;
Editor.DeUnderlineSelection[@selection, source];
END; -- of InitSourceSelection --

GetFromSourceSelection: PROCEDURE RETURNS [char: CHARACTER] =
BEGIN
char ← csD.Read[selectionCS];
IF csD.GetPosition[selectionCS] = csD.GetLength[selectionCS]
THEN csD.Reset[selectionCS];
END; -- of GetFromSourceSelection --

FlushSourceSelection: PROCEDURE =
BEGIN
IF selectionCS # NIL THEN {csD.Destroy[selectionCS]; selectionCS←NIL};
END; -- of FlushSourceSelection --

StuffIntoKeystream: ENTRY PROCEDURE[selection: inD.TextSelectionPtr]
RETURNS [BOOLEAN] =
BEGIN
breathingSpace: CARDINAL = 5;
selectionLength: CARDINAL = selection.end - selection.start;
ks: StreamDefs.KeyboardHandle = KeyPrivate.ks;
ksSpace: CARDINAL =
(IF ks.in >= ks.out THEN StreamDefs.KeyBufChars - (ks.in - ks.out)
ELSE ks.out - ks.in) - 1;
message: vmD.VirtualMessagePtr = selection.mnp.message;

IF selectionLength + breathingSpace > ksSpace THEN RETURN[FALSE];
FOR i: ovD.CharIndex IN [selection.start .. selection.end) DO
ks.buffer[ks.in] ← vmD.GetMessageChar[message, i];
ks.in ← (ks.in + 1) MOD StreamDefs.KeyBufChars;
ENDLOOP;
BROADCAST KeyPrivate.charactersAvailable;
RETURN[TRUE]
END;

PutCharIntoKeystream: ENTRY PROCEDURE[char: CHARACTER] =
BEGIN
ks: StreamDefs.KeyboardHandle = KeyPrivate.ks;
newIn: CARDINAL ← (ks.in + 1) MOD StreamDefs.KeyBufChars;
IF newIn ~= ks.out THEN {ks.buffer[ks.in] ← char; ks.in ← newIn};
BROADCAST KeyPrivate.charactersAvailable;
END;

END. -- of ExecKeyboard --