diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp index da806681d44..667e58df1da 100644 --- a/backends/platform/sdl/win32/win32.cpp +++ b/backends/platform/sdl/win32/win32.cpp @@ -33,7 +33,7 @@ #define _WIN32_IE 0x500 #endif #include -#include +#include #include "common/scummsys.h" #include "common/config-manager.h" @@ -106,7 +106,7 @@ void OSystem_Win32::initBackend() { freopen("CONOUT$","w",stdout); freopen("CONOUT$","w",stderr); } - SetConsoleTitle("ScummVM Status Window"); + SetConsoleTitle(TEXT("ScummVM Status Window")); } else { FreeConsole(); } @@ -152,9 +152,12 @@ bool OSystem_Win32::displayLogFile() { // Try opening the log file with the default text editor // log files should be registered as "txtfile" by default and thus open in the default text editor - HINSTANCE shellExec = ShellExecute(getHwnd(), NULL, _logFilePath.c_str(), NULL, NULL, SW_SHOWNORMAL); - if ((intptr_t)shellExec > 32) + TCHAR *tLogFilePath = Win32::stringToTchar(_logFilePath); + HINSTANCE shellExec = ShellExecute(getHwnd(), NULL, tLogFilePath, NULL, NULL, SW_SHOWNORMAL); + if ((intptr_t)shellExec > 32) { + free(tLogFilePath); return true; + } // ShellExecute with the default verb failed, try the "Open with..." dialog PROCESS_INFORMATION processInformation; @@ -163,8 +166,8 @@ bool OSystem_Win32::displayLogFile() { memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); - char cmdLine[MAX_PATH * 2]; // CreateProcess may change the contents of cmdLine - sprintf(cmdLine, "rundll32 shell32.dll,OpenAs_RunDLL %s", _logFilePath.c_str()); + TCHAR cmdLine[MAX_PATH * 2]; // CreateProcess may change the contents of cmdLine + _stprintf(cmdLine, TEXT("rundll32 shell32.dll,OpenAs_RunDLL %s"), tLogFilePath); BOOL result = CreateProcess(NULL, cmdLine, NULL, @@ -175,6 +178,7 @@ bool OSystem_Win32::displayLogFile() { NULL, &startupInfo, &processInformation); + free(tLogFilePath); if (result) { CloseHandle(processInformation.hProcess); CloseHandle(processInformation.hThread); @@ -185,7 +189,9 @@ bool OSystem_Win32::displayLogFile() { } bool OSystem_Win32::openUrl(const Common::String &url) { - HINSTANCE result = ShellExecute(getHwnd(), NULL, /*(wchar_t*)nativeFilePath.utf16()*/url.c_str(), NULL, NULL, SW_SHOWNORMAL); + TCHAR *tUrl = Win32::stringToTchar(url); + HINSTANCE result = ShellExecute(getHwnd(), NULL, tUrl, NULL, NULL, SW_SHOWNORMAL); + free(tUrl); // ShellExecute returns a value greater than 32 if successful if ((intptr_t)result <= 32) { warning("ShellExecute failed: error = %p", (void*)result); @@ -207,14 +213,14 @@ Common::String OSystem_Win32::getSystemLanguage() const { // We can not use "setlocale" (at least not for MSVC builds), since it // will return locales like: "English_USA.1252", thus we need a special // way to determine the locale string for Win32. - char langName[9]; - char ctryName[9]; + TCHAR langName[9]; + TCHAR ctryName[9]; - if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 && - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) { - Common::String localeName = langName; + if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, langName, ARRAYSIZE(langName)) != 0 && + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ctryName, ARRAYSIZE(ctryName)) != 0) { + Common::String localeName = Win32::tcharToString(langName); localeName += "_"; - localeName += ctryName; + localeName += Win32::tcharToString(ctryName); return localeName; } @@ -232,49 +238,49 @@ Common::String OSystem_Win32::getScreenshotsPath() { } // Use the My Pictures folder. - char picturesPath[MAX_PATH]; + TCHAR picturesPath[MAX_PATH]; if (SHGetFolderPathFunc(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, picturesPath) != S_OK) { warning("Unable to access My Pictures directory"); return Common::String(); } - screenshotsPath = Common::String(picturesPath) + "\\ScummVM Screenshots\\"; + _tcscat(picturesPath, TEXT("\\ScummVM Screenshots\\")); // If the directory already exists (as it should in most cases), // we don't want to fail, but we need to stop on other errors (such as ERROR_PATH_NOT_FOUND) - if (!CreateDirectory(screenshotsPath.c_str(), NULL)) { + if (!CreateDirectory(picturesPath, NULL)) { if (GetLastError() != ERROR_ALREADY_EXISTS) error("Cannot create ScummVM Screenshots folder"); } - return screenshotsPath; + return Win32::tcharToString(picturesPath); } Common::String OSystem_Win32::getDefaultConfigFileName() { - char configFile[MAX_PATH]; + TCHAR configFile[MAX_PATH]; // Use the Application Data directory of the user profile. if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configFile) == S_OK) { - strcat(configFile, "\\ScummVM"); + _tcscat(configFile, TEXT("\\ScummVM")); if (!CreateDirectory(configFile, NULL)) { if (GetLastError() != ERROR_ALREADY_EXISTS) error("Cannot create ScummVM application data folder"); } - strcat(configFile, "\\" DEFAULT_CONFIG_FILE); + _tcscat(configFile, TEXT("\\" DEFAULT_CONFIG_FILE)); FILE *tmp = NULL; - if ((tmp = fopen(configFile, "r")) == NULL) { + if ((tmp = _tfopen(configFile, TEXT("r"))) == NULL) { // Check windows directory - char oldConfigFile[MAX_PATH]; + TCHAR oldConfigFile[MAX_PATH]; uint ret = GetWindowsDirectory(oldConfigFile, MAX_PATH); if (ret == 0 || ret > MAX_PATH) error("Cannot retrieve the path of the Windows directory"); - strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE); - if ((tmp = fopen(oldConfigFile, "r"))) { - strcpy(configFile, oldConfigFile); + _tcscat(oldConfigFile, TEXT("\\" DEFAULT_CONFIG_FILE)); + if ((tmp = _tfopen(oldConfigFile, TEXT("r")))) { + _tcscpy(configFile, oldConfigFile); fclose(tmp); } @@ -288,14 +294,14 @@ Common::String OSystem_Win32::getDefaultConfigFileName() { if (ret == 0 || ret > MAX_PATH) error("Cannot retrieve the path of the Windows directory"); - strcat(configFile, "\\" DEFAULT_CONFIG_FILE); + _tcscat(configFile, TEXT("\\" DEFAULT_CONFIG_FILE)); } - return configFile; + return Win32::tcharToString(configFile); } Common::String OSystem_Win32::getDefaultLogFileName() { - char logFile[MAX_PATH]; + TCHAR logFile[MAX_PATH]; // Use the Application Data directory of the user profile. if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, logFile) != S_OK) { @@ -303,13 +309,13 @@ Common::String OSystem_Win32::getDefaultLogFileName() { return Common::String(); } - strcat(logFile, "\\ScummVM"); + _tcscat(logFile, TEXT("\\ScummVM")); CreateDirectory(logFile, NULL); - strcat(logFile, "\\Logs"); + _tcscat(logFile, TEXT("\\Logs")); CreateDirectory(logFile, NULL); - strcat(logFile, "\\scummvm.log"); + _tcscat(logFile, TEXT("\\scummvm.log")); - return logFile; + return Win32::tcharToString(logFile); } namespace { diff --git a/backends/platform/sdl/win32/win32_wrapper.cpp b/backends/platform/sdl/win32/win32_wrapper.cpp index c188ad999ef..4ed76754f96 100644 --- a/backends/platform/sdl/win32/win32_wrapper.cpp +++ b/backends/platform/sdl/win32/win32_wrapper.cpp @@ -53,10 +53,16 @@ BOOL VerifyVersionInfoFunc(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwType return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask); } -HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath) { - typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath); +HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath) { + typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath); - SHGetFolderPathFunc pSHGetFolderPath = (SHGetFolderPathFunc)(void *)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetFolderPathA"); + SHGetFolderPathFunc pSHGetFolderPath = (SHGetFolderPathFunc)(void *)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), +#ifndef UNICODE + "SHGetFolderPathA" +#else + "SHGetFolderPathW" +#endif + ); if (pSHGetFolderPath) return pSHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath); @@ -80,7 +86,12 @@ bool confirmWindowsVersion(int majorVersion, int minorVersion) { return VerifyVersionInfoFunc(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask); } -wchar_t *ansiToUnicode(const char *s, uint codePage) { +wchar_t *ansiToUnicode(const char *s) { +#ifndef UNICODE + uint codePage = CP_ACP; +#else + uint codePage = CP_UTF8; +#endif DWORD size = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0); if (size > 0) { @@ -92,7 +103,12 @@ wchar_t *ansiToUnicode(const char *s, uint codePage) { return NULL; } -char *unicodeToAnsi(const wchar_t *s, uint codePage) { +char *unicodeToAnsi(const wchar_t *s) { +#ifndef UNICODE + uint codePage = CP_ACP; +#else + uint codePage = CP_UTF8; +#endif DWORD size = WideCharToMultiByte(codePage, 0, s, -1, NULL, 0, 0, 0); if (size > 0) { @@ -104,4 +120,25 @@ char *unicodeToAnsi(const wchar_t *s, uint codePage) { return NULL; } +TCHAR *stringToTchar(const Common::String& s) { +#ifndef UNICODE + char *t = (char *)malloc(s.size() + 1); + strcpy(t, s.c_str()); + return t; +#else + return ansiToUnicode(s.c_str()); +#endif +} + +Common::String tcharToString(const TCHAR *t) { +#ifndef UNICODE + return t; +#else + char *utf8 = unicodeToAnsi(t); + Common::String s = utf8; + free(utf8); + return s; +#endif +} + } diff --git a/backends/platform/sdl/win32/win32_wrapper.h b/backends/platform/sdl/win32/win32_wrapper.h index ee3b77bed65..f16ecaad67c 100644 --- a/backends/platform/sdl/win32/win32_wrapper.h +++ b/backends/platform/sdl/win32/win32_wrapper.h @@ -24,8 +24,9 @@ #define PLATFORM_SDL_WIN32_WRAPPER_H #include "common/scummsys.h" +#include "common/str.h" -HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath); +HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath); // Helper functions namespace Win32 { @@ -41,25 +42,50 @@ bool confirmWindowsVersion(int majorVersion, int minorVersion); /** * Converts a C string into a Windows wide-character string. * Used to interact with Win32 Unicode APIs with no ANSI fallback. + * If UNICODE is defined then the conversion will use code page CP_UTF8, + * otherwise CP_ACP will be used. * * @param s Source string - * @param c Code Page, by default is CP_ACP (default Windows ANSI code page) * @return Converted string * * @note Return value must be freed by the caller. */ -wchar_t *ansiToUnicode(const char *s, uint codePage = CP_ACP); +wchar_t *ansiToUnicode(const char *s); /** * Converts a Windows wide-character string into a C string. * Used to interact with Win32 Unicode APIs with no ANSI fallback. + * If UNICODE is defined then the conversion will use code page CP_UTF8, + * otherwise CP_ACP will be used. * * @param s Source string - * @param c Code Page, by default is CP_ACP (default Windows ANSI code page) * @return Converted string * * @note Return value must be freed by the caller. */ -char *unicodeToAnsi(const wchar_t *s, uint codePage = CP_ACP); +char *unicodeToAnsi(const wchar_t *s); + +/** + * Converts a Common::String to a TCHAR array for the purpose of passing to + * a Windows API or CRT call. If UNICODE is defined then the string will be + * converted from UTF8 to to wide characters, otherwise the character array + * will be copied with no conversion. + * + * @param s Source string + * @return Converted string + * + * @note Return value must be freed by the caller. + */ +TCHAR *stringToTchar(const Common::String& s); + +/** + * Converts a TCHAR array returned from a Windows API or CRT call to a Common::String. + * If UNICODE is defined then the wide character array will be converted to UTF8, + * otherwise the char array will be copied with no conversion. + * + * @param s Source string + * @return Converted string + */ +Common::String tcharToString(const TCHAR *s); }