[PATCH v2 1/3] user32: Move ToUnicodeEx from wineandroid.drv to user32.

Rémi Bernon rbernon at codeweavers.com
Tue Apr 27 04:58:08 CDT 2021


As a default implementation for en_US keyboard layout, calling the
driver implementation next so that it can override the result.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

v2: * Use the english keyboard layout for the default impl, let the
      driver override the result if they can.

    * Only copy default buffer to user buffer in nulldrv, to leave user
      buffer untouched for drivers. ToUnicodeEx is not re-entrant when
      dealing with dead keys (although I don't think Wine uses that).

    * Use lstrcpynW instead of wcscpy.

    * Don't call debugstr_wn if len is < 0.

    * Drop controversial (Un)LoadKeyboardLayoutW patch for now.

Supersedes: 204512, 204513, 204518, 204519

 dlls/user32/driver.c                      | 11 ++-
 dlls/user32/input.c                       | 80 ++++++++++++++++++-
 dlls/user32/user_private.h                |  2 +-
 dlls/wineandroid.drv/keyboard.c           | 94 -----------------------
 dlls/wineandroid.drv/wineandroid.drv.spec |  1 -
 dlls/winemac.drv/keyboard.c               |  3 +-
 dlls/winemac.drv/winemac.drv.spec         |  2 +-
 dlls/winex11.drv/keyboard.c               |  3 +-
 dlls/winex11.drv/winex11.drv.spec         |  2 +-
 9 files changed, 90 insertions(+), 108 deletions(-)

diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 7ac77141696..c385ce0599c 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -284,9 +284,11 @@ static BOOL CDECL nulldrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
 }
 
 static INT CDECL nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
-                                      int size, UINT flags, HKL layout )
+                                      int size, UINT flags, HKL layout,
+                                      const WCHAR *default_buf, INT default_len )
 {
-    return 0;
+    lstrcpynW( str, default_buf, size );
+    return default_len;
 }
 
 static BOOL CDECL nulldrv_UnloadKeyboardLayout( HKL layout )
@@ -592,9 +594,10 @@ static BOOL CDECL loaderdrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
 }
 
 static INT CDECL loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
-                                  int size, UINT flags, HKL layout )
+                                        int size, UINT flags, HKL layout,
+                                        const WCHAR *default_buf, INT default_len )
 {
-    return load_driver()->pToUnicodeEx( virt, scan, state, str, size, flags, layout );
+    return load_driver()->pToUnicodeEx( virt, scan, state, str, size, flags, layout, default_buf, default_len );
 }
 
 static BOOL CDECL loaderdrv_UnloadKeyboardLayout( HKL layout )
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 805bfe3e9de..51a08d0786b 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -877,11 +877,83 @@ INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
 /****************************************************************************
  *		ToUnicodeEx (USER32.@)
  */
-INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
-		       LPWSTR lpwStr, int size, UINT flags, HKL hkl)
+INT WINAPI ToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
+                        WCHAR *str, int size, UINT flags, HKL layout )
 {
-    if (!lpKeyState) return 0;
-    return USER_Driver->pToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, hkl);
+    BOOL shift, ctrl, numlock;
+    WCHAR buffer[2];
+    INT len;
+
+    TRACE_(keyboard)( "virt %u, scan %u, state %p, str %p, size %d, flags %x, layout %p.\n",
+                      virt, scan, state, str, size, flags, layout );
+
+    if (!state) return 0;
+
+    shift = state[VK_SHIFT] & 0x80;
+    ctrl = state[VK_CONTROL] & 0x80;
+    numlock = state[VK_NUMLOCK] & 0x01;
+
+    /* FIXME: English keyboard layout specific */
+
+    if (scan & 0x8000) buffer[0] = 0; /* key up */
+    else if (!ctrl)
+    {
+        switch (virt)
+        {
+        case VK_BACK:       buffer[0] = '\b'; break;
+        case VK_OEM_1:      buffer[0] = shift ? ':' : ';'; break;
+        case VK_OEM_2:      buffer[0] = shift ? '?' : '/'; break;
+        case VK_OEM_3:      buffer[0] = shift ? '~' : '`'; break;
+        case VK_OEM_4:      buffer[0] = shift ? '{' : '['; break;
+        case VK_OEM_5:      buffer[0] = shift ? '|' : '\\'; break;
+        case VK_OEM_6:      buffer[0] = shift ? '}' : ']'; break;
+        case VK_OEM_7:      buffer[0] = shift ? '"' : '\''; break;
+        case VK_OEM_COMMA:  buffer[0] = shift ? '<' : ','; break;
+        case VK_OEM_MINUS:  buffer[0] = shift ? '_' : '-'; break;
+        case VK_OEM_PERIOD: buffer[0] = shift ? '>' : '.'; break;
+        case VK_OEM_PLUS:   buffer[0] = shift ? '+' : '='; break;
+        case VK_RETURN:     buffer[0] = '\r'; break;
+        case VK_SPACE:      buffer[0] = ' '; break;
+        case VK_TAB:        buffer[0] = '\t'; break;
+        case VK_MULTIPLY:   buffer[0] = '*'; break;
+        case VK_ADD:        buffer[0] = '+'; break;
+        case VK_SUBTRACT:   buffer[0] = '-'; break;
+        case VK_DIVIDE:     buffer[0] = '/'; break;
+        default:
+            if (virt >= '0' && virt <= '9')
+                buffer[0] = shift ? ")!@#$%^&*("[virt - '0'] : virt;
+            else if (virt >= 'A' && virt <= 'Z')
+                buffer[0] = shift || (state[VK_CAPITAL] & 0x01) ? virt : virt + 'a' - 'A';
+            else if (virt >= VK_NUMPAD0 && virt <= VK_NUMPAD9 && numlock && !shift)
+                buffer[0] = '0' + virt - VK_NUMPAD0;
+            else if (virt == VK_DECIMAL && numlock && !shift)
+                buffer[0] = '.';
+            else
+                buffer[0] = 0;
+            break;
+        }
+    }
+    else /* Control codes */
+    {
+        switch (virt)
+        {
+        case VK_OEM_4:     buffer[0] = 0x1b; break;
+        case VK_OEM_5:     buffer[0] = 0x1c; break;
+        case VK_OEM_6:     buffer[0] = 0x1d; break;
+        case VK_SUBTRACT:  buffer[0] = 0x1e; break;
+        default:
+            if (virt >= 'A' && virt <= 'Z') buffer[0] = virt - 'A' + 1;
+            else buffer[0] = 0;
+            break;
+        }
+    }
+    buffer[1] = 0;
+    len = wcslen( buffer );
+
+    len = USER_Driver->pToUnicodeEx( virt, scan, state, str, size, flags, layout, buffer, len );
+
+    TRACE_(keyboard)( "ret %d, str %s.\n", len, len < 0 ? "" : debugstr_wn(str, len) );
+    return len;
 }
 
 /****************************************************************************
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 5f8059a12a0..8f9841ec48b 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -71,7 +71,7 @@ typedef struct tagUSER_DRIVER {
     HKL    (CDECL *pLoadKeyboardLayout)(LPCWSTR, UINT);
     UINT   (CDECL *pMapVirtualKeyEx)(UINT, UINT, HKL);
     BOOL   (CDECL *pRegisterHotKey)(HWND, UINT, UINT);
-    INT    (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL);
+    INT    (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL, const WCHAR *, INT);
     BOOL   (CDECL *pUnloadKeyboardLayout)(HKL);
     void   (CDECL *pUnregisterHotKey)(HWND, UINT, UINT);
     SHORT  (CDECL *pVkKeyScanEx)(WCHAR, HKL);
diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c
index 0a6ede0ec5f..04565c3fad8 100644
--- a/dlls/wineandroid.drv/keyboard.c
+++ b/dlls/wineandroid.drv/keyboard.c
@@ -750,100 +750,6 @@ jboolean keyboard_event( JNIEnv *env, jobject obj, jint win, jint action, jint k
 }
 
 
-/***********************************************************************
- *           ANDROID_ToUnicodeEx
- */
-INT CDECL ANDROID_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
-                               LPWSTR buf, int size, UINT flags, HKL hkl )
-{
-    WCHAR buffer[2];
-    BOOL shift = state[VK_SHIFT] & 0x80;
-    BOOL ctrl = state[VK_CONTROL] & 0x80;
-    BOOL numlock = state[VK_NUMLOCK] & 0x01;
-
-    buffer[0] = buffer[1] = 0;
-
-    if (scan & 0x8000) return 0;  /* key up */
-
-    /* FIXME: hardcoded layout */
-
-    if (!ctrl)
-    {
-        switch (virt)
-        {
-        case VK_BACK:       buffer[0] = '\b'; break;
-        case VK_OEM_1:      buffer[0] = shift ? ':' : ';'; break;
-        case VK_OEM_2:      buffer[0] = shift ? '?' : '/'; break;
-        case VK_OEM_3:      buffer[0] = shift ? '~' : '`'; break;
-        case VK_OEM_4:      buffer[0] = shift ? '{' : '['; break;
-        case VK_OEM_5:      buffer[0] = shift ? '|' : '\\'; break;
-        case VK_OEM_6:      buffer[0] = shift ? '}' : ']'; break;
-        case VK_OEM_7:      buffer[0] = shift ? '"' : '\''; break;
-        case VK_OEM_COMMA:  buffer[0] = shift ? '<' : ','; break;
-        case VK_OEM_MINUS:  buffer[0] = shift ? '_' : '-'; break;
-        case VK_OEM_PERIOD: buffer[0] = shift ? '>' : '.'; break;
-        case VK_OEM_PLUS:   buffer[0] = shift ? '+' : '='; break;
-        case VK_RETURN:     buffer[0] = '\r'; break;
-        case VK_SPACE:      buffer[0] = ' '; break;
-        case VK_TAB:        buffer[0] = '\t'; break;
-        case VK_MULTIPLY:   buffer[0] = '*'; break;
-        case VK_ADD:        buffer[0] = '+'; break;
-        case VK_SUBTRACT:   buffer[0] = '-'; break;
-        case VK_DIVIDE:     buffer[0] = '/'; break;
-        default:
-            if (virt >= '0' && virt <= '9')
-            {
-                buffer[0] = shift ? ")!@#$%^&*("[virt - '0'] : virt;
-                break;
-            }
-            if (virt >= 'A' && virt <= 'Z')
-            {
-                buffer[0] =  shift || (state[VK_CAPITAL] & 0x01) ? virt : virt + 'a' - 'A';
-                break;
-            }
-            if (virt >= VK_NUMPAD0 && virt <= VK_NUMPAD9 && numlock && !shift)
-            {
-                buffer[0] = '0' + virt - VK_NUMPAD0;
-                break;
-            }
-            if (virt == VK_DECIMAL && numlock && !shift)
-            {
-                buffer[0] = '.';
-                break;
-            }
-            break;
-        }
-    }
-    else /* Control codes */
-    {
-        if (virt >= 'A' && virt <= 'Z')
-            buffer[0] = virt - 'A' + 1;
-        else
-        {
-            switch (virt)
-            {
-            case VK_OEM_4:
-                buffer[0] = 0x1b;
-                break;
-            case VK_OEM_5:
-                buffer[0] = 0x1c;
-                break;
-            case VK_OEM_6:
-                buffer[0] = 0x1d;
-                break;
-            case VK_SUBTRACT:
-                buffer[0] = 0x1e;
-                break;
-            }
-        }
-    }
-
-    lstrcpynW( buf, buffer, size );
-    TRACE( "returning %d / %s\n", strlenW( buffer ), debugstr_wn(buf, strlenW( buffer )));
-    return strlenW( buffer );
-}
-
-
 /***********************************************************************
  *           ANDROID_GetKeyNameText
  */
diff --git a/dlls/wineandroid.drv/wineandroid.drv.spec b/dlls/wineandroid.drv/wineandroid.drv.spec
index 00de23de27e..6f27c1586b3 100644
--- a/dlls/wineandroid.drv/wineandroid.drv.spec
+++ b/dlls/wineandroid.drv/wineandroid.drv.spec
@@ -7,7 +7,6 @@
 @ cdecl GetKeyNameText(long ptr long) ANDROID_GetKeyNameText
 @ cdecl GetKeyboardLayout(long) ANDROID_GetKeyboardLayout
 @ cdecl MapVirtualKeyEx(long long long) ANDROID_MapVirtualKeyEx
-@ cdecl ToUnicodeEx(long long ptr ptr long long long) ANDROID_ToUnicodeEx
 @ cdecl VkKeyScanEx(long long) ANDROID_VkKeyScanEx
 @ cdecl SetCursor(long) ANDROID_SetCursor
 @ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) ANDROID_ChangeDisplaySettingsEx
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index 1ea15f59341..d9c819431f2 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -1553,7 +1553,8 @@ BOOL CDECL macdrv_RegisterHotKey(HWND hwnd, UINT mod_flags, UINT vkey)
  *
  */
 INT CDECL macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
-                             LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
+                             LPWSTR bufW, int bufW_size, UINT flags, HKL hkl,
+                             const WCHAR *default_buf, INT default_len)
 {
     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
     INT ret = 0;
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index 39cf33370b4..97c94b6ee88 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -34,7 +34,7 @@
 @ cdecl SysCommand(long long long) macdrv_SysCommand
 @ cdecl SystemParametersInfo(long long ptr long) macdrv_SystemParametersInfo
 @ cdecl ThreadDetach() macdrv_ThreadDetach
-@ cdecl ToUnicodeEx(long long ptr ptr long long long) macdrv_ToUnicodeEx
+@ cdecl ToUnicodeEx(long long ptr ptr long long long ptr long) macdrv_ToUnicodeEx
 @ cdecl UnregisterHotKey(long long long) macdrv_UnregisterHotKey
 @ cdecl UpdateClipboard() macdrv_UpdateClipboard
 @ cdecl UpdateLayeredWindow(long ptr ptr) macdrv_UpdateLayeredWindow
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 01620c5e4a4..c45d12c7517 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -2432,7 +2432,8 @@ static char KEYBOARD_MapDeadKeysym(KeySym keysym)
  *
  */
 INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
-                             LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
+                             LPWSTR bufW, int bufW_size, UINT flags, HKL hkl,
+                             const WCHAR *default_buf, INT default_len)
 {
     Display *display = thread_init_display();
     XKeyEvent e;
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index c0e24d8fe82..b73ae87b929 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -11,7 +11,7 @@
 @ cdecl GetKeyboardLayoutName(ptr) X11DRV_GetKeyboardLayoutName
 @ cdecl LoadKeyboardLayout(wstr long) X11DRV_LoadKeyboardLayout
 @ cdecl MapVirtualKeyEx(long long long) X11DRV_MapVirtualKeyEx
-@ cdecl ToUnicodeEx(long long ptr ptr long long long) X11DRV_ToUnicodeEx
+@ cdecl ToUnicodeEx(long long ptr ptr long long long ptr long) X11DRV_ToUnicodeEx
 @ cdecl UnloadKeyboardLayout(long) X11DRV_UnloadKeyboardLayout
 @ cdecl VkKeyScanEx(long long) X11DRV_VkKeyScanEx
 @ cdecl DestroyCursorIcon(long) X11DRV_DestroyCursorIcon
-- 
2.31.0




More information about the wine-devel mailing list