From 5b74044c3e57c703bae746a9a8f6dc3aab51c33f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 11 Mar 2017 01:04:31 +0100 Subject: [PATCH] Use Unicode command line when not using wmain() under Windows While we use wmain() for the compilers that provide it since the changes of bfa78c63b9045c2a594ca6f04dc26a70c21f5f42, we still didn't handle Unicode command line arguments not representable in the current Windows code page correctly when using other compilers (e.g. MinGW). Now use Win32 ::GetCommandLine() function for them and parse the command line ourselves instead of relying on non-Unicode-friendly main() arguments which can't represent arbitrary Unicode strings when not using UTF-8 (which is never the case under Windows). --- include/wx/app.h | 34 ++++++++++++++++++++++++---------- include/wx/init.h | 2 +- include/wx/msw/init.h | 9 +++++++++ src/msw/main.cpp | 41 +++++++++++++++++++++++------------------ 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/include/wx/app.h b/include/wx/app.h index bc17b94b93..0201c8c7b2 100644 --- a/include/wx/app.h +++ b/include/wx/app.h @@ -798,17 +798,31 @@ public: // your compiler really, really wants main() to be in your main program (e.g. // hello.cpp). Now wxIMPLEMENT_APP should add this code if required. -// For compilers that support it, prefer to use wmain() as this ensures any -// Unicode strings can be passed as command line parameters and not just those -// representable in the current locale. -#if wxUSE_UNICODE && defined(__VISUALC__) - #define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ - int wmain(int argc, wchar_t **argv) \ - { \ - wxDISABLE_DEBUG_SUPPORT(); \ +// For compilers that support it, prefer to use wmain() and let the CRT parse +// the command line for us, for the others parse it ourselves under Windows to +// ensure that wxWidgets console applications accept arbitrary Unicode strings +// as command line parameters and not just those representable in the current +// locale (under Unix UTF-8, capable of representing any Unicode string, is +// almost always used and there is no way to retrieve the Unicode command line +// anyhow). +#if wxUSE_UNICODE && defined(__WINDOWS__) + #ifdef __VISUALC__ + #define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ + int wmain(int argc, wchar_t **argv) \ + { \ + wxDISABLE_DEBUG_SUPPORT(); \ \ - return wxEntry(argc, argv); \ - } + return wxEntry(argc, argv); \ + } + #else // No wmain(), use main() but don't trust its arguments. + #define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ + int main(int, char **) \ + { \ + wxDISABLE_DEBUG_SUPPORT(); \ + \ + return wxEntry(); \ + } + #endif #else // Use standard main() #define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ int main(int argc, char **argv) \ diff --git a/include/wx/init.h b/include/wx/init.h index 0810cceb49..ea542aea42 100644 --- a/include/wx/init.h +++ b/include/wx/init.h @@ -54,7 +54,7 @@ extern int WXDLLIMPEXP_BASE wxEntry(int& argc, char **argv); // Under Windows we define additional wxEntry() overloads with signature // compatible with WinMain() and not the traditional main(). -#if wxUSE_GUI && defined(__WINDOWS__) +#ifdef __WINDOWS__ #include "wx/msw/init.h" #endif diff --git a/include/wx/msw/init.h b/include/wx/msw/init.h index 847fb0888c..eb3fead314 100644 --- a/include/wx/msw/init.h +++ b/include/wx/msw/init.h @@ -15,6 +15,14 @@ // Windows-specific wxEntry() overload and wxIMPLEMENT_WXWIN_MAIN definition // ---------------------------------------------------------------------------- +// wxEntry() overload using the command line for the current process, instead +// of argc/argv provided by the CRT. This is only really useful when using +// Unicode with a compiler not providing wmain() or similar entry point, but is +// always provided for consistency. +extern int WXDLLIMPEXP_BASE wxEntry(); + +#if wxUSE_GUI + // we need HINSTANCE declaration to define WinMain() #include "wx/msw/wrapwin.h" @@ -81,5 +89,6 @@ extern WXDLLIMPEXP_CORE int } \ wxIMPLEMENT_WXWIN_MAIN_BORLAND_NONSTANDARD +#endif // wxUSE_GUI #endif // _WX_MSW_INIT_H_ diff --git a/src/msw/main.cpp b/src/msw/main.cpp index c2bda5e531..f2ea2860b7 100644 --- a/src/msw/main.cpp +++ b/src/msw/main.cpp @@ -194,8 +194,6 @@ int wxEntry(int& argc, wxChar **argv) #endif // wxUSE_BASE -#if wxUSE_GUI - // ---------------------------------------------------------------------------- // Windows-specific wxEntry // ---------------------------------------------------------------------------- @@ -204,8 +202,17 @@ struct wxMSWCommandLineArguments { wxMSWCommandLineArguments() { argc = 0; argv = NULL; } - void Init(const wxArrayString& args) + // Initialize this object from the current process command line. + void Init() { + // Get the command line. + const wxChar* const cmdLine = ::GetCommandLine(); + if ( !cmdLine ) + return; + + // And tokenize it. + const wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdLine); + argc = args.size(); // +1 here for the terminating NULL @@ -239,6 +246,8 @@ struct wxMSWCommandLineArguments static wxMSWCommandLineArguments wxArgs; +#if wxUSE_GUI + // common part of wxMSW-specific wxEntryStart() and wxEntry() overloads static bool wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow) @@ -249,20 +258,7 @@ wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow) wxApp::m_nCmdShow = nCmdShow; #endif - // parse the command line: we can't use pCmdLine in Unicode build so it is - // simpler to never use it at all (this also results in a more correct - // argv[0]) - - // break the command line in words - wxArrayString args; - - const wxChar *cmdLine = ::GetCommandLine(); - if ( cmdLine ) - { - args = wxCmdLineParser::ConvertStringToArgs(cmdLine); - } - - wxArgs.Init(args); + wxArgs.Init(); return true; } @@ -289,7 +285,16 @@ WXDLLEXPORT int wxEntry(HINSTANCE hInstance, return wxEntry(wxArgs.argc, wxArgs.argv); } -#endif // wxUSE_GUI +#else // !wxUSE_GUI + +int wxEntry() +{ + wxArgs.Init(); + + return wxEntry(wxArgs.argc, wxArgs.argv); +} + +#endif // wxUSE_GUI/!wxUSE_GUI // ---------------------------------------------------------------------------- // global HINSTANCE