summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2015-02-25 16:01:46 +0100
committerMax Kellermann <max@duempel.org>2015-03-05 10:15:10 +0100
commit65ff72cdf8d3fc8664893b55ca47fca284f34d87 (patch)
tree766eca97378aa4567d7e55aba24c4a785f956f9d
parent1da09563310a666095e93d3b4fdc5556a8a7c534 (diff)
fs/Traits: enable _UNICODE on Windows
Use wchar_t for everything on Windows. Solves a lot of filesystem charset problems.
-rw-r--r--configure.ac1
-rw-r--r--src/CommandLine.cxx13
-rw-r--r--src/PlaylistFile.cxx10
-rw-r--r--src/fs/AllocatedPath.cxx2
-rw-r--r--src/fs/Charset.cxx44
-rw-r--r--src/fs/NarrowPath.hxx20
-rw-r--r--src/fs/Traits.hxx4
-rw-r--r--src/net/SocketError.cxx25
8 files changed, 114 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index 7dbabbea0..e3aa2e7ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,6 +103,7 @@ mingw32* | windows*)
AM_CPPFLAGS="$AM_CPPFLAGS -DWIN32_LEAN_AND_MEAN"
AM_CPPFLAGS="$AM_CPPFLAGS -DWINVER=0x0600 -D_WIN32_WINNT=0x0600"
AM_CPPFLAGS="$AM_CPPFLAGS -DSTRICT"
+ AM_CPPFLAGS="$AM_CPPFLAGS -DUNICODE -D_UNICODE"
LIBS="$LIBS -lws2_32"
host_is_windows=yes
host_is_unix=no
diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx
index e87b1676f..1a55a29ea 100644
--- a/src/CommandLine.cxx
+++ b/src/CommandLine.cxx
@@ -35,6 +35,7 @@
#include "fs/Traits.hxx"
#include "fs/FileSystem.hxx"
#include "fs/StandardDirectory.hxx"
+#include "util/Macros.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/OptionDef.hxx"
@@ -337,7 +338,19 @@ parse_cmdline(int argc, char **argv, struct options *options,
if (config_file != nullptr) {
/* use specified configuration file */
+#ifdef _UNICODE
+ wchar_t buffer[MAX_PATH];
+ auto result = MultiByteToWideChar(CP_ACP, 0, config_file, -1,
+ buffer, ARRAY_SIZE(buffer));
+ if (result <= 0) {
+ error.SetLastError("MultiByteToWideChar() failed");
+ return false;
+ }
+
+ return ReadConfigFile(Path::FromFS(buffer), error);
+#else
return ReadConfigFile(Path::FromFS(config_file), error);
+#endif
}
/* use default configuration file path */
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx
index 791b2f2ed..1123f00ba 100644
--- a/src/PlaylistFile.cxx
+++ b/src/PlaylistFile.cxx
@@ -268,7 +268,17 @@ LoadPlaylistFile(const char *utf8path, Error &error)
if (*s == 0 || *s == PLAYLIST_COMMENT)
continue;
+#ifdef _UNICODE
+ wchar_t buffer[MAX_PATH];
+ auto result = MultiByteToWideChar(CP_ACP, 0, s, -1,
+ buffer, ARRAY_SIZE(buffer));
+ if (result <= 0)
+ continue;
+
+ const Path path = Path::FromFS(buffer);
+#else
const Path path = Path::FromFS(s);
+#endif
std::string uri_utf8;
diff --git a/src/fs/AllocatedPath.cxx b/src/fs/AllocatedPath.cxx
index 087cbf76a..8b03ed2f1 100644
--- a/src/fs/AllocatedPath.cxx
+++ b/src/fs/AllocatedPath.cxx
@@ -30,7 +30,7 @@ AllocatedPath::~AllocatedPath() {}
AllocatedPath
AllocatedPath::FromUTF8(const char *path_utf8)
{
-#ifdef HAVE_FS_CHARSET
+#if defined(HAVE_FS_CHARSET) || defined(WIN32)
return AllocatedPath(::PathFromUTF8(path_utf8));
#else
return FromFS(path_utf8);
diff --git a/src/fs/Charset.cxx b/src/fs/Charset.cxx
index bc6357297..b25615d42 100644
--- a/src/fs/Charset.cxx
+++ b/src/fs/Charset.cxx
@@ -25,6 +25,10 @@
#include "lib/icu/Converter.hxx"
#include "util/Error.hxx"
+#ifdef WIN32
+#include <windows.h>
+#endif
+
#include <algorithm>
#include <assert.h>
@@ -95,6 +99,24 @@ PathToUTF8(PathTraitsFS::const_pointer path_fs)
assert(path_fs != nullptr);
#endif
+#ifdef WIN32
+ int length = WideCharToMultiByte(CP_UTF8, 0, path_fs, -1, nullptr, 0,
+ nullptr, nullptr);
+ if (length <= 0)
+ return PathTraitsUTF8::string();
+
+ char *buffer = new char[length];
+ length = WideCharToMultiByte(CP_UTF8, 0, path_fs, -1, buffer, length,
+ nullptr, nullptr);
+ if (length <= 0) {
+ delete[] buffer;
+ return PathTraitsUTF8::string();
+ }
+
+ PathTraitsUTF8::string result(buffer);
+ delete[] buffer;
+ return FixSeparators(std::move(result));
+#else
#ifdef HAVE_FS_CHARSET
if (fs_converter == nullptr)
#endif
@@ -103,9 +125,10 @@ PathToUTF8(PathTraitsFS::const_pointer path_fs)
return FixSeparators(fs_converter->ToUTF8(path_fs));
#endif
+#endif
}
-#ifdef HAVE_FS_CHARSET
+#if defined(HAVE_FS_CHARSET) || defined(WIN32)
PathTraitsFS::string
PathFromUTF8(PathTraitsUTF8::const_pointer path_utf8)
@@ -115,10 +138,29 @@ PathFromUTF8(PathTraitsUTF8::const_pointer path_utf8)
assert(path_utf8 != nullptr);
#endif
+#ifdef WIN32
+ int length = MultiByteToWideChar(CP_UTF8, 0, path_utf8, -1,
+ nullptr, 0);
+ if (length <= 0)
+ return PathTraitsFS::string();
+
+ wchar_t *buffer = new wchar_t[length];
+ length = MultiByteToWideChar(CP_UTF8, 0, path_utf8, -1,
+ buffer, length);
+ if (length <= 0) {
+ delete[] buffer;
+ return PathTraitsFS::string();
+ }
+
+ PathTraitsFS::string result(buffer);
+ delete[] buffer;
+ return std::move(result);
+#else
if (fs_converter == nullptr)
return path_utf8;
return fs_converter->FromUTF8(path_utf8);
+#endif
}
#endif
diff --git a/src/fs/NarrowPath.hxx b/src/fs/NarrowPath.hxx
index 2088f9359..ad310cd5c 100644
--- a/src/fs/NarrowPath.hxx
+++ b/src/fs/NarrowPath.hxx
@@ -22,6 +22,11 @@
#include "check.h"
#include "Path.hxx"
+#include "util/Macros.hxx"
+
+#ifdef _UNICODE
+#include <windows.h>
+#endif
/**
* A path name that uses the regular (narrow) "char". This is used to
@@ -32,10 +37,25 @@ class NarrowPath {
typedef char value_type;
typedef const char *const_pointer;
+#ifdef _UNICODE
+ char value[PATH_MAX];
+#else
const_pointer value;
+#endif
public:
+#ifdef _UNICODE
+ explicit NarrowPath(Path _path) {
+ auto result = WideCharToMultiByte(CP_ACP, 0,
+ _path.c_str(), -1,
+ value, ARRAY_SIZE(value),
+ nullptr, nullptr);
+ if (result < 0)
+ value[0] = 0;
+ }
+#else
explicit NarrowPath(Path _path):value(_path.c_str()) {}
+#endif
operator const_pointer() const {
return value;
diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx
index cdd9b531d..b92330f60 100644
--- a/src/fs/Traits.hxx
+++ b/src/fs/Traits.hxx
@@ -43,7 +43,11 @@
* This class describes the nature of a native filesystem path.
*/
struct PathTraitsFS {
+#ifdef WIN32
+ typedef std::wstring string;
+#else
typedef std::string string;
+#endif
typedef string::traits_type char_traits;
typedef char_traits::char_type value_type;
typedef value_type *pointer;
diff --git a/src/net/SocketError.cxx b/src/net/SocketError.cxx
index c4c9d7a2c..efa969b1f 100644
--- a/src/net/SocketError.cxx
+++ b/src/net/SocketError.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "SocketError.hxx"
#include "util/Domain.hxx"
+#include "util/Macros.hxx"
#include <string.h>
@@ -29,13 +30,31 @@ const Domain socket_domain("socket");
SocketErrorMessage::SocketErrorMessage(socket_error_t code)
{
+#ifdef _UNICODE
+ wchar_t buffer[ARRAY_SIZE(msg)];
+#else
+ auto *buffer = msg;
+#endif
+
DWORD nbytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
- NULL, code, 0,
- (LPSTR)msg, sizeof(msg), NULL);
- if (nbytes == 0)
+ nullptr, code, 0,
+ buffer, ARRAY_SIZE(msg), nullptr);
+ if (nbytes == 0) {
strcpy(msg, "Unknown error");
+ return;
+ }
+
+#ifdef _UNICODE
+ auto length = WideCharToMultiByte(CP_UTF8, 0, buffer, -1,
+ msg, ARRAY_SIZE(msg),
+ nullptr, nullptr);
+ if (length <= 0) {
+ strcpy(msg, "WideCharToMultiByte() error");
+ return;
+ }
+#endif
}
#else