keyboard.pp 45 KB

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