crt.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. Borland Pascal 7 Compatible CRT Unit for Go32V1 and Go32V2
  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. { CRT modes }
  16. BW40 = 0; { 40x25 B/W on Color Adapter }
  17. CO40 = 1; { 40x25 Color on Color Adapter }
  18. BW80 = 2; { 80x25 B/W on Color Adapter }
  19. CO80 = 3; { 80x25 Color on Color Adapter }
  20. Mono = 7; { 80x25 on Monochrome Adapter }
  21. Font8x8 = 256; { Add-in for ROM font }
  22. { Mode constants for 3.0 compatibility }
  23. C40 = CO40;
  24. C80 = CO80;
  25. { Foreground and background color constants }
  26. Black = 0;
  27. Blue = 1;
  28. Green = 2;
  29. Cyan = 3;
  30. Red = 4;
  31. Magenta = 5;
  32. Brown = 6;
  33. LightGray = 7;
  34. { Foreground color constants }
  35. DarkGray = 8;
  36. LightBlue = 9;
  37. LightGreen = 10;
  38. LightCyan = 11;
  39. LightRed = 12;
  40. LightMagenta = 13;
  41. Yellow = 14;
  42. White = 15;
  43. { Add-in for blinking }
  44. Blink = 128;
  45. var
  46. { Interface variables }
  47. CheckBreak: Boolean; { Enable Ctrl-Break }
  48. CheckEOF: Boolean; { Enable Ctrl-Z }
  49. DirectVideo: Boolean; { Enable direct video addressing }
  50. CheckSnow: Boolean; { Enable snow filtering }
  51. LastMode: Word; { Current text mode }
  52. TextAttr: Byte; { Current text attribute }
  53. WindMin: Word; { Window upper left coordinates }
  54. WindMax: Word; { Window lower right coordinates }
  55. { Interface procedures }
  56. procedure AssignCrt(var F: Text);
  57. function KeyPressed: Boolean;
  58. function ReadKey: Char;
  59. procedure TextMode(Mode: Integer);
  60. procedure Window(X1,Y1,X2,Y2: Byte);
  61. procedure GotoXY(X,Y: Byte);
  62. function WhereX: Byte;
  63. function WhereY: Byte;
  64. procedure ClrScr;
  65. procedure ClrEol;
  66. procedure InsLine;
  67. procedure DelLine;
  68. procedure TextColor(Color: Byte);
  69. procedure TextBackground(Color: Byte);
  70. procedure LowVideo;
  71. procedure HighVideo;
  72. procedure NormVideo;
  73. procedure Delay(MS: Word);
  74. procedure Sound(Hz: Word);
  75. procedure NoSound;
  76. {Extra Functions}
  77. procedure cursoron;
  78. procedure cursoroff;
  79. procedure cursorbig;
  80. implementation
  81. uses
  82. go32;
  83. {$ASMMODE ATT}
  84. var
  85. DelayCnt, { don't modify this var name, as it is hard coded }
  86. ScreenWidth,
  87. ScreenHeight : longint;
  88. {
  89. definition of textrec is in textrec.inc
  90. }
  91. {$i textrec.inc}
  92. {****************************************************************************
  93. Low level Routines
  94. ****************************************************************************}
  95. procedure setscreenmode(mode : byte);
  96. begin
  97. asm
  98. movb 8(%ebp),%al
  99. xorb %ah,%ah
  100. pushl %ebp
  101. int $0x10
  102. popl %ebp
  103. end;
  104. end;
  105. function GetScreenHeight : longint;
  106. begin
  107. dosmemget($40,$84,getscreenheight,1);
  108. inc(getscreenheight);
  109. end;
  110. function GetScreenWidth : longint;
  111. begin
  112. dosmemget($40,$4a,getscreenwidth,1);
  113. end;
  114. procedure SetScreenCursor(x,y : longint);
  115. begin
  116. asm
  117. movb $0x02,%ah
  118. movb $0,%bh
  119. movb y,%dh
  120. movb x,%dl
  121. subw $0x0101,%dx
  122. pushl %ebp
  123. int $0x10
  124. popl %ebp
  125. end;
  126. end;
  127. procedure GetScreenCursor(var x,y : longint);
  128. begin
  129. x:=0;
  130. y:=0;
  131. dosmemget($40,$50,x,1);
  132. dosmemget($40,$51,y,1);
  133. inc(x);
  134. inc(y);
  135. end;
  136. {****************************************************************************
  137. Helper Routines
  138. ****************************************************************************}
  139. Function WinMinX: Byte;
  140. {
  141. Current Minimum X coordinate
  142. }
  143. Begin
  144. WinMinX:=(WindMin and $ff)+1;
  145. End;
  146. Function WinMinY: Byte;
  147. {
  148. Current Minimum Y Coordinate
  149. }
  150. Begin
  151. WinMinY:=(WindMin shr 8)+1;
  152. End;
  153. Function WinMaxX: Byte;
  154. {
  155. Current Maximum X coordinate
  156. }
  157. Begin
  158. WinMaxX:=(WindMax and $ff)+1;
  159. End;
  160. Function WinMaxY: Byte;
  161. {
  162. Current Maximum Y coordinate;
  163. }
  164. Begin
  165. WinMaxY:=(WindMax shr 8) + 1;
  166. End;
  167. Function FullWin:boolean;
  168. {
  169. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  170. }
  171. begin
  172. FullWin:=(WinMinX=1) and (WinMinY=1) and
  173. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  174. end;
  175. {****************************************************************************
  176. Public Crt Functions
  177. ****************************************************************************}
  178. procedure textmode(mode : integer);
  179. begin
  180. lastmode:=mode;
  181. mode:=mode and $ff;
  182. setscreenmode(mode);
  183. screenwidth:=getscreenwidth;
  184. screenheight:=getscreenheight;
  185. windmin:=0;
  186. windmax:=(screenwidth-1) or ((screenheight-1) shl 8);
  187. end;
  188. Procedure TextColor(Color: Byte);
  189. {
  190. Switch foregroundcolor
  191. }
  192. Begin
  193. TextAttr:=(Color and $f) or (TextAttr and $70);
  194. If (Color>15) Then TextAttr:=TextAttr Or Blink;
  195. End;
  196. Procedure TextBackground(Color: Byte);
  197. {
  198. Switch backgroundcolor
  199. }
  200. Begin
  201. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  202. End;
  203. Procedure HighVideo;
  204. {
  205. Set highlighted output.
  206. }
  207. Begin
  208. TextColor(TextAttr Or $08);
  209. End;
  210. Procedure LowVideo;
  211. {
  212. Set normal output
  213. }
  214. Begin
  215. TextColor(TextAttr And $77);
  216. End;
  217. Procedure NormVideo;
  218. {
  219. Set normal back and foregroundcolors.
  220. }
  221. Begin
  222. TextColor(7);
  223. TextBackGround(0);
  224. End;
  225. Procedure GotoXy(X: Byte; Y: Byte);
  226. {
  227. Go to coordinates X,Y in the current window.
  228. }
  229. Begin
  230. If (X>0) and (X<=WinMaxX- WinMinX+1) and
  231. (Y>0) and (Y<=WinMaxY-WinMinY+1) Then
  232. Begin
  233. Inc(X,WinMinX-1);
  234. Inc(Y,WinMinY-1);
  235. SetScreenCursor(x,y);
  236. End;
  237. End;
  238. Procedure Window(X1, Y1, X2, Y2: Byte);
  239. {
  240. Set screen window to the specified coordinates.
  241. }
  242. Begin
  243. if (X1>X2) or (X2>ScreenWidth) or
  244. (Y1>Y2) or (Y2>ScreenHeight) then
  245. exit;
  246. WindMin:=((Y1-1) Shl 8)+(X1-1);
  247. WindMax:=((Y2-1) Shl 8)+(X2-1);
  248. GoToXY(1,1);
  249. End;
  250. Procedure ClrScr;
  251. {
  252. Clear the current window, and set the cursor on 1,1
  253. }
  254. var
  255. fil : word;
  256. y : longint;
  257. begin
  258. fil:=32 or (textattr shl 8);
  259. if FullWin then
  260. DosmemFillWord($b800,0,ScreenHeight*ScreenWidth,fil)
  261. else
  262. begin
  263. for y:=WinMinY to WinMaxY do
  264. DosmemFillWord($b800,((y-1)*ScreenWidth+(WinMinX-1))*2,WinMaxX-WinMinX+1,fil);
  265. end;
  266. Gotoxy(1,1);
  267. end;
  268. Procedure ClrEol;
  269. {
  270. Clear from current position to end of line.
  271. }
  272. var
  273. x,y : longint;
  274. fil : word;
  275. Begin
  276. GetScreenCursor(x,y);
  277. fil:=32 or (textattr shl 8);
  278. if x<WinMaxX then
  279. DosmemFillword($b800,((y-1)*ScreenWidth+(x-1))*2,WinMaxX-x+1,fil);
  280. End;
  281. Function WhereX: Byte;
  282. {
  283. Return current X-position of cursor.
  284. }
  285. var
  286. x,y : longint;
  287. Begin
  288. GetScreenCursor(x,y);
  289. WhereX:=x-WinMinX+1;
  290. End;
  291. Function WhereY: Byte;
  292. {
  293. Return current Y-position of cursor.
  294. }
  295. var
  296. x,y : longint;
  297. Begin
  298. GetScreenCursor(x,y);
  299. WhereY:=y-WinMinY+1;
  300. End;
  301. {*************************************************************************
  302. KeyBoard
  303. *************************************************************************}
  304. var
  305. is_last : boolean;
  306. last : char;
  307. function readkey : char;
  308. var
  309. char2 : char;
  310. char1 : char;
  311. begin
  312. if is_last then
  313. begin
  314. is_last:=false;
  315. readkey:=last;
  316. end
  317. else
  318. begin
  319. asm
  320. movb $0,%ah
  321. pushl %ebp
  322. int $0x16
  323. popl %ebp
  324. movb %al,char1
  325. movb %ah,char2
  326. end;
  327. if char1=#0 then
  328. begin
  329. is_last:=true;
  330. last:=char2;
  331. end;
  332. readkey:=char1;
  333. end;
  334. end;
  335. function keypressed : boolean;
  336. begin
  337. if is_last then
  338. begin
  339. keypressed:=true;
  340. exit;
  341. end
  342. else
  343. begin
  344. asm
  345. movb $1,%ah
  346. pushl %ebp
  347. int $0x16
  348. popl %ebp
  349. setnz %al
  350. movb %al,__RESULT
  351. end;
  352. end;
  353. end;
  354. {*************************************************************************
  355. Delay
  356. *************************************************************************}
  357. procedure Delayloop;assembler;
  358. asm
  359. .LDelayLoop1:
  360. subl $1,%eax
  361. jc .LDelayLoop2
  362. cmpl %fs:(%edi),%ebx
  363. je .LDelayLoop1
  364. .LDelayLoop2:
  365. end;
  366. procedure initdelay;assembler;
  367. asm
  368. movl $0x46c,%edi
  369. movl $-28,%edx
  370. movl %fs:(%edi),%ebx
  371. .LInitDel1:
  372. cmpl %fs:(%edi),%ebx
  373. je .LInitDel1
  374. movl %fs:(%edi),%ebx
  375. movl %edx,%eax
  376. call DelayLoop
  377. notl %eax
  378. xorl %edx,%edx
  379. movl $55,%ecx
  380. divl %ecx
  381. movl %eax,DelayCnt
  382. end;
  383. procedure Delay(MS: Word);assembler;
  384. asm
  385. movzwl MS,%ecx
  386. jecxz .LDelay2
  387. movl $0x400,%edi
  388. movl DelayCnt,%edx
  389. movl %fs:(%edi),%ebx
  390. .LDelay1:
  391. movl %edx,%eax
  392. call DelayLoop
  393. loop .LDelay1
  394. .LDelay2:
  395. end;
  396. procedure sound(hz : word);
  397. begin
  398. if hz=0 then
  399. begin
  400. nosound;
  401. exit;
  402. end;
  403. asm
  404. movzwl hz,%ecx
  405. movl $1193046,%eax
  406. cltd
  407. divl %ecx
  408. movl %eax,%ecx
  409. movb $0xb6,%al
  410. outb %al,$0x43
  411. movb %cl,%al
  412. outb %al,$0x42
  413. movb %ch,%al
  414. outb %al,$0x42
  415. inb $0x61,%al
  416. orb $0x3,%al
  417. outb %al,$0x61
  418. end ['EAX','ECX','EDX'];
  419. end;
  420. procedure nosound;
  421. begin
  422. asm
  423. inb $0x61,%al
  424. andb $0xfc,%al
  425. outb %al,$0x61
  426. end ['EAX'];
  427. end;
  428. {****************************************************************************
  429. HighLevel Crt Functions
  430. ****************************************************************************}
  431. procedure removeline(y : longint);
  432. var
  433. fil : word;
  434. begin
  435. fil:=32 or (textattr shl 8);
  436. y:=WinMinY+y-1;
  437. While (y<WinMaxY) do
  438. begin
  439. dosmemmove($b800,(y*ScreenWidth+(WinMinX-1))*2,
  440. $b800,((y-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1)*2);
  441. inc(y);
  442. end;
  443. dosmemfillword($b800,((WinMaxY-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1),fil);
  444. end;
  445. procedure delline;
  446. begin
  447. removeline(wherey);
  448. end;
  449. procedure insline;
  450. var
  451. my,y : longint;
  452. fil : word;
  453. begin
  454. fil:=32 or (textattr shl 8);
  455. y:=WhereY;
  456. my:=WinMaxY-WinMinY;
  457. while (my>=y) do
  458. begin
  459. dosmemmove($b800,(((WinMinY+my-1)-1)*ScreenWidth+(WinMinX-1))*2,
  460. $b800,(((WinMinY+my)-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1)*2);
  461. dec(my);
  462. end;
  463. dosmemfillword($b800,(((WinMinY+y-1)-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1),fil);
  464. end;
  465. {****************************************************************************
  466. Extra Crt Functions
  467. ****************************************************************************}
  468. procedure cursoron;
  469. begin
  470. asm
  471. movb $1,%ah
  472. movb $10,%cl
  473. movb $9,%ch
  474. pushl %ebp
  475. int $0x10
  476. popl %ebp
  477. end;
  478. end;
  479. procedure cursoroff;
  480. begin
  481. asm
  482. movb $1,%ah
  483. movb $-1,%cl
  484. movb $-1,%ch
  485. pushl %ebp
  486. int $0x10
  487. popl %ebp
  488. end;
  489. end;
  490. procedure cursorbig;
  491. begin
  492. asm
  493. movb $1,%ah
  494. movw $110,%cx
  495. pushl %ebp
  496. int $0x10
  497. popl %ebp
  498. end;
  499. end;
  500. {*****************************************************************************
  501. Read and Write routines
  502. *****************************************************************************}
  503. var
  504. CurrX,CurrY : longint;
  505. Procedure WriteChar(c:char);
  506. var
  507. chattr : word;
  508. begin
  509. case c of
  510. #10 : inc(CurrY);
  511. #13 : CurrX:=WinMinX;
  512. #8 : begin
  513. if CurrX>WinMinX then
  514. dec(CurrX);
  515. end;
  516. #7 : begin { beep }
  517. end;
  518. else
  519. begin
  520. chattr:=(textattr shl 8) or byte(c);
  521. dosmemput($b800,((CurrY-1)*ScreenWidth+(CurrX-1))*2,chattr,2);
  522. inc(CurrX);
  523. end;
  524. end;
  525. if CurrX>WinMaxX then
  526. begin
  527. CurrX:=WinMinX;
  528. inc(CurrY);
  529. end;
  530. while CurrY>WinMaxY do
  531. begin
  532. removeline(1);
  533. dec(CurrY);
  534. end;
  535. end;
  536. Function CrtWrite(var f : textrec):integer;
  537. var
  538. i : longint;
  539. begin
  540. GetScreenCursor(CurrX,CurrY);
  541. for i:=0 to f.bufpos-1 do
  542. WriteChar(f.buffer[i]);
  543. SetScreenCursor(CurrX,CurrY);
  544. f.bufpos:=0;
  545. CrtWrite:=0;
  546. end;
  547. Function CrtRead(Var F: TextRec): Integer;
  548. procedure BackSpace;
  549. begin
  550. if (f.bufpos>0) and (f.bufpos=f.bufend) then
  551. begin
  552. WriteChar(#8);
  553. WriteChar(' ');
  554. WriteChar(#8);
  555. dec(f.bufpos);
  556. dec(f.bufend);
  557. end;
  558. end;
  559. var
  560. ch : Char;
  561. Begin
  562. GetScreenCursor(CurrX,CurrY);
  563. f.bufpos:=0;
  564. f.bufend:=0;
  565. repeat
  566. if f.bufpos>f.bufend then
  567. f.bufend:=f.bufpos;
  568. SetScreenCursor(CurrX,CurrY);
  569. ch:=readkey;
  570. case ch of
  571. #0 : case readkey of
  572. #71 : while f.bufpos>0 do
  573. begin
  574. dec(f.bufpos);
  575. WriteChar(#8);
  576. end;
  577. #75 : if f.bufpos>0 then
  578. begin
  579. dec(f.bufpos);
  580. WriteChar(#8);
  581. end;
  582. #77 : if f.bufpos<f.bufend then
  583. begin
  584. WriteChar(f.bufptr^[f.bufpos]);
  585. inc(f.bufpos);
  586. end;
  587. #79 : while f.bufpos<f.bufend do
  588. begin
  589. WriteChar(f.bufptr^[f.bufpos]);
  590. inc(f.bufpos);
  591. end;
  592. end;
  593. ^S,
  594. #8 : BackSpace;
  595. ^Y,
  596. #27 : begin
  597. f.bufpos:=f.bufend;
  598. while f.bufend>0 do
  599. BackSpace;
  600. end;
  601. #13 : begin
  602. WriteChar(#13);
  603. WriteChar(#10);
  604. f.bufptr^[f.bufend]:=#13;
  605. f.bufptr^[f.bufend+1]:=#10;
  606. inc(f.bufend,2);
  607. break;
  608. end;
  609. #26 : if CheckEOF then
  610. begin
  611. f.bufptr^[f.bufend]:=#26;
  612. inc(f.bufend);
  613. break;
  614. end;
  615. else
  616. begin
  617. if f.bufpos<f.bufsize-2 then
  618. begin
  619. f.buffer[f.bufpos]:=ch;
  620. inc(f.bufpos);
  621. WriteChar(ch);
  622. end;
  623. end;
  624. end;
  625. until false;
  626. f.bufpos:=0;
  627. SetScreenCursor(CurrX,CurrY);
  628. CrtRead:=0;
  629. End;
  630. Function CrtReturn:Integer;
  631. Begin
  632. CrtReturn:=0;
  633. end;
  634. Function CrtClose(Var F: TextRec): Integer;
  635. Begin
  636. F.Mode:=fmClosed;
  637. CrtClose:=0;
  638. End;
  639. Function CrtOpen(Var F: TextRec): Integer;
  640. Begin
  641. If F.Mode=fmOutput Then
  642. begin
  643. TextRec(F).InOutFunc:=@CrtWrite;
  644. TextRec(F).FlushFunc:=@CrtWrite;
  645. end
  646. Else
  647. begin
  648. F.Mode:=fmInput;
  649. TextRec(F).InOutFunc:=@CrtRead;
  650. TextRec(F).FlushFunc:=@CrtReturn;
  651. end;
  652. TextRec(F).CloseFunc:=@CrtClose;
  653. CrtOpen:=0;
  654. End;
  655. procedure AssignCrt(var F: Text);
  656. begin
  657. Assign(F,'');
  658. TextRec(F).OpenFunc:=@CrtOpen;
  659. end;
  660. var
  661. x,y : longint;
  662. begin
  663. { Load startup values }
  664. ScreenWidth:=GetScreenWidth;
  665. ScreenHeight:=GetScreenHeight;
  666. WindMax:=(ScreenWidth-1) or ((ScreenHeight-1) shl 8);
  667. { Load TextAttr }
  668. GetScreenCursor(x,y);
  669. dosmemget($b800,((y-1)*ScreenWidth+(x-1))*2+1,TextAttr,1);
  670. dosmemget($40,$49,lastmode,1);
  671. { Redirect the standard output }
  672. assigncrt(Output);
  673. Rewrite(Output);
  674. TextRec(Output).Handle:=StdOutputHandle;
  675. assigncrt(Input);
  676. Reset(Input);
  677. TextRec(Input).Handle:=StdInputHandle;
  678. { Calculates delay calibration }
  679. initdelay;
  680. end.
  681. {
  682. $Log$
  683. Revision 1.2 2000-07-13 11:33:38 michael
  684. + removed logs
  685. }