keyboard.pp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
  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. PushKey(ch);
  1032. break;
  1033. end;
  1034. end;
  1035. if assigned(NPT) and NPT^.CanBeTerminal then
  1036. begin
  1037. if assigned(NPT^.SpecialHandler) then
  1038. begin
  1039. NPT^.SpecialHandler;
  1040. PushExt(0);
  1041. end
  1042. else if NPT^.CharValue<>0 then
  1043. PushKey(chr(NPT^.CharValue))
  1044. else if NPT^.ScanValue<>0 then
  1045. PushExt(NPT^.ScanValue);
  1046. end
  1047. else
  1048. RestoreArray;
  1049. {$else NotUseTree}
  1050. {Esc Found ?}
  1051. If (ch=#27) then
  1052. begin
  1053. FD_Zero(fdsin);
  1054. fd_Set(StdInputHandle,fdsin);
  1055. State:=1;
  1056. store[0]:=#27;
  1057. arrayind:=1;
  1058. {$ifdef logging}
  1059. write(f,'Esc');
  1060. {$endif logging}
  1061. if InCnt=0 then
  1062. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1063. while (State<>0) and (sysKeyPressed) do
  1064. begin
  1065. ch:=ttyRecvChar;
  1066. store[arrayind]:=ch;
  1067. inc(arrayind);
  1068. {$ifdef logging}
  1069. if ord(ch)>31 then
  1070. write(f,ch)
  1071. else
  1072. write(f,'#',ord(ch):2);
  1073. {$endif logging}
  1074. OldState:=State;
  1075. State:=0;
  1076. case OldState of
  1077. 1 : begin {Esc}
  1078. case ch of
  1079. 'a'..'z',
  1080. '0'..'9',
  1081. '-','=' : PushExt(FAltKey(ch));
  1082. 'A'..'N',
  1083. 'P'..'Z' : PushExt(FAltKey(chr(ord(ch)+ord('a')-ord('A'))));
  1084. #10 : PushKey(#10);
  1085. #13 : PushKey(#10);
  1086. #27 : begin
  1087. IsAlt:=True;
  1088. State:=1;
  1089. end;
  1090. #127 : PushExt(kbAltDel);
  1091. '[' : State:=2;
  1092. 'O' : State:=6;
  1093. else
  1094. RestoreArray;
  1095. end;
  1096. end;
  1097. 2 : begin {Esc[}
  1098. case ch of
  1099. '[' : State:=3;
  1100. 'A' : PushExt(kbUp);
  1101. 'B' : PushExt(kbDown);
  1102. 'C' : PushExt(kbRight);
  1103. 'D' : PushExt(kbLeft);
  1104. 'F' : PushExt(kbEnd);
  1105. 'G' : PushKey('5');
  1106. 'H' : PushExt(kbHome);
  1107. 'K' : PushExt(kbEnd);
  1108. 'M' : State:=13;
  1109. '1' : State:=4;
  1110. '2' : State:=5;
  1111. '3' : State:=12;{PushExt(kbDel)}
  1112. '4' : PushExt(kbEnd);
  1113. '5' : PushExt(73);
  1114. '6' : PushExt(kbPgDn);
  1115. '?' : State:=7;
  1116. else
  1117. RestoreArray;
  1118. end;
  1119. if ch in ['4'..'6'] then
  1120. State:=255;
  1121. end;
  1122. 3 : begin {Esc[[}
  1123. case ch of
  1124. 'A' : PushExt(kbF1);
  1125. 'B' : PushExt(kbF2);
  1126. 'C' : PushExt(kbF3);
  1127. 'D' : PushExt(kbF4);
  1128. 'E' : PushExt(kbF5);
  1129. else
  1130. RestoreArray;
  1131. end;
  1132. end;
  1133. 4 : begin {Esc[1}
  1134. case ch of
  1135. '~' : PushExt(kbHome);
  1136. '7' : PushExt(kbF6);
  1137. '8' : PushExt(kbF7);
  1138. '9' : PushExt(kbF8);
  1139. else
  1140. RestoreArray;
  1141. end;
  1142. if (Ch<>'~') then
  1143. State:=255;
  1144. end;
  1145. 5 : begin {Esc[2}
  1146. case ch of
  1147. '~' : PushExt(kbIns);
  1148. '0' : pushExt(kbF9);
  1149. '1' : PushExt(kbF10);
  1150. '3' : PushExt($85){F11, but ShiftF1 also !!};
  1151. '4' : PushExt($86){F12, but Shift F2 also !!};
  1152. '5' : PushExt($56){ShiftF3};
  1153. '6' : PushExt($57){ShiftF4};
  1154. '8' : PushExt($58){ShiftF5};
  1155. '9' : PushExt($59){ShiftF6};
  1156. else
  1157. RestoreArray;
  1158. end;
  1159. if (Ch<>'~') then
  1160. State:=255;
  1161. end;
  1162. 12 : begin {Esc[3}
  1163. case ch of
  1164. '~' : PushExt(kbDel);
  1165. '1' : PushExt($5A){ShiftF7};
  1166. '2' : PushExt($5B){ShiftF8};
  1167. '3' : PushExt($5C){ShiftF9};
  1168. '4' : PushExt($5D){ShiftF10};
  1169. else
  1170. RestoreArray;
  1171. end;
  1172. if (Ch<>'~') then
  1173. State:=255;
  1174. end;
  1175. 6 : begin {EscO Function keys in vt100 mode PM }
  1176. case ch of
  1177. 'P' : {F1}PushExt(kbF1);
  1178. 'Q' : {F2}PushExt(kbF2);
  1179. 'R' : {F3}PushExt(kbF3);
  1180. 'S' : {F4}PushExt(kbF4);
  1181. 't' : {F5}PushExt(kbF5);
  1182. 'u' : {F6}PushExt(kbF6);
  1183. 'v' : {F7}PushExt(kbF7);
  1184. 'l' : {F8}PushExt(kbF8);
  1185. 'w' : {F9}PushExt(kbF9);
  1186. 'x' : {F10}PushExt(kbF10);
  1187. 'D' : {keyLeft}PushExt($4B);
  1188. 'C' : {keyRight}PushExt($4D);
  1189. 'A' : {keyUp}PushExt($48);
  1190. 'B' : {keyDown}PushExt($50);
  1191. else
  1192. RestoreArray;
  1193. end;
  1194. end;
  1195. 7 : begin {Esc[? keys in vt100 mode PM }
  1196. case ch of
  1197. '0' : State:=11;
  1198. '1' : State:=8;
  1199. '7' : State:=9;
  1200. else
  1201. RestoreArray;
  1202. end;
  1203. end;
  1204. 8 : begin {Esc[?1 keys in vt100 mode PM }
  1205. case ch of
  1206. 'l' : {local mode};
  1207. 'h' : {transmit mode};
  1208. ';' : { 'Esc[1;0c seems to be sent by M$ telnet app
  1209. for no hangup purposes }
  1210. state:=10;
  1211. else
  1212. RestoreArray;
  1213. end;
  1214. end;
  1215. 9 : begin {Esc[?7 keys in vt100 mode PM }
  1216. case ch of
  1217. 'l' : {exit_am_mode};
  1218. 'h' : {enter_am_mode};
  1219. else
  1220. RestoreArray;
  1221. end;
  1222. end;
  1223. 10 : begin {Esc[?1; keys in vt100 mode PM }
  1224. case ch of
  1225. '0' : state:=11;
  1226. else
  1227. RestoreArray;
  1228. end;
  1229. end;
  1230. 11 : begin {Esc[?1;0 keys in vt100 mode PM }
  1231. case ch of
  1232. 'c' : ;
  1233. else
  1234. RestoreArray;
  1235. end;
  1236. end;
  1237. 13 : begin {Esc[M mouse prefix for xterm }
  1238. GenMouseEvent;
  1239. end;
  1240. 255 : { just forget this trailing char };
  1241. end;
  1242. if (State<>0) and (InCnt=0) then
  1243. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1244. end;
  1245. if State=1 then
  1246. PushKey(ch);
  1247. {$endif NotUseTree}
  1248. if ch='$' then
  1249. begin { '$<XX>' means a delay of XX millisecs }
  1250. is_delay :=false;
  1251. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1252. if (sysKeyPressed) then
  1253. begin
  1254. ch:=ttyRecvChar;
  1255. is_delay:=(ch='<');
  1256. if not is_delay then
  1257. begin
  1258. PushKey('$');
  1259. PushKey(ch);
  1260. end
  1261. else
  1262. begin
  1263. {$ifdef logging}
  1264. write(f,'$<');
  1265. {$endif logging}
  1266. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1267. while (sysKeyPressed) and (ch<>'>') do
  1268. begin
  1269. { Should we really repect this delay ?? }
  1270. ch:=ttyRecvChar;
  1271. {$ifdef logging}
  1272. write(f,ch);
  1273. {$endif logging}
  1274. Select(StdInputHandle+1,@fdsin,nil,nil,10);
  1275. end;
  1276. end;
  1277. end
  1278. else
  1279. PushKey('$');
  1280. end;
  1281. end
  1282. {$ifdef logging}
  1283. writeln(f);
  1284. {$endif logging}
  1285. {$ifndef NotUseTree}
  1286. ;
  1287. ReadKey:=PopKey;
  1288. {$else NotUseTree}
  1289. else
  1290. Begin
  1291. case ch of
  1292. #127 : PushKey(#8);
  1293. else
  1294. PushKey(ch);
  1295. end;
  1296. End;
  1297. ReadKey:=PopKey;
  1298. {$endif NotUseTree}
  1299. End;
  1300. function ShiftState:byte;
  1301. var
  1302. arg,shift : longint;
  1303. begin
  1304. arg:=6;
  1305. shift:=0;
  1306. {$Ifndef BSD}
  1307. if IOCtl(StdInputHandle,TIOCLINUX,@arg) then
  1308. begin
  1309. if (arg and 8)<>0 then
  1310. shift:=kbAlt;
  1311. if (arg and 4)<>0 then
  1312. inc(shift,kbCtrl);
  1313. { 2 corresponds to AltGr so set both kbAlt and kbCtrl PM }
  1314. if (arg and 2)<>0 then
  1315. shift:=shift or (kbAlt or kbCtrl);
  1316. if (arg and 1)<>0 then
  1317. inc(shift,kbShift);
  1318. end;
  1319. {$endif}
  1320. ShiftState:=shift;
  1321. end;
  1322. { Exported functions }
  1323. procedure InitKeyboard;
  1324. begin
  1325. SetRawMode(true);
  1326. patchkeyboard;
  1327. {$ifdef logging}
  1328. assign(f,'keyboard.log');
  1329. rewrite(f);
  1330. {$endif logging}
  1331. if not IsConsole then
  1332. begin
  1333. { default for Shift prefix is ^ A}
  1334. if ShiftPrefix = 0 then
  1335. ShiftPrefix:=1;
  1336. {default for Alt prefix is ^Z }
  1337. if AltPrefix=0 then
  1338. AltPrefix:=26;
  1339. { default for Ctrl Prefix is ^W }
  1340. if CtrlPrefix=0 then
  1341. CtrlPrefix:=23;
  1342. end;
  1343. {$ifndef NotUseTree}
  1344. LoadDefaultSequences;
  1345. LoadTerminfoSequences;
  1346. {$endif not NotUseTree}
  1347. end;
  1348. procedure DoneKeyboard;
  1349. begin
  1350. unpatchkeyboard;
  1351. SetRawMode(false);
  1352. {$ifdef logging}
  1353. close(f);
  1354. {$endif logging}
  1355. end;
  1356. function GetKeyEvent: TKeyEvent;
  1357. function EvalScan(b:byte):byte;
  1358. const
  1359. DScan:array[0..31] of byte = (
  1360. $39, $02, $28, $04, $05, $06, $08, $28,
  1361. $0A, $0B, $09, $0D, $33, $0C, $34, $35,
  1362. $0B, $02, $03, $04, $05, $06, $07, $08,
  1363. $09, $0A, $27, $27, $33, $0D, $34, $35);
  1364. LScan:array[0..31] of byte = (
  1365. $29, $1E, $30, $2E, $20, $12, $21, $22,
  1366. $23, $17, $24, $25, $26, $32, $31, $18,
  1367. $19, $10, $13, $1F, $14, $16, $2F, $11,
  1368. $2D, $15, $2C, $1A, $2B, $1B, $29, $0C);
  1369. begin
  1370. if (b and $E0)=$20 { digits / leters } then
  1371. EvalScan:=DScan[b and $1F]
  1372. else
  1373. case b of
  1374. $08:EvalScan:=$0E; { backspace }
  1375. $09:EvalScan:=$0F; { TAB }
  1376. $0D:EvalScan:=$1C; { CR }
  1377. $1B:EvalScan:=$01; { esc }
  1378. $40:EvalScan:=$03; { @ }
  1379. $5E:EvalScan:=$07; { ^ }
  1380. $60:EvalScan:=$29; { ` }
  1381. else
  1382. EvalScan:=LScan[b and $1F];
  1383. end;
  1384. end;
  1385. function EvalScanZ(b:byte):byte;
  1386. begin
  1387. EvalScanZ:=b;
  1388. if b in [$3B..$44] { F1..F10 -> Alt-F1..Alt-F10} then
  1389. EvalScanZ:=b+$2D;
  1390. end;
  1391. const
  1392. {kbHome, kbUp, kbPgUp,Missing, kbLeft,
  1393. kbCenter, kbRight, kbAltGrayPlus, kbend,
  1394. kbDown, kbPgDn, kbIns, kbDel }
  1395. CtrlArrow : array [kbHome..kbDel] of byte =
  1396. {($77,$8d,$84,$8e,$73,$8f,$74,$90,$75,$91,$76);}
  1397. (kbCtrlHome,kbCtrlUp,kbCtrlPgUp,kbNoKey,kbCtrlLeft,
  1398. kbCtrlCenter,kbCtrlRight,kbAltGrayPlus,kbCtrlEnd,
  1399. kbCtrlDown,kbCtrlPgDn,kbCtrlIns,kbCtrlDel);
  1400. AltArrow : array [kbHome..kbDel] of byte =
  1401. (kbAltHome,kbAltUp,kbAltPgUp,kbNoKey,kbAltLeft,
  1402. kbCenter,kbAltRight,kbAltGrayPlus,kbAltEnd,
  1403. kbAltDown,kbAltPgDn,kbAltIns,kbAltDel);
  1404. var
  1405. MyScan,
  1406. SState : byte;
  1407. MyChar : char;
  1408. EscUsed,AltPrefixUsed,CtrlPrefixUsed,ShiftPrefixUsed,IsAlt,Again : boolean;
  1409. begin {main}
  1410. if PendingKeyEvent<>0 then
  1411. begin
  1412. GetKeyEvent:=PendingKeyEvent;
  1413. PendingKeyEvent:=0;
  1414. exit;
  1415. end;
  1416. MyChar:=Readkey(IsAlt);
  1417. MyScan:=ord(MyChar);
  1418. SState:=ShiftState;
  1419. CtrlPrefixUsed:=false;
  1420. AltPrefixUsed:=false;
  1421. ShiftPrefixUsed:=false;
  1422. EscUsed:=false;
  1423. if IsAlt then
  1424. SState:=SState or kbAlt;
  1425. repeat
  1426. again:=false;
  1427. if Mychar=#0 then
  1428. begin
  1429. MyScan:=ord(ReadKey(IsAlt));
  1430. { Handle Ctrl-<x>, but not AltGr-<x> }
  1431. if ((SState and kbCtrl)<>0) and ((SState and kbAlt) = 0) then
  1432. begin
  1433. case MyScan of
  1434. kbHome..kbDel : { cArrow }
  1435. MyScan:=CtrlArrow[MyScan];
  1436. kbF1..KbF10 : { cF1-cF10 }
  1437. MyScan:=MyScan+kbCtrlF1-kbF1;
  1438. kbF11..KbF12 : { cF11-cF12 }
  1439. MyScan:=MyScan+kbCtrlF11-kbF11;
  1440. end;
  1441. end
  1442. { Handle Alt-<x>, but not AltGr }
  1443. else if ((SState and kbAlt)<>0) and ((SState and kbCtrl) = 0) then
  1444. begin
  1445. case MyScan of
  1446. kbHome..kbDel : { AltArrow }
  1447. MyScan:=AltArrow[MyScan];
  1448. kbF1..KbF10 : { aF1-aF10 }
  1449. MyScan:=MyScan+kbAltF1-kbF1;
  1450. kbF11..KbF12 : { aF11-aF12 }
  1451. MyScan:=MyScan+kbAltF11-kbF11;
  1452. end;
  1453. end
  1454. else if (SState and kbShift)<>0 then
  1455. begin
  1456. case MyScan of
  1457. kbIns: MyScan:=kbShiftIns;
  1458. kbDel: MyScan:=kbShiftDel;
  1459. kbF1..KbF10 : { sF1-sF10 }
  1460. MyScan:=MyScan+kbShiftF1-kbF1;
  1461. kbF11..KbF12 : { sF11-sF12 }
  1462. MyScan:=MyScan+kbShiftF11-kbF11;
  1463. end;
  1464. end;
  1465. if (MyChar<>#0) or (MyScan<>0) or (SState<>0) then
  1466. GetKeyEvent:=$3000000 or ord(MyChar) or (MyScan shl 8) or (SState shl 16)
  1467. else
  1468. GetKeyEvent:=0;
  1469. exit;
  1470. end
  1471. else if MyChar=#27 then
  1472. begin
  1473. if EscUsed then
  1474. SState:=SState and not kbAlt
  1475. else
  1476. begin
  1477. SState:=SState or kbAlt;
  1478. Again:=true;
  1479. EscUsed:=true;
  1480. end;
  1481. end
  1482. else if (AltPrefix<>0) and (MyChar=chr(AltPrefix)) then
  1483. begin { ^Z - replace Alt for Linux OS }
  1484. if AltPrefixUsed then
  1485. begin
  1486. SState:=SState and not kbAlt;
  1487. end
  1488. else
  1489. begin
  1490. AltPrefixUsed:=true;
  1491. SState:=SState or kbAlt;
  1492. Again:=true;
  1493. end;
  1494. end
  1495. else if (CtrlPrefix<>0) and (MyChar=chr(CtrlPrefix)) then
  1496. begin
  1497. if CtrlPrefixUsed then
  1498. SState:=SState and not kbCtrl
  1499. else
  1500. begin
  1501. CtrlPrefixUsed:=true;
  1502. SState:=SState or kbCtrl;
  1503. Again:=true;
  1504. end;
  1505. end
  1506. else if (ShiftPrefix<>0) and (MyChar=chr(ShiftPrefix)) then
  1507. begin
  1508. if ShiftPrefixUsed then
  1509. SState:=SState and not kbShift
  1510. else
  1511. begin
  1512. ShiftPrefixUsed:=true;
  1513. SState:=SState or kbShift;
  1514. Again:=true;
  1515. end;
  1516. end;
  1517. if not again then
  1518. begin
  1519. MyScan:=EvalScan(ord(MyChar));
  1520. if ((SState and kbAlt)<>0) and ((SState and kbCtrl) = 0) then
  1521. begin
  1522. if MyScan in [$02..$0D] then
  1523. inc(MyScan,$76);
  1524. MyChar:=chr(0);
  1525. end
  1526. else if (SState and kbShift)<>0 then
  1527. if MyChar=#9 then
  1528. begin
  1529. MyChar:=#0;
  1530. MyScan:=kbShiftTab;
  1531. end;
  1532. end
  1533. else
  1534. begin
  1535. MyChar:=Readkey(IsAlt);
  1536. MyScan:=ord(MyChar);
  1537. if IsAlt then
  1538. SState:=SState or kbAlt;
  1539. end;
  1540. until not Again;
  1541. if (MyChar<>#0) or (MyScan<>0) or (SState<>0) then
  1542. GetKeyEvent:=$3000000 or ord(MyChar) or (MyScan shl 8) or (SState shl 16)
  1543. else
  1544. GetKeyEvent:=0;
  1545. end;
  1546. function PollKeyEvent: TKeyEvent;
  1547. begin
  1548. if PendingKeyEvent<>0 then
  1549. exit(PendingKeyEvent);
  1550. if keypressed then
  1551. begin
  1552. { just get the key and place it in the pendingkeyevent }
  1553. PendingKeyEvent:=GetKeyEvent;
  1554. PollKeyEvent:=PendingKeyEvent;
  1555. end
  1556. else
  1557. PollKeyEvent:=0;
  1558. end;
  1559. function PollShiftStateEvent: TKeyEvent;
  1560. begin
  1561. PollShiftStateEvent:=ShiftState shl 16;
  1562. end;
  1563. { Function key translation }
  1564. type
  1565. TTranslationEntry = packed record
  1566. Min, Max: Byte;
  1567. Offset: Word;
  1568. end;
  1569. const
  1570. TranslationTableEntries = 12;
  1571. TranslationTable: array [1..TranslationTableEntries] of TTranslationEntry =
  1572. ((Min: $3B; Max: $44; Offset: kbdF1), { function keys F1-F10 }
  1573. (Min: $54; Max: $5D; Offset: kbdF1), { Shift fn keys F1-F10 }
  1574. (Min: $5E; Max: $67; Offset: kbdF1), { Ctrl fn keys F1-F10 }
  1575. (Min: $68; Max: $71; Offset: kbdF1), { Alt fn keys F1-F10 }
  1576. (Min: $85; Max: $86; Offset: kbdF11), { function keys F11-F12 }
  1577. (Min: $87; Max: $88; Offset: kbdF11), { Shift+function keys F11-F12 }
  1578. (Min: $89; Max: $8A; Offset: kbdF11), { Ctrl+function keys F11-F12 }
  1579. (Min: $8B; Max: $8C; Offset: kbdF11), { Alt+function keys F11-F12 }
  1580. (Min: $47; Max: $49; Offset: kbdHome), { Keypad keys kbdHome-kbdPgUp }
  1581. (Min: $4B; Max: $4D; Offset: kbdLeft), { Keypad keys kbdLeft-kbdRight }
  1582. (Min: $4F; Max: $51; Offset: kbdEnd), { Keypad keys kbdEnd-kbdPgDn }
  1583. (Min: $52; Max: $53; Offset: kbdInsert));
  1584. function TranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
  1585. var
  1586. I: Integer;
  1587. ScanCode: Byte;
  1588. begin
  1589. if KeyEvent and $03000000 = $03000000 then
  1590. begin
  1591. if KeyEvent and $000000FF <> 0 then
  1592. begin
  1593. TranslateKeyEvent := KeyEvent and $00FFFFFF;
  1594. exit;
  1595. end
  1596. else
  1597. begin
  1598. { This is a function key }
  1599. ScanCode := (KeyEvent and $0000FF00) shr 8;
  1600. for I := 1 to TranslationTableEntries do
  1601. begin
  1602. if (TranslationTable[I].Min <= ScanCode) and (ScanCode <= TranslationTable[I].Max) then
  1603. begin
  1604. TranslateKeyEvent := $02000000 + (KeyEvent and $00FF0000) +
  1605. (ScanCode - TranslationTable[I].Min) + TranslationTable[I].Offset;
  1606. exit;
  1607. end;
  1608. end;
  1609. end;
  1610. end;
  1611. TranslateKeyEvent := KeyEvent;
  1612. end;
  1613. function TranslateKeyEventUniCode(KeyEvent: TKeyEvent): TKeyEvent;
  1614. begin
  1615. TranslateKeyEventUniCode := KeyEvent;
  1616. ErrorCode:=errKbdNotImplemented;
  1617. end;
  1618. procedure RestoreStartMode;
  1619. begin
  1620. TCSetAttr(1,TCSANOW,StartTio);
  1621. end;
  1622. begin
  1623. TCGetAttr(1,StartTio);
  1624. end.
  1625. {
  1626. $Log$
  1627. Revision 1.5 2001-08-02 20:56:08 peter
  1628. * Regenerated
  1629. Revision 1.4 2001/06/27 21:37:38 peter
  1630. * v10 merges
  1631. Revision 1.3 2001/04/10 23:35:02 peter
  1632. * fixed argument name
  1633. * merged fixes
  1634. Revision 1.2.2.5 2001/03/27 12:38:10 pierre
  1635. + RestoreStartMode function
  1636. Revision 1.2.2.4 2001/03/27 11:41:03 pierre
  1637. * fix the special handler case to avoid waiting for one more char
  1638. Revision 1.2.2.3 2001/03/24 22:38:46 pierre
  1639. * fix bug with AltGr keys
  1640. Revision 1.2.2.2 2001/01/30 22:23:44 peter
  1641. * unix back to linux
  1642. Revision 1.2.2.1 2001/01/30 21:52:02 peter
  1643. * moved api utils to rtl
  1644. Revision 1.2 2001/01/21 20:21:40 marco
  1645. * Rename fest II. Rtl OK
  1646. Revision 1.1 2001/01/13 11:03:58 peter
  1647. * API 2 RTL commit
  1648. }