crt.pp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  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. Redir : boolean; { is the output 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:=Attr and $f;
  215. OBg:=Attr 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 Redir 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<>TextAttr then
  404. begin
  405. if not Redir then
  406. ttySendStr(Attr2Ansi(a,TextAttr));
  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 Redir) 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. Begin
  534. ttyColor((Color and $8f) or (TextAttr and $70));
  535. End;
  536. Procedure TextBackground(Color: Byte);
  537. {
  538. Switch backgroundcolor
  539. }
  540. Begin
  541. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  542. End;
  543. Procedure HighVideo;
  544. {
  545. Set highlighted output.
  546. }
  547. Begin
  548. TextColor(TextAttr Or $08);
  549. End;
  550. Procedure LowVideo;
  551. {
  552. Set normal output
  553. }
  554. Begin
  555. TextColor(TextAttr And $77);
  556. End;
  557. Procedure NormVideo;
  558. {
  559. Set normal back and foregroundcolors.
  560. }
  561. Begin
  562. TextColor(7);
  563. TextBackGround(0);
  564. End;
  565. Procedure GotoXy(X: Byte; Y: Byte);
  566. {
  567. Go to coordinates X,Y in the current window.
  568. }
  569. Begin
  570. If (X>0) and (X<=WinMaxX- WinMinX+1) and
  571. (Y>0) and (Y<=WinMaxY-WinMinY+1) Then
  572. Begin
  573. Inc(X,WinMinX-1);
  574. Inc(Y,WinMinY-1);
  575. ttyGotoXY(x,y);
  576. End;
  577. End;
  578. Procedure Window(X1, Y1, X2, Y2: Byte);
  579. {
  580. Set screen window to the specified coordinates.
  581. }
  582. Begin
  583. if (X1>X2) or (X2>ScreenWidth) or
  584. (Y1>Y2) or (Y2>ScreenHeight) then
  585. exit;
  586. WindMin:=((Y1-1) Shl 8)+(X1-1);
  587. WindMax:=((Y2-1) Shl 8)+(X2-1);
  588. GoToXY(1,1);
  589. End;
  590. Procedure ClrScr;
  591. {
  592. Clear the current window, and set the cursor on x1,y1
  593. }
  594. Var
  595. CY,i : Longint;
  596. oldflush : boolean;
  597. Begin
  598. { See if color has changed }
  599. if OldTextAttr<>TextAttr then
  600. begin
  601. i:=TextAttr;
  602. TextAttr:=OldTextAttr;
  603. ttyColor(i);
  604. end;
  605. oldflush:=ttySetFlush(Flushing);
  606. if FullWin then
  607. begin
  608. if not Redir then
  609. ttySendStr(#27'[H'#27'[2J');
  610. CurrX:=1;
  611. CurrY:=1;
  612. FillWord(ConsoleBuf^,ScreenWidth*ScreenHeight,(TextAttr shl 8)+ord(' '));
  613. end
  614. else
  615. begin
  616. For Cy:=WinMinY To WinMaxY Do
  617. DoEmptyLine(Cy,WinMinX,WinMaxX);
  618. GoToXY(1,1);
  619. end;
  620. ttySetFlush(oldflush);
  621. End;
  622. Procedure ClrEol;
  623. {
  624. Clear from current position to end of line.
  625. }
  626. var
  627. len,i : longint;
  628. IsLastLine : boolean;
  629. Begin
  630. { See if color has changed }
  631. if OldTextAttr<>TextAttr then
  632. begin
  633. i:=TextAttr;
  634. TextAttr:=OldTextAttr;
  635. ttyColor(i);
  636. end;
  637. if FullWin or (WinMaxX = ScreenWidth) then
  638. begin
  639. if not Redir then
  640. ttySendStr(#27'[K');
  641. end
  642. else
  643. begin
  644. { Tweak windmax so no scrolling happends }
  645. len:=WinMaxX-CurrX+1;
  646. IsLastLine:=false;
  647. if CurrY=WinMaxY then
  648. begin
  649. inc(WindMax,$0203);
  650. IsLastLine:=true;
  651. end;
  652. ttySendStr(Space(len));
  653. if IsLastLine then
  654. dec(WindMax,$0203);
  655. ttyGotoXY(0,0);
  656. end;
  657. End;
  658. Function WhereX: Byte;
  659. {
  660. Return current X-position of cursor.
  661. }
  662. Begin
  663. WhereX:=CurrX-WinMinX+1;
  664. End;
  665. Function WhereY: Byte;
  666. {
  667. Return current Y-position of cursor.
  668. }
  669. Begin
  670. WhereY:=CurrY-WinMinY+1;
  671. End;
  672. Procedure ScrollScrnRegionUp(xl,yl,xh,yh, count: longint);
  673. {
  674. Scroll the indicated region count lines up. The empty lines are filled
  675. with blanks in the current color. The screen position is restored
  676. afterwards.
  677. }
  678. Var
  679. y,oldx,oldy : byte;
  680. oldflush : boolean;
  681. Begin
  682. oldflush:=ttySetFlush(Flushing);
  683. oldx:=CurrX;
  684. oldy:=CurrY;
  685. {Scroll}
  686. For y:=yl to yh-count do
  687. DoScrollLine(y+count,y,xl,xh);
  688. {Restore TextAttr}
  689. ttySendStr(Attr2Ansi(TextAttr,$ff));
  690. {Fill the rest with empty lines}
  691. for y:=yh-count+1 to yh do
  692. DoEmptyLine(y,xl,xh);
  693. {Restore current position}
  694. ttyGotoXY(OldX,OldY);
  695. ttySetFlush(oldflush);
  696. End;
  697. Procedure ScrollScrnRegionDown(xl,yl,xh,yh, count: longint);
  698. {
  699. Scroll the indicated region count lines down. The empty lines are filled
  700. with blanks in the current color. The screen position is restored
  701. afterwards.
  702. }
  703. Var
  704. y,oldx,oldy : byte;
  705. oldflush : boolean;
  706. Begin
  707. oldflush:=ttySetFlush(Flushing);
  708. oldx:=CurrX;
  709. oldy:=CurrY;
  710. {Scroll}
  711. for y:=yh downto yl+count do
  712. DoScrollLine(y-count,y,xl,xh);
  713. {Restore TextAttr}
  714. ttySendStr(Attr2Ansi(TextAttr,$ff));
  715. {Fill the rest with empty lines}
  716. for y:=yl to yl+count-1 do
  717. DoEmptyLine(y,xl,xh);
  718. {Restore current position}
  719. ttyGotoXY(OldX,OldY);
  720. ttySetFlush(oldflush);
  721. End;
  722. {*************************************************************************
  723. KeyBoard
  724. *************************************************************************}
  725. Const
  726. KeyBufferSize = 20;
  727. var
  728. KeyBuffer : Array[0..KeyBufferSize-1] of Char;
  729. KeyPut,
  730. KeySend : longint;
  731. Procedure PushKey(Ch:char);
  732. Var
  733. Tmp : Longint;
  734. Begin
  735. Tmp:=KeyPut;
  736. Inc(KeyPut);
  737. If KeyPut>=KeyBufferSize Then
  738. KeyPut:=0;
  739. If KeyPut<>KeySend Then
  740. KeyBuffer[Tmp]:=Ch
  741. Else
  742. KeyPut:=Tmp;
  743. End;
  744. Function PopKey:char;
  745. Begin
  746. If KeyPut<>KeySend Then
  747. Begin
  748. PopKey:=KeyBuffer[KeySend];
  749. Inc(KeySend);
  750. If KeySend>=KeyBufferSize Then
  751. KeySend:=0;
  752. End
  753. Else
  754. PopKey:=#0;
  755. End;
  756. Procedure PushExt(b:byte);
  757. begin
  758. PushKey(#0);
  759. PushKey(chr(b));
  760. end;
  761. const
  762. AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-=';
  763. AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+
  764. #044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131;
  765. Function FAltKey(ch:char):byte;
  766. var
  767. Idx : longint;
  768. Begin
  769. Idx:=Pos(ch,AltKeyStr);
  770. if Idx>0 then
  771. FAltKey:=byte(AltCodeStr[Idx])
  772. else
  773. FAltKey:=0;
  774. End;
  775. Function KeyPressed:Boolean;
  776. var
  777. fdsin : fdSet;
  778. Begin
  779. if (KeySend<>KeyPut) or (InCnt>0) then
  780. KeyPressed:=true
  781. else
  782. begin
  783. FD_Zero(fdsin);
  784. fd_Set(TTYin,fdsin);
  785. Keypressed:=(Select(TTYIn+1,@fdsin,nil,nil,0)>0);
  786. end;
  787. End;
  788. Function ReadKey:char;
  789. Var
  790. ch : char;
  791. OldState,
  792. State : longint;
  793. FDS : FDSet;
  794. Begin
  795. {Check Buffer first}
  796. if KeySend<>KeyPut then
  797. begin
  798. ReadKey:=PopKey;
  799. exit;
  800. end;
  801. {Wait for Key}
  802. FD_Zero (FDS);
  803. FD_Set (0,FDS);
  804. Select (1,@FDS,nil,nil,nil);
  805. ch:=ttyRecvChar;
  806. {Esc Found ?}
  807. CASE ch OF
  808. #27: begin
  809. State:=1;
  810. Delay(10);
  811. while (State<>0) and (KeyPressed) do
  812. begin
  813. ch:=ttyRecvChar;
  814. OldState:=State;
  815. State:=0;
  816. case OldState of
  817. 1 : begin {Esc}
  818. case ch of
  819. 'a'..'z',
  820. '0'..'9',
  821. '-','=' : PushExt(FAltKey(ch));
  822. #10 : PushKey(#10);
  823. '[' : State:=2;
  824. else
  825. begin
  826. PushKey(ch);
  827. PushKey(#27);
  828. end;
  829. end;
  830. end;
  831. 2 : begin {Esc[}
  832. case ch of
  833. '[' : State:=3;
  834. 'A' : PushExt(72);
  835. 'B' : PushExt(80);
  836. 'C' : PushExt(77);
  837. 'D' : PushExt(75);
  838. {$IFDEF FREEBSD}
  839. {'E' - Center key, not handled in DOS TP7}
  840. 'F' : PushExt(79); {End}
  841. 'G': PushExt(81); {PageDown}
  842. {$ELSE}
  843. 'G' : PushKey('5'); {Center key, Linux}
  844. {$ENDIF}
  845. 'H' : PushExt(71);
  846. {$IFDEF FREEBSD}
  847. 'I' : PushExt(73); {PageUp}
  848. {$ENDIF}
  849. 'K' : PushExt(79);
  850. {$IFDEF FREEBSD}
  851. 'L' : StoExt(82); {Insert - Deekoo}
  852. 'M' : StoExt(59); {F1-F10 - Deekoo}
  853. 'N' : StoExt(60); {F2}
  854. 'O' : StoExt(61); {F3}
  855. 'P' : StoExt(62); {F4}
  856. 'Q' : StoExt(63); {F5}
  857. 'R' : StoExt(64); {F6}
  858. 'S' : StoExt(65); {F7}
  859. 'T' : StoExt(66); {F8}
  860. 'U' : StoExt(67); {F9}
  861. 'V' : StoExt(68); {F10}
  862. {Not sure if TP/BP handles F11 and F12 like this normally;
  863. In pcemu, a TP7 executable handles 'em this way, though.}
  864. 'W' : StoExt(133); {F11}
  865. 'X' : StoExt(134); {F12}
  866. 'Y' : StoExt(84); {Shift-F1}
  867. 'Z' : StoExt(85); {Shift-F2}
  868. 'a' : StoExt(86); {Shift-F3}
  869. 'b' : StoExt(87); {Shift-F4}
  870. 'c' : StoExt(88); {Shift-F5}
  871. 'd' : StoExt(89); {Shift-F6}
  872. 'e' : StoExt(90); {Shift-F7}
  873. 'f' : StoExt(91); {Shift-F8}
  874. 'g' : StoExt(92); {Shift-F9}
  875. 'h' : StoExt(93); {Shift-F10}
  876. 'i' : StoExt(135); {Shift-F11}
  877. 'j' : StoExt(136); {Shift-F12}
  878. 'k' : StoExt(94); {Ctrl-F1}
  879. 'l' : StoExt(95);
  880. 'm' : StoExt(96);
  881. 'n' : StoExt(97);
  882. 'o' : StoExt(98);
  883. 'p' : StoExt(99);
  884. 'q' : StoExt(100);
  885. 'r' : StoExt(101);
  886. 's' : StoExt(102);
  887. 't' : StoExt(103); {Ctrl-F10}
  888. 'u' : StoExt(137); {Ctrl-F11}
  889. 'v' : StoExt(138); {Ctrl-F12}
  890. {$ENDIF}
  891. '1' : State:=4;
  892. '2' : State:=5;
  893. '3' : State:=6;
  894. '4' : PushExt(79);
  895. '5' : PushExt(73);
  896. '6' : PushExt(81);
  897. else
  898. begin
  899. PushKey(ch);
  900. PushKey('[');
  901. PushKey(#27);
  902. end;
  903. end;
  904. if ch in ['4'..'6'] then
  905. State:=255;
  906. end;
  907. 3 : begin {Esc[[}
  908. case ch of
  909. 'A' : PushExt(59);
  910. 'B' : PushExt(60);
  911. 'C' : PushExt(61);
  912. 'D' : PushExt(62);
  913. 'E' : PushExt(63);
  914. end;
  915. end;
  916. 4 : begin {Esc[1}
  917. case ch of
  918. '~' : PushExt(71);
  919. '7' : PushExt(64);
  920. '8' : PushExt(65);
  921. '9' : PushExt(66);
  922. end;
  923. if (Ch<>'~') then
  924. State:=255;
  925. end;
  926. 5 : begin {Esc[2}
  927. case ch of
  928. '~' : PushExt(82);
  929. '0' : pushExt(67);
  930. '1' : PushExt(68);
  931. '3' : PushExt(133); {F11}
  932. {Esc[23~ is also shift-F1,shift-F11}
  933. '4' : PushExt(134); {F12}
  934. {Esc[24~ is also shift-F2,shift-F12}
  935. '5' : PushExt(86); {Shift-F3}
  936. '6' : PushExt(87); {Shift-F4}
  937. '8' : PushExt(88); {Shift-F5}
  938. '9' : PushExt(89); {Shift-F6}
  939. end;
  940. if (Ch<>'~') then
  941. State:=255;
  942. end;
  943. 6 : begin {Esc[3}
  944. case ch of
  945. '~' : PushExt(83); {Del}
  946. '1' : PushExt(90); {Shift-F7}
  947. '2' : PushExt(91); {Shift-F8}
  948. '3' : PushExt(92); {Shift-F9}
  949. '4' : PushExt(93); {Shift-F10}
  950. end;
  951. if (Ch<>'~') then
  952. State:=255;
  953. end;
  954. 255 : ;
  955. end;
  956. if State<>0 then
  957. Delay(10);
  958. end;
  959. if State=1 then
  960. PushKey(ch);
  961. end;
  962. #127: PushKey(#8);
  963. else PushKey(ch);
  964. End;
  965. ReadKey:=PopKey;
  966. End;
  967. Procedure Delay(DTime: Word);
  968. {
  969. Wait for DTime milliseconds.
  970. }
  971. Begin
  972. Select(0,nil,nil,nil,DTime);
  973. End;
  974. {****************************************************************************
  975. Write(ln)/Read(ln) support
  976. ****************************************************************************}
  977. procedure DoLn;
  978. begin
  979. if CurrY=WinMaxY then
  980. begin
  981. if FullWin then
  982. begin
  983. ttySendStr(#10#13);
  984. CurrX:=WinMinX;
  985. CurrY:=WinMaxY;
  986. end
  987. else
  988. begin
  989. ScrollScrnRegionUp(WinMinX,WinMinY,WinMaxX,WinMaxY,1);
  990. ttyGotoXY(WinMinX,WinMaxY);
  991. end;
  992. end
  993. else
  994. ttyGotoXY(WinMinX,CurrY+1);
  995. end;
  996. var
  997. Lastansi : boolean;
  998. AnsiCode : string;
  999. Procedure DoWrite(const s:String);
  1000. {
  1001. Write string to screen, parse most common AnsiCodes
  1002. }
  1003. var
  1004. found,
  1005. OldFlush : boolean;
  1006. x,y,
  1007. i,j,
  1008. SendBytes : longint;
  1009. function AnsiPara(var hstr:string):byte;
  1010. var
  1011. k,j : longint;
  1012. code : word;
  1013. begin
  1014. j:=pos(';',hstr);
  1015. if j=0 then
  1016. j:=length(hstr);
  1017. val(copy(hstr,3,j-3),k,code);
  1018. Delete(hstr,3,j-2);
  1019. if k=0 then
  1020. k:=1;
  1021. AnsiPara:=k;
  1022. end;
  1023. procedure SendText;
  1024. var
  1025. LeftX : longint;
  1026. begin
  1027. while (SendBytes>0) do
  1028. begin
  1029. LeftX:=WinMaxX-CurrX+1;
  1030. if (SendBytes>LeftX) or (CurrX+SendBytes=81) then
  1031. begin
  1032. ttyWrite(Copy(s,i-SendBytes,LeftX));
  1033. dec(SendBytes,LeftX);
  1034. DoLn;
  1035. end
  1036. else
  1037. begin
  1038. ttyWrite(Copy(s,i-SendBytes,SendBytes));
  1039. SendBytes:=0;
  1040. end;
  1041. end;
  1042. end;
  1043. begin
  1044. oldflush:=ttySetFlush(Flushing);
  1045. { Support textattr:= changing }
  1046. if OldTextAttr<>TextAttr then
  1047. begin
  1048. i:=TextAttr;
  1049. TextAttr:=OldTextAttr;
  1050. ttyColor(i);
  1051. end;
  1052. { write the stuff }
  1053. SendBytes:=0;
  1054. i:=1;
  1055. while (i<=length(s)) do
  1056. begin
  1057. if (s[i]=#27) or (LastAnsi) then
  1058. begin
  1059. SendText;
  1060. LastAnsi:=false;
  1061. j:=i;
  1062. found:=false;
  1063. while (j<=length(s)) and (not found) do
  1064. begin
  1065. found:=not (s[j] in [#27,'[','0'..'9',';','?']);
  1066. inc(j);
  1067. end;
  1068. Ansicode:=AnsiCode+Copy(s,i,j-i);
  1069. if found then
  1070. begin
  1071. case AnsiCode[length(AnsiCode)] of
  1072. 'm' : ttyColor(Ansi2Attr(AnsiCode,TextAttr));
  1073. 'H' : begin {No other way :( Coz First Para=Y}
  1074. y:=AnsiPara(AnsiCode);
  1075. x:=AnsiPara(AnsiCode);
  1076. GotoXY(y,x);
  1077. end;
  1078. 'J' : if AnsiPara(AnsiCode)=2 then
  1079. ClrScr;
  1080. 'K' : ClrEol;
  1081. 'A' : GotoXY(CurrX,Max(CurrY-AnsiPara(AnsiCode),WinMinY));
  1082. 'B' : GotoXY(CurrX,Min(CurrY+AnsiPara(AnsiCode),WinMaxY));
  1083. 'C' : GotoXY(Min(CurrX+AnsiPara(AnsiCode),WinMaxX),CurrY);
  1084. 'D' : GotoXY(Max(CurrX-AnsiPara(AnsiCode),WinMinX),CurrY);
  1085. 'h' : ; {Stupid Thedraw [?7h Code}
  1086. else
  1087. found:=false;
  1088. end;
  1089. end
  1090. else
  1091. begin
  1092. LastAnsi:=true;
  1093. found:=true;
  1094. end;
  1095. {Clear AnsiCode?}
  1096. if not LastAnsi then
  1097. AnsiCode:='';
  1098. {Increase Idx or SendBytes}
  1099. if found then
  1100. i:=j-1
  1101. else
  1102. inc(SendBytes);
  1103. end
  1104. else
  1105. begin
  1106. LastAnsi:=false;
  1107. case s[i] of
  1108. #13 : begin {CR}
  1109. SendText;
  1110. ttyGotoXY(WinMinX,CurrY);
  1111. end;
  1112. #10 : begin {NL}
  1113. SendText;
  1114. DoLn;
  1115. end;
  1116. #9 : begin {Tab}
  1117. SendText;
  1118. ttyWrite(Space(9-((CurrX-1) and $08)));
  1119. end;
  1120. #8 : begin {BackSpace}
  1121. SendText;
  1122. ttyWrite(#8);
  1123. end;
  1124. else
  1125. inc(SendBytes);
  1126. end;
  1127. end;
  1128. inc(i);
  1129. end;
  1130. if SendBytes>0 then
  1131. SendText;
  1132. ttySetFlush(oldFLush);
  1133. end;
  1134. Function CrtWrite(Var F: TextRec): Integer;
  1135. {
  1136. Top level write function for CRT
  1137. }
  1138. Var
  1139. Temp : String;
  1140. idx,i : Longint;
  1141. oldflush : boolean;
  1142. Begin
  1143. oldflush:=ttySetFlush(Flushing);
  1144. idx:=0;
  1145. while (F.BufPos>0) do
  1146. begin
  1147. i:=F.BufPos;
  1148. if i>255 then
  1149. i:=255;
  1150. Move(F.BufPTR^[idx],Temp[1],F.BufPos);
  1151. Temp[0]:=Chr(i);
  1152. DoWrite(Temp);
  1153. dec(F.BufPos,i);
  1154. inc(idx,i);
  1155. end;
  1156. ttySetFlush(oldFLush);
  1157. CrtWrite:=0;
  1158. End;
  1159. Function CrtRead(Var F: TextRec): Integer;
  1160. {
  1161. Read from CRT associated file.
  1162. }
  1163. var
  1164. i : longint;
  1165. Begin
  1166. F.BufEnd:=fdRead(F.Handle, F.BufPtr^, F.BufSize);
  1167. { fix #13 only's -> #10 to overcome terminal setting }
  1168. for i:=1to F.BufEnd do
  1169. begin
  1170. if (F.BufPtr^[i-1]=#13) and (F.BufPtr^[i]<>#10) then
  1171. F.BufPtr^[i-1]:=#10;
  1172. end;
  1173. F.BufPos:=F.BufEnd;
  1174. CrtWrite(F);
  1175. CrtRead:=0;
  1176. End;
  1177. Function CrtReturn(Var F:TextRec):Integer;
  1178. Begin
  1179. CrtReturn:=0;
  1180. end;
  1181. Function CrtClose(Var F: TextRec): Integer;
  1182. {
  1183. Close CRT associated file.
  1184. }
  1185. Begin
  1186. F.Mode:=fmClosed;
  1187. CrtClose:=0;
  1188. End;
  1189. Function CrtOpen(Var F: TextRec): Integer;
  1190. {
  1191. Open CRT associated file.
  1192. }
  1193. Begin
  1194. If F.Mode=fmOutput Then
  1195. begin
  1196. TextRec(F).InOutFunc:=@CrtWrite;
  1197. TextRec(F).FlushFunc:=@CrtWrite;
  1198. end
  1199. Else
  1200. begin
  1201. F.Mode:=fmInput;
  1202. TextRec(F).InOutFunc:=@CrtRead;
  1203. TextRec(F).FlushFunc:=@CrtReturn;
  1204. end;
  1205. TextRec(F).CloseFunc:=@CrtClose;
  1206. CrtOpen:=0;
  1207. End;
  1208. procedure AssignCrt(var F: Text);
  1209. {
  1210. Assign a file to the console. All output on file goes to console instead.
  1211. }
  1212. begin
  1213. Assign(F,'');
  1214. TextRec(F).OpenFunc:=@CrtOpen;
  1215. end;
  1216. {******************************************************************************
  1217. High Level Functions
  1218. ******************************************************************************}
  1219. Procedure DelLine;
  1220. {
  1221. Delete current line. Scroll subsequent lines up
  1222. }
  1223. Begin
  1224. ScrollScrnRegionUp(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1225. End;
  1226. Procedure InsLine;
  1227. {
  1228. Insert line at current cursor position. Scroll subsequent lines down.
  1229. }
  1230. Begin
  1231. ScrollScrnRegionDown(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1232. End;
  1233. Procedure Sound(Hz: Word);
  1234. {
  1235. Does nothing under linux
  1236. }
  1237. begin
  1238. end;
  1239. Procedure NoSound;
  1240. {
  1241. Does nothing under linux
  1242. }
  1243. begin
  1244. end;
  1245. Procedure TextMode(Mode: Integer);
  1246. {
  1247. Only Clears Screen under linux
  1248. }
  1249. begin
  1250. ClrScr;
  1251. end;
  1252. {******************************************************************************
  1253. Extra
  1254. ******************************************************************************}
  1255. procedure CursorBig;
  1256. begin
  1257. ttySendStr(#27'[?17;0;64c');
  1258. end;
  1259. procedure CursorOn;
  1260. begin
  1261. ttySendStr(#27'[?2c');
  1262. end;
  1263. procedure CursorOff;
  1264. begin
  1265. ttySendStr(#27'[?1c');
  1266. end;
  1267. {******************************************************************************
  1268. Initialization
  1269. ******************************************************************************}
  1270. var
  1271. OldIO : TermIos;
  1272. Procedure SetRawMode(b:boolean);
  1273. Var
  1274. Tio : Termios;
  1275. Begin
  1276. if b then
  1277. begin
  1278. TCGetAttr(1,Tio);
  1279. OldIO:=Tio;
  1280. CFMakeRaw(Tio);
  1281. end
  1282. else
  1283. Tio:=OldIO;
  1284. TCSetAttr(1,TCSANOW,Tio);
  1285. End;
  1286. procedure GetXY(var x,y:byte);
  1287. var
  1288. fds : fdSet;
  1289. i,j,
  1290. readed : longint;
  1291. buf : array[0..255] of char;
  1292. s : string[16];
  1293. begin
  1294. x:=0;
  1295. y:=0;
  1296. s:=#27'[6n';
  1297. fdWrite(0,s[1],length(s));
  1298. FD_Zero(fds);
  1299. FD_Set(1,fds);
  1300. if (Select(2,@fds,nil,nil,1000)>0) then
  1301. begin
  1302. readed:=fdRead(1,buf,sizeof(buf));
  1303. i:=0;
  1304. while (i+5<readed) and (buf[i]<>#27) and (buf[i+1]<>'[') do
  1305. inc(i);
  1306. if i+5<readed then
  1307. begin
  1308. s:=space(16);
  1309. move(buf[i+2],s[1],16);
  1310. i:=Pos(';',s);
  1311. if i>0 then
  1312. begin
  1313. Val(Copy(s,1,i-1),y);
  1314. j:=Pos('R',s);
  1315. if j=0 then
  1316. j:=length(s);
  1317. Val(Copy(s,i+1,j-(i+1)),x);
  1318. end;
  1319. end;
  1320. end;
  1321. end;
  1322. Procedure GetConsoleBuf;
  1323. var
  1324. WinInfo : TWinSize;
  1325. begin
  1326. if Assigned(ConsoleBuf) then
  1327. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1328. if (not Redir) and IOCtl(TextRec(Output).Handle,TIOCGWINSZ,@Wininfo) then
  1329. begin
  1330. ScreenWidth:=Wininfo.ws_col;
  1331. ScreenHeight:=Wininfo.ws_row;
  1332. end
  1333. else
  1334. begin
  1335. ScreenWidth:=80;
  1336. ScreenHeight:=25;
  1337. end;
  1338. GetMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1339. FillChar(ConsoleBuf^,ScreenHeight*ScreenWidth*2,0);
  1340. end;
  1341. Procedure CrtExit;
  1342. {
  1343. We need to restore normal keyboard mode upon exit !!
  1344. }
  1345. Begin
  1346. ttyFlushOutput;
  1347. SetRawMode(False);
  1348. { remove console buf }
  1349. if Assigned(ConsoleBuf) then
  1350. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1351. ExitProc:=ExitSave;
  1352. End;
  1353. Begin
  1354. {Hook Exit}
  1355. ExitSave:=ExitProc;
  1356. ExitProc:=@CrtExit;
  1357. { Redirect the standard output }
  1358. assigncrt(Output);
  1359. Rewrite(Output);
  1360. TextRec(Output).Handle:=StdOutputHandle;
  1361. assigncrt(Input);
  1362. Reset(Input);
  1363. TextRec(Input).Handle:=StdInputHandle;
  1364. { Are we redirected to a file ? }
  1365. Redir:=not IsAtty(TextRec(Output).Handle);
  1366. { Get Size of terminal and set WindMax to the window }
  1367. GetConsoleBuf;
  1368. WindMax:=((ScreenHeight-1) Shl 8)+(ScreenWidth-1);
  1369. {Get Current X&Y or Reset to Home}
  1370. if Redir then
  1371. begin
  1372. CurrX:=1;
  1373. CurrY:=1;
  1374. end
  1375. else
  1376. begin
  1377. { Set default Terminal Settings }
  1378. SetRawMode(True);
  1379. { Get current X,Y if not set already }
  1380. GetXY(CurrX,CurrY);
  1381. if (CurrX=0) then
  1382. begin
  1383. CurrX:=1;
  1384. CurrY:=1;
  1385. ttySendStr(#27'[H');
  1386. end;
  1387. {Reset Attribute (TextAttr=7 at startup)}
  1388. ttySendStr(#27'[m');
  1389. end;
  1390. End.
  1391. {
  1392. $Log$
  1393. Revision 1.21 2000-01-07 16:41:39 daniel
  1394. * copyright 2000
  1395. Revision 1.20 2000/01/07 16:32:26 daniel
  1396. * copyright 2000 added
  1397. Revision 1.19 1999/10/22 14:36:20 peter
  1398. * crtreturn also needs f:textrec as parameter
  1399. Revision 1.18 1999/09/07 07:47:46 peter
  1400. * write > 255 chars
  1401. Revision 1.17 1999/09/07 07:38:09 michael
  1402. + Applied readkey patch from Deekoo L
  1403. Revision 1.16 1999/06/09 16:46:10 peter
  1404. * fixed fullwin,textbackground
  1405. Revision 1.15 1999/02/08 10:35:14 peter
  1406. * readkey fixes from the mailinglist
  1407. + cursoron/off/big from the mailinglist
  1408. Revision 1.14 1999/01/15 12:47:16 peter
  1409. * init window size to the size of the console instead of 80,25
  1410. Revision 1.13 1998/11/16 10:21:27 peter
  1411. * fixes for H+
  1412. Revision 1.12 1998/11/10 15:01:01 peter
  1413. * fixed GetXY at startup
  1414. Revision 1.11 1998/10/30 12:11:51 peter
  1415. * fixed fullwi, which did not check for 1,1
  1416. Revision 1.10 1998/10/27 11:13:27 peter
  1417. * fixed ttyWrite() with #8
  1418. Revision 1.9 1998/10/15 08:31:53 peter
  1419. + get winsize at startup
  1420. + ConsoleBuf to interface
  1421. Revision 1.8 1998/08/28 11:00:20 peter
  1422. * fixed #8 writing
  1423. Revision 1.7 1998/07/04 11:17:18 peter
  1424. * fixes for window (from "Heinz Ziegenhorn" <[email protected]>)
  1425. Revision 1.6 1998/06/19 16:51:50 peter
  1426. * added #13 -> #10 translation for CrtRead to overcome readln probs
  1427. Revision 1.5 1998/06/19 14:47:52 michael
  1428. + Enter key maps again to #13
  1429. Revision 1.4 1998/05/06 12:35:26 michael
  1430. + Removed log from before restored version.
  1431. Revision 1.3 1998/04/16 07:49:11 michael
  1432. * fixed bug. Clrscr and Clreol didn't take change in textattr in account.
  1433. Revision 1.2 1998/04/05 13:56:54 peter
  1434. - fixed mouse to compile with $i386_att
  1435. + linux crt supports redirecting (not Esc-codes anymore)
  1436. }