reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit eb24962768785d42f5f83a41037a94d8b91f5616
parent 0e9c55babf65706476acfe5e2c4913524e8a1f40
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Thu, 17 Dec 2015 22:29:05 -0800

fix encoding issues on Windows

Why doesn't Windows support UTF-8 by default yet?

Diffstat:
Msrc/config.cpp | 1+
Asrc/encoding.cpp | 36++++++++++++++++++++++++++++++++++++
Asrc/encoding.hpp | 47+++++++++++++++++++++++++++++++++++++++++++++++
Msrc/menu.cpp | 6++++++
Msrc/menu.hpp | 4++++
Msrc/path.cpp | 2+-
Msrc/pkgtransaction.cpp | 25++++++++++++++++++++++---
Msrc/pkgtransaction.hpp | 3+++
Msrc/progress.cpp | 16+++++++++-------
Msrc/progress.hpp | 4++--
Msrc/reapack.cpp | 10+---------
Msrc/report.cpp | 4+++-
Msrc/transaction.cpp | 5+++--
Mtest/helper/io.cpp | 2+-
Mwin32.tup | 2+-
15 files changed, 140 insertions(+), 27 deletions(-)

diff --git a/src/config.cpp b/src/config.cpp @@ -20,6 +20,7 @@ #include "path.hpp" #ifdef _WIN32 +#undef UNICODE #include <windows.h> #else #include <swell/swell.h> diff --git a/src/encoding.cpp b/src/encoding.cpp @@ -0,0 +1,36 @@ +/* ReaPack: Package manager for REAPER + * Copyright (C) 2015 Christian Fillion + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "encoding.hpp" + +#ifdef _WIN32 +#include <windows.h> + +auto_string make_autostring(const std::string &input) +{ + const char *cstr = input.c_str(); + const int size = MultiByteToWideChar(CP_UTF8, 0, cstr, -1, nullptr, 0); + + wchar_t *output = new wchar_t[size]; + MultiByteToWideChar(CP_UTF8, 0, cstr, -1, output, size); + + auto_string string(output); + delete[] output; + + return string; +} +#endif diff --git a/src/encoding.hpp b/src/encoding.hpp @@ -0,0 +1,47 @@ +/* ReaPack: Package manager for REAPER + * Copyright (C) 2015 Christian Fillion + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef REAPACK_ENCODING_HPP +#define REAPACK_ENCODING_HPP + +// This whole file is a huge hack to support unicode on Windows +// MultiByteToWideChar is required to make file path like +// "C:\Users\Test\Downloads\Новая папка" work on Windows... + +#include <string> + +#ifdef _WIN32 + +typedef wchar_t auto_char; +typedef std::wstring auto_string; + +#define AUTO_STR(text) L##text +#define to_autostring std::to_wstring +auto_string make_autostring(const std::string &); + +#else + +typedef char auto_char; +typedef std::string auto_string; + +#define AUTO_STR(text) text +#define to_autostring std::to_string +#define make_autostring(string) string + +#endif + +#endif diff --git a/src/menu.cpp b/src/menu.cpp @@ -17,6 +17,12 @@ #include "menu.hpp" +#ifdef _WIN32 +#define MENUITEMINFO MENUITEMINFOA +#undef InsertMenuItem +#define InsertMenuItem InsertMenuItemA +#endif + Menu::Menu(HMENU handle) : m_handle(handle) { diff --git a/src/menu.hpp b/src/menu.hpp @@ -36,7 +36,11 @@ public: Menu addMenu(const char *label); private: +#ifdef _WIN32 + void append(MENUITEMINFOA &); +#else void append(MENUITEMINFO &); +#endif HMENU m_handle; unsigned int m_size; diff --git a/src/path.cpp b/src/path.cpp @@ -45,7 +45,7 @@ void Path::clear() string Path::basename() const { if(m_parts.empty()) - return string(); + return {}; return m_parts.back(); } diff --git a/src/pkgtransaction.cpp b/src/pkgtransaction.cpp @@ -17,6 +17,7 @@ #include "pkgtransaction.hpp" +#include "encoding.hpp" #include "path.hpp" #include "transaction.hpp" @@ -97,9 +98,9 @@ void PackageTransaction::commit() const string tempPath = m_transaction->prefixPath(paths.first).join(); const string targetPath = m_transaction->prefixPath(paths.second).join(); - remove(targetPath.c_str()); + RemoveFile(targetPath); - if(rename(tempPath.c_str(), targetPath.c_str())) { + if(RenameFile(tempPath, targetPath)) { m_transaction->addError(strerror(errno), targetPath); rollback(); return; @@ -115,9 +116,27 @@ void PackageTransaction::rollback() for(const PathPair &paths : m_files) { const string tempPath = m_transaction->prefixPath(paths.first).join(); - if(remove(tempPath.c_str())) + if(RemoveFile(tempPath)) m_transaction->addError(strerror(errno), tempPath); } m_files.clear(); } + +int PackageTransaction::RemoveFile(const std::string &path) +{ +#ifdef _WIN32 + return _wremove(make_autostring(path).c_str()); +#else + return remove(path.c_str()); +#endif +} + +int PackageTransaction::RenameFile(const std::string &from, const std::string &to) +{ +#ifdef _WIN32 + return _wrename(make_autostring(from).c_str(), make_autostring(to).c_str()); +#else + return rename(from.c_str(), to.c_str()); +#endif +} diff --git a/src/pkgtransaction.hpp b/src/pkgtransaction.hpp @@ -42,6 +42,9 @@ public: void cancel(); private: + static int RemoveFile(const std::string &); + static int RenameFile(const std::string &, const std::string &); + typedef std::pair<Path, Path> PathPair; void finish(); diff --git a/src/progress.cpp b/src/progress.cpp @@ -21,7 +21,7 @@ #include "resource.hpp" #include "transaction.hpp" -static const char *TITLE = "ReaPack: Download in progress"; +static const auto_char *TITLE = AUTO_STR("ReaPack: Download in progress"); using namespace std; @@ -43,7 +43,7 @@ void Progress::setTransaction(Transaction *t) if(!m_transaction) return; - SetWindowText(m_label, "Initializing..."); + SetWindowText(m_label, AUTO_STR("Initializing...")); m_transaction->downloadQueue()->onPush( bind(&Progress::addDownload, this, placeholders::_1)); @@ -77,7 +77,7 @@ void Progress::addDownload(Download *dl) updateProgress(); dl->onStart([=] { - m_currentName = dl->name(); + m_currentName = make_autostring(dl->name()); updateProgress(); }); @@ -89,15 +89,17 @@ void Progress::addDownload(Download *dl) void Progress::updateProgress() { - const string text = "Downloading " + - to_string(min(m_done + 1, m_total)) + " of " + - to_string(m_total) + ": " + m_currentName; + const auto_string text = AUTO_STR("Downloading ") + + to_autostring(min(m_done + 1, m_total)) + AUTO_STR(" of ") + + to_autostring(m_total) + AUTO_STR(": ") + m_currentName; SetWindowText(m_label, text.c_str()); const double pos = (double)m_done / m_total; const int percent = (int)(pos * 100); - const string title = string(TITLE) + " (" + to_string(percent) + "%)"; + + const auto_string title = auto_string(TITLE) + + AUTO_STR(" (") + to_autostring(percent) + AUTO_STR("%)"); SendMessage(m_progress, PBM_SETPOS, percent, 0); SetWindowText(handle(), title.c_str()); diff --git a/src/progress.hpp b/src/progress.hpp @@ -20,7 +20,7 @@ #include "dialog.hpp" -#include <string> +#include "encoding.hpp" class Download; class Transaction; @@ -40,7 +40,7 @@ private: void updateProgress(); Transaction *m_transaction; - std::string m_currentName; + auto_string m_currentName; HWND m_label; HWND m_progress; diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -113,15 +113,7 @@ void ReaPack::importRemote() if(!GetUserFileNameForRead(path, title, "ReaPackRemote")) return; -#ifdef _WIN32 - // fixes unicode path like "C:\Users\Test\Downloads\Новая папка" on Windows - wchar_t wpath[PATH_SIZE]; - MultiByteToWideChar(CP_UTF8, 0, path, sizeof(path), wpath, PATH_SIZE); - - ifstream file(wpath); -#else - ifstream file(path); -#endif + ifstream file(make_autostring(path)); if(!file) { ShowMessageBox(strerror(errno), title, 0); diff --git a/src/report.cpp b/src/report.cpp @@ -17,6 +17,7 @@ #include "report.hpp" +#include "encoding.hpp" #include "resource.hpp" #include "transaction.hpp" @@ -56,7 +57,8 @@ void Report::onInit() if(updates) formatUpdates(text); - SetDlgItemText(handle(), IDC_REPORT, text.str().c_str()); + auto_string str = make_autostring(text.str()); + SetDlgItemText(handle(), IDC_REPORT, str.c_str()); } void Report::onCommand(WPARAM wParam, LPARAM) diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -17,6 +17,7 @@ #include "transaction.hpp" +#include "encoding.hpp" #include "errors.hpp" #include "pkgtransaction.hpp" @@ -153,7 +154,7 @@ bool Transaction::saveFile(Download *dl, const Path &path) RecursiveCreateDirectory(path.dirname().c_str(), 0); const string strPath = path.join(); - ofstream file(strPath, ios_base::binary); + ofstream file(make_autostring(strPath), ios_base::binary); if(!file) { addError(strerror(errno), strPath); @@ -212,7 +213,7 @@ void Transaction::registerFiles(const vector<Path> &list) auto it = dupBegin; do { - addError("Conflict: This file is part of more than one package", + addError("Conflict: This file is owned by more than one package", it->join()); it++; diff --git a/test/helper/io.cpp b/test/helper/io.cpp @@ -6,6 +6,6 @@ using namespace std; ostream &operator<<(ostream &os, const Path &path) { - os << "\"" + path.join() + '"'; + os << "\"" << path.join() << '"'; return os; } diff --git a/win32.tup b/win32.tup @@ -7,7 +7,7 @@ CXXFLAGS := /nologo /W3 /WX /wd4996 /O2 /EHsc /MT CXXFLAGS += /Ivendor /Ivendor/WDL /Ivendor/WDL/WDL CXXFLAGS += /Ivendor/libcurl_@(WINARCH)/include CXXFLAGS += /DWDL_NO_DEFINE_MINMAX -CXXFLAGS += /DCURL_STATICLIB +CXXFLAGS += /DCURL_STATICLIB /DUNICODE LD := $(WRAP) link LDFLAGS := /nologo user32.lib