diff --git a/include/string.hpp b/include/string.hpp index ad093e05..eafe63fc 100644 --- a/include/string.hpp +++ b/include/string.hpp @@ -10,6 +10,9 @@ namespace rack { namespace string { +/** Converts a UTF-16/32 string (depending on the size of wchar_t) to a UTF-8 string. */ +std::string fromWstring(const std::wstring &s); +std::wstring toWstring(const std::string &s); /** Converts a `printf()` format string and optional arguments into a std::string Remember that "%s" must reference a `char *`, so use `.c_str()` for `std::string`s. */ diff --git a/src/asset.cpp b/src/asset.cpp index 6cdd9ebd..7f3be2aa 100644 --- a/src/asset.cpp +++ b/src/asset.cpp @@ -1,6 +1,7 @@ #include "asset.hpp" #include "system.hpp" #include "settings.hpp" +#include "string.hpp" #include "plugin/Plugin.hpp" #if defined ARCH_MAC @@ -52,10 +53,7 @@ void init() { // Convert to short path to avoid Unicode wchar_t moduleBufShortW[MAX_PATH]; GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW)); - // Convert to UTF-8. - char moduleBuf[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, moduleBufShortW, -1, moduleBuf, sizeof(moduleBuf), NULL, NULL); - systemDir = moduleBuf; + systemDir = string::fromWstring(moduleBufShortW); #endif #if defined ARCH_LIN // Users should launch Rack from their terminal in the system directory @@ -74,14 +72,11 @@ void init() { // Get "My Documents" folder wchar_t documentsBufW[MAX_PATH] = L"."; HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW); - // assert(result == S_OK); + assert(result == S_OK); // Convert to short path to avoid Unicode wchar_t documentsBufShortW[MAX_PATH]; GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW)); - // Convert to UTF-8. - char documentsBuf[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, documentsBufShortW, -1, documentsBuf, sizeof(documentsBuf), NULL, NULL); - userDir = documentsBuf; + userDir = string::fromWstring(documentsBufShortW); userDir += "/Rack"; #endif #if defined ARCH_MAC diff --git a/src/string.cpp b/src/string.cpp index aa9a404a..a7781d5a 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -1,4 +1,6 @@ #include "string.hpp" +#include // for wstring_convert +#include // for codecvt_utf8_utf16 #include // for tolower and toupper #include // for transform #include // for dirname and basename @@ -8,6 +10,16 @@ namespace rack { namespace string { +std::string fromWstring(const std::wstring &s) { + std::wstring_convert> converter; + return converter.to_bytes(s); +} + +std::wstring toWstring(const std::string &s) { + std::wstring_convert> converter; + return converter.from_bytes(s); +} + std::string f(const char *format, ...) { va_list args; va_start(args, format); diff --git a/src/system.cpp b/src/system.cpp index 533a87ae..1e000a16 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -85,9 +85,8 @@ void copyFile(const std::string &srcPath, const std::string &destPath) { void createDirectory(const std::string &path) { #if defined ARCH_WIN - wchar_t pathW[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); - CreateDirectoryW(pathW, NULL); + std::wstring pathW = string::toWstring(path); + CreateDirectoryW(pathW.c_str(), NULL); #else mkdir(path.c_str(), 0755); #endif @@ -162,9 +161,8 @@ void openBrowser(const std::string &url) { std::system(command.c_str()); #endif #if defined ARCH_WIN - wchar_t urlW[1024]; - MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, urlW, LENGTHOF(urlW)); - ShellExecuteW(NULL, L"open", urlW, NULL, NULL, SW_SHOWNORMAL); + std::wstring urlW = string::toWstring(url); + ShellExecuteW(NULL, L"open", urlW.c_str(), NULL, NULL, SW_SHOWNORMAL); #endif } @@ -174,9 +172,8 @@ void openFolder(const std::string &path) { (void) std::system(command.c_str()); #endif #if defined ARCH_WIN - wchar_t pathW[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); - ShellExecuteW(NULL, L"explorer", pathW, NULL, NULL, SW_SHOWNORMAL); + std::wstring pathW = string::toWstring(path); + ShellExecuteW(NULL, L"explorer", pathW.c_str(), NULL, NULL, SW_SHOWNORMAL); #endif } @@ -190,9 +187,8 @@ void runProcessAsync(const std::string &path) { startupInfo.cb = sizeof(startupInfo); std::memset(&processInfo, 0, sizeof(processInfo)); - wchar_t pathW[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); - CreateProcessW(pathW, NULL, + std::wstring pathW = string::toWstring(path); + CreateProcessW(pathW.c_str(), NULL, NULL, NULL, false, 0, NULL, NULL, &startupInfo, &processInfo); #endif