| @@ -12,9 +12,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); | |||||
| /** Performs a Unicode string conversion from UTF-16 to UTF-8. */ | |||||
| std::string UTF16toUTF8(const std::u16string& s); | |||||
| std::u16string UTF8toUTF16(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, otherwise you might get binary garbage. | Remember that "%s" must reference a `char *`, so use `.c_str()` for `std::string`s, otherwise you might get binary garbage. | ||||
| */ | */ | ||||
| @@ -61,12 +61,12 @@ static void initSystemDir() { | |||||
| #endif | #endif | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| // Get path to executable | // Get path to executable | ||||
| wchar_t moduleBufW[MAX_PATH]; | |||||
| DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW)); | |||||
| char16_t moduleBufU16[MAX_PATH]; | |||||
| DWORD length = GetModuleFileNameW(NULL, moduleBufU16, LENGTHOF(moduleBufU16)); | |||||
| assert(length > 0); | assert(length > 0); | ||||
| // Get folder of executable | // Get folder of executable | ||||
| PathRemoveFileSpecW(moduleBufW); | |||||
| systemDir = string::fromWstring(moduleBufW); | |||||
| PathRemoveFileSpecW(moduleBufU16); | |||||
| systemDir = string::UTF16toUTF8(moduleBufU16); | |||||
| #endif | #endif | ||||
| #if defined ARCH_LIN | #if defined ARCH_LIN | ||||
| // Use the current working directory as the default path on Linux. | // Use the current working directory as the default path on Linux. | ||||
| @@ -86,10 +86,10 @@ static void initUserDir() { | |||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| // Get "My Documents" folder | // Get "My Documents" folder | ||||
| wchar_t documentsBufW[MAX_PATH] = L"."; | |||||
| HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW); | |||||
| char16_t documentsBufU16[MAX_PATH] = L"."; | |||||
| HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufU16); | |||||
| assert(result == S_OK); | assert(result == S_OK); | ||||
| userDir = string::fromWstring(documentsBufW); | |||||
| userDir = string::UTF16toUTF8(documentsBufU16); | |||||
| userDir += "/Rack"; | userDir += "/Rack"; | ||||
| #endif | #endif | ||||
| #if defined ARCH_MAC | #if defined ARCH_MAC | ||||
| @@ -1,4 +1,5 @@ | |||||
| #include <common.hpp> | #include <common.hpp> | ||||
| #include <string.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -26,36 +27,16 @@ const std::string API_VERSION = "2"; | |||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| #include <windows.h> | #include <windows.h> | ||||
| static wchar_t* utf8_to_w(const char* str) { | |||||
| int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0, 0); | |||||
| wchar_t* strW = (wchar_t*) malloc(len * sizeof(wchar_t)); | |||||
| MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len); | |||||
| return strW; | |||||
| } | |||||
| FILE* fopen_utf8(const char* filename, const char* mode) { | FILE* fopen_utf8(const char* filename, const char* mode) { | ||||
| wchar_t* filenameW = utf8_to_w(filename); | |||||
| wchar_t* modeW = utf8_to_w(mode); | |||||
| FILE* file = _wfopen(filenameW, modeW); | |||||
| free(filenameW); | |||||
| free(modeW); | |||||
| return file; | |||||
| return _wfopen(rack::string::UTF8toUTF16(filename).c_str(), rack::string::UTF8toUTF16(mode).c_str()); | |||||
| } | } | ||||
| int remove_utf8(const char* path) { | int remove_utf8(const char* path) { | ||||
| wchar_t* pathW = utf8_to_w(path); | |||||
| int ret = _wremove(pathW); | |||||
| free(pathW); | |||||
| return ret; | |||||
| return _wremove(rack::string::UTF8toUTF16(path).c_str()); | |||||
| } | } | ||||
| int rename_utf8(const char* oldname, const char* newname) { | int rename_utf8(const char* oldname, const char* newname) { | ||||
| wchar_t* oldnameW = utf8_to_w(oldname); | |||||
| wchar_t* newnameW = utf8_to_w(newname); | |||||
| int ret = _wrename(oldnameW, newnameW); | |||||
| free(oldnameW); | |||||
| free(newnameW); | |||||
| return ret; | |||||
| return _wrename(rack::string::UTF8toUTF16(oldname).c_str(), rack::string::UTF8toUTF16(newname).c_str()); | |||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -46,8 +46,8 @@ namespace plugin { | |||||
| static void* loadLibrary(std::string libraryPath) { | static void* loadLibrary(std::string libraryPath) { | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); | SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); | ||||
| std::wstring libraryFilenameW = string::toWstring(libraryPath); | |||||
| HINSTANCE handle = LoadLibraryW(libraryFilenameW.c_str()); | |||||
| std::u16string libraryFilenameU16 = string::UTF8toUTF16(libraryPath); | |||||
| HINSTANCE handle = LoadLibraryW(libraryFilenameU16.c_str()); | |||||
| SetErrorMode(0); | SetErrorMode(0); | ||||
| if (!handle) { | if (!handle) { | ||||
| int error = GetLastError(); | int error = GetLastError(); | ||||
| @@ -12,14 +12,14 @@ namespace rack { | |||||
| namespace string { | namespace string { | ||||
| std::string fromWstring(const std::wstring& s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | |||||
| std::string UTF16toUTF8(const std::u16string& s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; | |||||
| return converter.to_bytes(s); | return converter.to_bytes(s); | ||||
| } | } | ||||
| std::wstring toWstring(const std::string& s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | |||||
| std::u16string UTF8toUTF16(const std::string& s) { | |||||
| std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; | |||||
| return converter.from_bytes(s); | return converter.from_bytes(s); | ||||
| } | } | ||||
| @@ -137,11 +137,11 @@ std::string absolutePath(const std::string& path) { | |||||
| if (absPathC) | if (absPathC) | ||||
| return absPathC; | return absPathC; | ||||
| #elif defined ARCH_WIN | #elif defined ARCH_WIN | ||||
| std::wstring pathW = toWstring(path); | |||||
| wchar_t buf[PATH_MAX]; | |||||
| wchar_t* absPathC = _wfullpath(buf, pathW.c_str(), PATH_MAX); | |||||
| std::u16string pathU16 = UTF8toUTF16(path); | |||||
| char16_t buf[PATH_MAX]; | |||||
| char16_t* absPathC = _wfullpath(buf, pathU16.c_str(), PATH_MAX); | |||||
| if (absPathC) | if (absPathC) | ||||
| return fromWstring(absPathC); | |||||
| return UTF16toUTF8(absPathC); | |||||
| #endif | #endif | ||||
| return ""; | return ""; | ||||
| } | } | ||||
| @@ -130,8 +130,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 | ||||
| std::wstring pathW = string::toWstring(path); | |||||
| _wmkdir(pathW.c_str()); | |||||
| std::u16string pathU16 = string::UTF8toUTF16(path); | |||||
| _wmkdir(pathU16.c_str()); | |||||
| #else | #else | ||||
| mkdir(path.c_str(), 0755); | mkdir(path.c_str(), 0755); | ||||
| #endif | #endif | ||||
| @@ -150,8 +150,8 @@ void createDirectories(const std::string& path) { | |||||
| void removeDirectory(const std::string& path) { | void removeDirectory(const std::string& path) { | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| std::wstring pathW = string::toWstring(path); | |||||
| _wrmdir(pathW.c_str()); | |||||
| std::u16string pathU16 = string::UTF8toUTF16(path); | |||||
| _wrmdir(pathU16.c_str()); | |||||
| #else | #else | ||||
| rmdir(path.c_str()); | rmdir(path.c_str()); | ||||
| #endif | #endif | ||||
| @@ -170,9 +170,9 @@ void removeDirectories(const std::string& path) { | |||||
| std::string getWorkingDirectory() { | std::string getWorkingDirectory() { | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| wchar_t buf[4096] = L""; | |||||
| char16_t buf[4096] = L""; | |||||
| GetCurrentDirectory(sizeof(buf), buf); | GetCurrentDirectory(sizeof(buf), buf); | ||||
| return string::fromWstring(buf); | |||||
| return string::UTF16toUTF8(buf); | |||||
| #else | #else | ||||
| char buf[4096] = ""; | char buf[4096] = ""; | ||||
| getcwd(buf, sizeof(buf)); | getcwd(buf, sizeof(buf)); | ||||
| @@ -183,8 +183,8 @@ std::string getWorkingDirectory() { | |||||
| void setWorkingDirectory(const std::string& path) { | void setWorkingDirectory(const std::string& path) { | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| std::wstring pathW = string::toWstring(path); | |||||
| SetCurrentDirectory(pathW.c_str()); | |||||
| std::u16string pathU16 = string::UTF8toUTF16(path); | |||||
| SetCurrentDirectory(pathU16.c_str()); | |||||
| #else | #else | ||||
| chdir(path.c_str()); | chdir(path.c_str()); | ||||
| #endif | #endif | ||||
| @@ -301,7 +301,7 @@ 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 | ||||
| std::wstring urlW = string::toWstring(url); | |||||
| std::u16string urlW = string::UTF8toUTF16(url); | |||||
| ShellExecuteW(NULL, L"open", urlW.c_str(), NULL, NULL, SW_SHOWDEFAULT); | ShellExecuteW(NULL, L"open", urlW.c_str(), NULL, NULL, SW_SHOWDEFAULT); | ||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -317,8 +317,8 @@ void openFolder(const std::string& path) { | |||||
| std::system(command.c_str()); | std::system(command.c_str()); | ||||
| #endif | #endif | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| std::wstring pathW = string::toWstring(path); | |||||
| ShellExecuteW(NULL, L"explore", pathW.c_str(), NULL, NULL, SW_SHOWDEFAULT); | |||||
| std::u16string pathU16 = string::UTF8toUTF16(path); | |||||
| ShellExecuteW(NULL, L"explore", pathU16.c_str(), NULL, NULL, SW_SHOWDEFAULT); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -330,8 +330,8 @@ void runProcessDetached(const std::string& path) { | |||||
| shExInfo.cbSize = sizeof(shExInfo); | shExInfo.cbSize = sizeof(shExInfo); | ||||
| shExInfo.lpVerb = L"runas"; | shExInfo.lpVerb = L"runas"; | ||||
| std::wstring pathW = string::toWstring(path); | |||||
| shExInfo.lpFile = pathW.c_str(); | |||||
| std::u16string pathU16 = string::UTF8toUTF16(path); | |||||
| shExInfo.lpFile = pathU16.c_str(); | |||||
| shExInfo.nShow = SW_SHOW; | shExInfo.nShow = SW_SHOW; | ||||
| if (ShellExecuteExW(&shExInfo)) { | if (ShellExecuteExW(&shExInfo)) { | ||||