-- 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.