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@xxxxxxxxxxxxxxx> 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;