diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index e9e4302758..c2408a5541 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -41,6 +41,13 @@ private: std::vector args; }; +/* The only way to pass Unicode on Winodws with CLI is to use wide + characters interface which presents UTF-16 encoding. The rest of + OpenMW application stack assumes UTF-8 encoding, therefore this + conversion. + + For boost::filesystem::path::imbue see components/files/windowspath.cpp +*/ int wmain(int argc, wchar_t *wargv[]) { utf8argv converter(argc, wargv); char **argv = converter.get(); diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 41240ae488..6b58304a0f 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -27,6 +27,13 @@ namespace Files WindowsPath::WindowsPath(const std::string& application_name) : mName(application_name) { + /* Since on Windows boost::path.string() returns string of narrow + characters in local encoding, it is required to path::imbue() + with UTF-8 encoding (generated for empty name from boost::locale) + to handle Unicode in platform-agnostic way using std::string. + + See boost::filesystem and boost::locale reference for details. + */ boost::filesystem::path::imbue(boost::locale::generator().generate("")); } diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 44d5fe3d53..77dbcb1ee1 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -26,6 +26,13 @@ namespace bfs = boost::filesystem; namespace { + /** \brief Custom Ogre::LogListener interface implementation being + able to portably handle UTF-8 encoded path. + + Effectively this is used in conjunction with default listener, + but since on every message messageLogged() set 'skip' flag to + true, there should be no troubles sharing same file. + */ class LogListener : public Ogre::LogListener { bfs::ofstream file; @@ -87,6 +94,7 @@ namespace OgreInit Ogre::Log *log = Ogre::LogManager::getSingleton().createLog(logPath); #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + // Use custom listener only on Windows log->addListener(new LogListener(logPath)); #endif diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp index 5be99f166a..21b2d9c9a3 100644 --- a/extern/oics/tinyxml.cpp +++ b/extern/oics/tinyxml.cpp @@ -32,7 +32,7 @@ distribution. #include "tinyxml.h" #ifdef _WIN32 -#include +#include // import MultiByteToWideChar #endif diff --git a/extern/shiny/Main/Preprocessor.cpp b/extern/shiny/Main/Preprocessor.cpp index bc2957da1b..c03879d460 100644 --- a/extern/shiny/Main/Preprocessor.cpp +++ b/extern/shiny/Main/Preprocessor.cpp @@ -6,6 +6,15 @@ #include +/* + Almost exact copy of load_file_to_string policy found in + boost::wave headers with the only change that it uses + boost::filesystem facility to handle UTF-8 paths used + throughout OpenMW (bfs::fstream, bfs::path). + + Original namespace is used due to required bost::wave + internal symbols. +*/ namespace boost { namespace wave { namespace iteration_context_policies { diff --git a/libs/openengine/gui/loglistener.hpp b/libs/openengine/gui/loglistener.hpp index 20f23cf0ce..47978ba447 100644 --- a/libs/openengine/gui/loglistener.hpp +++ b/libs/openengine/gui/loglistener.hpp @@ -8,6 +8,8 @@ namespace MyGUI { + /// \brief Custom MyGUI::ILogListener interface implementation + /// being able to portably handle UTF-8 encoded path. class CustomLogListener : public ILogListener { public: diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index fa7419b32d..383d37640b 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -559,6 +559,8 @@ public: } }; +/// \brief Helper class holding data that required during +/// MyGUI log creation class LogFacility { ConsoleLogListener mConsole; @@ -615,6 +617,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool mRenderManager = new MyGUI::OgreRenderManager(); mDataManager = new MyGUI::FixedOgreDataManager(); + // Do not use default log since it don't support Unicode path on Windows. + // Instead, manually create log source using LogFacility and pass it. mLogFacility = new MyGUI::LogFacility(theLogFile, logging); LogManager::getInstance().addLogSource(mLogFacility->getSource()); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 64d65ea0da..8fcf615ba4 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -51,6 +51,10 @@ void OgreRenderer::update(float dt) void OgreRenderer::screenshot(const std::string &file) { + /* Since Ogre uses narrow character interfaces, it does not support + Unicode paths on Windows. Therefore we had to implement screenshot + saving manually. + */ namespace bfs = boost::filesystem; bfs::ofstream out(bfs::path(file), std::ios::binary);