video.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Florian Klaempfl
  4. System independent low-level video interface for win32
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. This library 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. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; if not, write to the Free
  15. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. }
  17. uses
  18. windows,dos;
  19. var
  20. OldVideoBuf : PVideoBuf;
  21. ConsoleInfo : TConsoleScreenBufferInfo;
  22. ConsoleCursorInfo : TConsoleCursorInfo;
  23. MaxVideoBufSize : DWord;
  24. procedure InitVideo;
  25. begin
  26. ScreenColor:=true;
  27. GetConsoleScreenBufferInfo(TextRec(Output).Handle, ConsoleInfo);
  28. GetConsoleCursorInfo(TextRec(Output).Handle, ConsoleCursorInfo);
  29. with ConsoleInfo.srWindow do
  30. begin
  31. ScreenWidth:=right-left+1;
  32. ScreenHeight:=bottom-top+1;
  33. end;
  34. { srWindow is sometimes bigger then dwMaximumWindowSize
  35. this led to wrong ScreenWidth and ScreenHeight values PM }
  36. { damned: its also sometimes less !! PM }
  37. with ConsoleInfo.dwMaximumWindowSize do
  38. begin
  39. {if ScreenWidth>X then}
  40. ScreenWidth:=X;
  41. {if ScreenHeight>Y then}
  42. ScreenHeight:=Y;
  43. end;
  44. { TDrawBuffer only has FVMaxWidth elements
  45. larger values lead to crashes }
  46. if ScreenWidth> FVMaxWidth then
  47. ScreenWidth:=FVMaxWidth;
  48. CursorX:=ConsoleInfo.dwCursorPosition.x;
  49. CursorY:=ConsoleInfo.dwCursorPosition.y;
  50. if not ConsoleCursorInfo.bvisible then
  51. CursorLines:=0
  52. else
  53. CursorLines:=ConsoleCursorInfo.dwSize;
  54. { allocate back buffer }
  55. MaxVideoBufSize:= ScreenWidth * ScreenHeight * 2;
  56. VideoBufSize:=ScreenWidth*ScreenHeight*2;
  57. GetMem(VideoBuf,MaxVideoBufSize);
  58. GetMem(OldVideoBuf,MaxVideoBufSize);
  59. {ClearScreen; not needed PM }
  60. end;
  61. procedure DoneVideo;
  62. begin
  63. { ClearScreen; also not needed PM }
  64. SetCursorType(crUnderLine);
  65. { SetCursorPos(0,0); also not needed PM }
  66. FreeMem(VideoBuf,MaxVideoBufSize);
  67. FreeMem(OldVideoBuf,MaxVideoBufSize);
  68. VideoBufSize:=0;
  69. end;
  70. function GetCapabilities: Word;
  71. begin
  72. GetCapabilities:=cpColor or cpChangeCursor;
  73. end;
  74. procedure SetCursorPos(NewCursorX, NewCursorY: Word);
  75. var
  76. pos : COORD;
  77. begin
  78. pos.x:=NewCursorX;
  79. pos.y:=NewCursorY;
  80. SetConsoleCursorPosition(TextRec(Output).Handle,pos);
  81. CursorX:=pos.x;
  82. CursorY:=pos.y;
  83. end;
  84. function GetCursorType: Word;
  85. begin
  86. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  87. if not ConsoleCursorInfo.bvisible then
  88. GetCursorType:=crHidden
  89. else
  90. case ConsoleCursorInfo.dwSize of
  91. 1..30:
  92. GetCursorType:=crUnderline;
  93. 31..70:
  94. GetCursorType:=crHalfBlock;
  95. 71..100:
  96. GetCursorType:=crBlock;
  97. end;
  98. end;
  99. procedure SetCursorType(NewType: Word);
  100. begin
  101. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  102. if newType=crHidden then
  103. ConsoleCursorInfo.bvisible:=false
  104. else
  105. begin
  106. ConsoleCursorInfo.bvisible:=true;
  107. case NewType of
  108. crUnderline:
  109. ConsoleCursorInfo.dwSize:=10;
  110. crHalfBlock:
  111. ConsoleCursorInfo.dwSize:=50;
  112. crBlock:
  113. ConsoleCursorInfo.dwSize:=99;
  114. end
  115. end;
  116. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  117. end;
  118. function DefaultVideoModeSelector(const VideoMode: TVideoMode; Params: Longint): Boolean;
  119. begin
  120. end;
  121. procedure ClearScreen;
  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 UpdateScreen(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. orl %ecx,%ecx
  158. jz .Lno_update
  159. movb $1,force
  160. .Lno_update:
  161. end;
  162. end;
  163. if Force then
  164. begin
  165. BufSize.X := ScreenWidth;
  166. BufSize.Y := ScreenHeight;
  167. BufCoord.X := 0;
  168. BufCoord.Y := 0;
  169. with WriteRegion do
  170. begin
  171. Top :=0;
  172. Left :=0;
  173. Bottom := ScreenHeight-1;
  174. Right := ScreenWidth-1;
  175. end;
  176. New(LineBuf);
  177. BufCounter := 0;
  178. for LineCounter := 1 to ScreenHeight do
  179. begin
  180. for ColCounter := 1 to ScreenWidth do
  181. begin
  182. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  183. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  184. Inc(BufCounter);
  185. end; { for }
  186. end; { for }
  187. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  188. Dispose(LineBuf);
  189. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  190. end;
  191. end;
  192. }
  193. var
  194. x1,y1,x2,y2 : longint;
  195. begin
  196. if LockUpdateScreen<>0 then
  197. exit;
  198. if force then
  199. smallforce:=true
  200. else
  201. begin
  202. asm
  203. movl VideoBuf,%esi
  204. movl OldVideoBuf,%edi
  205. movl VideoBufSize,%ecx
  206. shrl $2,%ecx
  207. repe
  208. cmpsl
  209. orl %ecx,%ecx
  210. jz .Lno_update
  211. movb $1,smallforce
  212. .Lno_update:
  213. end;
  214. end;
  215. if SmallForce then
  216. begin
  217. BufSize.X := ScreenWidth;
  218. BufSize.Y := ScreenHeight;
  219. BufCoord.X := 0;
  220. BufCoord.Y := 0;
  221. with WriteRegion do
  222. begin
  223. Top :=0;
  224. Left :=0;
  225. Bottom := ScreenHeight-1;
  226. Right := ScreenWidth-1;
  227. end;
  228. New(LineBuf);
  229. BufCounter := 0;
  230. x1:=ScreenWidth+1;
  231. x2:=-1;
  232. y1:=ScreenHeight+1;
  233. y2:=-1;
  234. for LineCounter := 1 to ScreenHeight do
  235. begin
  236. for ColCounter := 1 to ScreenWidth do
  237. begin
  238. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  239. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  240. begin
  241. if ColCounter<x1 then
  242. x1:=ColCounter;
  243. if ColCounter>x2 then
  244. x2:=ColCounter;
  245. if LineCounter<y1 then
  246. y1:=LineCounter;
  247. if LineCounter>y2 then
  248. y2:=LineCounter;
  249. end;
  250. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  251. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  252. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  253. else }
  254. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  255. Inc(BufCounter);
  256. end; { for }
  257. end; { for }
  258. BufSize.X := ScreenWidth;
  259. BufSize.Y := ScreenHeight;
  260. with WriteRegion do
  261. begin
  262. if force then
  263. begin
  264. Top := 0;
  265. Left :=0;
  266. Bottom := ScreenHeight-1;
  267. Right := ScreenWidth-1;
  268. BufCoord.X := 0;
  269. BufCoord.Y := 0;
  270. end
  271. else
  272. begin
  273. Top := y1-1;
  274. Left :=x1-1;
  275. Bottom := y2-1;
  276. Right := x2-1;
  277. BufCoord.X := x1-1;
  278. BufCoord.Y := y1-1;
  279. end;
  280. end;
  281. {
  282. writeln('X1: ',x1);
  283. writeln('Y1: ',y1);
  284. writeln('X2: ',x2);
  285. writeln('Y2: ',y2);
  286. }
  287. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  288. Dispose(LineBuf);
  289. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  290. end;
  291. end;
  292. procedure RegisterVideoModes;
  293. begin
  294. { don't know what to do for win32 (FK) }
  295. RegisterVideoMode(80, 25, True, @DefaultVideoModeSelector, $00000003);
  296. end;
  297. procedure TargetEntry;
  298. begin
  299. end;
  300. procedure TargetExit;
  301. begin
  302. end;
  303. {
  304. $Log$
  305. Revision 1.4 2000-10-15 09:21:28 peter
  306. * FVMaxWidth (merged)
  307. Revision 1.3 2000/10/04 11:53:32 pierre
  308. Add TargetEntry and TargetExit (merged)
  309. Revision 1.2 2000/07/13 11:32:27 michael
  310. + removed logs
  311. }