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:
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