| @@ -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. | |||
| */ | |||
| @@ -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 | |||
| @@ -1,4 +1,6 @@ | |||
| #include "string.hpp" | |||
| #include <locale> // for wstring_convert | |||
| #include <codecvt> // for codecvt_utf8_utf16 | |||
| #include <cctype> // for tolower and toupper | |||
| #include <algorithm> // for transform | |||
| #include <libgen.h> // for dirname and basename | |||
| @@ -8,6 +10,16 @@ namespace rack { | |||
| 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, ...) { | |||
| va_list args; | |||
| va_start(args, format); | |||
| @@ -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 | |||