video.pp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. ConsoleInfo : TConsoleScreenBufferInfo;
  22. ConsoleCursorInfo : TConsoleCursorInfo;
  23. procedure SysInitVideo;
  24. begin
  25. ScreenColor:=true;
  26. GetConsoleScreenBufferInfo(TextRec(Output).Handle, ConsoleInfo);
  27. GetConsoleCursorInfo(TextRec(Output).Handle, ConsoleCursorInfo);
  28. {
  29. About the ConsoleCursorInfo record: There are 3 possible
  30. structures in it that can be regarded as the 'screen':
  31. - dwsize : contains the cols & row in current screen buffer.
  32. - srwindow : Coordinates (relative to buffer) of upper left
  33. & lower right corners of visible console.
  34. - dmMaximumWindowSize : Maximal size of Screen buffer.
  35. The first implementation of video used srWindow. After some
  36. bug-reports, this was switched to dwMaximumWindowSize.
  37. }
  38. with ConsoleInfo.dwMaximumWindowSize do
  39. begin
  40. ScreenWidth:=X;
  41. ScreenHeight:=Y;
  42. end;
  43. { TDrawBuffer only has FVMaxWidth elements
  44. larger values lead to crashes }
  45. if ScreenWidth> FVMaxWidth then
  46. ScreenWidth:=FVMaxWidth;
  47. CursorX:=ConsoleInfo.dwCursorPosition.x;
  48. CursorY:=ConsoleInfo.dwCursorPosition.y;
  49. if not ConsoleCursorInfo.bvisible then
  50. CursorLines:=0
  51. else
  52. CursorLines:=ConsoleCursorInfo.dwSize;
  53. end;
  54. procedure SysDoneVideo;
  55. begin
  56. SetCursorType(crUnderLine);
  57. end;
  58. function SysGetCapabilities: Word;
  59. begin
  60. SysGetCapabilities:=cpColor or cpChangeCursor;
  61. end;
  62. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  63. var
  64. pos : COORD;
  65. begin
  66. pos.x:=NewCursorX;
  67. pos.y:=NewCursorY;
  68. SetConsoleCursorPosition(TextRec(Output).Handle,pos);
  69. CursorX:=pos.x;
  70. CursorY:=pos.y;
  71. end;
  72. function SysGetCursorType: Word;
  73. begin
  74. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  75. if not ConsoleCursorInfo.bvisible then
  76. SysGetCursorType:=crHidden
  77. else
  78. case ConsoleCursorInfo.dwSize of
  79. 1..30:
  80. SysGetCursorType:=crUnderline;
  81. 31..70:
  82. SysGetCursorType:=crHalfBlock;
  83. 71..100:
  84. SysGetCursorType:=crBlock;
  85. end;
  86. end;
  87. procedure SysSetCursorType(NewType: Word);
  88. begin
  89. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  90. if newType=crHidden then
  91. ConsoleCursorInfo.bvisible:=false
  92. else
  93. begin
  94. ConsoleCursorInfo.bvisible:=true;
  95. case NewType of
  96. crUnderline:
  97. ConsoleCursorInfo.dwSize:=10;
  98. crHalfBlock:
  99. ConsoleCursorInfo.dwSize:=50;
  100. crBlock:
  101. ConsoleCursorInfo.dwSize:=99;
  102. end
  103. end;
  104. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  105. end;
  106. procedure SysClearScreen;
  107. begin
  108. UpdateScreen(true);
  109. end;
  110. {$IFDEF FPC}
  111. function WriteConsoleOutput(hConsoleOutput:HANDLE; lpBuffer:pointer; dwBufferSize:COORD; dwBufferCoord:COORD;
  112. var lpWriteRegion:SMALL_RECT):WINBOOL; stdcall;external 'kernel32' name 'WriteConsoleOutputA';
  113. {$ENDIF}
  114. procedure SysUpdateScreen(Force: Boolean);
  115. type TmpRec = Array[0..(1024*32) - 1] of TCharInfo;
  116. type WordRec = record
  117. One, Two: Byte;
  118. end; { wordrec }
  119. var
  120. BufSize,
  121. BufCoord : COORD;
  122. WriteRegion : SMALL_RECT;
  123. LineBuf : ^TmpRec;
  124. BufCounter : Longint;
  125. LineCounter,
  126. ColCounter : Longint;
  127. smallforce : boolean;
  128. x1,y1,x2,y2 : longint;
  129. begin
  130. if force then
  131. smallforce:=true
  132. else
  133. begin
  134. asm
  135. movl VideoBuf,%esi
  136. movl OldVideoBuf,%edi
  137. movl VideoBufSize,%ecx
  138. shrl $2,%ecx
  139. repe
  140. cmpsl
  141. setne smallforce
  142. end;
  143. end;
  144. if SmallForce then
  145. begin
  146. BufSize.X := ScreenWidth;
  147. BufSize.Y := ScreenHeight;
  148. BufCoord.X := 0;
  149. BufCoord.Y := 0;
  150. with WriteRegion do
  151. begin
  152. Top :=0;
  153. Left :=0;
  154. Bottom := ScreenHeight-1;
  155. Right := ScreenWidth-1;
  156. end;
  157. New(LineBuf);
  158. BufCounter := 0;
  159. x1:=ScreenWidth+1;
  160. x2:=-1;
  161. y1:=ScreenHeight+1;
  162. y2:=-1;
  163. for LineCounter := 1 to ScreenHeight do
  164. begin
  165. for ColCounter := 1 to ScreenWidth do
  166. begin
  167. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  168. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  169. begin
  170. if ColCounter<x1 then
  171. x1:=ColCounter;
  172. if ColCounter>x2 then
  173. x2:=ColCounter;
  174. if LineCounter<y1 then
  175. y1:=LineCounter;
  176. if LineCounter>y2 then
  177. y2:=LineCounter;
  178. end;
  179. {$ifdef VER1_0}
  180. Word(LineBuf^[BufCounter].UniCodeChar) := WordRec(VideoBuf^[BufCounter]).One;
  181. {$else}
  182. LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
  183. {$endif}
  184. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  185. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  186. else }
  187. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  188. Inc(BufCounter);
  189. end; { for }
  190. end; { for }
  191. BufSize.X := ScreenWidth;
  192. BufSize.Y := ScreenHeight;
  193. with WriteRegion do
  194. begin
  195. if force then
  196. begin
  197. Top := 0;
  198. Left :=0;
  199. Bottom := ScreenHeight-1;
  200. Right := ScreenWidth-1;
  201. BufCoord.X := 0;
  202. BufCoord.Y := 0;
  203. end
  204. else
  205. begin
  206. Top := y1-1;
  207. Left :=x1-1;
  208. Bottom := y2-1;
  209. Right := x2-1;
  210. BufCoord.X := x1-1;
  211. BufCoord.Y := y1-1;
  212. end;
  213. end;
  214. {
  215. writeln('X1: ',x1);
  216. writeln('Y1: ',y1);
  217. writeln('X2: ',x2);
  218. writeln('Y2: ',y2);
  219. }
  220. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  221. Dispose(LineBuf);
  222. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  223. end;
  224. end;
  225. Const
  226. SysVideoDriver : TVideoDriver = (
  227. InitDriver : @SysInitVideo;
  228. DoneDriver : @SysDoneVideo;
  229. UpdateScreen : @SysUpdateScreen;
  230. ClearScreen : @SysClearScreen;
  231. SetVideoMode : Nil;
  232. GetVideoModeCount : Nil;
  233. GetVideoModeData : Nil;
  234. SetCursorPos : @SysSetCursorPos;
  235. GetCursorType : @SysGetCursorType;
  236. SetCursorType : @SysSetCursorType;
  237. GetCapabilities : @SysGetCapabilities
  238. );
  239. initialization
  240. SetVideoDriver(SysVideoDriver);
  241. end.
  242. {
  243. $Log$
  244. Revision 1.11 2003-09-17 15:06:36 peter
  245. * stdcall patch
  246. Revision 1.10 2002/12/15 20:22:56 peter
  247. * fix updatescreen compare that was wrong when the last char was
  248. different
  249. Revision 1.9 2002/10/06 20:00:22 peter
  250. * Use Widechar in the Windows unit
  251. Revision 1.8 2002/09/07 16:01:29 peter
  252. * old logs removed and tabs fixed
  253. }