Implemented ToUnicode() support on Windows 95/98/ME/NT/2000/XP
authorSam Lantinga <slouken@libsdl.org>
Thu, 19 Jan 2006 09:09:32 +0000
changeset 12537c7ddaf195bf
parent 1252 57be1c741b8b
child 1254 c2ee0f7fa711
Implemented ToUnicode() support on Windows 95/98/ME/NT/2000/XP
This is a collaborative effort between Alex Volkov and John Popplewell.
Thanks guys! (Fixes bug #39)
src/video/wincommon/SDL_lowvideo.h
src/video/wincommon/SDL_sysevents.c
src/video/windib/SDL_dibevents.c
src/video/windib/SDL_vkeys.h
src/video/windx5/SDL_dx5events.c
test/checkkeys.c
     1.1 --- a/src/video/wincommon/SDL_lowvideo.h	Thu Jan 19 08:53:12 2006 +0000
     1.2 +++ b/src/video/wincommon/SDL_lowvideo.h	Thu Jan 19 09:09:32 2006 +0000
     1.3 @@ -109,4 +109,9 @@
     1.4     GDL_CreateWindow as well */
     1.5  LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
     1.6  
     1.7 +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */
     1.8 +typedef int (WINAPI *ToUnicodeFN)(UINT, UINT, PBYTE, LPWSTR, int, UINT);
     1.9 +
    1.10 +extern ToUnicodeFN SDL_ToUnicode;
    1.11 +
    1.12  #endif /* SDL_lowvideo_h */
     2.1 --- a/src/video/wincommon/SDL_sysevents.c	Thu Jan 19 08:53:12 2006 +0000
     2.2 +++ b/src/video/wincommon/SDL_sysevents.c	Thu Jan 19 09:09:32 2006 +0000
     2.3 @@ -79,6 +79,15 @@
     2.4  void (*WIN_WinPAINT)(_THIS, HDC hdc);
     2.5  extern void DIB_SwapGamma(_THIS);
     2.6  
     2.7 +/* Variables and support functions for SDL_ToUnicode() */
     2.8 +static int codepage;
     2.9 +static int Is9xME();
    2.10 +static int GetCodePage();
    2.11 +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, BYTE *keystate, Uint16 *wchars, int wsize, UINT flags);
    2.12 +
    2.13 +ToUnicodeFN SDL_ToUnicode = ToUnicode9xME;
    2.14 +
    2.15 +
    2.16  #if defined(_WIN32_WCE)
    2.17  
    2.18  // dynamically load aygshell dll because we want SDL to work on HPC and be300
    2.19 @@ -622,6 +631,11 @@
    2.20  		}
    2.21  		return(0);
    2.22  
    2.23 +		case WM_INPUTLANGCHANGE: {
    2.24 +			codepage = GetCodePage();
    2.25 +		}
    2.26 +		return(TRUE);
    2.27 +
    2.28  		default: {
    2.29  			/* Special handling by the video driver */
    2.30  			if (HandleMessage) {
    2.31 @@ -728,6 +742,10 @@
    2.32  	/* Check for SDL_WINDOWID hack */
    2.33  	SDL_windowid = getenv("SDL_WINDOWID");
    2.34  
    2.35 +	/* Initialise variables for SDL_ToUnicode() */
    2.36 +	codepage = GetCodePage();
    2.37 +	SDL_ToUnicode = Is9xME() ? ToUnicode9xME : ToUnicode;
    2.38 +
    2.39  	app_registered = 1;
    2.40  	return(0);
    2.41  }
    2.42 @@ -751,3 +769,39 @@
    2.43  	app_registered = 0;
    2.44  }
    2.45  
    2.46 +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */
    2.47 +
    2.48 +static int Is9xME()
    2.49 +{
    2.50 +	OSVERSIONINFO   info;
    2.51 +
    2.52 +	memset(&info, 0, sizeof(info));
    2.53 +	info.dwOSVersionInfoSize = sizeof(info);
    2.54 +	if (!GetVersionEx(&info)) {
    2.55 +		return 0;
    2.56 +	}
    2.57 +	return (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
    2.58 +}
    2.59 +
    2.60 +static int GetCodePage()
    2.61 +{
    2.62 +	char	buff[8];
    2.63 +	int	lcid = MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT);
    2.64 +	int	cp = GetACP();
    2.65 +
    2.66 +	if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buff, sizeof(buff))) {
    2.67 +		cp = atoi(buff);
    2.68 +	}
    2.69 +	return cp;
    2.70 +}
    2.71 +
    2.72 +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, PBYTE keystate, LPWSTR wchars, int wsize, UINT flags)
    2.73 +{
    2.74 +	BYTE	chars[2];
    2.75 +
    2.76 +	if (ToAsciiEx(vkey, scancode, keystate, (WORD*)chars, 0, GetKeyboardLayout(0)) == 1) {
    2.77 +		return MultiByteToWideChar(codepage, 0, chars, 1, wchars, wsize);
    2.78 +	}
    2.79 +	return 0;
    2.80 +}
    2.81 +
     3.1 --- a/src/video/windib/SDL_dibevents.c	Thu Jan 19 08:53:12 2006 +0000
     3.2 +++ b/src/video/windib/SDL_dibevents.c	Thu Jan 19 09:09:32 2006 +0000
     3.3 @@ -281,6 +281,7 @@
     3.4  	VK_keymap[VK_EQUALS] = SDLK_EQUALS;
     3.5  	VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET;
     3.6  	VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH;
     3.7 +	VK_keymap[VK_OEM_102] = SDLK_LESS;
     3.8  	VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET;
     3.9  	VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE;
    3.10  	VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE;
    3.11 @@ -385,17 +386,18 @@
    3.12  	keysym->sym = VK_keymap[vkey];
    3.13  	keysym->mod = KMOD_NONE;
    3.14  	keysym->unicode = 0;
    3.15 -	if ( pressed && SDL_TranslateUNICODE ) { /* Someday use ToUnicode() */
    3.16 +	if ( pressed && SDL_TranslateUNICODE ) {
    3.17  #ifdef NO_GETKEYBOARDSTATE
    3.18  		/* Uh oh, better hope the vkey is close enough.. */
    3.19  		keysym->unicode = vkey;
    3.20  #else
    3.21 -		BYTE keystate[256];
    3.22 -		BYTE chars[2];
    3.23 +		BYTE	keystate[256];
    3.24 +		Uint16	wchars[2];
    3.25  
    3.26  		GetKeyboardState(keystate);
    3.27 -		if ( ToAscii(vkey,scancode,keystate,(WORD *)chars,0) == 1 ) {
    3.28 -			keysym->unicode = chars[0];
    3.29 +		if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1)
    3.30 +		{
    3.31 +			keysym->unicode = wchars[0];
    3.32  		}
    3.33  #endif /* NO_GETKEYBOARDSTATE */
    3.34  	}
     4.1 --- a/src/video/windib/SDL_vkeys.h	Thu Jan 19 08:53:12 2006 +0000
     4.2 +++ b/src/video/windib/SDL_vkeys.h	Thu Jan 19 09:09:32 2006 +0000
     4.3 @@ -77,3 +77,4 @@
     4.4  #define VK_RBRACKET	0xDD
     4.5  #define VK_APOSTROPHE	0xDE
     4.6  #define VK_BACKTICK	0xDF
     4.7 +#define VK_OEM_102	0xE2
     5.1 --- a/src/video/windx5/SDL_dx5events.c	Thu Jan 19 08:53:12 2006 +0000
     5.2 +++ b/src/video/windx5/SDL_dx5events.c	Thu Jan 19 09:09:32 2006 +0000
     5.3 @@ -824,11 +824,11 @@
     5.4  	keysym->sym = DIK_keymap[scancode];
     5.5  	keysym->mod = KMOD_NONE;
     5.6  	keysym->unicode = 0;
     5.7 -	if ( pressed && SDL_TranslateUNICODE ) { /* Someday use ToUnicode() */
     5.8 +	if ( pressed && SDL_TranslateUNICODE ) {
     5.9  		UINT vkey;
    5.10  #ifndef NO_GETKEYBOARDSTATE
    5.11 -		BYTE keystate[256];
    5.12 -		BYTE chars[2];
    5.13 +		BYTE	keystate[256];
    5.14 +		Uint16	wchars[2];
    5.15  #endif
    5.16  
    5.17  		vkey = MapVirtualKey(scancode, 1);
    5.18 @@ -837,10 +837,11 @@
    5.19  		keysym->unicode = vkey;
    5.20  #else
    5.21  		GetKeyboardState(keystate);
    5.22 -		if ( ToAscii(vkey,scancode,keystate,(WORD *)chars,0) == 1 ) {
    5.23 -			keysym->unicode = chars[0];
    5.24 +		if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1)
    5.25 +		{
    5.26 +			keysym->unicode = wchars[0];
    5.27  		}
    5.28 -#endif
    5.29 +#endif /* NO_GETKEYBOARDSTATE */
    5.30  	}
    5.31  	return(keysym);
    5.32  }
     6.1 --- a/test/checkkeys.c	Thu Jan 19 08:53:12 2006 +0000
     6.2 +++ b/test/checkkeys.c	Thu Jan 19 09:09:32 2006 +0000
     6.3 @@ -73,6 +73,8 @@
     6.4  			/* This is a Latin-1 program, so only show 8-bits */
     6.5  			if ( !(sym->unicode & 0xFF00) )
     6.6  				printf(" (%c)", sym->unicode);
     6.7 +			else
     6.8 +				printf(" (0x%X)", sym->unicode);
     6.9  #endif
    6.10  		}
    6.11  	}