crt.pp 12 KB

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