From 1c5bc5373853cb8fdf43ec46ba4f00ce2325113d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 25 Jan 2024 18:53:56 -0500 Subject: [PATCH] windows: Manage WideCharToMultiByte vs Windows XP. Reference Issue #8666. --- src/core/windows/SDL_windows.c | 10 ++++++++++ src/core/windows/SDL_windows.h | 3 +++ src/hidapi/windows/hid.c | 8 ++++++++ src/video/windows/SDL_windowsevents.c | 2 +- src/video/winrt/SDL_winrtkeyboard.cpp | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index e7e0bc56d5..37e685a3ab 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -376,6 +376,16 @@ SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat) return 0; } + +int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar) +{ + if (WIN_IsWindowsXP()) { + dwFlags &= ~WC_ERR_INVALID_CHARS; // not supported before Vista. Without this flag, it will just replace bogus chars with U+FFFD. You're on your own, WinXP. + } + return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar); +} + + /* Win32-specific SDL_RunApp(), which does most of the SDL_main work, based on SDL_windows_main.c, placed in the public domain by Sam Lantinga 4/13/98 */ #ifdef SDL_PLATFORM_WIN32 diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 850b4ecac4..2434a8532c 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -173,6 +173,9 @@ extern BOOL WIN_IsRectEmpty(const RECT *rect); extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat); +/* WideCharToMultiByte, but with some WinXP manangement. */ +extern int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/hidapi/windows/hid.c b/src/hidapi/windows/hid.c index 3a90a3db37..b602fb7c2e 100644 --- a/src/hidapi/windows/hid.c +++ b/src/hidapi/windows/hid.c @@ -795,13 +795,21 @@ end: static char *hid_internal_UTF16toUTF8(const wchar_t *src) { char *dst = NULL; +#ifdef HIDAPI_USING_SDL_RUNTIME + int len = WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL); +#else int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL); +#endif if (len) { dst = (char*)calloc(len, sizeof(char)); if (dst == NULL) { return NULL; } +#ifdef HIDAPI_USING_SDL_RUNTIME + WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL); +#else WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL); +#endif } return dst; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 2ac4e78aef..930c2a7da0 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -973,7 +973,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) }; char utf8[5]; - int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + int result = WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); if (result > 0) { SDL_SendKeyboardText(utf8); } diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index b1aa6b0363..f210fab4f0 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -101,6 +101,7 @@ void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core:: }; char utf8[5]; + // doesn't need to be WIN_WideCharToMultiByte, since we don't care about WinXP support in WinRT. int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); if (result > 0) { SDL_SendKeyboardText(utf8);