| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- (* Release 3.10 *)
- (*-------------------------------------------------------------------------*
- * *
- * KEYBOARD.MOD - COMMS Toolkit Keyboard interface *
- * *
- * COPYRIGHT (C) 1988..1992 Clarion Software Corporation. *
- * All Rights Reserved *
- * *
- *--------------------------------------------------------------------------*)
- IMPLEMENTATION MODULE Keyboard;
- (*%F _OS2*)
- IMPORT Lib,SYSTEM;
- CONST
- KbdDriverInstalled = FALSE;
- KbdInterrupt = 09H; (* kbd interrupts handler consts *)
- KbdDataPort = 60H;
- KbdControlPort = 61H;
- ClrKbdBit = 7;
- KbdQueueSize = 16;
- RightShiftActive = 0; (* kbd status word bit numbers *)
- LeftShiftActive = 1;
- ControlActive = 2;
- AltActive = 3;
- ScrollLockActive = 4;
- NumLockActive = 5;
- CapsLockActive = 6;
- InsertActive = 7;
- ScrollLockHeld = 12;
- NumLockHeld = 13;
- CapsLockHeld = 14;
- InsertHeld = 15;
- NumLock = 69; (* SCAN CODES FOR VARIOUS KEYS *)
- BreakKey = 70;
- ScrollLock = 70;
- AltKey = 56;
- CtlKey = 29;
- CapsLock = 58;
- LeftShift = 42;
- RightShift = 54;
- TYPE
- Reg = RECORD
- CASE : BOOLEAN OF
- TRUE : X : CARDINAL; |
- FALSE : H : SHORTCARD;
- L : SHORTCARD; |
- END; (*CASE*)
- END; (*RECORD*)
- VAR (* keyboard stuff *)
- KbdFlags [40H:17H] : BITSET;
- (*$W+*)
- KbdQueue [40H:1AH] : RECORD
- rptr,wptr : CARDINAL;
- Buff : ARRAY[0..KbdQueueSize-1] OF
- RECORD
- key,scan : CHAR
- END;
- END;
- (*$W-*)
- Extended : BOOLEAN;
- OldVect9,OldVect16 : FarADDRESS;
- Continue : PROC;
- (*.............................................*)
- PROCEDURE SetVector(Int:WORD;Addr:FarADDRESS);
- VAR
- r : SYSTEM.Registers;
- BEGIN
- r.AH := 25H;
- r.AL := BYTE(Int);
- r.DS := SYSTEM.Seg(Addr^);
- r.DX := SYSTEM.Ofs(Addr^);
- Lib.Intr(r,21H); (* DOS Interrupt *)
- END SetVector;
- (*.............................................*)
- PROCEDURE GetVector(Int:WORD):FarADDRESS;
- VAR
- r : SYSTEM.Registers;
- BEGIN
- r.AH := 35H;
- r.AL := BYTE(Int);
- Lib.Intr(r,21H); (* DOS Interrupt *)
- RETURN [r.ES:r.BX];
- END GetVector;
- (*.............................................*)
- PROCEDURE StoreKey(c:CHAR; code:CARDINAL);
- VAR
- newwptr,capc : CARDINAL;
- BEGIN
- WITH KbdQueue DO
- newwptr := wptr+2;
- IF newwptr=62 THEN
- newwptr:=30;
- END;
- IF newwptr<>rptr THEN
- capc := ORD(CAP(c));
- IF (ControlActive IN KbdFlags) AND (capc>64) AND (capc<96) THEN
- c := CHR(capc-64);
- ELSIF (c>='a') AND (c<='z') AND (CapsLockActive IN KbdFlags) THEN
- c := CHR(capc)
- END;
- Buff[(wptr-30)>>1].key := c;
- Buff[(wptr-30)>>1].scan := CHR(code);
- wptr := newwptr;
- ELSE
- Lib.Sound(200);
- Lib.Delay(50);
- Lib.NoSound;
- END;
- END;
- END StoreKey;
- (*.............................................*)
- PROCEDURE Shifted():BOOLEAN;
- BEGIN
- RETURN KbdFlags*{LeftShiftActive,RightShiftActive}<>{};
- END Shifted;
- (*.............................................*)
- (*# save, call(interrupt=>on,reg_saved=>(ax,bx,cx,dx,di,si,ds,es,st1,st2),reg_param=>(),same_ds=>off)*)
- (* NB, The interrupt pragma sets up the registers as parameters to the *)
- (* procedure in the order defined below. This ollows easy access to *)
- (* the entry registers. *)
- PROCEDURE KeyboardInterrupt;
- CONST
- Row1 = '1234567890-=';
- Row1Shifted = '!"#$%^&*()_+';
- Row2 = 'qwertyuiop[]';
- Row2Shifted = 'QWERTYUIOP{}';
- Row3 = "asdfghjkl;'`";
- Row3Shifted = 'ASDFGHJKL:@~';
- Row4 = '\zxcvbnm,./';
- Row4Shifted = '|ZXCVBNM<>?';
- KeyPad = '789-456+1230.';
- VAR
- code : CARDINAL;
- ch,resetkb,
- kbcontrol : CHAR;
- BEGIN
- ch := CHAR(SYSTEM.In(KbdDataPort)); (* read char *)
- IF ORD(ch)<128 (* key press *) THEN
- code := ORD(ch);
- CASE code OF
- 1 : StoreKey(CHR(27),1); |
- 2..13 : IF AltActive IN KbdFlags THEN
- StoreKey(0C,120+code-2);
- ELSIF Shifted() THEN
- StoreKey(Row1Shifted[code-2],code);
- ELSE
- StoreKey(Row1[code-2],code);
- END; |
- 14 : IF Shifted() OR (ControlActive IN KbdFlags) THEN
- StoreKey(CHR(127),14)
- ELSE
- StoreKey(CHR(8),14);
- END; |
- 15 : IF Shifted() THEN
- StoreKey(0C,15)
- ELSE
- StoreKey(CHR(9),15)
- END; |
- 16..27 : IF AltActive IN KbdFlags THEN
- StoreKey(0C,code)
- ELSIF Shifted() THEN
- StoreKey(Row2Shifted[code-16],code)
- ELSE
- StoreKey(Row2[code-16],code)
- END; |
- 28 : IF ControlActive IN KbdFlags THEN
- ch := CHR(10)
- ELSE
- ch := CHR(13)
- END;
- StoreKey(ch,28); |
- CtlKey : INCL(KbdFlags,ControlActive) |
- 30..41 : IF AltActive IN KbdFlags THEN
- StoreKey(0C,code)
- ELSIF Shifted() THEN
- StoreKey(Row3Shifted[code-30],code)
- ELSE
- StoreKey(Row3[code-30],code)
- END; |
- LeftShift : INCL(KbdFlags,LeftShiftActive); |
- 43..53 : IF AltActive IN KbdFlags THEN
- StoreKey(0C,code)
- ELSIF Shifted() THEN
- StoreKey(Row4Shifted[code-43],code)
- ELSE
- StoreKey(Row4[code-43],code)
- END; |
- RightShift : INCL(KbdFlags,RightShiftActive); |
- 55 : StoreKey('*',55); |
- AltKey : INCL(KbdFlags,AltActive); |
- 57 : StoreKey(' ',57); |
- CapsLock : KbdFlags := KbdFlags/{CapsLockActive};
- INCL(KbdFlags,CapsLockHeld); |
- 59..68 : IF AltActive IN KbdFlags THEN
- StoreKey(0C,code+45)
- ELSIF ControlActive IN KbdFlags THEN
- StoreKey(0C,code+35)
- ELSIF Shifted() THEN
- StoreKey(0C,code+25)
- ELSE
- StoreKey(0C,code);
- END; |
- NumLock,
- BreakKey : IF AltActive IN KbdFlags THEN
- StoreKey(0C,code);
- END; |
- 71..83 : IF KbdFlags*{AltActive,ControlActive}<>{} THEN
- StoreKey(0C,code+62)
- ELSIF Shifted() THEN
- StoreKey(KeyPad[code-71],code)
- ELSE
- IF code=82 THEN
- KbdFlags := KbdFlags/{InsertActive};
- INCL(KbdFlags,InsertHeld);
- END;
- StoreKey(0C,code);
- END; |
- ELSE
- StoreKey(0C,code);
- END
- ELSE
- ch := CHR(ORD(ch)-128); (* KEY RELEASE *)
- CASE ORD(ch) OF
- AltKey : EXCL(KbdFlags,AltActive); |
- CtlKey : EXCL(KbdFlags,ControlActive); |
- LeftShift : EXCL(KbdFlags,LeftShiftActive); |
- RightShift : EXCL(KbdFlags,RightShiftActive); |
- CapsLock : EXCL(KbdFlags,CapsLockHeld); |
- 82 : EXCL(KbdFlags,InsertHeld); |
- END;
- END;
- kbcontrol := CHAR(SYSTEM.In(KbdControlPort));
- resetkb := CHR(CARDINAL(BITSET(ORD(kbcontrol))+{ClrKbdBit}));
- SYSTEM.Out(KbdControlPort,SHORTCARD(resetkb));
- SYSTEM.Out(KbdControlPort,SHORTCARD(kbcontrol));
- SYSTEM.Out(20H,20H); (* send EOI to interrupt controller *)
- END KeyboardInterrupt;
- (*# restore *)
- (*.............................................*)
- PROCEDURE RdKey():CHAR;
- VAR
- c : CHAR;
- R : SYSTEM.Registers;
- BEGIN
- IF Extended THEN
- c := ScanCode;
- Extended:=FALSE
- ELSE
- IF KbdDriverInstalled THEN
- WITH KbdQueue DO
- WHILE rptr=wptr DO
- (* Wait for keypress *)
- END;
- WITH Buff[(rptr-30)>>1] DO
- c := key;
- ScanCode := scan;
- END;
- rptr := rptr+2;
- IF rptr=62 THEN
- rptr:=30;
- END;
- END;
- ELSE
- R.AH := 0;
- Lib.Intr(R,16H);
- IF R.AX=0 THEN END; (* break *) (* --- ??? --- *)
- c := CHR(R.AL);
- ScanCode := CHR(R.AH);
- END;
- END;
- Extended := c=0C;
- RETURN c;
- END RdKey;
- (*.............................................*)
- PROCEDURE KeyPressed():BOOLEAN;
- VAR
- R : SYSTEM.Registers;
- BEGIN
- IF Extended THEN
- RETURN TRUE;
- END;
- IF KbdDriverInstalled THEN
- RETURN KbdQueue.rptr<>KbdQueue.wptr;
- ELSE
- R.AH := 1;
- Lib.Intr(R,16H);
- RETURN NOT (SYSTEM.ZeroFlag IN R.Flags) ;
- END;
- END KeyPressed;
- (*.............................................*)
- (*# save, call(interrupt=>on,reg_saved=>(ax,bx,cx,dx,di,si,ds,es,st1,st2),reg_param=>(),same_ds=>off)*)
- (* NB, The interrupt pragma sets up the registers as parameters to the *)
- (* procedure in the order defined below. This ollows easy access to *)
- (* the entry registers. *)
- PROCEDURE BiosKbd(Flags:BITSET;CS,IP:CARDINAL;A,C,D,B:Reg;SP,BP,SI,DI,DS,ES:CARDINAL);
- BEGIN
- SYSTEM.EI;
- IF A.H = 0 THEN (* Read keyboard *)
- A.L := SHORTCARD(RdKey());
- A.H := SHORTCARD(ScanCode);
- Extended := FALSE;
- ELSIF A.H=1 THEN (* Keypressed *)
- WITH KbdQueue DO
- IF rptr=wptr THEN (* No key ready *)
- INCL(Flags,SYSTEM.ZeroFlag);
- ELSE
- EXCL(Flags,SYSTEM.ZeroFlag);
- WITH Buff[(rptr-30)>>1] DO
- A.L := SHORTCARD(key);
- A.H := SHORTCARD(scan);
- END;
- END;
- END;
- ELSIF A.H=2 THEN (* Get Shift Status *)
- A.L := SHORTCARD(CARDINAL(KbdFlags) MOD 100H);
- END;
- END BiosKbd;
- (*# restore *)
- (*.............................................*)
- PROCEDURE TermProc;
- BEGIN
- SYSTEM.DI;
- SetVector(KbdInterrupt,OldVect9);
- SetVector(16H,OldVect16);
- SYSTEM.EI;
- Continue();
- END TermProc;
- (*.............................................*)
- BEGIN (* KeyBoard *)
- Extended := FALSE;
- IF KbdDriverInstalled THEN
- OldVect9 := GetVector(KbdInterrupt);
- OldVect16 := GetVector(16H);
- SYSTEM.DI;
- SetVector(KbdInterrupt,FarADR(KeyboardInterrupt));
- SetVector(16H,FarADR(BiosKbd));
- SYSTEM.EI;
- Lib.Terminate(TermProc,Continue);
- END;
- END Keyboard.
- (*%E*)
- (*%T _OS2*)
- (* OS/2 version *)
- IMPORT Kbd;
- VAR
- Extended : BOOLEAN;
- PROCEDURE RdKey() : CHAR;
- VAR
- k : Kbd.KEYINFO;
- r : CARDINAL;
- BEGIN
- IF Extended THEN
- Extended := FALSE;
- RETURN ScanCode;
- ELSE
- r := Kbd.CharIn(k,Kbd.IO_WAIT,0);
- IF (k.char=0C) OR (k.char=CHR(0E0H)) THEN
- ScanCode := CHAR(k.scan);
- k.char := 0C;
- Extended := TRUE;
- END;
- RETURN (k.char);
- END;
- END RdKey;
- PROCEDURE KeyPressed():BOOLEAN;
- VAR
- r : CARDINAL;
- k : Kbd.KEYINFO;
- BEGIN
- IF Extended THEN
- RETURN TRUE;
- ELSE
- k.char := 0C;
- k.scan := 0;
- k.nlsShift := 0;
- r := Kbd.Peek(k,0);
- RETURN (k.scan#0) OR (k.char#0C);
- END;
- END KeyPressed;
- BEGIN
- Extended := FALSE;
- END Keyboard.
- (*%E*)
|