-- KeyStreams.Mesa Edited by Sandman on September 2, 1980 7:55 AM
-- Copyright Xerox Corporation 1979, 1980
DIRECTORY
AltoDisplay USING [CursorXY, MouseXY],
ControlDefs USING [GlobalFrameHandle],
InlineDefs USING [BITAND, BITNOT, BITOR, BITSHIFT],
FrameDefs USING [
GlobalFrame, MakeCodeResident, SelfDestruct, UnlockCode, UnNew],
KeyPrivate USING [
charactersAvailable, cursor, halt, InputBufferEmpty, KeyboardData, keys,
KeyTable, ks, monitor, mouse, newState, oldState, ProcessKeyboard, ReadChar,
wakeup],
KeyDefs USING [Keyboard, KeyItem, KeyName, Keys],
ProcessDefs USING [CV, DIW, GetPriority, InterruptLevel, Priority, SetPriority],
StreamDefs USING [
KeyboardHandle, KeyBufChars, StreamError, StreamHandle, StreamObject,
trackCursor, userAbort],
Storage USING [Node, Free];
KeyStreams: MONITOR LOCKS KeyPrivate.monitor
IMPORTS
FrameDefs, InlineDefs, KeyDefs, KeyPrivate, ProcessDefs, StreamDefs, Storage
EXPORTS KeyDefs, StreamDefs
SHARES StreamDefs =
BEGIN OPEN StreamDefs, KeyPrivate;
-- The Stream part:
data: POINTER TO KeyboardData;
GetDefaultKey: PUBLIC PROCEDURE RETURNS [KeyboardHandle] =
BEGIN RETURN[@data.stream]; END;
GetCurrentKey: PUBLIC PROCEDURE RETURNS [KeyboardHandle] =
BEGIN RETURN[ks]; END;
CreateKeyStream: PUBLIC PROCEDURE RETURNS [KeyboardHandle] =
BEGIN OPEN Storage;
s: KeyboardHandle ← Storage.Node[SIZE[Keyboard StreamObject]];
s↑ ← data.stream;
s.in ← s.out ← 0;
data.stream.link ← s;
RETURN[s];
END;
OpenKeyStream: PUBLIC ENTRY PROCEDURE [stream: StreamHandle] =
BEGIN
WITH s: stream SELECT FROM
Keyboard => ks ← @s;
ENDCASE => SIGNAL StreamError[stream, StreamType ! UNWIND => NULL];
RETURN;
END;
ClearInputBuffer: ENTRY PROCEDURE [stream: StreamHandle] =
BEGIN
WITH s: stream SELECT FROM
Keyboard => s.in ← s.out ← 0;
ENDCASE => SIGNAL StreamError[stream, StreamType ! UNWIND => NULL];
RETURN;
END;
PutBackChar: ENTRY PROCEDURE [stream: StreamHandle, char: UNSPECIFIED] =
BEGIN
newout: CARDINAL;
WITH s: stream SELECT FROM
Keyboard =>
BEGIN
newout ← s.out;
newout ← IF newout = 0 THEN KeyBufChars - 1 ELSE newout - 1;
IF newout # s.in THEN
BEGIN
s.out ← newout;
s.buffer[s.out] ← char;
BROADCAST charactersAvailable;
END;
END;
ENDCASE => SIGNAL StreamError[stream, StreamType ! UNWIND => NULL];
RETURN;
END;
WriteChar: PROCEDURE [stream: StreamHandle, char: UNSPECIFIED] =
BEGIN SIGNAL StreamError[stream, StreamAccess]; RETURN END;
CloseKeyStream: PUBLIC ENTRY PROCEDURE [stream: StreamHandle] =
BEGIN
WITH s: stream SELECT FROM
Keyboard => ks ← @data.stream;
ENDCASE => SIGNAL StreamError[stream, StreamType ! UNWIND => NULL];
RETURN;
END;
DestroyKey: --ENTRY--PROCEDURE [stream: StreamHandle] =
BEGIN OPEN Storage;
prev: StreamHandle;
WITH s: stream SELECT FROM
Keyboard =>
BEGIN
IF @s = ks THEN ks ← @data.stream;
IF @s # @data.stream THEN
BEGIN
IF data.stream.link = stream THEN data.stream.link ← stream.link
ELSE
FOR prev ← @data.stream, prev.link DO
IF prev.link = NIL THEN ERROR;
IF prev.link = stream THEN BEGIN prev.link ← stream.link; EXIT END;
ENDLOOP;
Free[@s ! UNWIND => NULL];
END;
END;
ENDCASE => SIGNAL StreamError[stream, StreamType ! UNWIND => NULL];
RETURN;
END;
InitKeyTable: PROCEDURE =
BEGIN OPEN KeyDefs;
data.table ←
[ -- MEMORY[177033B] Index [0..15]
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- UNUSED
KeyItem[FALSE, 0, 0], -- KeyItemset1
KeyItem[FALSE, 0, 0], -- KeyItemset2
KeyItem[FALSE, 0, 0], -- KeyItemset3
KeyItem[FALSE, 0, 0], -- KeyItemset4
KeyItem[FALSE, 0, 0], -- KeyItemset5
KeyItem[FALSE, 0, 0], -- Red
KeyItem[FALSE, 0, 0], -- Blue
KeyItem[FALSE, 0, 0], -- Yellow
-- MEMORY[177034B] Index [16..31]
KeyItem[FALSE, 45B, 65B], -- %,5
KeyItem[FALSE, 44B, 64B], -- $,4
KeyItem[FALSE, 176B, 66B], -- ~,6
KeyItem[TRUE, 105B, 145B], -- E
KeyItem[FALSE, 46B, 67B], -- &,7
KeyItem[TRUE, 104B, 144B], -- D
KeyItem[TRUE, 125B, 165B], -- U
KeyItem[TRUE, 126B, 166B], -- V
KeyItem[FALSE, 51B, 60B], -- ),0
KeyItem[TRUE, 113B, 153B], -- K
KeyItem[FALSE, 30B, 55B], -- `,-
KeyItem[TRUE, 120B, 160B], -- P
KeyItem[FALSE, 77B, 57B], -- ?,/
KeyItem[FALSE, 174B, 134B], -- |,\
KeyItem[FALSE, 12B, 12B], -- LF
KeyItem[FALSE, 10B, 10B], -- BS
-- MEMORY[177035B] Index [32..47]
KeyItem[FALSE, 43B, 63B], -- #,3
KeyItem[FALSE, 100B, 62B], -- @,2
KeyItem[TRUE, 127B, 167B], -- W
KeyItem[TRUE, 121B, 161B], -- Q
KeyItem[TRUE, 123B, 163B], -- S
KeyItem[TRUE, 101B, 141B], -- A
KeyItem[FALSE, 50B, 71B], -- (,9
KeyItem[TRUE, 111B, 151B], -- I
KeyItem[TRUE, 130B, 170B], -- X
KeyItem[TRUE, 117B, 157B], -- O
KeyItem[TRUE, 114B, 154B], -- L
KeyItem[FALSE, 74B, 54B], -- <,,
KeyItem[FALSE, 42B, 47B], -- ",'
KeyItem[FALSE, 175B, 135B], -- },]
KeyItem[FALSE, 0B, 0B], -- SPARE2
KeyItem[FALSE, 27B, 27B], -- SPARE1
-- MEMORY[177036B] Index [48..63]
KeyItem[FALSE, 41B, 61B], -- !,1
KeyItem[FALSE, 33B, 33B], -- ESCAPE
KeyItem[FALSE, 11B, 11B], -- TAB
KeyItem[TRUE, 106B, 146B], -- F
KeyItem[FALSE, 0B, 0B], -- CONTROL
KeyItem[TRUE, 103B, 143B], -- C
KeyItem[TRUE, 112B, 152B], -- J
KeyItem[TRUE, 102B, 142B], -- B
KeyItem[TRUE, 132B, 172B], -- Z
KeyItem[FALSE, 0B, 0B], -- SHIFT
KeyItem[FALSE, 76B, 56B], -- >,.
KeyItem[FALSE, 72B, 73B], -- :,;
KeyItem[FALSE, 15B, 15B], -- CR
KeyItem[FALSE, 136B, 137B], -- ↑,←
KeyItem[FALSE, 177B, 177B], -- DEL
KeyItem[FALSE, 0B, 0B], -- NOT USED (FL3)
-- MEMORY[177037B] Index [64..79]
KeyItem[TRUE, 122B, 162B], -- R
KeyItem[TRUE, 124B, 164B], -- T
KeyItem[TRUE, 107B, 147B], -- G
KeyItem[TRUE, 131B, 171B], -- Y
KeyItem[TRUE, 110B, 150B], -- H
KeyItem[FALSE, 52B, 70B], -- *,8
KeyItem[TRUE, 116B, 156B], -- N
KeyItem[TRUE, 115B, 155B], -- M
KeyItem[FALSE, 0B, 0B], -- LOCK
KeyItem[FALSE, 40B, 40B], -- SPACE
KeyItem[FALSE, 173B, 133B], -- {,[
KeyItem[FALSE, 53B, 75B], -- +,=
KeyItem[FALSE, 0B, 0B], -- SHIFT
KeyItem[FALSE, 0B, 0B], -- SPARE3
KeyItem[FALSE, 0B, 0B], -- NOT USED (FL4)
KeyItem[FALSE, 0B, 0B]]; -- NOT USED (FR5)
END;
ChangeKey: PUBLIC PROCEDURE [key: KeyDefs.KeyName, action: KeyDefs.KeyItem]
RETURNS [oldAction: KeyDefs.KeyItem] =
BEGIN
oldAction ← data.table[LOOPHOLE[key, CARDINAL]];
data.table[LOOPHOLE[key, CARDINAL]] ← action;
RETURN
END;
-- The Process (and initialization) part
StartKeyHandler: PUBLIC PROCEDURE =
BEGIN OPEN ProcessDefs;
frame: ControlDefs.GlobalFrameHandle = FrameDefs.GlobalFrame[KeyDefs.Keyboard];
KeyboardPriority: Priority = 6;
KeyboardLevel: InterruptLevel = 7;
KeyboardBit: WORD = InlineDefs.BITSHIFT[1, KeyboardLevel];
save: Priority = GetPriority[];
data ← Storage.Node[SIZE[KeyboardData]];
InitKeyTable[];
data.stream ← StreamObject[
ClearInputBuffer, ReadChar, PutBackChar, WriteChar, InputBufferEmpty,
DestroyKey, NIL, Keyboard[0, 0, ]];
FrameDefs.MakeCodeResident[frame];
IF ~frame.started THEN START KeyDefs.Keyboard;
trackCursor ← TRUE;
userAbort ← FALSE;
halt ← FALSE;
keys ← LOOPHOLE[KeyDefs.Keys];
oldState ← @data.old;
data.old ← keys↑;
newState ← @data.new;
KeyTable ← @data.table;
ks ← @data.stream;
mouse ← AltoDisplay.MouseXY;
cursor ← AltoDisplay.CursorXY;
SetPriority[KeyboardPriority];
data.process ← FORK ProcessKeyboard;
SetPriority[save];
CV[KeyboardLevel] ← @wakeup;
DIW↑ ← InlineDefs.BITOR[DIW↑, KeyboardBit];
END;
StopKeyHandler: PUBLIC PROCEDURE =
BEGIN OPEN ProcessDefs;
KeyboardLevel: InterruptLevel = 7;
KeyboardBit: WORD = InlineDefs.BITSHIFT[1, KeyboardLevel];
frame: ControlDefs.GlobalFrameHandle = FrameDefs.GlobalFrame[KeyDefs.Keyboard];
halt ← TRUE;
JOIN data.process;
CV[KeyboardLevel] ← NIL;
DIW↑ ← InlineDefs.BITAND[DIW↑, InlineDefs.BITNOT[KeyboardBit]];
FrameDefs.UnlockCode[frame];
Storage.Free[data];
END;
DestroyKeyHandler: PUBLIC PROCEDURE =
BEGIN
IF ~halt THEN StopKeyHandler[];
FrameDefs.UnNew[FrameDefs.GlobalFrame[KeyDefs.Keyboard]];
FrameDefs.SelfDestruct[];
END;
FrameDefs.UnlockCode[FrameDefs.GlobalFrame[KeyDefs.Keyboard]];
END.