crt.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2004 by the Free Pascal development team.
  4. Borland Pascal 7 Compatible CRT Unit for Netware (libc version)
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit crt;
  12. interface
  13. {$i crth.inc}
  14. Const
  15. ScreenHeight : longint=25;
  16. ScreenWidth : longint=80;
  17. implementation
  18. uses Libc;
  19. {$ASMMODE ATT}
  20. var
  21. ScreenHandle : scr_t;
  22. { Definition of textrec is in textrec.inc }
  23. {$i textrec.inc}
  24. {****************************************************************************
  25. Low level Routines
  26. ****************************************************************************}
  27. procedure setscreenmode(mode : byte);
  28. begin
  29. setscreenmode (mode);
  30. end;
  31. function GetScreenHeight : longint;
  32. VAR Height, Width : WORD;
  33. begin
  34. GetScreenSize(Height, Width);
  35. GetScreenHeight := Height;
  36. end;
  37. function GetScreenWidth : longint;
  38. VAR Height, Width : WORD;
  39. begin
  40. GetScreenSize(Height, Width);
  41. GetScreenWidth := Width;
  42. end;
  43. procedure GetScreenCursor(var x,y : longint);
  44. begin
  45. x := wherecol+1;
  46. y := whererow+1;
  47. end;
  48. {****************************************************************************
  49. Helper Routines
  50. ****************************************************************************}
  51. Function WinMinX: Longint;
  52. {
  53. Current Minimum X coordinate
  54. }
  55. Begin
  56. WinMinX:=(WindMin and $ff)+1;
  57. End;
  58. Function WinMinY: Longint;
  59. {
  60. Current Minimum Y Coordinate
  61. }
  62. Begin
  63. WinMinY:=(WindMin shr 8)+1;
  64. End;
  65. Function WinMaxX: Longint;
  66. {
  67. Current Maximum X coordinate
  68. }
  69. Begin
  70. WinMaxX:=(WindMax and $ff)+1;
  71. End;
  72. Function WinMaxY: Longint;
  73. {
  74. Current Maximum Y coordinate;
  75. }
  76. Begin
  77. WinMaxY:=(WindMax shr 8) + 1;
  78. End;
  79. Function FullWin:boolean;
  80. {
  81. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  82. }
  83. begin
  84. FullWin:=(WinMinX=1) and (WinMinY=1) and
  85. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  86. end;
  87. {****************************************************************************
  88. Public Crt Functions
  89. ****************************************************************************}
  90. procedure TextMode (Mode: word);
  91. begin
  92. Window (1,1,byte(ScreenWidth),byte(ScreenHeight));
  93. ClrScr;
  94. end;
  95. Procedure TextColor(Color: Byte);
  96. {
  97. Switch foregroundcolor
  98. }
  99. Begin
  100. TextAttr:=(Color and $f) or (TextAttr and $70);
  101. If (Color>15) Then TextAttr:=TextAttr Or Blink;
  102. End;
  103. Procedure TextBackground(Color: Byte);
  104. {
  105. Switch backgroundcolor
  106. }
  107. Begin
  108. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  109. End;
  110. Procedure HighVideo;
  111. {
  112. Set highlighted output.
  113. }
  114. Begin
  115. TextColor(TextAttr Or $08);
  116. End;
  117. Procedure LowVideo;
  118. {
  119. Set normal output
  120. }
  121. Begin
  122. TextColor(TextAttr And $77);
  123. End;
  124. Procedure NormVideo;
  125. {
  126. Set normal back and foregroundcolors.
  127. }
  128. Begin
  129. TextColor(7);
  130. TextBackGround(0);
  131. End;
  132. Procedure GotoXy(X: tcrtcoord; Y: tcrtcoord);
  133. {
  134. Go to coordinates X,Y in the current window.
  135. }
  136. Begin
  137. If (X>0) and (X<=WinMaxX- WinMinX+1) and
  138. (Y>0) and (Y<=WinMaxY-WinMinY+1) Then
  139. Begin
  140. X := X + WinMinX - 1;
  141. Y := Y + WinMinY - 1;
  142. gotorowcol (y-1,x-1);
  143. End;
  144. End;
  145. Procedure Window(X1, Y1, X2, Y2: Byte);
  146. {
  147. Set screen window to the specified coordinates.
  148. }
  149. Begin
  150. if (X1>X2) or (X2>ScreenWidth) or
  151. (Y1>Y2) or (Y2>ScreenHeight) then
  152. exit;
  153. WindMin:=((Y1-1) Shl 8)+(X1-1);
  154. WindMax:=((Y2-1) Shl 8)+(X2-1);
  155. GoToXY(1,1);
  156. End;
  157. Procedure ClrScr;
  158. {
  159. Clear the current window, and set the cursor on 1,1
  160. }
  161. var
  162. rowlen,rows: longint;
  163. begin
  164. if FullWin then
  165. begin
  166. clearscreen; {seems to swich cursor off}
  167. //_DisplayInputCursor;
  168. end else
  169. begin
  170. rowlen := WinMaxX-WinMinX+1;
  171. rows := WinMaxY-WinMinY+1;
  172. FillScreenArea(ScreenHandle,WinMinY-1,WinMinX-1,rows,rowlen,' ',textattr);
  173. end;
  174. Gotoxy(1,1);
  175. end;
  176. Procedure ClrEol;
  177. {
  178. Clear from current position to end of line.
  179. }
  180. var
  181. x,y : longint;
  182. rowlen : word;
  183. Begin
  184. GetScreenCursor(x,y);
  185. if x<WinMaxX then
  186. begin
  187. rowlen := WinMaxX-x+1;
  188. FillScreenArea(ScreenHandle,y-1,x-1,1,rowlen,' ',textattr);
  189. end;
  190. End;
  191. Function WhereX: tcrtcoord;
  192. {
  193. Return current X-position of cursor.
  194. }
  195. Begin
  196. WhereX:=wherecol-WinMinX+1;
  197. End;
  198. Function WhereY: tcrtcoord;
  199. {
  200. Return current Y-position of cursor.
  201. }
  202. Begin
  203. WhereY:=whererow-WinMinY+1;
  204. End;
  205. {*************************************************************************
  206. Keyboard
  207. *************************************************************************}
  208. var
  209. is_last : boolean;
  210. {
  211. function readkey : char;
  212. var
  213. keytype,modifier,scancode : longint;
  214. begin
  215. if is_last then
  216. begin
  217. is_last:=false;
  218. readkey:=getch;
  219. end else
  220. begin
  221. // _SetCtrlCharCheckMode (CheckBreak);
  222. WaitForKey (ScreenHandle);
  223. getkey(keytype,modifer,scancode):longint;
  224. char1 := getch;
  225. if char1 = #0 then is_last := true;
  226. readkey:=char1;
  227. end;
  228. end;
  229. }
  230. function readkey : char; // for now
  231. begin
  232. readkey := char(getcharacter);
  233. end;
  234. function keypressed : boolean;
  235. begin
  236. if is_last then
  237. begin
  238. keypressed:=true;
  239. exit;
  240. end else
  241. keypressed := (kbhit <> 0);
  242. end;
  243. {*************************************************************************
  244. Delay
  245. *************************************************************************}
  246. procedure Delay(MS: Word);
  247. begin
  248. libc.delay (MS);
  249. end;
  250. procedure sound(hz : word);
  251. begin
  252. RingBell;
  253. end;
  254. procedure nosound;
  255. begin
  256. end;
  257. {****************************************************************************
  258. HighLevel Crt Functions
  259. ****************************************************************************}
  260. {procedure removeline(y : longint);
  261. var
  262. fil : word;
  263. rowlen : word;
  264. p : pointer;
  265. begin
  266. fil:=32 or (textattr shl 8);
  267. rowlen:=WinMaxX-WinMinX+1;
  268. GetMem (p, rowlen*2);
  269. y:=WinMinY+y-1;
  270. While (y<=WinMaxY) do
  271. begin
  272. _CopyFromScreenMemory (1,rowlen,p,WinMinX-1,word(y));
  273. _CopyToScreenMemory (1,rowlen,p,WinMinX-1,word(y-1));
  274. inc(y);
  275. end;
  276. FillWord (p^,rowlen,fil);
  277. _CopyToScreenMemory (1,rowlen,p,WinMinX-1,WinMaxY-1);
  278. FreeMem (p, rowlen*2);
  279. end;}
  280. procedure removeline(y : longint);
  281. var rowlen : longint;
  282. begin
  283. rowlen:=WinMaxX-WinMinX+1;
  284. y:=WinMinY+y-1-1;
  285. ScrollScreenArea(ScreenHandle,y,WinMinX-1,WinMaxY-WinMinY+1,rowlen,1,0,SCROLL_UP);
  286. end;
  287. procedure delline;
  288. begin
  289. removeline(wherey);
  290. end;
  291. procedure insline;
  292. var rowlen : longint;
  293. begin
  294. rowlen:=WinMaxX-WinMinX+1;
  295. ScrollScreenArea(ScreenHandle,wherecol,WinMinX-1,WinMaxY-WinMinY+1,rowlen,1,textattr,SCROLL_DOWN);
  296. end;
  297. {****************************************************************************
  298. Extra Crt Functions
  299. ****************************************************************************}
  300. procedure cursoron;
  301. begin
  302. SetCursorStyle(ScreenHandle,CURSOR_NORMAL);
  303. EnableInputCursor(ScreenHandle);
  304. end;
  305. procedure cursoroff;
  306. begin
  307. DisableInputCursor (ScreenHandle);
  308. end;
  309. procedure cursorbig;
  310. begin
  311. SetCursorStyle(ScreenHandle,CURSOR_BLOCK);
  312. EnableInputCursor(ScreenHandle);
  313. end;
  314. {*****************************************************************************
  315. Read and Write routines
  316. *****************************************************************************}
  317. var
  318. CurrX,CurrY : longint;
  319. Procedure WriteChar(c:char);
  320. var st : array [0..1] of char;
  321. begin
  322. case c of
  323. #10 : inc(CurrY);
  324. #13 : CurrX:=WinMinX;
  325. #8 : begin
  326. if CurrX>WinMinX then
  327. dec(CurrX);
  328. end;
  329. #7 : begin { beep }
  330. RingBell;
  331. end;
  332. else
  333. begin
  334. //WriteScreenCharacterAttribute(ScreenHandle,CurrY-1,CurrX-1,c,textattr); {not available in protected mode}
  335. st[0] := c;
  336. st[1] := #0;
  337. OutputToScreenWithAttribute(ScreenHandle,textattr,@st);
  338. inc(CurrX);
  339. end;
  340. end;
  341. if CurrX>WinMaxX then
  342. begin
  343. CurrX:=WinMinX;
  344. inc(CurrY);
  345. end;
  346. while CurrY>WinMaxY do
  347. begin
  348. removeline(1);
  349. dec(CurrY);
  350. end;
  351. end;
  352. Function CrtWrite(var f : textrec):integer;
  353. var
  354. i : longint;
  355. begin
  356. GetScreenCursor(CurrX,CurrY);
  357. for i:=0 to f.bufpos-1 do
  358. WriteChar(f.buffer[i]); { ad: may be better to use a buffer but i think it's fast enough }
  359. gotorowcol (CurrY-1,CurrX-1);
  360. f.bufpos:=0;
  361. CrtWrite:=0;
  362. end;
  363. Function CrtRead(Var F: TextRec): Integer;
  364. procedure BackSpace;
  365. begin
  366. if (f.bufpos>0) and (f.bufpos=f.bufend) then
  367. begin
  368. WriteChar(#8);
  369. WriteChar(' ');
  370. WriteChar(#8);
  371. dec(f.bufpos);
  372. dec(f.bufend);
  373. end;
  374. end;
  375. var
  376. ch : Char;
  377. Begin
  378. GetScreenCursor(CurrX,CurrY);
  379. f.bufpos:=0;
  380. f.bufend:=0;
  381. repeat
  382. if f.bufpos>f.bufend then
  383. f.bufend:=f.bufpos;
  384. gotorowcol (CurrY-1,CurrX-1);
  385. ch:=readkey;
  386. case ch of
  387. #0 : case readkey of
  388. #71 : while f.bufpos>0 do
  389. begin
  390. dec(f.bufpos);
  391. WriteChar(#8);
  392. end;
  393. #75 : if f.bufpos>0 then
  394. begin
  395. dec(f.bufpos);
  396. WriteChar(#8);
  397. end;
  398. #77 : if f.bufpos<f.bufend then
  399. begin
  400. WriteChar(f.bufptr^[f.bufpos]);
  401. inc(f.bufpos);
  402. end;
  403. #79 : while f.bufpos<f.bufend do
  404. begin
  405. WriteChar(f.bufptr^[f.bufpos]);
  406. inc(f.bufpos);
  407. end;
  408. end;
  409. ^S,
  410. #8 : BackSpace;
  411. ^Y,
  412. #27 : begin
  413. f.bufpos:=f.bufend;
  414. while f.bufend>0 do
  415. BackSpace;
  416. end;
  417. #13 : begin
  418. WriteChar(#13);
  419. WriteChar(#10);
  420. f.bufptr^[f.bufend]:=#13;
  421. f.bufptr^[f.bufend+1]:=#10;
  422. inc(f.bufend,2);
  423. break;
  424. end;
  425. #26 : if CheckEOF then
  426. begin
  427. f.bufptr^[f.bufend]:=#26;
  428. inc(f.bufend);
  429. break;
  430. end;
  431. else
  432. begin
  433. if f.bufpos<f.bufsize-2 then
  434. begin
  435. f.buffer[f.bufpos]:=ch;
  436. inc(f.bufpos);
  437. WriteChar(ch);
  438. end;
  439. end;
  440. end;
  441. until false;
  442. f.bufpos:=0;
  443. gotorowcol (CurrY-1,CurrX-1);
  444. CrtRead:=0;
  445. End;
  446. {$Warnings off}
  447. Function CrtReturn(Var F: TextRec): Integer;
  448. Begin
  449. CrtReturn:=0;
  450. end;
  451. {$Warnings on}
  452. Function CrtClose(Var F: TextRec): Integer;
  453. Begin
  454. F.Mode:=fmClosed;
  455. CrtClose:=0;
  456. End;
  457. Function CrtOpen(Var F: TextRec): Integer;
  458. Begin
  459. If F.Mode=fmOutput Then
  460. begin
  461. TextRec(F).InOutFunc:=@CrtWrite;
  462. TextRec(F).FlushFunc:=@CrtWrite;
  463. end
  464. Else
  465. begin
  466. F.Mode:=fmInput;
  467. TextRec(F).InOutFunc:=@CrtRead;
  468. TextRec(F).FlushFunc:=@CrtReturn;
  469. end;
  470. TextRec(F).CloseFunc:=@CrtClose;
  471. CrtOpen:=0;
  472. End;
  473. procedure AssignCrt(var F: Text);
  474. begin
  475. Assign(F,'');
  476. TextRec(F).OpenFunc:=@CrtOpen;
  477. end;
  478. procedure InitScreenMode;
  479. var
  480. s_mode : dword;
  481. begin
  482. getscreenmode (s_mode);
  483. lastmode := s_mode;
  484. end;
  485. var
  486. x,y : longint;
  487. begin
  488. ScreenHandle := getscreenhandle;
  489. { Load startup values }
  490. ScreenWidth:=GetScreenWidth;
  491. ScreenHeight:=GetScreenHeight;
  492. lastmode := CO80;
  493. GetScreenCursor(x,y);
  494. TextColor (LightGray);
  495. TextBackground (Black);
  496. InitScreenMode;
  497. { Redirect the standard output }
  498. assigncrt(Output);
  499. Rewrite(Output);
  500. TextRec(Output).Handle:=StdOutputHandle;
  501. assigncrt(Input);
  502. Reset(Input);
  503. TextRec(Input).Handle:=StdInputHandle;
  504. CheckBreak := FALSE;
  505. CheckEOF := FALSE;
  506. //_SetCtrlCharCheckMode (CheckBreak);
  507. //_SetAutoScreenDestructionMode (TRUE);
  508. end.