1 /**
2 ** vd_win32.c ---- the standard Win32-API driver
3 **
4 ** Author: Gernot Graeff
5 ** E-mail: gernot.graeff@t-online.de
6 ** Date: 13.11.98
7 **
8 ** This file is part of the GRX graphics library.
9 **
10 ** The GRX graphics library is free software; you can redistribute it
11 ** and/or modify it under some conditions; see the "copying.grx" file
12 ** for details.
13 **
14 ** This library is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Changes by Josu Onandia (jonandia@fagorautomation.es) 21/02/2001
19 ** - The colors loaded in the ColorList are guaranteed to be actually used
20 ** by Windows (GetNearestColor), for the GR_frameWin32 to work.
21 ** - When the window is created, it gets the maximum size allowed by the
22 ** current mode. Indeed this size is stored (maxWindowWidth/
23 ** maxWindowHeight).
24 ** When the window is going to be resized (WM_GETMINMAXINFO) it's not
25 ** allowed to grow bigger than this maximum size (it makes nosense).
26 ** - Added some modes for 24bpp colors.
27 ** - When changed to text-mode, the graphics window is hidden. If the
28 ** application has a console (linked with -mconsole) it can use
29 ** printf/scanf and the like.
30 ** When changed again into graphics mode, the window reappears.
31 ** - Inter-task synchronization. In some cases the two threads are
32 ** manipulating at the same time the main window, and the on-memory
33 ** bitmap. I guess this is causing trouble, so in some cases the main
34 ** thread suspends the worker thread, make its operation, and then
35 ** resumes it.
36 ** - The window title is selectable with a define, at compile time.
37 ** If not defined, it defaults to "GRX".
38 **
39 ** Changes by M.Alvarez (malfer@telefonica.net) 02/01/2002
40 ** - Go to full screen if the framemode dimensions are equal to
41 ** the screen dimensions (setting the client start area at 0,0).
42 **
43 ** Changes by M.Alvarez (malfer@telefonica.net) 02/02/2002
44 ** - The w32 imput queue implemented as a circular queue.
45 ** - All the input related code moved to w32inp.c
46 ** - The main window is created in WinMain, so the grx program
47 ** can use other videodrivers like the memory one.
48 **
49 ** Changes by M.Alvarez (malfer@telefonica.net) 11/02/2002
50 ** - Now the GRX window is properly closed, so the previous app
51 ** gets the focus.
52 **
53 ** Changes by M.Alvarez (malfer@telefonica.net) 31/03/2002
54 ** - Accepts arbitrary (user defined) resolution.
55 **
56 ** Changes by Thomas Demmer (TDemmer@krafteurope.com)
57 ** - Instead of begin with WinMain and start a thread with the main
58 ** GRX program, do it backward: begin in main and start a thread to
59 ** handle the Windows window. With this change we get rid of the
60 ** awful GRXMain special entry point.
61 **
62 ** Changes by M.Alvarez (malfer@telefonica.net) 12/02/2003
63 ** - Sanitize the Thomas changes.
64 **
65 ** Changes by Thomas Demmer (TDemmer@krafteurope.com) 18/03/2003
66 ** - Use a DIB for the hDCMem.
67 **
68 ** Changes by Josu Onandia (jonandia@fagorautomation.es) 19/03/2003
69 ** - With the Thomas idea of using a DIB, we can now use the DIB like
70 ** a linear frame buffer, so the new win32 framedrivers can take
71 ** advantage of the standard GRX frame drivers.
72 **
73 ** Changes by Peter Gerwinski 19/06/2004
74 ** - more W32 events handling
75 **
76 ** Changes by Maurice Lombardi 21/08/2007
77 ** - Corrections to WM_PAINT
78 ** 1 - revert the previous change: was saturating GrMouseInfo->queue
79 ** for fast paintings
80 ** 2 - GetUpdateRect() gave wrong UpdateRect !!!
81 **
82 ** Changes by Peter Schauer <peterschauer@gmx.net> 12/05/2008
83 ** - vdrivers/vd_win32.c has a race condition with the loadcolor
84 ** SetDIBColorTable function call, which happens sometimes on
85 ** fast multiprocessor machines. This affects only 8 bpp modes,
86 ** as loadcolor is not called in 32 bpp modes.
87 ** If the WndThread is currently executing its BitBlt during WM_PAINT
88 ** processing and the GRX user thread is calling GrAllocColor, the
89 ** SetDIBColorTable function call fails, as the DC is locked by the BitBlt.
90 ** This results in the color not being set, which could also happen
91 ** during the initial setting of the VGA colors in _GrResetColors.
92 ** My proposed fix delays the SetDIBColorTable call and moves it to
93 ** the WM_PAINT processing, making it synchronous with the BitBlt call.
94 **
95 ** Changes by M.Alvarez (malfer@telefonica.net) 01/12/2007
96 ** - Added videomodes for wide monitors
97 **
98 **/
99
100 #include "libwin32.h"
101 #include "libgrx.h"
102 #include "grdriver.h"
103 #include "arith.h"
104
105 #ifndef GRXWINDOW_TITLE
106 #define GRXWINDOW_TITLE "GRX"
107 #endif
108
109 HWND hGRXWnd = NULL;
110 HWND hPrvWnd = NULL;
111 HDC hDCMem = NULL;
112
113 CRITICAL_SECTION _csEventQueue;
114 W32Event *_W32EventQueue = NULL;
115 volatile int _W32EventQueueSize = 0;
116 volatile int _W32EventQueueRead = 0;
117 volatile int _W32EventQueueWrite = 0;
118 volatile int _W32EventQueueLength = 0;
119
120 static HBITMAP hBmpDIB = NULL;
121
122 static int maxScreenWidth, maxScreenHeight;
123 static int maxWindowWidth, maxWindowHeight;
124
125 HANDLE windowThread = INVALID_HANDLE_VALUE;
126 static HANDLE mainThread = INVALID_HANDLE_VALUE;
127
128 static volatile int isWindowThreadRunning = 0;
129 static volatile int isMainWaitingTermination = 0;
130
131 struct _GR_modifiedColors {
132 int modified;
133 RGBQUAD color;
134 };
135 static struct _GR_modifiedColors modifiedColors[256];
136 static volatile int isColorModified = 0;
137
138 static DWORD WINAPI WndThread(void *param);
139 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
140 LPARAM lParam);
141
loadcolor(int c,int r,int g,int b)142 static void loadcolor(int c, int r, int g, int b)
143 {
144 RGBQUAD color;
145 color.rgbBlue = b;
146 color.rgbGreen = g;
147 color.rgbRed = r;
148 color.rgbReserved = 0;
149 if (c >= 0 && c <= 256) {
150 modifiedColors[c].color = color;
151 modifiedColors[c].modified = 1;
152 isColorModified = 1;
153 InvalidateRect(hGRXWnd, NULL, FALSE);
154 }
155 }
156
CreateDIB8(HDC hdc,int w,int h,char ** pBits)157 static HBITMAP CreateDIB8(HDC hdc, int w, int h, char **pBits)
158 {
159 BITMAPINFO *pbmInfo;
160 HBITMAP hBmp;
161
162 pbmInfo = malloc(sizeof(BITMAPINFO) +256*sizeof(RGBQUAD));
163 pbmInfo->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
164 pbmInfo->bmiHeader.biWidth = w;
165 pbmInfo->bmiHeader.biHeight = -h;
166 pbmInfo->bmiHeader.biPlanes = 1;
167 pbmInfo->bmiHeader.biBitCount = 8;
168 pbmInfo->bmiHeader.biCompression = BI_RGB;
169 pbmInfo->bmiHeader.biSizeImage = 0;
170 pbmInfo->bmiHeader.biXPelsPerMeter = 0;
171 pbmInfo->bmiHeader.biYPelsPerMeter = 0;
172 pbmInfo->bmiHeader.biClrUsed = 0;
173 pbmInfo->bmiHeader.biClrImportant = 0;
174 hBmp = CreateDIBSection(0, pbmInfo, DIB_RGB_COLORS, (void*)pBits, 0, 0);
175 free(pbmInfo);
176 return(hBmp);
177 }
178
CreateDIB24(HDC hdc,int w,int h,char ** pBits)179 static HBITMAP CreateDIB24(HDC hdc, int w, int h, char **pBits)
180 {
181 BITMAPINFO *pbmInfo;
182 HBITMAP hBmp;
183
184 pbmInfo = malloc(sizeof(BITMAPINFO));
185 pbmInfo->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
186 pbmInfo->bmiHeader.biWidth = w;
187 pbmInfo->bmiHeader.biHeight = -h;
188 pbmInfo->bmiHeader.biPlanes = 1;
189 pbmInfo->bmiHeader.biBitCount = 24;
190 pbmInfo->bmiHeader.biCompression = BI_RGB;
191 pbmInfo->bmiHeader.biSizeImage = 0;
192 pbmInfo->bmiHeader.biXPelsPerMeter = 0;
193 pbmInfo->bmiHeader.biYPelsPerMeter = 0;
194 pbmInfo->bmiHeader.biClrUsed = 0;
195 pbmInfo->bmiHeader.biClrImportant = 0;
196 hBmp = CreateDIBSection(0, pbmInfo, DIB_RGB_COLORS, (void*)pBits, 0, 0);
197 free(pbmInfo);
198 return(hBmp);
199 }
200
setmode(GrVideoMode * mp,int noclear)201 static int setmode(GrVideoMode * mp, int noclear)
202 {
203 RECT Rect;
204 HDC hDC;
205 HBRUSH hBrush;
206 RGBQUAD color;
207 int inipos;
208
209 if (mp->extinfo->mode != GR_frameText) {
210 inipos = 50;
211 if (mp->width == maxScreenWidth && mp->height == maxScreenHeight)
212 inipos = 0;
213 Rect.left = inipos;
214 Rect.top = inipos;
215 Rect.right = mp->width + inipos;
216 Rect.bottom = mp->height + inipos;
217 AdjustWindowRect(&Rect, WS_OVERLAPPEDWINDOW, FALSE);
218 maxWindowWidth = Rect.right - Rect.left;
219 maxWindowHeight = Rect.bottom - Rect.top;
220 SetWindowPos(hGRXWnd, NULL,
221 Rect.left, Rect.top,
222 maxWindowWidth, maxWindowHeight,
223 SWP_DRAWFRAME | SWP_NOZORDER | SWP_SHOWWINDOW);
224
225 if (hBmpDIB != NULL) {
226 DeleteObject(hBmpDIB);
227 hBmpDIB = NULL;
228 }
229 hDC = GetDC(hGRXWnd);
230 if (hDCMem == NULL)
231 hDCMem = CreateCompatibleDC(hDC);
232 if (mp->bpp == 8) {
233 hBmpDIB = CreateDIB8(hDC, mp->width, mp->height,
234 &mp->extinfo->frame);
235 } else {
236 hBmpDIB = CreateDIB24(hDC, mp->width, mp->height,
237 &mp->extinfo->frame);
238 }
239 SelectObject(hDCMem, hBmpDIB);
240 if (mp->bpp == 8) {
241 color.rgbBlue = color.rgbGreen = color.rgbRed =
242 color.rgbReserved = 0;
243 SetDIBColorTable(hDCMem, 0, 1, &color);
244 }
245 SetRect(&Rect, 0, 0, mp->width, mp->height);
246 hBrush = CreateSolidBrush(0);
247 FillRect(hDCMem, &Rect, hBrush);
248 if (mp->bpp == 8)
249 BitBlt(hDC, 0, 0, mp->width, mp->height, hDCMem, 0, 0, SRCCOPY);
250 else
251 FillRect(hDC, &Rect, hBrush);
252 ReleaseDC(hGRXWnd, hDC);
253 DeleteObject(hBrush);
254 UpdateWindow(hGRXWnd);
255 SetForegroundWindow(hGRXWnd);
256 } else {
257 /* If changing to text-mode, hide the graphics window. */
258 if (hGRXWnd != NULL) {
259 ShowWindow(hGRXWnd, SW_HIDE);
260 SetForegroundWindow(hPrvWnd);
261 }
262 }
263 return (TRUE);
264 }
265
setbank_dummy(int bk)266 static void setbank_dummy(int bk)
267 {
268 bk = bk;
269 }
270
271 GrVideoModeExt grtextext = {
272 GR_frameText, /* frame driver */
273 NULL, /* frame driver override */
274 NULL, /* frame buffer address */
275 {0, 0, 0}, /* color precisions */
276 {0, 0, 0}, /* color component bit positions */
277 0, /* mode flag bits */
278 setmode, /* mode set */
279 NULL, /* virtual size set */
280 NULL, /* virtual scroll */
281 NULL, /* bank set function */
282 NULL, /* double bank set function */
283 NULL /* color loader */
284 };
285
286 static GrVideoModeExt grxwinext8 = {
287 GR_frameWIN32_8, /* frame driver */
288 NULL, /* frame driver override */
289 NULL, /* frame buffer address */
290 {8, 8, 8}, /* color precisions */
291 {0, 8, 16}, /* color component bit positions */
292 0, /* mode flag bits */
293 setmode, /* mode set */
294 NULL, /* virtual size set */
295 NULL, /* virtual scroll */
296 setbank_dummy, /* bank set function */
297 NULL, /* double bank set function */
298 loadcolor /* color loader */
299 };
300
301 static GrVideoModeExt grxwinext24 = {
302 GR_frameWIN32_24, /* frame driver */
303 NULL, /* frame driver override */
304 NULL, /* frame buffer address */
305 {8, 8, 8}, /* color precisions */
306 {16, 8, 0}, /* color component bit positions */
307 0, /* mode flag bits */
308 setmode, /* mode set */
309 NULL, /* virtual size set */
310 NULL, /* virtual scroll */
311 setbank_dummy, /* bank set function */
312 NULL, /* double bank set function */
313 NULL /* color loader */
314 };
315
316 static GrVideoMode modes[] = {
317 /* pres. bpp wdt hgt BIOS scan priv. &ext */
318 {TRUE, 8, 80, 25, 0x00, 80, 1, &grtextext},
319
320 {TRUE, 8, 320, 240, 0x00, 320, 0, &grxwinext8},
321 {TRUE, 8, 640, 480, 0x00, 640, 0, &grxwinext8},
322 {TRUE, 8, 800, 600, 0x00, 800, 0, &grxwinext8},
323 {TRUE, 8, 1024, 768, 0x00, 1024, 0, &grxwinext8},
324 {TRUE, 8, 1280, 1024, 0x00, 1280, 0, &grxwinext8},
325 {TRUE, 8, 1600, 1200, 0x00, 1600, 0, &grxwinext8},
326 {TRUE, 8, 1440, 900, 0x00, 1440, 0, &grxwinext8},
327 {TRUE, 8, 1680, 1050, 0x00, 1680, 0, &grxwinext8},
328 {TRUE, 8, 1920, 1200, 0x00, 1920, 0, &grxwinext8},
329 {TRUE, 8, 2560, 1600, 0x00, 2560, 0, &grxwinext8},
330
331 {TRUE, 24, 320, 240, 0x00, 960, 0, &grxwinext24},
332 {TRUE, 24, 640, 480, 0x00, 1920, 0, &grxwinext24},
333 {TRUE, 24, 800, 600, 0x00, 2400, 0, &grxwinext24},
334 {TRUE, 24, 1024, 768, 0x00, 3072, 0, &grxwinext24},
335 {TRUE, 24, 1280, 1024, 0x00, 3840, 0, &grxwinext24},
336 {TRUE, 24, 1600, 1200, 0x00, 4800, 0, &grxwinext24},
337 {TRUE, 24, 1440, 900, 0x00, 4320, 0, &grxwinext24},
338 {TRUE, 24, 1680, 1050, 0x00, 5040, 0, &grxwinext24},
339 {TRUE, 24, 1920, 1200, 0x00, 5760, 0, &grxwinext24},
340 {TRUE, 24, 2560, 1600, 0x00, 7680, 0, &grxwinext24},
341
342 {FALSE, 0, 9999, 9999, 0x00, 0, 0, NULL}
343 };
344
detect(void)345 static int detect(void)
346 {
347 static int inited = 0;
348 WNDCLASSEX wndclass;
349
350 if (!inited) {
351 wndclass.cbSize = sizeof(wndclass);
352 wndclass.style = CS_HREDRAW | CS_VREDRAW;
353 wndclass.lpfnWndProc = WndProc;
354 wndclass.cbClsExtra = 0;
355 wndclass.cbWndExtra = 0;
356 wndclass.hInstance = GetModuleHandle(NULL);
357 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
358 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
359 wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
360 wndclass.lpszMenuName = NULL;
361 wndclass.lpszClassName = "GRXCLASS";
362 wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
363 if (RegisterClassEx(&wndclass)== 0) return FALSE;
364 inited = 1;
365 }
366
367 return TRUE;
368 }
369
init(char * options)370 static int init(char *options)
371 {
372 int i;
373 DWORD thread_id;
374
375 if (!detect()) return FALSE;
376
377 /* WARNING: mainThread can not be used in the windowThread */
378 mainThread = GetCurrentThread();
379
380 hPrvWnd = GetForegroundWindow();
381
382 InitializeCriticalSection(&_csEventQueue);
383
384 /* The modes not compatible width the configuration */
385 /* of Windows are made 'non-present' */
386 maxScreenWidth = GetSystemMetrics(SM_CXSCREEN);
387 for (i = 1; i < itemsof(modes); i++) {
388 if (modes[i].width > maxScreenWidth)
389 modes[i].present = FALSE;
390 }
391 maxScreenHeight = GetSystemMetrics(SM_CYSCREEN);
392 for (i = 1; i < itemsof(modes); i++) {
393 if (modes[i].height > maxScreenHeight)
394 modes[i].present = FALSE;
395 }
396
397 windowThread = CreateThread(NULL, 0, WndThread, NULL, 0, &thread_id);
398
399 /* Wait for thread creating the window. This is a busy */
400 /* waiting loop (bad), but we Sleep to yield (good) */
401 while (isWindowThreadRunning == 0)
402 Sleep(1);
403
404 return TRUE;
405 }
406
reset(void)407 static void reset(void)
408 {
409 isMainWaitingTermination = 1;
410 PostMessage(hGRXWnd, WM_CLOSE, 0, 0);
411
412 while (isWindowThreadRunning == 1)
413 Sleep(1);
414
415 isMainWaitingTermination = 0;
416 DeleteCriticalSection(&_csEventQueue);
417
418 if(hBmpDIB != NULL)
419 {
420 DeleteObject(hBmpDIB);
421 hBmpDIB = NULL;
422 }
423 if (hDCMem != NULL) {
424 DeleteDC(hDCMem);
425 hDCMem = NULL;
426 }
427 }
428
_w32_selectmode(GrVideoDriver * drv,int w,int h,int bpp,int txt,unsigned int * ep)429 static GrVideoMode * _w32_selectmode(GrVideoDriver * drv, int w, int h,
430 int bpp, int txt, unsigned int * ep)
431 {
432 GrVideoMode *mp, *res;
433 long resto;
434
435 if (txt) {
436 res = _gr_selectmode(drv, w, h, bpp, txt, ep);
437 goto done;
438 }
439 for (mp = &modes[1]; mp < &modes[itemsof(modes)-1]; mp++) {
440 if (mp->present && mp->width == w && mp->height == h) {
441 res = _gr_selectmode(drv, w, h, bpp, txt, ep);
442 goto done;
443 }
444 }
445 /* no predefined mode found. Create a new mode if we can*/
446 if (w <= maxScreenWidth && h <= maxScreenHeight) {
447 mp->present = TRUE;
448 mp->width = w;
449 mp->height = h;
450 if (bpp <= 8) {
451 mp->bpp = 8;
452 mp->extinfo = &grxwinext8;
453 resto = mp->width % 4;
454 if (resto) resto = 4 - resto;
455 mp->lineoffset = mp->width + resto;
456 }
457 else {
458 mp->bpp = 24;
459 mp->extinfo = &grxwinext24;
460 resto = (mp->width * 3) % 4;
461 if (resto) resto = 4 - resto;
462 mp->lineoffset = mp->width * 3 + resto;
463 }
464 }
465 res = _gr_selectmode(drv, w, h, bpp, txt, ep);
466 done:
467 return res;
468 }
469
470 GrVideoDriver _GrVideoDriverWIN32 = {
471 "win32", /* name */
472 GR_WIN32, /* adapter type */
473 NULL, /* inherit modes from this driver */
474 modes, /* mode table */
475 itemsof(modes), /* # of modes */
476 detect, /* detection routine */
477 init, /* initialization routine */
478 reset, /* reset routine */
479 _w32_selectmode, /* special mode select routine */
480 GR_DRIVERF_USER_RESOLUTION /* arbitrary resolution possible */
481 };
482
WndThread(void * param)483 static DWORD WINAPI WndThread(void *param)
484 {
485 MSG msg;
486
487 hGRXWnd = CreateWindow("GRXCLASS", GRXWINDOW_TITLE,
488 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
489 | WS_THICKFRAME | WS_MINIMIZEBOX, 0, 0,
490 CW_USEDEFAULT, CW_USEDEFAULT, NULL,
491 NULL, GetModuleHandle(NULL), NULL);
492 ShowWindow(hGRXWnd, SW_HIDE);
493
494 isWindowThreadRunning = 1;
495
496 while (GetMessage(&msg, NULL, 0, 0)) {
497 TranslateMessage(&msg);
498 DispatchMessage(&msg);
499 }
500
501 isWindowThreadRunning = 0;
502
503 ExitThread(0);
504 return 0;
505 }
506
convertwin32keystate(void)507 static int convertwin32keystate(void)
508 {
509 int fkbState = 0;
510
511 if (GetKeyState(VK_SHIFT) < 0)
512 fkbState |= GR_KB_SHIFT;
513 if (GetKeyState(VK_CONTROL) < 0)
514 fkbState |= GR_KB_CTRL;
515 if (GetKeyState(VK_MENU) < 0)
516 fkbState |= GR_KB_ALT;
517 if (GetKeyState(VK_SCROLL) < 0)
518 fkbState |= GR_KB_SCROLLOCK;
519 if (GetKeyState(VK_NUMLOCK) < 0)
520 fkbState |= GR_KB_NUMLOCK;
521 if (GetKeyState(VK_CAPITAL) < 0)
522 fkbState |= GR_KB_CAPSLOCK;
523 if (GetKeyState(VK_INSERT) < 0)
524 fkbState |= GR_KB_INSERT;
525 return fkbState;
526 }
527
EnqueueW32Event(UINT uMsg,WPARAM wParam,LPARAM lParam,int kbstat)528 static void EnqueueW32Event(UINT uMsg, WPARAM wParam, LPARAM lParam,
529 int kbstat)
530 {
531 if (_W32EventQueue == NULL)
532 return;
533
534 EnterCriticalSection(&_csEventQueue);
535 _W32EventQueue[_W32EventQueueWrite].uMsg = uMsg;
536 _W32EventQueue[_W32EventQueueWrite].wParam = wParam;
537 _W32EventQueue[_W32EventQueueWrite].lParam = lParam;
538 _W32EventQueue[_W32EventQueueWrite].kbstat = kbstat;
539 if (++_W32EventQueueWrite == _W32EventQueueSize)
540 _W32EventQueueWrite = 0;
541 if (++_W32EventQueueLength > _W32EventQueueSize) {
542 _W32EventQueueLength--;
543 if (++_W32EventQueueRead == _W32EventQueueSize)
544 _W32EventQueueRead = 0;
545 }
546 LeaveCriticalSection(&_csEventQueue);
547 }
548
WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)549 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
550 LPARAM lParam)
551 {
552 static int cursorOn = 1;
553 int kbstat;
554 BOOL fInsert;
555
556 switch (uMsg) {
557
558 case WM_NCHITTEST:
559 {
560 LRESULT res = DefWindowProc(hWnd, uMsg, wParam, lParam);
561 if (res == HTCLIENT) {
562 if (cursorOn) {
563 ShowCursor(FALSE);
564 cursorOn = 0;
565 }
566 } else {
567 if (!cursorOn) {
568 ShowCursor(TRUE);
569 cursorOn = 1;
570 }
571 }
572 return res;
573 }
574
575 case WM_CLOSE:
576 if (!isMainWaitingTermination && MessageBox(hWnd,
577 "This will abort the program\nare you sure?", "Abort",
578 MB_APPLMODAL | MB_ICONQUESTION | MB_YESNO ) != IDYES)
579 return 0;
580 DestroyWindow(hWnd);
581 if (!isMainWaitingTermination)
582 {
583 isWindowThreadRunning = 0;
584 ExitProcess(1);
585 }
586 break;
587
588 case WM_DESTROY:
589 PostQuitMessage(0);
590 break;
591
592 case WM_GETMINMAXINFO:
593 {
594 LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
595
596 lpmmi->ptMaxSize.x = lpmmi->ptMaxTrackSize.x = maxWindowWidth;
597 lpmmi->ptMaxSize.y = lpmmi->ptMaxTrackSize.y = maxWindowHeight;
598 }
599 return 0;
600
601 case WM_SYSCHAR:
602 fInsert = FALSE;
603 kbstat = convertwin32keystate();
604 if (kbstat & GR_KB_ALT) {
605 if (wParam >= 'a' && wParam <= 'z')
606 fInsert = TRUE;
607 if (wParam >= 'A' && wParam <= 'Z')
608 fInsert = TRUE;
609 if (wParam >= '0' && wParam <= '9')
610 fInsert = TRUE;
611 }
612 if (!fInsert)
613 break;
614 EnqueueW32Event(uMsg, wParam, lParam, kbstat);
615 return 0;
616
617 case WM_COMMAND:
618 case WM_CHAR:
619 case WM_KEYDOWN:
620 case WM_SYSKEYDOWN:
621 case WM_LBUTTONDOWN:
622 case WM_MBUTTONDOWN:
623 case WM_RBUTTONDOWN:
624 case WM_LBUTTONUP:
625 case WM_MBUTTONUP:
626 case WM_RBUTTONUP:
627 case WM_MOUSEMOVE:
628 {
629 kbstat = convertwin32keystate();
630 EnqueueW32Event(uMsg, wParam, lParam, kbstat);
631 }
632 return 0;
633
634 case WM_MOUSEWHEEL:
635 {
636 kbstat = convertwin32keystate();
637 /* twice to simulate down up */
638 EnqueueW32Event(uMsg, wParam, lParam, kbstat);
639 EnqueueW32Event(uMsg, wParam, lParam, kbstat);
640 }
641 return 0;
642
643
644 case WM_PAINT:
645 {
646 HDC hDC;
647 PAINTSTRUCT ps;
648
649 if (isColorModified) {
650 int c;
651
652 isColorModified = 0;
653 for (c = 0; c < 256; c++) {
654 if (modifiedColors[c].modified) {
655 int res;
656
657 modifiedColors[c].modified = 0;
658 if ((res = SetDIBColorTable(hDCMem, c, 1, &modifiedColors[c].color)) != 1)
659 DBGPRINTF(DBG_DRIVER,("SetDIBColorTable returned %d (%ld) color %d\n", res, GetLastError(), c));
660 }
661 }
662 }
663
664 hDC = BeginPaint(hWnd, &ps);
665 BitBlt(hDC,
666 ps.rcPaint.left, ps.rcPaint.top,
667 ps.rcPaint.right - ps.rcPaint.left + 1,
668 ps.rcPaint.bottom - ps.rcPaint.top + 1,
669 hDCMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
670 EndPaint(hWnd, &ps);
671 }
672 return 0;
673
674 case WM_SYSCOMMAND:
675 case WM_NCCREATE:
676 case WM_NCPAINT:
677 case WM_NCMOUSEMOVE:
678 case WM_PALETTEISCHANGING:
679 case WM_ACTIVATEAPP:
680 case WM_NCCALCSIZE:
681 case WM_ACTIVATE:
682 case WM_NCACTIVATE:
683 case WM_SHOWWINDOW:
684 case WM_WINDOWPOSCHANGING:
685 case WM_GETTEXT:
686 case WM_SETFOCUS:
687 case WM_KILLFOCUS:
688 case WM_GETICON:
689 case WM_ERASEBKGND:
690 case WM_QUERYNEWPALETTE:
691 case WM_WINDOWPOSCHANGED:
692 case WM_GETDLGCODE:
693 case WM_MOVE:
694 case WM_SIZE:
695 case WM_SETCURSOR:
696 case WM_HELP:
697 case WM_KEYUP:
698 case WM_SYSKEYUP:
699 break;
700
701 default:
702 /*
703 char szMsg[255];
704 sprintf(szMsg, "Msg %x, wParam %d, lParam %d",
705 uMsg, wParam, lParam);
706 MessageBox(NULL, szMsg, "Msg", MB_OK);
707 */
708 break;
709
710 }
711
712 return DefWindowProc(hWnd, uMsg, wParam, lParam);
713 }
714