video.pp 9.2 KB

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