KEYBOARD.MOD 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * KEYBOARD.MOD - COMMS Toolkit Keyboard interface *
  5. * *
  6. * COPYRIGHT (C) 1988..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. IMPLEMENTATION MODULE Keyboard;
  11. (*%F _OS2*)
  12. IMPORT Lib,SYSTEM;
  13. CONST
  14. KbdDriverInstalled = FALSE;
  15. KbdInterrupt = 09H; (* kbd interrupts handler consts *)
  16. KbdDataPort = 60H;
  17. KbdControlPort = 61H;
  18. ClrKbdBit = 7;
  19. KbdQueueSize = 16;
  20. RightShiftActive = 0; (* kbd status word bit numbers *)
  21. LeftShiftActive = 1;
  22. ControlActive = 2;
  23. AltActive = 3;
  24. ScrollLockActive = 4;
  25. NumLockActive = 5;
  26. CapsLockActive = 6;
  27. InsertActive = 7;
  28. ScrollLockHeld = 12;
  29. NumLockHeld = 13;
  30. CapsLockHeld = 14;
  31. InsertHeld = 15;
  32. NumLock = 69; (* SCAN CODES FOR VARIOUS KEYS *)
  33. BreakKey = 70;
  34. ScrollLock = 70;
  35. AltKey = 56;
  36. CtlKey = 29;
  37. CapsLock = 58;
  38. LeftShift = 42;
  39. RightShift = 54;
  40. TYPE
  41. Reg = RECORD
  42. CASE : BOOLEAN OF
  43. TRUE : X : CARDINAL; |
  44. FALSE : H : SHORTCARD;
  45. L : SHORTCARD; |
  46. END; (*CASE*)
  47. END; (*RECORD*)
  48. VAR (* keyboard stuff *)
  49. KbdFlags [40H:17H] : BITSET;
  50. (*$W+*)
  51. KbdQueue [40H:1AH] : RECORD
  52. rptr,wptr : CARDINAL;
  53. Buff : ARRAY[0..KbdQueueSize-1] OF
  54. RECORD
  55. key,scan : CHAR
  56. END;
  57. END;
  58. (*$W-*)
  59. Extended : BOOLEAN;
  60. OldVect9,OldVect16 : FarADDRESS;
  61. Continue : PROC;
  62. (*.............................................*)
  63. PROCEDURE SetVector(Int:WORD;Addr:FarADDRESS);
  64. VAR
  65. r : SYSTEM.Registers;
  66. BEGIN
  67. r.AH := 25H;
  68. r.AL := BYTE(Int);
  69. r.DS := SYSTEM.Seg(Addr^);
  70. r.DX := SYSTEM.Ofs(Addr^);
  71. Lib.Intr(r,21H); (* DOS Interrupt *)
  72. END SetVector;
  73. (*.............................................*)
  74. PROCEDURE GetVector(Int:WORD):FarADDRESS;
  75. VAR
  76. r : SYSTEM.Registers;
  77. BEGIN
  78. r.AH := 35H;
  79. r.AL := BYTE(Int);
  80. Lib.Intr(r,21H); (* DOS Interrupt *)
  81. RETURN [r.ES:r.BX];
  82. END GetVector;
  83. (*.............................................*)
  84. PROCEDURE StoreKey(c:CHAR; code:CARDINAL);
  85. VAR
  86. newwptr,capc : CARDINAL;
  87. BEGIN
  88. WITH KbdQueue DO
  89. newwptr := wptr+2;
  90. IF newwptr=62 THEN
  91. newwptr:=30;
  92. END;
  93. IF newwptr<>rptr THEN
  94. capc := ORD(CAP(c));
  95. IF (ControlActive IN KbdFlags) AND (capc>64) AND (capc<96) THEN
  96. c := CHR(capc-64);
  97. ELSIF (c>='a') AND (c<='z') AND (CapsLockActive IN KbdFlags) THEN
  98. c := CHR(capc)
  99. END;
  100. Buff[(wptr-30)>>1].key := c;
  101. Buff[(wptr-30)>>1].scan := CHR(code);
  102. wptr := newwptr;
  103. ELSE
  104. Lib.Sound(200);
  105. Lib.Delay(50);
  106. Lib.NoSound;
  107. END;
  108. END;
  109. END StoreKey;
  110. (*.............................................*)
  111. PROCEDURE Shifted():BOOLEAN;
  112. BEGIN
  113. RETURN KbdFlags*{LeftShiftActive,RightShiftActive}<>{};
  114. END Shifted;
  115. (*.............................................*)
  116. (*# save, call(interrupt=>on,reg_saved=>(ax,bx,cx,dx,di,si,ds,es,st1,st2),reg_param=>(),same_ds=>off)*)
  117. (* NB, The interrupt pragma sets up the registers as parameters to the *)
  118. (* procedure in the order defined below. This ollows easy access to *)
  119. (* the entry registers. *)
  120. PROCEDURE KeyboardInterrupt;
  121. CONST
  122. Row1 = '1234567890-=';
  123. Row1Shifted = '!"#$%^&*()_+';
  124. Row2 = 'qwertyuiop[]';
  125. Row2Shifted = 'QWERTYUIOP{}';
  126. Row3 = "asdfghjkl;'`";
  127. Row3Shifted = 'ASDFGHJKL:@~';
  128. Row4 = '\zxcvbnm,./';
  129. Row4Shifted = '|ZXCVBNM<>?';
  130. KeyPad = '789-456+1230.';
  131. VAR
  132. code : CARDINAL;
  133. ch,resetkb,
  134. kbcontrol : CHAR;
  135. BEGIN
  136. ch := CHAR(SYSTEM.In(KbdDataPort)); (* read char *)
  137. IF ORD(ch)<128 (* key press *) THEN
  138. code := ORD(ch);
  139. CASE code OF
  140. 1 : StoreKey(CHR(27),1); |
  141. 2..13 : IF AltActive IN KbdFlags THEN
  142. StoreKey(0C,120+code-2);
  143. ELSIF Shifted() THEN
  144. StoreKey(Row1Shifted[code-2],code);
  145. ELSE
  146. StoreKey(Row1[code-2],code);
  147. END; |
  148. 14 : IF Shifted() OR (ControlActive IN KbdFlags) THEN
  149. StoreKey(CHR(127),14)
  150. ELSE
  151. StoreKey(CHR(8),14);
  152. END; |
  153. 15 : IF Shifted() THEN
  154. StoreKey(0C,15)
  155. ELSE
  156. StoreKey(CHR(9),15)
  157. END; |
  158. 16..27 : IF AltActive IN KbdFlags THEN
  159. StoreKey(0C,code)
  160. ELSIF Shifted() THEN
  161. StoreKey(Row2Shifted[code-16],code)
  162. ELSE
  163. StoreKey(Row2[code-16],code)
  164. END; |
  165. 28 : IF ControlActive IN KbdFlags THEN
  166. ch := CHR(10)
  167. ELSE
  168. ch := CHR(13)
  169. END;
  170. StoreKey(ch,28); |
  171. CtlKey : INCL(KbdFlags,ControlActive) |
  172. 30..41 : IF AltActive IN KbdFlags THEN
  173. StoreKey(0C,code)
  174. ELSIF Shifted() THEN
  175. StoreKey(Row3Shifted[code-30],code)
  176. ELSE
  177. StoreKey(Row3[code-30],code)
  178. END; |
  179. LeftShift : INCL(KbdFlags,LeftShiftActive); |
  180. 43..53 : IF AltActive IN KbdFlags THEN
  181. StoreKey(0C,code)
  182. ELSIF Shifted() THEN
  183. StoreKey(Row4Shifted[code-43],code)
  184. ELSE
  185. StoreKey(Row4[code-43],code)
  186. END; |
  187. RightShift : INCL(KbdFlags,RightShiftActive); |
  188. 55 : StoreKey('*',55); |
  189. AltKey : INCL(KbdFlags,AltActive); |
  190. 57 : StoreKey(' ',57); |
  191. CapsLock : KbdFlags := KbdFlags/{CapsLockActive};
  192. INCL(KbdFlags,CapsLockHeld); |
  193. 59..68 : IF AltActive IN KbdFlags THEN
  194. StoreKey(0C,code+45)
  195. ELSIF ControlActive IN KbdFlags THEN
  196. StoreKey(0C,code+35)
  197. ELSIF Shifted() THEN
  198. StoreKey(0C,code+25)
  199. ELSE
  200. StoreKey(0C,code);
  201. END; |
  202. NumLock,
  203. BreakKey : IF AltActive IN KbdFlags THEN
  204. StoreKey(0C,code);
  205. END; |
  206. 71..83 : IF KbdFlags*{AltActive,ControlActive}<>{} THEN
  207. StoreKey(0C,code+62)
  208. ELSIF Shifted() THEN
  209. StoreKey(KeyPad[code-71],code)
  210. ELSE
  211. IF code=82 THEN
  212. KbdFlags := KbdFlags/{InsertActive};
  213. INCL(KbdFlags,InsertHeld);
  214. END;
  215. StoreKey(0C,code);
  216. END; |
  217. ELSE
  218. StoreKey(0C,code);
  219. END
  220. ELSE
  221. ch := CHR(ORD(ch)-128); (* KEY RELEASE *)
  222. CASE ORD(ch) OF
  223. AltKey : EXCL(KbdFlags,AltActive); |
  224. CtlKey : EXCL(KbdFlags,ControlActive); |
  225. LeftShift : EXCL(KbdFlags,LeftShiftActive); |
  226. RightShift : EXCL(KbdFlags,RightShiftActive); |
  227. CapsLock : EXCL(KbdFlags,CapsLockHeld); |
  228. 82 : EXCL(KbdFlags,InsertHeld); |
  229. END;
  230. END;
  231. kbcontrol := CHAR(SYSTEM.In(KbdControlPort));
  232. resetkb := CHR(CARDINAL(BITSET(ORD(kbcontrol))+{ClrKbdBit}));
  233. SYSTEM.Out(KbdControlPort,SHORTCARD(resetkb));
  234. SYSTEM.Out(KbdControlPort,SHORTCARD(kbcontrol));
  235. SYSTEM.Out(20H,20H); (* send EOI to interrupt controller *)
  236. END KeyboardInterrupt;
  237. (*# restore *)
  238. (*.............................................*)
  239. PROCEDURE RdKey():CHAR;
  240. VAR
  241. c : CHAR;
  242. R : SYSTEM.Registers;
  243. BEGIN
  244. IF Extended THEN
  245. c := ScanCode;
  246. Extended:=FALSE
  247. ELSE
  248. IF KbdDriverInstalled THEN
  249. WITH KbdQueue DO
  250. WHILE rptr=wptr DO
  251. (* Wait for keypress *)
  252. END;
  253. WITH Buff[(rptr-30)>>1] DO
  254. c := key;
  255. ScanCode := scan;
  256. END;
  257. rptr := rptr+2;
  258. IF rptr=62 THEN
  259. rptr:=30;
  260. END;
  261. END;
  262. ELSE
  263. R.AH := 0;
  264. Lib.Intr(R,16H);
  265. IF R.AX=0 THEN END; (* break *) (* --- ??? --- *)
  266. c := CHR(R.AL);
  267. ScanCode := CHR(R.AH);
  268. END;
  269. END;
  270. Extended := c=0C;
  271. RETURN c;
  272. END RdKey;
  273. (*.............................................*)
  274. PROCEDURE KeyPressed():BOOLEAN;
  275. VAR
  276. R : SYSTEM.Registers;
  277. BEGIN
  278. IF Extended THEN
  279. RETURN TRUE;
  280. END;
  281. IF KbdDriverInstalled THEN
  282. RETURN KbdQueue.rptr<>KbdQueue.wptr;
  283. ELSE
  284. R.AH := 1;
  285. Lib.Intr(R,16H);
  286. RETURN NOT (SYSTEM.ZeroFlag IN R.Flags) ;
  287. END;
  288. END KeyPressed;
  289. (*.............................................*)
  290. (*# save, call(interrupt=>on,reg_saved=>(ax,bx,cx,dx,di,si,ds,es,st1,st2),reg_param=>(),same_ds=>off)*)
  291. (* NB, The interrupt pragma sets up the registers as parameters to the *)
  292. (* procedure in the order defined below. This ollows easy access to *)
  293. (* the entry registers. *)
  294. PROCEDURE BiosKbd(Flags:BITSET;CS,IP:CARDINAL;A,C,D,B:Reg;SP,BP,SI,DI,DS,ES:CARDINAL);
  295. BEGIN
  296. SYSTEM.EI;
  297. IF A.H = 0 THEN (* Read keyboard *)
  298. A.L := SHORTCARD(RdKey());
  299. A.H := SHORTCARD(ScanCode);
  300. Extended := FALSE;
  301. ELSIF A.H=1 THEN (* Keypressed *)
  302. WITH KbdQueue DO
  303. IF rptr=wptr THEN (* No key ready *)
  304. INCL(Flags,SYSTEM.ZeroFlag);
  305. ELSE
  306. EXCL(Flags,SYSTEM.ZeroFlag);
  307. WITH Buff[(rptr-30)>>1] DO
  308. A.L := SHORTCARD(key);
  309. A.H := SHORTCARD(scan);
  310. END;
  311. END;
  312. END;
  313. ELSIF A.H=2 THEN (* Get Shift Status *)
  314. A.L := SHORTCARD(CARDINAL(KbdFlags) MOD 100H);
  315. END;
  316. END BiosKbd;
  317. (*# restore *)
  318. (*.............................................*)
  319. PROCEDURE TermProc;
  320. BEGIN
  321. SYSTEM.DI;
  322. SetVector(KbdInterrupt,OldVect9);
  323. SetVector(16H,OldVect16);
  324. SYSTEM.EI;
  325. Continue();
  326. END TermProc;
  327. (*.............................................*)
  328. BEGIN (* KeyBoard *)
  329. Extended := FALSE;
  330. IF KbdDriverInstalled THEN
  331. OldVect9 := GetVector(KbdInterrupt);
  332. OldVect16 := GetVector(16H);
  333. SYSTEM.DI;
  334. SetVector(KbdInterrupt,FarADR(KeyboardInterrupt));
  335. SetVector(16H,FarADR(BiosKbd));
  336. SYSTEM.EI;
  337. Lib.Terminate(TermProc,Continue);
  338. END;
  339. END Keyboard.
  340. (*%E*)
  341. (*%T _OS2*)
  342. (* OS/2 version *)
  343. IMPORT Kbd;
  344. VAR
  345. Extended : BOOLEAN;
  346. PROCEDURE RdKey() : CHAR;
  347. VAR
  348. k : Kbd.KEYINFO;
  349. r : CARDINAL;
  350. BEGIN
  351. IF Extended THEN
  352. Extended := FALSE;
  353. RETURN ScanCode;
  354. ELSE
  355. r := Kbd.CharIn(k,Kbd.IO_WAIT,0);
  356. IF (k.char=0C) OR (k.char=CHR(0E0H)) THEN
  357. ScanCode := CHAR(k.scan);
  358. k.char := 0C;
  359. Extended := TRUE;
  360. END;
  361. RETURN (k.char);
  362. END;
  363. END RdKey;
  364. PROCEDURE KeyPressed():BOOLEAN;
  365. VAR
  366. r : CARDINAL;
  367. k : Kbd.KEYINFO;
  368. BEGIN
  369. IF Extended THEN
  370. RETURN TRUE;
  371. ELSE
  372. k.char := 0C;
  373. k.scan := 0;
  374. k.nlsShift := 0;
  375. r := Kbd.Peek(k,0);
  376. RETURN (k.scan#0) OR (k.char#0C);
  377. END;
  378. END KeyPressed;
  379. BEGIN
  380. Extended := FALSE;
  381. END Keyboard.
  382. (*%E*)
  383.