keyboard.inc 27 KB

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