crt.pp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699
  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 BaseUnix ,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. fpWrite(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:=fpread(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 : tfdSet;
  770. begin
  771. if (InCnt>0) then
  772. sysKeyPressed:=true
  773. else
  774. begin
  775. fpFD_ZERO(fdsin);
  776. fpFD_SET(TTYin,fdsin);
  777. sysKeypressed:=(fpSelect(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 : TFDSet;
  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. FpFD_ZERO (FDS);
  802. fpFD_SET (0,FDS);
  803. fpSelect (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. {$IFDEF Unix}
  828. 'O': State:=7;
  829. {$ENDIF}
  830. else
  831. begin
  832. PushKey(ch);
  833. PushKey(#27);
  834. end;
  835. end;
  836. end;
  837. 2 : begin {Esc[}
  838. case ch of
  839. '[' : State:=3;
  840. 'A' : PushExt(72);
  841. 'B' : PushExt(80);
  842. 'C' : PushExt(77);
  843. 'D' : PushExt(75);
  844. {$IFDEF FREEBSD}
  845. {'E' - Center key, not handled in DOS TP7}
  846. 'F' : PushExt(79); {End}
  847. 'G': PushExt(81); {PageDown}
  848. {$ELSE}
  849. 'G' : PushKey('5'); {Center key, Linux}
  850. {$ENDIF}
  851. 'H' : PushExt(71);
  852. {$IFDEF FREEBSD}
  853. 'I' : PushExt(73); {PageUp}
  854. {$ENDIF}
  855. 'K' : PushExt(79);
  856. {$IFDEF FREEBSD}
  857. 'L' : PushExt(82); {Insert - Deekoo}
  858. 'M' : PushExt(59); {F1-F10 - Deekoo}
  859. 'N' : PushExt(60); {F2}
  860. 'O' : PushExt(61); {F3}
  861. 'P' : PushExt(62); {F4}
  862. 'Q' : PushExt(63); {F5}
  863. 'R' : PushExt(64); {F6}
  864. 'S' : PushExt(65); {F7}
  865. 'T' : PushExt(66); {F8}
  866. 'U' : PushExt(67); {F9}
  867. 'V' : PushExt(68); {F10}
  868. {Not sure if TP/BP handles F11 and F12 like this normally;
  869. In pcemu, a TP7 executable handles 'em this way, though.}
  870. 'W' : PushExt(133); {F11}
  871. 'X' : PushExt(134); {F12}
  872. 'Y' : PushExt(84); {Shift-F1}
  873. 'Z' : PushExt(85); {Shift-F2}
  874. 'a' : PushExt(86); {Shift-F3}
  875. 'b' : PushExt(87); {Shift-F4}
  876. 'c' : PushExt(88); {Shift-F5}
  877. 'd' : PushExt(89); {Shift-F6}
  878. 'e' : PushExt(90); {Shift-F7}
  879. 'f' : PushExt(91); {Shift-F8}
  880. 'g' : PushExt(92); {Shift-F9}
  881. 'h' : PushExt(93); {Shift-F10}
  882. 'i' : PushExt(135); {Shift-F11}
  883. 'j' : PushExt(136); {Shift-F12}
  884. 'k' : PushExt(94); {Ctrl-F1}
  885. 'l' : PushExt(95);
  886. 'm' : PushExt(96);
  887. 'n' : PushExt(97);
  888. 'o' : PushExt(98);
  889. 'p' : PushExt(99);
  890. 'q' : PushExt(100);
  891. 'r' : PushExt(101);
  892. 's' : PushExt(102);
  893. 't' : PushExt(103); {Ctrl-F10}
  894. 'u' : PushExt(137); {Ctrl-F11}
  895. 'v' : PushExt(138); {Ctrl-F12}
  896. {$ENDIF}
  897. '1' : State:=4;
  898. '2' : State:=5;
  899. '3' : State:=6;
  900. '4' : PushExt(79);
  901. '5' : PushExt(73);
  902. '6' : PushExt(81);
  903. else
  904. begin
  905. PushKey(ch);
  906. PushKey('[');
  907. PushKey(#27);
  908. end;
  909. end;
  910. if ch in ['4'..'6'] then
  911. State:=255;
  912. end;
  913. 3 : begin {Esc[[}
  914. case ch of
  915. 'A' : PushExt(59);
  916. 'B' : PushExt(60);
  917. 'C' : PushExt(61);
  918. 'D' : PushExt(62);
  919. 'E' : PushExt(63);
  920. end;
  921. end;
  922. 4 : begin {Esc[1}
  923. case ch of
  924. '~' : PushExt(71);
  925. '7' : PushExt(64);
  926. '8' : PushExt(65);
  927. '9' : PushExt(66);
  928. end;
  929. if (Ch<>'~') then
  930. State:=255;
  931. end;
  932. 5 : begin {Esc[2}
  933. case ch of
  934. '~' : PushExt(82);
  935. '0' : pushExt(67);
  936. '1' : PushExt(68);
  937. '3' : PushExt(133); {F11}
  938. {Esc[23~ is also shift-F1,shift-F11}
  939. '4' : PushExt(134); {F12}
  940. {Esc[24~ is also shift-F2,shift-F12}
  941. '5' : PushExt(86); {Shift-F3}
  942. '6' : PushExt(87); {Shift-F4}
  943. '8' : PushExt(88); {Shift-F5}
  944. '9' : PushExt(89); {Shift-F6}
  945. end;
  946. if (Ch<>'~') then
  947. State:=255;
  948. end;
  949. 6 : begin {Esc[3}
  950. case ch of
  951. '~' : PushExt(83); {Del}
  952. '1' : PushExt(90); {Shift-F7}
  953. '2' : PushExt(91); {Shift-F8}
  954. '3' : PushExt(92); {Shift-F9}
  955. '4' : PushExt(93); {Shift-F10}
  956. end;
  957. if (Ch<>'~') then
  958. State:=255;
  959. end;
  960. {$ifdef Unix}
  961. 7 : begin {Esc[O}
  962. case ch of
  963. 'A' : PushExt(72);
  964. 'B' : PushExt(80);
  965. 'C' : PushExt(77);
  966. 'D' : PushExt(75);
  967. end;
  968. end;
  969. {$endif}
  970. 255 : ;
  971. end;
  972. if State<>0 then
  973. Delay(10);
  974. end;
  975. if State=1 then
  976. PushKey(ch);
  977. end;
  978. #127: PushKey(#8);
  979. else PushKey(ch);
  980. End;
  981. ReadKey:=PopKey;
  982. End;
  983. Procedure Delay(DTime: Word);
  984. {
  985. Wait for DTime milliseconds.
  986. }
  987. Begin
  988. fpSelect(0,nil,nil,nil,DTime);
  989. End;
  990. {****************************************************************************
  991. Write(ln)/Read(ln) support
  992. ****************************************************************************}
  993. procedure DoLn;
  994. begin
  995. if CurrY=WinMaxY then
  996. begin
  997. if FullWin then
  998. begin
  999. ttySendStr(#10#13);
  1000. CurrX:=WinMinX;
  1001. CurrY:=WinMaxY;
  1002. end
  1003. else
  1004. begin
  1005. ScrollScrnRegionUp(WinMinX,WinMinY,WinMaxX,WinMaxY,1);
  1006. ttyGotoXY(WinMinX,WinMaxY);
  1007. end;
  1008. end
  1009. else
  1010. ttyGotoXY(WinMinX,CurrY+1);
  1011. end;
  1012. var
  1013. Lastansi : boolean;
  1014. AnsiCode : string;
  1015. Procedure DoWrite(const s:String);
  1016. {
  1017. Write string to screen, parse most common AnsiCodes
  1018. }
  1019. var
  1020. found,
  1021. OldFlush : boolean;
  1022. x,y,
  1023. i,j,
  1024. SendBytes : longint;
  1025. function AnsiPara(var hstr:string):byte;
  1026. var
  1027. k,j : longint;
  1028. code : word;
  1029. begin
  1030. j:=pos(';',hstr);
  1031. if j=0 then
  1032. j:=length(hstr);
  1033. val(copy(hstr,3,j-3),k,code);
  1034. Delete(hstr,3,j-2);
  1035. if k=0 then
  1036. k:=1;
  1037. AnsiPara:=k;
  1038. end;
  1039. procedure SendText;
  1040. var
  1041. LeftX : longint;
  1042. begin
  1043. while (SendBytes>0) do
  1044. begin
  1045. LeftX:=WinMaxX-CurrX+1;
  1046. if (SendBytes>LeftX) then
  1047. begin
  1048. ttyWrite(Copy(s,i-SendBytes,LeftX));
  1049. dec(SendBytes,LeftX);
  1050. DoLn;
  1051. end
  1052. else
  1053. begin
  1054. ttyWrite(Copy(s,i-SendBytes,SendBytes));
  1055. SendBytes:=0;
  1056. end;
  1057. end;
  1058. end;
  1059. begin
  1060. oldflush:=ttySetFlush(Flushing);
  1061. { Support textattr:= changing }
  1062. if OldTextAttr<>TextAttr then
  1063. begin
  1064. i:=TextAttr;
  1065. TextAttr:=OldTextAttr;
  1066. ttyColor(i);
  1067. end;
  1068. { write the stuff }
  1069. SendBytes:=0;
  1070. i:=1;
  1071. while (i<=length(s)) do
  1072. begin
  1073. if (s[i]=#27) or (LastAnsi) then
  1074. begin
  1075. SendText;
  1076. LastAnsi:=false;
  1077. j:=i;
  1078. found:=false;
  1079. while (j<=length(s)) and (not found) do
  1080. begin
  1081. found:=not (s[j] in [#27,'[','0'..'9',';','?']);
  1082. inc(j);
  1083. end;
  1084. Ansicode:=AnsiCode+Copy(s,i,j-i);
  1085. if found then
  1086. begin
  1087. case AnsiCode[length(AnsiCode)] of
  1088. 'm' : ttyColor(Ansi2Attr(AnsiCode,TextAttr));
  1089. 'H' : begin {No other way :( Coz First Para=Y}
  1090. y:=AnsiPara(AnsiCode);
  1091. x:=AnsiPara(AnsiCode);
  1092. GotoXY(x,y);
  1093. end;
  1094. 'J' : if AnsiPara(AnsiCode)=2 then
  1095. ClrScr;
  1096. 'K' : ClrEol;
  1097. 'A' : GotoXY(CurrX,Max(CurrY-AnsiPara(AnsiCode),WinMinY));
  1098. 'B' : GotoXY(CurrX,Min(CurrY+AnsiPara(AnsiCode),WinMaxY));
  1099. 'C' : GotoXY(Min(CurrX+AnsiPara(AnsiCode),WinMaxX),CurrY);
  1100. 'D' : GotoXY(Max(CurrX-AnsiPara(AnsiCode),WinMinX),CurrY);
  1101. 'h' : ; {Stupid Thedraw [?7h Code}
  1102. else
  1103. found:=false;
  1104. end;
  1105. end
  1106. else
  1107. begin
  1108. LastAnsi:=true;
  1109. found:=true;
  1110. end;
  1111. {Clear AnsiCode?}
  1112. if not LastAnsi then
  1113. AnsiCode:='';
  1114. {Increase Idx or SendBytes}
  1115. if found then
  1116. i:=j-1
  1117. else
  1118. inc(SendBytes);
  1119. end
  1120. else
  1121. begin
  1122. LastAnsi:=false;
  1123. case s[i] of
  1124. #13 : begin {CR}
  1125. SendText;
  1126. ttyGotoXY(WinMinX,CurrY);
  1127. end;
  1128. #10 : begin {NL}
  1129. SendText;
  1130. DoLn;
  1131. end;
  1132. #9 : begin {Tab}
  1133. SendText;
  1134. ttyWrite(Space(9-((CurrX-1) and $08)));
  1135. end;
  1136. #8 : begin {BackSpace}
  1137. SendText;
  1138. ttyWrite(#8);
  1139. end;
  1140. else
  1141. inc(SendBytes);
  1142. end;
  1143. end;
  1144. inc(i);
  1145. end;
  1146. if SendBytes>0 then
  1147. SendText;
  1148. ttySetFlush(oldFLush);
  1149. end;
  1150. Function CrtWrite(Var F: TextRec): Integer;
  1151. {
  1152. Top level write function for CRT
  1153. }
  1154. Var
  1155. Temp : String;
  1156. idx,i : Longint;
  1157. oldflush : boolean;
  1158. Begin
  1159. oldflush:=ttySetFlush(Flushing);
  1160. idx:=0;
  1161. while (F.BufPos>0) do
  1162. begin
  1163. i:=F.BufPos;
  1164. if i>255 then
  1165. i:=255;
  1166. Move(F.BufPTR^[idx],Temp[1],i);
  1167. SetLength(Temp,i);
  1168. DoWrite(Temp);
  1169. dec(F.BufPos,i);
  1170. inc(idx,i);
  1171. end;
  1172. ttySetFlush(oldFLush);
  1173. CrtWrite:=0;
  1174. End;
  1175. Function CrtRead(Var F: TextRec): Integer;
  1176. {
  1177. Read from CRT associated file.
  1178. }
  1179. var
  1180. c : char;
  1181. i : longint;
  1182. Begin
  1183. if isATTY(F.Handle) then
  1184. begin
  1185. F.BufPos := 0;
  1186. i := 0;
  1187. repeat
  1188. c := readkey;
  1189. case c of
  1190. { ignore special keys }
  1191. #0:
  1192. c:= readkey;
  1193. { Backspace }
  1194. #8:
  1195. if i > 0 then
  1196. begin
  1197. if not(OutputRedir or InputRedir) then
  1198. write(#8#32#8);
  1199. dec(i);
  1200. end;
  1201. { Unhandled extended key }
  1202. #27:;
  1203. { CR }
  1204. #13:
  1205. begin
  1206. F.BufPtr^[i] := #10;
  1207. if not(OutputRedir or InputRedir) then
  1208. write(#10);
  1209. inc(i);
  1210. end;
  1211. else
  1212. begin
  1213. if not(OutputRedir or InputRedir) then
  1214. write(c);
  1215. F.BufPtr^[i] := c;
  1216. inc(i);
  1217. end;
  1218. end;
  1219. until (c in [#10,#13]) or (i >= F.BufSize);
  1220. F.BufEnd := i;
  1221. CrtRead := 0;
  1222. exit;
  1223. end;
  1224. F.BufEnd:=fpRead(F.Handle, F.BufPtr^, F.BufSize);
  1225. { fix #13 only's -> #10 to overcome terminal setting }
  1226. for i:=1to F.BufEnd do
  1227. begin
  1228. if (F.BufPtr^[i-1]=#13) and (F.BufPtr^[i]<>#10) then
  1229. F.BufPtr^[i-1]:=#10;
  1230. end;
  1231. F.BufPos:=F.BufEnd;
  1232. if not(OutputRedir or InputRedir) then
  1233. CrtWrite(F)
  1234. else F.BufPos := 0;
  1235. CrtRead:=0;
  1236. End;
  1237. Function CrtReturn(Var F:TextRec):Integer;
  1238. Begin
  1239. CrtReturn:=0;
  1240. end;
  1241. Function CrtClose(Var F: TextRec): Integer;
  1242. {
  1243. Close CRT associated file.
  1244. }
  1245. Begin
  1246. F.Mode:=fmClosed;
  1247. CrtClose:=0;
  1248. End;
  1249. Function CrtOpen(Var F: TextRec): Integer;
  1250. {
  1251. Open CRT associated file.
  1252. }
  1253. Begin
  1254. If F.Mode=fmOutput Then
  1255. begin
  1256. TextRec(F).InOutFunc:=@CrtWrite;
  1257. TextRec(F).FlushFunc:=@CrtWrite;
  1258. end
  1259. Else
  1260. begin
  1261. F.Mode:=fmInput;
  1262. TextRec(F).InOutFunc:=@CrtRead;
  1263. TextRec(F).FlushFunc:=@CrtReturn;
  1264. end;
  1265. TextRec(F).CloseFunc:=@CrtClose;
  1266. CrtOpen:=0;
  1267. End;
  1268. procedure AssignCrt(var F: Text);
  1269. {
  1270. Assign a file to the console. All output on file goes to console instead.
  1271. }
  1272. begin
  1273. Assign(F,'');
  1274. TextRec(F).OpenFunc:=@CrtOpen;
  1275. end;
  1276. {******************************************************************************
  1277. High Level Functions
  1278. ******************************************************************************}
  1279. Procedure DelLine;
  1280. {
  1281. Delete current line. Scroll subsequent lines up
  1282. }
  1283. Begin
  1284. ScrollScrnRegionUp(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1285. End;
  1286. Procedure InsLine;
  1287. {
  1288. Insert line at current cursor position. Scroll subsequent lines down.
  1289. }
  1290. Begin
  1291. ScrollScrnRegionDown(WinMinX, CurrY, WinMaxX, WinMaxY, 1);
  1292. End;
  1293. const
  1294. KIOCSOUND = $4B2F; // start sound generation (0 for off)
  1295. Procedure Sound(Hz: Word);
  1296. begin
  1297. if not OutputRedir then
  1298. fpIoctl(TextRec(Output).Handle, KIOCSOUND, Pointer(1193180 div Hz));
  1299. end;
  1300. Procedure NoSound;
  1301. begin
  1302. if not OutputRedir then
  1303. fpIoctl(TextRec(Output).Handle, KIOCSOUND, nil);
  1304. end;
  1305. Procedure TextMode(Mode: Integer);
  1306. {
  1307. Only Clears Screen under linux}
  1308. begin
  1309. ClrScr;
  1310. end;
  1311. {******************************************************************************
  1312. Extra
  1313. ******************************************************************************}
  1314. procedure CursorBig;
  1315. begin
  1316. ttySendStr(#27'[?17;0;64c');
  1317. end;
  1318. procedure CursorOn;
  1319. begin
  1320. ttySendStr(#27'[?2c');
  1321. end;
  1322. procedure CursorOff;
  1323. begin
  1324. ttySendStr(#27'[?1c');
  1325. end;
  1326. {******************************************************************************
  1327. Initialization
  1328. ******************************************************************************}
  1329. var
  1330. OldIO : Unix.TermIos;
  1331. inputRaw, outputRaw: boolean;
  1332. procedure saveRawSettings(const tio: Unix.termios);
  1333. Begin
  1334. with tio do
  1335. begin
  1336. inputRaw :=
  1337. ((c_iflag and (IGNBRK or BRKINT or PARMRK or ISTRIP or
  1338. INLCR or IGNCR or ICRNL or IXON)) = 0) and
  1339. ((c_lflag and (ECHO or ECHONL or ICANON or ISIG or IEXTEN)) = 0);
  1340. outPutRaw :=
  1341. ((c_oflag and OPOST) = 0) and
  1342. ((c_cflag and (CSIZE or PARENB)) = 0) and
  1343. ((c_cflag and CS8) <> 0);
  1344. end;
  1345. end;
  1346. procedure restoreRawSettings(tio: Unix.termios);
  1347. begin
  1348. with tio do
  1349. begin
  1350. if inputRaw then
  1351. begin
  1352. c_iflag := c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
  1353. INLCR or IGNCR or ICRNL or IXON));
  1354. c_lflag := c_lflag and
  1355. (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
  1356. end;
  1357. if outPutRaw then
  1358. begin
  1359. c_oflag := c_oflag and not(OPOST);
  1360. c_cflag := c_cflag and not(CSIZE or PARENB) or CS8;
  1361. end;
  1362. end;
  1363. end;
  1364. Procedure SetRawMode(b:boolean);
  1365. Var
  1366. Tio : Termios;
  1367. Begin
  1368. if b then
  1369. begin
  1370. TCGetAttr(1,Tio);
  1371. SaveRawSettings(Tio);
  1372. OldIO:=Tio;
  1373. CFMakeRaw(Tio);
  1374. end
  1375. else
  1376. begin
  1377. RestoreRawSettings(OldIO);
  1378. Tio:=OldIO;
  1379. end;
  1380. TCSetAttr(1,TCSANOW,Tio);
  1381. End;
  1382. procedure GetXY(var x,y:byte);
  1383. var
  1384. fds : tfdSet;
  1385. i,j,
  1386. readed : longint;
  1387. buf : array[0..255] of char;
  1388. s : string[16];
  1389. begin
  1390. x:=0;
  1391. y:=0;
  1392. s:=#27'[6n';
  1393. fpWrite(0,s[1],length(s));
  1394. fpFD_ZERO(fds);
  1395. fpFD_SET(1,fds);
  1396. if (fpSelect(2,@fds,nil,nil,1000)>0) then
  1397. begin
  1398. readed:=fpRead(1,buf,sizeof(buf));
  1399. i:=0;
  1400. while (i+5<readed) and (buf[i]<>#27) and (buf[i+1]<>'[') do
  1401. inc(i);
  1402. if i+5<readed then
  1403. begin
  1404. s:=space(16);
  1405. move(buf[i+2],s[1],16);
  1406. i:=Pos(';',s);
  1407. if i>0 then
  1408. begin
  1409. Val(Copy(s,1,i-1),y);
  1410. j:=Pos('R',s);
  1411. if j=0 then
  1412. j:=length(s);
  1413. Val(Copy(s,i+1,j-(i+1)),x);
  1414. end;
  1415. end;
  1416. end;
  1417. end;
  1418. Procedure GetConsoleBuf;
  1419. var
  1420. WinInfo : TWinSize;
  1421. begin
  1422. if Assigned(ConsoleBuf) then
  1423. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1424. if (not OutputRedir) and (fpIOCtl(TextRec(Output).Handle,TIOCGWINSZ,@Wininfo)>=0) then
  1425. begin
  1426. ScreenWidth:=Wininfo.ws_col;
  1427. ScreenHeight:=Wininfo.ws_row;
  1428. end
  1429. else
  1430. begin
  1431. ScreenWidth:=80;
  1432. ScreenHeight:=25;
  1433. end;
  1434. GetMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1435. FillChar(ConsoleBuf^,ScreenHeight*ScreenWidth*2,0);
  1436. end;
  1437. Initialization
  1438. { Redirect the standard output }
  1439. assigncrt(Output);
  1440. Rewrite(Output);
  1441. TextRec(Output).Handle:=StdOutputHandle;
  1442. assigncrt(Input);
  1443. Reset(Input);
  1444. TextRec(Input).Handle:=StdInputHandle;
  1445. { Are we redirected to a file ? }
  1446. OutputRedir:= not IsAtty(TextRec(Output).Handle);
  1447. { does the input come from another console or from a file? }
  1448. InputRedir :=
  1449. not IsAtty(TextRec(Input).Handle) or
  1450. (not OutputRedir and
  1451. (TTYName(TextRec(Input).Handle) <> TTYName(TextRec(Output).Handle)));
  1452. { Get Size of terminal and set WindMax to the window }
  1453. GetConsoleBuf;
  1454. WinMinX:=1;
  1455. WinMinY:=1;
  1456. WinMaxX:=ScreenWidth;
  1457. WinMaxY:=ScreenHeight;
  1458. WindMax:=((ScreenHeight-1) Shl 8)+(ScreenWidth-1);
  1459. {Get Current X&Y or Reset to Home}
  1460. if OutputRedir then
  1461. begin
  1462. CurrX:=1;
  1463. CurrY:=1;
  1464. end
  1465. else
  1466. begin
  1467. { Set default Terminal Settings }
  1468. SetRawMode(True);
  1469. { Get current X,Y if not set already }
  1470. GetXY(CurrX,CurrY);
  1471. if (CurrX=0) then
  1472. begin
  1473. CurrX:=1;
  1474. CurrY:=1;
  1475. ttySendStr(#27'[H');
  1476. end;
  1477. {Reset Attribute (TextAttr=7 at startup)}
  1478. ttySendStr(#27'[m');
  1479. end;
  1480. Finalization
  1481. ttyFlushOutput;
  1482. SetRawMode(False);
  1483. { remove console buf }
  1484. if Assigned(ConsoleBuf) then
  1485. FreeMem(ConsoleBuf,ScreenHeight*ScreenWidth*2);
  1486. End.
  1487. {
  1488. $Log$
  1489. Revision 1.13 2003-09-16 20:52:24 marco
  1490. * small cleanups. Mostly killing of already commented code in unix etc
  1491. Revision 1.12 2003/09/16 16:13:56 marco
  1492. * fdset functions renamed to fp<posix name>
  1493. Revision 1.11 2003/09/14 20:15:01 marco
  1494. * Unix reform stage two. Remove all calls from Unix that exist in Baseunix.
  1495. Revision 1.10 2002/09/07 16:01:27 peter
  1496. * old logs removed and tabs fixed
  1497. Revision 1.9 2002/05/31 13:37:24 marco
  1498. * more Renamefest
  1499. }