mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
WIN32: Make OSystem_Win32 UNICODE compatible
This commit is contained in:
parent
fbf16c5a58
commit
ee5162078e
@ -33,7 +33,7 @@
|
||||
#define _WIN32_IE 0x500
|
||||
#endif
|
||||
#include <shlobj.h>
|
||||
#include <wchar.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user