2
0

crt.pp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Michael Van Canneyt and Peter Vreman,
  5. members of the Free Pascal development team.
  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 Crt;
  13. Interface
  14. {$i crth.inc}
  15. Const
  16. { Controlling consts }
  17. Flushing = false; {if true then don't buffer output}
  18. ConsoleMaxX = 1024;
  19. ConsoleMaxY = 1024;
  20. ScreenHeight : longint = 25;
  21. ScreenWidth : longint = 80;
  22. Type
  23. TCharAttr=packed record
  24. ch : char;
  25. attr : byte;
  26. end;
  27. TConsoleBuf=Array[0..ConsoleMaxX*ConsoleMaxY-1] of TCharAttr;
  28. PConsoleBuf=^TConsoleBuf;
  29. var
  30. ConsoleBuf : PConsoleBuf;
  31. Implementation
  32. uses BaseUnix ,unix, termio;
  33. {
  34. The definitions of TextRec and FileRec are in separate files.
  35. }
  36. {$i textrec.inc}
  37. Const
  38. OldTextAttr : byte = $07;
  39. Var
  40. CurrX,CurrY : Byte;
  41. OutputRedir, InputRedir : boolean; { is the output/input being redirected (not a TTY) }
  42. WinMinX,
  43. WinMinY,
  44. WinMaxX,
  45. WinMaxY : Longint;
  46. {*****************************************************************************
  47. Some Handy Functions Not in the System.PP
  48. *****************************************************************************}
  49. Function Str(l:longint):string;
  50. {
  51. Return a String of the longint
  52. }
  53. var
  54. hstr : string[32];
  55. begin
  56. System.Str(l,hstr);
  57. Str:=hstr;
  58. end;
  59. Function Max(l1,l2:longint):longint;
  60. {
  61. Return the maximum of l1 and l2
  62. }
  63. begin
  64. if l1>l2 then
  65. Max:=l1
  66. else
  67. Max:=l2;
  68. end;
  69. Function Min(l1,l2:longint):longint;
  70. {
  71. Return the minimum of l1 and l2
  72. }
  73. begin
  74. if l1<l2 then
  75. Min:=l1
  76. else
  77. Min:=l2;
  78. end;
  79. {*****************************************************************************
  80. Optimal AnsiString Conversion Routines
  81. *****************************************************************************}
  82. Function XY2Ansi(x,y,ox,oy:longint):String;
  83. {
  84. Returns a string with the escape sequences to go to X,Y on the screen
  85. }
  86. Begin
  87. if y=oy then
  88. begin
  89. if x=ox then
  90. begin
  91. // this workaround should improve behaviour on some terminals.
  92. // debian bug 216057 but I also observed this with video on FreeBSD
  93. if x=screenwidth then
  94. XY2Ansi:=#27'['+Str(y)+';'+Str(x)+'H'
  95. else
  96. // end workaround
  97. XY2Ansi:='';
  98. exit;
  99. end;
  100. {$ifdef Linux} // linux CRT shortcut
  101. if x=1 then
  102. begin
  103. XY2Ansi:=#13;
  104. exit;
  105. end;
  106. {$endif}
  107. if x>ox then
  108. begin
  109. XY2Ansi:=#27'['+Str(x-ox)+'C';
  110. exit;
  111. end
  112. else
  113. begin
  114. XY2Ansi:=#27'['+Str(ox-x)+'D';
  115. exit;
  116. end;
  117. end;
  118. if x=ox then
  119. begin
  120. if y>oy then
  121. begin
  122. XY2Ansi:=#27'['+Str(y-oy)+'B';
  123. exit;
  124. end
  125. else
  126. begin
  127. XY2Ansi:=#27'['+Str(oy-y)+'A';
  128. exit;
  129. end;
  130. end;
  131. {$ifdef Linux} // this shortcut isn't for everybody
  132. if (x=1) and (oy+1=y) then
  133. XY2Ansi:=#13#10
  134. else
  135. {$endif}
  136. XY2Ansi:=#27'['+Str(y)+';'+Str(x)+'H';
  137. End;
  138. const
  139. AnsiTbl : string[8]='04261537';
  140. Function Attr2Ansi(Attr,OAttr:longint):string;
  141. {
  142. Convert Attr to an Ansi String, the Optimal code is calculate
  143. with use of the old OAttr
  144. }
  145. var
  146. hstr : string[16];
  147. OFg,OBg,Fg,Bg : longint;
  148. procedure AddSep(ch:char);
  149. begin
  150. if length(hstr)>0 then
  151. hstr:=hstr+';';
  152. hstr:=hstr+ch;
  153. end;
  154. begin
  155. if Attr=OAttr then
  156. begin
  157. Attr2Ansi:='';
  158. exit;
  159. end;
  160. Hstr:='';
  161. Fg:=Attr and $f;
  162. Bg:=Attr shr 4;
  163. OFg:=OAttr and $f;
  164. OBg:=OAttr shr 4;
  165. if (OFg<>7) or (Fg=7) or ((OFg>7) and (Fg<8)) or ((OBg>7) and (Bg<8)) then
  166. begin
  167. hstr:='0';
  168. OFg:=7;
  169. OBg:=0;
  170. end;
  171. if (Fg>7) and (OFg<8) then
  172. begin
  173. AddSep('1');
  174. OFg:=OFg or 8;
  175. end;
  176. if (Bg and 8)<>(OBg and 8) then
  177. begin
  178. AddSep('5');
  179. OBg:=OBg or 8;
  180. end;
  181. if (Fg<>OFg) then
  182. begin
  183. AddSep('3');
  184. hstr:=hstr+AnsiTbl[(Fg and 7)+1];
  185. end;
  186. if (Bg<>OBg) then
  187. begin
  188. AddSep('4');
  189. hstr:=hstr+AnsiTbl[(Bg and 7)+1];
  190. end;
  191. if hstr='0' then
  192. hstr:='';
  193. Attr2Ansi:=#27'['+hstr+'m';
  194. end;
  195. Function Ansi2Attr(Const HStr:String;oattr:longint):longint;
  196. {
  197. Convert an Escape sequence to an attribute value, uses Oattr as the last
  198. color written
  199. }
  200. var
  201. i,j : longint;
  202. begin
  203. i:=2;
  204. if (Length(HStr)<3) or (Hstr[1]<>#27) or (Hstr[2]<>'[') then
  205. i:=255;
  206. while (i<length(Hstr)) do
  207. begin
  208. inc(i);
  209. case Hstr[i] of
  210. '0' : OAttr:=7;
  211. '1' : OAttr:=OAttr or $8;
  212. '5' : OAttr:=OAttr or $80;
  213. '3' : begin
  214. inc(i);
  215. j:=pos(Hstr[i],AnsiTbl);
  216. if j>0 then
  217. OAttr:=(OAttr and $f8) or (j-1);
  218. end;
  219. '4' : begin
  220. inc(i);
  221. j:=pos(Hstr[i],AnsiTbl);
  222. if j>0 then
  223. OAttr:=(OAttr and $8f) or ((j-1) shl 4);
  224. end;
  225. 'm' : i:=length(HStr);
  226. end;
  227. end;
  228. Ansi2Attr:=OAttr;
  229. end;
  230. {*****************************************************************************
  231. Buffered StdIn/StdOut IO
  232. *****************************************************************************}
  233. const
  234. ttyIn=0; {Handles for stdin/stdout}
  235. ttyOut=1;
  236. ttyFlush:boolean=true;
  237. {Buffered Input/Output}
  238. InSize=256;
  239. OutSize=1024;
  240. var
  241. InBuf : array[0..InSize-1] of char;
  242. InCnt,
  243. InHead,
  244. InTail : longint;
  245. OutBuf : array[0..OutSize-1] of char;
  246. OutCnt : longint;
  247. {Flush Output Buffer}
  248. procedure ttyFlushOutput;
  249. begin
  250. if OutCnt>0 then
  251. begin
  252. fpWrite(ttyOut,OutBuf,OutCnt);
  253. OutCnt:=0;
  254. end;
  255. end;
  256. Function ttySetFlush(b:boolean):boolean;
  257. begin
  258. ttySetFlush:=ttyFlush;
  259. ttyFlush:=b;
  260. if ttyFlush then
  261. ttyFlushOutput;
  262. end;
  263. {Send Char to Remote}
  264. Procedure ttySendChar(c:char);
  265. Begin
  266. if OutCnt<OutSize then
  267. begin
  268. OutBuf[OutCnt]:=c;
  269. inc(OutCnt);
  270. end;
  271. {Full ?}
  272. if (OutCnt>=OutSize) then
  273. ttyFlushOutput;
  274. End;
  275. {Send String to Remote}
  276. procedure ttySendStr(const hstr:string);
  277. var
  278. i : longint;
  279. begin
  280. for i:=1to length(hstr) do
  281. ttySendChar(hstr[i]);
  282. if ttyFlush then
  283. ttyFlushOutput;
  284. end;
  285. {Get Char from Remote}
  286. function ttyRecvChar:char;
  287. var
  288. Readed,i : longint;
  289. begin
  290. {Buffer Empty? Yes, Input from StdIn}
  291. if (InHead=InTail) then
  292. begin
  293. {Calc Amount of Chars to Read}
  294. i:=InSize-InHead;
  295. if InTail>InHead then
  296. i:=InTail-InHead;
  297. {Read}
  298. Readed:=fpread(TTYIn,InBuf[InHead],i);
  299. {Increase Counters}
  300. inc(InCnt,Readed);
  301. inc(InHead,Readed);
  302. {Wrap if End has Reached}
  303. if InHead>=InSize then
  304. InHead:=0;
  305. end;
  306. {Check Buffer}
  307. if (InCnt=0) then
  308. ttyRecvChar:=#0
  309. else
  310. begin
  311. ttyRecvChar:=InBuf[InTail];
  312. dec(InCnt);
  313. inc(InTail);
  314. if InTail>=InSize then
  315. InTail:=0;
  316. end;
  317. end;
  318. {*****************************************************************************
  319. Screen Routines not Window Depended
  320. *****************************************************************************}
  321. procedure ttyGotoXY(x,y:longint);
  322. {
  323. Goto XY on the Screen, if a value is 0 the goto the current
  324. postion of that value and always recalc the ansicode for it
  325. }
  326. begin
  327. if x=0 then
  328. begin
  329. x:=CurrX;
  330. CurrX:=$ff;
  331. end;
  332. if y=0 then
  333. begin
  334. y:=CurrY;
  335. CurrY:=$ff;
  336. end;
  337. if OutputRedir then
  338. begin
  339. if longint(y)-longint(CurrY)=1 then
  340. ttySendStr(#10);
  341. end
  342. else
  343. ttySendStr(XY2Ansi(x,y,CurrX,CurrY));
  344. CurrX:=x;
  345. CurrY:=y;
  346. end;
  347. procedure ttyColor(a:longint);
  348. {
  349. Set Attribute to A, only output if not the last attribute is set
  350. }
  351. begin
  352. if a<>OldTextAttr then
  353. begin
  354. if not OutputRedir then
  355. ttySendStr(Attr2Ansi(a,OldTextAttr));
  356. TextAttr:=a;
  357. OldTextAttr:=a;
  358. end;
  359. end;
  360. procedure ttyWrite(const s:string);
  361. {
  362. Write a string to the output, memory copy and Current X&Y are also updated
  363. }
  364. var
  365. idx,i : longint;
  366. begin
  367. ttySendStr(s);
  368. {Update MemCopy}
  369. idx:=(CurrY-1)*ScreenWidth-1;
  370. for i:=1to length(s) do
  371. if s[i]=#8 then
  372. begin
  373. if CurrX>1 then
  374. dec(CurrX);
  375. end
  376. else
  377. begin
  378. ConsoleBuf^[idx+CurrX].ch:=s[i];
  379. ConsoleBuf^[idx+CurrX].attr:=TextAttr;
  380. inc(CurrX);
  381. if CurrX>ScreenWidth then
  382. CurrX:=ScreenWidth;
  383. end;
  384. end;
  385. Function FullWin:boolean;
  386. {
  387. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  388. }
  389. begin
  390. FullWin:=(WinMinX=1) and (WinMinY=1) and
  391. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  392. end;
  393. procedure LineWrite(const temp:String);
  394. {
  395. Write a Line to the screen, doesn't write on 80,25 under Dos
  396. the Current CurrX is set to WinMax. NO MEMORY UPDATE!
  397. }
  398. begin
  399. CurrX:=WinMaxX+1;
  400. if (CurrX>=ScreenWidth) then
  401. CurrX:=WinMaxX;
  402. ttySendStr(Temp);
  403. end;
  404. Procedure DoEmptyLine(y,xl,xh:Longint);
  405. {
  406. Write an empty line at row Y from column Xl to Xh. Memory is also updated.
  407. }
  408. Var
  409. len : Longint;
  410. blank_with_attribute : TCharAttr;
  411. Begin
  412. ttyGotoXY(xl,y);
  413. len:=xh-xl+1;
  414. LineWrite(Space(len));
  415. blank_with_attribute.ch:=' ';
  416. blank_with_attribute.attr:=TextAttr;
  417. FillWord(ConsoleBuf^[(y-1)*ScreenWidth+xl-1],len,word(blank_with_attribute));
  418. End;
  419. procedure DoScrollLine(y1,y2,xl,xh:longint);
  420. {
  421. Move Line y1 to y2, use only columns Xl-Xh, Memory is updated also
  422. }
  423. var
  424. Temp : string;
  425. idx,
  426. OldAttr,
  427. x,attr : longint;
  428. begin
  429. ttyGotoXY(xl,y2);
  430. { precalc ConsoleBuf[] y-offset }
  431. idx:=(y1-1)*ScreenWidth-1;
  432. { update screen }
  433. OldAttr:=$ff;
  434. Temp:='';
  435. For x:=xl To xh Do
  436. Begin
  437. attr:=ConsoleBuf^[idx+x].attr;
  438. if (attr<>OldAttr) and (not OutputRedir) then
  439. begin
  440. temp:=temp+Attr2Ansi(Attr,OldAttr);
  441. OldAttr:=Attr;
  442. end;
  443. Temp:=Temp+ConsoleBuf^[idx+x].ch;
  444. if (x=xh) or (length(Temp)>240) then
  445. begin
  446. LineWrite(Temp);
  447. Temp:='';
  448. end;
  449. End;
  450. {Update memory copy}
  451. Move(ConsoleBuf^[(y1-1)*ScreenWidth+xl-1],ConsoleBuf^[(y2-1)*ScreenWidth+xl-1],(xh-xl+1)*2);
  452. end;
  453. Procedure TextColor(Color: Byte);
  454. {
  455. Switch foregroundcolor
  456. }
  457. var AddBlink : byte;
  458. Begin
  459. If (Color>15) Then
  460. AddBlink:=Blink
  461. else
  462. AddBlink:=0;
  463. ttyColor((Color and $f) or (TextAttr and $70) or AddBlink);
  464. End;
  465. Procedure TextBackground(Color: Byte);
  466. {
  467. Switch backgroundcolor
  468. }
  469. Begin
  470. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink));
  471. ttyColor(TextAttr);
  472. End;
  473. Procedure HighVideo;
  474. {
  475. Set highlighted output.
  476. }
  477. Begin
  478. TextColor(TextAttr Or $08);
  479. End;
  480. Procedure LowVideo;
  481. {
  482. Set normal output
  483. }
  484. Begin
  485. TextColor(TextAttr And $77);
  486. End;
  487. Procedure NormVideo;
  488. {
  489. Set normal back and foregroundcolors.
  490. }
  491. Begin
  492. TextColor(7);
  493. TextBackGround(0);
  494. End;
  495. Procedure GotoXy(X: Byte; Y: Byte);
  496. {
  497. Go to coordinates X,Y in the current window.
  498. }
  499. Begin
  500. If (X>0) and (X<=WinMaxX- WinMinX+1) and
  501. (Y>0) and (Y<=WinMaxY-WinMinY+1) Then
  502. Begin
  503. Inc(X,WinMinX-1);
  504. Inc(Y,WinMinY-1);
  505. ttyGotoXY(x,y);
  506. End;
  507. End;
  508. Procedure Window(X1, Y1, X2, Y2: Byte);
  509. {
  510. Set screen window to the specified coordinates.
  511. }
  512. Begin
  513. if (X1>X2) or (X2>ScreenWidth) or
  514. (Y1>Y2) or (Y2>ScreenHeight) then
  515. exit;
  516. WinMinX:=X1;
  517. WinMaxX:=X2;
  518. WinMinY:=Y1;
  519. WinMaxY:=Y2;
  520. WindMin:=((Y1-1) Shl 8)+(X1-1);
  521. WindMax:=((Y2-1) Shl 8)+(X2-1);
  522. GoToXY(1,1);
  523. End;
  524. Procedure ClrScr;
  525. {
  526. Clear the current window, and set the cursor on 1,1
  527. }
  528. Var
  529. CY,i : Longint;
  530. oldflush : boolean;
  531. blank_with_attribute : TCharAttr;
  532. Begin
  533. { See if color has changed }
  534. if OldTextAttr<>TextAttr then
  535. begin
  536. i:=TextAttr;
  537. TextAttr:=OldTextAttr;
  538. ttyColor(i);
  539. end;
  540. oldflush:=ttySetFlush(Flushing);
  541. if FullWin then
  542. begin
  543. if not OutputRedir then
  544. ttySendStr(#27'[H'#27'[2J');
  545. CurrX:=1;
  546. CurrY:=1;
  547. blank_with_attribute.ch := ' ';
  548. blank_with_attribute.attr := TextAttr;
  549. FillWord(ConsoleBuf^,ScreenWidth*ScreenHeight,word(blank_with_attribute));
  550. end
  551. else
  552. begin
  553. For Cy:=WinMinY To WinMaxY Do
  554. DoEmptyLine(Cy,WinMinX,WinMaxX);
  555. GoToXY(1,1);
  556. end;
  557. ttySetFlush(oldflush);
  558. End;
  559. Procedure ClrEol;
  560. {
  561. Clear from current position to end of line.
  562. }
  563. var
  564. len,i : longint;
  565. IsLastLine : boolean;
  566. Begin
  567. { See if color has changed }
  568. if OldTextAttr<>TextAttr then
  569. begin
  570. i:=TextAttr;
  571. TextAttr:=OldTextAttr;
  572. ttyColor(i);
  573. end;
  574. if FullWin or (WinMaxX = ScreenWidth) then
  575. begin
  576. if not OutputRedir then
  577. ttySendStr(#27'[K');
  578. end
  579. else
  580. begin
  581. { Tweak winmaxx and winmaxy so no scrolling happends }
  582. len:=WinMaxX-CurrX+1;
  583. IsLastLine:=false;
  584. if CurrY=WinMaxY then
  585. begin
  586. inc(WinMaxX,3);
  587. inc(WinMaxY,2);
  588. IsLastLine:=true;
  589. end;
  590. ttySendStr(Space(len));
  591. if IsLastLine then
  592. begin
  593. dec(WinMaxX,3);
  594. dec(WinMaxY,2);
  595. end;
  596. ttyGotoXY(0,0);
  597. end;
  598. End;
  599. Function WhereX: Byte;
  600. {
  601. Return current X-position of cursor.
  602. }
  603. Begin
  604. WhereX:=CurrX-WinMinX+1;
  605. End;
  606. Function WhereY: Byte;
  607. {
  608. Return current Y-position of cursor.
  609. }
  610. Begin
  611. WhereY:=CurrY-WinMinY+1;
  612. End;
  613. Procedure ScrollScrnRegionUp(xl,yl,xh,yh, count: longint);
  614. {
  615. Scroll the indicated region count lines up. The empty lines are filled
  616. with blanks in the current color. The screen position is restored
  617. afterwards.
  618. }
  619. Var
  620. y,oldx,oldy : byte;
  621. oldflush : boolean;
  622. Begin
  623. oldflush:=ttySetFlush(Flushing);
  624. oldx:=CurrX;
  625. oldy:=CurrY;
  626. {Scroll}
  627. For y:=yl to yh-count do
  628. DoScrollLine(y+count,y,xl,xh);
  629. {Restore TextAttr}
  630. ttySendStr(Attr2Ansi(TextAttr,$ff));
  631. {Fill the rest with empty lines}
  632. for y:=yh-count+1 to yh do
  633. DoEmptyLine(y,xl,xh);
  634. {Restore current position}
  635. ttyGotoXY(OldX,OldY);
  636. ttySetFlush(oldflush);
  637. End;
  638. Procedure ScrollScrnRegionDown(xl,yl,xh,yh, count: longint);
  639. {
  640. Scroll the indicated region count lines down. The empty lines are filled
  641. with blanks in the current color. The screen position is restored
  642. afterwards.
  643. }
  644. Var
  645. y,oldx,oldy : byte;
  646. oldflush : boolean;
  647. Begin
  648. oldflush:=ttySetFlush(Flushing);
  649. oldx:=CurrX;
  650. oldy:=CurrY;
  651. {Scroll}
  652. for y:=yh downto yl+count do
  653. DoScrollLine(y-count,y,xl,xh);
  654. {Restore TextAttr}
  655. ttySendStr(Attr2Ansi(TextAttr,$ff));
  656. {Fill the rest with empty lines}
  657. for y:=yl to yl+count-1 do
  658. DoEmptyLine(y,xl,xh);
  659. {Restore current position}
  660. ttyGotoXY(OldX,OldY);
  661. ttySetFlush(oldflush);
  662. End;
  663. {*************************************************************************
  664. KeyBoard
  665. *************************************************************************}
  666. Const
  667. KeyBufferSize = 20;
  668. var
  669. KeyBuffer : Array[0..KeyBufferSize-1] of Char;
  670. KeyPut,
  671. KeySend : longint;
  672. Procedure PushKey(Ch:char);
  673. Var
  674. Tmp : Longint;
  675. Begin
  676. Tmp:=KeyPut;
  677. Inc(KeyPut);
  678. If KeyPut>=KeyBufferSize Then
  679. KeyPut:=0;
  680. If KeyPut<>KeySend Then
  681. KeyBuffer[Tmp]:=Ch
  682. Else
  683. KeyPut:=Tmp;
  684. End;
  685. Function PopKey:char;
  686. Begin
  687. If KeyPut<>KeySend Then
  688. Begin
  689. PopKey:=KeyBuffer[KeySend];
  690. Inc(KeySend);
  691. If KeySend>=KeyBufferSize Then
  692. KeySend:=0;
  693. End
  694. Else
  695. PopKey:=#0;
  696. End;
  697. Procedure PushExt(b:byte);
  698. begin
  699. PushKey(#0);
  700. PushKey(chr(b));
  701. end;
  702. const
  703. AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-=';
  704. AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+
  705. #044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131;
  706. Function FAltKey(ch:char):byte;
  707. var
  708. Idx : longint;
  709. Begin
  710. Idx:=Pos(ch,AltKeyStr);
  711. if Idx>0 then
  712. FAltKey:=byte(AltCodeStr[Idx])
  713. else
  714. FAltKey:=0;
  715. End;
  716. { This one doesn't care about keypresses already processed by readkey }
  717. { and waiting in the KeyBuffer, only about waiting keypresses at the }
  718. { TTYLevel (including ones that are waiting in the TTYRecvChar buffer) }
  719. function sysKeyPressed: boolean;
  720. var
  721. fdsin : tfdSet;
  722. begin
  723. if (InCnt>0) then
  724. sysKeyPressed:=true
  725. else
  726. begin
  727. fpFD_ZERO(fdsin);
  728. fpFD_SET(TTYin,fdsin);
  729. sysKeypressed:=(fpSelect(TTYIn+1,@fdsin,nil,nil,0)>0);
  730. end;
  731. end;
  732. Function KeyPressed:Boolean;
  733. Begin
  734. Keypressed := (KeySend<>KeyPut) or sysKeyPressed;
  735. End;
  736. Function ReadKey:char;
  737. Var
  738. ch : char;
  739. OldState,
  740. State : longint;
  741. FDS : TFDSet;
  742. Begin
  743. {Check Buffer first}
  744. if KeySend<>KeyPut then
  745. begin
  746. ReadKey:=PopKey;
  747. exit;
  748. end;
  749. {Wait for Key}
  750. { Only if none are waiting! (JM) }
  751. if not sysKeyPressed then
  752. begin
  753. FpFD_ZERO (FDS);
  754. fpFD_SET (0,FDS);
  755. fpSelect (1,@FDS,nil,nil,nil);
  756. end;
  757. ch:=ttyRecvChar;
  758. {Esc Found ?}
  759. CASE ch OF
  760. #27: begin
  761. State:=1;
  762. Delay(10);
  763. { This has to be sysKeyPressed and not "keyPressed", since after }
  764. { one iteration keyPressed will always be true because of the }
  765. { pushKey commands (JM) }
  766. while (State<>0) and (sysKeyPressed) do
  767. begin
  768. ch:=ttyRecvChar;
  769. OldState:=State;
  770. State:=0;
  771. case OldState of
  772. 1 : begin {Esc}
  773. case ch of
  774. 'a'..'z',
  775. '0'..'9',
  776. '-','=' : PushExt(FAltKey(ch));
  777. #10 : PushKey(#10);
  778. '[' : State:=2;
  779. {$IFDEF Unix}
  780. 'O': State:=7;
  781. {$ENDIF}
  782. else
  783. begin
  784. PushKey(ch);
  785. PushKey(#27);
  786. end;
  787. end;
  788. end;
  789. 2 : begin {Esc[}
  790. case ch of
  791. '[' : State:=3;
  792. 'A' : PushExt(72);
  793. 'B' : PushExt(80);
  794. 'C' : PushExt(77);
  795. 'D' : PushExt(75);
  796. {$IFDEF FREEBSD}
  797. {'E' - Center key, not handled in DOS TP7}
  798. 'F' : PushExt(79); {End}
  799. 'G': PushExt(81); {PageDown}
  800. {$ELSE}
  801. 'G' : PushKey('5'); {Center key, Linux}
  802. {$ENDIF}
  803. 'H' : PushExt(71);
  804. {$IFDEF FREEBSD}
  805. 'I' : PushExt(73); {PageUp}
  806. {$ENDIF}
  807. 'K' : PushExt(79);
  808. {$IFDEF FREEBSD}
  809. 'L' : PushExt(82); {Insert - Deekoo}
  810. 'M' : PushExt(59); {F1-F10 - Deekoo}
  811. 'N' : PushExt(60); {F2}
  812. 'O' : PushExt(61); {F3}
  813. 'P' : PushExt(62); {F4}
  814. 'Q' : PushExt(63); {F5}
  815. 'R' : PushExt(64); {F6}
  816. 'S' : PushExt(65); {F7}
  817. 'T' : PushExt(66); {F8}
  818. 'U' : PushExt(67); {F9}
  819. 'V' : PushExt(68); {F10}
  820. {Not sure if TP/BP handles F11 and F12 like this normally;
  821. In pcemu, a TP7 executable handles 'em this way, though.}
  822. 'W' : PushExt(133); {F11}
  823. 'X' : PushExt(134); {F12}
  824. 'Y' : PushExt(84); {Shift-F1}
  825. 'Z' : PushExt(85); {Shift-F2}
  826. 'a' : PushExt(86); {Shift-F3}
  827. 'b' : PushExt(87); {Shift-F4}
  828. 'c' : PushExt(88); {Shift-F5}
  829. 'd' : PushExt(89); {Shift-F6}
  830. 'e' : PushExt(90); {Shift-F7}
  831. 'f' : PushExt(91); {Shift-F8}
  832. 'g' : PushExt(92); {Shift-F9}
  833. 'h' : PushExt(93); {Shift-F10}
  834. 'i' : PushExt(135); {Shift-F11}
  835. 'j' : PushExt(136); {Shift-F12}
  836. 'k' : PushExt(94); {Ctrl-F1}
  837. 'l' : PushExt(95);
  838. 'm' : PushExt(96);
  839. 'n' : PushExt(97);
  840. 'o' : PushExt(98);
  841. 'p' : PushExt(99);
  842. 'q' : PushExt(100);
  843. 'r' : PushExt(101);
  844. 's' : PushExt(102);
  845. 't' : PushExt(103); {Ctrl-F10}
  846. 'u' : PushExt(137); {Ctrl-F11}
  847. 'v' : PushExt(138); {Ctrl-F12}
  848. {$ENDIF}
  849. '1' : State:=4;
  850. '2' : State:=5;
  851. '3' : State:=6;
  852. '4' : PushExt(79);
  853. '5' : PushExt(73);
  854. '6' : PushExt(81);
  855. else
  856. begin
  857. PushKey(ch);
  858. PushKey('[');
  859. PushKey(#27);
  860. end;
  861. end;
  862. if ch in ['4'..'6'] then
  863. State:=255;
  864. end;
  865. 3 : begin {Esc[[}
  866. case ch of
  867. 'A' : PushExt(59);
  868. 'B' : PushExt(60);
  869. 'C' : PushExt(61);
  870. 'D' : PushExt(62);
  871. 'E' : PushExt(63);
  872. end;
  873. end;
  874. 4 : begin {Esc[1}
  875. case ch of
  876. '~' : PushExt(71);
  877. '7' : PushExt(64);
  878. '8' : PushExt(65);
  879. '9' : PushExt(66);
  880. end;
  881. if (Ch<>'~') then
  882. State:=255;
  883. end;
  884. 5 : begin {Esc[2}
  885. case ch of
  886. '~' : PushExt(82);
  887. '0' : pushExt(67);
  888. '1' : PushExt(68);
  889. '3' : PushExt(133); {F11}
  890. {Esc[23~ is also shift-F1,shift-F11}
  891. '4' : PushExt(134); {F12}
  892. {Esc[24~ is also shift-F2,shift-F12}
  893. '5' : PushExt(86); {Shift-F3}
  894. '6' : PushExt(87); {Shift-F4}
  895. '8' : PushExt(88); {Shift-F5}
  896. '9' : PushExt(89); {Shift-F6}
  897. end;
  898. if (Ch<>'~') then
  899. State:=255;
  900. end;
  901. 6 : begin {Esc[3}
  902. case ch of
  903. '~' : PushExt(83); {Del}
  904. '1' : PushExt(90); {Shift-F7}
  905. '2' : PushExt(91); {Shift-F8}
  906. '3' : PushExt(92); {Shift-F9}
  907. '4' : PushExt(93); {Shift-F10}
  908. end;
  909. if (Ch<>'~') then
  910. State:=255;
  911. end;
  912. {$ifdef Unix}
  913. 7 : begin {Esc[O}
  914. case ch of
  915. 'A' : PushExt(72);
  916. 'B' : PushExt(80);
  917. 'C' : PushExt(77);
  918. 'D' : PushExt(75);
  919. end;
  920. end;
  921. {$endif}
  922. 255 : ;
  923. end;
  924. if State<>0 then
  925. Delay(10);
  926. end;
  927. if State=1 then
  928. PushKey(ch);
  929. end;
  930. #127: PushKey(#8);
  931. else PushKey(ch);
  932. End;
  933. ReadKey:=PopKey;
  934. End;
  935. Procedure Delay(MS: Word);
  936. {
  937. Wait for DTime milliseconds.
  938. }
  939. Begin
  940. fpSelect(0,nil,nil,nil,MS);
  941. End;
  942. {****************************************************************************
  943. Write(ln)/Read(ln) support
  944. ****************************************************************************}
  945. procedure DoLn;
  946. begin
  947. if CurrY=WinMaxY then
  948. begin
  949. if FullWin then
  950. begin
  951. ttySendStr(#10#13);
  952. CurrX:=WinMinX;
  953. CurrY:=WinMaxY;
  954. end
  955. else
  956. begin
  957. ScrollScrnRegionUp(WinMinX,WinMinY,WinMaxX,WinMaxY,1);
  958. ttyGotoXY(WinMinX,WinMaxY);
  959. end;
  960. end
  961. else
  962. ttyGotoXY(WinMinX,CurrY+1);
  963. end;
  964. var
  965. Lastansi : boolean;
  966. AnsiCode : string;
  967. Procedure DoWrite(const s:String);
  968. {
  969. Write string to screen, parse most common AnsiCodes
  970. }
  971. var
  972. found,
  973. OldFlush : boolean;
  974. x,y,
  975. i,j,
  976. SendBytes : longint;
  977. function AnsiPara(var hstr:string):byte;
  978. var
  979. k,j : longint;
  980. code : word;
  981. begin
  982. j:=pos(';',hstr);
  983. if j=0 then
  984. j:=length(hstr);
  985. val(copy(hstr,3,j-3),k,code);
  986. Delete(hstr,3,j-2);
  987. if k=0 then
  988. k:=1;
  989. AnsiPara:=k;
  990. end;
  991. procedure SendText;
  992. var
  993. LeftX : longint;
  994. begin
  995. while (SendBytes>0) do
  996. begin
  997. LeftX:=WinMaxX-CurrX+1;
  998. if (SendBytes>LeftX) then
  999. begin
  1000. ttyWrite(Copy(s,i-SendBytes,LeftX));
  1001. dec(SendBytes,LeftX);
  1002. DoLn;
  1003. end
  1004. else
  1005. begin
  1006. ttyWrite(Copy(s,i-SendBytes,SendBytes));
  1007. SendBytes:=0;
  1008. end;
  1009. end;
  1010. end;
  1011. begin
  1012. oldflush:=ttySetFlush(Flushing);
  1013. { Support textattr:= changing }
  1014. if OldTextAttr<>TextAttr then
  1015. begin
  1016. i:=TextAttr;
  1017. TextAttr:=OldTextAttr;
  1018. ttyColor(i);
  1019. end;
  1020. { write the stuff }
  1021. SendBytes:=0;
  1022. i:=1;
  1023. while (i<=length(s)) do
  1024. begin
  1025. if (s[i]=#27) or (LastAnsi) then
  1026. begin
  1027. SendText;
  1028. LastAnsi:=false;
  1029. j:=i;
  1030. found:=false;
  1031. while (j<=length(s)) and (not found) do
  1032. begin
  1033. found:=not (s[j] in [#27,'[','0'..'9',';','?']);
  1034. inc(j);
  1035. end;
  1036. Ansicode:=AnsiCode+Copy(s,i,j-i);
  1037. if found then
  1038. begin
  1039. case AnsiCode[length(AnsiCode)] of
  1040. 'm' : ttyColor(Ansi2Attr(AnsiCode,TextAttr));
  1041. 'H' : begin {No other way :( Coz First Para=Y}
  1042. y:=AnsiPara(AnsiCode);
  1043. x:=AnsiPara(AnsiCode);
  1044. GotoXY(x,y);
  1045. end;
  1046. 'J' : if AnsiPara(AnsiCode)=2 then
  1047. ClrScr;
  1048. 'K' : ClrEol;
  1049. 'A' : GotoXY(CurrX,Max(CurrY-AnsiPara(AnsiCode),WinMinY));
  1050. 'B' : GotoXY(CurrX,Min(CurrY+AnsiPara(AnsiCode),WinMaxY));
  1051. 'C' : GotoXY(Min(CurrX+AnsiPara(AnsiCode),WinMaxX),CurrY);
  1052. 'D' : GotoXY(Max(CurrX-AnsiPara(AnsiCode),WinMinX),CurrY);
  1053. 'h' : ; {Stupid Thedraw [?7h Code}
  1054. else
  1055. found:=false;
  1056. end;
  1057. end
  1058. else
  1059. begin
  1060. LastAnsi:=true;
  1061. found:=true;
  1062. end;
  1063. {Clear AnsiCode?}
  1064. if not LastAnsi then
  1065. AnsiCode:='';
  1066. {Increase Idx or SendBytes}
  1067. if found then
  1068. i:=j-1
  1069. else
  1070. inc(SendBytes);
  1071. end
  1072. else
  1073. begin
  1074. LastAnsi:=false;
  1075. case s[i] of
  1076. #13 : begin {CR}
  1077. SendText;
  1078. ttyGotoXY(WinMinX,CurrY);
  1079. end;
  1080. #10 : begin {NL}
  1081. SendText;
  1082. DoLn;
  1083. end;
  1084. #9 : begin {Tab}
  1085. SendText;
  1086. ttyWrite(Space(9-((CurrX-1) and $08)));
  1087. end;
  1088. #8 : begin {BackSpace}
  1089. SendText;
  1090. ttyWrite(#8);
  1091. end;
  1092. else
  1093. inc(SendBytes);
  1094. end;
  1095. end;
  1096. inc(i);
  1097. end;
  1098. if SendBytes>0 then
  1099. SendText;
  1100. ttySetFlush(oldFLush);
  1101. end;
  1102. Function CrtWrite(Var F: TextRec): Integer;
  1103. {
  1104. Top level write function for CRT
  1105. }
  1106. Var
  1107. Temp : String;
  1108. idx,i : Longint;
  1109. oldflush : boolean;
  1110. Begin
  1111. oldflush:=ttySetFlush(Flushing);
  1112. idx:=0;
  1113. while (F.BufPos>0) do
  1114. begin
  1115. i:=F.BufPos;
  1116. if i>255 then
  1117. i:=255;
  1118. Move(F.BufPTR^[idx],Temp[1],i);
  1119. SetLength(Temp,i);
  1120. DoWrite(Temp);
  1121. dec(F.BufPos,i);
  1122. inc(idx,i);
  1123. end;
  1124. ttySetFlush(oldFLush);
  1125. CrtWrite:=0;
  1126. End;
  1127. Function CrtRead(Var F: TextRec): Integer;
  1128. {
  1129. Read from CRT associated file.
  1130. }
  1131. var
  1132. c : char;
  1133. i : longint;
  1134. Begin
  1135. if isATTY(F.Handle)<>-1 then
  1136. begin
  1137. F.BufPos := 0;
  1138. i := 0;
  1139. repeat
  1140. c := readkey;
  1141. case c of
  1142. { ignore special keys }
  1143. #0:
  1144. c:= readkey;
  1145. { Backspace }
  1146. #8:
  1147. if i > 0 then
  1148. begin
  1149. if not(OutputRedir or InputRedir) then
  1150. write(#8#32#8);
  1151. dec(i);
  1152. end;
  1153. { Unhandled extended key }
  1154. #27:;
  1155. { CR }
  1156. #13:
  1157. begin
  1158. F.BufPtr^[i] := #10;
  1159. if not(OutputRedir or InputRedir) then
  1160. write(#10);
  1161. inc(i);
  1162. end;
  1163. else
  1164. begin
  1165. if not(OutputRedir or InputRedir) then
  1166. write(c);
  1167. F.BufPtr^[i] := c;
  1168. inc(i);
  1169. end;
  1170. end;
  1171. until (c in [#10,#13]) or (i >= F.BufSize);
  1172. F.BufEnd := i;
  1173. CrtRead := 0;
  1174. exit;
  1175. end;
  1176. F.BufEnd:=fpRead(F.Handle, F.BufPtr^, F.BufSize);
  1177. { fix #13 only's -> #10 to overcome terminal setting }
  1178. for i:=1to F.BufEnd do
  1179. begin
  1180. if (F.BufPtr^[i-1]=#13) and (F.BufPtr^[i]<>#10) then
  1181. F.BufPtr^[i-1]:=#10;
  1182. end;
  1183. F.BufPos:=F.BufEnd;
  1184. if not(OutputRedir or InputRedir) then
  1185. CrtWrite(F)
  1186. else F.BufPos := 0;
  1187. CrtRead:=0;
  1188. End;
  1189. Function CrtReturn(Var F:TextRec):Integer;
  1190. Begin
  1191. CrtReturn:=0;
  1192. end;
  1193. Function CrtClose(Var F: TextRec): Integer;
  1194. {
  1195. Close CRT associated file.
  1196. }
  1197. Begin
  1198. F.Mode:=fmClosed;
  1199. CrtClose:=0;
  1200. End;
  1201. Function CrtOpen(Var F: TextRec): Integer;
  1202. {
  1203. Open CRT associated file.
  1204. }
  1205. Begin
  1206. If F.Mode=fmOutput Then
  1207. begin
  1208. TextRec(F).InOutFunc:=@CrtWrite;
  1209. TextRec(F).FlushFunc:=@CrtWrite;
  1210. end
  1211. Else
  1212. begin
  1213. F.Mode:=fmInput;
  1214. TextRec(F).InOutFunc:=@CrtRead;
  1215. TextRec(F).FlushFunc:=@CrtReturn;
  1216. end;
  1217. TextRec(F).CloseFunc:=@CrtClose;
  1218. CrtOpen:=0;
  1219. End;
  1220. procedure AssignCrt(var F: Text);
  1221. {
  1222. Assign a file to the console. All output on file goes to console instead.
  1223. }
  1224. begin
  1225. Assign(F,'');
  1226. TextRec(F).OpenFunc:=@CrtOpen;
  1227. end;
  1228. {******************************************************************************
  1229. High Level Functions
  1230. ******************************************************************************}
  1231. Procedure DelLine;
  1232. {
  1233. Delete current line. Scroll subsequent lines up
  1234. }
  1235. Begin
  1236. ScrollScrnRegionUp(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1237. End;
  1238. Procedure InsLine;
  1239. {
  1240. Insert line at current cursor position. Scroll subsequent lines down.
  1241. }
  1242. Begin
  1243. ScrollScrnRegionDown(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1244. End;
  1245. const
  1246. KIOCSOUND = $4B2F; // start sound generation (0 for off)
  1247. Procedure Sound(Hz: Word);
  1248. begin
  1249. if not OutputRedir then
  1250. fpIoctl(TextRec(Output).Handle, KIOCSOUND, Pointer(1193180 div Hz));
  1251. end;
  1252. Procedure NoSound;
  1253. begin
  1254. if not OutputRedir then
  1255. fpIoctl(TextRec(Output).Handle, KIOCSOUND, nil);
  1256. end;
  1257. Procedure TextMode(Mode: Integer);
  1258. {
  1259. Only Clears Screen under linux}
  1260. begin
  1261. ClrScr;
  1262. end;
  1263. {******************************************************************************
  1264. Extra
  1265. ******************************************************************************}
  1266. procedure CursorBig;
  1267. begin
  1268. ttySendStr(#27'[?17;0;64c');
  1269. end;
  1270. procedure CursorOn;
  1271. begin
  1272. ttySendStr(#27'[?2c');
  1273. end;
  1274. procedure CursorOff;
  1275. begin
  1276. ttySendStr(#27'[?1c');
  1277. end;
  1278. {******************************************************************************
  1279. Initialization
  1280. ******************************************************************************}
  1281. var
  1282. OldIO : termio.TermIos;
  1283. inputRaw, outputRaw: boolean;
  1284. procedure saveRawSettings(const tio: termio.termios);
  1285. Begin
  1286. with tio do
  1287. begin
  1288. inputRaw :=
  1289. ((c_iflag and (IGNBRK or BRKINT or PARMRK or ISTRIP or
  1290. INLCR or IGNCR or ICRNL or IXON)) = 0) and
  1291. ((c_lflag and (ECHO or ECHONL or ICANON or ISIG or IEXTEN)) = 0);
  1292. outPutRaw :=
  1293. ((c_oflag and OPOST) = 0) and
  1294. ((c_cflag and (CSIZE or PARENB)) = 0) and
  1295. ((c_cflag and CS8) <> 0);
  1296. end;
  1297. end;
  1298. procedure restoreRawSettings(tio: termio.termios);
  1299. begin
  1300. with tio do
  1301. begin
  1302. if inputRaw then
  1303. begin
  1304. c_iflag := c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
  1305. INLCR or IGNCR or ICRNL or IXON));
  1306. c_lflag := c_lflag and
  1307. (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
  1308. end;
  1309. if outPutRaw then
  1310. begin
  1311. c_oflag := c_oflag and not(OPOST);
  1312. c_cflag := c_cflag and not(CSIZE or PARENB) or CS8;
  1313. end;
  1314. end;
  1315. end;
  1316. Procedure SetRawMode(b:boolean);
  1317. Var
  1318. Tio : Termios;
  1319. Begin
  1320. if b then
  1321. begin
  1322. TCGetAttr(1,Tio);
  1323. SaveRawSettings(Tio);
  1324. OldIO:=Tio;
  1325. CFMakeRaw(Tio);
  1326. end
  1327. else
  1328. begin
  1329. RestoreRawSettings(OldIO);
  1330. Tio:=OldIO;
  1331. end;
  1332. TCSetAttr(1,TCSANOW,Tio);
  1333. End;
  1334. procedure GetXY(var x,y:byte);
  1335. var
  1336. fds : tfdSet;
  1337. i,j,
  1338. readed : longint;
  1339. buf : array[0..255] of char;
  1340. s : string[16];
  1341. begin
  1342. x:=0;
  1343. y:=0;
  1344. s:=#27'[6n';
  1345. fpWrite(0,s[1],length(s));
  1346. fpFD_ZERO(fds);
  1347. fpFD_SET(1,fds);
  1348. if (fpSelect(2,@fds,nil,nil,1000)>0) then
  1349. begin
  1350. readed:=fpRead(1,buf,sizeof(buf));
  1351. i:=0;
  1352. while (i+5<readed) and (buf[i]<>#27) and (buf[i+1]<>'[') do
  1353. inc(i);
  1354. if i+5<readed then
  1355. begin
  1356. s:=space(16);
  1357. move(buf[i+2],s[1],16);
  1358. i:=Pos(';',s);
  1359. if i>0 then
  1360. begin
  1361. Val(Copy(s,1,i-1),y);
  1362. j:=Pos('R',s);
  1363. if j=0 then
  1364. j:=length(s);
  1365. Val(Copy(s,i+1,j-(i+1)),x);
  1366. end;
  1367. end;
  1368. end;
  1369. end;
  1370. Procedure GetConsoleBuf;
  1371. var
  1372. WinInfo : TWinSize;
  1373. begin
  1374. if Assigned(ConsoleBuf) then
  1375. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1376. ScreenWidth:=0;
  1377. ScreenHeight:=0;
  1378. if (not OutputRedir) and (fpIOCtl(TextRec(Output).Handle,TIOCGWINSZ,@Wininfo)>=0) then
  1379. begin
  1380. ScreenWidth:=Wininfo.ws_col;
  1381. ScreenHeight:=Wininfo.ws_row;
  1382. end;
  1383. // Set some arbitrary defaults which make some sense...
  1384. If (ScreenWidth=0) then
  1385. ScreenWidth:=80;
  1386. If (ScreenHeight=0) then
  1387. ScreenHeight:=25;
  1388. GetMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1389. FillChar(ConsoleBuf^,ScreenHeight*ScreenWidth*2,0);
  1390. end;
  1391. Initialization
  1392. { Redirect the standard output }
  1393. assigncrt(Output);
  1394. Rewrite(Output);
  1395. TextRec(Output).Handle:=StdOutputHandle;
  1396. assigncrt(Input);
  1397. Reset(Input);
  1398. TextRec(Input).Handle:=StdInputHandle;
  1399. { Are we redirected to a file ? }
  1400. OutputRedir:= IsAtty(TextRec(Output).Handle)=-1;
  1401. { does the input come from another console or from a file? }
  1402. InputRedir :=
  1403. (IsAtty(TextRec(Input).Handle)=-1) or
  1404. (not OutputRedir and
  1405. (TTYName(TextRec(Input).Handle) <> TTYName(TextRec(Output).Handle)));
  1406. { Get Size of terminal and set WindMax to the window }
  1407. GetConsoleBuf;
  1408. WinMinX:=1;
  1409. WinMinY:=1;
  1410. WinMaxX:=ScreenWidth;
  1411. WinMaxY:=ScreenHeight;
  1412. WindMax:=((ScreenHeight-1) Shl 8)+(ScreenWidth-1);
  1413. {Get Current X&Y or Reset to Home}
  1414. if OutputRedir then
  1415. begin
  1416. CurrX:=1;
  1417. CurrY:=1;
  1418. end
  1419. else
  1420. begin
  1421. { Set default Terminal Settings }
  1422. SetRawMode(True);
  1423. { Get current X,Y if not set already }
  1424. GetXY(CurrX,CurrY);
  1425. if (CurrX=0) then
  1426. begin
  1427. CurrX:=1;
  1428. CurrY:=1;
  1429. ttySendStr(#27'[H');
  1430. end;
  1431. {Reset Attribute (TextAttr=7 at startup)}
  1432. ttySendStr(#27'[m');
  1433. end;
  1434. Finalization
  1435. ttyFlushOutput;
  1436. if not OutputRedir then
  1437. SetRawMode(False);
  1438. { remove console buf }
  1439. if Assigned(ConsoleBuf) then
  1440. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1441. End.
  1442. {
  1443. $Log$
  1444. Revision 1.23 2005-03-15 09:20:11 jonas
  1445. * endianess fixes from mischi
  1446. Revision 1.22 2005/02/14 17:13:31 peter
  1447. * truncate log
  1448. }