added support for masks of higher resolutions than the bitmaps they mask
[swftools.git] / lib / gfxwindow_win32.c
1 /* gfxwindow.h \r
2 \r
3    Simple GUI abstraction- Windows implementation\r
4 \r
5    Part of the swftools package.\r
6 \r
7    Copyright (c) 2005 Matthias Kramm <kramm@quiss.org> \r
8 \r
9    This program is free software; you can redistribute it and/or modify\r
10    it under the terms of the GNU General Public License as published by\r
11    the Free Software Foundation; either version 2 of the License, or\r
12    (at your option) any later version.\r
13 \r
14    This program is distributed in the hope that it will be useful,\r
15    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17    GNU General Public License for more details.\r
18 \r
19    You should have received a copy of the GNU General Public License\r
20    along with this program; if not, write to the Free Software\r
21    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */\r
22 \r
23 #include <windows.h>\r
24 #include <commctrl.h>\r
25 #include <stdio.h>\r
26 #include <string.h>\r
27 #include "gfx.h"\r
28 \r
29 static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);\r
30 \r
31 static char szWinName[] = "MyWin";\r
32 static HDC hdc;\r
33 static HWND hwnd;\r
34 static char*text="";\r
35 static int textx;\r
36 static int texty;\r
37 static int a = 0;\r
38 static HDC dc, memDc;\r
39 static HBITMAP   piccy;\r
40 \r
41 static int sizex=640;\r
42 static int sizey=388;\r
43 static char *screen;\r
44 static char *offscreen;\r
45 static int screensize;\r
46 \r
47 static DWORD threadID;\r
48 static DWORD mainthreadID;\r
49 static HANDLE thread;\r
50 static HINSTANCE me,prev;\r
51 static int nWinMode;\r
52 static int posx,posy;\r
53 static RECT desktopSize;\r
54 static int initialized = 0;\r
55 \r
56 static int cwidth=640,cheight=388;\r
57 \r
58 #define DIB\r
59 \r
60 static void openWindow(int _sizex, int _sizey)\r
61 {\r
62     RECT r;int ok;\r
63 \r
64     sizex = _sizex;\r
65     sizey = _sizey;\r
66     \r
67     ok = (int)GetClientRect(GetDesktopWindow(), &r);\r
68     if(!ok) {\r
69         r.left = r.top = 0;\r
70         r.right = 1280;\r
71         r.bottom = 1024;\r
72     }\r
73     desktopSize = r;\r
74 \r
75     hwnd=CreateWindow(szWinName,\r
76                       0, //window title\r
77                       WS_POPUP|WS_VISIBLE,\r
78                       posx=100, //CW_USEDEFAULT,\r
79                       posy=200, //CW_USEDEFAULT,\r
80                       640,388,\r
81                       HWND_DESKTOP,\r
82                       NULL,me,NULL);\r
83     SendMessage(hwnd, 1024+5 /*SB_SETBORDERS*/, 0, 0);\r
84     \r
85     ShowWindow(hwnd,nWinMode);\r
86     UpdateWindow(hwnd);\r
87 \r
88     dc=GetDC(hwnd);\r
89     memDc=CreateCompatibleDC(dc);\r
90 //    SetTimer(hwnd,1,1000,NULL);\r
91 //    SetTimer(hwnd,1,33,NULL);\r
92 \r
93 #ifdef DIB\r
94     void * ppvBits = 0;\r
95     BITMAPINFO info;\r
96     memset(&info, sizeof(info), 0);\r
97     info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
98     info.bmiHeader.biWidth = sizex;\r
99     info.bmiHeader.biHeight = sizey;\r
100     info.bmiHeader.biPlanes= 1;\r
101     info.bmiHeader.biBitCount = 24;\r
102     info.bmiHeader.biCompression = BI_RGB;\r
103     info.bmiHeader.biSizeImage = sizex*sizey*3;\r
104 \r
105     piccy = CreateDIBSection(0, &info, DIB_RGB_COLORS, &ppvBits, 0,0);\r
106     screen = (char*)ppvBits;\r
107     offscreen = (char*)malloc(sizex*sizey*4);\r
108     screensize = sizex*sizey*3;\r
109     GdiFlush();\r
110 #else\r
111     screen = (char*)malloc(sizex*sizey*3);\r
112     offscreen = (char*)malloc(sizex*sizey*4);\r
113     screensize = sizex*sizey*3;\r
114     piccy = CreateBitmap(sizex, sizey, 1, 24, screen);\r
115 #endif\r
116 \r
117     SelectObject(memDc,piccy);\r
118     \r
119 }\r
120 \r
121 static void closeWindow()\r
122 {\r
123     DeleteDC(memDc);\r
124     ReleaseDC(hwnd,dc);\r
125     KillTimer(hwnd,1);\r
126 }\r
127 \r
128 static int initwin32()\r
129 {\r
130     MSG msg;\r
131     int ret;\r
132     WNDCLASS wcl;\r
133 \r
134     me =  GetModuleHandle(NULL);\r
135     prev = NULL;\r
136     nWinMode = SW_SHOW;\r
137 \r
138     if(GetClassInfo(0, szWinName, &wcl)) {\r
139         /* already registered */\r
140         exit(1);\r
141     }\r
142     wcl.hInstance    =me;\r
143     wcl.lpszClassName=szWinName;\r
144     wcl.lpfnWndProc  =WindowFunc;\r
145     wcl.style        =2;\r
146     wcl.hIcon        =LoadIcon  (NULL, IDI_HAND);\r
147     wcl.hCursor      =LoadCursor(NULL, IDC_HAND);//IDC_CROSS);\r
148     wcl.lpszMenuName =NULL;\r
149     wcl.cbClsExtra   =0;\r
150     wcl.cbWndExtra   =0;\r
151     wcl.hbrBackground=(HBRUSH)GetStockObject(NULL_BRUSH);//WHITE_BRUSH);\r
152 \r
153     if(!RegisterClass(&wcl)) \r
154         exit(1);\r
155 \r
156     //mainthreadID = GetCurrentThreadId();\r
157 \r
158     //openWindow(640,388);\r
159 \r
160     //thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(maincaller), (/*data*/0), 0, (LPDWORD)&(threadID));\r
161   \r
162     /*while(GetMessage(&msg,NULL,0,0))\r
163     {\r
164         TranslateMessage(&msg);\r
165         DispatchMessage(&msg);\r
166     }*/\r
167 \r
168     //closeWindow();\r
169     //ret = msg.wParam;\r
170 \r
171     initialized = 1;\r
172 \r
173     return ret;\r
174 }\r
175 \r
176 #define Q_REDRAW 0x7f01\r
177 #define Q_DUMMY  0x7f02\r
178 \r
179 static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
180 {\r
181  switch(message)\r
182  {\r
183    case WM_DESTROY:\r
184     PostQuitMessage(0);\r
185     break;\r
186    case WM_PAINT:\r
187     BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
188    break;\r
189    case Q_DUMMY:\r
190    break;\r
191    case Q_REDRAW: {\r
192     int x,y;\r
193     for(y=0;y<sizey;y++) {\r
194         unsigned char*o = (unsigned char*)&offscreen[y*sizex*4];\r
195         unsigned char*s = (unsigned char*)&screen[(sizey-y-1)*sizex*3];\r
196         for(x=0;x<sizex;x++) {\r
197             s[0] = o[0];\r
198             s[1] = o[1];\r
199             s[2] = o[2];\r
200             s+=3;\r
201             o+=4;\r
202         }\r
203     }\r
204 \r
205 #ifndef DIB\r
206     SetBitmapBits(piccy, screensize, screen);\r
207     InvalidateRect(hwnd,NULL,1);\r
208 #endif\r
209 \r
210 #ifdef DIB\r
211     //SetDIBitsToDevice\r
212     BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
213 #else\r
214     BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
215 #endif\r
216    break;\r
217    }\r
218    case WM_TIMER:\r
219     //InvalidateRect(hwnd,NULL,1);\r
220    default:\r
221     return DefWindowProc(hwnd, message, wParam, lParam);\r
222  }\r
223  return 0;\r
224 }\r
225 \r
226 static void ModeRGB_on(window_t*win)\r
227 {\r
228     MSG msg;\r
229     //printf("on()\n");\r
230     openWindow(sizex, sizey);\r
231     win->currentscr = (unsigned char*)offscreen;\r
232 \r
233     while(GetMessage(&msg,NULL,0,0))\r
234     {\r
235         TranslateMessage(&msg);\r
236         DispatchMessage(&msg);\r
237         if(msg.message == WM_PAINT)\r
238             break;\r
239     }\r
240 }\r
241 static void ModeRGB_off(window_t*win)\r
242 {\r
243     MSG msg;\r
244     //printf("off()\n");\r
245     //TODO: shouldn't this be DestroyWindow(hwnd)?\r
246     PostMessage(hwnd, WM_DESTROY, 0, 0);\r
247     while(GetMessage(&msg,NULL,0,0))\r
248     {\r
249         TranslateMessage(&msg);\r
250         DispatchMessage(&msg);\r
251         if(msg.message == WM_DESTROY)\r
252             break;\r
253     }\r
254     closeWindow();\r
255     win->currentscr = win->lastscr = 0;\r
256 }\r
257 static void ModeRGB_flippage(window_t*win)\r
258 {\r
259     MSG msg;\r
260     PostMessage(hwnd, Q_REDRAW, 0, 0);\r
261     while(GetMessage(&msg,NULL,0,0))\r
262     {\r
263         TranslateMessage(&msg);\r
264         DispatchMessage(&msg);\r
265         if(msg.message == Q_REDRAW)\r
266             break;\r
267     }\r
268     win->currentscr = (byte*)offscreen;\r
269 }\r
270 static gfxevent_t ModeRGB_getEvent(window_t*win)\r
271 {\r
272     MSG msg;\r
273     WPARAM wParam;\r
274     LPARAM lParam;\r
275     gfxevent_t event;\r
276 \r
277     //PostMessage(hwnd, Q_DUMMY, 0, 0);\r
278 \r
279     event.type = GFXEVENT_NOTHING;\r
280     event.key = 0;\r
281     event.x = 0;\r
282     event.y = 0;\r
283     event.type = 0;\r
284     event.button = 0;\r
285 \r
286     if(!PeekMessage(&msg,NULL,0,0,0))\r
287         return event;//nothing\r
288 \r
289     while(GetMessage(&msg,NULL,0,0))\r
290     {\r
291         lParam = msg.lParam;\r
292         wParam = msg.wParam;\r
293         if(msg.message == Q_DUMMY) {\r
294             event.type = GFXEVENT_NOTHING;\r
295             break;\r
296         } else if(msg.message == WM_LBUTTONDOWN) {\r
297             event.type = GFXEVENT_MOUSEPRESS;\r
298             event.button = 1;\r
299             event.x = (signed short int)LOWORD(lParam);\r
300             event.y = (signed short int)HIWORD(lParam);\r
301             SetCapture(hwnd);\r
302             break;\r
303         } else if(msg.message == WM_LBUTTONUP) {\r
304             event.type = GFXEVENT_MOUSERELEASE;\r
305             event.button = 1;\r
306             event.x = (signed short int)LOWORD(lParam);\r
307             event.y = (signed short int)HIWORD(lParam);\r
308             ReleaseCapture();\r
309             break;\r
310         } else if(msg.message == WM_MBUTTONDOWN) {\r
311             event.type = GFXEVENT_MOUSEPRESS;\r
312             event.button = 2;\r
313             event.x = (signed short int)LOWORD(lParam);\r
314             event.y = (signed short int)HIWORD(lParam);\r
315             SetCapture(hwnd);\r
316             break;\r
317         } else if(msg.message == WM_MBUTTONUP) {\r
318             event.type = GFXEVENT_MOUSERELEASE;\r
319             event.button = 1;\r
320             event.x = (signed short int)LOWORD(lParam);\r
321             event.y = (signed short int)HIWORD(lParam);\r
322             ReleaseCapture();\r
323             break;\r
324         } else if(msg.message == WM_RBUTTONDOWN) {\r
325             event.type = GFXEVENT_MOUSEPRESS;\r
326             event.button = 3;\r
327             event.x = (signed short int)LOWORD(lParam);\r
328             event.y = (signed short int)HIWORD(lParam);\r
329             SetCapture(hwnd);\r
330             break;\r
331         } else if(msg.message == WM_RBUTTONUP) {\r
332             event.type = GFXEVENT_MOUSERELEASE;\r
333             event.button = 3;\r
334             event.x = (signed short int)LOWORD(lParam);\r
335             event.y = (signed short int)HIWORD(lParam);\r
336             ReleaseCapture();\r
337             break;\r
338         } else if(msg.message == WM_MOUSEMOVE) {\r
339             event.type = GFXEVENT_MOUSEMOVE;\r
340             event.x = (signed short int)LOWORD(lParam);\r
341             event.y = (signed short int)HIWORD(lParam);\r
342             break;\r
343         } else if(msg.message == WM_CHAR) {\r
344             event.type = GFXEVENT_KEYPRESS;\r
345             event.key = (char)wParam;\r
346             break;\r
347         } else {\r
348             TranslateMessage(&msg);\r
349             DispatchMessage(&msg);\r
350             event.type = GFXEVENT_NOTHING;\r
351             break;\r
352         }\r
353     }\r
354     return event;\r
355 }\r
356 static void ModeRGB_move(window_t*win, int relx,int rely)\r
357 {\r
358     MSG msg;\r
359     PostMessage(hwnd, Q_DUMMY, 0, 0);\r
360     while(GetMessage(&msg,NULL,0,0))\r
361     {\r
362         if(msg.message == WM_LBUTTONUP) {\r
363             SendMessage(hwnd, msg.message, msg.wParam, msg.lParam);\r
364             return;\r
365         }\r
366         TranslateMessage(&msg);\r
367         DispatchMessage(&msg);\r
368         if(msg.message == Q_DUMMY)\r
369             break;\r
370     }\r
371     posx+=relx;\r
372     posy+=rely;\r
373    \r
374     if(posx > desktopSize.right-cwidth) posx = desktopSize.right-cwidth;\r
375     if(posy > desktopSize.bottom-cheight) posy = desktopSize.bottom-cheight;\r
376     if(posx < desktopSize.left) posx = desktopSize.left;\r
377     if(posy < desktopSize.top) posy = desktopSize.top;\r
378 \r
379     SetWindowPos(hwnd, HWND_TOP, posx, posy, 0, 0, SWP_NOSIZE);\r
380     PostMessage(hwnd, Q_DUMMY, 0, 0);\r
381     while(GetMessage(&msg,NULL,0,0))\r
382     {\r
383         if(msg.message == WM_LBUTTONUP) {\r
384             SendMessage(hwnd, msg.message, msg.wParam, msg.lParam);\r
385             break;;\r
386         }\r
387         TranslateMessage(&msg);\r
388         DispatchMessage(&msg);\r
389         if(msg.message == Q_DUMMY)\r
390             break;\r
391     }\r
392 }\r
393 static void ModeRGB_resize(window_t*win, int width,int height)\r
394 {\r
395     if(width>sizex || height>sizey) {\r
396         printf("mode24::resize: can only make windows smaller\n");\r
397         return;\r
398     }\r
399     if(width<1) width=1;\r
400     if(height<1) height=1;\r
401     cwidth = width;\r
402     cheight = height;\r
403     SetWindowPos(hwnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE);\r
404     win->move(win,0,0);\r
405 }\r
406 \r
407 \r
408 window_t* window_new(window_t*win, int width, int height)\r
409 {\r
410     window_t*w = (window_t*)malloc(sizeof(window_t));\r
411     memset(w, 0, sizeof(window_t));\r
412     if(!initialized)\r
413         initwin32();\r
414     w->currentscr = w->lastscr = 0;\r
415     sizex = width;\r
416     sizey = height;\r
417     cwidth = sizex;\r
418     cheight = sizey;\r
419     //printf("contruct(%d, %d)\n", x, y);\r
420     w->on = ModeRGB_on;\r
421     w->off = ModeRGB_off;\r
422     w->move = ModeRGB_move;\r
423     w->resize = ModeRGB_resize;\r
424     w->flippage = ModeRGB_flippage;\r
425     w->getEvent = ModeRGB_getEvent;\r
426     w->width = width;\r
427     w->height = height;\r
428     return w;\r
429 }\r
430 \r