src/video/windib/SDL_dibevents.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 May 2009 12:40:16 +0000
branchSDL-1.2
changeset 4179 d7294b7c732d
parent 4170 092c0bc69155
child 4219 0a7481888fd1
permissions -rw-r--r--
Date: Fri, 24 Apr 2009 17:47:07 +0200
From: Stefan Klug
Subject: Re: [SDL] SVN doesn't compile for wince

the patch applied for Revision 4483 was seemingly not checked for side
effects.
It broke the WinCE build.
The attached patch should fix these problems. I'm not using SDL 1.2 on
CE anymore, and therefore haven't tested the patch... but at least it
compiles ;-)

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