From 5a423d124cb0ad8e861b35470e85647827e9cf8b Mon Sep 17 00:00:00 2001 From: Edgar Velazquez-Armendariz Date: Thu, 18 Oct 2012 15:14:11 -0400 Subject: [PATCH] Added Unicode support for the Windows command line tools. --- CMakeLists.txt | 5 ++ SConstruct | 6 +- data/windows/wmain_stub.cpp | 110 +++++++++++++++++++++++++++++++++++ src/converter/CMakeLists.txt | 2 +- src/converter/SConscript | 4 +- src/converter/mtsimport.cpp | 2 +- src/mitsuba/CMakeLists.txt | 6 +- src/mitsuba/SConscript | 8 +-- src/mitsuba/mitsuba.cpp | 12 +++- src/mitsuba/mtssrv.cpp | 12 +++- src/mitsuba/mtsutil.cpp | 4 +- 11 files changed, 150 insertions(+), 21 deletions(-) create mode 100644 data/windows/wmain_stub.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ba178d1..4c3e42be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,8 +85,13 @@ endif() # Additional files to add to main executables if(APPLE) set(MTS_DARWIN_STUB "${CMAKE_CURRENT_SOURCE_DIR}/src/mitsuba/darwin_stub.mm") + set(MTS_WINDOWS_STUB "") +elseif(WIN32) + set(MTS_DARWIN_STUB "") + set(MTS_WINDOWS_STUB "${CMAKE_CURRENT_SOURCE_DIR}/data/windows/wmain_stub.cpp") else() set(MTS_DARWIN_STUB "") + set(MTS_WINDOWS_STUB "") endif() diff --git a/SConstruct b/SConstruct index 44f5ef65..c881913a 100644 --- a/SConstruct +++ b/SConstruct @@ -6,9 +6,10 @@ import os resources = [] plugins = [] stubs = [] +winstubs = [] Export('SCons', 'sys', 'os', 'glob', 'resources', - 'plugins', 'stubs') + 'plugins', 'stubs', 'winstubs') # Configure the build framework env = SConscript('build/SConscript.configure') @@ -18,6 +19,9 @@ Export('env') if sys.platform == 'win32': # Set an application icon on Windows resources += [ env.RES('data/windows/mitsuba_res.rc') ] + # Convert the command line args from UTF-8 to UTF-16 + winstubs += [os.path.abspath('data/windows/wmain_stub.cpp')] + Export('winstubs') def build(scriptFile, exports = [], duplicate = 0): dirname = '/'.join(os.path.dirname(scriptFile).split('/')[1:]) diff --git a/data/windows/wmain_stub.cpp b/data/windows/wmain_stub.cpp new file mode 100644 index 00000000..3580bbad --- /dev/null +++ b/data/windows/wmain_stub.cpp @@ -0,0 +1,110 @@ +/* + This file is part of Mitsuba, a physically based rendering system. + + Copyright (c) 2007-2012 by Wenzel Jakob and others. + + Mitsuba is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License Version 3 + as published by the Free Software Foundation. + + Mitsuba 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#if defined(__WINDOWS__) + +// Stub for generating UTF-8 command line arguments from wmain (UTF-16) +#include + +extern int mts_main(int argc, char **argv); + + +namespace { + +class ArgsUTF8 { +public: + ArgsUTF8(int argc, wchar_t *wargv[]) : + m_argc(-1), m_argv(NULL), m_data(NULL) + { + if (argc > 0) + m_argc = argc; + else + return; + + m_argv = new char*[argc]; + int total = 0; + + // Pass 1: get the lengths of each converted string an allocate data + for (int i = 0; i < argc; ++i) { + const int lenUtf8 = WideCharToMultiByte(CP_UTF8, 0, + wargv[i], -1, NULL, 0, NULL, NULL); + if (lenUtf8 != 0) { + total += lenUtf8; + m_argv[i] = reinterpret_cast(lenUtf8); + } else { + m_argc = i; + break; + } + } + + if (m_argc < 1) + return; + + m_data = new char[total]; + int currOffset = 0; + + // Pass 2: perform the conversion + for (int i = 0; i < m_argc; ++i) { + int lenUtf8 = reinterpret_cast(m_argv[i]); + m_argv[i] = m_data + currOffset; + lenUtf8 = WideCharToMultiByte(CP_UTF8, 0, + wargv[i], -1, m_argv[i], lenUtf8, NULL, NULL); + if (lenUtf8 != 0) { + currOffset += lenUtf8; + } else { + m_argc = i; + return; + } + } + } + + ~ArgsUTF8() { + if (m_argv != NULL) { + delete [] m_argv; + } + if (m_data != NULL) { + delete [] m_data; + } + } + + inline int argc() const { + return m_argc; + } + + inline char** argv() const { + return m_argv; + } + +private: + int m_argc; + char** m_argv; + char* m_data; +}; + +} // namespace + + +// MSDN Documentation: +// http://msdn.microsoft.com/en-US/library/fzc2cy7w%28v=vs.110%29.aspx +int wmain(int argc, wchar_t *wargv[], wchar_t *envp[]) { + ArgsUTF8 argsUTF8(argc, wargv); + return mts_main(argsUTF8.argc(), argsUTF8.argv()); +} + +#endif // __WINDOWS__ diff --git a/src/converter/CMakeLists.txt b/src/converter/CMakeLists.txt index 1e8fd414..0bfabe44 100644 --- a/src/converter/CMakeLists.txt +++ b/src/converter/CMakeLists.txt @@ -25,5 +25,5 @@ target_link_libraries(mtsconverter_lib ${COLLADA_LIBRARIES} ${XERCES_LIBRARIES} ${OPENGL_glu_LIBRARY}) add_mts_exe(mtsimport mtsimport.cpp ${SRCS} - ${MTS_DARWIN_STUB} LINK_LIBRARIES mtsconverter_lib + ${MTS_DARWIN_STUB} ${MTS_WINDOWS_STUB} LINK_LIBRARIES mtsconverter_lib RES_DESCRIPTION "Mitsuba COLLADA 1.4 & Wavefront OBJ importer") diff --git a/src/converter/SConscript b/src/converter/SConscript index 626a9906..f7112e89 100644 --- a/src/converter/SConscript +++ b/src/converter/SConscript @@ -1,4 +1,4 @@ -Import('mainEnv', 'hasCollada', 'stubs') +Import('mainEnv', 'hasCollada', 'stubs', 'winstubs') converter_objects = [] @@ -18,7 +18,7 @@ if hasCollada: colladaEnv.StaticObject('obj.cpp'), colladaEnv.StaticObject('converter.cpp') ] - colladaEnv.Program('mtsimport', stubs + ['mtsimport.cpp'] + colladaEnv.Program('mtsimport', stubs + winstubs + ['mtsimport.cpp'] + converter_objects) Return('converter_objects') diff --git a/src/converter/mtsimport.cpp b/src/converter/mtsimport.cpp index ba3b74c3..f7d1ff31 100644 --- a/src/converter/mtsimport.cpp +++ b/src/converter/mtsimport.cpp @@ -241,7 +241,7 @@ int mts_main(int argc, char **argv) { return retval; } -#if !defined(__OSX__) +#if !defined(__OSX__) && !defined(__WINDOWS__) int main(int argc, char **argv) { return mts_main(argc, argv); } diff --git a/src/mitsuba/CMakeLists.txt b/src/mitsuba/CMakeLists.txt index 36d6ca8b..6baf6e4d 100644 --- a/src/mitsuba/CMakeLists.txt +++ b/src/mitsuba/CMakeLists.txt @@ -5,9 +5,9 @@ endif() include_directories(${XERCES_INCLUDE_DIRS}) -add_mts_exe(mtssrv mtssrv.cpp +add_mts_exe(mtssrv mtssrv.cpp ${MTS_WINDOWS_STUB} RES_DESCRIPTION "Mitsuba compute node application") -add_mts_exe(mitsuba mitsuba.cpp +add_mts_exe(mitsuba mitsuba.cpp ${MTS_WINDOWS_STUB} RES_DESCRIPTION "Mitsuba command line interface frontend") -add_mts_exe(mtsutil mtsutil.cpp ${MTS_DARWIN_STUB} +add_mts_exe(mtsutil mtsutil.cpp ${MTS_DARWIN_STUB} ${MTS_WINDOWS_STUB} RES_DESCRIPTION "Mitsuba utility launcher") diff --git a/src/mitsuba/SConscript b/src/mitsuba/SConscript index 9a2abd4d..82bffc2a 100644 --- a/src/mitsuba/SConscript +++ b/src/mitsuba/SConscript @@ -1,4 +1,4 @@ -Import('sys', 'env', 'hasCollada', 'stubs') +Import('sys', 'env', 'hasCollada', 'stubs', 'winstubs') # Create an environment with Xerces and OpenGL mainEnv = env.Clone() @@ -24,10 +24,10 @@ if sys.platform == 'darwin': stubs += [mainEnv_osx.StaticObject('darwin_stub.mm')] mainEnv.Append(LINKFLAGS=['-Xlinker', '-rpath', '-Xlinker', '@executable_path/../Frameworks']) -mainEnv.Program('mtsutil', stubs + ['mtsutil.cpp']) +mainEnv.Program('mtsutil', stubs + winstubs + ['mtsutil.cpp']) # Build the command-line+GUI interface -mainEnv.Program('mtssrv', ['mtssrv.cpp']) -mainEnv.Program('mitsuba', ['mitsuba.cpp']) +mainEnv.Program('mtssrv', winstubs + ['mtssrv.cpp']) +mainEnv.Program('mitsuba', winstubs + ['mitsuba.cpp']) Return('mainEnv') diff --git a/src/mitsuba/mitsuba.cpp b/src/mitsuba/mitsuba.cpp index f81fcebf..44a4c3c6 100644 --- a/src/mitsuba/mitsuba.cpp +++ b/src/mitsuba/mitsuba.cpp @@ -124,7 +124,7 @@ private: int m_timeout; }; -int mts_main(int argc, char **argv) { +int mitsuba_app(int argc, char **argv) { char optchar, *end_ptr = NULL; try { @@ -397,7 +397,7 @@ int mts_main(int argc, char **argv) { return 0; } -int main(int argc, char **argv) { +int mts_main(int argc, char **argv) { /* Initialize the core framework */ Class::staticInitialization(); Object::staticInitialization(); @@ -426,7 +426,7 @@ int main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); #endif - int retval = mts_main(argc, argv); + int retval = mitsuba_app(argc, argv); /* Shutdown the core framework */ SceneHandler::staticShutdown(); @@ -449,3 +449,9 @@ int main(int argc, char **argv) { return retval; } + +#if !defined(__WINDOWS__) +int main(int argc, char **argv) { + return mts_main(argc, argv); +} +#endif diff --git a/src/mitsuba/mtssrv.cpp b/src/mitsuba/mtssrv.cpp index e9d57fa6..bb931ed6 100644 --- a/src/mitsuba/mtssrv.cpp +++ b/src/mitsuba/mtssrv.cpp @@ -90,7 +90,7 @@ void collect_zombies(int s) { } #endif -int mts_main(int argc, char **argv) { +int mtssrv(int argc, char **argv) { char optchar, *end_ptr = NULL; try { @@ -382,7 +382,7 @@ int mts_main(int argc, char **argv) { return 0; } -int main(int argc, char **argv) { +int mts_main(int argc, char **argv) { /* Initialize the core framework */ Class::staticInitialization(); Object::staticInitialization(); @@ -409,7 +409,7 @@ int main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); #endif - int retval = mts_main(argc, argv); + int retval = mtssrv(argc, argv); /* Shutdown the core framework */ SHVector::staticShutdown(); @@ -432,3 +432,9 @@ int main(int argc, char **argv) { return retval; } + +#if !defined(__WINDOWS__) +int main(int argc, char **argv) { + return mts_main(argc, argv); +} +#endif diff --git a/src/mitsuba/mtsutil.cpp b/src/mitsuba/mtsutil.cpp index 0bc79720..282355ce 100644 --- a/src/mitsuba/mtsutil.cpp +++ b/src/mitsuba/mtsutil.cpp @@ -435,10 +435,8 @@ int mts_main(int argc, char **argv) { return retval; } -#if !defined(__OSX__) +#if !defined(__OSX__) && !defined(__WINDOWS__) int main(int argc, char **argv) { return mts_main(argc, argv); } #endif - -