Add preliminary support for keyboard layout APIs

Dmitry Timoshkov dmitry at baikal.ru
Sun Nov 9 06:25:38 CST 2003


Hello,

note to Shachar:

this implementation doesn't really work due to "merged" keyboard
layouts we have. I.e. since we have Israelian keyboard layout
with both english and hebrew characters, after the MappingNotify
event we're still using the same keyboard layout with same LCID
identifier, and applications receive WM_INPUTLANGCHANGE(REQUEST)
with the same, not changed keyboard layout identifier.

You can make it work though, using an ugly workaround:

setxkbmap us
wine WINWORD.EXE

type something in Word, then in another xterm and run
setxkbmap ru

switch back to Word and continue typing. Word will see the change
and kindly reflect that in the status bar.

In order to experiment with Hebrew you need to create a pure Hebrew
keyboard layout in Wine, and use 'setxkbmap il'.

Perhaps a way to go is to handle X layout switch notification event
and figure out what layout is really used from the merged mapping
we currently have. So far I have no an idea how to do that.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Add preliminary support for keyboard layout APIs.

This patch must be applied after the VkKeyScan fix.

diff -u cvs/hq/wine/dlls/ttydrv/ttydrv.spec wine/dlls/ttydrv/ttydrv.spec
--- cvs/hq/wine/dlls/ttydrv/ttydrv.spec	Tue Nov  5 14:52:35 2002
+++ wine/dlls/ttydrv/ttydrv.spec	Sat Nov  8 14:40:59 2003
@@ -35,10 +35,10 @@
 
 # USER driver
 
-@ cdecl VkKeyScan(long) TTYDRV_VkKeyScan
-@ cdecl MapVirtualKey(long long) TTYDRV_MapVirtualKey
-@ cdecl GetKeyNameText(long str long) TTYDRV_GetKeyNameText
-@ cdecl ToUnicode(long long ptr ptr long long) TTYDRV_ToUnicode
+@ cdecl VkKeyScanEx(long long) TTYDRV_VkKeyScanEx
+@ cdecl MapVirtualKeyEx(long long long) TTYDRV_MapVirtualKeyEx
+@ cdecl GetKeyNameText(long ptr long) TTYDRV_GetKeyNameText
+@ cdecl ToUnicodeEx(long long ptr ptr long long long) TTYDRV_ToUnicodeEx
 @ cdecl Beep() TTYDRV_Beep
 @ cdecl SetCursor(ptr) TTYDRV_SetCursor
 @ cdecl GetScreenSaveActive() TTYDRV_GetScreenSaveActive
diff -u cvs/hq/wine/dlls/ttydrv/user.c wine/dlls/ttydrv/user.c
--- cvs/hq/wine/dlls/ttydrv/user.c	Tue Sep  9 15:36:26 2003
+++ wine/dlls/ttydrv/user.c	Sat Nov  8 14:39:36 2003
@@ -34,17 +34,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
 struct tagCURSORICONINFO;
 
 /***********************************************************************
- *		VkKeyScan (TTYDRV.@)
+ *		VkKeyScanEx (TTYDRV.@)
  */
-WORD TTYDRV_VkKeyScan(CHAR cChar)
+SHORT TTYDRV_VkKeyScanEx(WCHAR cChar, HKL hkl)
 {
   return 0;
 }
 
 /***********************************************************************
- *		MapVirtualKey (TTYDRV.@)
+ *		MapVirtualKeyEx (TTYDRV.@)
  */
-UINT16 TTYDRV_MapVirtualKey(UINT16 wCode, UINT16 wMapType)
+UINT TTYDRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
 {
   return 0;
 }
@@ -52,7 +52,7 @@ UINT16 TTYDRV_MapVirtualKey(UINT16 wCode
 /***********************************************************************
  *		GetKeyNameText (TTYDRV.@)
  */
-INT16 TTYDRV_GetKeyNameText( LONG lParam, LPSTR lpBuffer, INT16 nSize )
+INT TTYDRV_GetKeyNameText( LONG lParam, LPWSTR lpBuffer, INT nSize )
 {
   if(lpBuffer && nSize)
     {
@@ -62,10 +62,10 @@ INT16 TTYDRV_GetKeyNameText( LONG lParam
 }
 
 /***********************************************************************
- *		ToUnicode (TTYDRV.@)
+ *		ToUnicodeEx (TTYDRV.@)
  */
-INT TTYDRV_ToUnicode( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
-		      LPWSTR pwszBuff, int cchBuff, UINT flags )
+INT TTYDRV_ToUnicodeEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+		      LPWSTR pwszBuff, int cchBuff, UINT flags, HKL hkl )
 {
   return 0;
 }
diff -u cvs/hq/wine/dlls/user/user32.spec wine/dlls/user/user32.spec
--- cvs/hq/wine/dlls/user/user32.spec	Fri Oct 10 22:05:33 2003
+++ wine/dlls/user/user32.spec	Sun Nov  9 13:49:01 2003
@@ -591,7 +591,7 @@
 @ stdcall UnhookWindowsHook(long ptr)
 @ stdcall UnhookWindowsHookEx(long)
 @ stdcall UnionRect(ptr ptr ptr)
-@ stub UnloadKeyboardLayout
+@ stdcall UnloadKeyboardLayout(long)
 @ stub UnlockWindowStation
 @ stdcall UnpackDDElParam(long long ptr ptr)
 @ stdcall UnregisterClassA(str long)
diff -u cvs/hq/wine/dlls/user/user_main.c wine/dlls/user/user_main.c
--- cvs/hq/wine/dlls/user/user_main.c	Fri Oct 10 22:05:33 2003
+++ wine/dlls/user/user_main.c	Sun Nov  9 13:46:19 2003
@@ -76,10 +76,16 @@ static BOOL load_driver(void)
     }
 
     GET_USER_FUNC(InitKeyboard);
-    GET_USER_FUNC(VkKeyScan);
-    GET_USER_FUNC(MapVirtualKey);
+    GET_USER_FUNC(VkKeyScanEx);
+    GET_USER_FUNC(MapVirtualKeyEx);
     GET_USER_FUNC(GetKeyNameText);
-    GET_USER_FUNC(ToUnicode);
+    GET_USER_FUNC(ToUnicodeEx);
+    GET_USER_FUNC(GetKeyboardLayoutList);
+    GET_USER_FUNC(GetKeyboardLayout);
+    GET_USER_FUNC(GetKeyboardLayoutName);
+    GET_USER_FUNC(LoadKeyboardLayout);
+    GET_USER_FUNC(ActivateKeyboardLayout);
+    GET_USER_FUNC(UnloadKeyboardLayout);
     GET_USER_FUNC(Beep);
     GET_USER_FUNC(InitMouse);
     GET_USER_FUNC(SetCursor);
diff -u cvs/hq/wine/dlls/x11drv/Makefile.in wine/dlls/x11drv/Makefile.in
--- cvs/hq/wine/dlls/x11drv/Makefile.in	Mon Oct 20 13:17:19 2003
+++ wine/dlls/x11drv/Makefile.in	Sun Nov  9 14:37:45 2003
@@ -6,7 +6,7 @@ VPATH     = @srcdir@
 MODULE    = x11drv.dll
 IMPORTS   = user32 gdi32 advapi32 kernel32 ntdll
 EXTRAINCL = @X_CFLAGS@
-EXTRALIBS = @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
+EXTRALIBS = $(LIBUNICODE) @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
 
 C_SRCS = \
 	$(TOPOBJDIR)/graphics/x11drv/bitblt.c \
diff -u cvs/hq/wine/dlls/x11drv/keyboard.c wine/dlls/x11drv/keyboard.c
--- cvs/hq/wine/dlls/x11drv/keyboard.c	Sun Nov  9 19:56:14 2003
+++ wine/dlls/x11drv/keyboard.c	Sun Nov  9 19:54:10 2003
@@ -44,10 +44,12 @@
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
+#include "winuser.h"
 #include "wine/winuser16.h"
 #include "winnls.h"
 #include "win.h"
 #include "x11drv.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
@@ -115,6 +117,16 @@ static const WORD main_key_vkey_qwerty[M
    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
 };
 
+static const WORD main_key_vkey_qwerty_v2[MAIN_LEN] =
+{
+/* NOTE: this layout must concur with the scan codes layout above */
+   VK_OEM_5,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_PLUS,VK_OEM_4,
+   VK_Q,VK_W,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_6,VK_OEM_1,
+   VK_A,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_OEM_3,VK_OEM_7,VK_OEM_2,
+   VK_Z,VK_X,VK_C,VK_V,VK_B,VK_N,VK_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_MINUS,
+   VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
+};
+
 static const WORD main_key_vkey_qwertz[MAIN_LEN] =
 {
 /* NOTE: this layout must concur with the scan codes layout above */
@@ -738,68 +750,70 @@ static const char main_key_vnc[MAIN_LEN]
 
 /*** Layout table. Add your keyboard mappings to this list */
 static const struct {
+    LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
+                 in the appropriate dlls/kernel/nls/.nls file */
     const char *comment;
     const char (*key)[MAIN_LEN][4];
     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
 } main_key_tab[]={
- {"United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
- {"British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
- {"Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
- {"Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
- {"Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
- {"Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
- {"United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
- {"Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
+ {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
+ {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
+ {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
+ {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
+ {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
+ {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
+ {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
+ {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041e, "Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
 
- {NULL, NULL, NULL, NULL} /* sentinel */
+ {0, NULL, NULL, NULL, NULL} /* sentinel */
 };
 static unsigned kbd_layout=0; /* index into above table of layouts */
 
@@ -1487,26 +1501,148 @@ void X11DRV_InitKeyboard( BYTE *key_stat
 
 
 /***********************************************************************
+ *		GetKeyboardLayoutList (X11DRV.@)
+ */
+UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
+{
+    INT i;
+
+    TRACE("%d, %p\n", size, hkl);
+
+    if (!size)
+    {
+        size = 4096; /* hope we will never have that many */
+        hkl = NULL;
+    }
+
+    for (i = 0; main_key_tab[i].comment && (i < size); i++)
+    {
+        if (hkl)
+            hkl[i] = (HKL)main_key_tab[i].lcid;
+    }
+    return i;
+}
+
+
+/***********************************************************************
+ *		GetKeyboardLayout (X11DRV.@)
+ */
+HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
+{
+    DWORD layout;
+    LANGID langid;
+
+    if (dwThreadid)
+        FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid);
+
+    layout = main_key_tab[kbd_layout].lcid;
+    /* 
+     * Microsoft Office expects this value to be something specific
+     * for Japanese and Korean Windows with an IME the value is 0xe001
+     * We should probibly check to see if an IME exists and if so then
+     * set this word properly.
+     */
+    langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
+    if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
+        layout |= 0xe001 << 16; /* FIXME */
+
+    return (HKL)layout;
+}
+
+
+/***********************************************************************
+ *		GetKeyboardLayoutName (X11DRV.@)
+ */
+BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
+{
+    static const WCHAR formatW[] = {'%','0','8','l','x',0};
+    DWORD layout;
+    LANGID langid;
+
+    layout = main_key_tab[kbd_layout].lcid;
+    /* see comment above */
+    langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
+    if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
+        layout |= 0xe001 << 16; /* FIXME */
+
+    sprintfW(name, formatW, layout);
+    TRACE("returning %s\n", debugstr_w(name));
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *		LoadKeyboardLayout (X11DRV.@)
+ */
+HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
+{
+    FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+
+/***********************************************************************
+ *		UnloadKeyboardLayout (X11DRV.@)
+ */
+BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
+{
+    FIXME("%p: stub!\n", hkl);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *		ActivateKeyboardLayout (X11DRV.@)
+ */
+HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
+{
+    FIXME("%p, %04x: stub!\n", hkl, flags);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+
+/***********************************************************************
  *           X11DRV_MappingNotify
  */
 void X11DRV_MappingNotify( XMappingEvent *event )
 {
+    HWND hwnd;
+
     TSXRefreshKeyboardMapping(event);
     X11DRV_InitKeyboard( pKeyStateTable );
+
+    hwnd = GetFocus();
+    if (!hwnd) hwnd = GetActiveWindow();
+    PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
+                 0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
 }
 
 
 /***********************************************************************
- *		VkKeyScan (X11DRV.@)
+ *		VkKeyScanEx (X11DRV.@)
+ *
+ * Note: Windows ignores HKL parameter and uses current active layout instead
  */
-WORD X11DRV_VkKeyScan(CHAR cChar)
+SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
 {
     Display *display = thread_display();
     KeyCode keycode;
     KeySym keysym;
     int i, index;
+    CHAR cChar;
     SHORT ret;
 
+    if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
+    {
+        WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
+        return -1;
+    }
+
+    TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
+
     /* char->keysym (same for ANSI chars) */
     keysym = (unsigned char)cChar; /* (!) cChar is signed */
     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
@@ -1565,15 +1701,18 @@ WORD X11DRV_VkKeyScan(CHAR cChar)
 }
 
 /***********************************************************************
- *		MapVirtualKey (X11DRV.@)
+ *		MapVirtualKeyEx (X11DRV.@)
  */
-UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
+UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
 {
     Display *display = thread_display();
 
 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
 
-	TRACE("wCode=0x%x wMapType=%d ...\n", wCode,wMapType);
+    TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
+    if (hkl != X11DRV_GetKeyboardLayout(0))
+        FIXME("keyboard layout %p is not supported\n", hkl);
+
 	switch(wMapType) {
 		case 0:	{ /* vkey-code to scan-code */
 			/* let's do vkey -> keycode -> scan */
@@ -1667,7 +1806,7 @@ UINT X11DRV_MapVirtualKey(UINT wCode, UI
 /***********************************************************************
  *		GetKeyNameText (X11DRV.@)
  */
-INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
+INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
 {
   int vkey, ansi, scanCode;
   KeyCode keyc;
@@ -1679,7 +1818,7 @@ INT X11DRV_GetKeyNameText(LONG lParam, L
   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
 
   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
-  vkey = X11DRV_MapVirtualKey(scanCode, 1);
+  vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
 
   /*  handle "don't care" bit (0x02000000) */
   if (!(lParam & 0x02000000)) {
@@ -1701,7 +1840,7 @@ INT X11DRV_GetKeyNameText(LONG lParam, L
     }
   }
 
-  ansi = X11DRV_MapVirtualKey(vkey, 2);
+  ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
 
   /* first get the name of the "regular" keys which is the Upper case
@@ -1715,7 +1854,7 @@ INT X11DRV_GetKeyNameText(LONG lParam, L
       {
         if ((nSize >= 2) && lpBuffer)
 	{
-        *lpBuffer = toupper((char)ansi);
+          *lpBuffer = toupperW((WCHAR)ansi);
           *(lpBuffer+1) = 0;
           return 1;
         }
@@ -1747,7 +1886,8 @@ INT X11DRV_GetKeyNameText(LONG lParam, L
             scanCode, keyc, (int)keys, name);
       if (lpBuffer && nSize && name)
       {
-          lstrcpynA(lpBuffer, name, nSize);
+          MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
+          lpBuffer[nSize - 1] = 0;
           return 1;
       }
   }
@@ -1839,7 +1979,7 @@ static char KEYBOARD_MapDeadKeysym(KeySy
 }
 
 /***********************************************************************
- *		ToUnicode (X11DRV.@)
+ *		ToUnicodeEx (X11DRV.@)
  *
  * The ToUnicode function translates the specified virtual-key code and keyboard
  * state to the corresponding Windows character or characters.
@@ -1856,8 +1996,8 @@ static char KEYBOARD_MapDeadKeysym(KeySy
  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
  *
  */
-INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
-		     LPWSTR bufW, int bufW_size, UINT flags)
+INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+		     LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
 {
     Display *display = thread_display();
     XKeyEvent e;
@@ -1873,6 +2013,9 @@ INT X11DRV_ToUnicode(UINT virtKey, UINT 
         TRACE("Key UP, doing nothing\n" );
         return 0;
     }
+
+    if (hkl != X11DRV_GetKeyboardLayout(0))
+        FIXME("keyboard layout %p is not supported\n", hkl);
 
     e.display = display;
     e.keycode = 0;
diff -u cvs/hq/wine/dlls/x11drv/x11drv.spec wine/dlls/x11drv/x11drv.spec
--- cvs/hq/wine/dlls/x11drv/x11drv.spec	Sun Aug 10 21:33:59 2003
+++ wine/dlls/x11drv/x11drv.spec	Sun Nov  9 18:48:40 2003
@@ -61,10 +61,16 @@
 # USER driver
 
 @ cdecl InitKeyboard(ptr) X11DRV_InitKeyboard
-@ cdecl VkKeyScan(long) X11DRV_VkKeyScan
-@ cdecl MapVirtualKey(long long) X11DRV_MapVirtualKey
-@ cdecl GetKeyNameText(long str long) X11DRV_GetKeyNameText
-@ cdecl ToUnicode(long long ptr ptr long long) X11DRV_ToUnicode
+@ cdecl VkKeyScanEx(long long) X11DRV_VkKeyScanEx
+@ cdecl MapVirtualKeyEx(long long long) X11DRV_MapVirtualKeyEx
+@ cdecl GetKeyNameText(long ptr long) X11DRV_GetKeyNameText
+@ cdecl ToUnicodeEx(long long ptr ptr long long long) X11DRV_ToUnicodeEx
+@ cdecl GetKeyboardLayoutList(long ptr) X11DRV_GetKeyboardLayoutList
+@ cdecl GetKeyboardLayout(long) X11DRV_GetKeyboardLayout
+@ cdecl GetKeyboardLayoutName(ptr) X11DRV_GetKeyboardLayoutName
+@ cdecl LoadKeyboardLayout(wstr long) X11DRV_LoadKeyboardLayout
+@ cdecl ActivateKeyboardLayout(long long) X11DRV_ActivateKeyboardLayout
+@ cdecl UnloadKeyboardLayout(long) X11DRV_UnloadKeyboardLayout
 @ cdecl Beep() X11DRV_Beep
 @ cdecl InitMouse(ptr) X11DRV_InitMouse
 @ cdecl SetCursor(ptr) X11DRV_SetCursor
diff -u cvs/hq/wine/include/user.h wine/include/user.h
--- cvs/hq/wine/include/user.h	Tue Sep  9 15:36:34 2003
+++ wine/include/user.h	Sun Nov  9 14:49:37 2003
@@ -72,10 +72,16 @@ enum wine_internal_message
 typedef struct tagUSER_DRIVER {
     /* keyboard functions */
     void   (*pInitKeyboard)(LPBYTE);
-    WORD   (*pVkKeyScan)(CHAR);
-    UINT   (*pMapVirtualKey)(UINT,UINT);
-    INT    (*pGetKeyNameText)(LONG,LPSTR,INT);
-    INT    (*pToUnicode)(UINT, UINT, LPBYTE, LPWSTR, int, UINT);
+    SHORT  (*pVkKeyScanEx)(WCHAR, HKL);
+    UINT   (*pMapVirtualKeyEx)(UINT, UINT, HKL);
+    INT    (*pGetKeyNameText)(LONG, LPWSTR, INT);
+    INT    (*pToUnicodeEx)(UINT, UINT, LPBYTE, LPWSTR, int, UINT, HKL);
+    UINT   (*pGetKeyboardLayoutList)(INT, HKL *);
+    HKL    (*pGetKeyboardLayout)(DWORD);
+    BOOL   (*pGetKeyboardLayoutName)(LPWSTR);
+    HKL    (*pLoadKeyboardLayout)(LPCWSTR, UINT);
+    HKL    (*pActivateKeyboardLayout)(HKL, UINT);
+    BOOL   (*pUnloadKeyboardLayout)(HKL);
     void   (*pBeep)(void);
     /* mouse functions */
     void   (*pInitMouse)(LPBYTE);
diff -u cvs/hq/wine/include/winuser.h wine/include/winuser.h
--- cvs/hq/wine/include/winuser.h	Sat Oct  4 15:30:12 2003
+++ wine/include/winuser.h	Sun Nov  9 18:46:58 2003
@@ -3714,7 +3714,7 @@ BOOL      WINAPI EnumThreadWindows(DWORD
 BOOL      WINAPI ExitWindowsEx(UINT,DWORD);
 BOOL      WINAPI GetIconInfo(HICON,PICONINFO);
 HKL       WINAPI GetKeyboardLayout(DWORD);
-INT       WINAPI GetKeyboardLayoutList(INT,HKL *);
+UINT      WINAPI GetKeyboardLayoutList(INT,HKL *);
 BOOL      WINAPI GetComboBoxInfo(HWND,PCOMBOBOXINFO);
 DWORD     WINAPI GetMenuContextHelpId(HMENU);
 UINT      WINAPI GetMenuDefaultItem(HMENU,UINT,UINT);
@@ -3767,9 +3767,11 @@ HWINEVENTHOOK WINAPI SetWinEventHook(DWO
 WORD        WINAPI TileWindows (HWND, UINT, const LPRECT,
                                 UINT, const HWND *);
 INT         WINAPI ToUnicode(UINT,UINT,PBYTE,LPWSTR,int,UINT);
+INT         WINAPI ToUnicodeEx(UINT,UINT,LPBYTE,LPWSTR,int,UINT,HKL);
 BOOL      WINAPI TrackPopupMenuEx(HMENU,UINT,INT,INT,HWND,
                                     LPTPMPARAMS);
 BOOL        WINAPI UnhookWinEvent(HWINEVENTHOOK);
+BOOL        WINAPI UnloadKeyboardLayout(HKL);
 BOOL        WINAPI UnregisterDeviceNotification(HDEVNOTIFY);
 BOOL        WINAPI UnregisterHotKey(HWND,INT);
 DWORD       WINAPI WaitForInputIdle(HANDLE,DWORD);
@@ -4077,8 +4079,8 @@ INT         WINAPI GetKeyboardType(INT);
 INT         WINAPI GetKeyNameTextA(LONG,LPSTR,INT);
 INT         WINAPI GetKeyNameTextW(LONG,LPWSTR,INT);
 #define     GetKeyNameText WINELIB_NAME_AW(GetKeyNameText)
-INT       WINAPI GetKeyboardLayoutNameA(LPSTR);
-INT       WINAPI GetKeyboardLayoutNameW(LPWSTR);
+BOOL        WINAPI GetKeyboardLayoutNameA(LPSTR);
+BOOL        WINAPI GetKeyboardLayoutNameW(LPWSTR);
 #define     GetKeyboardLayoutName WINELIB_NAME_AW(GetKeyboardLayoutName)
 SHORT       WINAPI GetKeyState(INT);
 HWND      WINAPI GetLastActivePopup(HWND);
@@ -4399,8 +4401,8 @@ BOOL        WINAPI UpdateWindow(HWND);
 UINT        WINAPI UserRealizePalette(HDC);
 BOOL        WINAPI ValidateRect(HWND,const RECT*);
 BOOL        WINAPI ValidateRgn(HWND,HRGN);
-WORD        WINAPI VkKeyScanA(CHAR);
-WORD        WINAPI VkKeyScanW(WCHAR);
+SHORT       WINAPI VkKeyScanA(CHAR);
+SHORT       WINAPI VkKeyScanW(WCHAR);
 #define     VkKeyScan WINELIB_NAME_AW(VkKeyScan)
 WORD        WINAPI VkKeyScanExA(CHAR, HKL);
 WORD        WINAPI VkKeyScanExW(WCHAR, HKL);
diff -u cvs/hq/wine/windows/defwnd.c wine/windows/defwnd.c
--- cvs/hq/wine/windows/defwnd.c	Thu Sep 18 10:44:38 2003
+++ wine/windows/defwnd.c	Sun Nov  9 18:28:20 2003
@@ -859,6 +859,14 @@ LRESULT WINAPI DefWindowProcA( HWND hwnd
 	}
 	break;
 
+    case WM_INPUTLANGCHANGEREQUEST:
+        /* notify about the switch only if it's really our current layout */
+        if ((HKL)lParam == GetKeyboardLayout(0))
+            result = SendMessageA( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
+        else
+            result = 0;
+        break;
+
     default:
         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
         break;
@@ -969,6 +977,14 @@ LRESULT WINAPI DefWindowProcW(
 		result = DEFWND_ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
 	}
 	break;
+
+    case WM_INPUTLANGCHANGEREQUEST:
+        /* notify about the switch only if it's really our current layout */
+        if ((HKL)lParam == GetKeyboardLayout(0))
+            result = SendMessageW( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
+        else
+            result = 0;
+        break;
 
     default:
         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
diff -u cvs/hq/wine/windows/input.c wine/windows/input.c
--- cvs/hq/wine/windows/input.c	Thu Oct 30 14:47:36 2003
+++ wine/windows/input.c	Sun Nov  9 18:53:44 2003
@@ -645,17 +645,22 @@ BOOL16 WINAPI IsUserIdle16(void)
  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
  */
-WORD WINAPI VkKeyScanA(CHAR cChar)
+SHORT WINAPI VkKeyScanA(CHAR cChar)
 {
-    return USER_Driver.pVkKeyScan( cChar );
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return VkKeyScanW(wChar);
 }
 
 /******************************************************************************
  *		VkKeyScanW (USER32.@)
  */
-WORD WINAPI VkKeyScanW(WCHAR cChar)
+SHORT WINAPI VkKeyScanW(WCHAR cChar)
 {
-	return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
+    return VkKeyScanExW(cChar, GetKeyboardLayout(0));
 }
 
 /**********************************************************************
@@ -663,8 +668,12 @@ WORD WINAPI VkKeyScanW(WCHAR cChar)
  */
 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
 {
-    /* FIXME: complete workaround this is */
-    return VkKeyScanA(cChar);
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return VkKeyScanExW(wChar, dwhkl);
 }
 
 /******************************************************************************
@@ -672,8 +681,9 @@ WORD WINAPI VkKeyScanExA(CHAR cChar, HKL
  */
 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
 {
-    /* FIXME: complete workaround this is */
-    return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
+    if (USER_Driver.pVkKeyScanEx)
+        return USER_Driver.pVkKeyScanEx(cChar, dwhkl);
+    return -1;
 }
 
 /******************************************************************************
@@ -701,7 +711,7 @@ INT WINAPI GetKeyboardType(INT nTypeFlag
  */
 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
 {
-    return USER_Driver.pMapVirtualKey( code, maptype );
+    return MapVirtualKeyExA( code, maptype, GetKeyboardLayout(0) );
 }
 
 /******************************************************************************
@@ -709,7 +719,7 @@ UINT WINAPI MapVirtualKeyA(UINT code, UI
  */
 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
 {
-    return MapVirtualKeyA(code,maptype);
+    return MapVirtualKeyExW(code, maptype, GetKeyboardLayout(0));
 }
 
 /******************************************************************************
@@ -717,9 +727,7 @@ UINT WINAPI MapVirtualKeyW(UINT code, UI
  */
 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
 {
-    if (hkl)
-    	FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
-    return MapVirtualKeyA(code,maptype);
+    return MapVirtualKeyExW(code, maptype, hkl);
 }
 
 /******************************************************************************
@@ -727,9 +735,11 @@ UINT WINAPI MapVirtualKeyExA(UINT code, 
  */
 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
 {
-    if (hkl)
-    	FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
-    return MapVirtualKeyA(code,maptype);
+    TRACE_(keyboard)("(%d, %d, %p)\n", code, maptype, hkl);
+
+    if (USER_Driver.pMapVirtualKeyEx)
+        return USER_Driver.pMapVirtualKeyEx(code, maptype, hkl);
+    return 0;
 }
 
 /****************************************************************************
@@ -751,37 +761,37 @@ INT16 WINAPI GetKeyboardLayoutName16(LPS
 /***********************************************************************
  *		GetKeyboardLayout (USER32.@)
  *
- * FIXME: - device handle for keyboard layout defaulted to
+ *        - device handle for keyboard layout defaulted to
  *          the language id. This is the way Windows default works.
  *        - the thread identifier (dwLayout) is also ignored.
  */
 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
 {
-        UINT layout;
-        layout = GetSystemDefaultLCID(); /* FIXME */
-        layout |= (layout<<16);          /* FIXME */
-        TRACE_(keyboard)("returning %08x\n",layout);
-        return (HKL)layout;
+    if (USER_Driver.pGetKeyboardLayout)
+        return USER_Driver.pGetKeyboardLayout(dwLayout);
+    return 0;
 }
 
 /****************************************************************************
  *		GetKeyboardLayoutNameA (USER32.@)
  */
-INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
+BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID)
 {
-        sprintf(pwszKLID, "%p",GetKeyboardLayout(0));
-        return 1;
+    WCHAR buf[KL_NAMELENGTH];
+
+    if (GetKeyboardLayoutNameW(buf))
+        return WideCharToMultiByte( CP_ACP, 0, buf, -1, pszKLID, KL_NAMELENGTH, NULL, NULL ) != 0;
+    return FALSE;
 }
 
 /****************************************************************************
  *		GetKeyboardLayoutNameW (USER32.@)
  */
-INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
+BOOL WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
 {
-        char buf[KL_NAMELENGTH];
-	int res = GetKeyboardLayoutNameA(buf);
-        MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
-	return res;
+    if (USER_Driver.pGetKeyboardLayoutName)
+        return USER_Driver.pGetKeyboardLayoutName(pwszKLID);
+    return FALSE;
 }
 
 /****************************************************************************
@@ -789,7 +799,18 @@ INT WINAPI GetKeyboardLayoutNameW(LPWSTR
  */
 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
 {
-    return USER_Driver.pGetKeyNameText( lParam, lpBuffer, nSize );
+    WCHAR buf[256];
+    INT ret;
+
+    if (!GetKeyNameTextW(lParam, buf, 256))
+        return 0;
+    ret = WideCharToMultiByte(CP_ACP, 0, buf, -1, lpBuffer, nSize, NULL, NULL);
+    if (!ret && nSize)
+    {
+        ret = nSize - 1;
+        lpBuffer[ret] = 0;
+    }
+    return ret;
 }
 
 /****************************************************************************
@@ -797,15 +818,9 @@ INT WINAPI GetKeyNameTextA(LONG lParam, 
  */
 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
 {
-	int res;
-	LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
-	if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
-	res = GetKeyNameTextA(lParam,buf,nSize);
-
-        if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
-            lpBuffer[nSize-1] = 0;
-	HeapFree( GetProcessHeap(), 0, buf );
-	return res;
+    if (USER_Driver.pGetKeyNameText)
+        return USER_Driver.pGetKeyNameText( lParam, lpBuffer, nSize );
+    return 0;
 }
 
 /****************************************************************************
@@ -814,7 +829,7 @@ INT WINAPI GetKeyNameTextW(LONG lParam, 
 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
 		     LPWSTR lpwStr, int size, UINT flags)
 {
-    return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
+    return ToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, GetKeyboardLayout(0));
 }
 
 /****************************************************************************
@@ -823,24 +838,18 @@ INT WINAPI ToUnicode(UINT virtKey, UINT 
 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
 		       LPWSTR lpwStr, int size, UINT flags, HKL hkl)
 {
-    /* FIXME: need true implementation */
-    return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
+    if (USER_Driver.pToUnicodeEx)
+        return USER_Driver.pToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, hkl);
+    return 0;
 }
 
 /****************************************************************************
  *		ToAscii (USER32.@)
  */
-INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
-                        LPWORD lpChar,UINT flags )
+INT WINAPI ToAscii( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+                    LPWORD lpChar, UINT flags )
 {
-    WCHAR uni_chars[2];
-    INT ret, n_ret;
-
-    ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
-    if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
-    else n_ret = ret;
-    WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
-    return ret;
+    return ToAsciiEx(virtKey, scanCode, lpKeyState, lpChar, flags, GetKeyboardLayout(0));
 }
 
 /****************************************************************************
@@ -849,19 +858,25 @@ INT WINAPI ToAscii( UINT virtKey,UINT sc
 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
                       LPWORD lpChar, UINT flags, HKL dwhkl )
 {
-    /* FIXME: need true implementation */
-    return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
+    WCHAR uni_chars[2];
+    INT ret, n_ret;
+
+    ret = ToUnicodeEx(virtKey, scanCode, lpKeyState, uni_chars, 2, flags, dwhkl);
+    if (ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
+    else n_ret = ret;
+    WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
+    return ret;
 }
 
 /**********************************************************************
  *		ActivateKeyboardLayout (USER32.@)
- *
- * Call ignored. WINE supports only system default keyboard layout.
  */
 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
 {
     TRACE_(keyboard)("(%p, %d)\n", hLayout, flags);
-    ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
+
+    if (USER_Driver.pActivateKeyboardLayout)
+        return USER_Driver.pActivateKeyboardLayout(hLayout, flags);
     return 0;
 }
 
@@ -869,21 +884,16 @@ HKL WINAPI ActivateKeyboardLayout(HKL hL
 /***********************************************************************
  *		GetKeyboardLayoutList (USER32.@)
  *
- * FIXME: Supports only the system default language and layout and
- *          returns only 1 value.
- *
  * Return number of values available if either input parm is
  *  0, per MS documentation.
- *
  */
-INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
+UINT WINAPI GetKeyboardLayoutList(INT nBuff, HKL *layouts)
 {
-        TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
-        if (!nBuff || !layouts)
-            return 1;
-	if (layouts)
-		layouts[0] = GetKeyboardLayout(0);
-	return 1;
+    TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
+
+    if (USER_Driver.pGetKeyboardLayoutList)
+        return USER_Driver.pGetKeyboardLayoutList(nBuff, layouts);
+    return 0;
 }
 
 
@@ -905,13 +915,14 @@ BOOL WINAPI UnregisterHotKey(HWND hwnd,I
 
 /***********************************************************************
  *		LoadKeyboardLayoutW (USER32.@)
- * Call ignored. WINE supports only system default keyboard layout.
  */
 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
 {
     TRACE_(keyboard)("(%s, %d)\n", debugstr_w(pwszKLID), Flags);
-    ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
-  return 0;
+
+    if (USER_Driver.pLoadKeyboardLayout)
+        return USER_Driver.pLoadKeyboardLayout(pwszKLID, Flags);
+    return 0;
 }
 
 /***********************************************************************
@@ -930,6 +941,18 @@ HKL WINAPI LoadKeyboardLayoutA(LPCSTR pw
     return ret;
 }
 
+
+/***********************************************************************
+ *		UnloadKeyboardLayout (USER32.@)
+ */
+BOOL WINAPI UnloadKeyboardLayout(HKL hkl)
+{
+    TRACE_(keyboard)("(%p)\n", hkl);
+
+    if (USER_Driver.pUnloadKeyboardLayout)
+        return USER_Driver.pUnloadKeyboardLayout(hkl);
+    return 0;
+}
 
 typedef struct __TRACKINGLIST {
     TRACKMOUSEEVENT tme;






More information about the wine-patches mailing list