SDL-1.2.14
[sdl_omap.git] / src / video / windib / SDL_dibevents.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26
27 #include "SDL_main.h"
28 #include "SDL_events.h"
29 #include "SDL_syswm.h"
30 #include "../../events/SDL_sysevents.h"
31 #include "../../events/SDL_events_c.h"
32 #include "../wincommon/SDL_lowvideo.h"
33 #include "SDL_gapidibvideo.h"
34 #include "SDL_vkeys.h"
35
36 #ifdef SDL_VIDEO_DRIVER_GAPI
37 #include "../gapi/SDL_gapivideo.h"
38 #endif
39
40 #ifdef SDL_VIDEO_DRIVER_WINDIB
41 #include "SDL_dibvideo.h"
42 #endif
43
44 #ifndef WM_APP
45 #define WM_APP  0x8000
46 #endif
47
48 #ifdef _WIN32_WCE
49 #define NO_GETKEYBOARDSTATE
50 #endif
51
52 /* The translation table from a Microsoft VK keysym to a SDL keysym */
53 static SDLKey VK_keymap[SDLK_LAST];
54 static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed);
55 static SDLKey Arrows_keymap[4];
56
57 /* Masks for processing the windows KEYDOWN and KEYUP messages */
58 #define REPEATED_KEYMASK        (1<<30)
59 #define EXTENDED_KEYMASK        (1<<24)
60
61 /* DJM: If the user setup the window for us, we want to save his window proc,
62    and give him a chance to handle some messages. */
63 #ifdef STRICT
64 #define WNDPROCTYPE     WNDPROC
65 #else
66 #define WNDPROCTYPE     FARPROC
67 #endif
68 static WNDPROCTYPE userWindowProc = NULL;
69
70
71 #ifdef SDL_VIDEO_DRIVER_GAPI
72
73 WPARAM rotateKey(WPARAM key,int direction) 
74 {
75         if(direction ==0 ) return key;
76         
77         switch (key) {
78                 case 0x26: /* up */
79                         return Arrows_keymap[(2 + direction) % 4];
80                 case 0x27: /* right */
81                         return Arrows_keymap[(1 + direction) % 4];
82                 case 0x28: /* down */
83                         return Arrows_keymap[direction % 4];
84                 case 0x25: /* left */
85                         return Arrows_keymap[(3 + direction) % 4];
86         }
87
88         return key;
89 }
90
91 static void GapiTransform(GapiInfo *gapiInfo, LONG *x, LONG *y)
92 {
93     if(gapiInfo->hiresFix)
94     {
95         *x *= 2;
96         *y *= 2;
97     }
98
99     // 0 3 0
100     if((!gapiInfo->userOrientation && gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) ||
101     // 3 0 3
102        (gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation) ||
103     // 3 0 0
104        (gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation))
105     {
106         Sint16 temp = *x;
107         *x = SDL_VideoSurface->w - *y;
108         *y = temp;
109     }
110     else
111     // 0 0 0
112     if((!gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) ||
113     // 0 0 3
114       (!gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation))
115     {
116         // without changes
117         // *x = *x;
118         // *y = *y;
119     }
120     // default
121     else
122     {
123         // without changes
124         // *x = *x;
125         // *y = *y;
126     }
127 }
128 #endif 
129
130
131 /* The main Win32 event handler */
132 LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
133 {
134         extern int posted;
135
136         switch (msg) {
137                 case WM_SYSKEYDOWN:
138                 case WM_KEYDOWN: {
139                         SDL_keysym keysym;
140
141 #ifdef SDL_VIDEO_DRIVER_GAPI
142                         if(this->hidden->gapiInfo)
143                         {
144                                 // Drop GAPI artefacts
145                                 if (wParam == 0x84 || wParam == 0x5B)
146                                         return 0;
147
148                                 wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform);
149                         }
150 #endif 
151                         /* Ignore repeated keys */
152                         if ( lParam&REPEATED_KEYMASK ) {
153                                 return(0);
154                         }
155                         switch (wParam) {
156                                 case VK_CONTROL:
157                                         if ( lParam&EXTENDED_KEYMASK )
158                                                 wParam = VK_RCONTROL;
159                                         else
160                                                 wParam = VK_LCONTROL;
161                                         break;
162                                 case VK_SHIFT:
163                                         /* EXTENDED trick doesn't work here */
164                                         {
165                                         Uint8 *state = SDL_GetKeyState(NULL);
166                                         if (state[SDLK_LSHIFT] == SDL_RELEASED && (GetKeyState(VK_LSHIFT) & 0x8000)) {
167                                                 wParam = VK_LSHIFT;
168                                         } else if (state[SDLK_RSHIFT] == SDL_RELEASED && (GetKeyState(VK_RSHIFT) & 0x8000)) {
169                                                 wParam = VK_RSHIFT;
170                                         } else {
171                                                 /* Win9x */
172                                                 int sc = HIWORD(lParam) & 0xFF;
173
174                                                 if (sc == 0x2A)
175                                                         wParam = VK_LSHIFT;
176                                                 else
177                                                 if (sc == 0x36)
178                                                         wParam = VK_RSHIFT;
179                                                 else
180                                                         wParam = VK_LSHIFT;
181                                         }
182                                         }
183                                         break;
184                                 case VK_MENU:
185                                         if ( lParam&EXTENDED_KEYMASK )
186                                                 wParam = VK_RMENU;
187                                         else
188                                                 wParam = VK_LMENU;
189                                         break;
190                         }
191 #ifdef NO_GETKEYBOARDSTATE
192                         /* this is the workaround for the missing ToAscii() and ToUnicode() in CE (not necessary at KEYUP!) */
193                         if ( SDL_TranslateUNICODE ) {
194                                 MSG m;
195
196                                 m.hwnd = hwnd;
197                                 m.message = msg;
198                                 m.wParam = wParam;
199                                 m.lParam = lParam;
200                                 m.time = 0;
201                                 if ( PeekMessage(&m, hwnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) {
202                                         GetMessage(&m, hwnd, 0, WM_USER);
203                                         wParam = m.wParam;
204                                 }
205                         }
206 #endif /* NO_GETKEYBOARDSTATE */
207                         posted = SDL_PrivateKeyboard(SDL_PRESSED,
208                                 TranslateKey(wParam,HIWORD(lParam),&keysym,1));
209                 }
210                 return(0);
211
212                 case WM_SYSKEYUP:
213                 case WM_KEYUP: {
214                         SDL_keysym keysym;
215
216 #ifdef SDL_VIDEO_DRIVER_GAPI
217                         if(this->hidden->gapiInfo)
218                         {
219                                 // Drop GAPI artifacts
220                                 if (wParam == 0x84 || wParam == 0x5B)
221                                         return 0;
222         
223                                 wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform);
224                         }
225 #endif
226
227                         switch (wParam) {
228                                 case VK_CONTROL:
229                                         if ( lParam&EXTENDED_KEYMASK )
230                                                 wParam = VK_RCONTROL;
231                                         else
232                                                 wParam = VK_LCONTROL;
233                                         break;
234                                 case VK_SHIFT:
235                                         /* EXTENDED trick doesn't work here */
236                                         {
237                                         Uint8 *state = SDL_GetKeyState(NULL);
238                                         if (state[SDLK_LSHIFT] == SDL_PRESSED && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
239                                                 wParam = VK_LSHIFT;
240                                         } else if (state[SDLK_RSHIFT] == SDL_PRESSED && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
241                                                 wParam = VK_RSHIFT;
242                                         } else {
243                                                 /* Win9x */
244                                                 int sc = HIWORD(lParam) & 0xFF;
245
246                                                 if (sc == 0x2A)
247                                                         wParam = VK_LSHIFT;
248                                                 else
249                                                 if (sc == 0x36)
250                                                         wParam = VK_RSHIFT;
251                                                 else
252                                                         wParam = VK_LSHIFT;
253                                         }
254                                         }
255                                         break;
256                                 case VK_MENU:
257                                         if ( lParam&EXTENDED_KEYMASK )
258                                                 wParam = VK_RMENU;
259                                         else
260                                                 wParam = VK_LMENU;
261                                         break;
262                         }
263                         /* Windows only reports keyup for print screen */
264                         if ( wParam == VK_SNAPSHOT && SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED ) {
265                                 posted = SDL_PrivateKeyboard(SDL_PRESSED,
266                                         TranslateKey(wParam,HIWORD(lParam),&keysym,1));
267                         }
268                         posted = SDL_PrivateKeyboard(SDL_RELEASED,
269                                 TranslateKey(wParam,HIWORD(lParam),&keysym,0));
270                 }
271                 return(0);
272 #if defined(SC_SCREENSAVE) && defined(SC_MONITORPOWER)
273                 case WM_SYSCOMMAND: {
274                         const DWORD val = (DWORD) (wParam & 0xFFF0);
275                         if ((val == SC_SCREENSAVE) || (val == SC_MONITORPOWER)) {
276                                 if (this->hidden->dibInfo && !allow_screensaver) {
277                                         /* Note that this doesn't stop anything on Vista
278                                            if the screensaver has a password. */
279                                         return(0);
280                                 }
281                         }
282                 }
283                 /* Fall through to default processing */
284 #endif /* SC_SCREENSAVE && SC_MONITORPOWER */
285
286                 default: {
287                         /* Only post the event if we're watching for it */
288                         if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
289                                 SDL_SysWMmsg wmmsg;
290
291                                 SDL_VERSION(&wmmsg.version);
292                                 wmmsg.hwnd = hwnd;
293                                 wmmsg.msg = msg;
294                                 wmmsg.wParam = wParam;
295                                 wmmsg.lParam = lParam;
296                                 posted = SDL_PrivateSysWMEvent(&wmmsg);
297
298                         /* DJM: If the user isn't watching for private
299                                 messages in her SDL event loop, then pass it
300                                 along to any win32 specific window proc.
301                          */
302                         } else if (userWindowProc) {
303                                 return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam);
304                         }
305                 }
306                 break;
307         }
308         return(DefWindowProc(hwnd, msg, wParam, lParam));
309 }
310
311 #ifdef _WIN32_WCE
312 static BOOL GetLastStylusPos(POINT* ptLast)
313 {
314     BOOL bResult = FALSE;
315     UINT nRet;
316     GetMouseMovePoints(ptLast, 1, &nRet);
317     if ( nRet == 1 ) {
318         ptLast->x /= 4;
319         ptLast->y /= 4;
320         bResult = TRUE;
321     }
322     return bResult;
323 }
324 #endif
325
326 static void DIB_GenerateMouseMotionEvent(_THIS)
327 {
328         extern int mouse_relative;
329         extern int posted;
330
331         POINT mouse;
332 #ifdef _WIN32_WCE
333         if ( !GetCursorPos(&mouse) && !GetLastStylusPos(&mouse) ) return;
334 #else
335         if ( !GetCursorPos(&mouse) ) return;
336 #endif
337
338         if ( mouse_relative ) {
339                 POINT center;
340                 center.x = (SDL_VideoSurface->w/2);
341                 center.y = (SDL_VideoSurface->h/2);
342                 ClientToScreen(SDL_Window, &center);
343
344                 mouse.x -= center.x;
345                 mouse.y -= center.y;
346                 if ( mouse.x || mouse.y ) {
347                         SetCursorPos(center.x, center.y);
348                         posted = SDL_PrivateMouseMotion(0, 1, (Sint16)mouse.x, (Sint16)mouse.y);
349                 }
350         } else {
351                 ScreenToClient(SDL_Window, &mouse);
352 #ifdef SDL_VIDEO_DRIVER_GAPI
353        if (SDL_VideoSurface && this->hidden->gapiInfo)
354                         GapiTransform(this->hidden->gapiInfo, &mouse.x, &mouse.y);
355 #endif
356                 posted = SDL_PrivateMouseMotion(0, 0, (Sint16)mouse.x, (Sint16)mouse.y);
357         }
358 }
359
360 void DIB_PumpEvents(_THIS)
361 {
362         MSG msg;
363
364         while ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
365                 if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
366                         TranslateMessage(&msg);
367                         DispatchMessage(&msg);
368                 }
369         }
370
371         if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) {
372                 DIB_GenerateMouseMotionEvent( this );
373         }
374 }
375
376 static HKL hLayoutUS = NULL;
377
378 void DIB_InitOSKeymap(_THIS)
379 {
380         int     i;
381 #ifndef _WIN32_WCE
382         char    current_layout[KL_NAMELENGTH];
383
384         GetKeyboardLayoutName(current_layout);
385         //printf("Initial Keyboard Layout Name: '%s'\n", current_layout);
386
387         hLayoutUS = LoadKeyboardLayout("00000409", KLF_NOTELLSHELL);
388
389         if (!hLayoutUS) {
390                 //printf("Failed to load US keyboard layout. Using current.\n");
391                 hLayoutUS = GetKeyboardLayout(0);
392         }
393         LoadKeyboardLayout(current_layout, KLF_ACTIVATE);
394 #else
395 #if _WIN32_WCE >=420
396         TCHAR   current_layout[KL_NAMELENGTH];
397
398         GetKeyboardLayoutName(current_layout);
399         //printf("Initial Keyboard Layout Name: '%s'\n", current_layout);
400
401         hLayoutUS = LoadKeyboardLayout(L"00000409", 0);
402
403         if (!hLayoutUS) {
404                 //printf("Failed to load US keyboard layout. Using current.\n");
405                 hLayoutUS = GetKeyboardLayout(0);
406         }
407         LoadKeyboardLayout(current_layout, 0);
408 #endif // _WIN32_WCE >=420
409 #endif
410         /* Map the VK keysyms */
411         for ( i=0; i<SDL_arraysize(VK_keymap); ++i )
412                 VK_keymap[i] = SDLK_UNKNOWN;
413
414         VK_keymap[VK_BACK] = SDLK_BACKSPACE;
415         VK_keymap[VK_TAB] = SDLK_TAB;
416         VK_keymap[VK_CLEAR] = SDLK_CLEAR;
417         VK_keymap[VK_RETURN] = SDLK_RETURN;
418         VK_keymap[VK_PAUSE] = SDLK_PAUSE;
419         VK_keymap[VK_ESCAPE] = SDLK_ESCAPE;
420         VK_keymap[VK_SPACE] = SDLK_SPACE;
421         VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE;
422         VK_keymap[VK_COMMA] = SDLK_COMMA;
423         VK_keymap[VK_MINUS] = SDLK_MINUS;
424         VK_keymap[VK_PERIOD] = SDLK_PERIOD;
425         VK_keymap[VK_SLASH] = SDLK_SLASH;
426         VK_keymap[VK_0] = SDLK_0;
427         VK_keymap[VK_1] = SDLK_1;
428         VK_keymap[VK_2] = SDLK_2;
429         VK_keymap[VK_3] = SDLK_3;
430         VK_keymap[VK_4] = SDLK_4;
431         VK_keymap[VK_5] = SDLK_5;
432         VK_keymap[VK_6] = SDLK_6;
433         VK_keymap[VK_7] = SDLK_7;
434         VK_keymap[VK_8] = SDLK_8;
435         VK_keymap[VK_9] = SDLK_9;
436         VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON;
437         VK_keymap[VK_EQUALS] = SDLK_EQUALS;
438         VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET;
439         VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH;
440         VK_keymap[VK_OEM_102] = SDLK_LESS;
441         VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET;
442         VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE;
443         VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE;
444         VK_keymap[VK_A] = SDLK_a;
445         VK_keymap[VK_B] = SDLK_b;
446         VK_keymap[VK_C] = SDLK_c;
447         VK_keymap[VK_D] = SDLK_d;
448         VK_keymap[VK_E] = SDLK_e;
449         VK_keymap[VK_F] = SDLK_f;
450         VK_keymap[VK_G] = SDLK_g;
451         VK_keymap[VK_H] = SDLK_h;
452         VK_keymap[VK_I] = SDLK_i;
453         VK_keymap[VK_J] = SDLK_j;
454         VK_keymap[VK_K] = SDLK_k;
455         VK_keymap[VK_L] = SDLK_l;
456         VK_keymap[VK_M] = SDLK_m;
457         VK_keymap[VK_N] = SDLK_n;
458         VK_keymap[VK_O] = SDLK_o;
459         VK_keymap[VK_P] = SDLK_p;
460         VK_keymap[VK_Q] = SDLK_q;
461         VK_keymap[VK_R] = SDLK_r;
462         VK_keymap[VK_S] = SDLK_s;
463         VK_keymap[VK_T] = SDLK_t;
464         VK_keymap[VK_U] = SDLK_u;
465         VK_keymap[VK_V] = SDLK_v;
466         VK_keymap[VK_W] = SDLK_w;
467         VK_keymap[VK_X] = SDLK_x;
468         VK_keymap[VK_Y] = SDLK_y;
469         VK_keymap[VK_Z] = SDLK_z;
470         VK_keymap[VK_DELETE] = SDLK_DELETE;
471
472         VK_keymap[VK_NUMPAD0] = SDLK_KP0;
473         VK_keymap[VK_NUMPAD1] = SDLK_KP1;
474         VK_keymap[VK_NUMPAD2] = SDLK_KP2;
475         VK_keymap[VK_NUMPAD3] = SDLK_KP3;
476         VK_keymap[VK_NUMPAD4] = SDLK_KP4;
477         VK_keymap[VK_NUMPAD5] = SDLK_KP5;
478         VK_keymap[VK_NUMPAD6] = SDLK_KP6;
479         VK_keymap[VK_NUMPAD7] = SDLK_KP7;
480         VK_keymap[VK_NUMPAD8] = SDLK_KP8;
481         VK_keymap[VK_NUMPAD9] = SDLK_KP9;
482         VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD;
483         VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE;
484         VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY;
485         VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS;
486         VK_keymap[VK_ADD] = SDLK_KP_PLUS;
487
488         VK_keymap[VK_UP] = SDLK_UP;
489         VK_keymap[VK_DOWN] = SDLK_DOWN;
490         VK_keymap[VK_RIGHT] = SDLK_RIGHT;
491         VK_keymap[VK_LEFT] = SDLK_LEFT;
492         VK_keymap[VK_INSERT] = SDLK_INSERT;
493         VK_keymap[VK_HOME] = SDLK_HOME;
494         VK_keymap[VK_END] = SDLK_END;
495         VK_keymap[VK_PRIOR] = SDLK_PAGEUP;
496         VK_keymap[VK_NEXT] = SDLK_PAGEDOWN;
497
498         VK_keymap[VK_F1] = SDLK_F1;
499         VK_keymap[VK_F2] = SDLK_F2;
500         VK_keymap[VK_F3] = SDLK_F3;
501         VK_keymap[VK_F4] = SDLK_F4;
502         VK_keymap[VK_F5] = SDLK_F5;
503         VK_keymap[VK_F6] = SDLK_F6;
504         VK_keymap[VK_F7] = SDLK_F7;
505         VK_keymap[VK_F8] = SDLK_F8;
506         VK_keymap[VK_F9] = SDLK_F9;
507         VK_keymap[VK_F10] = SDLK_F10;
508         VK_keymap[VK_F11] = SDLK_F11;
509         VK_keymap[VK_F12] = SDLK_F12;
510         VK_keymap[VK_F13] = SDLK_F13;
511         VK_keymap[VK_F14] = SDLK_F14;
512         VK_keymap[VK_F15] = SDLK_F15;
513
514         VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK;
515         VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK;
516         VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK;
517         VK_keymap[VK_RSHIFT] = SDLK_RSHIFT;
518         VK_keymap[VK_LSHIFT] = SDLK_LSHIFT;
519         VK_keymap[VK_RCONTROL] = SDLK_RCTRL;
520         VK_keymap[VK_LCONTROL] = SDLK_LCTRL;
521         VK_keymap[VK_RMENU] = SDLK_RALT;
522         VK_keymap[VK_LMENU] = SDLK_LALT;
523         VK_keymap[VK_RWIN] = SDLK_RSUPER;
524         VK_keymap[VK_LWIN] = SDLK_LSUPER;
525
526         VK_keymap[VK_HELP] = SDLK_HELP;
527 #ifdef VK_PRINT
528         VK_keymap[VK_PRINT] = SDLK_PRINT;
529 #endif
530         VK_keymap[VK_SNAPSHOT] = SDLK_PRINT;
531         VK_keymap[VK_CANCEL] = SDLK_BREAK;
532         VK_keymap[VK_APPS] = SDLK_MENU;
533
534         Arrows_keymap[3] = 0x25;
535         Arrows_keymap[2] = 0x26;
536         Arrows_keymap[1] = 0x27;
537         Arrows_keymap[0] = 0x28;
538 }
539
540 #define EXTKEYPAD(keypad) ((scancode & 0x100)?(mvke):(keypad))
541
542 static int SDL_MapVirtualKey(int scancode, int vkey)
543 {
544 #ifndef _WIN32_WCE
545         int     mvke  = MapVirtualKeyEx(scancode & 0xFF, 1, hLayoutUS);
546 #else
547         int     mvke  = MapVirtualKey(scancode & 0xFF, 1);
548 #endif
549
550         switch(vkey) {
551                 /* These are always correct */
552                 case VK_DIVIDE:
553                 case VK_MULTIPLY:
554                 case VK_SUBTRACT:
555                 case VK_ADD:
556                 case VK_LWIN:
557                 case VK_RWIN:
558                 case VK_APPS:
559                 /* These are already handled */
560                 case VK_LCONTROL:
561                 case VK_RCONTROL:
562                 case VK_LSHIFT:
563                 case VK_RSHIFT:
564                 case VK_LMENU:
565                 case VK_RMENU:
566                 case VK_SNAPSHOT:
567                 case VK_PAUSE:
568                         return vkey;
569         }       
570         switch(mvke) {
571                 /* Distinguish between keypad and extended keys */
572                 case VK_INSERT: return EXTKEYPAD(VK_NUMPAD0);
573                 case VK_DELETE: return EXTKEYPAD(VK_DECIMAL);
574                 case VK_END:    return EXTKEYPAD(VK_NUMPAD1);
575                 case VK_DOWN:   return EXTKEYPAD(VK_NUMPAD2);
576                 case VK_NEXT:   return EXTKEYPAD(VK_NUMPAD3);
577                 case VK_LEFT:   return EXTKEYPAD(VK_NUMPAD4);
578                 case VK_CLEAR:  return EXTKEYPAD(VK_NUMPAD5);
579                 case VK_RIGHT:  return EXTKEYPAD(VK_NUMPAD6);
580                 case VK_HOME:   return EXTKEYPAD(VK_NUMPAD7);
581                 case VK_UP:     return EXTKEYPAD(VK_NUMPAD8);
582                 case VK_PRIOR:  return EXTKEYPAD(VK_NUMPAD9);
583         }
584         return mvke?mvke:vkey;
585 }
586
587 static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed)
588 {
589         /* Set the keysym information */
590         keysym->scancode = (unsigned char) scancode;
591         keysym->mod = KMOD_NONE;
592         keysym->unicode = 0;
593         
594         if ((vkey == VK_RETURN) && (scancode & 0x100)) {
595                 /* No VK_ code for the keypad enter key */
596                 keysym->sym = SDLK_KP_ENTER;
597         }
598         else {
599                 keysym->sym = VK_keymap[SDL_MapVirtualKey(scancode, vkey)];
600         }
601
602         if ( pressed && SDL_TranslateUNICODE ) {
603 #ifdef NO_GETKEYBOARDSTATE
604                 /* Uh oh, better hope the vkey is close enough.. */
605                 if((keysym->sym == vkey) || (vkey > 0x7f))
606                 keysym->unicode = vkey;
607 #else
608                 BYTE    keystate[256];
609                 Uint16  wchars[2];
610
611                 GetKeyboardState(keystate);
612                 /* Numlock isn't taken into account in ToUnicode,
613                  * so we handle it as a special case here */
614                 if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)
615                 {
616                         keysym->unicode = vkey - VK_NUMPAD0 + '0';
617                 }
618                 else if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0)
619                 {
620                         keysym->unicode = wchars[0];
621                 }
622 #endif /* NO_GETKEYBOARDSTATE */
623         }
624
625 #if 0
626         {
627                 HKL     hLayoutCurrent = GetKeyboardLayout(0);
628                 int     sc = scancode & 0xFF;
629
630                 printf("SYM:%d, VK:0x%02X, SC:0x%04X, US:(1:0x%02X, 3:0x%02X), "
631                         "Current:(1:0x%02X, 3:0x%02X)\n",
632                         keysym->sym, vkey, scancode,
633                         MapVirtualKeyEx(sc, 1, hLayoutUS),
634                         MapVirtualKeyEx(sc, 3, hLayoutUS),
635                         MapVirtualKeyEx(sc, 1, hLayoutCurrent),
636                         MapVirtualKeyEx(sc, 3, hLayoutCurrent)
637                 );
638         }
639 #endif
640         return(keysym);
641 }
642
643 int DIB_CreateWindow(_THIS)
644 {
645         char *windowid;
646
647         SDL_RegisterApp(NULL, 0, 0);
648
649         windowid = SDL_getenv("SDL_WINDOWID");
650         SDL_windowid = (windowid != NULL);
651         if ( SDL_windowid ) {
652 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
653                 /* wince 2.1 does not have strtol */
654                 wchar_t *windowid_t = SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t));
655                 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1, windowid_t, SDL_strlen(windowid) + 1);
656                 SDL_Window = (HWND)wcstol(windowid_t, NULL, 0);
657                 SDL_free(windowid_t);
658 #else
659                 SDL_Window = (HWND)SDL_strtoull(windowid, NULL, 0);
660 #endif
661                 if ( SDL_Window == NULL ) {
662                         SDL_SetError("Couldn't get user specified window");
663                         return(-1);
664                 }
665
666                 /* DJM: we want all event's for the user specified
667                         window to be handled by SDL.
668                  */
669                 userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);
670                 SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage);
671         } else {
672                 SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
673                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
674                         CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL);
675                 if ( SDL_Window == NULL ) {
676                         SDL_SetError("Couldn't create window");
677                         return(-1);
678                 }
679                 ShowWindow(SDL_Window, SW_HIDE);
680         }
681
682         /* JC 14 Mar 2006
683                 Flush the message loop or this can cause big problems later
684                 Especially if the user decides to use dialog boxes or assert()!
685         */
686         WIN_FlushMessageQueue();
687
688         return(0);
689 }
690
691 void DIB_DestroyWindow(_THIS)
692 {
693         if ( SDL_windowid ) {
694                 SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc);
695         } else {
696                 DestroyWindow(SDL_Window);
697         }
698         SDL_UnregisterApp();
699
700         /* JC 14 Mar 2006
701                 Flush the message loop or this can cause big problems later
702                 Especially if the user decides to use dialog boxes or assert()!
703         */
704         WIN_FlushMessageQueue();
705 }