crt.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. {$ifdef HASTHREADVAR}
  164. threadvar
  165. {$else HASTHREADVAR}
  166. var
  167. {$endif HASTHREADVAR}
  168. CurrX, CurrY: dword;
  169. procedure WriteChar (C: char);
  170. begin
  171. case C of
  172. #7: WriteBell;
  173. #8: if CurrX >= WindMinX then
  174. Dec (CurrX);
  175. { #9: x:=(x-lo(windmin)) and $fff8+8+lo(windmin);}
  176. #10: Inc (CurrY);
  177. #13: CurrX := WindMinX;
  178. else
  179. begin
  180. WriteNormal (C, CurrX, CurrY);
  181. Inc (CurrX);
  182. end;
  183. end;
  184. if CurrX > WindMaxX then
  185. begin
  186. CurrX := WindMinX;
  187. Inc (CurrY);
  188. end;
  189. if CurrY > WindMaxY then
  190. begin
  191. RemoveLines (0, 1);
  192. CurrY := WindMaxY;
  193. end;
  194. end;
  195. function CrtWrite (var F: TextRec): integer;
  196. var
  197. I: dword;
  198. {Write a series of characters to the console.}
  199. begin
  200. if F.BufPos > 0 then
  201. begin
  202. GetScreenCursor (CurrX, CurrY);
  203. for I := 0 to Pred (F.BufPos) do
  204. WriteChar ((PChar (F.BufPtr) + I)^);
  205. SetScreenCursor (CurrX, CurrY);
  206. F.BufPos := 0;
  207. end;
  208. CrtWrite := 0;
  209. end;
  210. function CrtRead (var F: TextRec): integer;
  211. {Read a series of characters from the console.}
  212. var
  213. C: char;
  214. begin
  215. GetScreenCursor (CurrX, CurrY);
  216. F.BufPos := 0;
  217. F.BufEnd := 0;
  218. repeat
  219. if F.BufPos > F.BufEnd then
  220. F.BufEnd := F.BufPos;
  221. SetScreenCursor (CurrX, CurrY);
  222. C := ReadKey;
  223. case C of
  224. #0: ReadKey;
  225. (* The following code to support input editing is incomplete anyway
  226. - no handling of line breaks, no possibility to insert characters
  227. or delete characters inside the string, etc.
  228. #0 : case readkey of
  229. #71 : while f.bufpos>0 do
  230. begin
  231. dec(f.bufpos);
  232. WriteChar(#8);
  233. end;
  234. #75 : if f.bufpos>0 then
  235. begin
  236. dec(f.bufpos);
  237. WriteChar(#8);
  238. end;
  239. #77 : if f.bufpos<f.bufend then
  240. begin
  241. WriteChar(f.bufptr^[f.bufpos]);
  242. inc(f.bufpos);
  243. end;
  244. #79 : while f.bufpos<f.bufend do
  245. begin
  246. WriteChar(f.bufptr^[f.bufpos]);
  247. inc(f.bufpos);
  248. end;
  249. end;
  250. *)
  251. #8: if (F.BufPos > 0) and (F.BufPos = F.BufEnd) then
  252. begin
  253. {$WARNING CrtRead doesn't handle line breaks correctly (same bug as TP/BP)!}
  254. WriteChar (#8);
  255. WriteChar (' ');
  256. WriteChar (#8);
  257. Dec (F.BufPos);
  258. Dec (F.BufEnd);
  259. end;
  260. #13: begin
  261. WriteChar(#13);
  262. WriteChar(#10);
  263. F.BufPtr^ [F.BufEnd] := #13;
  264. Inc (F.BufEnd);
  265. F.BufPtr^ [F.BufEnd] := #10;
  266. Inc (F.BufEnd);
  267. break;
  268. end;
  269. #26: if CheckEOF then
  270. begin
  271. F.BufPtr^ [F.BufEnd] := #26;
  272. Inc (F.BufEnd);
  273. break;
  274. end;
  275. #32..#255: if F.BufPos < F.BufSize - 2 then
  276. begin
  277. F.BufPtr^ [F.BufPos] := C;
  278. Inc (F.BufPos);
  279. WriteChar (C);
  280. end;
  281. end
  282. until false;
  283. CrtRead := 0;
  284. end;
  285. function CrtReturn (var F: TextRec): integer;
  286. begin
  287. CrtReturn:=0;
  288. end;
  289. function CrtClose (var F: TextRec): integer;
  290. begin
  291. F.Mode := fmClosed;
  292. CrtClose := 0;
  293. end;
  294. function CrtOpen (var F: TextRec): integer;
  295. begin
  296. if F.Mode = fmOutput then
  297. begin
  298. TextRec(F).InOutFunc := @CrtWrite;
  299. TextRec(F).FlushFunc := @CrtWrite;
  300. end
  301. else
  302. begin
  303. F.Mode := fmInput;
  304. TextRec(F).InOutFunc := @CrtRead;
  305. TextRec(F).FlushFunc := @CrtReturn;
  306. end;
  307. TextRec(F).CloseFunc := @CrtClose;
  308. CrtOpen := 0;
  309. end;
  310. procedure AssignCrt (var F: text);
  311. {Assigns a file to the crt console.}
  312. begin
  313. Assign (F, '');
  314. TextRec (F).OpenFunc := @CrtOpen;
  315. end;
  316. {$IFNDEF HAS_SOUND}
  317. procedure Sound (Hz: word);
  318. (* Dummy Sound implementation - for platforms requiring both frequence
  319. and duration at the beginning instead of start and stop procedures. *)
  320. begin
  321. end;
  322. {$ENDIF HAS_SOUND}
  323. {$IFNDEF HAS_NOSOUND}
  324. procedure NoSound;
  325. (* Dummy NoSound implementation - for platforms requiring both frequence
  326. and duration at the beginning instead of start and stop procedures. *)
  327. begin
  328. end;
  329. {$ENDIF HAS_NOSOUND}
  330. procedure CrtInit;
  331. (* Common part of unit initialization. *)
  332. begin
  333. TextAttr := LightGray;
  334. WindMin := 0;
  335. WindMaxX := Pred (ScreenWidth);
  336. WindMaxY := Pred (ScreenHeight);
  337. if WindMaxX >= 255 then
  338. WindMax := 255
  339. else
  340. WindMax := WindMaxX;
  341. if WindMaxY >= 255 then
  342. WindMax := WindMax or $FF00
  343. else
  344. WindMax := WindMax or (WindMaxY shl 8);
  345. ExtKeyCode := #0;
  346. AssignCrt (Input);
  347. Reset (Input);
  348. AssignCrt (Output);
  349. Rewrite (Output);
  350. end;
  351. {
  352. $Log: crt.inc,v $
  353. Revision 1.3 2005/05/14 15:01:49 hajny
  354. * TextMode parameter type changed to word for TP/BP compatibility
  355. Revision 1.2 2005/05/14 14:58:41 hajny
  356. * TextMode parameter type changed temporarily not to break other platforms
  357. Revision 1.1 2005/05/14 14:32:55 hajny
  358. + basis for common platform independent implementation of Crt
  359. }