crt.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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. interface
  12. const
  13. { CRT modes }
  14. BW40 = 0; { 40x25 B/W on Color Adapter }
  15. CO40 = 1; { 40x25 Color on Color Adapter }
  16. BW80 = 2; { 80x25 B/W on Color Adapter }
  17. CO80 = 3; { 80x25 Color on Color Adapter }
  18. Mono = 7; { 80x25 on Monochrome Adapter }
  19. Font8x8 = 256; { Add-in for ROM font }
  20. { Mode constants for 3.0 compatibility }
  21. C40 = CO40;
  22. C80 = CO80;
  23. { Foreground and background color constants }
  24. Black = 0;
  25. Blue = 1;
  26. Green = 2;
  27. Cyan = 3;
  28. Red = 4;
  29. Magenta = 5;
  30. Brown = 6;
  31. LightGray = 7;
  32. { Foreground color constants }
  33. DarkGray = 8;
  34. LightBlue = 9;
  35. LightGreen = 10;
  36. LightCyan = 11;
  37. LightRed = 12;
  38. LightMagenta = 13;
  39. Yellow = 14;
  40. White = 15;
  41. { Add-in for blinking }
  42. Blink = 128;
  43. var
  44. { Interface variables }
  45. CheckBreak: Boolean; { Enable Ctrl-Break }
  46. CheckEOF: Boolean; { Enable Ctrl-Z }
  47. DirectVideo: Boolean; { Enable direct video addressing }
  48. CheckSnow: Boolean; { Enable snow filtering }
  49. LastMode: Word; { Current text mode }
  50. TextAttr: Byte; { Current text attribute }
  51. WindMin: Word; { Window upper left coordinates }
  52. WindMax: Word; { Window lower right coordinates }
  53. { FPC Specific for large screen support }
  54. WindMinX : DWord;
  55. WindMaxX : DWord;
  56. WindMinY : DWord;
  57. WindMaxY : DWord ;
  58. { Interface procedures }
  59. procedure AssignCrt(var F: Text);
  60. function KeyPressed: Boolean;
  61. function ReadKey: Char;
  62. procedure TextMode(Mode: Integer);
  63. procedure Window(X1,Y1,X2,Y2: DWord);
  64. procedure GotoXY(X,Y: DWord);
  65. function WhereX: DWord;
  66. function WhereY: DWord;
  67. procedure ClrScr;
  68. procedure ClrEol;
  69. procedure InsLine;
  70. procedure DelLine;
  71. procedure TextColor(Color: Byte);
  72. procedure TextBackground(Color: Byte);
  73. procedure LowVideo;
  74. procedure HighVideo;
  75. procedure NormVideo;
  76. procedure Delay(MS: Word);
  77. procedure Sound(Hz: Word);
  78. procedure NoSound;
  79. {Extra Functions}
  80. procedure cursoron;
  81. procedure cursoroff;
  82. procedure cursorbig;
  83. implementation
  84. uses
  85. windows;
  86. var
  87. SaveCursorSize: Longint;
  88. {
  89. definition of textrec is in textrec.inc
  90. }
  91. {$i textrec.inc}
  92. {****************************************************************************
  93. Low level Routines
  94. ****************************************************************************}
  95. procedure TurnMouseOff;
  96. var Mode: DWORD;
  97. begin
  98. if GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), @Mode) then begin { Turn the mouse-cursor off }
  99. Mode := Mode AND cardinal(NOT enable_processed_input)
  100. AND cardinal(NOT enable_mouse_input);
  101. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), Mode);
  102. end; { if }
  103. end; { proc. TurnMouseOff }
  104. function GetScreenHeight : DWord;
  105. var
  106. ConsoleInfo: TConsoleScreenBufferinfo;
  107. begin
  108. if (not GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), ConsoleInfo)) then begin
  109. {$ifdef SYSTEMDEBUG}
  110. Writeln(stderr,'GetScreenHeight failed GetLastError returns ',GetLastError);
  111. Halt(1);
  112. {$endif SYSTEMDEBUG}
  113. // ts: this is really silly assumption; imho better: issue a halt
  114. GetScreenHeight:=25;
  115. end else
  116. GetScreenHeight := ConsoleInfo.dwSize.Y;
  117. end; { func. GetScreenHeight }
  118. function GetScreenWidth : DWord;
  119. var
  120. ConsoleInfo: TConsoleScreenBufferInfo;
  121. begin
  122. if (not GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), ConsoleInfo)) then begin
  123. {$ifdef SYSTEMDEBUG}
  124. Writeln(stderr,'GetScreenWidth failed GetLastError returns ',GetLastError);
  125. Halt(1);
  126. {$endif SYSTEMDEBUG}
  127. // ts: this is really silly assumption; imho better: issue a halt
  128. GetScreenWidth:=80;
  129. end else
  130. GetScreenWidth := ConsoleInfo.dwSize.X;
  131. end; { func. GetScreenWidth }
  132. procedure GetScreenCursor(var x : DWord; var y : DWord);
  133. var
  134. ConsoleInfo : TConsoleScreenBufferInfo;
  135. begin
  136. FillChar(ConsoleInfo, SizeOf(ConsoleInfo), 0);
  137. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), ConsoleInfo);
  138. X := ConsoleInfo.dwCursorPosition.X + 1;
  139. Y := ConsoleInfo.dwCursorPosition.Y + 1;
  140. end;
  141. procedure SetScreenCursor(x,y : DWord);
  142. var
  143. CurInfo: TCoord;
  144. begin
  145. FillChar(Curinfo, SizeOf(Curinfo), 0);
  146. CurInfo.X := X - 1;
  147. CurInfo.Y := Y - 1;
  148. SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CurInfo);
  149. end;
  150. {****************************************************************************
  151. Public Crt Functions
  152. ****************************************************************************}
  153. procedure textmode(mode : integer);
  154. begin
  155. {!!! Not done yet !!! }
  156. end;
  157. Procedure TextColor(Color: Byte);
  158. { Switch foregroundcolor }
  159. Begin
  160. TextAttr:=(Color and $8f) or (TextAttr and $70);
  161. End;
  162. Procedure TextBackground(Color: Byte);
  163. { Switch backgroundcolor }
  164. Begin
  165. TextAttr:=((Color shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  166. End;
  167. Procedure HighVideo;
  168. { Set highlighted output. }
  169. Begin
  170. TextColor(TextAttr Or $08);
  171. End;
  172. Procedure LowVideo;
  173. { Set normal output }
  174. Begin
  175. TextColor(TextAttr And $77);
  176. End;
  177. Procedure NormVideo;
  178. { Set normal back and foregroundcolors. }
  179. Begin
  180. TextColor(7);
  181. TextBackGround(0);
  182. End;
  183. Procedure GotoXY(X: DWord; Y: DWord);
  184. { Go to coordinates X,Y in the current window. }
  185. Begin
  186. If (X > 0) and (X <= (WindMaxX - WindMinX + 1)) and
  187. (Y > 0) and (Y <= (WindMaxY - WindMinY + 1)) Then Begin
  188. Inc(X, WindMinX - 1);
  189. Inc(Y, WindMinY - 1);
  190. SetScreenCursor(x,y);
  191. End;
  192. End;
  193. Procedure Window(X1, Y1, X2, Y2: DWord);
  194. {
  195. Set screen window to the specified coordinates.
  196. }
  197. Begin
  198. if (X1 > X2) or (X2 > GetScreenWidth) or
  199. (Y1 > Y2) or (Y2 > GetScreenHeight) then
  200. exit;
  201. WindMinY := Y1;
  202. WindMaxY := Y2;
  203. WindMinX := X1;
  204. WindMaxX := X2;
  205. WindMin:=((Y1-1) Shl 8)+(X1-1);
  206. WindMax:=((Y2-1) Shl 8)+(X2-1);
  207. GotoXY(1, 1);
  208. End;
  209. procedure ClrScr;
  210. var
  211. DestCoor: TCoord;
  212. numChars, x : DWord;
  213. begin
  214. DestCoor.X := WindMinX - 1;
  215. DestCoor.Y := WindMinY - 1;
  216. numChars := (WindMaxX - WindMinX + 1) * (WindMaxY - WindMinY + 1);
  217. FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), TextAttr,
  218. numChars, DestCoor, x);
  219. FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), #32,
  220. numChars, DestCoor, x);
  221. GotoXY(1, 1);
  222. end; { proc. ClrScr }
  223. procedure ClrEol;
  224. {
  225. Clear from current position to end of line.
  226. }
  227. var
  228. Temp: DWord;
  229. CharInfo: Char;
  230. Coord: TCoord;
  231. X,Y: DWord;
  232. begin
  233. GetScreenCursor(x, y);
  234. CharInfo := #32;
  235. Coord.X := X - 1;
  236. Coord.Y := Y - 1;
  237. FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), CharInfo, WindMaxX - X + 1,
  238. Coord, @Temp);
  239. FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), TextAttr, WindMaxX - X + 1,
  240. Coord, @Temp);
  241. end;
  242. Function WhereX: DWord;
  243. {
  244. Return current X-position of cursor.
  245. }
  246. var
  247. x,y : DWord;
  248. Begin
  249. GetScreenCursor(x, y);
  250. WhereX:= x - WindMinX +1;
  251. End;
  252. Function WhereY: DWord;
  253. {
  254. Return current Y-position of cursor.
  255. }
  256. var
  257. x, y : DWord;
  258. Begin
  259. GetScreenCursor(x, y);
  260. WhereY:= y - WindMinY + 1;
  261. End;
  262. {*************************************************************************
  263. KeyBoard
  264. *************************************************************************}
  265. var
  266. ScanCode : char;
  267. SpecialKey : boolean;
  268. DoingNumChars: Boolean;
  269. DoingNumCode: Byte;
  270. Function RemapScanCode (ScanCode: byte; CtrlKeyState: byte; keycode:longint): byte;
  271. { Several remappings of scancodes are necessary to comply with what
  272. we get with MSDOS. Special Windows keys, as Alt-Tab, Ctrl-Esc etc.
  273. are excluded }
  274. var
  275. AltKey, CtrlKey, ShiftKey: boolean;
  276. const
  277. {
  278. Keypad key scancodes:
  279. Ctrl Norm
  280. $77 $47 - Home
  281. $8D $48 - Up arrow
  282. $84 $49 - PgUp
  283. $8E $4A - -
  284. $73 $4B - Left Arrow
  285. $8F $4C - 5
  286. $74 $4D - Right arrow
  287. $4E $4E - +
  288. $75 $4F - End
  289. $91 $50 - Down arrow
  290. $76 $51 - PgDn
  291. $92 $52 - Ins
  292. $93 $53 - Del
  293. }
  294. CtrlKeypadKeys: array[$47..$53] of byte =
  295. ($77, $8D, $84, $8E, $73, $8F, $74, $4E, $75, $91, $76, $92, $93);
  296. begin
  297. AltKey := ((CtrlKeyState AND
  298. (RIGHT_ALT_PRESSED OR LEFT_ALT_PRESSED)) > 0);
  299. CtrlKey := ((CtrlKeyState AND
  300. (RIGHT_CTRL_PRESSED OR LEFT_CTRL_PRESSED)) > 0);
  301. ShiftKey := ((CtrlKeyState AND SHIFT_PRESSED) > 0);
  302. if AltKey then
  303. begin
  304. case ScanCode of
  305. // Digits, -, =
  306. $02..$0D: inc(ScanCode, $76);
  307. // Function keys
  308. $3B..$44: inc(Scancode, $2D);
  309. $57..$58: inc(Scancode, $34);
  310. // Extended cursor block keys
  311. $47..$49, $4B, $4D, $4F..$53:
  312. inc(Scancode, $50);
  313. // Other keys
  314. $1C: Scancode := $A6; // Enter
  315. $35: Scancode := $A4; // / (keypad and normal!)
  316. end
  317. end
  318. else if CtrlKey then
  319. case Scancode of
  320. // Tab key
  321. $0F: Scancode := $94;
  322. // Function keys
  323. $3B..$44: inc(Scancode, $23);
  324. $57..$58: inc(Scancode, $32);
  325. // Keypad keys
  326. $35: Scancode := $95; // \
  327. $37: Scancode := $96; // *
  328. $47..$53: Scancode := CtrlKeypadKeys[Scancode];
  329. end
  330. else if ShiftKey then
  331. case Scancode of
  332. // Function keys
  333. $3B..$44: inc(Scancode, $19);
  334. $57..$58: inc(Scancode, $30);
  335. end
  336. else
  337. case Scancode of
  338. // Function keys
  339. $57..$58: inc(Scancode, $2E); // F11 and F12
  340. end;
  341. RemapScanCode := ScanCode;
  342. end;
  343. function KeyPressed : boolean;
  344. var
  345. nevents,nread : dword;
  346. buf : TINPUTRECORD;
  347. AltKey: Boolean;
  348. c : longint;
  349. begin
  350. KeyPressed := FALSE;
  351. if ScanCode <> #0 then
  352. KeyPressed := TRUE
  353. else
  354. begin
  355. GetNumberOfConsoleInputEvents(TextRec(input).Handle,nevents);
  356. while nevents>0 do
  357. begin
  358. ReadConsoleInputA(TextRec(input).Handle,buf,1,nread);
  359. if buf.EventType = KEY_EVENT then
  360. if buf.Event.KeyEvent.bKeyDown then
  361. begin
  362. { Alt key is VK_MENU }
  363. { Capslock key is VK_CAPITAL }
  364. AltKey := ((Buf.Event.KeyEvent.dwControlKeyState AND
  365. (RIGHT_ALT_PRESSED OR LEFT_ALT_PRESSED)) > 0);
  366. if not(Buf.Event.KeyEvent.wVirtualKeyCode in [VK_SHIFT, VK_MENU, VK_CONTROL,
  367. VK_CAPITAL, VK_NUMLOCK,
  368. VK_SCROLL]) then
  369. begin
  370. keypressed:=true;
  371. if (ord(buf.Event.KeyEvent.AsciiChar) = 0) or
  372. (buf.Event.KeyEvent.dwControlKeyState and (LEFT_ALT_PRESSED or ENHANCED_KEY) > 0) then
  373. begin
  374. SpecialKey := TRUE;
  375. ScanCode := Chr(RemapScanCode(Buf.Event.KeyEvent.wVirtualScanCode, Buf.Event.KeyEvent.dwControlKeyState,
  376. Buf.Event.KeyEvent.wVirtualKeyCode));
  377. end
  378. else
  379. begin
  380. { Map shift-tab }
  381. if (buf.Event.KeyEvent.AsciiChar=#9) and
  382. (buf.Event.KeyEvent.dwControlKeyState and SHIFT_PRESSED > 0) then
  383. begin
  384. SpecialKey := TRUE;
  385. ScanCode := #15;
  386. end
  387. else
  388. begin
  389. SpecialKey := FALSE;
  390. ScanCode := Chr(Ord(buf.Event.KeyEvent.AsciiChar));
  391. end;
  392. end;
  393. if AltKey then
  394. begin
  395. case Buf.Event.KeyEvent.wVirtualScanCode of
  396. 71 : c:=7;
  397. 72 : c:=8;
  398. 73 : c:=9;
  399. 75 : c:=4;
  400. 76 : c:=5;
  401. 77 : c:=6;
  402. 79 : c:=1;
  403. 80 : c:=2;
  404. 81 : c:=3;
  405. 82 : c:=0;
  406. else
  407. break;
  408. end;
  409. DoingNumChars := true;
  410. DoingNumCode := Byte((DoingNumCode * 10) + c);
  411. Keypressed := false;
  412. Specialkey := false;
  413. ScanCode := #0;
  414. end
  415. else
  416. break;
  417. end;
  418. end
  419. else
  420. begin
  421. if (Buf.Event.KeyEvent.wVirtualKeyCode in [VK_MENU]) then
  422. if DoingNumChars then
  423. if DoingNumCode > 0 then
  424. begin
  425. ScanCode := Chr(DoingNumCode);
  426. Keypressed := true;
  427. DoingNumChars := false;
  428. DoingNumCode := 0;
  429. break
  430. end; { if }
  431. end;
  432. { if we got a key then we can exit }
  433. if keypressed then
  434. exit;
  435. GetNumberOfConsoleInputEvents(TextRec(input).Handle,nevents);
  436. end;
  437. end;
  438. end;
  439. function ReadKey: char;
  440. begin
  441. while (not KeyPressed) do
  442. Sleep(1);
  443. if SpecialKey then begin
  444. ReadKey := #0;
  445. SpecialKey := FALSE;
  446. end else begin
  447. ReadKey := ScanCode;
  448. ScanCode := #0;
  449. end;
  450. end;
  451. {*************************************************************************
  452. Delay
  453. *************************************************************************}
  454. procedure Delay(MS: Word);
  455. begin
  456. Sleep(ms);
  457. end; { proc. Delay }
  458. procedure sound(hz : word);
  459. begin
  460. MessageBeep(0); { lame ;-) }
  461. end;
  462. procedure nosound;
  463. begin
  464. end;
  465. {****************************************************************************
  466. HighLevel Crt Functions
  467. ****************************************************************************}
  468. procedure removeline(y : DWord);
  469. var
  470. ClipRect: TSmallRect;
  471. SrcRect: TSmallRect;
  472. DestCoor: TCoord;
  473. CharInfo: TCharInfo;
  474. begin
  475. CharInfo.UnicodeChar := #32;
  476. CharInfo.Attributes := TextAttr;
  477. Y := (WindMinY - 1) + (Y - 1) + 1;
  478. SrcRect.Top := Y;
  479. SrcRect.Left := WindMinX - 1;
  480. SrcRect.Right := WindMaxX - 1;
  481. SrcRect.Bottom := WindMaxY - 1;
  482. DestCoor.X := WindMinX - 1;
  483. DestCoor.Y := Y - 1;
  484. ClipRect := SrcRect;
  485. cliprect.top := destcoor.y;
  486. ScrollConsoleScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE), SrcRect, ClipRect,
  487. DestCoor, CharInfo);
  488. end; { proc. RemoveLine }
  489. procedure delline;
  490. begin
  491. removeline(wherey);
  492. end; { proc. DelLine }
  493. procedure insline;
  494. var
  495. ClipRect: TSmallRect;
  496. SrcRect: TSmallRect;
  497. DestCoor: TCoord;
  498. CharInfo: TCharInfo;
  499. X,Y: DWord;
  500. begin
  501. GetScreenCursor(X, Y);
  502. CharInfo.UnicodeChar := #32;
  503. CharInfo.Attributes := TextAttr;
  504. SrcRect.Top := Y - 1;
  505. SrcRect.Left := WindMinX - 1;
  506. SrcRect.Right := WindMaxX - 1;
  507. SrcRect.Bottom := WindMaxY - 1 + 1;
  508. DestCoor.X := WindMinX - 1;
  509. DestCoor.Y := Y;
  510. ClipRect := SrcRect;
  511. ClipRect.Bottom := WindMaxY - 1;
  512. ScrollConsoleScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE), SrcRect, ClipRect,
  513. DestCoor, CharInfo);
  514. end; { proc. InsLine }
  515. {****************************************************************************
  516. Extra Crt Functions
  517. ****************************************************************************}
  518. procedure cursoron;
  519. var CursorInfo: TConsoleCursorInfo;
  520. begin
  521. GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  522. CursorInfo.dwSize := SaveCursorSize;
  523. CursorInfo.bVisible := true;
  524. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  525. end;
  526. procedure cursoroff;
  527. var CursorInfo: TConsoleCursorInfo;
  528. begin
  529. GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  530. CursorInfo.bVisible := false;
  531. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  532. end;
  533. procedure cursorbig;
  534. var CursorInfo: TConsoleCursorInfo;
  535. begin
  536. GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  537. CursorInfo.dwSize := 100;
  538. CursorInfo.bVisible := true;
  539. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  540. end;
  541. {*****************************************************************************
  542. Read and Write routines
  543. *****************************************************************************}
  544. var
  545. CurrX, CurrY : DWord;
  546. procedure WriteChar(c : char);
  547. var
  548. WritePos: Coord; { Upper-left cell to write from }
  549. numWritten : DWord;
  550. WinAttr : word;
  551. begin
  552. Case C of
  553. #10 : begin
  554. Inc(CurrY);
  555. end;
  556. #13 : begin
  557. CurrX := WindMinX;
  558. end; { if }
  559. #08 : begin
  560. if CurrX > WindMinX then Dec(CurrX);
  561. end; { ^H }
  562. #07 : begin
  563. //MessagBeep(0);
  564. end; { ^G }
  565. else begin
  566. WritePos.X := currX - 1;
  567. WritePos.Y := currY - 1;
  568. WriteConsoleOutputCharacter(GetStdhandle(STD_OUTPUT_HANDLE),
  569. @c, 1, writePos, numWritten);
  570. WinAttr:=TextAttr;
  571. WriteConsoleOutputAttribute(GetStdhandle(STD_OUTPUT_HANDLE),
  572. @WinAttr, 1, writePos, numWritten);
  573. Inc(CurrX);
  574. end; { else }
  575. end; { case }
  576. if CurrX > WindMaxX then begin
  577. CurrX := WindMinX;
  578. Inc(CurrY);
  579. end; { if }
  580. While CurrY > WindMaxY do 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 begin
  600. WriteChar(#8);
  601. WriteChar(' ');
  602. WriteChar(#8);
  603. dec(f.bufpos);
  604. dec(f.bufend);
  605. end;
  606. end;
  607. var
  608. ch : Char;
  609. Begin
  610. GetScreenCursor(CurrX,CurrY);
  611. f.bufpos:=0;
  612. f.bufend:=0;
  613. repeat
  614. if f.bufpos>f.bufend then
  615. f.bufend:=f.bufpos;
  616. SetScreenCursor(CurrX,CurrY);
  617. ch:=readkey;
  618. case ch of
  619. #0 : case readkey of
  620. #71 : while f.bufpos>0 do begin
  621. dec(f.bufpos);
  622. WriteChar(#8);
  623. end;
  624. #75 : if f.bufpos>0 then begin
  625. dec(f.bufpos);
  626. WriteChar(#8);
  627. end;
  628. #77 : if f.bufpos<f.bufend then begin
  629. WriteChar(f.bufptr^[f.bufpos]);
  630. inc(f.bufpos);
  631. end;
  632. #79 : while f.bufpos<f.bufend do begin
  633. WriteChar(f.bufptr^[f.bufpos]);
  634. inc(f.bufpos);
  635. end;
  636. end;
  637. ^S,
  638. #8 : BackSpace;
  639. ^Y,
  640. #27 : begin
  641. while f.bufpos<f.bufend do begin
  642. WriteChar(f.bufptr^[f.bufpos]);
  643. inc(f.bufpos);
  644. end;
  645. while f.bufend>0 do
  646. BackSpace;
  647. end;
  648. #13 : begin
  649. WriteChar(#13);
  650. WriteChar(#10);
  651. f.bufptr^[f.bufend]:=#13;
  652. f.bufptr^[f.bufend+1]:=#10;
  653. inc(f.bufend,2);
  654. break;
  655. end;
  656. #26 : if CheckEOF then begin
  657. f.bufptr^[f.bufend]:=#26;
  658. inc(f.bufend);
  659. break;
  660. end;
  661. else begin
  662. if f.bufpos<f.bufsize-2 then begin
  663. f.buffer[f.bufpos]:=ch;
  664. inc(f.bufpos);
  665. WriteChar(ch);
  666. end;
  667. end;
  668. end;
  669. until false;
  670. f.bufpos:=0;
  671. SetScreenCursor(CurrX, CurrY);
  672. CrtRead:=0;
  673. End;
  674. Function CrtReturn(Var F:TextRec):Integer;
  675. Begin
  676. CrtReturn:=0;
  677. end;
  678. Function CrtClose(Var F: TextRec): Integer;
  679. Begin
  680. F.Mode:=fmClosed;
  681. CrtClose:=0;
  682. End;
  683. Function CrtOpen(Var F: TextRec): Integer;
  684. Begin
  685. If F.Mode=fmOutput Then begin
  686. TextRec(F).InOutFunc:=@CrtWrite;
  687. TextRec(F).FlushFunc:=@CrtWrite;
  688. end Else begin
  689. F.Mode:=fmInput;
  690. TextRec(F).InOutFunc:=@CrtRead;
  691. TextRec(F).FlushFunc:=@CrtReturn;
  692. end;
  693. TextRec(F).CloseFunc:=@CrtClose;
  694. CrtOpen:=0;
  695. End;
  696. procedure AssignCrt(var F: Text);
  697. begin
  698. Assign(F,'');
  699. TextRec(F).OpenFunc:=@CrtOpen;
  700. end;
  701. var
  702. CursorInfo : TConsoleCursorInfo;
  703. ConsoleInfo : TConsoleScreenBufferinfo;
  704. // ts
  705. begin
  706. { Initialize the output handles }
  707. LastMode := 3;
  708. SetActiveWindow(0);
  709. {--------------------- Get the cursor size and such -----------------------}
  710. FillChar(CursorInfo, SizeOf(CursorInfo), 00);
  711. GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), CursorInfo);
  712. SaveCursorSize := CursorInfo.dwSize;
  713. {------------------ Get the current cursor position and attr --------------}
  714. FillChar(ConsoleInfo, SizeOf(ConsoleInfo), 0);
  715. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), ConsoleInfo);
  716. TextAttr := ConsoleInfo.wAttributes;
  717. { Not required, the dos crt does also not touch the mouse }
  718. {TurnMouseOff;}
  719. WindMinX := (ConsoleInfo.srWindow.Left) + 1;
  720. WindMinY := (ConsoleInfo.srWindow.Top) + 1;
  721. WindMaxX := (ConsoleInfo.srWindow.Right) + 1;
  722. WindMaxY := (ConsoleInfo.srWindow.Bottom) + 1;
  723. DoingNumChars := false;
  724. DoingNumCode := 0;
  725. { Redirect the standard output }
  726. AssignCrt(Output);
  727. Rewrite(Output);
  728. TextRec(Output).Handle:= GetStdHandle(STD_OUTPUT_HANDLE);
  729. AssignCrt(Input);
  730. Reset(Input);
  731. TextRec(Input).Handle:= GetStdHandle(STD_INPUT_HANDLE);
  732. end. { unit Crt }
  733. {
  734. $Log$
  735. Revision 1.20 2003-11-03 09:42:28 marco
  736. * Peter's Cardinal<->Longint fixes patch
  737. Revision 1.19 2002/12/15 20:23:30 peter
  738. * fix empty string in readln when not at end of string
  739. * fix alt-xyz in readkey
  740. Revision 1.18 2002/10/06 20:00:22 peter
  741. * Use Widechar in the Windows unit
  742. Revision 1.17 2002/09/07 16:01:28 peter
  743. * old logs removed and tabs fixed
  744. Revision 1.16 2002/01/19 11:56:34 peter
  745. * fixed clrscr for small windows
  746. * no turnoffmouse
  747. }