keyboard.pp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Keyboard unit for Win32
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit Keyboard;
  14. interface
  15. {$i keybrdh.inc}
  16. implementation
  17. { WARNING: Keyboard-Drivers (i.e. german) will only work under WinNT.
  18. 95 and 98 do not support keyboard-drivers other than us for win32
  19. console-apps. So we always get the keys in us-keyboard layout
  20. from Win9x.
  21. }
  22. uses
  23. Windows,
  24. Dos,
  25. WinEvent;
  26. {$i keyboard.inc}
  27. const MaxQueueSize = 120;
  28. FrenchKeyboard = $040C040C;
  29. var
  30. keyboardeventqueue : array[0..maxqueuesize] of TKeyEventRecord;
  31. nextkeyevent,nextfreekeyevent : longint;
  32. newKeyEvent : THandle; {sinaled if key is available}
  33. lockVar : TCriticalSection; {for queue access}
  34. lastShiftState : byte; {set by handler for PollShiftStateEvent}
  35. altNumActive : boolean; {for alt+0..9}
  36. altNumBuffer : string [3];
  37. { used for keyboard specific stuff }
  38. KeyBoardLayout : HKL;
  39. procedure incqueueindex(var l : longint);
  40. begin
  41. inc(l);
  42. { wrap around? }
  43. if l>maxqueuesize then
  44. l:=0;
  45. end;
  46. function keyEventsInQueue : boolean;
  47. begin
  48. keyEventsInQueue := (nextkeyevent <> nextfreekeyevent);
  49. end;
  50. { gets or peeks the next key from the queue, does not wait for new keys }
  51. function getKeyEventFromQueue (VAR t : TKeyEventRecord; Peek : boolean) : boolean;
  52. begin
  53. EnterCriticalSection (lockVar);
  54. if keyEventsInQueue then
  55. begin
  56. t := keyboardeventqueue[nextkeyevent];
  57. if not peek then incqueueindex (nextkeyevent);
  58. getKeyEventFromQueue := true;
  59. if not keyEventsInQueue then ResetEvent (newKeyEvent);
  60. end else
  61. begin
  62. getKeyEventFromQueue := false;
  63. ResetEvent (newKeyEvent);
  64. end;
  65. LeaveCriticalSection (lockVar);
  66. end;
  67. { gets the next key from the queue, does wait for new keys }
  68. function getKeyEventFromQueueWait (VAR t : TKeyEventRecord) : boolean;
  69. begin
  70. WaitForSingleObject (newKeyEvent, INFINITE);
  71. getKeyEventFromQueueWait := getKeyEventFromQueue (t, false);
  72. end;
  73. { translate win32 shift-state to keyboard shift state }
  74. function transShiftState (ControlKeyState : dword) : byte;
  75. var b : byte;
  76. begin
  77. b := 0;
  78. if ControlKeyState and SHIFT_PRESSED <> 0 then { win32 makes no difference between left and right shift }
  79. b := b or kbShift;
  80. if (ControlKeyState and LEFT_CTRL_PRESSED <> 0) or
  81. (ControlKeyState and RIGHT_CTRL_PRESSED <> 0) then
  82. b := b or kbCtrl;
  83. if (ControlKeyState and LEFT_ALT_PRESSED <> 0) or
  84. (ControlKeyState and RIGHT_ALT_PRESSED <> 0) then
  85. b := b or kbAlt;
  86. transShiftState := b;
  87. end;
  88. { The event-Handler thread from the unit event will call us if a key-event
  89. is available }
  90. procedure HandleKeyboard(var ir:INPUT_RECORD);
  91. var
  92. i : longint;
  93. c : word;
  94. addThis: boolean;
  95. begin
  96. with ir.Event.KeyEvent do
  97. begin
  98. { key up events are ignored (except alt) }
  99. if bKeyDown then
  100. begin
  101. EnterCriticalSection (lockVar);
  102. for i:=1 to wRepeatCount do
  103. begin
  104. addThis := true;
  105. if (dwControlKeyState and LEFT_ALT_PRESSED <> 0) or
  106. (dwControlKeyState and RIGHT_ALT_PRESSED <> 0) then {alt pressed}
  107. if (wVirtualKeyCode >= $60) and (wVirtualKeyCode <= $69) then {0..9 on NumBlock}
  108. begin
  109. if length (altNumBuffer) = 3 then
  110. delete (altNumBuffer,1,1);
  111. altNumBuffer := altNumBuffer + char (wVirtualKeyCode-48);
  112. altNumActive := true;
  113. addThis := false;
  114. end else
  115. begin
  116. altNumActive := false;
  117. altNumBuffer := '';
  118. end;
  119. if addThis then
  120. begin
  121. keyboardeventqueue[nextfreekeyevent]:=
  122. ir.Event.KeyEvent;
  123. incqueueindex(nextfreekeyevent);
  124. end;
  125. end;
  126. lastShiftState := transShiftState (dwControlKeyState); {save it for PollShiftStateEvent}
  127. SetEvent (newKeyEvent); {event that a new key is available}
  128. LeaveCriticalSection (lockVar);
  129. end
  130. else
  131. begin
  132. lastShiftState := transShiftState (dwControlKeyState); {save it for PollShiftStateEvent}
  133. {for alt-number we have to look for alt-key release}
  134. if altNumActive then
  135. begin
  136. if (wVirtualKeyCode = $12) then {alt-released}
  137. begin
  138. if altNumBuffer <> '' then {numbers with alt pressed?}
  139. begin
  140. Val (altNumBuffer, c, i);
  141. if (i = 0) and (c <= 255) then {valid number?}
  142. begin {add to queue}
  143. fillchar (ir, sizeof (ir), 0);
  144. bKeyDown := true;
  145. AsciiChar := char (c);
  146. {and add to queue}
  147. EnterCriticalSection (lockVar);
  148. keyboardeventqueue[nextfreekeyevent]:=ir.Event.KeyEvent;
  149. incqueueindex(nextfreekeyevent);
  150. SetEvent (newKeyEvent); {event that a new key is available}
  151. LeaveCriticalSection (lockVar);
  152. end;
  153. end;
  154. altNumActive := false; {clear alt-buffer}
  155. altNumBuffer := '';
  156. end;
  157. end;
  158. end;
  159. end;
  160. end;
  161. procedure SysInitKeyboard;
  162. begin
  163. KeyBoardLayout:=GetKeyboardLayout(0);
  164. lastShiftState := 0;
  165. FlushConsoleInputBuffer(StdInputHandle);
  166. newKeyEvent := CreateEvent (nil, // address of security attributes
  167. true, // flag for manual-reset event
  168. false, // flag for initial state
  169. nil); // address of event-object name
  170. if newKeyEvent = INVALID_HANDLE_VALUE then
  171. begin
  172. // what to do here ????
  173. RunError (217);
  174. end;
  175. InitializeCriticalSection (lockVar);
  176. altNumActive := false;
  177. altNumBuffer := '';
  178. nextkeyevent:=0;
  179. nextfreekeyevent:=0;
  180. SetKeyboardEventHandler (@HandleKeyboard);
  181. end;
  182. procedure SysDoneKeyboard;
  183. begin
  184. SetKeyboardEventHandler(nil); {hangs???}
  185. DeleteCriticalSection (lockVar);
  186. FlushConsoleInputBuffer(StdInputHandle);
  187. closeHandle (newKeyEvent);
  188. end;
  189. {$define USEKEYCODES}
  190. {Translatetable Win32 -> Dos for Special Keys = Function Key, Cursor Keys
  191. and Keys other than numbers on numblock (to make fv happy) }
  192. {combinations under dos: Shift+Ctrl: same as Ctrl
  193. Shift+Alt : same as alt
  194. Ctrl+Alt : nothing (here we get it like alt)}
  195. {$ifdef USEKEYCODES}
  196. { use positive values for ScanCode we want to set
  197. 0 for key where we should leave the scancode
  198. -1 for OEM specifc keys
  199. -2 for unassigned
  200. -3 for Kanji systems ???
  201. }
  202. const
  203. Unassigned = -2;
  204. Kanji = -3;
  205. OEM_specific = -1;
  206. KeyToQwertyScan : array [0..255] of integer =
  207. (
  208. { 00 } 0,
  209. { 01 VK_LBUTTON } 0,
  210. { 02 VK_RBUTTON } 0,
  211. { 03 VK_CANCEL } 0,
  212. { 04 VK_MBUTTON } 0,
  213. { 05 unassigned } -2,
  214. { 06 unassigned } -2,
  215. { 07 unassigned } -2,
  216. { 08 VK_BACK } $E,
  217. { 09 VK_TAB } $F,
  218. { 0A unassigned } -2,
  219. { 0B unassigned } -2,
  220. { 0C VK_CLEAR ?? } 0,
  221. { 0D VK_RETURN } 0,
  222. { 0E unassigned } -2,
  223. { 0F unassigned } -2,
  224. { 10 VK_SHIFT } 0,
  225. { 11 VK_CONTROL } 0,
  226. { 12 VK_MENU (Alt key) } 0,
  227. { 13 VK_PAUSE } 0,
  228. { 14 VK_CAPITAL (Caps Lock) } 0,
  229. { 15 Reserved for Kanji systems} -3,
  230. { 16 Reserved for Kanji systems} -3,
  231. { 17 Reserved for Kanji systems} -3,
  232. { 18 Reserved for Kanji systems} -3,
  233. { 19 Reserved for Kanji systems} -3,
  234. { 1A unassigned } -2,
  235. { 1B VK_ESCAPE } $1,
  236. { 1C Reserved for Kanji systems} -3,
  237. { 1D Reserved for Kanji systems} -3,
  238. { 1E Reserved for Kanji systems} -3,
  239. { 1F Reserved for Kanji systems} -3,
  240. { 20 VK_SPACE} 0,
  241. { 21 VK_PRIOR (PgUp) } 0,
  242. { 22 VK_NEXT (PgDown) } 0,
  243. { 23 VK_END } 0,
  244. { 24 VK_HOME } 0,
  245. { 25 VK_LEFT } 0,
  246. { 26 VK_UP } 0,
  247. { 27 VK_RIGHT } 0,
  248. { 28 VK_DOWN } 0,
  249. { 29 VK_SELECT ??? } 0,
  250. { 2A OEM specific !! } -1,
  251. { 2B VK_EXECUTE } 0,
  252. { 2C VK_SNAPSHOT } 0,
  253. { 2D VK_INSERT } 0,
  254. { 2E VK_DELETE } 0,
  255. { 2F VK_HELP } 0,
  256. { 30 VK_0 '0' } 11,
  257. { 31 VK_1 '1' } 2,
  258. { 32 VK_2 '2' } 3,
  259. { 33 VK_3 '3' } 4,
  260. { 34 VK_4 '4' } 5,
  261. { 35 VK_5 '5' } 6,
  262. { 36 VK_6 '6' } 7,
  263. { 37 VK_7 '7' } 8,
  264. { 38 VK_8 '8' } 9,
  265. { 39 VK_9 '9' } 10,
  266. { 3A unassigned } -2,
  267. { 3B unassigned } -2,
  268. { 3C unassigned } -2,
  269. { 3D unassigned } -2,
  270. { 3E unassigned } -2,
  271. { 3F unassigned } -2,
  272. { 40 unassigned } -2,
  273. { 41 VK_A 'A' } $1E,
  274. { 42 VK_B 'B' } $30,
  275. { 43 VK_C 'C' } $2E,
  276. { 44 VK_D 'D' } $20,
  277. { 45 VK_E 'E' } $12,
  278. { 46 VK_F 'F' } $21,
  279. { 47 VK_G 'G' } $22,
  280. { 48 VK_H 'H' } $23,
  281. { 49 VK_I 'I' } $17,
  282. { 4A VK_J 'J' } $24,
  283. { 4B VK_K 'K' } $25,
  284. { 4C VK_L 'L' } $26,
  285. { 4D VK_M 'M' } $32,
  286. { 4E VK_N 'N' } $31,
  287. { 4F VK_O 'O' } $18,
  288. { 50 VK_P 'P' } $19,
  289. { 51 VK_Q 'Q' } $10,
  290. { 52 VK_R 'R' } $13,
  291. { 53 VK_S 'S' } $1F,
  292. { 54 VK_T 'T' } $14,
  293. { 55 VK_U 'U' } $16,
  294. { 56 VK_V 'V' } $2F,
  295. { 57 VK_W 'W' } $11,
  296. { 58 VK_X 'X' } $2D,
  297. { 59 VK_Y 'Y' } $15,
  298. { 5A VK_Z 'Z' } $2C,
  299. { 5B unassigned } -2,
  300. { 5C unassigned } -2,
  301. { 5D unassigned } -2,
  302. { 5E unassigned } -2,
  303. { 5F unassigned } -2,
  304. { 60 VK_NUMPAD0 NumKeyPad '0' } 11,
  305. { 61 VK_NUMPAD1 NumKeyPad '1' } 2,
  306. { 62 VK_NUMPAD2 NumKeyPad '2' } 3,
  307. { 63 VK_NUMPAD3 NumKeyPad '3' } 4,
  308. { 64 VK_NUMPAD4 NumKeyPad '4' } 5,
  309. { 65 VK_NUMPAD5 NumKeyPad '5' } 6,
  310. { 66 VK_NUMPAD6 NumKeyPad '6' } 7,
  311. { 67 VK_NUMPAD7 NumKeyPad '7' } 8,
  312. { 68 VK_NUMPAD8 NumKeyPad '8' } 9,
  313. { 69 VK_NUMPAD9 NumKeyPad '9' } 10,
  314. { 6A VK_MULTIPLY } 0,
  315. { 6B VK_ADD } 0,
  316. { 6C VK_SEPARATOR } 0,
  317. { 6D VK_SUBSTRACT } 0,
  318. { 6E VK_DECIMAL } 0,
  319. { 6F VK_DIVIDE } 0,
  320. { 70 VK_F1 'F1' } $3B,
  321. { 71 VK_F2 'F2' } $3C,
  322. { 72 VK_F3 'F3' } $3D,
  323. { 73 VK_F4 'F4' } $3E,
  324. { 74 VK_F5 'F5' } $3F,
  325. { 75 VK_F6 'F6' } $40,
  326. { 76 VK_F7 'F7' } $41,
  327. { 77 VK_F8 'F8' } $42,
  328. { 78 VK_F9 'F9' } $43,
  329. { 79 VK_F10 'F10' } $44,
  330. { 7A VK_F11 'F11' } $57,
  331. { 7B VK_F12 'F12' } $58,
  332. { 7C VK_F13 } 0,
  333. { 7D VK_F14 } 0,
  334. { 7E VK_F15 } 0,
  335. { 7F VK_F16 } 0,
  336. { 80 VK_F17 } 0,
  337. { 81 VK_F18 } 0,
  338. { 82 VK_F19 } 0,
  339. { 83 VK_F20 } 0,
  340. { 84 VK_F21 } 0,
  341. { 85 VK_F22 } 0,
  342. { 86 VK_F23 } 0,
  343. { 87 VK_F24 } 0,
  344. { 88 unassigned } -2,
  345. { 89 VK_NUMLOCK } 0,
  346. { 8A VK_SCROLL } 0,
  347. { 8B unassigned } -2,
  348. { 8C unassigned } -2,
  349. { 8D unassigned } -2,
  350. { 8E unassigned } -2,
  351. { 8F unassigned } -2,
  352. { 90 unassigned } -2,
  353. { 91 unassigned } -2,
  354. { 92 unassigned } -2,
  355. { 93 unassigned } -2,
  356. { 94 unassigned } -2,
  357. { 95 unassigned } -2,
  358. { 96 unassigned } -2,
  359. { 97 unassigned } -2,
  360. { 98 unassigned } -2,
  361. { 99 unassigned } -2,
  362. { 9A unassigned } -2,
  363. { 9B unassigned } -2,
  364. { 9C unassigned } -2,
  365. { 9D unassigned } -2,
  366. { 9E unassigned } -2,
  367. { 9F unassigned } -2,
  368. { A0 unassigned } -2,
  369. { A1 unassigned } -2,
  370. { A2 unassigned } -2,
  371. { A3 unassigned } -2,
  372. { A4 unassigned } -2,
  373. { A5 unassigned } -2,
  374. { A6 unassigned } -2,
  375. { A7 unassigned } -2,
  376. { A8 unassigned } -2,
  377. { A9 unassigned } -2,
  378. { AA unassigned } -2,
  379. { AB unassigned } -2,
  380. { AC unassigned } -2,
  381. { AD unassigned } -2,
  382. { AE unassigned } -2,
  383. { AF unassigned } -2,
  384. { B0 unassigned } -2,
  385. { B1 unassigned } -2,
  386. { B2 unassigned } -2,
  387. { B3 unassigned } -2,
  388. { B4 unassigned } -2,
  389. { B5 unassigned } -2,
  390. { B6 unassigned } -2,
  391. { B7 unassigned } -2,
  392. { B8 unassigned } -2,
  393. { B9 unassigned } -2,
  394. { BA OEM specific } 0,
  395. { BB OEM specific } 0,
  396. { BC OEM specific } 0,
  397. { BD OEM specific } 0,
  398. { BE OEM specific } 0,
  399. { BF OEM specific } 0,
  400. { C0 OEM specific } 0,
  401. { C1 unassigned } -2,
  402. { C2 unassigned } -2,
  403. { C3 unassigned } -2,
  404. { C4 unassigned } -2,
  405. { C5 unassigned } -2,
  406. { C6 unassigned } -2,
  407. { C7 unassigned } -2,
  408. { C8 unassigned } -2,
  409. { C9 unassigned } -2,
  410. { CA unassigned } -2,
  411. { CB unassigned } -2,
  412. { CC unassigned } -2,
  413. { CD unassigned } -2,
  414. { CE unassigned } -2,
  415. { CF unassigned } -2,
  416. { D0 unassigned } -2,
  417. { D1 unassigned } -2,
  418. { D2 unassigned } -2,
  419. { D3 unassigned } -2,
  420. { D4 unassigned } -2,
  421. { D5 unassigned } -2,
  422. { D6 unassigned } -2,
  423. { D7 unassigned } -2,
  424. { D8 unassigned } -2,
  425. { D9 unassigned } -2,
  426. { DA unassigned } -2,
  427. { DB OEM specific } 0,
  428. { DC OEM specific } 0,
  429. { DD OEM specific } 0,
  430. { DE OEM specific } 0,
  431. { DF OEM specific } 0,
  432. { E0 OEM specific } 0,
  433. { E1 OEM specific } 0,
  434. { E2 OEM specific } 0,
  435. { E3 OEM specific } 0,
  436. { E4 OEM specific } 0,
  437. { E5 unassigned } -2,
  438. { E6 OEM specific } 0,
  439. { E7 unassigned } -2,
  440. { E8 unassigned } -2,
  441. { E9 OEM specific } 0,
  442. { EA OEM specific } 0,
  443. { EB OEM specific } 0,
  444. { EC OEM specific } 0,
  445. { ED OEM specific } 0,
  446. { EE OEM specific } 0,
  447. { EF OEM specific } 0,
  448. { F0 OEM specific } 0,
  449. { F1 OEM specific } 0,
  450. { F2 OEM specific } 0,
  451. { F3 OEM specific } 0,
  452. { F4 OEM specific } 0,
  453. { F5 OEM specific } 0,
  454. { F6 unassigned } -2,
  455. { F7 unassigned } -2,
  456. { F8 unassigned } -2,
  457. { F9 unassigned } -2,
  458. { FA unassigned } -2,
  459. { FB unassigned } -2,
  460. { FC unassigned } -2,
  461. { FD unassigned } -2,
  462. { FE unassigned } -2,
  463. { FF unassigned } -2
  464. );
  465. {$endif USEKEYCODES}
  466. type TTEntryT = packed record
  467. n,s,c,a : byte; {normal,shift, ctrl, alt, normal only for f11,f12}
  468. end;
  469. CONST
  470. DosTT : ARRAY [$3B..$58] OF TTEntryT =
  471. ((n : $3B; s : $54; c : $5E; a: $68), {3B F1}
  472. (n : $3C; s : $55; c : $5F; a: $69), {3C F2}
  473. (n : $3D; s : $56; c : $60; a: $6A), {3D F3}
  474. (n : $3E; s : $57; c : $61; a: $6B), {3E F4}
  475. (n : $3F; s : $58; c : $62; a: $6C), {3F F5}
  476. (n : $40; s : $59; c : $63; a: $6D), {40 F6}
  477. (n : $41; s : $5A; c : $64; a: $6E), {41 F7}
  478. (n : $42; s : $5B; c : $65; a: $6F), {42 F8}
  479. (n : $43; s : $5C; c : $66; a: $70), {43 F9}
  480. (n : $44; s : $5D; c : $67; a: $71), {44 F10}
  481. (n : $45; s : $00; c : $00; a: $00), {45 ???}
  482. (n : $46; s : $00; c : $00; a: $00), {46 ???}
  483. (n : $47; s : $47; c : $77; a: $97), {47 Home}
  484. (n : $48; s : $00; c : $8D; a: $98), {48 Up}
  485. (n : $49; s : $49; c : $84; a: $99), {49 PgUp}
  486. (n : $4A; s : $00; c : $8E; a: $4A), {4A -}
  487. (n : $4B; s : $4B; c : $73; a: $9B), {4B Left}
  488. (n : $4C; s : $00; c : $00; a: $00), {4C ???}
  489. (n : $4D; s : $4D; c : $74; a: $9D), {4D Right}
  490. (n : $4E; s : $00; c : $90; a: $4E), {4E +}
  491. (n : $4F; s : $4F; c : $75; a: $9F), {4F End}
  492. (n : $50; s : $50; c : $91; a: $A0), {50 Down}
  493. (n : $51; s : $51; c : $76; a: $A1), {51 PgDown}
  494. (n : $52; s : $52; c : $92; a: $A2), {52 Insert}
  495. (n : $53; s : $53; c : $93; a: $A3), {53 Del}
  496. (n : $54; s : $00; c : $00; a: $00), {54 ???}
  497. (n : $55; s : $00; c : $00; a: $00), {55 ???}
  498. (n : $56; s : $00; c : $00; a: $00), {56 ???}
  499. (n : $85; s : $87; c : $89; a: $8B), {57 F11}
  500. (n : $86; s : $88; c : $8A; a: $8C)); {58 F12}
  501. DosTT09 : ARRAY [$02..$0F] OF TTEntryT =
  502. ((n : $00; s : $00; c : $00; a: $78), {02 1 }
  503. (n : $00; s : $00; c : $00; a: $79), {03 2 }
  504. (n : $00; s : $00; c : $00; a: $7A), {04 3 }
  505. (n : $00; s : $00; c : $00; a: $7B), {05 4 }
  506. (n : $00; s : $00; c : $00; a: $7C), {06 5 }
  507. (n : $00; s : $00; c : $00; a: $7D), {07 6 }
  508. (n : $00; s : $00; c : $00; a: $7E), {08 7 }
  509. (n : $00; s : $00; c : $00; a: $7F), {09 8 }
  510. (n : $00; s : $00; c : $00; a: $80), {0A 9 }
  511. (n : $00; s : $00; c : $00; a: $81), {0B 0 }
  512. (n : $00; s : $00; c : $00; a: $82), {0C ß }
  513. (n : $00; s : $00; c : $00; a: $00), {0D}
  514. (n : $00; s : $09; c : $00; a: $00), {0E Backspace}
  515. (n : $00; s : $0F; c : $94; a: $00)); {0F Tab }
  516. function TranslateKey (t : TKeyEventRecord) : TKeyEvent;
  517. var key : TKeyEvent;
  518. ss : byte;
  519. {$ifdef USEKEYCODES}
  520. ScanCode : byte;
  521. {$endif USEKEYCODES}
  522. b : byte;
  523. begin
  524. Key := 0;
  525. if t.bKeyDown then
  526. begin
  527. { ascii-char is <> 0 if not a specal key }
  528. { we return it here otherwise we have to translate more later }
  529. if t.AsciiChar <> #0 then
  530. begin
  531. {drivers needs scancode, we return it here as under dos and linux
  532. with $03000000 = the lowest two bytes is the physical representation}
  533. {$ifdef USEKEYCODES}
  534. Scancode:=KeyToQwertyScan[t.wVirtualKeyCode AND $00FF];
  535. If ScanCode>0 then
  536. t.wVirtualScanCode:=ScanCode;
  537. Key := byte (t.AsciiChar) + (t.wVirtualScanCode shl 8) + $03000000;
  538. ss := transShiftState (t.dwControlKeyState);
  539. key := key or (ss shl 16);
  540. if (ss and kbAlt <> 0) and (t.dwControlKeyState and RIGHT_ALT_PRESSED = 0) then
  541. key := key and $FFFFFF00;
  542. {$else not USEKEYCODES}
  543. Key := byte (t.AsciiChar) + ((t.wVirtualScanCode AND $00FF) shl 8) + $03000000;
  544. {$endif not USEKEYCODES}
  545. end else
  546. begin
  547. {$ifdef USEKEYCODES}
  548. Scancode:=KeyToQwertyScan[t.wVirtualKeyCode AND $00FF];
  549. If ScanCode>0 then
  550. t.wVirtualScanCode:=ScanCode;
  551. {$endif not USEKEYCODES}
  552. translateKey := 0;
  553. { ignore shift,ctrl,alt,numlock,capslock alone }
  554. case t.wVirtualKeyCode of
  555. $0010, {shift}
  556. $0011, {ctrl}
  557. $0012, {alt}
  558. $0014, {capslock}
  559. $0090, {numlock}
  560. $0091, {scrollock}
  561. { This should be handled !! }
  562. { these last two are OEM specific
  563. this is not good !!! }
  564. $00DC, {^ : next key i.e. a is modified }
  565. { Strange on my keyboard this corresponds to double point over i or u PM }
  566. $00DD: exit; {´ and ` : next key i.e. e is modified }
  567. end;
  568. key := $03000000 + (t.wVirtualScanCode shl 8); { make lower 8 bit=0 like under dos }
  569. end;
  570. { Handling of ~ key as AltGr 2 }
  571. { This is also French keyboard specific !! }
  572. { but without this I can not get a ~ !! PM }
  573. if (t.wVirtualKeyCode=$32) and
  574. (KeyBoardLayout = FrenchKeyboard) and
  575. (t.dwControlKeyState and RIGHT_ALT_PRESSED <> 0) then
  576. key:=(key and $ffffff00) or ord('~');
  577. { ok, now add Shift-State }
  578. ss := transShiftState (t.dwControlKeyState);
  579. key := key or (ss shl 16);
  580. { Reset Ascii-Char if Alt+Key, fv needs that, may be we
  581. need it for other special keys too
  582. 18 Sept 1999 AD: not for right Alt i.e. for AltGr+ß = \ on german keyboard }
  583. if ((ss and kbAlt <> 0) and (t.dwControlKeyState and RIGHT_ALT_PRESSED = 0)) or
  584. (*
  585. { yes, we need it for cursor keys, 25=left, 26=up, 27=right,28=down}
  586. {aggg, this will not work because esc is also virtualKeyCode 27!!}
  587. {if (t.wVirtualKeyCode >= 25) and (t.wVirtualKeyCode <= 28) then}
  588. no VK_ESCAPE is $1B !!
  589. there was a mistake :
  590. VK_LEFT is $25 not 25 !! *)
  591. { not $2E VK_DELETE because its only the Keypad point !! PM }
  592. (t.wVirtualKeyCode in [$21..$28,$2C,$2D,$2F]) then
  593. { if t.wVirtualScanCode in [$47..$49,$4b,$4d,$4f,$50..$53] then}
  594. key := key and $FFFFFF00;
  595. {and translate to dos-scancodes to make fv happy, we will convert this
  596. back in translateKeyEvent}
  597. if (t.dwControlKeyState and RIGHT_ALT_PRESSED) = 0 then {not for alt-gr}
  598. if (t.wVirtualScanCode >= low (DosTT)) and
  599. (t.wVirtualScanCode <= high (dosTT)) then
  600. begin
  601. b := 0;
  602. if (ss and kbAlt) <> 0 then
  603. b := DosTT[t.wVirtualScanCode].a
  604. else
  605. if (ss and kbCtrl) <> 0 then
  606. b := DosTT[t.wVirtualScanCode].c
  607. else
  608. if (ss and kbShift) <> 0 then
  609. b := DosTT[t.wVirtualScanCode].s
  610. else
  611. b := DosTT[t.wVirtualScanCode].n;
  612. if b <> 0 then
  613. key := (key and $FFFF00FF) or (longint (b) shl 8);
  614. end;
  615. {Alt-0 to Alt-9}
  616. if (t.dwControlKeyState and RIGHT_ALT_PRESSED) = 0 then {not for alt-gr}
  617. if (t.wVirtualScanCode >= low (DosTT09)) and
  618. (t.wVirtualScanCode <= high (dosTT09)) then
  619. begin
  620. b := 0;
  621. if (ss and kbAlt) <> 0 then
  622. b := DosTT09[t.wVirtualScanCode].a
  623. else
  624. if (ss and kbCtrl) <> 0 then
  625. b := DosTT09[t.wVirtualScanCode].c
  626. else
  627. if (ss and kbShift) <> 0 then
  628. b := DosTT09[t.wVirtualScanCode].s
  629. else
  630. b := DosTT09[t.wVirtualScanCode].n;
  631. if b <> 0 then
  632. key := (key and $FFFF0000) or (longint (b) shl 8);
  633. end;
  634. TranslateKey := key;
  635. end;
  636. translateKey := Key;
  637. end;
  638. function SysGetKeyEvent: TKeyEvent;
  639. var t : TKeyEventRecord;
  640. key : TKeyEvent;
  641. begin
  642. key := 0;
  643. repeat
  644. if getKeyEventFromQueueWait (t) then
  645. key := translateKey (t);
  646. until key <> 0;
  647. {$ifdef DEBUG}
  648. last_ir.Event.KeyEvent:=t;
  649. {$endif DEBUG}
  650. SysGetKeyEvent := key;
  651. end;
  652. function SysPollKeyEvent: TKeyEvent;
  653. var t : TKeyEventRecord;
  654. k : TKeyEvent;
  655. begin
  656. SysPollKeyEvent := 0;
  657. if getKeyEventFromQueue (t, true) then
  658. begin
  659. { we get an enty for shift, ctrl, alt... }
  660. k := translateKey (t);
  661. while (k = 0) do
  662. begin
  663. getKeyEventFromQueue (t, false); {remove it}
  664. if not getKeyEventFromQueue (t, true) then exit;
  665. k := translateKey (t)
  666. end;
  667. SysPollKeyEvent := k;
  668. end;
  669. end;
  670. function SysTranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  671. begin
  672. if KeyEvent and $03000000 = $03000000 then
  673. begin
  674. if KeyEvent and $000000FF <> 0 then
  675. begin
  676. SysTranslateKeyEvent := KeyEvent and $00FFFFFF;
  677. exit;
  678. end;
  679. {translate function-keys and other specials, ascii-codes are already ok}
  680. case (KeyEvent AND $0000FF00) shr 8 of
  681. {F1..F10}
  682. $3B..$44 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $3B + $02000000;
  683. {F11,F12}
  684. $85..$86 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $85 + $02000000;
  685. {Shift F1..F10}
  686. $54..$5D : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $54 + $02000000;
  687. {Shift F11,F12}
  688. $87..$88 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $87 + $02000000;
  689. {Alt F1..F10}
  690. $68..$71 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $68 + $02000000;
  691. {Alt F11,F12}
  692. $8B..$8C : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $8B + $02000000;
  693. {Ctrl F1..F10}
  694. $5E..$67 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $5E + $02000000;
  695. {Ctrl F11,F12}
  696. $89..$8A : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $89 + $02000000;
  697. {normal,ctrl,alt}
  698. $47,$77,$97 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdHome + $02000000;
  699. $48,$8D,$98 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdUp + $02000000;
  700. $49,$84,$99 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdPgUp + $02000000;
  701. $4b,$73,$9B : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdLeft + $02000000;
  702. $4d,$74,$9D : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdRight + $02000000;
  703. $4f,$75,$9F : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdEnd + $02000000;
  704. $50,$91,$A0 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdDown + $02000000;
  705. $51,$76,$A1 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdPgDn + $02000000;
  706. $52,$92,$A2 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdInsert + $02000000;
  707. $53,$93,$A3 : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdDelete + $02000000;
  708. else
  709. SysTranslateKeyEvent := KeyEvent;
  710. end;
  711. end else
  712. SysTranslateKeyEvent := KeyEvent;
  713. end;
  714. function SysGetShiftState: Byte;
  715. begin
  716. {may be better to save the last state and return that if no key is in buffer???}
  717. SysGetShiftState:= lastShiftState;
  718. end;
  719. Const
  720. SysKeyboardDriver : TKeyboardDriver = (
  721. InitDriver : @SysInitKeyBoard;
  722. DoneDriver : @SysDoneKeyBoard;
  723. GetKeyevent : @SysGetKeyEvent;
  724. PollKeyEvent : @SysPollKeyEvent;
  725. GetShiftState : @SysGetShiftState;
  726. TranslateKeyEvent : @SysTranslateKeyEvent;
  727. TranslateKeyEventUnicode : Nil;
  728. );
  729. begin
  730. SetKeyBoardDriver(SysKeyBoardDriver);
  731. end.
  732. {
  733. $Log$
  734. Revision 1.5 2001-09-21 21:33:36 michael
  735. + Merged driver support from fixbranch
  736. Revision 1.4 2001/08/05 12:23:57 peter
  737. * fixed for new input_record
  738. Revision 1.2.2.4 2001/09/21 21:20:43 michael
  739. + Added support for keyboard driver.
  740. + Added DefaultTranslateKeyEvent,DefaultTranslateKeyEventUnicode
  741. + PendingKeyEvent variable no longer public. Handling of this variable is
  742. now done entirely by global functions. System dependent code should not
  743. need it, it is set automatically.
  744. + InitVideo DoneVideo will check whether the keyboard is initialized or not.
  745. Revision 1.2.2.3 2001/08/05 12:24:37 peter
  746. * fixed for new input_record
  747. Revision 1.2.2.2 2001/02/05 15:30:06 pierre
  748. * fix compiliing with -dDEBUG
  749. Revision 1.3 2001/05/20 12:08:17 peter
  750. * fixed to compile with debug
  751. Revision 1.2 2001/01/14 22:20:00 peter
  752. * slightly optimized event handling (merged)
  753. Revision 1.1 2001/01/13 11:03:59 peter
  754. * API 2 RTL commit
  755. }