2
0

crt.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. {
  2. $Id$
  3. Borland Pascal 7 Compatible CRT Unit for win32
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit crt;
  11. {$mode objfpc}
  12. interface
  13. const
  14. { CRT modes }
  15. BW40 = 0; { 40x25 B/W on Color Adapter }
  16. CO40 = 1; { 40x25 Color on Color Adapter }
  17. BW80 = 2; { 80x25 B/W on Color Adapter }
  18. CO80 = 3; { 80x25 Color on Color Adapter }
  19. Mono = 7; { 80x25 on Monochrome Adapter }
  20. Font8x8 = 256; { Add-in for ROM font }
  21. { Mode constants for 3.0 compatibility }
  22. C40 = CO40;
  23. C80 = CO80;
  24. { Foreground and background color constants }
  25. Black = 0;
  26. Blue = 1;
  27. Green = 2;
  28. Cyan = 3;
  29. Red = 4;
  30. Magenta = 5;
  31. Brown = 6;
  32. LightGray = 7;
  33. { Foreground color constants }
  34. DarkGray = 8;
  35. LightBlue = 9;
  36. LightGreen = 10;
  37. LightCyan = 11;
  38. LightRed = 12;
  39. LightMagenta = 13;
  40. Yellow = 14;
  41. White = 15;
  42. { Add-in for blinking }
  43. Blink = 128;
  44. var
  45. { Interface variables }
  46. CheckBreak: Boolean; { Enable Ctrl-Break }
  47. CheckEOF: Boolean; { Enable Ctrl-Z }
  48. DirectVideo: Boolean; { Enable direct video addressing }
  49. CheckSnow: Boolean; { Enable snow filtering }
  50. LastMode: Word; { Current text mode }
  51. TextAttr: Byte; { Current text attribute }
  52. WindMin: Word; { Window upper left coordinates }
  53. WindMax: Word; { Window lower right coordinates }
  54. { Interface procedures }
  55. procedure AssignCrt(var F: Text);
  56. function KeyPressed: Boolean;
  57. function ReadKey: Char;
  58. procedure TextMode(Mode: Integer);
  59. procedure Window(X1,Y1,X2,Y2: Byte);
  60. procedure GotoXY(X,Y: Byte);
  61. function WhereX: Byte;
  62. function WhereY: Byte;
  63. procedure ClrScr;
  64. procedure ClrEol;
  65. procedure InsLine;
  66. procedure DelLine;
  67. procedure TextColor(Color: Byte);
  68. procedure TextBackground(Color: Byte);
  69. procedure LowVideo;
  70. procedure HighVideo;
  71. procedure NormVideo;
  72. procedure Delay(MS: Word);
  73. procedure Sound(Hz: Word);
  74. procedure NoSound;
  75. {Extra Functions}
  76. procedure cursoron;
  77. procedure cursoroff;
  78. procedure cursorbig;
  79. implementation
  80. uses
  81. dos,
  82. windows;
  83. var
  84. OutHandle : THandle;
  85. InputHandle : THandle;
  86. CursorSaveX : Longint;
  87. CursorSaveY : Longint;
  88. ScreenWidth : Longint;
  89. ScreenHeight : Longint;
  90. IsWindowsNT : Boolean;
  91. SaveCursorSize: Longint;
  92. {
  93. definition of textrec is in textrec.inc
  94. }
  95. {$i textrec.inc}
  96. {****************************************************************************
  97. Low level Routines
  98. ****************************************************************************}
  99. function GetPlatformID: Longint;
  100. var OsVersion: TOSVersionInfo;
  101. begin
  102. OsVersion.dwOsVersionInfoSize := SizeOf(OsVersion);
  103. GetVersionEx(@OsVersion);
  104. Result := OsVersion.dwPlatformID;
  105. end; { func. GetPlatformID }
  106. procedure TurnMouseOff;
  107. var Mode: DWORD;
  108. begin
  109. if GetConsoleMode(InputHandle, @Mode) then { Turn the mouse-cursor off }
  110. begin
  111. Mode := Mode AND NOT enable_processed_input
  112. AND NOT enable_mouse_input;
  113. SetConsoleMode(InputHandle, Mode);
  114. end; { if }
  115. end; { proc. TurnMouseOff }
  116. function GetScreenHeight : longint;
  117. var ConsoleInfo: TConsoleScreenBufferinfo;
  118. begin
  119. GetConsoleScreenBufferInfo(OutHandle, ConsoleInfo);
  120. Result := ConsoleInfo.dwSize.Y;
  121. end; { func. GetScreenHeight }
  122. function GetScreenWidth : longint;
  123. var ConsoleInfo: TConsoleScreenBufferInfo;
  124. begin
  125. GetConsoleScreenBufferInfo(OutHandle, ConsoleInfo);
  126. Result := ConsoleInfo.dwSize.X;
  127. end; { func. GetScreenWidth }
  128. procedure SetScreenCursor(x,y : longint);
  129. var CurInfo: TCoord;
  130. begin
  131. FillChar(Curinfo, SizeOf(Curinfo), 0);
  132. CurInfo.X := X - 1;
  133. CurInfo.Y := Y - 1;
  134. SetConsoleCursorPosition(OutHandle, CurInfo);
  135. CursorSaveX := X - 1;
  136. CursorSaveY := Y - 1;
  137. end;
  138. procedure GetScreenCursor(var x,y : longint);
  139. begin
  140. X := CursorSaveX + 1;
  141. Y := CursorSaveY + 1;
  142. end;
  143. {****************************************************************************
  144. Helper Routines
  145. ****************************************************************************}
  146. Function WinMinX: Byte;
  147. {
  148. Current Minimum X coordinate
  149. }
  150. Begin
  151. WinMinX:=(WindMin and $ff)+1;
  152. End;
  153. Function WinMinY: Byte;
  154. {
  155. Current Minimum Y Coordinate
  156. }
  157. Begin
  158. WinMinY:=(WindMin shr 8)+1;
  159. End;
  160. Function WinMaxX: Byte;
  161. {
  162. Current Maximum X coordinate
  163. }
  164. Begin
  165. WinMaxX:=(WindMax and $ff)+1;
  166. End;
  167. Function WinMaxY: Byte;
  168. {
  169. Current Maximum Y coordinate;
  170. }
  171. Begin
  172. WinMaxY:=(WindMax shr 8) + 1;
  173. End;
  174. Function FullWin:boolean;
  175. {
  176. Full Screen 80x25? Window(1,1,80,25) is used, allows faster routines
  177. }
  178. begin
  179. FullWin:=(WinMinX=1) and (WinMinY=1) and
  180. (WinMaxX=ScreenWidth) and (WinMaxY=ScreenHeight);
  181. end;
  182. {****************************************************************************
  183. Public Crt Functions
  184. ****************************************************************************}
  185. procedure textmode(mode : integer);
  186. begin
  187. {!!! Not done yet !!! }
  188. end;
  189. Procedure TextColor(Color: Byte);
  190. {
  191. Switch foregroundcolor
  192. }
  193. Begin
  194. TextAttr:=(Color and $8f) or (TextAttr and $70);
  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. var
  252. ClipRect: TSmallRect;
  253. SrcRect: TSmallRect;
  254. DestCoor: TCoord;
  255. CharInfo: TCharInfo;
  256. begin
  257. CharInfo.UnicodeChar := 32;
  258. CharInfo.Attributes := TextAttr;
  259. SrcRect.Left := WinMinX - 1;
  260. SrcRect.Top := WinMinY - 1;
  261. SrcRect.Right := WinMaxX - 1;
  262. SrcRect.Bottom := WinMaxY - 1;
  263. ClipRect := SrcRect;
  264. if IsWindowsNT then
  265. begin
  266. DestCoor.X := -WinMaxX;
  267. DestCoor.Y := -WinMaxY;
  268. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect,
  269. DestCoor, CharInfo);
  270. end
  271. else begin { Win95 seems to have a bug in scrolling, unfortunately }
  272. { This routine 3 times copies the bottom 12 lines to the }
  273. { top part of the screen. This eventually will clear the }
  274. { screen. }
  275. DestCoor.X := WinMinX - 1;
  276. DestCoor.Y := WinMinY - (Succ((WinMaxY - WinMinY) div 2));
  277. {-------- Scroll 1st part }
  278. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect,
  279. DestCoor, CharInfo);
  280. {-------- Scroll 2nd part }
  281. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect,
  282. DestCoor, CharInfo);
  283. {-------- Scroll 3rd part (last line) }
  284. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect,
  285. DestCoor, CharInfo);
  286. end; { if in Windows95 }
  287. GotoXY(1,1);
  288. end; { proc. ClrScr }
  289. procedure ClrEol;
  290. {
  291. Clear from current position to end of line.
  292. }
  293. var Temp: Dword;
  294. CharInfo: Char;
  295. Coord: TCoord;
  296. X,Y: Longint;
  297. begin
  298. GetScreenCursor(x,y);
  299. CharInfo := #32;
  300. Coord.X := X - 1;
  301. Coord.Y := Y - 1;
  302. FillConsoleOutputCharacter(OutHandle, CharInfo, WinMaxX - (X + 01), Coord, @Temp);
  303. end;
  304. Function WhereX: Byte;
  305. {
  306. Return current X-position of cursor.
  307. }
  308. var
  309. x,y : longint;
  310. Begin
  311. GetScreenCursor(x,y);
  312. WhereX:=x-WinMinX+1;
  313. End;
  314. Function WhereY: Byte;
  315. {
  316. Return current Y-position of cursor.
  317. }
  318. var
  319. x,y : longint;
  320. Begin
  321. GetScreenCursor(x,y);
  322. WhereY:=y-WinMinY+1;
  323. End;
  324. {*************************************************************************
  325. KeyBoard
  326. *************************************************************************}
  327. var
  328. ScanCode : char;
  329. SpecialKey : boolean;
  330. Function RemapScanCode (ScanCode: byte; CtrlKeyState: byte): byte;
  331. { Several remappings of scancodes are necessary to comply with what
  332. we get with MSDOS. Special Windows keys, as Alt-Tab, Ctrl-Esc etc.
  333. are excluded }
  334. var
  335. AltKey, CtrlKey, ShiftKey: boolean;
  336. const
  337. {
  338. Keypad key scancodes:
  339. Ctrl Norm
  340. $77 $47 - Home
  341. $8D $48 - Up arrow
  342. $84 $49 - PgUp
  343. $8E $4A - -
  344. $73 $4B - Left Arrow
  345. $8F $4C - 5
  346. $74 $4D - Right arrow
  347. $4E $4E - +
  348. $75 $4F - End
  349. $91 $50 - Down arrow
  350. $76 $51 - PgDn
  351. $92 $52 - Ins
  352. $93 $53 - Del
  353. }
  354. CtrlKeypadKeys: array[$47..$53] of byte =
  355. ($77, $8D, $84, $8E, $73, $8F, $74, $4E, $75, $91, $76, $92, $93);
  356. begin
  357. AltKey := ((CtrlKeyState AND
  358. (RIGHT_ALT_PRESSED OR LEFT_ALT_PRESSED)) > 0);
  359. CtrlKey := ((CtrlKeyState AND
  360. (RIGHT_CTRL_PRESSED OR LEFT_CTRL_PRESSED)) > 0);
  361. ShiftKey := ((CtrlKeyState AND SHIFT_PRESSED) > 0);
  362. if AltKey then
  363. case ScanCode of
  364. // Digits, -, =
  365. $02..$0D: inc(ScanCode, $76);
  366. // Function keys
  367. $3B..$44: inc(Scancode, $2D);
  368. $57..$58: inc(Scancode, $34);
  369. // Extended cursor block keys
  370. $47..$49, $4B, $4D, $4F..$53:
  371. inc(Scancode, $50);
  372. // Other keys
  373. $1C: Scancode := $A6; // Enter
  374. $35: Scancode := $A4; // / (keypad and normal!)
  375. end
  376. else if CtrlKey then
  377. case Scancode of
  378. // Tab key
  379. $0F: Scancode := $94;
  380. // Function keys
  381. $3B..$44: inc(Scancode, $23);
  382. $57..$58: inc(Scancode, $32);
  383. // Keypad keys
  384. $35: Scancode := $95; // \
  385. $37: Scancode := $96; // *
  386. $47..$53: Scancode := CtrlKeypadKeys[Scancode];
  387. end
  388. else if ShiftKey then
  389. case Scancode of
  390. // Function keys
  391. $3B..$44: inc(Scancode, $19);
  392. $57..$58: inc(Scancode, $30);
  393. end
  394. else
  395. case Scancode of
  396. // Function keys
  397. $57..$58: inc(Scancode, $2E); // F11 and F12
  398. end;
  399. Result := ScanCode;
  400. end;
  401. function KeyPressed : boolean;
  402. var
  403. nevents, nread, i: longint;
  404. buf : TINPUTRECORD;
  405. begin
  406. KeyPressed := FALSE;
  407. if ScanCode <> #0 then
  408. KeyPressed := TRUE
  409. else
  410. begin
  411. nevents:=0;
  412. GetNumberOfConsoleInputEvents(TextRec(input).Handle,nevents);
  413. For i := 1 to nevents do
  414. begin
  415. ReadConsoleInputA(TextRec(input).Handle,buf,1,nread);
  416. if buf.EventType = KEY_EVENT then
  417. if buf.KeyEvent.bKeyDown then
  418. begin
  419. KeyPressed := TRUE;
  420. if ord(buf.KeyEvent.AsciiChar) = 0 then
  421. begin
  422. SpecialKey := TRUE;
  423. ScanCode := Chr(RemapScanCode(Buf.KeyEvent.wVirtualScanCode, Buf.KeyEvent.dwControlKeyState));
  424. end
  425. else
  426. begin
  427. SpecialKey := FALSE;
  428. ScanCode := Chr(Ord(buf.KeyEvent.AsciiChar));
  429. end;
  430. break;
  431. end;
  432. end;
  433. end;
  434. end;
  435. function ReadKey: char;
  436. begin
  437. repeat
  438. Sleep(1);
  439. until KeyPressed;
  440. if SpecialKey then begin
  441. ReadKey := #0;
  442. SpecialKey := FALSE;
  443. end
  444. else begin
  445. ReadKey := ScanCode;
  446. ScanCode := #0;
  447. end;
  448. end;
  449. {*************************************************************************
  450. Delay
  451. *************************************************************************}
  452. procedure Delay(MS: Word);
  453. begin
  454. Sleep(ms);
  455. end; { proc. Delay }
  456. procedure sound(hz : word);
  457. begin
  458. MessageBeep(0); { lame ;-) }
  459. end;
  460. procedure nosound;
  461. begin
  462. end;
  463. {****************************************************************************
  464. HighLevel Crt Functions
  465. ****************************************************************************}
  466. procedure removeline(y : longint);
  467. var
  468. ClipRect: TSmallRect;
  469. SrcRect: TSmallRect;
  470. DestCoor: TCoord;
  471. CharInfo: TCharInfo;
  472. begin
  473. CharInfo.UnicodeChar := 32;
  474. CharInfo.Attributes := TextAttr;
  475. SrcRect.Top := Y - 01;
  476. SrcRect.Left := WinMinX - 1;
  477. SrcRect.Right := WinMaxX - 1;
  478. SrcRect.Bottom := WinMaxY - 1;
  479. DestCoor.X := WinMinX - 1;
  480. DestCoor.Y := Y - 2;
  481. ClipRect := SrcRect;
  482. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect, DestCoor, CharInfo);
  483. end; { proc. RemoveLine }
  484. procedure delline;
  485. begin
  486. removeline(wherey);
  487. end; { proc. DelLine }
  488. procedure insline;
  489. var
  490. ClipRect: TSmallRect;
  491. SrcRect: TSmallRect;
  492. DestCoor: TCoord;
  493. CharInfo: TCharInfo;
  494. X,Y: Longint;
  495. begin
  496. GetScreenCursor(X, Y);
  497. CharInfo.UnicodeChar := 32;
  498. CharInfo.Attributes := TextAttr;
  499. SrcRect.Top := Y - 1;
  500. SrcRect.Left := WinMinX - 1;
  501. SrcRect.Right := WinMaxX - 1;
  502. SrcRect.Bottom := WinMaxY - 1;
  503. DestCoor.X := WinMinX - 1;
  504. DestCoor.Y := Y;
  505. ClipRect := SrcRect;
  506. ScrollConsoleScreenBuffer(OutHandle, SrcRect, ClipRect, DestCoor, CharInfo);
  507. end; { proc. InsLine }
  508. {****************************************************************************
  509. Extra Crt Functions
  510. ****************************************************************************}
  511. procedure cursoron;
  512. var CursorInfo: TConsoleCursorInfo;
  513. begin
  514. GetConsoleCursorInfo(OutHandle, CursorInfo);
  515. CursorInfo.dwSize := SaveCursorSize;
  516. CursorInfo.bVisible := true;
  517. SetConsoleCursorInfo(OutHandle, CursorInfo);
  518. end;
  519. procedure cursoroff;
  520. var CursorInfo: TConsoleCursorInfo;
  521. begin
  522. GetConsoleCursorInfo(OutHandle, CursorInfo);
  523. CursorInfo.bVisible := false;
  524. SetConsoleCursorInfo(OutHandle, CursorInfo);
  525. end;
  526. procedure cursorbig;
  527. var CursorInfo: TConsoleCursorInfo;
  528. begin
  529. GetConsoleCursorInfo(OutHandle, CursorInfo);
  530. CursorInfo.dwSize := 100;
  531. CursorInfo.bVisible := true;
  532. SetConsoleCursorInfo(OutHandle, CursorInfo);
  533. end;
  534. {*****************************************************************************
  535. Read and Write routines
  536. *****************************************************************************}
  537. var
  538. CurrX, CurrY : longint;
  539. procedure WriteChar(c:char);
  540. var
  541. Cell : TCharInfo;
  542. BufSize : Coord; { Column-row size of source buffer }
  543. WritePos: TCoord; { Upper-left cell to write from }
  544. DestRect: TSmallRect;
  545. begin
  546. Case C of
  547. #10 : begin
  548. Inc(CurrY);
  549. end;
  550. #13 : begin
  551. CurrX := WinMinX;
  552. end; { if }
  553. #08 : begin
  554. if CurrX > WinMinX then Dec(CurrX);
  555. end; { ^H }
  556. #07 : begin
  557. // MessagBeep(0);
  558. end; { ^G }
  559. else begin
  560. BufSize.X := 01;
  561. BufSize.Y := 01;
  562. WritePos.X := 0;
  563. WritePos.Y := 0;
  564. Cell.UniCodeChar := Ord(c);
  565. Cell.Attributes := TextAttr;
  566. DestRect.Left := (CurrX - 01);
  567. DestRect.Top := (CurrY - 01);
  568. DestRect.Right := (CurrX - 01) + 01;
  569. DestRect.Bottom := (CurrY - 01);
  570. WriteConsoleOutput(OutHandle, Cell, BufSize, WritePos, @DestRect);
  571. Inc(CurrX);
  572. end; { else }
  573. end; { case }
  574. if CurrX > WinMaxX then
  575. begin
  576. CurrX := WinMinX;
  577. Inc(CurrY);
  578. end; { if }
  579. While CurrY > WinMaxY do
  580. begin
  581. RemoveLine(1);
  582. Dec(CurrY);
  583. end; { while }
  584. end;
  585. Function CrtWrite(var f : textrec):integer;
  586. var
  587. i : longint;
  588. begin
  589. GetScreenCursor(CurrX,CurrY);
  590. for i:=0 to f.bufpos-1 do
  591. WriteChar(f.buffer[i]);
  592. SetScreenCursor(CurrX,CurrY);
  593. f.bufpos:=0;
  594. CrtWrite:=0;
  595. end;
  596. Function CrtRead(Var F: TextRec): Integer;
  597. procedure BackSpace;
  598. begin
  599. if (f.bufpos>0) and (f.bufpos=f.bufend) then
  600. begin
  601. WriteChar(#8);
  602. WriteChar(' ');
  603. WriteChar(#8);
  604. dec(f.bufpos);
  605. dec(f.bufend);
  606. end;
  607. end;
  608. var
  609. ch : Char;
  610. Begin
  611. GetScreenCursor(CurrX,CurrY);
  612. f.bufpos:=0;
  613. f.bufend:=0;
  614. repeat
  615. if f.bufpos>f.bufend then
  616. f.bufend:=f.bufpos;
  617. SetScreenCursor(CurrX,CurrY);
  618. ch:=readkey;
  619. case ch of
  620. #0 : case readkey of
  621. #71 : while f.bufpos>0 do
  622. begin
  623. dec(f.bufpos);
  624. WriteChar(#8);
  625. end;
  626. #75 : if f.bufpos>0 then
  627. begin
  628. dec(f.bufpos);
  629. WriteChar(#8);
  630. end;
  631. #77 : if f.bufpos<f.bufend then
  632. begin
  633. WriteChar(f.bufptr^[f.bufpos]);
  634. inc(f.bufpos);
  635. end;
  636. #79 : while f.bufpos<f.bufend do
  637. begin
  638. WriteChar(f.bufptr^[f.bufpos]);
  639. inc(f.bufpos);
  640. end;
  641. end;
  642. ^S,
  643. #8 : BackSpace;
  644. ^Y,
  645. #27 : begin
  646. f.bufpos:=f.bufend;
  647. while f.bufend>0 do
  648. BackSpace;
  649. end;
  650. #13 : begin
  651. WriteChar(#13);
  652. WriteChar(#10);
  653. f.bufptr^[f.bufend]:=#13;
  654. f.bufptr^[f.bufend+1]:=#10;
  655. inc(f.bufend,2);
  656. break;
  657. end;
  658. #26 : if CheckEOF then
  659. begin
  660. f.bufptr^[f.bufend]:=#26;
  661. inc(f.bufend);
  662. break;
  663. end;
  664. else
  665. begin
  666. if f.bufpos<f.bufsize-2 then
  667. begin
  668. f.buffer[f.bufpos]:=ch;
  669. inc(f.bufpos);
  670. WriteChar(ch);
  671. end;
  672. end;
  673. end;
  674. until false;
  675. f.bufpos:=0;
  676. SetScreenCursor(CurrX,CurrY);
  677. CrtRead:=0;
  678. End;
  679. Function CrtReturn:Integer;
  680. Begin
  681. CrtReturn:=0;
  682. end;
  683. Function CrtClose(Var F: TextRec): Integer;
  684. Begin
  685. F.Mode:=fmClosed;
  686. CrtClose:=0;
  687. End;
  688. Function CrtOpen(Var F: TextRec): Integer;
  689. Begin
  690. If F.Mode=fmOutput Then
  691. begin
  692. TextRec(F).InOutFunc:=@CrtWrite;
  693. TextRec(F).FlushFunc:=@CrtWrite;
  694. end
  695. Else
  696. begin
  697. F.Mode:=fmInput;
  698. TextRec(F).InOutFunc:=@CrtRead;
  699. TextRec(F).FlushFunc:=@CrtReturn;
  700. end;
  701. TextRec(F).CloseFunc:=@CrtClose;
  702. CrtOpen:=0;
  703. End;
  704. procedure AssignCrt(var F: Text);
  705. begin
  706. Assign(F,'');
  707. TextRec(F).OpenFunc:=@CrtOpen;
  708. end;
  709. var CursorInfo : TConsoleCursorInfo;
  710. ConsoleInfo: TConsoleScreenBufferinfo;
  711. begin
  712. { Initialize the output handles }
  713. OutHandle := GetStdHandle(STD_OUTPUT_HANDLE);
  714. InputHandle := GetStdHandle(STD_INPUT_HANDLE);
  715. LastMode := 3;
  716. {--------------------- Get the cursor size and such -----------------------}
  717. FillChar(CursorInfo, SizeOf(CursorInfo), 00);
  718. GetConsoleCursorInfo(OutHandle, CursorInfo);
  719. SaveCursorSize := CursorInfo.dwSize;
  720. {------------------ Get the current cursor position and attr --------------}
  721. FillChar(ConsoleInfo, SizeOf(ConsoleInfo), 0);
  722. GetConsoleScreenBufferInfo(OutHandle, ConsoleInfo);
  723. CursorSaveX := ConsoleInfo.dwCursorPosition.X;
  724. CursorSaveY := ConsoleInfo.dwCursorPosition.Y;
  725. TextAttr := ConsoleInfo.wAttributes;
  726. { Load startup values }
  727. ScreenWidth := GetScreenWidth;
  728. ScreenHeight := GetScreenHeight;
  729. IsWindowsNT := (GetPlatformID = VER_PLATFORM_WIN32_NT);
  730. TurnMouseOff;
  731. WindMax := (ScreenWidth - 1) OR ((ScreenHeight - 1) SHL 8);
  732. { Redirect the standard output }
  733. AssignCrt(Output);
  734. Rewrite(Output);
  735. TextRec(Output).Handle:= OutHandle;
  736. AssignCrt(Input);
  737. Reset(Input);
  738. TextRec(Input).Handle:= InputHandle;
  739. end. { unit Crt }
  740. {
  741. $Log$
  742. Revision 1.8 1999-06-09 16:46:11 peter
  743. * fixed fullwin,textbackground
  744. Revision 1.7 1999/05/22 14:01:01 peter
  745. * more fixed from Maarten Bekkers
  746. Revision 1.6 1999/05/19 16:22:02 peter
  747. * fixed left crt bugs
  748. Revision 1.5 1999/05/01 13:18:26 peter
  749. * changed back fixes
  750. Revision 1.4 1999/04/30 11:34:27 michael
  751. + Fixed some compiling errors
  752. Revision 1.3 1999/04/23 09:06:17 michael
  753. + now it REALLY compiles
  754. Revision 1.2 1999/04/20 11:34:12 peter
  755. + crt unit that compiles
  756. }