src/video/windib/SDL_dibevents.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 13 Apr 2009 08:42:09 +0000
branchSDL-1.2
changeset 4170 092c0bc69155
parent 4167 a6f635e5eaa6
child 4179 d7294b7c732d
permissions -rw-r--r--
Fixed bug #618

Description From Tim Angus 2008-08-30 12:23:56 (-) [reply]

As we all know SDL 1.2 doesn't handle dead keys well since one key press
potentially equals two (or more) characters. For example, on many layouts,
keying <backquote>,<space> results in <no character>,<backquote><space>. Since
the unicode member of the SDL_keysym struct only has room for one character,
only one can be returned.

On Linux, the first character is returned. On Windows however, unless the exact
number of characters generated by the keypress is 1, nothing is returned. The
following patch addresses this inconsistency.

Updated patch which includes a further fix to the handling of the numpad when
numlock is on. This further fix is courtesy Amanieu d'Antras.
     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 #endif 
    92 
    93 
    94 /* The main Win32 event handler */
    95 LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    96 {
    97 	extern int posted;
    98 
    99 	switch (msg) {
   100 		case WM_SYSKEYDOWN:
   101 		case WM_KEYDOWN: {
   102 			SDL_keysym keysym;
   103 
   104 #ifdef SDL_VIDEO_DRIVER_GAPI
   105 			if(this->hidden->gapiInfo)
   106 			{
   107 				// Drop GAPI artefacts
   108 				if (wParam == 0x84 || wParam == 0x5B)
   109 					return 0;
   110 
   111 				wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform);
   112 			}
   113 #endif 
   114 			/* Ignore repeated keys */
   115 			if ( lParam&REPEATED_KEYMASK ) {
   116 				return(0);
   117 			}
   118 			switch (wParam) {
   119 				case VK_CONTROL:
   120 					if ( lParam&EXTENDED_KEYMASK )
   121 						wParam = VK_RCONTROL;
   122 					else
   123 						wParam = VK_LCONTROL;
   124 					break;
   125 				case VK_SHIFT:
   126 					/* EXTENDED trick doesn't work here */
   127 					{
   128 					Uint8 *state = SDL_GetKeyState(NULL);
   129 					if (state[SDLK_LSHIFT] == SDL_RELEASED && (GetKeyState(VK_LSHIFT) & 0x8000)) {
   130 						wParam = VK_LSHIFT;
   131 					} else if (state[SDLK_RSHIFT] == SDL_RELEASED && (GetKeyState(VK_RSHIFT) & 0x8000)) {
   132 						wParam = VK_RSHIFT;
   133 					} else {
   134 						/* Win9x */
   135 						int sc = HIWORD(lParam) & 0xFF;
   136 
   137 						if (sc == 0x2A)
   138 							wParam = VK_LSHIFT;
   139 						else
   140 						if (sc == 0x36)
   141 							wParam = VK_RSHIFT;
   142 						else
   143 							wParam = VK_LSHIFT;
   144 					}
   145 					}
   146 					break;
   147 				case VK_MENU:
   148 					if ( lParam&EXTENDED_KEYMASK )
   149 						wParam = VK_RMENU;
   150 					else
   151 						wParam = VK_LMENU;
   152 					break;
   153 			}
   154 #ifdef NO_GETKEYBOARDSTATE
   155 			/* this is the workaround for the missing ToAscii() and ToUnicode() in CE (not necessary at KEYUP!) */
   156 			if ( SDL_TranslateUNICODE ) {
   157 				MSG m;
   158 
   159 				m.hwnd = hwnd;
   160 				m.message = msg;
   161 				m.wParam = wParam;
   162 				m.lParam = lParam;
   163 				m.time = 0;
   164 				if ( TranslateMessage(&m) && PeekMessage(&m, hwnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) {
   165 					GetMessage(&m, hwnd, 0, WM_USER);
   166 			    		wParam = m.wParam;
   167 				}
   168 			}
   169 #endif /* NO_GETKEYBOARDSTATE */
   170 			posted = SDL_PrivateKeyboard(SDL_PRESSED,
   171 				TranslateKey(wParam,HIWORD(lParam),&keysym,1));
   172 		}
   173 		return(0);
   174 
   175 		case WM_SYSKEYUP:
   176 		case WM_KEYUP: {
   177 			SDL_keysym keysym;
   178 
   179 #ifdef SDL_VIDEO_DRIVER_GAPI
   180 			if(this->hidden->gapiInfo)
   181 			{
   182 				// Drop GAPI artifacts
   183 				if (wParam == 0x84 || wParam == 0x5B)
   184 					return 0;
   185 	
   186 				wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform);
   187 			}
   188 #endif
   189 
   190 			switch (wParam) {
   191 				case VK_CONTROL:
   192 					if ( lParam&EXTENDED_KEYMASK )
   193 						wParam = VK_RCONTROL;
   194 					else
   195 						wParam = VK_LCONTROL;
   196 					break;
   197 				case VK_SHIFT:
   198 					/* EXTENDED trick doesn't work here */
   199 					{
   200 					Uint8 *state = SDL_GetKeyState(NULL);
   201 					if (state[SDLK_LSHIFT] == SDL_PRESSED && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
   202 						wParam = VK_LSHIFT;
   203 					} else if (state[SDLK_RSHIFT] == SDL_PRESSED && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
   204 						wParam = VK_RSHIFT;
   205 					} else {
   206 						/* Win9x */
   207 						int sc = HIWORD(lParam) & 0xFF;
   208 
   209 						if (sc == 0x2A)
   210 							wParam = VK_LSHIFT;
   211 						else
   212 						if (sc == 0x36)
   213 							wParam = VK_RSHIFT;
   214 						else
   215 							wParam = VK_LSHIFT;
   216 					}
   217 					}
   218 					break;
   219 				case VK_MENU:
   220 					if ( lParam&EXTENDED_KEYMASK )
   221 						wParam = VK_RMENU;
   222 					else
   223 						wParam = VK_LMENU;
   224 					break;
   225 			}
   226 			/* Windows only reports keyup for print screen */
   227 			if ( wParam == VK_SNAPSHOT && SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED ) {
   228 				posted = SDL_PrivateKeyboard(SDL_PRESSED,
   229 					TranslateKey(wParam,HIWORD(lParam),&keysym,1));
   230 			}
   231 			posted = SDL_PrivateKeyboard(SDL_RELEASED,
   232 				TranslateKey(wParam,HIWORD(lParam),&keysym,0));
   233 		}
   234 		return(0);
   235 #if defined(SC_SCREENSAVE) && defined(SC_MONITORPOWER)
   236 		case WM_SYSCOMMAND: {
   237 			const DWORD val = (DWORD) (wParam & 0xFFF0);
   238 			if ((val == SC_SCREENSAVE) || (val == SC_MONITORPOWER)) {
   239 				if (this->hidden->dibInfo && !allow_screensaver) {
   240 					/* Note that this doesn't stop anything on Vista
   241 					   if the screensaver has a password. */
   242 					return(0);
   243 				}
   244 			}
   245 		}
   246 		/* Fall through to default processing */
   247 #endif /* SC_SCREENSAVE && SC_MONITORPOWER */
   248 
   249 		default: {
   250 			/* Only post the event if we're watching for it */
   251 			if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
   252 			        SDL_SysWMmsg wmmsg;
   253 
   254 				SDL_VERSION(&wmmsg.version);
   255 				wmmsg.hwnd = hwnd;
   256 				wmmsg.msg = msg;
   257 				wmmsg.wParam = wParam;
   258 				wmmsg.lParam = lParam;
   259 				posted = SDL_PrivateSysWMEvent(&wmmsg);
   260 
   261 			/* DJM: If the user isn't watching for private
   262 				messages in her SDL event loop, then pass it
   263 				along to any win32 specific window proc.
   264 			 */
   265 			} else if (userWindowProc) {
   266 				return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam);
   267 			}
   268 		}
   269 		break;
   270 	}
   271 	return(DefWindowProc(hwnd, msg, wParam, lParam));
   272 }
   273 
   274 static void DIB_GenerateMouseMotionEvent(void)
   275 {
   276 	extern int mouse_relative;
   277 	extern int posted;
   278 
   279 	POINT mouse;
   280 	GetCursorPos( &mouse );
   281 
   282 	if ( mouse_relative ) {
   283 		POINT center;
   284 		center.x = (SDL_VideoSurface->w/2);
   285 		center.y = (SDL_VideoSurface->h/2);
   286 		ClientToScreen(SDL_Window, &center);
   287 
   288 		mouse.x -= (Sint16)center.x;
   289 		mouse.y -= (Sint16)center.y;
   290 		if ( mouse.x || mouse.y ) {
   291 			SetCursorPos(center.x, center.y);
   292 			posted = SDL_PrivateMouseMotion(0, 1, mouse.x, mouse.y);
   293 		}
   294 	} else if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) {
   295 		ScreenToClient(SDL_Window, &mouse);
   296 #ifdef _WIN32_WCE
   297 		if (SDL_VideoSurface)
   298 			GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &mouse.x, &mouse.y);
   299 #endif
   300 		posted = SDL_PrivateMouseMotion(0, 0, mouse.x, mouse.y);
   301 	}
   302 }
   303 
   304 void DIB_PumpEvents(_THIS)
   305 {
   306 	MSG msg;
   307 
   308 	while ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
   309 		if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
   310 			DispatchMessage(&msg);
   311 		}
   312 	}
   313 
   314 	if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   315 		DIB_GenerateMouseMotionEvent( );
   316 	}
   317 }
   318 
   319 static HKL hLayoutUS = NULL;
   320 
   321 void DIB_InitOSKeymap(_THIS)
   322 {
   323 	int	i;
   324 #ifndef _WIN32_WCE
   325 	char	current_layout[KL_NAMELENGTH];
   326 
   327 	GetKeyboardLayoutName(current_layout);
   328 	//printf("Initial Keyboard Layout Name: '%s'\n", current_layout);
   329 
   330 	hLayoutUS = LoadKeyboardLayout("00000409", KLF_NOTELLSHELL);
   331 
   332 	if (!hLayoutUS) {
   333 		//printf("Failed to load US keyboard layout. Using current.\n");
   334 		hLayoutUS = GetKeyboardLayout(0);
   335 	}
   336 	LoadKeyboardLayout(current_layout, KLF_ACTIVATE);
   337 #else
   338 #if _WIN32_WCE >=420
   339 	TCHAR	current_layout[KL_NAMELENGTH];
   340 
   341 	GetKeyboardLayoutName(current_layout);
   342 	//printf("Initial Keyboard Layout Name: '%s'\n", current_layout);
   343 
   344 	hLayoutUS = LoadKeyboardLayout(L"00000409", 0);
   345 
   346 	if (!hLayoutUS) {
   347 		//printf("Failed to load US keyboard layout. Using current.\n");
   348 		hLayoutUS = GetKeyboardLayout(0);
   349 	}
   350 	LoadKeyboardLayout(current_layout, 0);
   351 #endif // _WIN32_WCE >=420
   352 #endif
   353 	/* Map the VK keysyms */
   354 	for ( i=0; i<SDL_arraysize(VK_keymap); ++i )
   355 		VK_keymap[i] = SDLK_UNKNOWN;
   356 
   357 	VK_keymap[VK_BACK] = SDLK_BACKSPACE;
   358 	VK_keymap[VK_TAB] = SDLK_TAB;
   359 	VK_keymap[VK_CLEAR] = SDLK_CLEAR;
   360 	VK_keymap[VK_RETURN] = SDLK_RETURN;
   361 	VK_keymap[VK_PAUSE] = SDLK_PAUSE;
   362 	VK_keymap[VK_ESCAPE] = SDLK_ESCAPE;
   363 	VK_keymap[VK_SPACE] = SDLK_SPACE;
   364 	VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE;
   365 	VK_keymap[VK_COMMA] = SDLK_COMMA;
   366 	VK_keymap[VK_MINUS] = SDLK_MINUS;
   367 	VK_keymap[VK_PERIOD] = SDLK_PERIOD;
   368 	VK_keymap[VK_SLASH] = SDLK_SLASH;
   369 	VK_keymap[VK_0] = SDLK_0;
   370 	VK_keymap[VK_1] = SDLK_1;
   371 	VK_keymap[VK_2] = SDLK_2;
   372 	VK_keymap[VK_3] = SDLK_3;
   373 	VK_keymap[VK_4] = SDLK_4;
   374 	VK_keymap[VK_5] = SDLK_5;
   375 	VK_keymap[VK_6] = SDLK_6;
   376 	VK_keymap[VK_7] = SDLK_7;
   377 	VK_keymap[VK_8] = SDLK_8;
   378 	VK_keymap[VK_9] = SDLK_9;
   379 	VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON;
   380 	VK_keymap[VK_EQUALS] = SDLK_EQUALS;
   381 	VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET;
   382 	VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH;
   383 	VK_keymap[VK_OEM_102] = SDLK_LESS;
   384 	VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET;
   385 	VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE;
   386 	VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE;
   387 	VK_keymap[VK_A] = SDLK_a;
   388 	VK_keymap[VK_B] = SDLK_b;
   389 	VK_keymap[VK_C] = SDLK_c;
   390 	VK_keymap[VK_D] = SDLK_d;
   391 	VK_keymap[VK_E] = SDLK_e;
   392 	VK_keymap[VK_F] = SDLK_f;
   393 	VK_keymap[VK_G] = SDLK_g;
   394 	VK_keymap[VK_H] = SDLK_h;
   395 	VK_keymap[VK_I] = SDLK_i;
   396 	VK_keymap[VK_J] = SDLK_j;
   397 	VK_keymap[VK_K] = SDLK_k;
   398 	VK_keymap[VK_L] = SDLK_l;
   399 	VK_keymap[VK_M] = SDLK_m;
   400 	VK_keymap[VK_N] = SDLK_n;
   401 	VK_keymap[VK_O] = SDLK_o;
   402 	VK_keymap[VK_P] = SDLK_p;
   403 	VK_keymap[VK_Q] = SDLK_q;
   404 	VK_keymap[VK_R] = SDLK_r;
   405 	VK_keymap[VK_S] = SDLK_s;
   406 	VK_keymap[VK_T] = SDLK_t;
   407 	VK_keymap[VK_U] = SDLK_u;
   408 	VK_keymap[VK_V] = SDLK_v;
   409 	VK_keymap[VK_W] = SDLK_w;
   410 	VK_keymap[VK_X] = SDLK_x;
   411 	VK_keymap[VK_Y] = SDLK_y;
   412 	VK_keymap[VK_Z] = SDLK_z;
   413 	VK_keymap[VK_DELETE] = SDLK_DELETE;
   414 
   415 	VK_keymap[VK_NUMPAD0] = SDLK_KP0;
   416 	VK_keymap[VK_NUMPAD1] = SDLK_KP1;
   417 	VK_keymap[VK_NUMPAD2] = SDLK_KP2;
   418 	VK_keymap[VK_NUMPAD3] = SDLK_KP3;
   419 	VK_keymap[VK_NUMPAD4] = SDLK_KP4;
   420 	VK_keymap[VK_NUMPAD5] = SDLK_KP5;
   421 	VK_keymap[VK_NUMPAD6] = SDLK_KP6;
   422 	VK_keymap[VK_NUMPAD7] = SDLK_KP7;
   423 	VK_keymap[VK_NUMPAD8] = SDLK_KP8;
   424 	VK_keymap[VK_NUMPAD9] = SDLK_KP9;
   425 	VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD;
   426 	VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE;
   427 	VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY;
   428 	VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS;
   429 	VK_keymap[VK_ADD] = SDLK_KP_PLUS;
   430 
   431 	VK_keymap[VK_UP] = SDLK_UP;
   432 	VK_keymap[VK_DOWN] = SDLK_DOWN;
   433 	VK_keymap[VK_RIGHT] = SDLK_RIGHT;
   434 	VK_keymap[VK_LEFT] = SDLK_LEFT;
   435 	VK_keymap[VK_INSERT] = SDLK_INSERT;
   436 	VK_keymap[VK_HOME] = SDLK_HOME;
   437 	VK_keymap[VK_END] = SDLK_END;
   438 	VK_keymap[VK_PRIOR] = SDLK_PAGEUP;
   439 	VK_keymap[VK_NEXT] = SDLK_PAGEDOWN;
   440 
   441 	VK_keymap[VK_F1] = SDLK_F1;
   442 	VK_keymap[VK_F2] = SDLK_F2;
   443 	VK_keymap[VK_F3] = SDLK_F3;
   444 	VK_keymap[VK_F4] = SDLK_F4;
   445 	VK_keymap[VK_F5] = SDLK_F5;
   446 	VK_keymap[VK_F6] = SDLK_F6;
   447 	VK_keymap[VK_F7] = SDLK_F7;
   448 	VK_keymap[VK_F8] = SDLK_F8;
   449 	VK_keymap[VK_F9] = SDLK_F9;
   450 	VK_keymap[VK_F10] = SDLK_F10;
   451 	VK_keymap[VK_F11] = SDLK_F11;
   452 	VK_keymap[VK_F12] = SDLK_F12;
   453 	VK_keymap[VK_F13] = SDLK_F13;
   454 	VK_keymap[VK_F14] = SDLK_F14;
   455 	VK_keymap[VK_F15] = SDLK_F15;
   456 
   457 	VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK;
   458 	VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK;
   459 	VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK;
   460 	VK_keymap[VK_RSHIFT] = SDLK_RSHIFT;
   461 	VK_keymap[VK_LSHIFT] = SDLK_LSHIFT;
   462 	VK_keymap[VK_RCONTROL] = SDLK_RCTRL;
   463 	VK_keymap[VK_LCONTROL] = SDLK_LCTRL;
   464 	VK_keymap[VK_RMENU] = SDLK_RALT;
   465 	VK_keymap[VK_LMENU] = SDLK_LALT;
   466 	VK_keymap[VK_RWIN] = SDLK_RSUPER;
   467 	VK_keymap[VK_LWIN] = SDLK_LSUPER;
   468 
   469 	VK_keymap[VK_HELP] = SDLK_HELP;
   470 #ifdef VK_PRINT
   471 	VK_keymap[VK_PRINT] = SDLK_PRINT;
   472 #endif
   473 	VK_keymap[VK_SNAPSHOT] = SDLK_PRINT;
   474 	VK_keymap[VK_CANCEL] = SDLK_BREAK;
   475 	VK_keymap[VK_APPS] = SDLK_MENU;
   476 
   477 	Arrows_keymap[3] = 0x25;
   478 	Arrows_keymap[2] = 0x26;
   479 	Arrows_keymap[1] = 0x27;
   480 	Arrows_keymap[0] = 0x28;
   481 }
   482 
   483 #define EXTKEYPAD(keypad) ((scancode & 0x100)?(mvke):(keypad))
   484 
   485 static int SDL_MapVirtualKey(int scancode, int vkey)
   486 {
   487 #ifndef _WIN32_WCE
   488 	int	mvke  = MapVirtualKeyEx(scancode & 0xFF, 1, hLayoutUS);
   489 #else
   490 	int	mvke  = MapVirtualKey(scancode & 0xFF, 1);
   491 #endif
   492 
   493 	switch(vkey) {
   494 		/* These are always correct */
   495 		case VK_DIVIDE:
   496 		case VK_MULTIPLY:
   497 		case VK_SUBTRACT:
   498 		case VK_ADD:
   499 		case VK_LWIN:
   500 		case VK_RWIN:
   501 		case VK_APPS:
   502 		/* These are already handled */
   503 		case VK_LCONTROL:
   504 		case VK_RCONTROL:
   505 		case VK_LSHIFT:
   506 		case VK_RSHIFT:
   507 		case VK_LMENU:
   508 		case VK_RMENU:
   509 		case VK_SNAPSHOT:
   510 		case VK_PAUSE:
   511 			return vkey;
   512 	}	
   513 	switch(mvke) {
   514 		/* Distinguish between keypad and extended keys */
   515 		case VK_INSERT: return EXTKEYPAD(VK_NUMPAD0);
   516 		case VK_DELETE: return EXTKEYPAD(VK_DECIMAL);
   517 		case VK_END:    return EXTKEYPAD(VK_NUMPAD1);
   518 		case VK_DOWN:   return EXTKEYPAD(VK_NUMPAD2);
   519 		case VK_NEXT:   return EXTKEYPAD(VK_NUMPAD3);
   520 		case VK_LEFT:   return EXTKEYPAD(VK_NUMPAD4);
   521 		case VK_CLEAR:  return EXTKEYPAD(VK_NUMPAD5);
   522 		case VK_RIGHT:  return EXTKEYPAD(VK_NUMPAD6);
   523 		case VK_HOME:   return EXTKEYPAD(VK_NUMPAD7);
   524 		case VK_UP:     return EXTKEYPAD(VK_NUMPAD8);
   525 		case VK_PRIOR:  return EXTKEYPAD(VK_NUMPAD9);
   526 	}
   527 	return mvke?mvke:vkey;
   528 }
   529 
   530 static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed)
   531 {
   532 	/* Set the keysym information */
   533 	keysym->scancode = (unsigned char) scancode;
   534 	keysym->mod = KMOD_NONE;
   535 	keysym->unicode = 0;
   536 	
   537 	if ((vkey == VK_RETURN) && (scancode & 0x100)) {
   538 		/* No VK_ code for the keypad enter key */
   539 		keysym->sym = SDLK_KP_ENTER;
   540 	}
   541 	else {
   542 		keysym->sym = VK_keymap[SDL_MapVirtualKey(scancode, vkey)];
   543 	}
   544 
   545 	if ( pressed && SDL_TranslateUNICODE ) {
   546 #ifdef NO_GETKEYBOARDSTATE
   547 		/* Uh oh, better hope the vkey is close enough.. */
   548 		if((keysym->sym == vkey) || (vkey > 0x7f))
   549 		keysym->unicode = vkey;
   550 #else
   551 		BYTE	keystate[256];
   552 		Uint16	wchars[2];
   553 
   554 		GetKeyboardState(keystate);
   555 		/* Numlock isn't taken into account in ToUnicode,
   556 		 * so we handle it as a special case here */
   557 		if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)
   558 		{
   559 			keysym->unicode = vkey - VK_NUMPAD0 + '0';
   560 		}
   561 		else if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0)
   562 		{
   563 			keysym->unicode = wchars[0];
   564 		}
   565 #endif /* NO_GETKEYBOARDSTATE */
   566 	}
   567 
   568 #if 0
   569 	{
   570 		HKL     hLayoutCurrent = GetKeyboardLayout(0);
   571 		int     sc = scancode & 0xFF;
   572 
   573 		printf("SYM:%d, VK:0x%02X, SC:0x%04X, US:(1:0x%02X, 3:0x%02X), "
   574 			"Current:(1:0x%02X, 3:0x%02X)\n",
   575 			keysym->sym, vkey, scancode,
   576 			MapVirtualKeyEx(sc, 1, hLayoutUS),
   577 			MapVirtualKeyEx(sc, 3, hLayoutUS),
   578 			MapVirtualKeyEx(sc, 1, hLayoutCurrent),
   579 			MapVirtualKeyEx(sc, 3, hLayoutCurrent)
   580 		);
   581 	}
   582 #endif
   583 	return(keysym);
   584 }
   585 
   586 int DIB_CreateWindow(_THIS)
   587 {
   588 	char *windowid = SDL_getenv("SDL_WINDOWID");
   589 
   590 	SDL_RegisterApp(NULL, 0, 0);
   591 
   592 	SDL_windowid = (windowid != NULL);
   593 	if ( SDL_windowid ) {
   594 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
   595 		/* wince 2.1 does not have strtol */
   596 		wchar_t *windowid_t = SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t));
   597 		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1, windowid_t, SDL_strlen(windowid) + 1);
   598 		SDL_Window = (HWND)wcstol(windowid_t, NULL, 0);
   599 		SDL_free(windowid_t);
   600 #else
   601 		SDL_Window = (HWND)SDL_strtoull(windowid, NULL, 0);
   602 #endif
   603 		if ( SDL_Window == NULL ) {
   604 			SDL_SetError("Couldn't get user specified window");
   605 			return(-1);
   606 		}
   607 
   608 		/* DJM: we want all event's for the user specified
   609 			window to be handled by SDL.
   610 		 */
   611 		userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);
   612 		SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage);
   613 	} else {
   614 		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
   615                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
   616                         CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL);
   617 		if ( SDL_Window == NULL ) {
   618 			SDL_SetError("Couldn't create window");
   619 			return(-1);
   620 		}
   621 		ShowWindow(SDL_Window, SW_HIDE);
   622 	}
   623 
   624 	/* JC 14 Mar 2006
   625 		Flush the message loop or this can cause big problems later
   626 		Especially if the user decides to use dialog boxes or assert()!
   627 	*/
   628 	WIN_FlushMessageQueue();
   629 
   630 	return(0);
   631 }
   632 
   633 void DIB_DestroyWindow(_THIS)
   634 {
   635 	if ( SDL_windowid ) {
   636 		SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc);
   637 	} else {
   638 		DestroyWindow(SDL_Window);
   639 	}
   640 	SDL_UnregisterApp();
   641 
   642 	/* JC 14 Mar 2006
   643 		Flush the message loop or this can cause big problems later
   644 		Especially if the user decides to use dialog boxes or assert()!
   645 	*/
   646 	WIN_FlushMessageQueue();
   647 }