keyboard.pp 25 KB

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