keyboard.pp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686
  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 linux
  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. Const
  17. AltPrefix : byte = 0;
  18. ShiftPrefix : byte = 0;
  19. CtrlPrefix : byte = 0;
  20. Function RawReadKey:char;
  21. Function RawReadString : String;
  22. Function KeyPressed : Boolean;
  23. {$ifndef NotUseTree}
  24. Procedure AddSequence(Const St : String; Char,Scan :byte);
  25. Function FindSequence(Const St : String;var AChar, Ascan : byte) : boolean;
  26. {$endif NotUseTree}
  27. implementation
  28. uses
  29. Mouse,
  30. {$ifndef NotUseTree}
  31. Strings,
  32. TermInfo,
  33. {$endif NotUseTree}
  34. Linux;
  35. {$i keyboard.inc}
  36. var
  37. OldIO : TermIos;
  38. {$ifdef logging}
  39. f : text;
  40. {$endif logging}
  41. { list of all dos scancode for key giving 0 as char }
  42. Const
  43. kbNoKey = $00;
  44. kbAltEsc = $01;
  45. kbAltSpace = $02;
  46. kbCtrlIns = $04;
  47. kbShiftIns = $05;
  48. kbCtrlDel = $06;
  49. kbShiftDel = $07;
  50. kbAltBack = $08;
  51. kbAltShiftBack= $09;
  52. kbShiftTab = $0F;
  53. kbAltQ = $10;
  54. kbAltW = $11;
  55. kbAltE = $12;
  56. kbAltR = $13;
  57. kbAltT = $14;
  58. kbAltY = $15;
  59. kbAltU = $16;
  60. kbAltI = $17;
  61. kbAltO = $18;
  62. kbAltP = $19;
  63. kbAltLftBrack = $1A;
  64. kbAltRgtBrack = $1B;
  65. kbAltA = $1E;
  66. kbAltS = $1F;
  67. kbAltD = $20;
  68. kbAltF = $21;
  69. kbAltG = $22;
  70. kbAltH = $23;
  71. kbAltJ = $24;
  72. kbAltK = $25;
  73. kbAltL = $26;
  74. kbAltSemiCol = $27;
  75. kbAltQuote = $28;
  76. kbAltOpQuote = $29;
  77. kbAltBkSlash = $2B;
  78. kbAltZ = $2C;
  79. kbAltX = $2D;
  80. kbAltC = $2E;
  81. kbAltV = $2F;
  82. kbAltB = $30;
  83. kbAltN = $31;
  84. kbAltM = $32;
  85. kbAltComma = $33;
  86. kbAltPeriod = $34;
  87. kbAltSlash = $35;
  88. kbAltGreyAst = $37;
  89. kbF1 = $3B;
  90. kbF2 = $3C;
  91. kbF3 = $3D;
  92. kbF4 = $3E;
  93. kbF5 = $3F;
  94. kbF6 = $40;
  95. kbF7 = $41;
  96. kbF8 = $42;
  97. kbF9 = $43;
  98. kbF10 = $44;
  99. kbHome = $47;
  100. kbUp = $48;
  101. kbPgUp = $49;
  102. kbLeft = $4B;
  103. kbCenter = $4C;
  104. kbRight = $4D;
  105. kbAltGrayPlus = $4E;
  106. kbend = $4F;
  107. kbDown = $50;
  108. kbPgDn = $51;
  109. kbIns = $52;
  110. kbDel = $53;
  111. kbShiftF1 = $54;
  112. kbShiftF2 = $55;
  113. kbShiftF3 = $56;
  114. kbShiftF4 = $57;
  115. kbShiftF5 = $58;
  116. kbShiftF6 = $59;
  117. kbShiftF7 = $5A;
  118. kbShiftF8 = $5B;
  119. kbShiftF9 = $5C;
  120. kbShiftF10 = $5D;
  121. kbCtrlF1 = $5E;
  122. kbCtrlF2 = $5F;
  123. kbCtrlF3 = $60;
  124. kbCtrlF4 = $61;
  125. kbCtrlF5 = $62;
  126. kbCtrlF6 = $63;
  127. kbCtrlF7 = $64;
  128. kbCtrlF8 = $65;
  129. kbCtrlF9 = $66;
  130. kbCtrlF10 = $67;
  131. kbAltF1 = $68;
  132. kbAltF2 = $69;
  133. kbAltF3 = $6A;
  134. kbAltF4 = $6B;
  135. kbAltF5 = $6C;
  136. kbAltF6 = $6D;
  137. kbAltF7 = $6E;
  138. kbAltF8 = $6F;
  139. kbAltF9 = $70;
  140. kbAltF10 = $71;
  141. kbCtrlPrtSc = $72;
  142. kbCtrlLeft = $73;
  143. kbCtrlRight = $74;
  144. kbCtrlend = $75;
  145. kbCtrlPgDn = $76;
  146. kbCtrlHome = $77;
  147. kbAlt1 = $78;
  148. kbAlt2 = $79;
  149. kbAlt3 = $7A;
  150. kbAlt4 = $7B;
  151. kbAlt5 = $7C;
  152. kbAlt6 = $7D;
  153. kbAlt7 = $7E;
  154. kbAlt8 = $7F;
  155. kbAlt9 = $80;
  156. kbAlt0 = $81;
  157. kbAltMinus = $82;
  158. kbAltEqual = $83;
  159. kbCtrlPgUp = $84;
  160. kbF11 = $85;
  161. kbF12 = $86;
  162. kbShiftF11 = $87;
  163. kbShiftF12 = $88;
  164. kbCtrlF11 = $89;
  165. kbCtrlF12 = $8A;
  166. kbAltF11 = $8B;
  167. kbAltF12 = $8C;
  168. kbCtrlUp = $8D;
  169. kbCtrlMinus = $8E;
  170. kbCtrlCenter = $8F;
  171. kbCtrlGreyPlus= $90;
  172. kbCtrlDown = $91;
  173. kbCtrlTab = $94;
  174. kbAltHome = $97;
  175. kbAltUp = $98;
  176. kbAltPgUp = $99;
  177. kbAltLeft = $9B;
  178. kbAltRight = $9D;
  179. kbAltend = $9F;
  180. kbAltDown = $A0;
  181. kbAltPgDn = $A1;
  182. kbAltIns = $A2;
  183. kbAltDel = $A3;
  184. kbAltTab = $A5;
  185. {$ifdef Unused}
  186. type
  187. TKeyState = Record
  188. Normal, Shift, Ctrl, Alt : word;
  189. end;
  190. Const
  191. KeyStates : Array[0..255] of TKeyState
  192. (
  193. );
  194. {$endif Unused}
  195. Procedure SetRawMode(b:boolean);
  196. Var
  197. Tio : Termios;
  198. Begin
  199. TCGetAttr(1,Tio);
  200. if b then
  201. begin
  202. OldIO:=Tio;
  203. Tio.c_iflag:=Tio.c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
  204. INLCR or IGNCR or ICRNL or IXON));
  205. Tio.c_lflag:=Tio.c_lflag and (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
  206. end
  207. else
  208. Tio := OldIO;
  209. TCSetAttr(1,TCSANOW,Tio);
  210. End;
  211. type
  212. chgentry=packed record
  213. tab,
  214. idx,
  215. oldtab,
  216. oldidx : byte;
  217. oldval,
  218. newval : word;
  219. end;
  220. kbentry=packed record
  221. kb_table,
  222. kb_index : byte;
  223. kb_value : word;
  224. end;
  225. const
  226. kbdchanges=10;
  227. kbdchange:array[1..kbdchanges] of chgentry=(
  228. (tab:8; idx:$3b; oldtab:0; oldidx:$3b; oldval:0; newval:0),
  229. (tab:8; idx:$3c; oldtab:0; oldidx:$3c; oldval:0; newval:0),
  230. (tab:8; idx:$3d; oldtab:0; oldidx:$3d; oldval:0; newval:0),
  231. (tab:8; idx:$3e; oldtab:0; oldidx:$3e; oldval:0; newval:0),
  232. (tab:8; idx:$3f; oldtab:0; oldidx:$3f; oldval:0; newval:0),
  233. (tab:8; idx:$40; oldtab:0; oldidx:$40; oldval:0; newval:0),
  234. (tab:8; idx:$41; oldtab:0; oldidx:$41; oldval:0; newval:0),
  235. (tab:8; idx:$42; oldtab:0; oldidx:$42; oldval:0; newval:0),
  236. (tab:8; idx:$43; oldtab:0; oldidx:$43; oldval:0; newval:0),
  237. (tab:8; idx:$44; oldtab:0; oldidx:$44; oldval:0; newval:0)
  238. );
  239. KDGKBENT=$4B46;
  240. KDSKBENT=$4B47;
  241. procedure PatchKeyboard;
  242. var
  243. e : ^chgentry;
  244. entry : kbentry;
  245. i : longint;
  246. begin
  247. for i:=1 to kbdchanges do
  248. begin
  249. e:=@kbdchange[i];
  250. entry.kb_table:=e^.tab;
  251. entry.kb_index:=e^.idx;
  252. Ioctl(stdinputhandle,KDGKBENT,@entry);
  253. e^.oldval:=entry.kb_value;
  254. entry.kb_table:=e^.oldtab;
  255. entry.kb_index:=e^.oldidx;
  256. ioctl(stdinputhandle,KDGKBENT,@entry);
  257. e^.newval:=entry.kb_value;
  258. end;
  259. for i:=1to kbdchanges do
  260. begin
  261. e:=@kbdchange[i];
  262. entry.kb_table:=e^.tab;
  263. entry.kb_index:=e^.idx;
  264. entry.kb_value:=e^.newval;
  265. Ioctl(stdinputhandle,KDSKBENT,@entry);
  266. end;
  267. end;
  268. procedure UnpatchKeyboard;
  269. var
  270. e : ^chgentry;
  271. entry : kbentry;
  272. i : longint;
  273. begin
  274. for i:=1 to kbdchanges do
  275. begin
  276. e:=@kbdchange[i];
  277. entry.kb_table:=e^.tab;
  278. entry.kb_index:=e^.idx;
  279. entry.kb_value:=e^.oldval;
  280. Ioctl(stdinputhandle,KDSKBENT,@entry);
  281. end;
  282. end;
  283. { Buffered Input routines }
  284. const
  285. InSize=256;
  286. var
  287. InBuf : array [0..InSize-1] of char;
  288. InCnt,
  289. InHead,
  290. InTail : longint;
  291. function ttyRecvChar:char;
  292. var
  293. Readed,i : longint;
  294. begin
  295. {Buffer Empty? Yes, Input from StdIn}
  296. if (InHead=InTail) then
  297. begin
  298. {Calc Amount of Chars to Read}
  299. i:=InSize-InHead;
  300. if InTail>InHead then
  301. i:=InTail-InHead;
  302. {Read}
  303. Readed:=fdRead(StdInputHandle,InBuf[InHead],i);
  304. {Increase Counters}
  305. inc(InCnt,Readed);
  306. inc(InHead,Readed);
  307. {Wrap if End has Reached}
  308. if InHead>=InSize then
  309. InHead:=0;
  310. end;
  311. {Check Buffer}
  312. if (InCnt=0) then
  313. ttyRecvChar:=#0
  314. else
  315. begin
  316. ttyRecvChar:=InBuf[InTail];
  317. dec(InCnt);
  318. inc(InTail);
  319. if InTail>=InSize then
  320. InTail:=0;
  321. end;
  322. end;
  323. Const
  324. KeyBufferSize = 20;
  325. var
  326. KeyBuffer : Array[0..KeyBufferSize-1] of Char;
  327. KeyPut,
  328. KeySend : longint;
  329. Procedure PushKey(Ch:char);
  330. Var
  331. Tmp : Longint;
  332. Begin
  333. Tmp:=KeyPut;
  334. Inc(KeyPut);
  335. If KeyPut>=KeyBufferSize Then
  336. KeyPut:=0;
  337. If KeyPut<>KeySend Then
  338. KeyBuffer[Tmp]:=Ch
  339. Else
  340. KeyPut:=Tmp;
  341. End;
  342. Function PopKey:char;
  343. Begin
  344. If KeyPut<>KeySend Then
  345. Begin
  346. PopKey:=KeyBuffer[KeySend];
  347. Inc(KeySend);
  348. If KeySend>=KeyBufferSize Then
  349. KeySend:=0;
  350. End
  351. Else
  352. PopKey:=#0;
  353. End;
  354. Procedure PushExt(b:byte);
  355. begin
  356. PushKey(#0);
  357. PushKey(chr(b));
  358. end;
  359. const
  360. AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-=';
  361. AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+
  362. #044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131;
  363. Function FAltKey(ch:char):byte;
  364. var
  365. Idx : longint;
  366. Begin
  367. Idx:=Pos(ch,AltKeyStr);
  368. if Idx>0 then
  369. FAltKey:=byte(AltCodeStr[Idx])
  370. else
  371. FAltKey:=0;
  372. End;
  373. { This one doesn't care about keypresses already processed by readkey }
  374. { and waiting in the KeyBuffer, only about waiting keypresses at the }
  375. { TTYLevel (including ones that are waiting in the TTYRecvChar buffer) }
  376. function sysKeyPressed: boolean;
  377. var
  378. fdsin : fdSet;
  379. begin
  380. if (InCnt>0) then
  381. sysKeyPressed:=true
  382. else
  383. begin
  384. FD_Zero(fdsin);
  385. fd_Set(StdInputHandle,fdsin);
  386. sysKeypressed:=(Select(StdInputHandle+1,@fdsin,nil,nil,0)>0);
  387. end;
  388. end;
  389. Function KeyPressed:Boolean;
  390. Begin
  391. Keypressed := (KeySend<>KeyPut) or sysKeyPressed;
  392. End;
  393. Function IsConsole : Boolean;
  394. var
  395. ThisTTY: String[30];
  396. FName : String;
  397. TTYfd: longint;
  398. begin
  399. IsConsole:=false;
  400. { check for tty }
  401. ThisTTY:=TTYName(stdinputhandle);
  402. if IsATTY(stdinputhandle) then
  403. begin
  404. { running on a tty, find out whether locally or remotely }
  405. if (Copy(ThisTTY, 1, 8) = '/dev/tty') and
  406. (ThisTTY[9] >= '0') and (ThisTTY[9] <= '9') then
  407. begin
  408. { running on the console }
  409. FName:='/dev/vcsa' + ThisTTY[9];
  410. { check with read only as it might already be
  411. open in ReadWrite by video unit }
  412. TTYFd:=fdOpen(FName, 0, Open_RdOnly); { open console }
  413. end
  414. else
  415. TTYFd:=-1;
  416. if TTYFd<>-1 then
  417. begin
  418. IsConsole:=true;
  419. fdClose(TTYFd);
  420. end;
  421. end;
  422. end;
  423. Const
  424. LastMouseEvent : TMouseEvent =
  425. (
  426. Buttons : 0;
  427. X : 0;
  428. Y : 0;
  429. Action : 0;
  430. );
  431. {$ifndef NotUseTree}
  432. procedure GenMouseEvent;
  433. var MouseEvent: TMouseEvent;
  434. ch : char;
  435. fdsin : fdSet;
  436. begin
  437. FD_Zero(fdsin);
  438. fd_Set(StdInputHandle,fdsin);
  439. Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  440. if InCnt=0 then
  441. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  442. ch:=ttyRecvChar;
  443. { Other bits are used for Shift, Meta and Ctrl modifiers PM }
  444. case (ord(ch)-ord(' ')) and 3 of
  445. 0 : {left button press}
  446. MouseEvent.buttons:=1;
  447. 1 : {middle button pressed }
  448. MouseEvent.buttons:=2;
  449. 2 : { right button pressed }
  450. MouseEvent.buttons:=4;
  451. 3 : { no button pressed };
  452. end;
  453. if InCnt=0 then
  454. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  455. ch:=ttyRecvChar;
  456. MouseEvent.x:=Ord(ch)-ord(' ')-1;
  457. if InCnt=0 then
  458. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  459. ch:=ttyRecvChar;
  460. MouseEvent.y:=Ord(ch)-ord(' ')-1;
  461. if (MouseEvent.buttons<>0) then
  462. MouseEvent.action:=MouseActionDown
  463. else
  464. begin
  465. if (LastMouseEvent.Buttons<>0) and
  466. ((LastMouseEvent.X<>MouseEvent.X) or (LastMouseEvent.Y<>MouseEvent.Y)) then
  467. begin
  468. MouseEvent.Action:=MouseActionMove;
  469. MouseEvent.Buttons:=LastMouseEvent.Buttons;
  470. {$ifdef DebugMouse}
  471. Writeln(system.stderr,' Mouse Move (',MouseEvent.X,',',MouseEvent.Y,')');
  472. {$endif DebugMouse}
  473. PutMouseEvent(MouseEvent);
  474. MouseEvent.Buttons:=0;
  475. end;
  476. MouseEvent.Action:=MouseActionUp;
  477. end;
  478. PutMouseEvent(MouseEvent);
  479. {$ifdef DebugMouse}
  480. if MouseEvent.Action=MouseActionDown then
  481. Write(system.stderr,'Button down : ')
  482. else
  483. Write(system.stderr,'Button up : ');
  484. Writeln(system.stderr,'buttons = ',MouseEvent.Buttons,' (',MouseEvent.X,',',MouseEvent.Y,')');
  485. {$endif DebugMouse}
  486. LastMouseEvent:=MouseEvent;
  487. end;
  488. type
  489. TProcedure = procedure;
  490. PTreeElement = ^TTreeElement;
  491. TTreeElement = record
  492. Next,Parent,Child : PTreeElement;
  493. CanBeTerminal : boolean;
  494. char : byte;
  495. ScanValue : byte;
  496. CharValue : byte;
  497. SpecialHandler : TProcedure;
  498. end;
  499. var
  500. RootTree : Array[0..255] of PTreeElement;
  501. function NewPTree(ch : byte;Pa : PTreeElement) : PTreeElement;
  502. var PT : PTreeElement;
  503. begin
  504. New(PT);
  505. FillChar(PT^,SizeOf(TTreeElement),#0);
  506. PT^.char:=ch;
  507. PT^.Parent:=Pa;
  508. if Assigned(Pa) and (Pa^.Child=nil) then
  509. Pa^.Child:=PT;
  510. NewPTree:=PT;
  511. end;
  512. function DoAddSequence(Const St : String; AChar,AScan :byte) : PTreeElement;
  513. var
  514. CurPTree,NPT : PTreeElement;
  515. c : byte;
  516. i : longint;
  517. begin
  518. if St='' then
  519. begin
  520. DoAddSequence:=nil;
  521. exit;
  522. end;
  523. CurPTree:=RootTree[ord(st[1])];
  524. if CurPTree=nil then
  525. begin
  526. CurPTree:=NewPTree(ord(st[1]),nil);
  527. RootTree[ord(st[1])]:=CurPTree;
  528. end;
  529. for i:=2 to Length(St) do
  530. begin
  531. NPT:=CurPTree^.Child;
  532. c:=ord(St[i]);
  533. if NPT=nil then
  534. NPT:=NewPTree(c,CurPTree);
  535. CurPTree:=nil;
  536. while assigned(NPT) and (NPT^.char<c) do
  537. begin
  538. CurPTree:=NPT;
  539. NPT:=NPT^.Next;
  540. end;
  541. if assigned(NPT) and (NPT^.char=c) then
  542. CurPTree:=NPT
  543. else
  544. begin
  545. if CurPTree=nil then
  546. begin
  547. NPT^.Parent^.child:=NewPTree(c,NPT^.Parent);
  548. CurPTree:=NPT^.Parent^.Child;
  549. CurPTree^.Next:=NPT;
  550. end
  551. else
  552. begin
  553. CurPTree^.Next:=NewPTree(c,CurPTree^.Parent);
  554. CurPTree:=CurPTree^.Next;
  555. CurPTree^.Next:=NPT;
  556. end;
  557. end;
  558. end;
  559. if CurPTree^.CanBeTerminal then
  560. begin
  561. { here we have a conflict !! }
  562. { maybe we should claim }
  563. with CurPTree^ do
  564. begin
  565. {$ifdef DEBUG}
  566. if (ScanValue<>AScan) or (CharValue<>AChar) then
  567. Writeln(system.stderr,'key "',st,'" changed value');
  568. if (ScanValue<>AScan) then
  569. Writeln(system.stderr,'Scan was ',ScanValue,' now ',AScan);
  570. if (CharValue<>AChar) then
  571. Writeln(system.stderr,'Char was ',chr(CharValue),' now ',chr(AChar));
  572. {$endif DEBUG}
  573. ScanValue:=AScan;
  574. CharValue:=AChar;
  575. end;
  576. end
  577. else with CurPTree^ do
  578. begin
  579. CanBeTerminal:=True;
  580. ScanValue:=AScan;
  581. CharValue:=AChar;
  582. end;
  583. DoAddSequence:=CurPTree;
  584. end;
  585. procedure AddSequence(Const St : String; AChar,AScan :byte);
  586. begin
  587. DoAddSequence(St,AChar,AScan);
  588. end;
  589. { Returns the Child that as c as char if it exists }
  590. Function FindChild(c : byte;Root : PTreeElement) : PTreeElement;
  591. var
  592. NPT : PTreeElement;
  593. begin
  594. if not assigned(Root) then
  595. begin
  596. FindChild:=nil;
  597. exit;
  598. end;
  599. NPT:=Root^.Child;
  600. while assigned(NPT) and (NPT^.char<c) do
  601. NPT:=NPT^.Next;
  602. if assigned(NPT) and (NPT^.char=c) then
  603. FindChild:=NPT
  604. else
  605. FindChild:=nil;
  606. end;
  607. Function AddSpecialSequence(Const St : string;Proc : TProcedure) : PTreeElement;
  608. var
  609. NPT : PTreeElement;
  610. begin
  611. NPT:=DoAddSequence(St,0,0);
  612. NPT^.SpecialHandler:=Proc;
  613. AddSpecialSequence:=NPT;
  614. end;
  615. function FindSequence(Const St : String;var AChar,AScan :byte) : boolean;
  616. var
  617. NPT : PTreeElement;
  618. I : longint;
  619. begin
  620. FindSequence:=false;
  621. AChar:=0;
  622. AScan:=0;
  623. if St='' then
  624. exit;
  625. NPT:=RootTree[ord(St[1])];
  626. if not assigned(NPT) then
  627. exit;
  628. for i:=2 to Length(St) do
  629. begin
  630. NPT:=FindChild(ord(St[i]),NPT);
  631. if not assigned(NPT) then
  632. exit;
  633. end;
  634. if not NPT^.CanBeTerminal then
  635. exit
  636. else
  637. begin
  638. FindSequence:=true;
  639. AScan:=NPT^.ScanValue;
  640. AChar:=NPT^.CharValue;
  641. end;
  642. end;
  643. Procedure LoadDefaultSequences;
  644. begin
  645. AddSpecialSequence(#27'[M',@GenMouseEvent);
  646. { linux default values }
  647. if IsConsole then
  648. begin
  649. DoAddSequence(#127,8,0);
  650. end
  651. else
  652. begin
  653. DoAddSequence(#127,0,kbDel);
  654. end;
  655. { all Esc letter }
  656. DoAddSequence(#27'A',0,kbAltA);
  657. DoAddSequence(#27'a',0,kbAltA);
  658. DoAddSequence(#27'B',0,kbAltB);
  659. DoAddSequence(#27'b',0,kbAltB);
  660. DoAddSequence(#27'C',0,kbAltC);
  661. DoAddSequence(#27'c',0,kbAltC);
  662. DoAddSequence(#27'D',0,kbAltD);
  663. DoAddSequence(#27'd',0,kbAltD);
  664. DoAddSequence(#27'E',0,kbAltE);
  665. DoAddSequence(#27'e',0,kbAltE);
  666. DoAddSequence(#27'F',0,kbAltF);
  667. DoAddSequence(#27'f',0,kbAltF);
  668. DoAddSequence(#27'G',0,kbAltG);
  669. DoAddSequence(#27'g',0,kbAltG);
  670. DoAddSequence(#27'H',0,kbAltH);
  671. DoAddSequence(#27'h',0,kbAltH);
  672. DoAddSequence(#27'I',0,kbAltI);
  673. DoAddSequence(#27'i',0,kbAltI);
  674. DoAddSequence(#27'J',0,kbAltJ);
  675. DoAddSequence(#27'j',0,kbAltJ);
  676. DoAddSequence(#27'K',0,kbAltK);
  677. DoAddSequence(#27'k',0,kbAltK);
  678. DoAddSequence(#27'L',0,kbAltL);
  679. DoAddSequence(#27'l',0,kbAltL);
  680. DoAddSequence(#27'M',0,kbAltM);
  681. DoAddSequence(#27'm',0,kbAltM);
  682. DoAddSequence(#27'N',0,kbAltN);
  683. DoAddSequence(#27'n',0,kbAltN);
  684. DoAddSequence(#27'O',0,kbAltO);
  685. DoAddSequence(#27'o',0,kbAltO);
  686. DoAddSequence(#27'P',0,kbAltP);
  687. DoAddSequence(#27'p',0,kbAltP);
  688. DoAddSequence(#27'Q',0,kbAltQ);
  689. DoAddSequence(#27'q',0,kbAltQ);
  690. DoAddSequence(#27'R',0,kbAltR);
  691. DoAddSequence(#27'r',0,kbAltR);
  692. DoAddSequence(#27'S',0,kbAltS);
  693. DoAddSequence(#27's',0,kbAltS);
  694. DoAddSequence(#27'T',0,kbAltT);
  695. DoAddSequence(#27't',0,kbAltT);
  696. DoAddSequence(#27'U',0,kbAltU);
  697. DoAddSequence(#27'u',0,kbAltU);
  698. DoAddSequence(#27'V',0,kbAltV);
  699. DoAddSequence(#27'v',0,kbAltV);
  700. DoAddSequence(#27'W',0,kbAltW);
  701. DoAddSequence(#27'w',0,kbAltW);
  702. DoAddSequence(#27'X',0,kbAltX);
  703. DoAddSequence(#27'x',0,kbAltX);
  704. DoAddSequence(#27'Y',0,kbAltY);
  705. DoAddSequence(#27'y',0,kbAltY);
  706. DoAddSequence(#27'Z',0,kbAltZ);
  707. DoAddSequence(#27'z',0,kbAltZ);
  708. DoAddSequence(#27'-',0,kbAltMinus);
  709. DoAddSequence(#27'=',0,kbAltEqual);
  710. DoAddSequence(#27'0',0,kbAlt0);
  711. DoAddSequence(#27'1',0,kbAlt1);
  712. DoAddSequence(#27'2',0,kbAlt2);
  713. DoAddSequence(#27'3',0,kbAlt3);
  714. DoAddSequence(#27'4',0,kbAlt4);
  715. DoAddSequence(#27'5',0,kbAlt5);
  716. DoAddSequence(#27'6',0,kbAlt6);
  717. DoAddSequence(#27'7',0,kbAlt7);
  718. DoAddSequence(#27'8',0,kbAlt8);
  719. DoAddSequence(#27'9',0,kbAlt9);
  720. { vt100 default values }
  721. DoAddSequence(#27'[[A',0,kbF1);
  722. DoAddSequence(#27'[[B',0,kbF2);
  723. DoAddSequence(#27'[[C',0,kbF3);
  724. DoAddSequence(#27'[[D',0,kbF4);
  725. DoAddSequence(#27'[[E',0,kbF5);
  726. DoAddSequence(#27'[17~',0,kbF6);
  727. DoAddSequence(#27'[18~',0,kbF7);
  728. DoAddSequence(#27'[19~',0,kbF8);
  729. DoAddSequence(#27'[20~',0,kbF9);
  730. DoAddSequence(#27'[21~',0,kbF10);
  731. DoAddSequence(#27'[23~',0,kbF11);
  732. DoAddSequence(#27'[24~',0,kbF12);
  733. DoAddSequence(#27'[25~',0,kbShiftF3);
  734. DoAddSequence(#27'[26~',0,kbShiftF4);
  735. DoAddSequence(#27'[28~',0,kbShiftF5);
  736. DoAddSequence(#27'[29~',0,kbShiftF6);
  737. DoAddSequence(#27'[31~',0,kbShiftF7);
  738. DoAddSequence(#27'[32~',0,kbShiftF8);
  739. DoAddSequence(#27'[33~',0,kbShiftF9);
  740. DoAddSequence(#27'[34~',0,kbShiftF10);
  741. DoAddSequence(#27#27'[[A',0,kbAltF1);
  742. DoAddSequence(#27#27'[[B',0,kbAltF2);
  743. DoAddSequence(#27#27'[[C',0,kbAltF3);
  744. DoAddSequence(#27#27'[[D',0,kbAltF4);
  745. DoAddSequence(#27#27'[[E',0,kbAltF5);
  746. DoAddSequence(#27#27'[17~',0,kbAltF6);
  747. DoAddSequence(#27#27'[18~',0,kbAltF7);
  748. DoAddSequence(#27#27'[19~',0,kbAltF8);
  749. DoAddSequence(#27#27'[20~',0,kbAltF9);
  750. DoAddSequence(#27#27'[21~',0,kbAltF10);
  751. DoAddSequence(#27#27'[23~',0,kbAltF11);
  752. DoAddSequence(#27#27'[24~',0,kbAltF12);
  753. DoAddSequence(#27'[A',0,kbUp);
  754. DoAddSequence(#27'[B',0,kbDown);
  755. DoAddSequence(#27'[C',0,kbRight);
  756. DoAddSequence(#27'[D',0,kbLeft);
  757. DoAddSequence(#27'[F',0,kbEnd);
  758. DoAddSequence(#27'[H',0,kbHome);
  759. DoAddSequence(#27'[Z',0,kbShiftTab);
  760. DoAddSequence(#27'[5~',0,kbPgUp);
  761. DoAddSequence(#27'[6~',0,kbPgDn);
  762. DoAddSequence(#27'[4~',0,kbEnd);
  763. DoAddSequence(#27'[1~',0,kbHome);
  764. DoAddSequence(#27'[2~',0,kbIns);
  765. DoAddSequence(#27'[3~',0,kbDel);
  766. DoAddSequence(#27#27'[A',0,kbAltUp);
  767. DoAddSequence(#27#27'[B',0,kbAltDown);
  768. DoAddSequence(#27#27'[D',0,kbAltLeft);
  769. DoAddSequence(#27#27'[C',0,kbAltRight);
  770. DoAddSequence(#27#27'[5~',0,kbAltPgUp);
  771. DoAddSequence(#27#27'[6~',0,kbAltPgDn);
  772. DoAddSequence(#27#27'[4~',0,kbAltEnd);
  773. DoAddSequence(#27#27'[1~',0,kbAltHome);
  774. DoAddSequence(#27#27'[2~',0,kbAltIns);
  775. DoAddSequence(#27#27'[3~',0,kbAltDel);
  776. DoAddSequence(#27'OP',0,kbF1);
  777. DoAddSequence(#27'OQ',0,kbF2);
  778. DoAddSequence(#27'OR',0,kbF3);
  779. DoAddSequence(#27'OS',0,kbF4);
  780. DoAddSequence(#27'Ot',0,kbF5);
  781. DoAddSequence(#27'Ou',0,kbF6);
  782. DoAddSequence(#27'Ov',0,kbF7);
  783. DoAddSequence(#27'Ol',0,kbF8);
  784. DoAddSequence(#27'Ow',0,kbF9);
  785. DoAddSequence(#27'Ox',0,kbF10);
  786. DoAddSequence(#27'Oy',0,kbF11);
  787. DoAddSequence(#27'Oz',0,kbF12);
  788. DoAddSequence(#27#27'OP',0,kbAltF1);
  789. DoAddSequence(#27#27'OQ',0,kbAltF2);
  790. DoAddSequence(#27#27'OR',0,kbAltF3);
  791. DoAddSequence(#27#27'OS',0,kbAltF4);
  792. DoAddSequence(#27#27'Ot',0,kbAltF5);
  793. DoAddSequence(#27#27'Ou',0,kbAltF6);
  794. DoAddSequence(#27#27'Ov',0,kbAltF7);
  795. DoAddSequence(#27#27'Ol',0,kbAltF8);
  796. DoAddSequence(#27#27'Ow',0,kbAltF9);
  797. DoAddSequence(#27#27'Ox',0,kbAltF10);
  798. DoAddSequence(#27#27'Oy',0,kbAltF11);
  799. DoAddSequence(#27#27'Oz',0,kbAltF12);
  800. DoAddSequence(#27'OA',0,kbUp);
  801. DoAddSequence(#27'OB',0,kbDown);
  802. DoAddSequence(#27'OC',0,kbRight);
  803. DoAddSequence(#27'OD',0,kbLeft);
  804. DoAddSequence(#27#27'OA',0,kbAltUp);
  805. DoAddSequence(#27#27'OB',0,kbAltDown);
  806. DoAddSequence(#27#27'OC',0,kbAltRight);
  807. DoAddSequence(#27#27'OD',0,kbAltLeft);
  808. { xterm default values }
  809. { xterm alternate default values }
  810. { ignored sequences }
  811. DoAddSequence(#27'[?1;0c',0,0);
  812. DoAddSequence(#27'[?1l',0,0);
  813. DoAddSequence(#27'[?1h',0,0);
  814. DoAddSequence(#27'[?1;2c',0,0);
  815. DoAddSequence(#27'[?7l',0,0);
  816. DoAddSequence(#27'[?7h',0,0);
  817. end;
  818. function EnterEscapeSeqNdx(Ndx: Word;Char,Scan : byte) : PTreeElement;
  819. var
  820. P,pdelay: PChar;
  821. St : string;
  822. begin
  823. EnterEscapeSeqNdx:=nil;
  824. P:=cur_term_Strings^[Ndx];
  825. if assigned(p) then
  826. begin { Do not record the delays }
  827. pdelay:=strpos(p,'$<');
  828. if assigned(pdelay) then
  829. pdelay^:=#0;
  830. St:=StrPas(p);
  831. EnterEscapeSeqNdx:=DoAddSequence(St,Char,Scan);
  832. if assigned(pdelay) then
  833. pdelay^:='$';
  834. end;
  835. end;
  836. Procedure LoadTermInfoSequences;
  837. var
  838. err : longint;
  839. begin
  840. if not assigned(cur_term) then
  841. setupterm(nil, stdoutputhandle, err);
  842. if not assigned(cur_term_Strings) then
  843. exit;
  844. EnterEscapeSeqNdx(key_f1,0,kbF1);
  845. EnterEscapeSeqNdx(key_f2,0,kbF2);
  846. EnterEscapeSeqNdx(key_f3,0,kbF3);
  847. EnterEscapeSeqNdx(key_f4,0,kbF4);
  848. EnterEscapeSeqNdx(key_f5,0,kbF5);
  849. EnterEscapeSeqNdx(key_f6,0,kbF6);
  850. EnterEscapeSeqNdx(key_f7,0,kbF7);
  851. EnterEscapeSeqNdx(key_f8,0,kbF8);
  852. EnterEscapeSeqNdx(key_f9,0,kbF9);
  853. EnterEscapeSeqNdx(key_f10,0,kbF10);
  854. EnterEscapeSeqNdx(key_f11,0,kbF11);
  855. EnterEscapeSeqNdx(key_f12,0,kbF12);
  856. EnterEscapeSeqNdx(key_up,0,kbUp);
  857. EnterEscapeSeqNdx(key_down,0,kbDown);
  858. EnterEscapeSeqNdx(key_left,0,kbLeft);
  859. EnterEscapeSeqNdx(key_right,0,kbRight);
  860. EnterEscapeSeqNdx(key_ppage,0,kbPgUp);
  861. EnterEscapeSeqNdx(key_npage,0,kbPgDn);
  862. EnterEscapeSeqNdx(key_end,0,kbEnd);
  863. EnterEscapeSeqNdx(key_home,0,kbHome);
  864. EnterEscapeSeqNdx(key_ic,0,kbIns);
  865. EnterEscapeSeqNdx(key_dc,0,kbDel);
  866. EnterEscapeSeqNdx(key_stab,0,kbShiftTab);
  867. { EnterEscapeSeqNdx(key_,0,kb);
  868. EnterEscapeSeqNdx(key_,0,kb); }
  869. end;
  870. {$endif not NotUseTree}
  871. Function RawReadKey:char;
  872. Var
  873. fdsin : fdSet;
  874. Begin
  875. {Check Buffer first}
  876. if KeySend<>KeyPut then
  877. begin
  878. RawReadKey:=PopKey;
  879. exit;
  880. end;
  881. {Wait for Key}
  882. if not sysKeyPressed then
  883. begin
  884. FD_Zero (fdsin);
  885. FD_Set (StdInputHandle,fdsin);
  886. Select (StdInputHandle+1,@fdsin,nil,nil,nil);
  887. end;
  888. RawReadKey:=ttyRecvChar;
  889. end;
  890. Function RawReadString : String;
  891. Var
  892. ch : char;
  893. fdsin : fdSet;
  894. St : String;
  895. Begin
  896. St:=RawReadKey;
  897. FD_Zero (fdsin);
  898. FD_Set (StdInputHandle,fdsin);
  899. Repeat
  900. if InCnt=0 then
  901. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  902. if SysKeyPressed then
  903. ch:=ttyRecvChar
  904. else
  905. ch:=#0;
  906. if ch<>#0 then
  907. St:=St+ch;
  908. Until ch=#0;
  909. RawReadString:=St;
  910. end;
  911. Function ReadKey(var IsAlt : boolean):char;
  912. Var
  913. ch : char;
  914. {$ifdef NotUseTree}
  915. OldState : longint;
  916. State : longint;
  917. {$endif NotUseTree}
  918. is_delay : boolean;
  919. fdsin : fdSet;
  920. store : array [0..8] of char;
  921. arrayind : byte;
  922. {$ifndef NotUseTree}
  923. NPT,NNPT : PTreeElement;
  924. {$else NotUseTree}
  925. procedure GenMouseEvent;
  926. var MouseEvent: TMouseEvent;
  927. begin
  928. Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  929. case ch of
  930. #32 : {left button pressed }
  931. MouseEvent.buttons:=1;
  932. #33 : {middle button pressed }
  933. MouseEvent.buttons:=2;
  934. #34 : { right button pressed }
  935. MouseEvent.buttons:=4;
  936. #35 : { no button pressed };
  937. end;
  938. if InCnt=0 then
  939. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  940. ch:=ttyRecvChar;
  941. MouseEvent.x:=Ord(ch)-ord(' ')-1;
  942. if InCnt=0 then
  943. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  944. ch:=ttyRecvChar;
  945. MouseEvent.y:=Ord(ch)-ord(' ')-1;
  946. if (MouseEvent.buttons<>0) then
  947. MouseEvent.action:=MouseActionDown
  948. else
  949. begin
  950. if (LastMouseEvent.Buttons<>0) and
  951. ((LastMouseEvent.X<>MouseEvent.X) or (LastMouseEvent.Y<>MouseEvent.Y)) then
  952. begin
  953. MouseEvent.Action:=MouseActionMove;
  954. MouseEvent.Buttons:=LastMouseEvent.Buttons;
  955. PutMouseEvent(MouseEvent);
  956. MouseEvent.Buttons:=0;
  957. end;
  958. MouseEvent.Action:=MouseActionUp;
  959. end;
  960. PutMouseEvent(MouseEvent);
  961. LastMouseEvent:=MouseEvent;
  962. end;
  963. {$endif NotUseTree}
  964. procedure RestoreArray;
  965. var
  966. i : byte;
  967. begin
  968. for i:=0 to arrayind-1 do
  969. PushKey(store[i]);
  970. end;
  971. Begin
  972. IsAlt:=false;
  973. {Check Buffer first}
  974. if KeySend<>KeyPut then
  975. begin
  976. ReadKey:=PopKey;
  977. exit;
  978. end;
  979. {Wait for Key}
  980. if not sysKeyPressed then
  981. begin
  982. FD_Zero (fdsin);
  983. FD_Set (StdInputHandle,fdsin);
  984. Select (StdInputHandle+1,@fdsin,nil,nil,nil);
  985. end;
  986. ch:=ttyRecvChar;
  987. {$ifndef NotUseTree}
  988. NPT:=RootTree[ord(ch)];
  989. if not assigned(NPT) then
  990. PushKey(ch)
  991. else
  992. begin
  993. FD_Zero(fdsin);
  994. fd_Set(StdInputHandle,fdsin);
  995. store[0]:=ch;
  996. arrayind:=1;
  997. while assigned(NPT) and syskeypressed do
  998. begin
  999. if (InCnt=0) then
  1000. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1001. ch:=ttyRecvChar;
  1002. NNPT:=FindChild(ord(ch),NPT);
  1003. if assigned(NNPT) then
  1004. Begin
  1005. NPT:=NNPT;
  1006. if NPT^.CanBeTerminal and
  1007. assigned(NPT^.SpecialHandler) then
  1008. break;
  1009. End;
  1010. if ch<>#0 then
  1011. begin
  1012. store[arrayind]:=ch;
  1013. inc(arrayind);
  1014. end;
  1015. end;
  1016. if assigned(NPT) and NPT^.CanBeTerminal then
  1017. begin
  1018. if assigned(NPT^.SpecialHandler) then
  1019. begin
  1020. NPT^.SpecialHandler;
  1021. ch:=#0;
  1022. end
  1023. else if NPT^.CharValue<>0 then
  1024. PushKey(chr(NPT^.CharValue))
  1025. else if NPT^.ScanValue<>0 then
  1026. PushExt(NPT^.ScanValue);
  1027. end
  1028. else
  1029. RestoreArray;
  1030. {$else NotUseTree}
  1031. {Esc Found ?}
  1032. If (ch=#27) then
  1033. begin
  1034. FD_Zero(fdsin);
  1035. fd_Set(StdInputHandle,fdsin);
  1036. State:=1;
  1037. store[0]:=#27;
  1038. arrayind:=1;
  1039. {$ifdef logging}
  1040. write(f,'Esc');
  1041. {$endif logging}
  1042. if InCnt=0 then
  1043. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1044. while (State<>0) and (sysKeyPressed) do
  1045. begin
  1046. ch:=ttyRecvChar;
  1047. store[arrayind]:=ch;
  1048. inc(arrayind);
  1049. {$ifdef logging}
  1050. if ord(ch)>31 then
  1051. write(f,ch)
  1052. else
  1053. write(f,'#',ord(ch):2);
  1054. {$endif logging}
  1055. OldState:=State;
  1056. State:=0;
  1057. case OldState of
  1058. 1 : begin {Esc}
  1059. case ch of
  1060. 'a'..'z',
  1061. '0'..'9',
  1062. '-','=' : PushExt(FAltKey(ch));
  1063. 'A'..'N',
  1064. 'P'..'Z' : PushExt(FAltKey(chr(ord(ch)+ord('a')-ord('A'))));
  1065. #10 : PushKey(#10);
  1066. #13 : PushKey(#10);
  1067. #27 : begin
  1068. IsAlt:=True;
  1069. State:=1;
  1070. end;
  1071. #127 : PushExt(kbAltDel);
  1072. '[' : State:=2;
  1073. 'O' : State:=6;
  1074. else
  1075. RestoreArray;
  1076. end;
  1077. end;
  1078. 2 : begin {Esc[}
  1079. case ch of
  1080. '[' : State:=3;
  1081. 'A' : PushExt(kbUp);
  1082. 'B' : PushExt(kbDown);
  1083. 'C' : PushExt(kbRight);
  1084. 'D' : PushExt(kbLeft);
  1085. 'F' : PushExt(kbEnd);
  1086. 'G' : PushKey('5');
  1087. 'H' : PushExt(kbHome);
  1088. 'K' : PushExt(kbEnd);
  1089. 'M' : State:=13;
  1090. '1' : State:=4;
  1091. '2' : State:=5;
  1092. '3' : State:=12;{PushExt(kbDel)}
  1093. '4' : PushExt(kbEnd);
  1094. '5' : PushExt(73);
  1095. '6' : PushExt(kbPgDn);
  1096. '?' : State:=7;
  1097. else
  1098. RestoreArray;
  1099. end;
  1100. if ch in ['4'..'6'] then
  1101. State:=255;
  1102. end;
  1103. 3 : begin {Esc[[}
  1104. case ch of
  1105. 'A' : PushExt(kbF1);
  1106. 'B' : PushExt(kbF2);
  1107. 'C' : PushExt(kbF3);
  1108. 'D' : PushExt(kbF4);
  1109. 'E' : PushExt(kbF5);
  1110. else
  1111. RestoreArray;
  1112. end;
  1113. end;
  1114. 4 : begin {Esc[1}
  1115. case ch of
  1116. '~' : PushExt(kbHome);
  1117. '7' : PushExt(kbF6);
  1118. '8' : PushExt(kbF7);
  1119. '9' : PushExt(kbF8);
  1120. else
  1121. RestoreArray;
  1122. end;
  1123. if (Ch<>'~') then
  1124. State:=255;
  1125. end;
  1126. 5 : begin {Esc[2}
  1127. case ch of
  1128. '~' : PushExt(kbIns);
  1129. '0' : pushExt(kbF9);
  1130. '1' : PushExt(kbF10);
  1131. '3' : PushExt($85){F11, but ShiftF1 also !!};
  1132. '4' : PushExt($86){F12, but Shift F2 also !!};
  1133. '5' : PushExt($56){ShiftF3};
  1134. '6' : PushExt($57){ShiftF4};
  1135. '8' : PushExt($58){ShiftF5};
  1136. '9' : PushExt($59){ShiftF6};
  1137. else
  1138. RestoreArray;
  1139. end;
  1140. if (Ch<>'~') then
  1141. State:=255;
  1142. end;
  1143. 12 : begin {Esc[3}
  1144. case ch of
  1145. '~' : PushExt(kbDel);
  1146. '1' : PushExt($5A){ShiftF7};
  1147. '2' : PushExt($5B){ShiftF8};
  1148. '3' : PushExt($5C){ShiftF9};
  1149. '4' : PushExt($5D){ShiftF10};
  1150. else
  1151. RestoreArray;
  1152. end;
  1153. if (Ch<>'~') then
  1154. State:=255;
  1155. end;
  1156. 6 : begin {EscO Function keys in vt100 mode PM }
  1157. case ch of
  1158. 'P' : {F1}PushExt(kbF1);
  1159. 'Q' : {F2}PushExt(kbF2);
  1160. 'R' : {F3}PushExt(kbF3);
  1161. 'S' : {F4}PushExt(kbF4);
  1162. 't' : {F5}PushExt(kbF5);
  1163. 'u' : {F6}PushExt(kbF6);
  1164. 'v' : {F7}PushExt(kbF7);
  1165. 'l' : {F8}PushExt(kbF8);
  1166. 'w' : {F9}PushExt(kbF9);
  1167. 'x' : {F10}PushExt(kbF10);
  1168. 'D' : {keyLeft}PushExt($4B);
  1169. 'C' : {keyRight}PushExt($4D);
  1170. 'A' : {keyUp}PushExt($48);
  1171. 'B' : {keyDown}PushExt($50);
  1172. else
  1173. RestoreArray;
  1174. end;
  1175. end;
  1176. 7 : begin {Esc[? keys in vt100 mode PM }
  1177. case ch of
  1178. '0' : State:=11;
  1179. '1' : State:=8;
  1180. '7' : State:=9;
  1181. else
  1182. RestoreArray;
  1183. end;
  1184. end;
  1185. 8 : begin {Esc[?1 keys in vt100 mode PM }
  1186. case ch of
  1187. 'l' : {local mode};
  1188. 'h' : {transmit mode};
  1189. ';' : { 'Esc[1;0c seems to be sent by M$ telnet app
  1190. for no hangup purposes }
  1191. state:=10;
  1192. else
  1193. RestoreArray;
  1194. end;
  1195. end;
  1196. 9 : begin {Esc[?7 keys in vt100 mode PM }
  1197. case ch of
  1198. 'l' : {exit_am_mode};
  1199. 'h' : {enter_am_mode};
  1200. else
  1201. RestoreArray;
  1202. end;
  1203. end;
  1204. 10 : begin {Esc[?1; keys in vt100 mode PM }
  1205. case ch of
  1206. '0' : state:=11;
  1207. else
  1208. RestoreArray;
  1209. end;
  1210. end;
  1211. 11 : begin {Esc[?1;0 keys in vt100 mode PM }
  1212. case ch of
  1213. 'c' : ;
  1214. else
  1215. RestoreArray;
  1216. end;
  1217. end;
  1218. 13 : begin {Esc[M mouse prefix for xterm }
  1219. GenMouseEvent;
  1220. end;
  1221. 255 : { just forget this trailing char };
  1222. end;
  1223. if (State<>0) and (InCnt=0) then
  1224. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1225. end;
  1226. if State=1 then
  1227. PushKey(ch);
  1228. {$endif NotUseTree}
  1229. if ch='$' then
  1230. begin { '$<XX>' means a delay of XX millisecs }
  1231. is_delay :=false;
  1232. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1233. if (sysKeyPressed) then
  1234. begin
  1235. ch:=ttyRecvChar;
  1236. is_delay:=(ch='<');
  1237. if not is_delay then
  1238. begin
  1239. PushKey('$');
  1240. PushKey(ch);
  1241. end
  1242. else
  1243. begin
  1244. {$ifdef logging}
  1245. write(f,'$<');
  1246. {$endif logging}
  1247. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1248. while (sysKeyPressed) and (ch<>'>') do
  1249. begin
  1250. { Should we really repect this delay ?? }
  1251. ch:=ttyRecvChar;
  1252. {$ifdef logging}
  1253. write(f,ch);
  1254. {$endif logging}
  1255. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1256. end;
  1257. end;
  1258. end
  1259. else
  1260. PushKey('$');
  1261. end;
  1262. end
  1263. {$ifdef logging}
  1264. writeln(f);
  1265. {$endif logging}
  1266. {$ifndef NotUseTree}
  1267. ;
  1268. ReadKey:=PopKey;
  1269. {$else NotUseTree}
  1270. else
  1271. Begin
  1272. case ch of
  1273. #127 : PushKey(#8);
  1274. else
  1275. PushKey(ch);
  1276. end;
  1277. End;
  1278. ReadKey:=PopKey;
  1279. {$endif NotUseTree}
  1280. End;
  1281. function ShiftState:byte;
  1282. var
  1283. arg,shift : longint;
  1284. begin
  1285. arg:=6;
  1286. shift:=0;
  1287. {$Ifndef BSD}
  1288. if IOCtl(StdInputHandle,TIOCLINUX,@arg) then
  1289. begin
  1290. if (arg and (2 or 8))<>0 then
  1291. inc(shift,8);
  1292. if (arg and 4)<>0 then
  1293. inc(shift,4);
  1294. if (arg and 1)<>0 then
  1295. inc(shift,3);
  1296. end;
  1297. {$endif}
  1298. ShiftState:=shift;
  1299. end;
  1300. { Exported functions }
  1301. procedure InitKeyboard;
  1302. begin
  1303. SetRawMode(true);
  1304. patchkeyboard;
  1305. {$ifdef logging}
  1306. assign(f,'keyboard.log');
  1307. rewrite(f);
  1308. {$endif logging}
  1309. if not IsConsole then
  1310. begin
  1311. { default for Shift prefix is ^ A}
  1312. if ShiftPrefix = 0 then
  1313. ShiftPrefix:=1;
  1314. {default for Alt prefix is ^Z }
  1315. if AltPrefix=0 then
  1316. AltPrefix:=26;
  1317. { default for Ctrl Prefix is ^W }
  1318. if CtrlPrefix=0 then
  1319. CtrlPrefix:=23;
  1320. end;
  1321. {$ifndef NotUseTree}
  1322. LoadDefaultSequences;
  1323. LoadTerminfoSequences;
  1324. {$endif not NotUseTree}
  1325. end;
  1326. procedure DoneKeyboard;
  1327. begin
  1328. unpatchkeyboard;
  1329. SetRawMode(false);
  1330. {$ifdef logging}
  1331. close(f);
  1332. {$endif logging}
  1333. end;
  1334. function GetKeyEvent: TKeyEvent;
  1335. function EvalScan(b:byte):byte;
  1336. const
  1337. DScan:array[0..31] of byte = (
  1338. $39, $02, $28, $04, $05, $06, $08, $28,
  1339. $0A, $0B, $09, $0D, $33, $0C, $34, $35,
  1340. $0B, $02, $03, $04, $05, $06, $07, $08,
  1341. $09, $0A, $27, $27, $33, $0D, $34, $35);
  1342. LScan:array[0..31] of byte = (
  1343. $29, $1E, $30, $2E, $20, $12, $21, $22,
  1344. $23, $17, $24, $25, $26, $32, $31, $18,
  1345. $19, $10, $13, $1F, $14, $16, $2F, $11,
  1346. $2D, $15, $2C, $1A, $2B, $1B, $29, $0C);
  1347. begin
  1348. if (b and $E0)=$20 { digits / leters } then
  1349. EvalScan:=DScan[b and $1F]
  1350. else
  1351. case b of
  1352. $08:EvalScan:=$0E; { backspace }
  1353. $09:EvalScan:=$0F; { TAB }
  1354. $0D:EvalScan:=$1C; { CR }
  1355. $1B:EvalScan:=$01; { esc }
  1356. $40:EvalScan:=$03; { @ }
  1357. $5E:EvalScan:=$07; { ^ }
  1358. $60:EvalScan:=$29; { ` }
  1359. else
  1360. EvalScan:=LScan[b and $1F];
  1361. end;
  1362. end;
  1363. function EvalScanZ(b:byte):byte;
  1364. begin
  1365. EvalScanZ:=b;
  1366. if b in [$3B..$44] { F1..F10 -> Alt-F1..Alt-F10} then
  1367. EvalScanZ:=b+$2D;
  1368. end;
  1369. const
  1370. {kbHome, kbUp, kbPgUp,Missing, kbLeft,
  1371. kbCenter, kbRight, kbAltGrayPlus, kbend,
  1372. kbDown, kbPgDn, kbIns, kbDel }
  1373. CtrlArrow : array [kbHome..kbDel] of byte =
  1374. {($77,$8d,$84,$8e,$73,$8f,$74,$90,$75,$91,$76);}
  1375. (kbCtrlHome,kbCtrlUp,kbCtrlPgUp,kbNoKey,kbCtrlLeft,
  1376. kbCtrlCenter,kbCtrlRight,kbAltGrayPlus,kbCtrlEnd,
  1377. kbCtrlDown,kbCtrlPgDn,kbCtrlIns,kbCtrlDel);
  1378. AltArrow : array [kbHome..kbDel] of byte =
  1379. (kbAltHome,kbAltUp,kbAltPgUp,kbNoKey,kbAltLeft,
  1380. kbCenter,kbAltRight,kbAltGrayPlus,kbAltEnd,
  1381. kbAltDown,kbAltPgDn,kbAltIns,kbAltDel);
  1382. var
  1383. MyScan,
  1384. SState : byte;
  1385. MyChar : char;
  1386. EscUsed,AltPrefixUsed,CtrlPrefixUsed,ShiftPrefixUsed,IsAlt,Again : boolean;
  1387. begin {main}
  1388. if PendingKeyEvent<>0 then
  1389. begin
  1390. GetKeyEvent:=PendingKeyEvent;
  1391. PendingKeyEvent:=0;
  1392. exit;
  1393. end;
  1394. MyChar:=Readkey(IsAlt);
  1395. MyScan:=ord(MyChar);
  1396. SState:=ShiftState;
  1397. CtrlPrefixUsed:=false;
  1398. AltPrefixUsed:=false;
  1399. ShiftPrefixUsed:=false;
  1400. EscUsed:=false;
  1401. if IsAlt then
  1402. SState:=SState or kbAlt;
  1403. repeat
  1404. again:=false;
  1405. if Mychar=#0 then
  1406. begin
  1407. MyScan:=ord(ReadKey(IsAlt));
  1408. { Handle Ctrl-<x> }
  1409. if (SState and kbCtrl)<>0 then
  1410. begin
  1411. case MyScan of
  1412. kbHome..kbDel : { cArrow }
  1413. MyScan:=CtrlArrow[MyScan];
  1414. kbF1..KbF10 : { cF1-cF10 }
  1415. MyScan:=MyScan+kbCtrlF1-kbF1;
  1416. kbF11..KbF12 : { cF11-cF12 }
  1417. MyScan:=MyScan+kbCtrlF11-kbF11;
  1418. end;
  1419. end
  1420. { Handle Alt-<x> }
  1421. else if (SState and kbAlt)<>0 then
  1422. begin
  1423. case MyScan of
  1424. kbHome..kbDel : { AltArrow }
  1425. MyScan:=AltArrow[MyScan];
  1426. kbF1..KbF10 : { aF1-aF10 }
  1427. MyScan:=MyScan+kbAltF1-kbF1;
  1428. kbF11..KbF12 : { aF11-aF12 }
  1429. MyScan:=MyScan+kbAltF11-kbF11;
  1430. end;
  1431. end
  1432. else if (SState and kbShift)<>0 then
  1433. begin
  1434. case MyScan of
  1435. kbIns: MyScan:=kbShiftIns;
  1436. kbDel: MyScan:=kbShiftDel;
  1437. kbF1..KbF10 : { sF1-sF10 }
  1438. MyScan:=MyScan+kbShiftF1-kbF1;
  1439. kbF11..KbF12 : { sF11-sF12 }
  1440. MyScan:=MyScan+kbShiftF11-kbF11;
  1441. end;
  1442. end;
  1443. GetKeyEvent:=$3000000 or ord(MyChar) or (MyScan shl 8) or (SState shl 16);
  1444. exit;
  1445. end
  1446. else if MyChar=#27 then
  1447. begin
  1448. if EscUsed then
  1449. SState:=SState and not kbAlt
  1450. else
  1451. begin
  1452. SState:=SState or kbAlt;
  1453. Again:=true;
  1454. EscUsed:=true;
  1455. end;
  1456. end
  1457. else if (AltPrefix<>0) and (MyChar=chr(AltPrefix)) then
  1458. begin { ^Z - replace Alt for Linux OS }
  1459. if AltPrefixUsed then
  1460. begin
  1461. SState:=SState and not kbAlt;
  1462. end
  1463. else
  1464. begin
  1465. AltPrefixUsed:=true;
  1466. SState:=SState or kbAlt;
  1467. Again:=true;
  1468. end;
  1469. end
  1470. else if (CtrlPrefix<>0) and (MyChar=chr(CtrlPrefix)) then
  1471. begin
  1472. if CtrlPrefixUsed then
  1473. SState:=SState and not kbCtrl
  1474. else
  1475. begin
  1476. CtrlPrefixUsed:=true;
  1477. SState:=SState or kbCtrl;
  1478. Again:=true;
  1479. end;
  1480. end
  1481. else if (ShiftPrefix<>0) and (MyChar=chr(ShiftPrefix)) then
  1482. begin
  1483. if ShiftPrefixUsed then
  1484. SState:=SState and not kbShift
  1485. else
  1486. begin
  1487. ShiftPrefixUsed:=true;
  1488. SState:=SState or kbShift;
  1489. Again:=true;
  1490. end;
  1491. end;
  1492. if not again then
  1493. begin
  1494. MyScan:=EvalScan(ord(MyChar));
  1495. if (SState and kbAlt)<>0 then
  1496. begin
  1497. if MyScan in [$02..$0D] then
  1498. inc(MyScan,$76);
  1499. MyChar:=chr(0);
  1500. end
  1501. else if (SState and kbShift)<>0 then
  1502. if MyChar=#9 then
  1503. begin
  1504. MyChar:=#0;
  1505. MyScan:=kbShiftTab;
  1506. end;
  1507. end
  1508. else
  1509. begin
  1510. MyChar:=Readkey(IsAlt);
  1511. MyScan:=ord(MyChar);
  1512. if IsAlt then
  1513. SState:=SState or kbAlt;
  1514. end;
  1515. until not Again;
  1516. GetKeyEvent:=$3000000 or ord(MyChar) or (MyScan shl 8) or (SState shl 16);
  1517. end;
  1518. function PollKeyEvent: TKeyEvent;
  1519. begin
  1520. if PendingKeyEvent<>0 then
  1521. exit(PendingKeyEvent);
  1522. if keypressed then
  1523. begin
  1524. { just get the key and place it in the pendingkeyevent }
  1525. PendingKeyEvent:=GetKeyEvent;
  1526. PollKeyEvent:=PendingKeyEvent;
  1527. end
  1528. else
  1529. PollKeyEvent:=0;
  1530. end;
  1531. function PollShiftStateEvent: TKeyEvent;
  1532. begin
  1533. PollShiftStateEvent:=ShiftState shl 16;
  1534. end;
  1535. { Function key translation }
  1536. type
  1537. TTranslationEntry = packed record
  1538. Min, Max: Byte;
  1539. Offset: Word;
  1540. end;
  1541. const
  1542. TranslationTableEntries = 12;
  1543. TranslationTable: array [1..TranslationTableEntries] of TTranslationEntry =
  1544. ((Min: $3B; Max: $44; Offset: kbdF1), { function keys F1-F10 }
  1545. (Min: $54; Max: $5D; Offset: kbdF1), { Shift fn keys F1-F10 }
  1546. (Min: $5E; Max: $67; Offset: kbdF1), { Ctrl fn keys F1-F10 }
  1547. (Min: $68; Max: $71; Offset: kbdF1), { Alt fn keys F1-F10 }
  1548. (Min: $85; Max: $86; Offset: kbdF11), { function keys F11-F12 }
  1549. (Min: $87; Max: $88; Offset: kbdF11), { Shift+function keys F11-F12 }
  1550. (Min: $89; Max: $8A; Offset: kbdF11), { Ctrl+function keys F11-F12 }
  1551. (Min: $8B; Max: $8C; Offset: kbdF11), { Alt+function keys F11-F12 }
  1552. (Min: $47; Max: $49; Offset: kbdHome), { Keypad keys kbdHome-kbdPgUp }
  1553. (Min: $4B; Max: $4D; Offset: kbdLeft), { Keypad keys kbdLeft-kbdRight }
  1554. (Min: $4F; Max: $51; Offset: kbdEnd), { Keypad keys kbdEnd-kbdPgDn }
  1555. (Min: $52; Max: $53; Offset: kbdInsert));
  1556. function TranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  1557. var
  1558. I: Integer;
  1559. ScanCode: Byte;
  1560. begin
  1561. if KeyEvent and $03000000 = $03000000 then
  1562. begin
  1563. if KeyEvent and $000000FF <> 0 then
  1564. begin
  1565. TranslateKeyEvent := KeyEvent and $00FFFFFF;
  1566. exit;
  1567. end
  1568. else
  1569. begin
  1570. { This is a function key }
  1571. ScanCode := (KeyEvent and $0000FF00) shr 8;
  1572. for I := 1 to TranslationTableEntries do
  1573. begin
  1574. if (TranslationTable[I].Min <= ScanCode) and (ScanCode <= TranslationTable[I].Max) then
  1575. begin
  1576. TranslateKeyEvent := $02000000 + (KeyEvent and $00FF0000) +
  1577. (ScanCode - TranslationTable[I].Min) + TranslationTable[I].Offset;
  1578. exit;
  1579. end;
  1580. end;
  1581. end;
  1582. end;
  1583. TranslateKeyEvent := KeyEvent;
  1584. end;
  1585. function TranslateKeyEventUniCode(KeyEvent: TKeyEvent): TKeyEvent;
  1586. begin
  1587. TranslateKeyEventUniCode := KeyEvent;
  1588. ErrorCode:=errKbdNotImplemented;
  1589. end;
  1590. end.
  1591. {
  1592. $Log$
  1593. Revision 1.1 2001-01-13 11:03:58 peter
  1594. * API 2 RTL commit
  1595. }