crt.pp 34 KB

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