crt.inc 8.9 KB

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