2
0

video.pp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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; 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. (*
  129. begin
  130. if not force then
  131. begin
  132. asm
  133. movl VideoBuf,%esi
  134. movl OldVideoBuf,%edi
  135. movl VideoBufSize,%ecx
  136. shrl $2,%ecx
  137. repe
  138. cmpsl
  139. setne force
  140. end;
  141. end;
  142. if Force then
  143. begin
  144. BufSize.X := ScreenWidth;
  145. BufSize.Y := ScreenHeight;
  146. BufCoord.X := 0;
  147. BufCoord.Y := 0;
  148. with WriteRegion do
  149. begin
  150. Top :=0;
  151. Left :=0;
  152. Bottom := ScreenHeight-1;
  153. Right := ScreenWidth-1;
  154. end;
  155. New(LineBuf);
  156. BufCounter := 0;
  157. for LineCounter := 1 to ScreenHeight do
  158. begin
  159. for ColCounter := 1 to ScreenWidth do
  160. begin
  161. LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
  162. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  163. Inc(BufCounter);
  164. end; { for }
  165. end; { for }
  166. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  167. Dispose(LineBuf);
  168. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  169. end;
  170. end;
  171. *)
  172. var
  173. x1,y1,x2,y2 : longint;
  174. begin
  175. if force then
  176. smallforce:=true
  177. else
  178. begin
  179. asm
  180. movl VideoBuf,%esi
  181. movl OldVideoBuf,%edi
  182. movl VideoBufSize,%ecx
  183. shrl $2,%ecx
  184. repe
  185. cmpsl
  186. orl %ecx,%ecx
  187. jz .Lno_update
  188. movb $1,smallforce
  189. .Lno_update:
  190. end;
  191. end;
  192. if SmallForce then
  193. begin
  194. BufSize.X := ScreenWidth;
  195. BufSize.Y := ScreenHeight;
  196. BufCoord.X := 0;
  197. BufCoord.Y := 0;
  198. with WriteRegion do
  199. begin
  200. Top :=0;
  201. Left :=0;
  202. Bottom := ScreenHeight-1;
  203. Right := ScreenWidth-1;
  204. end;
  205. New(LineBuf);
  206. BufCounter := 0;
  207. x1:=ScreenWidth+1;
  208. x2:=-1;
  209. y1:=ScreenHeight+1;
  210. y2:=-1;
  211. for LineCounter := 1 to ScreenHeight do
  212. begin
  213. for ColCounter := 1 to ScreenWidth do
  214. begin
  215. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  216. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  217. begin
  218. if ColCounter<x1 then
  219. x1:=ColCounter;
  220. if ColCounter>x2 then
  221. x2:=ColCounter;
  222. if LineCounter<y1 then
  223. y1:=LineCounter;
  224. if LineCounter>y2 then
  225. y2:=LineCounter;
  226. end;
  227. {$ifdef HASWIDECHAR}
  228. {$ifdef VER1_0}
  229. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  230. {$else}
  231. LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
  232. {$endif}
  233. {$else}
  234. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One);
  235. {$endif}
  236. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  237. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  238. else }
  239. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  240. Inc(BufCounter);
  241. end; { for }
  242. end; { for }
  243. BufSize.X := ScreenWidth;
  244. BufSize.Y := ScreenHeight;
  245. with WriteRegion do
  246. begin
  247. if force then
  248. begin
  249. Top := 0;
  250. Left :=0;
  251. Bottom := ScreenHeight-1;
  252. Right := ScreenWidth-1;
  253. BufCoord.X := 0;
  254. BufCoord.Y := 0;
  255. end
  256. else
  257. begin
  258. Top := y1-1;
  259. Left :=x1-1;
  260. Bottom := y2-1;
  261. Right := x2-1;
  262. BufCoord.X := x1-1;
  263. BufCoord.Y := y1-1;
  264. end;
  265. end;
  266. {
  267. writeln('X1: ',x1);
  268. writeln('Y1: ',y1);
  269. writeln('X2: ',x2);
  270. writeln('Y2: ',y2);
  271. }
  272. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  273. Dispose(LineBuf);
  274. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  275. end;
  276. end;
  277. Const
  278. SysVideoDriver : TVideoDriver = (
  279. InitDriver : @SysInitVideo;
  280. DoneDriver : @SysDoneVideo;
  281. UpdateScreen : @SysUpdateScreen;
  282. ClearScreen : @SysClearScreen;
  283. SetVideoMode : Nil;
  284. GetVideoModeCount : Nil;
  285. GetVideoModeData : Nil;
  286. SetCursorPos : @SysSetCursorPos;
  287. GetCursorType : @SysGetCursorType;
  288. SetCursorType : @SysSetCursorType;
  289. GetCapabilities : @SysGetCapabilities
  290. );
  291. initialization
  292. SetVideoDriver(SysVideoDriver);
  293. end.
  294. {
  295. $Log$
  296. Revision 1.7 2001-10-06 22:28:24 michael
  297. + Merged video mode selection/setting system
  298. Revision 1.6 2001/09/21 19:50:19 michael
  299. + Merged driver support from fixbranch
  300. Revision 1.5 2001/08/01 18:01:20 peter
  301. * WChar fix to compile also with 1.0.x
  302. Revision 1.4 2001/07/30 15:01:12 marco
  303. * Fixed wchar=word to widechar conversion
  304. Revision 1.3 2001/06/13 18:32:55 peter
  305. * fixed crash within donevideo (merged)
  306. Revision 1.2 2001/04/10 21:28:36 peter
  307. * removed warnigns
  308. Revision 1.1.2.6 2001/10/06 22:23:41 michael
  309. + Better video mode selection/setting system
  310. Revision 1.1.2.5 2001/09/21 18:42:09 michael
  311. + Implemented support for custom video drivers.
  312. Revision 1.1.2.4 2001/06/12 22:34:20 pierre
  313. * avoid crash at exit of IDE
  314. Revision 1.1.2.3 2001/04/10 20:33:04 peter
  315. * remove some warnings
  316. Revision 1.1.2.2 2001/04/02 13:29:41 pierre
  317. * avoid crash if DoneVideo called twice
  318. Revision 1.1.2.1 2001/01/30 21:52:03 peter
  319. * moved api utils to rtl
  320. Revision 1.1 2001/01/13 11:03:59 peter
  321. * API 2 RTL commit
  322. }