keyboard.inc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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. var
  11. PendingKeyEvent : TKeyEvent;
  12. procedure PutKeyEvent(KeyEvent: TKeyEvent);
  13. begin
  14. PendingKeyEvent := KeyEvent;
  15. end;
  16. function GetKeyEventFlags(KeyEvent: TKeyEvent): Byte;
  17. begin
  18. GetKeyEventFlags := (KeyEvent and $FF000000) shr 24;
  19. end;
  20. function GetKeyEventChar(KeyEvent: TKeyEvent): Char;
  21. begin
  22. if KeyEvent and $03000000 = $00000000 then
  23. GetKeyEventChar := Chr(KeyEvent and $000000FF)
  24. else
  25. GetKeyEventChar := #0;
  26. end;
  27. function GetKeyEventUniCode(KeyEvent: TKeyEvent): Word;
  28. begin
  29. if KeyEvent and $03000000 = $01000000 then
  30. GetKeyEventUniCode := KeyEvent and $0000FFFF
  31. else
  32. GetKeyEventUniCode := 0;
  33. end;
  34. function GetKeyEventCode(KeyEvent: TKeyEvent): Word;
  35. begin
  36. GetKeyEventCode := KeyEvent and $0000FFFF
  37. end;
  38. function GetKeyEventShiftState(KeyEvent: TKeyEvent): Byte;
  39. begin
  40. GetKeyEventShiftState := (KeyEvent and $00FF0000) shr 16;
  41. end;
  42. function IsFunctionKey(KeyEvent: TKeyEvent): Boolean;
  43. begin
  44. IsFunctionKey := KeyEvent and $03000000 = $02000000;
  45. end;
  46. Var
  47. KeyBoardInitialized : Boolean;
  48. CurrentKeyboardDriver : TKeyboardDriver;
  49. procedure InitKeyboard;
  50. begin
  51. If Not KeyboardInitialized then
  52. begin
  53. If Assigned(CurrentKeyBoardDriver.InitDriver) Then
  54. CurrentKeyBoardDriver.InitDriver();
  55. KeyboardInitialized:=True;
  56. end;
  57. end;
  58. procedure DoneKeyboard;
  59. begin
  60. If KeyboardInitialized then
  61. begin
  62. If Assigned(CurrentKeyBoardDriver.DoneDriver) Then
  63. CurrentKeyBoardDriver.DoneDriver();
  64. KeyboardInitialized:=False;
  65. end;
  66. end;
  67. function GetKeyEvent: TKeyEvent;
  68. begin
  69. if PendingKeyEvent<>0 then
  70. begin
  71. GetKeyEvent:=PendingKeyEvent;
  72. PendingKeyEvent:=0;
  73. exit;
  74. end;
  75. If Assigned(CurrentKeyBoardDriver.GetKeyEvent) Then
  76. GetKeyEvent:=CurrentKeyBoardDriver.GetKeyEvent()
  77. else
  78. GetKeyEvent:=0;
  79. end;
  80. function PollKeyEvent: TKeyEvent;
  81. begin
  82. if PendingKeyEvent<>0 then
  83. exit(PendingKeyEvent);
  84. If Assigned(CurrentKeyBoardDriver.PollKeyEvent) Then
  85. begin
  86. PollKeyEvent:=CurrentKeyBoardDriver.PollKeyEvent();
  87. // PollKeyEvent:=PendingKeyEvent;
  88. // Must be done inside every keyboard specific
  89. // PollKeyEvent procedure
  90. // to avoid problems if that procedure is called directly PM
  91. end
  92. else
  93. PollKeyEvent:=0;
  94. end;
  95. Function SetKeyboardDriver (Const Driver : TKeyboardDriver) : Boolean;
  96. begin
  97. If Not KeyBoardInitialized then
  98. CurrentKeyBoardDriver:=Driver;
  99. SetKeyboardDriver:=Not KeyBoardInitialized;
  100. end;
  101. Procedure GetKeyboardDriver (Var Driver : TKeyboardDriver);
  102. begin
  103. Driver:=CurrentKeyBoardDriver;
  104. end;
  105. function PollShiftStateEvent: TKeyEvent;
  106. begin
  107. If Assigned(CurrentKeyBoardDriver.GetShiftState) then
  108. PollShiftStateEvent:=CurrentKeyBoardDriver.GetShiftState() shl 16
  109. else
  110. PollShiftStateEvent:=0;
  111. end;
  112. function DefaultTranslateKeyEventUniCode(KeyEvent: TKeyEvent): TKeyEvent;
  113. begin
  114. DefaultTranslateKeyEventUniCode:=KeyEvent;
  115. ErrorCode:=errKbdNotImplemented;
  116. end;
  117. function TranslateKeyEventUniCode(KeyEvent: TKeyEvent): TKeyEvent;
  118. begin
  119. if Assigned(CurrentKeyBoardDriver.TranslateKeyEventUnicode) then
  120. TranslateKeyEventUnicode:=CurrentKeyBoardDriver.TranslateKeyEventUnicode(KeyEvent)
  121. else
  122. TranslateKeyEventUnicode:=DefaultTranslateKeyEventUnicode(KeyEvent);
  123. end;
  124. type
  125. TTranslationEntry = packed record
  126. Min, Max: Byte;
  127. Offset: Word;
  128. end;
  129. const
  130. TranslationTableEntries = 12;
  131. TranslationTable: array [1..TranslationTableEntries] of TTranslationEntry =
  132. ((Min: $3B; Max: $44; Offset: kbdF1), { function keys F1-F10 }
  133. (Min: $54; Max: $5D; Offset: kbdF1), { Shift fn keys F1-F10 }
  134. (Min: $5E; Max: $67; Offset: kbdF1), { Ctrl fn keys F1-F10 }
  135. (Min: $68; Max: $71; Offset: kbdF1), { Alt fn keys F1-F10 }
  136. (Min: $85; Max: $86; Offset: kbdF11), { function keys F11-F12 }
  137. (Min: $87; Max: $88; Offset: kbdF11), { Shift+function keys F11-F12 }
  138. (Min: $89; Max: $8A; Offset: kbdF11), { Ctrl+function keys F11-F12 }
  139. (Min: $8B; Max: $8C; Offset: kbdF11), { Alt+function keys F11-F12 }
  140. (Min: $47; Max: $49; Offset: kbdHome), { Keypad keys kbdHome-kbdPgUp }
  141. (Min: $4B; Max: $4D; Offset: kbdLeft), { Keypad keys kbdLeft-kbdRight }
  142. (Min: $4F; Max: $51; Offset: kbdEnd), { Keypad keys kbdEnd-kbdPgDn }
  143. (Min: $52; Max: $53; Offset: kbdInsert));
  144. function DefaultTranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  145. var
  146. I: Integer;
  147. ScanCode: Byte;
  148. begin
  149. if KeyEvent and $03000000 = $03000000 then
  150. begin
  151. if KeyEvent and $000000FF <> 0 then
  152. begin
  153. DefaultTranslateKeyEvent := KeyEvent and $00FFFFFF;
  154. exit;
  155. end
  156. else
  157. begin
  158. { This is a function key }
  159. ScanCode := (KeyEvent and $0000FF00) shr 8;
  160. for I := 1 to TranslationTableEntries do
  161. begin
  162. if (TranslationTable[I].Min <= ScanCode) and (ScanCode <= TranslationTable[I].Max) then
  163. begin
  164. DefaultTranslateKeyEvent := $02000000 + (KeyEvent and $00FF0000) +
  165. Byte(ScanCode - TranslationTable[I].Min) + TranslationTable[I].Offset;
  166. exit;
  167. end;
  168. end;
  169. end;
  170. end;
  171. DefaultTranslateKeyEvent := KeyEvent;
  172. end;
  173. function TranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  174. begin
  175. if Assigned(CurrentKeyBoardDriver.TranslateKeyEvent) then
  176. TranslateKeyEvent:=CurrentKeyBoardDriver.TranslateKeyEvent(KeyEvent)
  177. else
  178. TranslateKeyEvent:=DefaultTranslateKeyEvent(KeyEvent);
  179. end;
  180. { ---------------------------------------------------------------------
  181. KeyEvent to String representation section.
  182. ---------------------------------------------------------------------}
  183. Procedure AddToString (Var S : String; Const A : String);
  184. begin
  185. If Length(S)=0 then
  186. S:=A
  187. else
  188. S:=S+' '+A;
  189. end;
  190. Function IntToStr(Int : Longint) : String;
  191. begin
  192. Str(Int,IntToStr);
  193. end;
  194. Function ShiftStateToString(KeyEvent : TKeyEvent; UseLeftRight : Boolean) : String;
  195. Var
  196. S : Integer;
  197. T : String;
  198. begin
  199. S:=GetKeyEventShiftState(KeyEvent);
  200. T:='';
  201. If (S and kbShift)<>0 then
  202. begin
  203. if UseLeftRight then
  204. case (S and kbShift) of
  205. kbShift : AddToString(T,SLeftRight[1]+' '+SAnd+' '+SLeftRight[2]);
  206. kbLeftShift : AddToString(T,SLeftRight[1]);
  207. kbRightShift : AddToString(T,SLeftRight[2]);
  208. end;
  209. AddToString(T,SShift[1]);
  210. end;
  211. If (S and kbCtrl)<>0 Then
  212. AddToString(T,SShift[2]);
  213. If (S and kbAlt)<>0 Then
  214. AddToString(T,SShift[3]);
  215. ShiftStateToString:=T;
  216. end;
  217. Function FunctionKeyName (KeyCode : Word) : String;
  218. begin
  219. If ((KeyCode-KbdF1)<$1F) Then
  220. FunctionKeyName:='F'+IntToStr((KeyCode-KbdF1+1))
  221. else
  222. begin
  223. If (KeyCode-kbdHome)<($2F-$1F) then
  224. FunctionKeyName:=SKeyPad[(KeyCode-kbdHome)]
  225. else
  226. FunctionKeyName:=SUnknownFunctionKey + IntToStr(KeyCode);
  227. end;
  228. end;
  229. Function KeyEventToString(KeyEvent : TKeyEvent) : String;
  230. Var
  231. T : String;
  232. begin
  233. T:=ShiftStateToString(KeyEvent,False);
  234. Case GetKeyEventFlags(KeyEvent) of
  235. kbASCII : AddToString(T,GetKeyEventChar(KeyEvent));
  236. kbUniCode : AddToString(T,SUniCodeChar+IntToStr(GetKeyEventUniCode(Keyevent)));
  237. kbFnKey : AddToString(T,FunctionKeyName(GetKeyEventCode(KeyEvent)));
  238. // Not good, we need a GetKeyEventScanCode function !!
  239. kbPhys : AddToString(T,SScanCode+IntToStr(KeyEvent and $ffff));
  240. end;
  241. KeyEventToString:=T;
  242. end;
  243. const
  244. PrevCtrlBreakHandler: TCtrlBreakHandler = nil;
  245. function KbdCtrlBreakHandler (CtrlBreak: boolean): boolean;
  246. begin
  247. (* Earlier registered handlers (user specific) have priority. *)
  248. if Assigned (PrevCtrlBreakHandler) then
  249. if PrevCtrlBreakHandler (CtrlBreak) then
  250. begin
  251. KbdCtrlBreakHandler := true;
  252. Exit;
  253. end;
  254. (* If Ctrl-Break was pressed, either ignore it or allow default processing. *)
  255. if CtrlBreak then
  256. KbdCtrlBreakHandler := false
  257. else (* Ctrl-C pressed or not possible to distinguish *)
  258. begin
  259. PutKeyEvent ((kbCtrl shl 16) or 3);
  260. KbdCtrlBreakHandler := true;
  261. end;
  262. end;
  263. procedure SetKbdCtrlBreakHandler;
  264. begin
  265. PrevCtrlBreakHandler := SysSetCtrlBreakHandler (@KbdCtrlBreakHandler);
  266. if PrevCtrlBreakHandler = TCtrlBreakHandler (pointer (-1)) then
  267. PrevCtrlBreakHandler := nil;
  268. end;