crt.pp 33 KB

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