video.inc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. {
  2. $Id$
  3. System independent low-level video interface for win32
  4. Copyright (c) 1999 by Florian Klaempfl
  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. CursorX:=ConsoleInfo.dwCursorPosition.x;
  45. CursorY:=ConsoleInfo.dwCursorPosition.y;
  46. if not ConsoleCursorInfo.bvisible then
  47. CursorLines:=0
  48. else
  49. CursorLines:=ConsoleCursorInfo.dwSize;
  50. { allocate back buffer }
  51. MaxVideoBufSize:= ScreenWidth * ScreenHeight * 2;
  52. VideoBufSize:=ScreenWidth*ScreenHeight*2;
  53. GetMem(VideoBuf,MaxVideoBufSize);
  54. GetMem(OldVideoBuf,MaxVideoBufSize);
  55. {ClearScreen; not needed PM }
  56. end;
  57. procedure DoneVideo;
  58. begin
  59. { ClearScreen; also not needed PM }
  60. SetCursorType(crUnderLine);
  61. { SetCursorPos(0,0); also not needed PM }
  62. FreeMem(VideoBuf,MaxVideoBufSize);
  63. FreeMem(OldVideoBuf,MaxVideoBufSize);
  64. VideoBufSize:=0;
  65. end;
  66. function GetCapabilities: Word;
  67. begin
  68. GetCapabilities:=cpColor or cpChangeCursor;
  69. end;
  70. procedure SetCursorPos(NewCursorX, NewCursorY: Word);
  71. var
  72. pos : COORD;
  73. begin
  74. pos.x:=NewCursorX;
  75. pos.y:=NewCursorY;
  76. SetConsoleCursorPosition(TextRec(Output).Handle,pos);
  77. CursorX:=pos.x;
  78. CursorY:=pos.y;
  79. end;
  80. function GetCursorType: Word;
  81. begin
  82. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  83. if not ConsoleCursorInfo.bvisible then
  84. GetCursorType:=crHidden
  85. else
  86. case ConsoleCursorInfo.dwSize of
  87. 1..30:
  88. GetCursorType:=crUnderline;
  89. 31..70:
  90. GetCursorType:=crHalfBlock;
  91. 71..100:
  92. GetCursorType:=crBlock;
  93. end;
  94. end;
  95. procedure SetCursorType(NewType: Word);
  96. begin
  97. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  98. if newType=crHidden then
  99. ConsoleCursorInfo.bvisible:=false
  100. else
  101. begin
  102. ConsoleCursorInfo.bvisible:=true;
  103. case NewType of
  104. crUnderline:
  105. ConsoleCursorInfo.dwSize:=10;
  106. crHalfBlock:
  107. ConsoleCursorInfo.dwSize:=50;
  108. crBlock:
  109. ConsoleCursorInfo.dwSize:=99;
  110. end
  111. end;
  112. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  113. end;
  114. function DefaultVideoModeSelector(const VideoMode: TVideoMode; Params: Longint): Boolean;
  115. begin
  116. end;
  117. procedure ClearScreen;
  118. begin
  119. FillWord(VideoBuf^,VideoBufSize div 2,$0720);
  120. UpdateScreen(true);
  121. end;
  122. {$IFDEF FPC}
  123. function WriteConsoleOutput(hConsoleOutput:HANDLE; lpBuffer:pointer; dwBufferSize:COORD; dwBufferCoord:COORD;
  124. var lpWriteRegion:SMALL_RECT):WINBOOL; external 'kernel32' name 'WriteConsoleOutputA';
  125. {$ENDIF}
  126. procedure UpdateScreen(Force: Boolean);
  127. type TmpRec = Array[0..(1024*32) - 1] of TCharInfo;
  128. type WordRec = record
  129. One, Two: Byte;
  130. end; { wordrec }
  131. var
  132. BufSize,
  133. BufCoord : COORD;
  134. WriteRegion : SMALL_RECT;
  135. LineBuf : ^TmpRec;
  136. BufCounter : Longint;
  137. LineCounter,
  138. ColCounter : Longint;
  139. smallforce : boolean;
  140. {
  141. begin
  142. if LockUpdateScreen<>0 then
  143. exit;
  144. if not force then
  145. begin
  146. asm
  147. movl VideoBuf,%esi
  148. movl OldVideoBuf,%edi
  149. movl VideoBufSize,%ecx
  150. shrl $2,%ecx
  151. repe
  152. cmpsl
  153. orl %ecx,%ecx
  154. jz .Lno_update
  155. movb $1,force
  156. .Lno_update:
  157. end;
  158. end;
  159. if Force then
  160. begin
  161. BufSize.X := ScreenWidth;
  162. BufSize.Y := ScreenHeight;
  163. BufCoord.X := 0;
  164. BufCoord.Y := 0;
  165. with WriteRegion do
  166. begin
  167. Top :=0;
  168. Left :=0;
  169. Bottom := ScreenHeight-1;
  170. Right := ScreenWidth-1;
  171. end;
  172. New(LineBuf);
  173. BufCounter := 0;
  174. for LineCounter := 1 to ScreenHeight do
  175. begin
  176. for ColCounter := 1 to ScreenWidth do
  177. begin
  178. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  179. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  180. Inc(BufCounter);
  181. end; { for }
  182. end; { for }
  183. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  184. Dispose(LineBuf);
  185. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  186. end;
  187. end;
  188. }
  189. var
  190. x1,y1,x2,y2 : longint;
  191. begin
  192. if LockUpdateScreen<>0 then
  193. exit;
  194. if force then
  195. smallforce:=true
  196. else
  197. begin
  198. asm
  199. movl VideoBuf,%esi
  200. movl OldVideoBuf,%edi
  201. movl VideoBufSize,%ecx
  202. shrl $2,%ecx
  203. repe
  204. cmpsl
  205. orl %ecx,%ecx
  206. jz .Lno_update
  207. movb $1,smallforce
  208. .Lno_update:
  209. end;
  210. end;
  211. if SmallForce then
  212. begin
  213. BufSize.X := ScreenWidth;
  214. BufSize.Y := ScreenHeight;
  215. BufCoord.X := 0;
  216. BufCoord.Y := 0;
  217. with WriteRegion do
  218. begin
  219. Top :=0;
  220. Left :=0;
  221. Bottom := ScreenHeight-1;
  222. Right := ScreenWidth-1;
  223. end;
  224. New(LineBuf);
  225. BufCounter := 0;
  226. x1:=ScreenWidth+1;
  227. x2:=-1;
  228. y1:=ScreenHeight+1;
  229. y2:=-1;
  230. for LineCounter := 1 to ScreenHeight do
  231. begin
  232. for ColCounter := 1 to ScreenWidth do
  233. begin
  234. if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
  235. (WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
  236. begin
  237. if ColCounter<x1 then
  238. x1:=ColCounter;
  239. if ColCounter>x2 then
  240. x2:=ColCounter;
  241. if LineCounter<y1 then
  242. y1:=LineCounter;
  243. if LineCounter>y2 then
  244. y2:=LineCounter;
  245. end;
  246. LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
  247. { If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
  248. LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
  249. else }
  250. LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
  251. Inc(BufCounter);
  252. end; { for }
  253. end; { for }
  254. BufSize.X := ScreenWidth;
  255. BufSize.Y := ScreenHeight;
  256. with WriteRegion do
  257. begin
  258. if force then
  259. begin
  260. Top := 0;
  261. Left :=0;
  262. Bottom := ScreenHeight-1;
  263. Right := ScreenWidth-1;
  264. BufCoord.X := 0;
  265. BufCoord.Y := 0;
  266. end
  267. else
  268. begin
  269. Top := y1-1;
  270. Left :=x1-1;
  271. Bottom := y2-1;
  272. Right := x2-1;
  273. BufCoord.X := x1-1;
  274. BufCoord.Y := y1-1;
  275. end;
  276. end;
  277. {
  278. writeln('X1: ',x1);
  279. writeln('Y1: ',y1);
  280. writeln('X2: ',x2);
  281. writeln('Y2: ',y2);
  282. }
  283. WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
  284. Dispose(LineBuf);
  285. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  286. end;
  287. end;
  288. procedure RegisterVideoModes;
  289. begin
  290. { don't know what to do for win32 (FK) }
  291. RegisterVideoMode(80, 25, True, @DefaultVideoModeSelector, $00000003);
  292. end;
  293. {
  294. $Log$
  295. Revision 1.2 2000-07-13 11:32:27 michael
  296. + removed logs
  297. }