| @@ -10,6 +10,9 @@ namespace rack { | |||||
| namespace string { | 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 | /** 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. | Remember that "%s" must reference a `char *`, so use `.c_str()` for `std::string`s. | ||||
| */ | */ | ||||
| @@ -1,6 +1,7 @@ | |||||
| #include "asset.hpp" | #include "asset.hpp" | ||||
| #include "system.hpp" | #include "system.hpp" | ||||
| #include "settings.hpp" | #include "settings.hpp" | ||||
| #include "string.hpp" | |||||
| #include "plugin/Plugin.hpp" | #include "plugin/Plugin.hpp" | ||||
| #if defined ARCH_MAC | #if defined ARCH_MAC | ||||
| @@ -52,10 +53,7 @@ void init() { | |||||
| // Convert to short path to avoid Unicode | // Convert to short path to avoid Unicode | ||||
| wchar_t moduleBufShortW[MAX_PATH]; | wchar_t moduleBufShortW[MAX_PATH]; | ||||
| GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW)); | 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 | #endif | ||||
| #if defined ARCH_LIN | #if defined ARCH_LIN | ||||
| // Users should launch Rack from their terminal in the system directory | // Users should launch Rack from their terminal in the system directory | ||||
| @@ -74,14 +72,11 @@ void init() { | |||||
| // Get "My Documents" folder | // Get "My Documents" folder | ||||
| wchar_t documentsBufW[MAX_PATH] = L"."; | wchar_t documentsBufW[MAX_PATH] = L"."; | ||||
| HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW); | 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 | // Convert to short path to avoid Unicode | ||||
| wchar_t documentsBufShortW[MAX_PATH]; | wchar_t documentsBufShortW[MAX_PATH]; | ||||
| GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW)); | 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"; | userDir += "/Rack"; | ||||
| #endif | #endif | ||||
| #if defined ARCH_MAC | #if defined ARCH_MAC | ||||
| @@ -1,4 +1,6 @@ | |||||
| #include "string.hpp" | #include "string.hpp" | ||||
| #include <locale> // for wstring_convert | |||||
| #include <codecvt> // for codecvt_utf8_utf16 | |||||
| #include <cctype> // for tolower and toupper | #include <cctype> // for tolower and toupper | ||||
| #include <algorithm> // for transform | #include <algorithm> // for transform | ||||
| #include <libgen.h> // for dirname and basename | #include <libgen.h> // for dirname and basename | ||||
| @@ -8,6 +10,16 @@ namespace rack { | |||||
| namespace string { | namespace string { | ||||
| std::string fromWstring(const std::wstring &s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | |||||
| return converter.to_bytes(s); | |||||
| } | |||||
| std::wstring toWstring(const std::string &s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | |||||
| return converter.from_bytes(s); | |||||
| } | |||||
| std::string f(const char *format, ...) { | std::string f(const char *format, ...) { | ||||
| va_list args; | va_list args; | ||||
| va_start(args, format); | va_start(args, format); | ||||
| @@ -85,9 +85,8 @@ void copyFile(const std::string &srcPath, const std::string &destPath) { | |||||
| void createDirectory(const std::string &path) { | void createDirectory(const std::string &path) { | ||||
| #if defined ARCH_WIN | #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 | #else | ||||
| mkdir(path.c_str(), 0755); | mkdir(path.c_str(), 0755); | ||||
| #endif | #endif | ||||
| @@ -162,9 +161,8 @@ void openBrowser(const std::string &url) { | |||||
| std::system(command.c_str()); | std::system(command.c_str()); | ||||
| #endif | #endif | ||||
| #if defined ARCH_WIN | #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 | #endif | ||||
| } | } | ||||
| @@ -174,9 +172,8 @@ void openFolder(const std::string &path) { | |||||
| (void) std::system(command.c_str()); | (void) std::system(command.c_str()); | ||||
| #endif | #endif | ||||
| #if defined ARCH_WIN | #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 | #endif | ||||
| } | } | ||||
| @@ -190,9 +187,8 @@ void runProcessAsync(const std::string &path) { | |||||
| startupInfo.cb = sizeof(startupInfo); | startupInfo.cb = sizeof(startupInfo); | ||||
| std::memset(&processInfo, 0, sizeof(processInfo)); | 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, | NULL, NULL, false, 0, NULL, NULL, | ||||
| &startupInfo, &processInfo); | &startupInfo, &processInfo); | ||||
| #endif | #endif | ||||