MODULE Keyboard;
IMPORT SYSTEM, Machine, KernelLog, Modules, Kernel, Objects, Inputs, Commands, Files;
CONST
ScrollLock = 0; NumLock = 1; CapsLock = 2; LAlt = 3; RAlt = 4;
LCtrl = 5; RCtrl = 6; LShift = 7; RShift = 8; GreyEsc = 9;
Resetting = 10; SetTypematic = 11; SendingLEDs = 12;
LMeta = 13; RMeta = 14;
DeadKey = 0;
TraceKeys = FALSE;
TYPE
Keyboard = OBJECT
VAR last: Inputs.KeyboardMsg;
PROCEDURE HandleInterrupt;
VAR m: SET; i: LONGINT; msg: Inputs.KeyboardMsg; k: INTEGER; c: CHAR;
BEGIN {EXCLUSIVE}
SYSTEM.PORTIN(060H, c);
SYSTEM.PORTIN(061H, SYSTEM.VAL(CHAR, m));
INCL(m, 7); SYSTEM.PORTOUT(061H, SYSTEM.VAL(CHAR, m));
EXCL(m, 7); SYSTEM.PORTOUT(061H, SYSTEM.VAL(CHAR, m));
IF TraceKeys THEN KernelLog.Hex(ORD(c), -3) END;
k := MapScanCode(c, msg.keysym);
IF k >= 0 THEN msg.ch := CHR(k) ELSE msg.ch := 0X END;
IF TraceKeys & (msg.keysym # Inputs.KsNil) THEN
KernelLog.Hex(msg.keysym, 9); KernelLog.Ln
END;
msg.flags := {};
FOR i := LAlt TO RShift DO
IF i IN flags THEN INCL(msg.flags, mapflag[i]) END
END;
FOR i := LMeta TO RMeta DO
IF i IN flags THEN INCL(msg.flags, i-LMeta+Inputs.LeftMeta) END
END;
IF c >= 80X THEN INCL(msg.flags, Inputs.Release) END;
IF (msg.flags # last.flags) OR (msg.ch # 0X) OR (msg.keysym # Inputs.KsNil) THEN
last := msg; Inputs.keyboard.Handle(msg)
END
END HandleInterrupt;
PROCEDURE &Init*;
BEGIN
last.ch := 0X; last.flags := {0..31};
Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+1)
END Init;
PROCEDURE Finalize;
BEGIN
Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+1)
END Finalize;
END Keyboard;
VAR
dkey: SHORTINT;
lastport: LONGINT;
lastvalue: SYSTEM.BYTE;
keyval: INTEGER;
table: SYSTEM.ADDRESS;
flags: SET;
keytable: POINTER TO ARRAY OF CHAR;
keyboard: Keyboard;
mapflag: ARRAY RShift+1 OF SHORTINT;
PROCEDURE TableUS(): SYSTEM.ADDRESS;
CODE {SYSTEM.AMD64}
LEA RAX, [RIP + L2 - L1];
L1:
LEAVE
RET
L2:
; alphabet
DB 1EH, 'a', 'A', 4H, 30H, 'b', 'B', 4H, 2EH, 'c', 'C', 4H, 20H, 'd', 'D', 4H
DB 12H, 'e', 'E', 4H, 21H, 'f', 'F', 4H, 22H, 'g', 'G', 4H, 23H, 'h', 'H', 4H
DB 17H, 'i', 'I', 4H, 24H, 'j', 'J', 4H, 25H, 'k', 'K', 4H, 26H, 'l', 'L', 4H
DB 32H, 'm', 'M', 4H, 31H, 'n', 'N', 4H, 18H, 'o', 'O', 4H, 19H, 'p', 'P', 4H
DB 10H, 'q', 'Q', 4H, 13H, 'r', 'R', 4H, 1FH, 's', 'S', 4H, 14H, 't', 'T', 4H
DB 16H, 'u', 'U', 4H, 2FH, 'v', 'V', 4H, 11H, 'w', 'W', 4H, 2DH, 'x', 'X', 4H
DB 15H, 'y', 'Y', 4H, 2CH, 'z', 'Z', 4H
; Oberon accents (LAlt & RAlt)
; DB 1EH, 'ä', 'Ä', 0CH, 12H, 'ë', 0FFH, 0CH, 18H, 'ö', 'Ö', 0CH, 16H, 'ü', 'Ü', 0CH
; DB 17H, 'ï', 0FFH, 0CH, 1FH, 'ß', 0FFH, 0CH, 2EH, 'ç', 0FFH, 0CH, 31H, 'ñ', 0FFH, 0CH
; DB 1EH, 'ä', 'Ä', 14H, 12H, 'ë', 0FFH, 14H, 18H, 'ö', 'Ö', 14H, 16H, 'ü', 'Ü', 14H
; DB 17H, 'ï', 0FFH, 14H, 1FH, 'ß', 0FFH, 14H, 2EH, 'ç', 0FFH, 14H, 31H, 'ñ', 0FFH, 14H
; ; dead keys (LAlt & RAlt)
; DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
; DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
; ; following keys
; DB 1EH, 'â', 0FFH, 20H, 12H, 'ê', 0FFH, 20H, 17H, 'î', 0FFH, 20H, 18H, 'ô', 0FFH, 20H
; DB 16H, 'û', 0FFH, 20H, 1EH, 'à', 0FFH, 60H, 12H, 'è', 0FFH, 60H, 17H, 'ì', 0FFH, 60H
; DB 18H, 'ò', 0FFH, 60H, 16H, 'ù', 0FFH, 60H, 1EH, 'á', 0FFH, 40H, 12H, 'é', 0FFH, 40H
; DB 1EH, 'ä', 'Ä', 0A4H, 12H, 'ë', 0FFH, 0A0H, 17H, 'ï', 0FFH, 0A0H, 18H, 'ö', 'Ö', 0A4H
; DB 16H, 'ü', 'Ü', 0A4H, 31H, 'ñ', 0FFH, 80H
DB 1EH, 83H, 80H, 0CH, 12H, 91H, 0FFH, 0CH, 18H, 84H, 81H, 0CH, 16H, 85H, 82H, 0CH
DB 17H, 92H, 0FFH, 0CH, 1FH, 96H, 0FFH, 0CH, 2EH, 93H, 0FFH, 0CH, 31H, 95H, 0FFH, 0CH
DB 1EH, 83H, 80H, 14H, 12H, 91H, 0FFH, 14H, 18H, 84H, 81H, 14H, 16H, 85H, 82H, 14H
DB 17H, 92H, 0FFH, 14H, 1FH, 96H, 0FFH, 14H, 2EH, 93H, 0FFH, 14H, 31H, 95H, 0FFH, 14H
; dead keys (LAlt & RAlt)
DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
; following keys
DB 1EH, 86H, 0FFH, 20H, 12H, 87H, 0FFH, 20H, 17H, 88H, 0FFH, 20H, 18H, 89H, 0FFH, 20H
DB 16H, 8AH, 0FFH, 20H, 1EH, 8BH, 0FFH, 60H, 12H, 8CH, 0FFH, 60H, 17H, 8DH, 0FFH, 60H
DB 18H, 8EH, 0FFH, 60H, 16H, 8FH, 0FFH, 60H, 1EH, 94H, 0FFH, 40H, 12H, 90H, 0FFH, 40H
DB 1EH, 83H, 80H, 0A4H, 12H, 91H, 0FFH, 0A0H, 17H, 92H, 0FFH, 0A0H, 18H, 84H, 81H, 0A4H
DB 16H, 85H, 82H, 0A4H, 31H, 95H, 0FFH, 80H
DB 1EH, 'a', 'A', 0CH, 12H, 'e', 0FFH, 0CH, 18H, 'o', 'O', 0CH, 16H, 'u', 'U', 0CH
DB 17H, 'i', 0FFH, 0CH, 1FH, 's', 0FFH, 0CH, 2EH, 'c', 0FFH, 0CH, 31H, 'n', 0FFH, 0CH
DB 1EH, 'a', 'A', 14H, 12H, 'e', 0FFH, 14H, 18H, 'o', 'O', 14H, 16H, 'u', 'U', 14H
DB 17H, 'i', 0FFH, 14H, 1FH, 's', 0FFH, 14H, 2EH, 'c', 0FFH, 14H, 31H, 'n', 0FFH, 14H
; dead keys (LAlt & RAlt)
DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
; following keys
DB 1EH, 'a', 0FFH, 20H, 12H, 'e', 0FFH, 20H, 17H, 'i', 0FFH, 20H, 18H, 'o', 0FFH, 20H
DB 16H, 'u', 0FFH, 20H, 1EH, 'a', 0FFH, 60H, 12H, 'e', 0FFH, 60H, 17H, 'i', 0FFH, 60H
DB 18H, 'o', 0FFH, 60H, 16H, 'u', 0FFH, 60H, 1EH, 'a', 0FFH, 40H, 12H, 'e', 0FFH, 40H
DB 1EH, 'a', 'A', 0A4H, 12H, 'e', 0FFH, 0A0H, 17H, 'i', 0FFH, 0A0H, 18H, 'o', 'O', 0A4H
DB 16H, 'u', 'U', 0A4H, 31H, 'n', 0FFH, 80H
; numbers at top
DB 0BH, '0', ')', 0H, 02H, '1', '!', 0H, 03H, '2', '@', 0H, 04H, '3', '#', 0H
DB 05H, '4', '$', 0H, 06H, '5', '%', 0H, 07H, '6', '^', 0H, 08H, '7', '&', 0H
DB 09H, '8', '*', 0H, 0AH, '9', '(', 0H
; symbol keys
DB 28H, 27H, 22H, 0H, 33H, ',', '<', 0H, 0CH, '-', '_', 0H, 34H, '.', '>', 0H
DB 35H, '/', '?', 0H, 27H, ';', ':', 0H, 0DH, '=', '+', 0H, 1AH, '[', '{', 0H
DB 2BH, '\', '|', 0H, 1BH, ']', '}', 0H, 29H, '`', '~', 0H
; control keys
DB 0EH, 7FH, 7FH, 0H ; backspace
DB 0FH, 09H, 09H, 0H ; tab
DB 1CH, 0DH, 0DH, 0H ; enter
DB 39H, 20H, 20H, 0H ; space
DB 01H, 1BH, 1BH, 0H ; esc
; keypad
DB 4FH, 0A9H, '1', 2H ; end/1
DB 50H, 0C2H, '2', 2H ; down/2
DB 51H, 0A3H, '3', 2H ; pgdn/3
DB 4BH, 0C4H, '4', 2H ; left/4
DB 4CH, 0FFH, '5', 2H ; center/5
DB 4DH, 0C3H, '6', 2H ; right/6
DB 47H, 0A8H, '7', 2H ; home/7
DB 48H, 0C1H, '8', 2H ; up/8
DB 49H, 0A2H, '9', 2H ; pgup/9
DB 52H, 0A0H, '0', 2H ; insert/0
DB 53H, 0A1H, 2EH, 2H ; del/.
; grey keys
DB 4AH, '-', '-', 0H ; grey -
DB 4EH, '+', '+', 0H ; grey +
DB 0B5H, '/', '/', 0H ; grey /
DB 37H, '*', '*', 0H ; grey *
DB 0D0H, 0C2H, 0C2H, 0H ; grey down
DB 0CBH, 0C4H, 0C4H, 0H ; grey left
DB 0CDH, 0C3H, 0C3H, 0H ; grey right
DB 0C8H, 0C1H, 0C1H, 0H ; grey up
DB 09CH, 0DH, 0DH, 0H ; grey enter
DB 0D2H, 0A0H, 0A0H, 0H ; grey ins
DB 0D3H, 0A1H, 0A1H, 0H ; grey del
DB 0C9H, 0A2H, 0A2H, 0H ; grey pgup
DB 0D1H, 0A3H, 0A3H, 0H ; grey pgdn
DB 0C7H, 0A8H, 0A8H, 0H ; grey home
DB 0CFH, 0A9H, 0A9H, 0H ; grey end
; function keys
DB 3BH, 0A4H, 0FFH, 0H ; F1
DB 3CH, 0A5H, 0FFH, 0H ; F2
DB 3DH, 0A6H, 0FFH, 0H ; F3
DB 3EH, 0A7H, 0FFH, 0H ; F4
DB 3FH, 0F5H, 0FFH, 0H ; F5
DB 40H, 0F6H, 0FFH, 0H ; F6
DB 41H, 0F7H, 0FFH, 0H ; F7
DB 42H, 0F8H, 0FFH, 0H ; F8
DB 43H, 0F9H, 0FFH, 0H ; F9
DB 44H, 0FAH, 0FFH, 0H ; F10
DB 57H, 0FBH, 0FFH, 0H ; F11
DB 58H, 0FCH, 0FFH, 0H ; F12
DB 0FFH
END TableUS;
PROCEDURE TableFromFile(name: ARRAY OF CHAR): SYSTEM.ADDRESS;
VAR f: Files.File; r: Files.Rider; len: LONGINT;
BEGIN
KernelLog.String("Keyboard: "); KernelLog.String(name);
f := Files.Old(name);
IF f # NIL THEN
len := f.Length();
IF len MOD 4 = 0 THEN
NEW(keytable, len+1);
f.Set(r, 0); f.ReadBytes(r, keytable^, 0, len);
IF r.res = 0 THEN
KernelLog.String(" loaded."); KernelLog.Ln;
keytable[len] := 0FFX;
RETURN SYSTEM.ADR(keytable[0])
ELSE
KernelLog.String(" res="); KernelLog.Int(r.res, 1)
END
ELSE
KernelLog.String(" len="); KernelLog.Int(len, 1)
END
ELSE
KernelLog.String(" not found.")
END;
KernelLog.Ln;
RETURN TableUS()
END TableFromFile;
PROCEDURE Translate(flags: SET; c: CHAR): INTEGER;
CONST
Alt = {LAlt, RAlt}; Ctrl = {LCtrl, RCtrl}; Shift = {LShift, RShift};
VAR a: SYSTEM.ADDRESS; s1: CHAR; s: SET; k: INTEGER; dkn: SHORTINT;
BEGIN {EXCLUSIVE}
IF (c = 46X) & (flags * Ctrl # {}) THEN RETURN -2 END;
IF (c = 44X) & (flags * Ctrl # {}) THEN RETURN 0FFH END;
IF (c = 53X) & (flags * Ctrl # {}) & (flags * Alt # {}) THEN RETURN 0A1H END;
IF GreyEsc IN flags THEN c := CHR(ORD(c)+80H) END;
a := table;
LOOP
SYSTEM.GET(a, s1);
IF s1 = 0FFX THEN
k := -1; dkey := 0; EXIT
ELSIF s1 = c THEN
SYSTEM.GET(a+3, SYSTEM.VAL(CHAR, s));
dkn := SHORT(SHORT(SYSTEM.VAL(LONGINT, SYSTEM.LSH(s * {5..7}, -5))));
s := s * {DeadKey, NumLock, CapsLock, LAlt, RAlt, LCtrl, RCtrl}; k := 0;
IF ((s * Alt = flags * Alt) OR (NumLock IN s) OR (s1 > 03BX)) & (dkn = dkey) THEN
IF flags * Shift # {} THEN INCL(s, LShift) END;
IF (CapsLock IN s) & (CapsLock IN flags) THEN s := s / {LShift} END;
IF NumLock IN s THEN
IF NumLock IN flags THEN s := s + {LShift} ELSE s := s - {LShift} END
END;
IF LShift IN s THEN SYSTEM.GET(a+2, SYSTEM.VAL(CHAR, k))
ELSE SYSTEM.GET(a+1, SYSTEM.VAL(CHAR, k))
END;
IF (DeadKey IN s) & (k <= 7) THEN
dkey := SHORT(k); k := -1
ELSIF k = 0FFH THEN
k := -1; dkey := 0
ELSE
IF flags * Ctrl # {} THEN
IF ((k >= 64) & (k <= 95)) OR ((k >= 97) & (k <= 122)) THEN
k := SHORT(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, k) * {0..4}))
ELSIF k = 13 THEN
k := 10
END
END;
IF flags * Alt # {} THEN
IF (k >= ORD('0')) & (k <= ORD('9')) & (NumLock IN s) THEN
IF keyval = -1 THEN keyval := k-ORD('0')
ELSE keyval := (10*keyval + (k-ORD('0'))) MOD 1000
END;
k := -1
END
END;
dkey := 0
END;
EXIT
END
END;
INC(a, 4)
END;
RETURN k
END Translate;
PROCEDURE Wait;
VAR t: Kernel.MilliTimer; s: SET;
BEGIN
Kernel.SetTimer(t, 20);
REPEAT
SYSTEM.PORTIN(64H, SYSTEM.VAL(CHAR, s))
UNTIL ~(1 IN s) OR Kernel.Expired(t)
END Wait;
PROCEDURE SendByte(port: LONGINT; value: SYSTEM.BYTE);
BEGIN
Wait; SYSTEM.PORTOUT(port, SYSTEM.VAL(CHAR, value));
lastport := port; lastvalue := value
END SendByte;
PROCEDURE ShiftKey(left, right: SHORTINT; in: BOOLEAN);
BEGIN
IF in THEN
IF GreyEsc IN flags THEN INCL(flags, right)
ELSE INCL(flags, left)
END
ELSE
IF GreyEsc IN flags THEN EXCL(flags, right)
ELSE EXCL(flags, left)
END
END
END ShiftKey;
PROCEDURE LedKey(VAR flags: SET; lock: SHORTINT; c: CHAR;
VAR k: INTEGER);
BEGIN
IF flags * {LAlt, RAlt, LCtrl, RCtrl, LShift, RShift} = {} THEN
flags := flags / {lock}
ELSE
k := Translate(flags, c)
END
END LedKey;
PROCEDURE MapScanCode(c: CHAR; VAR keysym: LONGINT): INTEGER;
VAR k: INTEGER; oldleds: SET;
BEGIN
SendByte(64H, 0ADX); Wait;
k := -1; oldleds := flags * {ScrollLock, NumLock, CapsLock};
keysym := Inputs.KsNil;
IF c = 0X THEN
ELSIF c = 0FAX THEN
IF Resetting IN flags THEN
EXCL(flags, Resetting); INCL(flags, SendingLEDs);
SendByte(60H, 0EDX)
ELSIF SendingLEDs IN flags THEN
SendByte(60H, SYSTEM.VAL(CHAR, oldleds));
EXCL(flags, SendingLEDs)
ELSIF SetTypematic IN flags THEN
EXCL(flags, SetTypematic); INCL(flags, Resetting);
SendByte(60H, 020X)
ELSE
END
ELSIF c = 0FEX THEN
SendByte(lastport, lastvalue)
ELSIF c = 038X THEN
ShiftKey(LAlt, RAlt, TRUE); keysym := Inputs.KsAltL
ELSIF c = 01DX THEN
ShiftKey(LCtrl, RCtrl, TRUE); keysym := Inputs.KsControlL
ELSIF c = 02AX THEN
IF ~(GreyEsc IN flags) THEN
INCL(flags, LShift); keysym := Inputs.KsShiftL
END
ELSIF c = 036X THEN
IF ~(GreyEsc IN flags) THEN
INCL(flags, RShift); keysym := Inputs.KsShiftR
END
ELSIF c = 05BX THEN
INCL(flags, LMeta); keysym := Inputs.KsMetaL
ELSIF c = 05CX THEN
INCL(flags, RMeta); keysym := Inputs.KsMetaR
ELSIF c = 03AX THEN
LedKey(flags, CapsLock, c, k)
ELSIF c = 046X THEN
LedKey(flags, ScrollLock, c, k);
IF k = -2 THEN keysym := Inputs.KsBreak END
ELSIF c = 045X THEN
LedKey(flags, NumLock, c, k)
ELSIF c = 0B8X THEN
ShiftKey(LAlt, RAlt, FALSE); keysym := Inputs.KsAltL;
IF (keyval >= 0) & (keyval < 255) THEN k := keyval END;
keyval := -1
ELSIF c = 09DX THEN
ShiftKey(LCtrl, RCtrl, FALSE); keysym := Inputs.KsControlL
ELSIF c = 0AAX THEN
IF ~(GreyEsc IN flags) THEN
EXCL(flags, LShift); keysym := Inputs.KsShiftL
END
ELSIF c = 0B6X THEN
IF ~(GreyEsc IN flags) THEN
EXCL(flags, RShift); keysym := Inputs.KsShiftR
END
ELSIF c = 0DBX THEN
EXCL(flags, LMeta); keysym := Inputs.KsMetaL
ELSIF c = 0DCX THEN
EXCL(flags, RMeta); keysym := Inputs.KsMetaR
ELSIF c = 05DX THEN
keysym := Inputs.KsMenu
ELSIF c < 080X THEN
k := Translate(flags, c);
IF c = 0EX THEN keysym := Inputs.KsBackSpace
ELSIF c = 0FX THEN keysym := Inputs.KsTab
ELSIF c = 1CX THEN keysym := Inputs.KsReturn
ELSIF c = 01X THEN keysym := Inputs.KsEscape
ELSIF c = 3DX THEN keysym := Inputs.KsF3
ELSIF c = 4AX THEN keysym := Inputs.KsKPSubtract
ELSIF c = 4EX THEN keysym := Inputs.KsKPAdd
ELSIF c = 0B5X THEN keysym := Inputs.KsKPDivide
ELSIF c = 37X THEN keysym := Inputs.KsKPMultiply
ELSIF k >= 0 THEN keysym := KeySym(CHR(k))
ELSE
END
ELSE
END;
IF c = 0E0X THEN INCL(flags, GreyEsc) ELSE EXCL(flags, GreyEsc) END;
IF flags * {ScrollLock, NumLock, CapsLock} # oldleds THEN
INCL(flags, SendingLEDs);
SendByte(60H, 0EDX)
END;
SendByte(64H, 0AEX);
RETURN k
END MapScanCode;
PROCEDURE KeySym(ch: CHAR): LONGINT;
VAR x: LONGINT;
BEGIN
IF (ch >= 1X) & (ch <= 7EX) THEN x := ORD(ch)
ELSIF ch = 0A0X THEN x := Inputs.KsInsert
ELSIF ch = 0A1X THEN x := Inputs.KsDelete
ELSIF ch = 0A8X THEN x := Inputs.KsHome
ELSIF ch = 0A9X THEN x := Inputs.KsEnd
ELSIF ch = 0A2X THEN x := Inputs.KsPageUp
ELSIF ch = 0A3X THEN x := Inputs.KsPageDown
ELSIF ch = 0C4X THEN x := Inputs.KsLeft
ELSIF ch = 0C1X THEN x := Inputs.KsUp
ELSIF ch = 0C3X THEN x := Inputs.KsRight
ELSIF ch = 0C2X THEN x := Inputs.KsDown
ELSIF ch = 0A4X THEN x := Inputs.KsF1
ELSIF ch = 0A5X THEN x := Inputs.KsF2
ELSIF ch = 0A7X THEN x := Inputs.KsF4
ELSIF ch = 0F5X THEN x := Inputs.KsF5
ELSIF ch = 0F6X THEN x := Inputs.KsF6
ELSIF ch = 0F7X THEN x := Inputs.KsF7
ELSIF ch = 0F8X THEN x := Inputs.KsF8
ELSIF ch = 0F9X THEN x := Inputs.KsF9
ELSIF ch = 0FAX THEN x := Inputs.KsF10
ELSIF ch = 0FBX THEN x := Inputs.KsF11
ELSIF ch = 0FCX THEN x := Inputs.KsF12
ELSE x := 0
END;
RETURN x
END KeySym;
PROCEDURE InitKeyboard;
VAR s: SET; c: CHAR; i: SHORTINT; k: ARRAY 32 OF CHAR;
BEGIN
keyval := -1; dkey := 0;
mapflag[LAlt] := Inputs.LeftAlt; mapflag[RAlt] := Inputs.RightAlt;
mapflag[LCtrl] := Inputs.LeftCtrl; mapflag[RCtrl] := Inputs.RightCtrl;
mapflag[LShift] := Inputs.LeftShift; mapflag[RShift] := Inputs.RightShift;
Machine.GetConfig("Keyboard", k);
i := 0; WHILE (k[i] # 0X) & (k[i] # '.') DO INC(i) END;
IF k[i] = '.' THEN table := TableFromFile(k)
ELSE table := TableUS()
END;
flags := {};
NEW(keyboard);
i := 8;
LOOP
SYSTEM.PORTIN(64H, SYSTEM.VAL(CHAR, s));
IF ~(0 IN s) OR (i = 0) THEN EXIT END;
SYSTEM.PORTIN(60H, c);
SYSTEM.PORTIN(61H, SYSTEM.VAL(CHAR, s));
INCL(s, 7); SYSTEM.PORTOUT(61H, SYSTEM.VAL(CHAR, s));
EXCL(s, 7); SYSTEM.PORTOUT(61H, SYSTEM.VAL(CHAR, s));
DEC(i)
END;
flags := {SetTypematic};
Machine.GetConfig("NumLock", k);
IF k[0] = '1' THEN INCL(flags, NumLock) END;
SendByte(60H, 0F3X)
END InitKeyboard;
PROCEDURE SetLayout*(context : Commands.Context);
VAR layoutFilename : ARRAY 256 OF CHAR;
BEGIN {EXCLUSIVE}
IF (keyboard # NIL) THEN
context.arg.GetString(layoutFilename);
table := TableFromFile(layoutFilename);
ELSE
context.error.String("Keyboard: No keyboard found."); context.error.Ln;
END;
END SetLayout;
PROCEDURE Install*;
END Install;
PROCEDURE Cleanup;
BEGIN
IF (keyboard # NIL) & (Modules.shutdown = Modules.None) THEN
keyboard.Finalize; keyboard := NIL
END
END Cleanup;
BEGIN
InitKeyboard;
Modules.InstallTermHandler(Cleanup)
END Keyboard.
(*
19.08.1999 pjm Split from Aos.Input
20.09.2006 Added SetLayout (staubesv)
*)
Keyboard.Install ~
Keyboard.SetLayout KeyCH.Bin ~
Keyboard.SetLayout KeyUS.Bin ~
SystemTools.Free Keyboard ~