crt.inc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1998 - 2005 by the Free Pascal development team.
  4. This file implements platform independent routines for Crt.
  5. It should be modified later to use routines from Keyboard and
  6. Video instead of code in platform-specific crt.pas.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. procedure GotoXY (X: byte; Y: byte);
  14. begin
  15. GotoXY32 (X, Y);
  16. end;
  17. procedure Window (X1, Y1, X2, Y2: byte);
  18. begin
  19. Window32 (X1, Y1, X2, Y2);
  20. end;
  21. function WhereX: byte;
  22. var
  23. X1: dword;
  24. begin
  25. X1 := WhereX32;
  26. if X1 > 255 then
  27. WhereX := 255
  28. else
  29. WhereX := X1;
  30. end;
  31. function WhereY: byte;
  32. var
  33. Y1: dword;
  34. begin
  35. Y1 := WhereY32;
  36. if Y1 > 255 then
  37. WhereY := 255
  38. else
  39. WhereY := Y1;
  40. end;
  41. procedure ClrScr;
  42. {Clears the current window.}
  43. begin
  44. RemoveLines (0, Succ (WindMaxY - WindMinY));
  45. GotoXY32 (1, 1);
  46. end;
  47. procedure GotoXY32 (X, Y: dword);
  48. (* Positions cursor on (X, Y) (1-based) relative to window origin; for TP/BP
  49. compatibility call completely ignored in case of incorrect parameters. *)
  50. begin
  51. if (X > 0) and (Y > 0) then
  52. begin
  53. Dec (X);
  54. Dec (Y);
  55. if (X <= WindMaxX - WindMinX) and (Y <= WindMaxY - WindMinY) then
  56. SetScreenCursor (X + WindMinX, Y + WindMinY);
  57. end;
  58. end;
  59. function WhereX32: dword;
  60. (* Returns the X position of the cursor (1-based). *)
  61. var
  62. X, Y: dword;
  63. begin
  64. GetScreenCursor (X, Y);
  65. WhereX32 := Succ (X - WindMinX);
  66. end;
  67. function WhereY32: dword;
  68. (* Returns the Y position of the cursor (1-based). *)
  69. var
  70. X, Y: dword;
  71. begin
  72. GetScreenCursor (X, Y);
  73. WhereY32 := Succ (Y - WindMinY);
  74. end;
  75. procedure ClrEol;
  76. (* Clears the line where cursor is located from current position up to end. *)
  77. var
  78. X, Y: dword;
  79. begin
  80. GetScreenCursor (X, Y);
  81. ClearCells (X, Y, Succ (WindMaxX - X));
  82. end;
  83. procedure DelLine;
  84. (* Deletes the line at cursor. *)
  85. begin
  86. RemoveLines (Pred (WhereY32), 1);
  87. end;
  88. procedure TextMode (Mode: word);
  89. { Use this procedure to set-up a specific text-mode.}
  90. begin
  91. TextAttr := $07;
  92. LastMode := Mode;
  93. SetScreenMode (Mode);
  94. WindMin := 0;
  95. WindMaxX := Pred (ScreenWidth);
  96. WindMaxY := Pred (ScreenHeight);
  97. if WindMaxX >= 255 then
  98. WindMax := 255
  99. else
  100. WindMax := WindMaxX;
  101. if WindMaxY >= 255 then
  102. WindMax := WindMax or $FF00
  103. else
  104. WindMax := WindMax or (WindMaxY shl 8);
  105. ClrScr;
  106. end;
  107. procedure TextColor (Color: byte);
  108. {All text written after calling this will have Color as foreground colour.}
  109. begin
  110. TextAttr := (TextAttr and $70) or (Color and $f);
  111. if Color > 15 then
  112. TextAttr := TextAttr or 128;
  113. end;
  114. procedure TextBackground (Color: byte);
  115. {All text written after calling this will have Color as background colour.}
  116. begin
  117. TextAttr := (TextAttr and $8F) or ((Color and $7) shl 4);
  118. end;
  119. procedure NormVideo;
  120. {Changes the text-background to black and the foreground to white.}
  121. begin
  122. TextAttr := $7;
  123. end;
  124. procedure LowVideo;
  125. {All text written after this will have low intensity.}
  126. begin
  127. TextAttr := TextAttr and $F7;
  128. end;
  129. procedure HighVideo;
  130. {All text written after this will have high intensity.}
  131. begin
  132. TextAttr := TextAttr or $8;
  133. end;
  134. procedure Window32 (X1, Y1, X2, Y2: dword);
  135. {Change the write window to the given coordinates.}
  136. begin
  137. if (X1 > 0) and (Y1 > 0) and (X2 <= ScreenWidth) and (Y2 <= ScreenHeight)
  138. and (X1 <= X2) and (Y1 <= Y2) then
  139. begin
  140. WindMinX := Pred (X1);
  141. WindMinY := Pred (Y1);
  142. if WindMinX >= 255 then
  143. WindMin := 255
  144. else
  145. WindMin := WindMinX;
  146. if WindMinY >= 255 then
  147. WindMin := WindMin or $FF00
  148. else
  149. WindMin := WindMin or (WindMinY shl 8);
  150. WindMaxX := Pred (X2);
  151. WindMaxY := Pred (Y2);
  152. if WindMaxX >= 255 then
  153. WindMax := 255
  154. else
  155. WindMax := WindMaxX;
  156. if WindMaxY >= 255 then
  157. WindMax := WindMax or $FF00
  158. else
  159. WindMax := WindMaxX or (WindMaxY shl 8);
  160. GotoXY32 (1, 1);
  161. end;
  162. end;
  163. threadvar
  164. CurrX, CurrY: dword;
  165. procedure WriteChar (C: char);
  166. begin
  167. case C of
  168. #7: WriteBell;
  169. #8: if CurrX >= WindMinX then
  170. Dec (CurrX);
  171. { #9: x:=(x-lo(windmin)) and $fff8+8+lo(windmin);}
  172. #10: Inc (CurrY);
  173. #13: CurrX := WindMinX;
  174. else
  175. begin
  176. WriteNormal (C, CurrX, CurrY);
  177. Inc (CurrX);
  178. end;
  179. end;
  180. if CurrX > WindMaxX then
  181. begin
  182. CurrX := WindMinX;
  183. Inc (CurrY);
  184. end;
  185. if CurrY > WindMaxY then
  186. begin
  187. RemoveLines (0, 1);
  188. CurrY := WindMaxY;
  189. end;
  190. end;
  191. function CrtWrite (var F: TextRec): integer;
  192. var
  193. I: dword;
  194. {Write a series of characters to the console.}
  195. begin
  196. if F.BufPos > 0 then
  197. begin
  198. GetScreenCursor (CurrX, CurrY);
  199. for I := 0 to Pred (F.BufPos) do
  200. WriteChar ((PChar (F.BufPtr) + I)^);
  201. SetScreenCursor (CurrX, CurrY);
  202. F.BufPos := 0;
  203. end;
  204. CrtWrite := 0;
  205. end;
  206. function CrtRead (var F: TextRec): integer;
  207. {Read a series of characters from the console.}
  208. var
  209. C: char;
  210. begin
  211. GetScreenCursor (CurrX, CurrY);
  212. F.BufPos := 0;
  213. F.BufEnd := 0;
  214. repeat
  215. if F.BufPos > F.BufEnd then
  216. F.BufEnd := F.BufPos;
  217. SetScreenCursor (CurrX, CurrY);
  218. C := ReadKey;
  219. case C of
  220. #0: ReadKey;
  221. (* The following code to support input editing is incomplete anyway
  222. - no handling of line breaks, no possibility to insert characters
  223. or delete characters inside the string, etc.
  224. #0 : case readkey of
  225. #71 : while f.bufpos>0 do
  226. begin
  227. dec(f.bufpos);
  228. WriteChar(#8);
  229. end;
  230. #75 : if f.bufpos>0 then
  231. begin
  232. dec(f.bufpos);
  233. WriteChar(#8);
  234. end;
  235. #77 : if f.bufpos<f.bufend then
  236. begin
  237. WriteChar(f.bufptr^[f.bufpos]);
  238. inc(f.bufpos);
  239. end;
  240. #79 : while f.bufpos<f.bufend do
  241. begin
  242. WriteChar(f.bufptr^[f.bufpos]);
  243. inc(f.bufpos);
  244. end;
  245. end;
  246. *)
  247. #8: if (F.BufPos > 0) and (F.BufPos = F.BufEnd) then
  248. begin
  249. {$WARNING CrtRead doesn't handle line breaks correctly (same bug as TP/BP)!}
  250. WriteChar (#8);
  251. WriteChar (' ');
  252. WriteChar (#8);
  253. Dec (F.BufPos);
  254. Dec (F.BufEnd);
  255. end;
  256. #13: begin
  257. WriteChar(#13);
  258. WriteChar(#10);
  259. F.BufPtr^ [F.BufEnd] := #13;
  260. Inc (F.BufEnd);
  261. F.BufPtr^ [F.BufEnd] := #10;
  262. Inc (F.BufEnd);
  263. break;
  264. end;
  265. #26: if CheckEOF then
  266. begin
  267. F.BufPtr^ [F.BufEnd] := #26;
  268. Inc (F.BufEnd);
  269. break;
  270. end;
  271. #32..#255: if F.BufPos < F.BufSize - 2 then
  272. begin
  273. F.BufPtr^ [F.BufPos] := C;
  274. Inc (F.BufPos);
  275. WriteChar (C);
  276. end;
  277. end
  278. until false;
  279. CrtRead := 0;
  280. end;
  281. function CrtReturn (var F: TextRec): integer;
  282. begin
  283. CrtReturn:=0;
  284. end;
  285. function CrtClose (var F: TextRec): integer;
  286. begin
  287. F.Mode := fmClosed;
  288. CrtClose := 0;
  289. end;
  290. function CrtOpen (var F: TextRec): integer;
  291. begin
  292. if F.Mode = fmOutput then
  293. begin
  294. TextRec(F).InOutFunc := @CrtWrite;
  295. TextRec(F).FlushFunc := @CrtWrite;
  296. end
  297. else
  298. begin
  299. F.Mode := fmInput;
  300. TextRec(F).InOutFunc := @CrtRead;
  301. TextRec(F).FlushFunc := @CrtReturn;
  302. end;
  303. TextRec(F).CloseFunc := @CrtClose;
  304. CrtOpen := 0;
  305. end;
  306. procedure AssignCrt (var F: text);
  307. {Assigns a file to the crt console.}
  308. begin
  309. Assign (F, '');
  310. TextRec (F).OpenFunc := @CrtOpen;
  311. end;
  312. {$IFNDEF HAS_SOUND}
  313. procedure Sound (Hz: word);
  314. (* Dummy Sound implementation - for platforms requiring both frequence
  315. and duration at the beginning instead of start and stop procedures. *)
  316. begin
  317. end;
  318. {$ENDIF HAS_SOUND}
  319. {$IFNDEF HAS_NOSOUND}
  320. procedure NoSound;
  321. (* Dummy NoSound implementation - for platforms requiring both frequence
  322. and duration at the beginning instead of start and stop procedures. *)
  323. begin
  324. end;
  325. {$ENDIF HAS_NOSOUND}
  326. procedure CrtInit;
  327. (* Common part of unit initialization. *)
  328. begin
  329. TextAttr := LightGray;
  330. WindMin := 0;
  331. WindMaxX := Pred (ScreenWidth);
  332. WindMaxY := Pred (ScreenHeight);
  333. if WindMaxX >= 255 then
  334. WindMax := 255
  335. else
  336. WindMax := WindMaxX;
  337. if WindMaxY >= 255 then
  338. WindMax := WindMax or $FF00
  339. else
  340. WindMax := WindMax or (WindMaxY shl 8);
  341. ExtKeyCode := #0;
  342. AssignCrt (Input);
  343. Reset (Input);
  344. AssignCrt (Output);
  345. Rewrite (Output);
  346. end;