keyboard.pp 28 KB

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