video.pp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2015 by Nikolay Nikolov
  4. member of the Free Pascal development team
  5. Video unit for Win16
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit video;
  14. {$ENDIF FPC_DOTTEDUNITS}
  15. {$mode objfpc}
  16. {$modeswitch advancedrecords}
  17. { smart callbacks: on }
  18. {$K+}
  19. interface
  20. {$IFDEF FPC_DOTTEDUNITS}
  21. uses
  22. WinApi.WinTypes;
  23. {$ELSE FPC_DOTTEDUNITS}
  24. uses
  25. WinTypes;
  26. {$ENDIF FPC_DOTTEDUNITS}
  27. {$I videoh.inc}
  28. var
  29. KeyEventWndProc: WNDPROC;
  30. implementation
  31. {$IFDEF FPC_DOTTEDUNITS}
  32. uses
  33. WinApi.WinProcs, System.Unicode.Graphemebreakproperty, System.Unicode.Eastasianwidth, System.CharSet;
  34. {$ELSE FPC_DOTTEDUNITS}
  35. uses
  36. WinProcs, graphemebreakproperty, eastasianwidth, charset;
  37. {$ENDIF FPC_DOTTEDUNITS}
  38. {$I video.inc}
  39. const
  40. ColorRefs: array[0..15] of COLORREF=
  41. ($000000,$aa0000,$00aa00,$aaaa00,$0000aa,$aa00aa,$0055aa,$aaaaaa,
  42. $555555,$ff5555,$55ff55,$ffff55,$5555ff,$ff55ff,$55ffff,$ffffff);
  43. var
  44. VideoWindow: HWND;
  45. procedure WindowPaint(hwnd: HWND);
  46. var
  47. dc: HDC;
  48. ps: PAINTSTRUCT;
  49. oldfont: HFONT;
  50. oldtextcolor,oldbkcolor: COLORREF;
  51. Metrics: TEXTMETRIC;
  52. y,y1,y2,x,x1,x2: SmallInt;
  53. ch: TVideoCell;
  54. CharWidth,CharHeight: SmallInt;
  55. begin
  56. dc:=BeginPaint(hwnd,FarAddr(ps));
  57. { don't do anything, before the video unit has been fully initialized... }
  58. if videobuf<>nil then
  59. begin
  60. oldfont:=SelectObject(dc,GetStockObject(OEM_FIXED_FONT));
  61. GetTextMetrics(dc,FarAddr(Metrics));
  62. CharWidth:=Metrics.tmMaxCharWidth;
  63. CharHeight:=Metrics.tmHeight+Metrics.tmExternalLeading;
  64. x1:=ps.rcPaint.left div CharWidth;
  65. x2:=1+ps.rcPaint.right div CharWidth;
  66. y1:=ps.rcPaint.top div CharHeight;
  67. y2:=1+ps.rcPaint.bottom div CharHeight;
  68. if x1<0 then
  69. x1:=0;
  70. if y1<0 then
  71. y1:=0;
  72. if x2>=ScreenWidth then
  73. x2:=ScreenWidth-1;
  74. if y2>=ScreenHeight then
  75. y2:=ScreenHeight-1;
  76. oldtextcolor:=GetTextColor(dc);
  77. oldbkcolor:=GetBkColor(dc);
  78. for y:=y1 to y2 do
  79. for x:=x1 to x2 do
  80. begin
  81. ch:=videobuf^[y*ScreenWidth+x];
  82. SetTextColor(dc,ColorRefs[(ch shr 8) and 15]);
  83. SetBkColor(dc,ColorRefs[(ch shr 12) and 15]);
  84. TextOut(dc,x*CharWidth,y*CharHeight,FarAddr(ch),1);
  85. end;
  86. SetTextColor(dc,oldtextcolor);
  87. SetBkColor(dc,oldbkcolor);
  88. SelectObject(dc,oldfont);
  89. end;
  90. EndPaint(hwnd,FarAddr(ps));
  91. end;
  92. function MainWndProc(hwnd: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; export;
  93. begin
  94. case msg of
  95. WM_KEYDOWN,
  96. WM_KEYUP,
  97. WM_SYSKEYDOWN,
  98. WM_SYSKEYUP:
  99. MainWndProc:=KeyEventWndProc(hwnd,msg,wParam,lParam);
  100. WM_PAINT:
  101. WindowPaint(hwnd);
  102. WM_DESTROY:
  103. begin
  104. VideoWindow:=0;
  105. PostQuitMessage(0);
  106. end;
  107. else
  108. MainWndProc:=DefWindowProc(hwnd,msg,wParam,lParam);
  109. end;
  110. end;
  111. procedure InitWinClass;
  112. var
  113. wc: WNDCLASS;
  114. begin
  115. wc.style:=0;
  116. wc.lpfnWndProc:=@MainWndProc;
  117. wc.cbClsExtra:=0;
  118. wc.cbWndExtra:=0;
  119. wc.hInstance:=HInstance;
  120. wc.hIcon:=LoadIcon(0,IDI_APPLICATION);
  121. wc.hCursor:=LoadCursor(0,IDC_ARROW);
  122. wc.hbrBackground:=GetStockObject(BLACK_BRUSH);
  123. wc.lpszMenuName:=nil;
  124. wc.lpszClassName:='FPCConsoleWndClass';
  125. if not RegisterClass(FarAddr(wc)) then
  126. begin
  127. MessageBox(0,'Error registering window class',nil,MB_OK or MB_ICONHAND or MB_TASKMODAL);
  128. Halt(1);
  129. end;
  130. end;
  131. procedure InitWindow;
  132. begin
  133. VideoWindow:=CreateWindow(
  134. 'FPCConsoleWndClass',
  135. 'Console',
  136. WS_OVERLAPPEDWINDOW,
  137. CW_USEDEFAULT,
  138. CW_USEDEFAULT,
  139. CW_USEDEFAULT,
  140. CW_USEDEFAULT,
  141. 0,
  142. 0,
  143. HInstance,
  144. nil);
  145. if VideoWindow=0 then
  146. begin
  147. MessageBox(0,'Error creating window',nil,MB_OK or MB_ICONHAND or MB_TASKMODAL);
  148. Halt(1);
  149. end;
  150. ShowWindow(VideoWindow,CmdShow);
  151. UpdateWindow(VideoWindow);
  152. end;
  153. procedure ProcessMessages;
  154. var
  155. m: MSG;
  156. begin
  157. while PeekMessage(FarAddr(m),0,0,0,1) do
  158. begin
  159. TranslateMessage(FarAddr(m));
  160. DispatchMessage(FarAddr(m));
  161. end;
  162. end;
  163. procedure SysInitVideo;
  164. begin
  165. if hPrevInst=0 then
  166. InitWinClass;
  167. InitWindow;
  168. ProcessMessages;
  169. ScreenWidth:=80;
  170. ScreenHeight:=25;
  171. end;
  172. procedure SysDoneVideo;
  173. begin
  174. if VideoWindow<>0 then
  175. begin
  176. if not DestroyWindow(VideoWindow) then
  177. MessageBox(0,'Error destroying window',nil,MB_OK or MB_ICONHAND or MB_TASKMODAL);
  178. VideoWindow:=0;
  179. end;
  180. end;
  181. procedure SysUpdateScreen(Force: Boolean);
  182. var
  183. dc: HDC;
  184. oldfont: HFONT;
  185. oldtextcolor,oldbkcolor: COLORREF;
  186. Metrics: TEXTMETRIC;
  187. y,x: SmallInt;
  188. ch: TVideoCell;
  189. CharWidth,CharHeight: SmallInt;
  190. begin
  191. if VideoWindow<>0 then
  192. begin
  193. dc:=GetDC(VideoWindow);
  194. if dc=0 then
  195. begin
  196. MessageBox(0,'GetDC() failed',nil,MB_OK or MB_ICONHAND or MB_TASKMODAL);
  197. exit;
  198. end;
  199. oldfont:=SelectObject(dc,GetStockObject(OEM_FIXED_FONT));
  200. GetTextMetrics(dc,FarAddr(Metrics));
  201. CharWidth:=Metrics.tmMaxCharWidth;
  202. CharHeight:=Metrics.tmHeight+Metrics.tmExternalLeading;
  203. oldtextcolor:=GetTextColor(dc);
  204. oldbkcolor:=GetBkColor(dc);
  205. for y:=0 to ScreenHeight-1 do
  206. for x:=0 to ScreenWidth-1 do
  207. begin
  208. ch:=videobuf^[y*ScreenWidth+x];
  209. if force or (ch<>oldvideobuf^[y*ScreenWidth+x]) then
  210. begin
  211. oldvideobuf^[y*ScreenWidth+x]:=videobuf^[y*ScreenWidth+x];
  212. SetTextColor(dc,ColorRefs[(ch shr 8) and 15]);
  213. SetBkColor(dc,ColorRefs[(ch shr 12) and 15]);
  214. TextOut(dc,x*CharWidth,y*CharHeight,FarAddr(ch),1);
  215. end;
  216. end;
  217. SetTextColor(dc,oldtextcolor);
  218. SetBkColor(dc,oldbkcolor);
  219. SelectObject(dc,oldfont);
  220. ReleaseDC(VideoWindow,dc);
  221. end;
  222. ProcessMessages;
  223. end;
  224. function SysGetCapabilities: Word;
  225. begin
  226. SysGetCapabilities:=cpUnderLine+cpBlink+cpColor;
  227. end;
  228. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  229. begin
  230. CursorX:=NewCursorX;
  231. CursorY:=NewCursorY;
  232. end;
  233. function SysGetCursorType: Word;
  234. begin
  235. end;
  236. procedure SysSetCursorType(NewType: Word);
  237. begin
  238. end;
  239. function SysSetVideoMode(const mode:Tvideomode):boolean;
  240. begin
  241. end;
  242. const
  243. SysVideoDriver: TVideoDriver = (
  244. InitDriver : @SysInitVideo;
  245. InitEnhancedDriver : nil;
  246. DoneDriver : @SysDoneVideo;
  247. UpdateScreen : @SysUpdateScreen;
  248. UpdateScreenArea : nil;
  249. ClearScreen : nil;
  250. SetVideoMode : @SysSetVideoMode;
  251. GetVideoModeCount : nil;
  252. GetVideoModeData : nil;
  253. SetCursorPos : @SysSetCursorPos;
  254. GetCursorType : @SysGetCursorType;
  255. SetCursorType : @SysSetCursorType;
  256. GetCapabilities : @SysGetCapabilities;
  257. GetActiveCodePage : nil;
  258. ActivateCodePage : nil;
  259. GetSupportedCodePageCount : nil;
  260. GetSupportedCodePage : nil;
  261. );
  262. begin
  263. KeyEventWndProc:=@DefWindowProc;
  264. SetVideoDriver(SysVideoDriver);
  265. end.