video.pp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Video unit for Win32
  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. unit Video;
  14. interface
  15. {$i videoh.inc}
  16. implementation
  17. uses
  18. windows,dos;
  19. {$i video.inc}
  20. var
  21. OldVideoBuf : PVideoBuf;
  22. ConsoleInfo : TConsoleScreenBufferInfo;
  23. ConsoleCursorInfo : TConsoleCursorInfo;
  24. MaxVideoBufSize : DWord;
  25. procedure InitVideo;
  26. begin
  27. ScreenColor:=true;
  28. GetConsoleScreenBufferInfo(TextRec(Output).Handle, ConsoleInfo);
  29. GetConsoleCursorInfo(TextRec(Output).Handle, ConsoleCursorInfo);
  30. with ConsoleInfo.srWindow do
  31. begin
  32. ScreenWidth:=right-left+1;
  33. ScreenHeight:=bottom-top+1;
  34. end;
  35. { srWindow is sometimes bigger then dwMaximumWindowSize
  36. this led to wrong ScreenWidth and ScreenHeight values PM }
  37. { damned: its also sometimes less !! PM }
  38. with ConsoleInfo.dwMaximumWindowSize do
  39. begin
  40. {if ScreenWidth>X then}
  41. ScreenWidth:=X;
  42. {if ScreenHeight>Y then}
  43. ScreenHeight:=Y;
  44. end;
  45. { TDrawBuffer only has FVMaxWidth elements
  46. larger values lead to crashes }
  47. if ScreenWidth> FVMaxWidth then
  48. ScreenWidth:=FVMaxWidth;
  49. CursorX:=ConsoleInfo.dwCursorPosition.x;
  50. CursorY:=ConsoleInfo.dwCursorPosition.y;
  51. if not ConsoleCursorInfo.bvisible then
  52. CursorLines:=0
  53. else
  54. CursorLines:=ConsoleCursorInfo.dwSize;
  55. { allocate back buffer }
  56. MaxVideoBufSize:= ScreenWidth * ScreenHeight * 2;
  57. VideoBufSize:=ScreenWidth*ScreenHeight*2;
  58. GetMem(VideoBuf,MaxVideoBufSize);
  59. GetMem(OldVideoBuf,MaxVideoBufSize);
  60. {ClearScreen; not needed PM }
  61. end;
  62. procedure DoneVideo;
  63. begin
  64. { ClearScreen; also not needed PM }
  65. SetCursorType(crUnderLine);
  66. { SetCursorPos(0,0); also not needed PM }
  67. FreeMem(VideoBuf,MaxVideoBufSize);
  68. FreeMem(OldVideoBuf,MaxVideoBufSize);
  69. VideoBufSize:=0;
  70. end;
  71. function GetCapabilities: Word;
  72. begin
  73. GetCapabilities:=cpColor or cpChangeCursor;
  74. end;
  75. procedure SetCursorPos(NewCursorX, NewCursorY: Word);
  76. var
  77. pos : COORD;
  78. begin
  79. pos.x:=NewCursorX;
  80. pos.y:=NewCursorY;
  81. SetConsoleCursorPosition(TextRec(Output).Handle,pos);
  82. CursorX:=pos.x;
  83. CursorY:=pos.y;
  84. end;
  85. function GetCursorType: Word;
  86. begin
  87. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  88. if not ConsoleCursorInfo.bvisible then
  89. GetCursorType:=crHidden
  90. else
  91. case ConsoleCursorInfo.dwSize of
  92. 1..30:
  93. GetCursorType:=crUnderline;
  94. 31..70:
  95. GetCursorType:=crHalfBlock;
  96. 71..100:
  97. GetCursorType:=crBlock;
  98. end;
  99. end;
  100. procedure SetCursorType(NewType: Word);
  101. begin
  102. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  103. if newType=crHidden then
  104. ConsoleCursorInfo.bvisible:=false
  105. else
  106. begin
  107. ConsoleCursorInfo.bvisible:=true;
  108. case NewType of
  109. crUnderline:
  110. ConsoleCursorInfo.dwSize:=10;
  111. crHalfBlock:
  112. ConsoleCursorInfo.dwSize:=50;
  113. crBlock:
  114. ConsoleCursorInfo.dwSize:=99;
  115. end
  116. end;
  117. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  118. end;
  119. function DefaultVideoModeSelector(const VideoMode: TVideoMode; Params: Longint): Boolean;
  120. begin
  121. DefaultVideoModeSelector:=true;
  122. end;
  123. procedure ClearScreen;
  124. begin
  125. FillWord(VideoBuf^,VideoBufSize div 2,$0720);
  126. UpdateScreen(true);
  127. end;
  128. {$IFDEF FPC}
  129. function WriteConsoleOutput(hConsoleOutput:HANDLE; lpBuffer:pointer; dwBufferSize:COORD; dwBufferCoord:COORD;
  130. var lpWriteRegion:SMALL_RECT):WINBOOL; external 'kernel32' name 'WriteConsoleOutputA';
  131. {$ENDIF}
  132. procedure UpdateScreen(Force: Boolean);
  133. type TmpRec = Array[0..(1024*32) - 1] of TCharInfo;
  134. type WordRec = record
  135. One, Two: Byte;
  136. end; { wordrec }
  137. var
  138. BufSize,
  139. BufCoord : COORD;
  140. WriteRegion : SMALL_RECT;
  141. LineBuf : ^TmpRec;
  142. BufCounter : Longint;
  143. LineCounter,
  144. ColCounter : Longint;
  145. smallforce : boolean;
  146. (*
  147. begin
  148. if LockUpdateScreen<>0 then
  149. exit;
  150. if not force then
  151. begin
  152. asm
  153. movl VideoBuf,%esi
  154. movl OldVideoBuf,%edi
  155. movl VideoBufSize,%ecx
  156. shrl $2,%ecx
  157. repe
  158. cmpsl
  159. setne force
  160. end;
  161. end;
  162. if Force then
  163. begin
  164. BufSize.X := ScreenWidth;
  165. BufSize.Y := ScreenHeight;
  166. BufCoord.X := 0;
  167. BufCoord.Y := 0;
  168. with WriteRegion do
  169. begin
  170. Top :=0;
  171. Left :=0;
  172. Bottom := ScreenHeight-1;
  173. Right := ScreenWidth-1;
  174. end;
  175. New(LineBuf);
  176. BufCounter := 0;
  177. for LineCounter := 1 to ScreenHeight do
  178. begin
  179. for ColCounter := 1 to ScreenWidth do
  180. begin
  181. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  182. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  183. Inc(BufCounter);
  184. end; { for }
  185. end; { for }
  186. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  187. Dispose(LineBuf);
  188. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  189. end;
  190. end;
  191. *)
  192. var
  193. x1,y1,x2,y2 : longint;
  194. begin
  195. if LockUpdateScreen<>0 then
  196. exit;
  197. if force then
  198. smallforce:=true
  199. else
  200. begin
  201. asm
  202. movl VideoBuf,%esi
  203. movl OldVideoBuf,%edi
  204. movl VideoBufSize,%ecx
  205. shrl $2,%ecx
  206. repe
  207. cmpsl
  208. orl %ecx,%ecx
  209. jz .Lno_update
  210. movb $1,smallforce
  211. .Lno_update:
  212. end;
  213. end;
  214. if SmallForce then
  215. begin
  216. BufSize.X := ScreenWidth;
  217. BufSize.Y := ScreenHeight;
  218. BufCoord.X := 0;
  219. BufCoord.Y := 0;
  220. with WriteRegion do
  221. begin
  222. Top :=0;
  223. Left :=0;
  224. Bottom := ScreenHeight-1;
  225. Right := ScreenWidth-1;
  226. end;
  227. New(LineBuf);
  228. BufCounter := 0;
  229. x1:=ScreenWidth+1;
  230. x2:=-1;
  231. y1:=ScreenHeight+1;
  232. y2:=-1;
  233. for LineCounter := 1 to ScreenHeight do
  234. begin
  235. for ColCounter := 1 to ScreenWidth do
  236. begin
  237. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  238. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  239. begin
  240. if ColCounter<x1 then
  241. x1:=ColCounter;
  242. if ColCounter>x2 then
  243. x2:=ColCounter;
  244. if LineCounter<y1 then
  245. y1:=LineCounter;
  246. if LineCounter>y2 then
  247. y2:=LineCounter;
  248. end;
  249. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  250. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  251. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  252. else }
  253. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  254. Inc(BufCounter);
  255. end; { for }
  256. end; { for }
  257. BufSize.X := ScreenWidth;
  258. BufSize.Y := ScreenHeight;
  259. with WriteRegion do
  260. begin
  261. if force then
  262. begin
  263. Top := 0;
  264. Left :=0;
  265. Bottom := ScreenHeight-1;
  266. Right := ScreenWidth-1;
  267. BufCoord.X := 0;
  268. BufCoord.Y := 0;
  269. end
  270. else
  271. begin
  272. Top := y1-1;
  273. Left :=x1-1;
  274. Bottom := y2-1;
  275. Right := x2-1;
  276. BufCoord.X := x1-1;
  277. BufCoord.Y := y1-1;
  278. end;
  279. end;
  280. {
  281. writeln('X1: ',x1);
  282. writeln('Y1: ',y1);
  283. writeln('X2: ',x2);
  284. writeln('Y2: ',y2);
  285. }
  286. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  287. Dispose(LineBuf);
  288. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  289. end;
  290. end;
  291. procedure RegisterVideoModes;
  292. begin
  293. { don't know what to do for win32 (FK) }
  294. RegisterVideoMode(80, 25, True, @DefaultVideoModeSelector, $00000003);
  295. end;
  296. initialization
  297. RegisterVideoModes;
  298. finalization
  299. UnRegisterVideoModes;
  300. end.
  301. {
  302. $Log$
  303. Revision 1.2 2001-04-10 21:28:36 peter
  304. * removed warnigns
  305. Revision 1.1 2001/01/13 11:03:59 peter
  306. * API 2 RTL commit
  307. }