video.pp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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 SysInitVideo;
  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. end;
  61. procedure SysDoneVideo;
  62. begin
  63. SetCursorType(crUnderLine);
  64. FreeMem(VideoBuf,MaxVideoBufSize);
  65. FreeMem(OldVideoBuf,MaxVideoBufSize);
  66. VideoBufSize:=0;
  67. VideoInitialized:=false;
  68. end;
  69. function SysGetCapabilities: Word;
  70. begin
  71. SysGetCapabilities:=cpColor or cpChangeCursor;
  72. end;
  73. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  74. var
  75. pos : COORD;
  76. begin
  77. pos.x:=NewCursorX;
  78. pos.y:=NewCursorY;
  79. SetConsoleCursorPosition(TextRec(Output).Handle,pos);
  80. CursorX:=pos.x;
  81. CursorY:=pos.y;
  82. end;
  83. function SysGetCursorType: Word;
  84. begin
  85. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  86. if not ConsoleCursorInfo.bvisible then
  87. SysGetCursorType:=crHidden
  88. else
  89. case ConsoleCursorInfo.dwSize of
  90. 1..30:
  91. SysGetCursorType:=crUnderline;
  92. 31..70:
  93. SysGetCursorType:=crHalfBlock;
  94. 71..100:
  95. SysGetCursorType:=crBlock;
  96. end;
  97. end;
  98. procedure SysSetCursorType(NewType: Word);
  99. begin
  100. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  101. if newType=crHidden then
  102. ConsoleCursorInfo.bvisible:=false
  103. else
  104. begin
  105. ConsoleCursorInfo.bvisible:=true;
  106. case NewType of
  107. crUnderline:
  108. ConsoleCursorInfo.dwSize:=10;
  109. crHalfBlock:
  110. ConsoleCursorInfo.dwSize:=50;
  111. crBlock:
  112. ConsoleCursorInfo.dwSize:=99;
  113. end
  114. end;
  115. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  116. end;
  117. function DefaultVideoModeSelector(const VideoMode: TVideoMode; Params: Longint): Boolean;
  118. begin
  119. DefaultVideoModeSelector:=true;
  120. end;
  121. procedure SysClearScreen;
  122. begin
  123. FillWord(VideoBuf^,VideoBufSize div 2,$0720);
  124. UpdateScreen(true);
  125. end;
  126. {$IFDEF FPC}
  127. function WriteConsoleOutput(hConsoleOutput:HANDLE; lpBuffer:pointer; dwBufferSize:COORD; dwBufferCoord:COORD;
  128. var lpWriteRegion:SMALL_RECT):WINBOOL; external 'kernel32' name 'WriteConsoleOutputA';
  129. {$ENDIF}
  130. procedure SysUpdateScreen(Force: Boolean);
  131. type TmpRec = Array[0..(1024*32) - 1] of TCharInfo;
  132. type WordRec = record
  133. One, Two: Byte;
  134. end; { wordrec }
  135. var
  136. BufSize,
  137. BufCoord : COORD;
  138. WriteRegion : SMALL_RECT;
  139. LineBuf : ^TmpRec;
  140. BufCounter : Longint;
  141. LineCounter,
  142. ColCounter : Longint;
  143. smallforce : boolean;
  144. (*
  145. begin
  146. if LockUpdateScreen<>0 then
  147. exit;
  148. if not force then
  149. begin
  150. asm
  151. movl VideoBuf,%esi
  152. movl OldVideoBuf,%edi
  153. movl VideoBufSize,%ecx
  154. shrl $2,%ecx
  155. repe
  156. cmpsl
  157. setne force
  158. end;
  159. end;
  160. if Force then
  161. begin
  162. BufSize.X := ScreenWidth;
  163. BufSize.Y := ScreenHeight;
  164. BufCoord.X := 0;
  165. BufCoord.Y := 0;
  166. with WriteRegion do
  167. begin
  168. Top :=0;
  169. Left :=0;
  170. Bottom := ScreenHeight-1;
  171. Right := ScreenWidth-1;
  172. end;
  173. New(LineBuf);
  174. BufCounter := 0;
  175. for LineCounter := 1 to ScreenHeight do
  176. begin
  177. for ColCounter := 1 to ScreenWidth do
  178. begin
  179. LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
  180. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  181. Inc(BufCounter);
  182. end; { for }
  183. end; { for }
  184. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  185. Dispose(LineBuf);
  186. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  187. end;
  188. end;
  189. *)
  190. var
  191. x1,y1,x2,y2 : longint;
  192. begin
  193. if force then
  194. smallforce:=true
  195. else
  196. begin
  197. asm
  198. movl VideoBuf,%esi
  199. movl OldVideoBuf,%edi
  200. movl VideoBufSize,%ecx
  201. shrl $2,%ecx
  202. repe
  203. cmpsl
  204. orl %ecx,%ecx
  205. jz .Lno_update
  206. movb $1,smallforce
  207. .Lno_update:
  208. end;
  209. end;
  210. if SmallForce then
  211. begin
  212. BufSize.X := ScreenWidth;
  213. BufSize.Y := ScreenHeight;
  214. BufCoord.X := 0;
  215. BufCoord.Y := 0;
  216. with WriteRegion do
  217. begin
  218. Top :=0;
  219. Left :=0;
  220. Bottom := ScreenHeight-1;
  221. Right := ScreenWidth-1;
  222. end;
  223. New(LineBuf);
  224. BufCounter := 0;
  225. x1:=ScreenWidth+1;
  226. x2:=-1;
  227. y1:=ScreenHeight+1;
  228. y2:=-1;
  229. for LineCounter := 1 to ScreenHeight do
  230. begin
  231. for ColCounter := 1 to ScreenWidth do
  232. begin
  233. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  234. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  235. begin
  236. if ColCounter<x1 then
  237. x1:=ColCounter;
  238. if ColCounter>x2 then
  239. x2:=ColCounter;
  240. if LineCounter<y1 then
  241. y1:=LineCounter;
  242. if LineCounter>y2 then
  243. y2:=LineCounter;
  244. end;
  245. {$ifdef HASWIDECHAR}
  246. {$ifdef VER1_0}
  247. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  248. {$else}
  249. LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
  250. {$endif}
  251. {$else}
  252. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One);
  253. {$endif}
  254. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  255. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  256. else }
  257. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  258. Inc(BufCounter);
  259. end; { for }
  260. end; { for }
  261. BufSize.X := ScreenWidth;
  262. BufSize.Y := ScreenHeight;
  263. with WriteRegion do
  264. begin
  265. if force then
  266. begin
  267. Top := 0;
  268. Left :=0;
  269. Bottom := ScreenHeight-1;
  270. Right := ScreenWidth-1;
  271. BufCoord.X := 0;
  272. BufCoord.Y := 0;
  273. end
  274. else
  275. begin
  276. Top := y1-1;
  277. Left :=x1-1;
  278. Bottom := y2-1;
  279. Right := x2-1;
  280. BufCoord.X := x1-1;
  281. BufCoord.Y := y1-1;
  282. end;
  283. end;
  284. {
  285. writeln('X1: ',x1);
  286. writeln('Y1: ',y1);
  287. writeln('X2: ',x2);
  288. writeln('Y2: ',y2);
  289. }
  290. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  291. Dispose(LineBuf);
  292. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  293. end;
  294. end;
  295. procedure RegisterVideoModes;
  296. begin
  297. { don't know what to do for win32 (FK) }
  298. RegisterVideoMode(80, 25, True, @DefaultVideoModeSelector, $00000003);
  299. end;
  300. Const
  301. SysVideoDriver : TVideoDriver = (
  302. InitDriver : @SysInitVideo;
  303. DoneDriver : @SysDoneVideo;
  304. UpdateScreen : @SysUpdateScreen;
  305. ClearScreen : @SysClearScreen;
  306. SetVideoMode : Nil;
  307. HasVideoMode : Nil;
  308. SetCursorPos : @SysSetCursorPos;
  309. GetCursorType : @SysGetCursorType;
  310. SetCursorType : @SysSetCursorType;
  311. GetCapabilities : @SysGetCapabilities
  312. );
  313. initialization
  314. SetVideoDriver(SysVideoDriver);
  315. RegisterVideoModes;
  316. finalization
  317. UnRegisterVideoModes;
  318. end.
  319. {
  320. $Log$
  321. Revision 1.6 2001-09-21 19:50:19 michael
  322. + Merged driver support from fixbranch
  323. Revision 1.5 2001/08/01 18:01:20 peter
  324. * WChar fix to compile also with 1.0.x
  325. Revision 1.4 2001/07/30 15:01:12 marco
  326. * Fixed wchar=word to widechar conversion
  327. Revision 1.3 2001/06/13 18:32:55 peter
  328. * fixed crash within donevideo (merged)
  329. Revision 1.2 2001/04/10 21:28:36 peter
  330. * removed warnigns
  331. Revision 1.1.2.5 2001/09/21 18:42:09 michael
  332. + Implemented support for custom video drivers.
  333. Revision 1.1.2.4 2001/06/12 22:34:20 pierre
  334. * avoid crash at exit of IDE
  335. Revision 1.1.2.3 2001/04/10 20:33:04 peter
  336. * remove some warnings
  337. Revision 1.1.2.2 2001/04/02 13:29:41 pierre
  338. * avoid crash if DoneVideo called twice
  339. Revision 1.1.2.1 2001/01/30 21:52:03 peter
  340. * moved api utils to rtl
  341. Revision 1.1 2001/01/13 11:03:59 peter
  342. * API 2 RTL commit
  343. }