crt.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. {
  2. $Id$
  3. Copyright (c) 1999-2001 by the Free Pascal development team.
  4. Borland Pascal 7 Compatible CRT Unit for Netware, tested with
  5. Netware 4.11 and 5.1
  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. {At initialization time, AutoScreenDestructionMode is set to true so after program termination
  13. no "press any key to close screen" is displayed. Also check for ctrl-c in readkey is disabled.
  14. To enable ctrl-c check, set CheckBreak to true before calling ReadKey.
  15. 2001/04/13 armin: first version for netware, compilable, completely untested
  16. 2001/04/14 armin: tested, seems to work
  17. TextMode, Sound and NoSound are dummys, don't know how to
  18. implement that for netware
  19. }
  20. unit crt;
  21. interface
  22. const
  23. { CRT modes }
  24. BW40 = 0; { 40x25 B/W on Color Adapter }
  25. CO40 = 1; { 40x25 Color on Color Adapter }
  26. BW80 = 2; { 80x25 B/W on Color Adapter }
  27. CO80 = 3; { 80x25 Color on Color Adapter }
  28. Mono = 7; { 80x25 on Monochrome Adapter }
  29. Font8x8 = 256; { Add-in for ROM font }
  30. { Mode constants for 3.0 compatibility }
  31. C40 = CO40;
  32. C80 = CO80;
  33. { Foreground and background color constants }
  34. Black = 0;
  35. Blue = 1;
  36. Green = 2;
  37. Cyan = 3;
  38. Red = 4;
  39. Magenta = 5;
  40. Brown = 6;
  41. LightGray = 7;
  42. { Foreground color constants }
  43. DarkGray = 8;
  44. LightBlue = 9;
  45. LightGreen = 10;
  46. LightCyan = 11;
  47. LightRed = 12;
  48. LightMagenta = 13;
  49. Yellow = 14;
  50. White = 15;
  51. { Add-in for blinking }
  52. Blink = 128;
  53. var
  54. { Interface variables }
  55. CheckBreak: Boolean; { Enable Ctrl-Break, supported on Netware }
  56. CheckEOF: Boolean; { Enable Ctrl-Z, supported on Netware }
  57. DirectVideo: Boolean; { Enable direct video addressing }
  58. CheckSnow: Boolean; { Enable snow filtering }
  59. LastMode: Word; { Current text mode }
  60. TextAttr: Byte; { Current text attribute }
  61. WindMin: Word; { Window upper left coordinates }
  62. WindMax: Word; { Window lower right coordinates }
  63. Const
  64. ScreenHeight : longint=25;
  65. ScreenWidth : longint=80;
  66. ConsoleMaxX=80;
  67. ConsoleMaxY=25;
  68. { Interface procedures }
  69. procedure AssignCrt(var F: Text);
  70. function KeyPressed: Boolean;
  71. function ReadKey: Char;
  72. procedure TextMode(Mode: Integer); {dummy function}
  73. procedure Window(X1,Y1,X2,Y2: Byte);
  74. procedure GotoXY(X,Y: Byte);
  75. function WhereX: Byte;
  76. function WhereY: Byte;
  77. procedure ClrScr;
  78. procedure ClrEol;
  79. procedure InsLine;
  80. procedure DelLine;
  81. procedure TextColor(Color: Byte);
  82. procedure TextBackground(Color: Byte);
  83. procedure LowVideo;
  84. procedure HighVideo;
  85. procedure NormVideo;
  86. procedure Delay(MS: Word);
  87. procedure Sound(Hz: Word); {dummy function}
  88. procedure NoSound; {dummy function}
  89. {Extra Functions}
  90. procedure cursoron;
  91. procedure cursoroff;
  92. procedure cursorbig;
  93. implementation
  94. {$I nwsys.inc}
  95. {$ASMMODE ATT}
  96. var
  97. DelayCnt,
  98. // ScreenWidth,
  99. // ScreenHeight : longint;
  100. VidSeg : Word;
  101. {
  102. definition of textrec is in textrec.inc
  103. }
  104. {$i textrec.inc}
  105. {****************************************************************************
  106. Low level Routines
  107. ****************************************************************************}
  108. procedure setscreenmode(mode : byte);
  109. begin
  110. end;
  111. function GetScreenHeight : longint;
  112. VAR Height, Width : WORD;
  113. begin
  114. _GetSizeOfScreen (Height,Width);
  115. GetScreenHeight := Height;
  116. end;
  117. function GetScreenWidth : longint;
  118. VAR Height, Width : WORD;
  119. begin
  120. _GetSizeOfScreen (Height,Width);
  121. GetScreenWidth := Width;
  122. end;
  123. procedure GetScreenCursor(var x,y : longint);
  124. begin
  125. x := _wherex+1;
  126. y := _wherey+1;
  127. end;
  128. {****************************************************************************
  129. Helper Routines
  130. ****************************************************************************}
  131. Function WinMinX: Longint;
  132. {
  133. Current Minimum X coordinate
  134. }
  135. Begin
  136. WinMinX:=(WindMin and $ff)+1;
  137. End;
  138. Function WinMinY: Longint;
  139. {
  140. Current Minimum Y Coordinate
  141. }
  142. Begin
  143. WinMinY:=(WindMin shr 8)+1;
  144. End;
  145. Function WinMaxX: Longint;
  146. {
  147. Current Maximum X coordinate
  148. }
  149. Begin
  150. WinMaxX:=(WindMax and $ff)+1;
  151. End;
  152. Function WinMaxY: Longint;
  153. {
  154. Current Maximum Y coordinate;
  155. }
  156. Begin
  157. WinMaxY:=(WindMax shr 8) + 1;
  158. End;
  159. Function FullWin:boolean;
  160. {
  161. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  162. }
  163. begin
  164. FullWin:=(WinMinX=1) and (WinMinY=1) and
  165. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  166. end;
  167. {****************************************************************************
  168. Public Crt Functions
  169. ****************************************************************************}
  170. procedure textmode(mode : integer);
  171. begin
  172. Window (1,1,ScreenWidth,ScreenHeight);
  173. ClrScr;
  174. end;
  175. Procedure TextColor(Color: Byte);
  176. {
  177. Switch foregroundcolor
  178. }
  179. Begin
  180. TextAttr:=(Color and $f) or (TextAttr and $70);
  181. If (Color>15) Then TextAttr:=TextAttr Or Blink;
  182. End;
  183. Procedure TextBackground(Color: Byte);
  184. {
  185. Switch backgroundcolor
  186. }
  187. Begin
  188. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  189. End;
  190. Procedure HighVideo;
  191. {
  192. Set highlighted output.
  193. }
  194. Begin
  195. TextColor(TextAttr Or $08);
  196. End;
  197. Procedure LowVideo;
  198. {
  199. Set normal output
  200. }
  201. Begin
  202. TextColor(TextAttr And $77);
  203. End;
  204. Procedure NormVideo;
  205. {
  206. Set normal back and foregroundcolors.
  207. }
  208. Begin
  209. TextColor(7);
  210. TextBackGround(0);
  211. End;
  212. Procedure GotoXy(X: Byte; Y: Byte);
  213. {
  214. Go to coordinates X,Y in the current window.
  215. }
  216. Begin
  217. If (X>0) and (X<=WinMaxX- WinMinX+1) and
  218. (Y>0) and (Y<=WinMaxY-WinMinY+1) Then
  219. Begin
  220. X := X + WinMinX - 1;
  221. Y := Y + WinMinY - 1;
  222. _GotoXY (x-1,y-1);
  223. End;
  224. End;
  225. Procedure Window(X1, Y1, X2, Y2: Byte);
  226. {
  227. Set screen window to the specified coordinates.
  228. }
  229. Begin
  230. if (X1>X2) or (X2>ScreenWidth) or
  231. (Y1>Y2) or (Y2>ScreenHeight) then
  232. exit;
  233. WindMin:=((Y1-1) Shl 8)+(X1-1);
  234. WindMax:=((Y2-1) Shl 8)+(X2-1);
  235. GoToXY(1,1);
  236. End;
  237. Procedure ClrScr;
  238. {
  239. Clear the current window, and set the cursor on 1,1
  240. }
  241. var
  242. fil : word;
  243. y : longint;
  244. p : pointer;
  245. rowlen,rows: longint;
  246. begin
  247. fil:=32 or (textattr shl 8);
  248. if FullWin then
  249. begin
  250. _clrscr; {seems to swich cursor off}
  251. _DisplayInputCursor;
  252. end else
  253. begin
  254. rowlen := WinMaxX-WinMinX+1;
  255. rows := WinMaxY-WinMinY+1;
  256. GetMem (p, rows * rowlen * 2);
  257. FillWord (p^, rows * rowlen, fil);
  258. _CopyToScreenMemory (rows,rowlen,p,WinMinX-1,WinMinY-1);
  259. FreeMem (p, rows * rowlen * 2);
  260. end;
  261. Gotoxy(1,1);
  262. end;
  263. Procedure ClrEol;
  264. {
  265. Clear from current position to end of line.
  266. }
  267. var
  268. x,y : longint;
  269. fil : word;
  270. rowlen : word;
  271. p : pointer;
  272. Begin
  273. GetScreenCursor(x,y);
  274. fil:=32 or (textattr shl 8);
  275. if x<WinMaxX then
  276. begin
  277. rowlen := WinMaxX-x+1;
  278. GetMem (p, rowlen * 2);
  279. FillWord (p^, rowlen, fil);
  280. _CopyToScreenMemory (1,rowlen,p,x-1,y-1);
  281. FreeMem (p, rowlen * 2);
  282. end;
  283. End;
  284. Function WhereX: Byte;
  285. {
  286. Return current X-position of cursor.
  287. }
  288. var
  289. x,y : longint;
  290. Begin
  291. GetScreenCursor(x,y);
  292. WhereX:=x-WinMinX+1;
  293. End;
  294. Function WhereY: Byte;
  295. {
  296. Return current Y-position of cursor.
  297. }
  298. var
  299. x,y : longint;
  300. Begin
  301. GetScreenCursor(x,y);
  302. WhereY:=y-WinMinY+1;
  303. End;
  304. {*************************************************************************
  305. Keyboard
  306. *************************************************************************}
  307. var
  308. is_last : boolean;
  309. function readkey : char;
  310. var
  311. char1 : char;
  312. begin
  313. if is_last then
  314. begin
  315. is_last:=false;
  316. readkey:=_getch;
  317. end else
  318. begin
  319. _SetCtrlCharCheckMode (CheckBreak);
  320. char1 := _getch;
  321. if char1 = #0 then is_last := true;
  322. readkey:=char1;
  323. end;
  324. end;
  325. function keypressed : boolean;
  326. begin
  327. if is_last then
  328. begin
  329. keypressed:=true;
  330. exit;
  331. end else
  332. keypressed := (_kbhit <> 0);
  333. end;
  334. {*************************************************************************
  335. Delay
  336. *************************************************************************}
  337. procedure Delay(MS: Word);
  338. begin
  339. _delay (MS);
  340. end;
  341. procedure sound(hz : word);
  342. begin
  343. _RingTheBell;
  344. end;
  345. procedure nosound;
  346. begin
  347. end;
  348. {****************************************************************************
  349. HighLevel Crt Functions
  350. ****************************************************************************}
  351. procedure removeline(y : longint);
  352. var
  353. fil : word;
  354. rowlen : word;
  355. p : pointer;
  356. begin
  357. fil:=32 or (textattr shl 8);
  358. rowlen:=WinMaxX-WinMinX+1;
  359. GetMem (p, rowlen*2);
  360. y:=WinMinY+y-1;
  361. While (y<=WinMaxY) do
  362. begin
  363. _CopyFromScreenMemory (1,rowlen,p,WinMinX-1,y);
  364. _CopyToScreenMemory (1,rowlen,p,WinMinX-1,y-1);
  365. inc(y);
  366. end;
  367. FillWord (p^,rowlen,fil);
  368. _CopyToScreenMemory (1,rowlen,p,WinMinX-1,WinMaxY-1);
  369. FreeMem (p, rowlen*2);
  370. end;
  371. procedure delline;
  372. begin
  373. removeline(wherey);
  374. end;
  375. procedure insline;
  376. var
  377. my,y : longint;
  378. fil : word;
  379. rowlen,x : word;
  380. p : pointer;
  381. begin
  382. fil:=32 or (textattr shl 8);
  383. y:=WhereY-1;
  384. my:=WinMaxY-WinMinY;
  385. rowlen := WinMaxX-WinMinX+1;
  386. GetMem (p, rowlen*2);
  387. while (my>=y) do
  388. begin
  389. _CopyFromScreenMemory (1,rowlen,p,WinMinX-1,my);
  390. _CopyToScreenMemory (1,rowlen,p,WinMinX-1,my+1);
  391. dec(my);
  392. end;
  393. FillWord (p^,rowlen,fil);
  394. _CopyToScreenMemory (1,rowlen,p,x,y);
  395. FreeMem (p, rowlen*2);
  396. end;
  397. {****************************************************************************
  398. Extra Crt Functions
  399. ****************************************************************************}
  400. procedure cursoron;
  401. begin
  402. if _IsColorMonitor <> 0 then
  403. _SetCursorShape (9,$A)
  404. else
  405. _SetCursorShape ($B,$D);
  406. _DisplayInputCursor;
  407. end;
  408. procedure cursoroff;
  409. begin
  410. _HideInputCursor;
  411. end;
  412. procedure cursorbig;
  413. begin
  414. _SetCursorShape (1,$A);
  415. _DisplayInputCursor;
  416. end;
  417. {*****************************************************************************
  418. Read and Write routines
  419. *****************************************************************************}
  420. var
  421. CurrX,CurrY : longint;
  422. Procedure WriteChar(c:char);
  423. var
  424. w : word;
  425. begin
  426. case c of
  427. #10 : inc(CurrY);
  428. #13 : CurrX:=WinMinX;
  429. #8 : begin
  430. if CurrX>WinMinX then
  431. dec(CurrX);
  432. end;
  433. #7 : begin { beep }
  434. _RingTheBell;
  435. end;
  436. else
  437. begin
  438. w:=(textattr shl 8) or byte(c);
  439. _CopyToScreenMemory (1,1,@w,CurrX-1,CurrY-1);
  440. inc(CurrX);
  441. end;
  442. end;
  443. if CurrX>WinMaxX then
  444. begin
  445. CurrX:=WinMinX;
  446. inc(CurrY);
  447. end;
  448. while CurrY>WinMaxY do
  449. begin
  450. removeline(1);
  451. dec(CurrY);
  452. end;
  453. end;
  454. Function CrtWrite(var f : textrec):integer;
  455. var
  456. i : longint;
  457. begin
  458. GetScreenCursor(CurrX,CurrY);
  459. for i:=0 to f.bufpos-1 do
  460. WriteChar(f.buffer[i]); { ad: may be better to use a buffer but i think it's fast enough }
  461. _GotoXY (CurrX-1,CurrY-1);
  462. f.bufpos:=0;
  463. CrtWrite:=0;
  464. end;
  465. Function CrtRead(Var F: TextRec): Integer;
  466. procedure BackSpace;
  467. begin
  468. if (f.bufpos>0) and (f.bufpos=f.bufend) then
  469. begin
  470. WriteChar(#8);
  471. WriteChar(' ');
  472. WriteChar(#8);
  473. dec(f.bufpos);
  474. dec(f.bufend);
  475. end;
  476. end;
  477. var
  478. ch : Char;
  479. Begin
  480. GetScreenCursor(CurrX,CurrY);
  481. f.bufpos:=0;
  482. f.bufend:=0;
  483. repeat
  484. if f.bufpos>f.bufend then
  485. f.bufend:=f.bufpos;
  486. _GotoXY (CurrX-1,CurrY-1);
  487. ch:=readkey;
  488. case ch of
  489. #0 : case readkey of
  490. #71 : while f.bufpos>0 do
  491. begin
  492. dec(f.bufpos);
  493. WriteChar(#8);
  494. end;
  495. #75 : if f.bufpos>0 then
  496. begin
  497. dec(f.bufpos);
  498. WriteChar(#8);
  499. end;
  500. #77 : if f.bufpos<f.bufend then
  501. begin
  502. WriteChar(f.bufptr^[f.bufpos]);
  503. inc(f.bufpos);
  504. end;
  505. #79 : while f.bufpos<f.bufend do
  506. begin
  507. WriteChar(f.bufptr^[f.bufpos]);
  508. inc(f.bufpos);
  509. end;
  510. end;
  511. ^S,
  512. #8 : BackSpace;
  513. ^Y,
  514. #27 : begin
  515. f.bufpos:=f.bufend;
  516. while f.bufend>0 do
  517. BackSpace;
  518. end;
  519. #13 : begin
  520. WriteChar(#13);
  521. WriteChar(#10);
  522. f.bufptr^[f.bufend]:=#13;
  523. f.bufptr^[f.bufend+1]:=#10;
  524. inc(f.bufend,2);
  525. break;
  526. end;
  527. #26 : if CheckEOF then
  528. begin
  529. f.bufptr^[f.bufend]:=#26;
  530. inc(f.bufend);
  531. break;
  532. end;
  533. else
  534. begin
  535. if f.bufpos<f.bufsize-2 then
  536. begin
  537. f.buffer[f.bufpos]:=ch;
  538. inc(f.bufpos);
  539. WriteChar(ch);
  540. end;
  541. end;
  542. end;
  543. until false;
  544. f.bufpos:=0;
  545. _GotoXY (CurrX-1,CurrY-1);
  546. CrtRead:=0;
  547. End;
  548. Function CrtReturn(Var F: TextRec): Integer;
  549. Begin
  550. CrtReturn:=0;
  551. end;
  552. Function CrtClose(Var F: TextRec): Integer;
  553. Begin
  554. F.Mode:=fmClosed;
  555. CrtClose:=0;
  556. End;
  557. Function CrtOpen(Var F: TextRec): Integer;
  558. Begin
  559. If F.Mode=fmOutput Then
  560. begin
  561. TextRec(F).InOutFunc:=@CrtWrite;
  562. TextRec(F).FlushFunc:=@CrtWrite;
  563. end
  564. Else
  565. begin
  566. F.Mode:=fmInput;
  567. TextRec(F).InOutFunc:=@CrtRead;
  568. TextRec(F).FlushFunc:=@CrtReturn;
  569. end;
  570. TextRec(F).CloseFunc:=@CrtClose;
  571. CrtOpen:=0;
  572. End;
  573. procedure AssignCrt(var F: Text);
  574. begin
  575. Assign(F,'');
  576. TextRec(F).OpenFunc:=@CrtOpen;
  577. end;
  578. var
  579. x,y : longint;
  580. begin
  581. { Load startup values }
  582. ScreenWidth:=GetScreenWidth;
  583. ScreenHeight:=GetScreenHeight;
  584. lastmode := CO80;
  585. TextMode (lastmode);
  586. GetScreenCursor(x,y);
  587. if screenheight>25 then
  588. lastmode:=lastmode or $100;
  589. TextColor (LightGray);
  590. TextBackground (Black);
  591. { Redirect the standard output }
  592. assigncrt(Output);
  593. Rewrite(Output);
  594. TextRec(Output).Handle:=StdOutputHandle;
  595. assigncrt(Input);
  596. Reset(Input);
  597. TextRec(Input).Handle:=StdInputHandle;
  598. CheckBreak := FALSE;
  599. CheckEOF := FALSE;
  600. _SetCtrlCharCheckMode (CheckBreak);
  601. _SetAutoScreenDestructionMode (TRUE);
  602. end.