crt.pp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705
  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. { This one doesn't care about keypresses already processed by readkey }
  782. { and waiting in the KeyBuffer, only about waiting keypresses at the }
  783. { TTYLevel (including ones that are waiting in the TTYRecvChar buffer) }
  784. function sysKeyPressed: boolean;
  785. var
  786. fdsin : fdSet;
  787. begin
  788. if (InCnt>0) then
  789. sysKeyPressed:=true
  790. else
  791. begin
  792. FD_Zero(fdsin);
  793. fd_Set(TTYin,fdsin);
  794. sysKeypressed:=(Select(TTYIn+1,@fdsin,nil,nil,0)>0);
  795. end;
  796. end;
  797. Function KeyPressed:Boolean;
  798. Begin
  799. Keypressed := (KeySend<>KeyPut) or sysKeyPressed;
  800. End;
  801. Function ReadKey:char;
  802. Var
  803. ch : char;
  804. OldState,
  805. State : longint;
  806. FDS : FDSet;
  807. Begin
  808. {Check Buffer first}
  809. if KeySend<>KeyPut then
  810. begin
  811. ReadKey:=PopKey;
  812. exit;
  813. end;
  814. {Wait for Key}
  815. { Only if none are waiting! (JM) }
  816. if not sysKeyPressed then
  817. begin
  818. FD_Zero (FDS);
  819. FD_Set (0,FDS);
  820. Select (1,@FDS,nil,nil,nil);
  821. end;
  822. ch:=ttyRecvChar;
  823. {Esc Found ?}
  824. CASE ch OF
  825. #27: begin
  826. State:=1;
  827. Delay(10);
  828. { This has to be sysKeyPressed and not "keyPressed", since after }
  829. { one iteration keyPressed will always be true because of the }
  830. { pushKey commands (JM) }
  831. while (State<>0) and (sysKeyPressed) do
  832. begin
  833. ch:=ttyRecvChar;
  834. OldState:=State;
  835. State:=0;
  836. case OldState of
  837. 1 : begin {Esc}
  838. case ch of
  839. 'a'..'z',
  840. '0'..'9',
  841. '-','=' : PushExt(FAltKey(ch));
  842. #10 : PushKey(#10);
  843. '[' : State:=2;
  844. else
  845. begin
  846. PushKey(ch);
  847. PushKey(#27);
  848. end;
  849. end;
  850. end;
  851. 2 : begin {Esc[}
  852. case ch of
  853. '[' : State:=3;
  854. 'A' : PushExt(72);
  855. 'B' : PushExt(80);
  856. 'C' : PushExt(77);
  857. 'D' : PushExt(75);
  858. {$IFDEF FREEBSD}
  859. {'E' - Center key, not handled in DOS TP7}
  860. 'F' : PushExt(79); {End}
  861. 'G': PushExt(81); {PageDown}
  862. {$ELSE}
  863. 'G' : PushKey('5'); {Center key, Linux}
  864. {$ENDIF}
  865. 'H' : PushExt(71);
  866. {$IFDEF FREEBSD}
  867. 'I' : PushExt(73); {PageUp}
  868. {$ENDIF}
  869. 'K' : PushExt(79);
  870. {$IFDEF FREEBSD}
  871. 'L' : StoExt(82); {Insert - Deekoo}
  872. 'M' : StoExt(59); {F1-F10 - Deekoo}
  873. 'N' : StoExt(60); {F2}
  874. 'O' : StoExt(61); {F3}
  875. 'P' : StoExt(62); {F4}
  876. 'Q' : StoExt(63); {F5}
  877. 'R' : StoExt(64); {F6}
  878. 'S' : StoExt(65); {F7}
  879. 'T' : StoExt(66); {F8}
  880. 'U' : StoExt(67); {F9}
  881. 'V' : StoExt(68); {F10}
  882. {Not sure if TP/BP handles F11 and F12 like this normally;
  883. In pcemu, a TP7 executable handles 'em this way, though.}
  884. 'W' : StoExt(133); {F11}
  885. 'X' : StoExt(134); {F12}
  886. 'Y' : StoExt(84); {Shift-F1}
  887. 'Z' : StoExt(85); {Shift-F2}
  888. 'a' : StoExt(86); {Shift-F3}
  889. 'b' : StoExt(87); {Shift-F4}
  890. 'c' : StoExt(88); {Shift-F5}
  891. 'd' : StoExt(89); {Shift-F6}
  892. 'e' : StoExt(90); {Shift-F7}
  893. 'f' : StoExt(91); {Shift-F8}
  894. 'g' : StoExt(92); {Shift-F9}
  895. 'h' : StoExt(93); {Shift-F10}
  896. 'i' : StoExt(135); {Shift-F11}
  897. 'j' : StoExt(136); {Shift-F12}
  898. 'k' : StoExt(94); {Ctrl-F1}
  899. 'l' : StoExt(95);
  900. 'm' : StoExt(96);
  901. 'n' : StoExt(97);
  902. 'o' : StoExt(98);
  903. 'p' : StoExt(99);
  904. 'q' : StoExt(100);
  905. 'r' : StoExt(101);
  906. 's' : StoExt(102);
  907. 't' : StoExt(103); {Ctrl-F10}
  908. 'u' : StoExt(137); {Ctrl-F11}
  909. 'v' : StoExt(138); {Ctrl-F12}
  910. {$ENDIF}
  911. '1' : State:=4;
  912. '2' : State:=5;
  913. '3' : State:=6;
  914. '4' : PushExt(79);
  915. '5' : PushExt(73);
  916. '6' : PushExt(81);
  917. else
  918. begin
  919. PushKey(ch);
  920. PushKey('[');
  921. PushKey(#27);
  922. end;
  923. end;
  924. if ch in ['4'..'6'] then
  925. State:=255;
  926. end;
  927. 3 : begin {Esc[[}
  928. case ch of
  929. 'A' : PushExt(59);
  930. 'B' : PushExt(60);
  931. 'C' : PushExt(61);
  932. 'D' : PushExt(62);
  933. 'E' : PushExt(63);
  934. end;
  935. end;
  936. 4 : begin {Esc[1}
  937. case ch of
  938. '~' : PushExt(71);
  939. '7' : PushExt(64);
  940. '8' : PushExt(65);
  941. '9' : PushExt(66);
  942. end;
  943. if (Ch<>'~') then
  944. State:=255;
  945. end;
  946. 5 : begin {Esc[2}
  947. case ch of
  948. '~' : PushExt(82);
  949. '0' : pushExt(67);
  950. '1' : PushExt(68);
  951. '3' : PushExt(133); {F11}
  952. {Esc[23~ is also shift-F1,shift-F11}
  953. '4' : PushExt(134); {F12}
  954. {Esc[24~ is also shift-F2,shift-F12}
  955. '5' : PushExt(86); {Shift-F3}
  956. '6' : PushExt(87); {Shift-F4}
  957. '8' : PushExt(88); {Shift-F5}
  958. '9' : PushExt(89); {Shift-F6}
  959. end;
  960. if (Ch<>'~') then
  961. State:=255;
  962. end;
  963. 6 : begin {Esc[3}
  964. case ch of
  965. '~' : PushExt(83); {Del}
  966. '1' : PushExt(90); {Shift-F7}
  967. '2' : PushExt(91); {Shift-F8}
  968. '3' : PushExt(92); {Shift-F9}
  969. '4' : PushExt(93); {Shift-F10}
  970. end;
  971. if (Ch<>'~') then
  972. State:=255;
  973. end;
  974. 255 : ;
  975. end;
  976. if State<>0 then
  977. Delay(10);
  978. end;
  979. if State=1 then
  980. PushKey(ch);
  981. end;
  982. #127: PushKey(#8);
  983. else PushKey(ch);
  984. End;
  985. ReadKey:=PopKey;
  986. End;
  987. Procedure Delay(DTime: Word);
  988. {
  989. Wait for DTime milliseconds.
  990. }
  991. Begin
  992. Select(0,nil,nil,nil,DTime);
  993. End;
  994. {****************************************************************************
  995. Write(ln)/Read(ln) support
  996. ****************************************************************************}
  997. procedure DoLn;
  998. begin
  999. if CurrY=WinMaxY then
  1000. begin
  1001. if FullWin then
  1002. begin
  1003. ttySendStr(#10#13);
  1004. CurrX:=WinMinX;
  1005. CurrY:=WinMaxY;
  1006. end
  1007. else
  1008. begin
  1009. ScrollScrnRegionUp(WinMinX,WinMinY,WinMaxX,WinMaxY,1);
  1010. ttyGotoXY(WinMinX,WinMaxY);
  1011. end;
  1012. end
  1013. else
  1014. ttyGotoXY(WinMinX,CurrY+1);
  1015. end;
  1016. var
  1017. Lastansi : boolean;
  1018. AnsiCode : string;
  1019. Procedure DoWrite(const s:String);
  1020. {
  1021. Write string to screen, parse most common AnsiCodes
  1022. }
  1023. var
  1024. found,
  1025. OldFlush : boolean;
  1026. x,y,
  1027. i,j,
  1028. SendBytes : longint;
  1029. function AnsiPara(var hstr:string):byte;
  1030. var
  1031. k,j : longint;
  1032. code : word;
  1033. begin
  1034. j:=pos(';',hstr);
  1035. if j=0 then
  1036. j:=length(hstr);
  1037. val(copy(hstr,3,j-3),k,code);
  1038. Delete(hstr,3,j-2);
  1039. if k=0 then
  1040. k:=1;
  1041. AnsiPara:=k;
  1042. end;
  1043. procedure SendText;
  1044. var
  1045. LeftX : longint;
  1046. begin
  1047. while (SendBytes>0) do
  1048. begin
  1049. LeftX:=WinMaxX-CurrX+1;
  1050. if (SendBytes>LeftX) then
  1051. begin
  1052. ttyWrite(Copy(s,i-SendBytes,LeftX));
  1053. dec(SendBytes,LeftX);
  1054. DoLn;
  1055. end
  1056. else
  1057. begin
  1058. ttyWrite(Copy(s,i-SendBytes,SendBytes));
  1059. SendBytes:=0;
  1060. end;
  1061. end;
  1062. end;
  1063. begin
  1064. oldflush:=ttySetFlush(Flushing);
  1065. { Support textattr:= changing }
  1066. if OldTextAttr<>TextAttr then
  1067. begin
  1068. i:=TextAttr;
  1069. TextAttr:=OldTextAttr;
  1070. ttyColor(i);
  1071. end;
  1072. { write the stuff }
  1073. SendBytes:=0;
  1074. i:=1;
  1075. while (i<=length(s)) do
  1076. begin
  1077. if (s[i]=#27) or (LastAnsi) then
  1078. begin
  1079. SendText;
  1080. LastAnsi:=false;
  1081. j:=i;
  1082. found:=false;
  1083. while (j<=length(s)) and (not found) do
  1084. begin
  1085. found:=not (s[j] in [#27,'[','0'..'9',';','?']);
  1086. inc(j);
  1087. end;
  1088. Ansicode:=AnsiCode+Copy(s,i,j-i);
  1089. if found then
  1090. begin
  1091. case AnsiCode[length(AnsiCode)] of
  1092. 'm' : ttyColor(Ansi2Attr(AnsiCode,TextAttr));
  1093. 'H' : begin {No other way :( Coz First Para=Y}
  1094. y:=AnsiPara(AnsiCode);
  1095. x:=AnsiPara(AnsiCode);
  1096. GotoXY(x,y);
  1097. end;
  1098. 'J' : if AnsiPara(AnsiCode)=2 then
  1099. ClrScr;
  1100. 'K' : ClrEol;
  1101. 'A' : GotoXY(CurrX,Max(CurrY-AnsiPara(AnsiCode),WinMinY));
  1102. 'B' : GotoXY(CurrX,Min(CurrY+AnsiPara(AnsiCode),WinMaxY));
  1103. 'C' : GotoXY(Min(CurrX+AnsiPara(AnsiCode),WinMaxX),CurrY);
  1104. 'D' : GotoXY(Max(CurrX-AnsiPara(AnsiCode),WinMinX),CurrY);
  1105. 'h' : ; {Stupid Thedraw [?7h Code}
  1106. else
  1107. found:=false;
  1108. end;
  1109. end
  1110. else
  1111. begin
  1112. LastAnsi:=true;
  1113. found:=true;
  1114. end;
  1115. {Clear AnsiCode?}
  1116. if not LastAnsi then
  1117. AnsiCode:='';
  1118. {Increase Idx or SendBytes}
  1119. if found then
  1120. i:=j-1
  1121. else
  1122. inc(SendBytes);
  1123. end
  1124. else
  1125. begin
  1126. LastAnsi:=false;
  1127. case s[i] of
  1128. #13 : begin {CR}
  1129. SendText;
  1130. ttyGotoXY(WinMinX,CurrY);
  1131. end;
  1132. #10 : begin {NL}
  1133. SendText;
  1134. DoLn;
  1135. end;
  1136. #9 : begin {Tab}
  1137. SendText;
  1138. ttyWrite(Space(9-((CurrX-1) and $08)));
  1139. end;
  1140. #8 : begin {BackSpace}
  1141. SendText;
  1142. ttyWrite(#8);
  1143. end;
  1144. else
  1145. inc(SendBytes);
  1146. end;
  1147. end;
  1148. inc(i);
  1149. end;
  1150. if SendBytes>0 then
  1151. SendText;
  1152. ttySetFlush(oldFLush);
  1153. end;
  1154. Function CrtWrite(Var F: TextRec): Integer;
  1155. {
  1156. Top level write function for CRT
  1157. }
  1158. Var
  1159. Temp : String;
  1160. idx,i : Longint;
  1161. oldflush : boolean;
  1162. Begin
  1163. oldflush:=ttySetFlush(Flushing);
  1164. idx:=0;
  1165. while (F.BufPos>0) do
  1166. begin
  1167. i:=F.BufPos;
  1168. if i>255 then
  1169. i:=255;
  1170. Move(F.BufPTR^[idx],Temp[1],i);
  1171. SetLength(Temp,i);
  1172. DoWrite(Temp);
  1173. dec(F.BufPos,i);
  1174. inc(idx,i);
  1175. end;
  1176. ttySetFlush(oldFLush);
  1177. CrtWrite:=0;
  1178. End;
  1179. Function CrtRead(Var F: TextRec): Integer;
  1180. {
  1181. Read from CRT associated file.
  1182. }
  1183. var
  1184. c: char;
  1185. i, CurX, CurY : longint;
  1186. Begin
  1187. if isATTY(F.Handle) then
  1188. begin
  1189. i := 0;
  1190. repeat
  1191. c := readkey;
  1192. case c of
  1193. { ignore special keys }
  1194. #0:
  1195. c:= readkey;
  1196. { Backspace }
  1197. #8:
  1198. if i > 0 then
  1199. begin
  1200. if not(OutputRedir or InputRedir) then
  1201. write(#8#32#8);
  1202. dec(i);
  1203. end;
  1204. { Unhandled extended key }
  1205. #27:;
  1206. { CR }
  1207. #13:
  1208. begin
  1209. F.BufPtr^[i] := #10;
  1210. if not(OutputRedir or InputRedir) then
  1211. write(#13);
  1212. inc(i);
  1213. end;
  1214. else
  1215. begin
  1216. if not(OutputRedir or InputRedir) then
  1217. write(c);
  1218. F.BufPtr^[i] := c;
  1219. inc(i);
  1220. end;
  1221. end;
  1222. until c in [#10,#13];
  1223. F.BufEnd := i;
  1224. CrtRead := 0;
  1225. exit;
  1226. end;
  1227. F.BufEnd:=fdRead(F.Handle, F.BufPtr^, F.BufSize);
  1228. { fix #13 only's -> #10 to overcome terminal setting }
  1229. for i:=1to F.BufEnd do
  1230. begin
  1231. if (F.BufPtr^[i-1]=#13) and (F.BufPtr^[i]<>#10) then
  1232. F.BufPtr^[i-1]:=#10;
  1233. end;
  1234. F.BufPos:=F.BufEnd;
  1235. if not(OutputRedir or InputRedir) then
  1236. CrtWrite(F)
  1237. else F.BufPos := 0;
  1238. CrtRead:=0;
  1239. End;
  1240. Function CrtReturn(Var F:TextRec):Integer;
  1241. Begin
  1242. CrtReturn:=0;
  1243. end;
  1244. Function CrtClose(Var F: TextRec): Integer;
  1245. {
  1246. Close CRT associated file.
  1247. }
  1248. Begin
  1249. F.Mode:=fmClosed;
  1250. CrtClose:=0;
  1251. End;
  1252. Function CrtOpen(Var F: TextRec): Integer;
  1253. {
  1254. Open CRT associated file.
  1255. }
  1256. Begin
  1257. If F.Mode=fmOutput Then
  1258. begin
  1259. TextRec(F).InOutFunc:=@CrtWrite;
  1260. TextRec(F).FlushFunc:=@CrtWrite;
  1261. end
  1262. Else
  1263. begin
  1264. F.Mode:=fmInput;
  1265. TextRec(F).InOutFunc:=@CrtRead;
  1266. TextRec(F).FlushFunc:=@CrtReturn;
  1267. end;
  1268. TextRec(F).CloseFunc:=@CrtClose;
  1269. CrtOpen:=0;
  1270. End;
  1271. procedure AssignCrt(var F: Text);
  1272. {
  1273. Assign a file to the console. All output on file goes to console instead.
  1274. }
  1275. begin
  1276. Assign(F,'');
  1277. TextRec(F).OpenFunc:=@CrtOpen;
  1278. end;
  1279. {******************************************************************************
  1280. High Level Functions
  1281. ******************************************************************************}
  1282. Procedure DelLine;
  1283. {
  1284. Delete current line. Scroll subsequent lines up
  1285. }
  1286. Begin
  1287. ScrollScrnRegionUp(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1288. End;
  1289. Procedure InsLine;
  1290. {
  1291. Insert line at current cursor position. Scroll subsequent lines down.
  1292. }
  1293. Begin
  1294. ScrollScrnRegionDown(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1295. End;
  1296. Procedure Sound(Hz: Word);
  1297. {
  1298. Does nothing under linux
  1299. }
  1300. begin
  1301. end;
  1302. Procedure NoSound;
  1303. {
  1304. Does nothing under linux
  1305. }
  1306. begin
  1307. end;
  1308. Procedure TextMode(Mode: Integer);
  1309. {
  1310. Only Clears Screen under linux
  1311. }
  1312. begin
  1313. ClrScr;
  1314. end;
  1315. {******************************************************************************
  1316. Extra
  1317. ******************************************************************************}
  1318. procedure CursorBig;
  1319. begin
  1320. ttySendStr(#27'[?17;0;64c');
  1321. end;
  1322. procedure CursorOn;
  1323. begin
  1324. ttySendStr(#27'[?2c');
  1325. end;
  1326. procedure CursorOff;
  1327. begin
  1328. ttySendStr(#27'[?1c');
  1329. end;
  1330. {******************************************************************************
  1331. Initialization
  1332. ******************************************************************************}
  1333. var
  1334. OldIO : TermIos;
  1335. Procedure SetRawMode(b:boolean);
  1336. Var
  1337. Tio : Termios;
  1338. Begin
  1339. if b then
  1340. begin
  1341. TCGetAttr(1,Tio);
  1342. OldIO:=Tio;
  1343. CFMakeRaw(Tio);
  1344. end
  1345. else
  1346. Tio:=OldIO;
  1347. TCSetAttr(1,TCSANOW,Tio);
  1348. End;
  1349. procedure GetXY(var x,y:byte);
  1350. var
  1351. fds : fdSet;
  1352. i,j,
  1353. readed : longint;
  1354. buf : array[0..255] of char;
  1355. s : string[16];
  1356. begin
  1357. x:=0;
  1358. y:=0;
  1359. s:=#27'[6n';
  1360. fdWrite(0,s[1],length(s));
  1361. FD_Zero(fds);
  1362. FD_Set(1,fds);
  1363. if (Select(2,@fds,nil,nil,1000)>0) then
  1364. begin
  1365. readed:=fdRead(1,buf,sizeof(buf));
  1366. i:=0;
  1367. while (i+5<readed) and (buf[i]<>#27) and (buf[i+1]<>'[') do
  1368. inc(i);
  1369. if i+5<readed then
  1370. begin
  1371. s:=space(16);
  1372. move(buf[i+2],s[1],16);
  1373. i:=Pos(';',s);
  1374. if i>0 then
  1375. begin
  1376. Val(Copy(s,1,i-1),y);
  1377. j:=Pos('R',s);
  1378. if j=0 then
  1379. j:=length(s);
  1380. Val(Copy(s,i+1,j-(i+1)),x);
  1381. end;
  1382. end;
  1383. end;
  1384. end;
  1385. Procedure GetConsoleBuf;
  1386. var
  1387. WinInfo : TWinSize;
  1388. begin
  1389. if Assigned(ConsoleBuf) then
  1390. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1391. if (not OutputRedir) and IOCtl(TextRec(Output).Handle,TIOCGWINSZ,@Wininfo) then
  1392. begin
  1393. ScreenWidth:=Wininfo.ws_col;
  1394. ScreenHeight:=Wininfo.ws_row;
  1395. end
  1396. else
  1397. begin
  1398. ScreenWidth:=80;
  1399. ScreenHeight:=25;
  1400. end;
  1401. GetMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1402. FillChar(ConsoleBuf^,ScreenHeight*ScreenWidth*2,0);
  1403. end;
  1404. Procedure CrtExit;
  1405. {
  1406. We need to restore normal keyboard mode upon exit !!
  1407. }
  1408. Begin
  1409. ttyFlushOutput;
  1410. SetRawMode(False);
  1411. { remove console buf }
  1412. if Assigned(ConsoleBuf) then
  1413. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1414. ExitProc:=ExitSave;
  1415. End;
  1416. Begin
  1417. {Hook Exit}
  1418. ExitSave:=ExitProc;
  1419. ExitProc:=@CrtExit;
  1420. { Redirect the standard output }
  1421. assigncrt(Output);
  1422. Rewrite(Output);
  1423. TextRec(Output).Handle:=StdOutputHandle;
  1424. assigncrt(Input);
  1425. Reset(Input);
  1426. TextRec(Input).Handle:=StdInputHandle;
  1427. { Are we redirected to a file ? }
  1428. OutputRedir:= not IsAtty(TextRec(Output).Handle);
  1429. { does the input come from another console or from a file? }
  1430. InputRedir :=
  1431. not IsAtty(TextRec(Input).Handle) or
  1432. (not OutputRedir and
  1433. (TTYName(TextRec(Input).Handle) <> TTYName(TextRec(Output).Handle)));
  1434. { Get Size of terminal and set WindMax to the window }
  1435. GetConsoleBuf;
  1436. WindMax:=((ScreenHeight-1) Shl 8)+(ScreenWidth-1);
  1437. {Get Current X&Y or Reset to Home}
  1438. if OutputRedir then
  1439. begin
  1440. CurrX:=1;
  1441. CurrY:=1;
  1442. end
  1443. else
  1444. begin
  1445. { Set default Terminal Settings }
  1446. SetRawMode(True);
  1447. { Get current X,Y if not set already }
  1448. GetXY(CurrX,CurrY);
  1449. if (CurrX=0) then
  1450. begin
  1451. CurrX:=1;
  1452. CurrY:=1;
  1453. ttySendStr(#27'[H');
  1454. end;
  1455. {Reset Attribute (TextAttr=7 at startup)}
  1456. ttySendStr(#27'[m');
  1457. end;
  1458. End.
  1459. {
  1460. $Log$
  1461. Revision 1.27 2000-06-05 08:35:28 jonas
  1462. * in readkey, check if keypresses are waiting using sysKeyPressed instead
  1463. of simply checking if there are keys left in the ttyRecvChar buffer
  1464. * CrtRead supports the backspace key when reading from a TTY.
  1465. NOTE: you have to use ReadKey or ttyRecvChar in crtRead, because it's
  1466. possible that when CrtRead starts, there are already keys waiting in
  1467. the ttyRecvChar buffer which would be missed using an fdRead!
  1468. Revision 1.26 2000/06/04 13:49:57 jonas
  1469. * fixed webbug 978
  1470. Revision 1.25 2000/05/08 13:24:27 peter
  1471. * removed hardcoded limit of 80 width
  1472. Revision 1.24 2000/04/14 12:15:31 pierre
  1473. * several bugs fixed
  1474. Revision 1.23 2000/04/07 13:26:27 jonas
  1475. * fix for web bug 917
  1476. * also do not mirror input if input is another TTY than output or if
  1477. input is redirected
  1478. Revision 1.22 2000/02/09 16:59:31 peter
  1479. * truncated log
  1480. Revision 1.21 2000/01/07 16:41:39 daniel
  1481. * copyright 2000
  1482. Revision 1.20 2000/01/07 16:32:26 daniel
  1483. * copyright 2000 added
  1484. Revision 1.19 1999/10/22 14:36:20 peter
  1485. * crtreturn also needs f:textrec as parameter
  1486. Revision 1.18 1999/09/07 07:47:46 peter
  1487. * write > 255 chars
  1488. Revision 1.17 1999/09/07 07:38:09 michael
  1489. + Applied readkey patch from Deekoo L
  1490. }