From 2a07f3a0d58fc5785652bc3deee5e742dac16f05 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Wed, 23 May 2018 17:21:01 +0200
Subject: [PATCH] Firmware updater: Fix filename encoding on Windows

---
 xs/src/avrdude/fileio.c              | 24 ++++++++++++++++++++++--
 xs/src/slic3r/GUI/FirmwareDialog.cpp |  6 ++++--
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/xs/src/avrdude/fileio.c b/xs/src/avrdude/fileio.c
index f2d617823..2ed19bd15 100644
--- a/xs/src/avrdude/fileio.c
+++ b/xs/src/avrdude/fileio.c
@@ -45,6 +45,8 @@
 
 #define MAX_LINE_LEN 256  /* max line length for ASCII format input files */
 
+#define MAX_MODE_LEN 32  // For fopen_utf8()
+
 
 struct ihexrec {
   unsigned char    reclen;
@@ -100,6 +102,23 @@ static int fmt_autodetect(char * fname);
 
 
 
+static FILE *fopen_utf8(const char *filename, const char *mode)
+{
+  // On Windows we need to convert the filename to UTF-16
+#if defined(WIN32NATIVE)
+  static wchar_t fname_buffer[PATH_MAX];
+  static wchar_t mode_buffer[MAX_MODE_LEN];
+
+  if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
+  if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
+
+  return _wfopen(fname_buffer, mode_buffer);
+#else
+  return fopen(filename, mode);
+#endif
+}
+
+
 char * fmtstr(FILEFMT format)
 {
   switch (format) {
@@ -1368,10 +1387,11 @@ static int fmt_autodetect(char * fname)
   int first = 1;
 
 #if defined(WIN32NATIVE)
-  f = fopen(fname, "r");
+  f = fopen_utf8(fname, "r");
 #else
   f = fopen(fname, "rb");
 #endif
+
   if (f == NULL) {
     avrdude_message(MSG_INFO, "%s: error opening %s: %s\n",
             progname, fname, strerror(errno));
@@ -1533,7 +1553,7 @@ int fileio(int op, char * filename, FILEFMT format,
 
   if (format != FMT_IMM) {
     if (!using_stdio) {
-      f = fopen(fname, fio.mode);
+      f = fopen_utf8(fname, fio.mode);
       if (f == NULL) {
         avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
                 progname, fio.iodesc, fname, strerror(errno));
diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/xs/src/slic3r/GUI/FirmwareDialog.cpp
index 8ea9d2d6e..e57ec6326 100644
--- a/xs/src/slic3r/GUI/FirmwareDialog.cpp
+++ b/xs/src/slic3r/GUI/FirmwareDialog.cpp
@@ -163,6 +163,7 @@ void FirmwareDialog::priv::perform_upload()
 
 	flashing_status(true);
 
+	const auto filename_utf8 = filename.utf8_str();
 	std::vector<std::string> args {{
 		"-v",
 		"-p", "atmega2560",
@@ -170,7 +171,7 @@ void FirmwareDialog::priv::perform_upload()
 		"-P", port,
 		"-b", "115200",   // XXX: is this ok to hardcode?
 		"-D",
-		"-U", (boost::format("flash:w:%1%:i") % filename.ToStdString()).str()
+		"-U", (boost::format("flash:w:%1%:i") % filename_utf8.data()).str()
 	}};
 
 	BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
@@ -187,8 +188,9 @@ void FirmwareDialog::priv::perform_upload()
 		.args(args)
 		.on_message(std::move([q](const char *msg, unsigned /* size */) {
 			auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
+			auto wxmsg = wxString::FromUTF8(msg);
 			evt->SetExtraLong(AE_MESSAGE);
-			evt->SetString(msg);
+			evt->SetString(std::move(wxmsg));
 			wxQueueEvent(q, evt);
 		}))
 		.on_progress(std::move([q](const char * /* task */, unsigned progress) {