keyboard.pp 43 KB

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