crt.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  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 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. ScreenWidth,
  56. ScreenHeight : longint;
  57. { Interface procedures }
  58. procedure AssignCrt(var F: Text);
  59. function KeyPressed: Boolean;
  60. function ReadKey: Char;
  61. procedure TextMode(Mode: Integer);
  62. procedure Window(X1,Y1,X2,Y2: Byte);
  63. procedure GotoXY(X,Y: Byte);
  64. function WhereX: Byte;
  65. function WhereY: Byte;
  66. procedure ClrScr;
  67. procedure ClrEol;
  68. procedure InsLine;
  69. procedure DelLine;
  70. procedure TextColor(Color: Byte);
  71. procedure TextBackground(Color: Byte);
  72. procedure LowVideo;
  73. procedure HighVideo;
  74. procedure NormVideo;
  75. procedure Delay(MS: Word);
  76. procedure Sound(Hz: Word);
  77. procedure NoSound;
  78. {Extra Functions}
  79. procedure cursoron;
  80. procedure cursoroff;
  81. procedure cursorbig;
  82. implementation
  83. uses
  84. go32;
  85. {$ASMMODE ATT}
  86. var
  87. DelayCnt : Longint;
  88. VidSeg : Word;
  89. {
  90. definition of textrec is in textrec.inc
  91. }
  92. {$i textrec.inc}
  93. {****************************************************************************
  94. Low level Routines
  95. ****************************************************************************}
  96. procedure setscreenmode(mode : byte);
  97. var
  98. regs : trealregs;
  99. begin
  100. regs.realeax:=mode;
  101. realintr($10,regs);
  102. end;
  103. function GetScreenHeight : longint;
  104. begin
  105. getscreenheight:=mem[$40:$84]+1;
  106. If mem[$40:$84]=0 then
  107. getscreenheight := 25;
  108. end;
  109. function GetScreenWidth : longint;
  110. begin
  111. getscreenwidth:=memw[$40:$4a];
  112. end;
  113. procedure SetScreenCursor(x,y : longint);
  114. var
  115. regs : trealregs;
  116. begin
  117. regs.realeax:=$0200;
  118. regs.realebx:=0;
  119. regs.realedx:=(y-1) shl 8+(x-1);
  120. realintr($10,regs);
  121. end;
  122. procedure GetScreenCursor(var x,y : longint);
  123. begin
  124. x:=mem[$40:$50]+1;
  125. y:=mem[$40:$51]+1;
  126. end;
  127. {****************************************************************************
  128. Helper Routines
  129. ****************************************************************************}
  130. Function WinMinX: Byte;
  131. {
  132. Current Minimum X coordinate
  133. }
  134. Begin
  135. WinMinX:=(WindMin and $ff)+1;
  136. End;
  137. Function WinMinY: Byte;
  138. {
  139. Current Minimum Y Coordinate
  140. }
  141. Begin
  142. WinMinY:=(WindMin shr 8)+1;
  143. End;
  144. Function WinMaxX: Byte;
  145. {
  146. Current Maximum X coordinate
  147. }
  148. Begin
  149. WinMaxX:=(WindMax and $ff)+1;
  150. End;
  151. Function WinMaxY: Byte;
  152. {
  153. Current Maximum Y coordinate;
  154. }
  155. Begin
  156. WinMaxY:=(WindMax shr 8) + 1;
  157. End;
  158. Function FullWin:boolean;
  159. {
  160. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  161. }
  162. begin
  163. FullWin:=(WinMinX=1) and (WinMinY=1) and
  164. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  165. end;
  166. {****************************************************************************
  167. Public Crt Functions
  168. ****************************************************************************}
  169. procedure textmode(mode : integer);
  170. var
  171. regs : trealregs;
  172. begin
  173. lastmode:=mode;
  174. mode:=mode and $ff;
  175. setscreenmode(mode);
  176. { set 8x8 font }
  177. if (lastmode and $100)<>0 then
  178. begin
  179. regs.realeax:=$1112;
  180. regs.realebx:=$0;
  181. realintr($10,regs);
  182. end;
  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(VidSeg,0,ScreenHeight*ScreenWidth,fil)
  261. else
  262. begin
  263. for y:=WinMinY to WinMaxY do
  264. DosmemFillWord(VidSeg,((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(VidSeg,((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. regs : trealregs;
  312. begin
  313. if is_last then
  314. begin
  315. is_last:=false;
  316. readkey:=last;
  317. end
  318. else
  319. begin
  320. regs.ah:=$10;
  321. realintr($16,regs);
  322. if (regs.al=$e0) and (regs.ah<>0) then
  323. regs.al:=0;
  324. char1:=chr(regs.al);
  325. char2:=chr(regs.ah);
  326. if char1=#0 then
  327. begin
  328. is_last:=true;
  329. last:=char2;
  330. end;
  331. readkey:=char1;
  332. end;
  333. end;
  334. function keypressed : boolean;
  335. var
  336. regs : trealregs;
  337. begin
  338. if is_last then
  339. begin
  340. keypressed:=true;
  341. exit;
  342. end
  343. else
  344. begin
  345. regs.ah:=$11;
  346. realintr($16,regs);
  347. keypressed:=((regs.realflags and zeroflag) = 0);
  348. end;
  349. end;
  350. {*************************************************************************
  351. Delay
  352. *************************************************************************}
  353. procedure Delayloop;assembler;
  354. asm
  355. .LDelayLoop1:
  356. subl $1,%eax
  357. jc .LDelayLoop2
  358. cmpl %fs:(%edi),%ebx
  359. je .LDelayLoop1
  360. .LDelayLoop2:
  361. end;
  362. procedure initdelay;assembler;
  363. asm
  364. { for some reason, using int $31/ax=$901 doesn't work here }
  365. { and interrupts are always disabled at this point when }
  366. { running a program inside gdb(pas). Web bug 1345 (JM) }
  367. sti
  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. inb $0x61,%al
  410. testb $0x3,%al
  411. jnz .Lsound_next
  412. orb $0x3,%al
  413. outb %al,$0x61
  414. movb $0xb6,%al
  415. outb %al,$0x43
  416. .Lsound_next:
  417. movb %cl,%al
  418. outb %al,$0x42
  419. movb %ch,%al
  420. outb %al,$0x42
  421. end ['EAX','ECX','EDX'];
  422. end;
  423. procedure nosound;
  424. begin
  425. asm
  426. inb $0x61,%al
  427. andb $0xfc,%al
  428. outb %al,$0x61
  429. end ['EAX'];
  430. end;
  431. {****************************************************************************
  432. HighLevel Crt Functions
  433. ****************************************************************************}
  434. procedure removeline(y : longint);
  435. var
  436. fil : word;
  437. begin
  438. fil:=32 or (textattr shl 8);
  439. y:=WinMinY+y-1;
  440. While (y<WinMaxY) do
  441. begin
  442. dosmemmove(VidSeg,(y*ScreenWidth+(WinMinX-1))*2,
  443. VidSeg,((y-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1)*2);
  444. inc(y);
  445. end;
  446. dosmemfillword(VidSeg,((WinMaxY-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1),fil);
  447. end;
  448. procedure delline;
  449. begin
  450. removeline(wherey);
  451. end;
  452. procedure insline;
  453. var
  454. my,y : longint;
  455. fil : word;
  456. begin
  457. fil:=32 or (textattr shl 8);
  458. y:=WhereY;
  459. my:=WinMaxY-WinMinY;
  460. while (my>=y) do
  461. begin
  462. dosmemmove(VidSeg,(((WinMinY+my-1)-1)*ScreenWidth+(WinMinX-1))*2,
  463. VidSeg,(((WinMinY+my)-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1)*2);
  464. dec(my);
  465. end;
  466. dosmemfillword(VidSeg,(((WinMinY+y-1)-1)*ScreenWidth+(WinMinX-1))*2,(WinMaxX-WinMinX+1),fil);
  467. end;
  468. {****************************************************************************
  469. Extra Crt Functions
  470. ****************************************************************************}
  471. procedure cursoron;
  472. var
  473. regs : trealregs;
  474. begin
  475. regs.realeax:=$0100;
  476. regs.realecx:=$90A;
  477. If VidSeg=$b800 then
  478. regs.realecx:=$90A
  479. else
  480. regs.realecx:=$b0d;
  481. realintr($10,regs);
  482. end;
  483. procedure cursoroff;
  484. var
  485. regs : trealregs;
  486. begin
  487. regs.realeax:=$0100;
  488. regs.realecx:=$ffff;
  489. realintr($10,regs);
  490. end;
  491. procedure cursorbig;
  492. var
  493. regs : trealregs;
  494. begin
  495. regs.realeax:=$0100;
  496. regs.realecx:=$10A;
  497. realintr($10,regs);
  498. end;
  499. {*****************************************************************************
  500. Read and Write routines
  501. *****************************************************************************}
  502. var
  503. CurrX,CurrY : longint;
  504. Procedure WriteChar(c:char);
  505. var
  506. regs : trealregs;
  507. begin
  508. case c of
  509. #10 : inc(CurrY);
  510. #13 : CurrX:=WinMinX;
  511. #8 : begin
  512. if CurrX>WinMinX then
  513. dec(CurrX);
  514. end;
  515. #7 : begin { beep }
  516. regs.dl:=7;
  517. regs.ah:=2;
  518. realintr($21,regs);
  519. end;
  520. else
  521. begin
  522. memw[VidSeg:((CurrY-1)*ScreenWidth+(CurrX-1))*2]:=(textattr shl 8) or byte(c);
  523. inc(CurrX);
  524. end;
  525. end;
  526. if CurrX>WinMaxX then
  527. begin
  528. CurrX:=WinMinX;
  529. inc(CurrY);
  530. end;
  531. while CurrY>WinMaxY do
  532. begin
  533. removeline(1);
  534. dec(CurrY);
  535. end;
  536. end;
  537. Function CrtWrite(var f : textrec):integer;
  538. var
  539. i : longint;
  540. begin
  541. GetScreenCursor(CurrX,CurrY);
  542. for i:=0 to f.bufpos-1 do
  543. WriteChar(f.buffer[i]);
  544. SetScreenCursor(CurrX,CurrY);
  545. f.bufpos:=0;
  546. CrtWrite:=0;
  547. end;
  548. Function CrtRead(Var F: TextRec): Integer;
  549. procedure BackSpace;
  550. begin
  551. if (f.bufpos>0) and (f.bufpos=f.bufend) then
  552. begin
  553. WriteChar(#8);
  554. WriteChar(' ');
  555. WriteChar(#8);
  556. dec(f.bufpos);
  557. dec(f.bufend);
  558. end;
  559. end;
  560. var
  561. ch : Char;
  562. Begin
  563. GetScreenCursor(CurrX,CurrY);
  564. f.bufpos:=0;
  565. f.bufend:=0;
  566. repeat
  567. if f.bufpos>f.bufend then
  568. f.bufend:=f.bufpos;
  569. SetScreenCursor(CurrX,CurrY);
  570. ch:=readkey;
  571. case ch of
  572. #0 : case readkey of
  573. #71 : while f.bufpos>0 do
  574. begin
  575. dec(f.bufpos);
  576. WriteChar(#8);
  577. end;
  578. #75 : if f.bufpos>0 then
  579. begin
  580. dec(f.bufpos);
  581. WriteChar(#8);
  582. end;
  583. #77 : if f.bufpos<f.bufend then
  584. begin
  585. WriteChar(f.bufptr^[f.bufpos]);
  586. inc(f.bufpos);
  587. end;
  588. #79 : while f.bufpos<f.bufend do
  589. begin
  590. WriteChar(f.bufptr^[f.bufpos]);
  591. inc(f.bufpos);
  592. end;
  593. end;
  594. ^S,
  595. #8 : BackSpace;
  596. ^Y,
  597. #27 : begin
  598. while f.bufpos<f.bufend do begin
  599. WriteChar(f.bufptr^[f.bufpos]);
  600. inc(f.bufpos);
  601. end;
  602. while f.bufend>0 do
  603. BackSpace;
  604. end;
  605. #13 : begin
  606. WriteChar(#13);
  607. WriteChar(#10);
  608. f.bufptr^[f.bufend]:=#13;
  609. f.bufptr^[f.bufend+1]:=#10;
  610. inc(f.bufend,2);
  611. break;
  612. end;
  613. #26 : if CheckEOF then
  614. begin
  615. f.bufptr^[f.bufend]:=#26;
  616. inc(f.bufend);
  617. break;
  618. end;
  619. else
  620. begin
  621. if f.bufpos<f.bufsize-2 then
  622. begin
  623. f.buffer[f.bufpos]:=ch;
  624. inc(f.bufpos);
  625. WriteChar(ch);
  626. end;
  627. end;
  628. end;
  629. until false;
  630. f.bufpos:=0;
  631. SetScreenCursor(CurrX,CurrY);
  632. CrtRead:=0;
  633. End;
  634. Function CrtReturn(Var F: TextRec): Integer;
  635. Begin
  636. CrtReturn:=0;
  637. end;
  638. Function CrtClose(Var F: TextRec): Integer;
  639. Begin
  640. F.Mode:=fmClosed;
  641. CrtClose:=0;
  642. End;
  643. Function CrtOpen(Var F: TextRec): Integer;
  644. Begin
  645. If F.Mode=fmOutput Then
  646. begin
  647. TextRec(F).InOutFunc:=@CrtWrite;
  648. TextRec(F).FlushFunc:=@CrtWrite;
  649. end
  650. Else
  651. begin
  652. F.Mode:=fmInput;
  653. TextRec(F).InOutFunc:=@CrtRead;
  654. TextRec(F).FlushFunc:=@CrtReturn;
  655. end;
  656. TextRec(F).CloseFunc:=@CrtClose;
  657. CrtOpen:=0;
  658. End;
  659. procedure AssignCrt(var F: Text);
  660. begin
  661. Assign(F,'');
  662. TextRec(F).OpenFunc:=@CrtOpen;
  663. end;
  664. { use the C version to avoid using dpmiexcp unit
  665. which makes sysutils and exceptions working incorrectly PM }
  666. function __djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;external;
  667. var
  668. x,y : longint;
  669. begin
  670. { Load startup values }
  671. ScreenWidth:=GetScreenWidth;
  672. ScreenHeight:=GetScreenHeight;
  673. WindMax:=(ScreenWidth-1) or ((ScreenHeight-1) shl 8);
  674. { Load TextAttr }
  675. GetScreenCursor(x,y);
  676. lastmode := mem[$40:$49];
  677. if screenheight>25 then
  678. lastmode:=lastmode or $100;
  679. If not(lastmode=Mono) then
  680. VidSeg := $b800
  681. else
  682. VidSeg := $b000;
  683. TextAttr:=mem[VidSeg:((y-1)*ScreenWidth+(x-1))*2+1];
  684. { Redirect the standard output }
  685. assigncrt(Output);
  686. Rewrite(Output);
  687. TextRec(Output).Handle:=StdOutputHandle;
  688. assigncrt(Input);
  689. Reset(Input);
  690. TextRec(Input).Handle:=StdInputHandle;
  691. { Calculates delay calibration }
  692. initdelay;
  693. { Enable ctrl-c input (JM) }
  694. __djgpp_set_ctrl_c(0);
  695. end.
  696. {
  697. $Log$
  698. Revision 1.9 2003-03-17 18:13:13 peter
  699. * exported ScreenHeight, ScreenWidth
  700. Revision 1.8 2002/12/15 20:22:24 peter
  701. * fix making string empty in readln when cursor is not at the end
  702. Revision 1.7 2002/09/10 10:38:04 pierre
  703. * merged from fixes: fix bug report 1974
  704. Revision 1.6 2002/09/07 16:01:18 peter
  705. * old logs removed and tabs fixed
  706. }