keybrdh.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. const
  11. { We have an errorcode base of 1010 }
  12. errKbdBase = 1010;
  13. errKbdInitError = errKbdBase + 0;
  14. errKbdNotImplemented = errKbdBase + 1;
  15. type
  16. TKeyEvent = Cardinal;
  17. TKeyRecord = packed record
  18. {$IFDEF ENDIAN_LITTLE}
  19. KeyCode : Word;
  20. ShiftState, Flags : Byte;
  21. {$ELSE}
  22. Flags, ShiftState : Byte;
  23. KeyCode : Word;
  24. {$ENDIF}
  25. end;
  26. { The structure of a TKeyEvent follows in LSB-MSB order:
  27. 2 bytes: depending on flags either the physical representation of a key
  28. (under DOS scancode, ascii code pair), or the translated
  29. ASCII/unicode character
  30. 1 byte: shift-state when this key was pressed (or shortly after)
  31. 1 byte: flags, the following flags are defined:
  32. bit0-1
  33. 0: the lowest two bytes is the translated ASCII value
  34. 1: the lowest two bytes is the translated Unicode value
  35. (wide-AnsiChar)
  36. 2: the lowest two bytes is a function key, and the lowest
  37. two bytes contains its platform independent code
  38. 3: the lowest two bytes is the physical representation
  39. bit2
  40. 0: the key is pressed
  41. 1: the key is released (This event is not guaranteed to occur on all platforms)
  42. bit3-7 undefined, should be 0
  43. If there are two keys returning the same AnsiChar-code, there's no way to find
  44. out which one was pressed (Gray+ and Simple+). If you need to know which
  45. was pressed, you'll need to use the untranslated keycodes, which is system
  46. dependent. System dependent constants may be defined to cover those, with
  47. possibily having the same name (but different value). }
  48. TEnhancedShiftStateElement = (
  49. essShift, { either Left or Right Shift is pressed }
  50. essLeftShift,
  51. essRightShift,
  52. essCtrl, { either Left or Right Ctrl is pressed }
  53. essLeftCtrl,
  54. essRightCtrl,
  55. essAlt, { either Left or Right Alt is pressed, but *not* AltGr }
  56. essLeftAlt,
  57. essRightAlt, { only on keyboard layouts, without AltGr }
  58. essAltGr, { only on keyboard layouts, with AltGr instead of Right Alt }
  59. essCapsLockPressed,
  60. essCapsLockOn,
  61. essNumLockPressed,
  62. essNumLockOn,
  63. essScrollLockPressed,
  64. essScrollLockOn
  65. );
  66. TEnhancedShiftState = set of TEnhancedShiftStateElement;
  67. { Note: not all consoles are able to distinguish between Left and Right Shift,
  68. Ctrl and Alt.
  69. Valid examples:
  70. [essShift] - Either Left or Right Shift is
  71. pressed. Console is NOT able to
  72. distinguish between Left and Right
  73. Shift.
  74. [essShift,essLeftShift] - Left Shift is pressed. Console CAN
  75. distinguish between Left and Right
  76. Shift.
  77. [essShift,essRightShift] - Right shift is pressed. Console CAN
  78. distinguish between Left and Right
  79. Shift.
  80. [essShift,essLeftShift,essRightShift] - Both Left Shift and Right Shift are
  81. pressed. Console CAN distinguish
  82. between Left and Right Shift.
  83. Invalid examples (it is a bug, if a console driver ever generates these):
  84. [essLeftShift] - missing essShift
  85. [essRightShift] - missing essShift
  86. [essLeftShift,essRightShift] - missing essShift
  87. Exactly the same principle applies to essCtrl, essLeftCtrl and essRightCtrl.
  88. For Alt, it depends on whether the current keyboard layout has a Right Alt
  89. or an AltGr key. If it's Right Alt, then essAltGr will not be seen, and the
  90. same principle described above applies to essAlt, essLeftAlt and
  91. essRightAlt. If the keyboard layout has an AltGr key, instead of Right Alt,
  92. then essRightAlt is not generated. The AltGr key generates only essAltGr,
  93. without essAlt, so for keyboards with AltGr instead of Right Alt:
  94. [essAltGr] - AltGr is pressed.
  95. [essAlt,essLeftAlt] - Left Alt is pressed.
  96. [essAlt,essLeftAlt, essAltGr] - Both Left Alt and AltGr are pressed.
  97. [essAlt,essAltGr] - Both (usually Left) Alt and AltGr are pressed, but the
  98. console is unable to distinguish between Left Alt and
  99. Right Alt (if it existed and was not marked AltGr - in
  100. theory it is possible for someone to make a keyboard
  101. with three separate keys: Left Alt, Right Alt and AltGr).
  102. [essAlt,essLeftAlt,essRightAlt,essAltGr] - The keyboard has three separate
  103. keys: Left Alt, Right Alt and
  104. AltGr and they are all pressed.
  105. Note that Windows handles AltGr internally as Left Ctrl+Right Alt, which we
  106. detect and convert to essAltGr, but this makes it impossible to distinguish
  107. between Left Ctrl+AltGr and only AltGr, since there's no way to tell whether
  108. the Left Ctrl that Windows report is dummy or real, so we always assume it's
  109. dummy and remove it from the shift state, if AltGr was pressed.
  110. }
  111. TEnhancedKeyEvent = record
  112. VirtualKeyCode: Word; { device-independent identifier of the key }
  113. VirtualScanCode: Word; { device-dependent value, generated by the keyboard }
  114. UnicodeChar: WideChar; { the translated Unicode character }
  115. AsciiChar: AnsiChar; { the translated ASCII character }
  116. ShiftState: TEnhancedShiftState;
  117. Flags: Byte;
  118. end;
  119. const
  120. { The Nil value for the enhanced key event }
  121. NilEnhancedKeyEvent: TEnhancedKeyEvent = (
  122. VirtualKeyCode: 0;
  123. VirtualScanCode: 0;
  124. UnicodeChar: #0;
  125. AsciiChar: #0;
  126. ShiftState: [];
  127. Flags: 0;
  128. );
  129. { System independent function key codes }
  130. kbdF1 = $FF01;
  131. kbdF2 = $FF02;
  132. kbdF3 = $FF03;
  133. kbdF4 = $FF04;
  134. kbdF5 = $FF05;
  135. kbdF6 = $FF06;
  136. kbdF7 = $FF07;
  137. kbdF8 = $FF08;
  138. kbdF9 = $FF09;
  139. kbdF10 = $FF0A;
  140. kbdF11 = $FF0B;
  141. kbdF12 = $FF0C;
  142. kbdF13 = $FF0D;
  143. kbdF14 = $FF0E;
  144. kbdF15 = $FF0F;
  145. kbdF16 = $FF10;
  146. kbdF17 = $FF11;
  147. kbdF18 = $FF12;
  148. kbdF19 = $FF13;
  149. kbdF20 = $FF14;
  150. kbdLWin = $FF15;
  151. kbdRWin = $FF16;
  152. kbdApps = $FF17;
  153. { $15 - $1F reserved for future Fxx keys }
  154. kbdHome = $FF20;
  155. kbdUp = $FF21;
  156. kbdPgUp = $FF22;
  157. kbdLeft = $FF23;
  158. kbdMiddle = $FF24;
  159. kbdRight = $FF25;
  160. kbdEnd = $FF26;
  161. kbdDown = $FF27;
  162. kbdPgDn = $FF28;
  163. kbdInsert = $FF29;
  164. kbdDelete = $FF2A;
  165. { $2B - $2F reserved for future keypad keys }
  166. { possible flag values }
  167. kbASCII = $00;
  168. kbUniCode = $01;
  169. kbFnKey = $02;
  170. kbPhys = $03;
  171. kbReleased = $04;
  172. { shiftstate flags }
  173. kbLeftShift = 1;
  174. kbRightShift = 2;
  175. kbShift = kbLeftShift or kbRightShift;
  176. kbCtrl = 4;
  177. kbAlt = 8;
  178. { ---------------------------------------------------------------------
  179. Key names. Can be localized if needed.
  180. ---------------------------------------------------------------------}
  181. SShift : Array [1..3] of string[5] = ('SHIFT','CTRL','ALT');
  182. SLeftRight : Array [1..2] of string[5] = ('LEFT','RIGHT');
  183. SUnicodeChar : Shortstring = 'Unicode character ';
  184. SScanCode : Shortstring = 'Key with scancode ';
  185. SUnknownFunctionKey : Shortstring = 'Unknown function key : ';
  186. SAnd : Shortstring = 'AND';
  187. SKeyPad : Array [0..($FF2F-kbdHome)] of string[6] =
  188. ('Home','Up','PgUp','Left',
  189. 'Middle','Right','End','Down',
  190. 'PgDn','Insert','Delete','',
  191. '','','','');
  192. Type
  193. TKeyboardDriver = Record
  194. InitDriver : Procedure;
  195. DoneDriver : Procedure;
  196. GetKeyEvent : Function : TKeyEvent;
  197. PollKeyEvent : Function : TKeyEvent;
  198. GetShiftState : Function : Byte;
  199. TranslateKeyEvent : Function (KeyEvent: TKeyEvent): TKeyEvent;
  200. TranslateKeyEventUniCode : Function (KeyEvent: TKeyEvent): TKeyEvent;
  201. GetEnhancedKeyEvent : Function : TEnhancedKeyEvent;
  202. PollEnhancedKeyEvent : Function : TEnhancedKeyEvent;
  203. end;
  204. procedure InitKeyboard;
  205. { Initializes the keyboard interface, additional platform specific parameters
  206. can be passed by global variables (RawMode etc.) for the first implementation
  207. under DOS it does nothing }
  208. procedure DoneKeyboard;
  209. { Deinitializes the keyboard interface }
  210. function GetKeyEvent: TKeyEvent;
  211. { Returns the last keyevent, and waits for one if not available }
  212. procedure PutKeyEvent(KeyEvent: TKeyEvent);
  213. { Adds the given KeyEvent to the input queue. Please note that depending on
  214. the implementation this can hold only one value (NO FIFOs etc) }
  215. function PollKeyEvent: TKeyEvent;
  216. { Checks if a keyevent is available, and returns it if one is found. If no
  217. event is pending, it returns 0 }
  218. function PollShiftStateEvent: TKeyEvent;
  219. { Return the current shiftstate in a keyevent }
  220. function TranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  221. { Performs ASCII translation of the KeyEvent }
  222. function TranslateKeyEventUniCode(KeyEvent: TKeyEvent): TKeyEvent;
  223. { Performs Unicode translation of the KeyEvent }
  224. function GetKeyEventFlags(KeyEvent: TKeyEvent): Byte;
  225. { Returns the flags part of the given KeyEvent }
  226. function GetKeyEventChar(KeyEvent: TKeyEvent): AnsiChar;
  227. { Returns the charcode part of the given KeyEvent, if it contains a translated
  228. keycode }
  229. function GetKeyEventUniCode(KeyEvent: TKeyEvent): Word;
  230. { Returns the unicode part of the given KeyEvent, if it contains a translated
  231. unicode character }
  232. function GetKeyEventCode(KeyEvent: TKeyEvent): Word;
  233. { Returns the translated function keycode part of the given KeyEvent, if it
  234. contains a translated function keycode }
  235. function GetKeyEventShiftState(KeyEvent: TKeyEvent): Byte;
  236. { Returns the shift-state values of the given KeyEvent }
  237. function IsFunctionKey(KeyEvent: TKeyEvent): Boolean;
  238. { Returns true if the given key was a function key or not }
  239. Function SetKeyboardDriver (Const Driver : TKeyboardDriver) : Boolean;
  240. { Sets the keyboard driver to use }
  241. Procedure GetKeyboardDriver (Var Driver : TKeyboardDriver);
  242. { Returns the currently active keyboard driver }
  243. Function ShiftStateToString(KeyEvent : TKeyEvent; UseLeftRight : Boolean) : Shortstring;
  244. { Returns a string representation of a shift state as returned by
  245. pollshiftstate }
  246. Function FunctionKeyName (KeyCode : Word) : Shortstring;
  247. { Returns the name of a function key if the key is one of the special keys . }
  248. Function KeyEventToString(KeyEvent : TKeyEvent) : Shortstring;
  249. { Returns a string representation of the pressed key }
  250. function GetEnhancedKeyEvent: TEnhancedKeyEvent;
  251. { Returns the last keyevent, and waits for one if not available }
  252. function PollEnhancedKeyEvent: TEnhancedKeyEvent;
  253. { Checks if a keyevent is available, and returns it if one is found. If no
  254. event is pending, it returns 0 }
  255. function ConvertEnhancedToLegacyShiftState(const ShiftState: TEnhancedShiftState): Byte;
  256. { Converts an enhanced shift state (as in TEnhancedKeyEvent.ShiftState) to a
  257. legacy shift state (as returned by GetShiftState or GetKeyEventShiftState) }
  258. operator = (const a, b: TEnhancedKeyEvent) res: Boolean;