crt.pp 35 KB

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