Merge branch 'unicode-cmdline-args'

Handle Unicode command line arguments in console applications with compilers
other than MSVC too.

Closes #14580.
This commit is contained in:
Vadim Zeitlin
2017-03-15 00:33:40 +01:00
4 changed files with 78 additions and 30 deletions

View File

@@ -798,17 +798,31 @@ public:
// your compiler really, really wants main() to be in your main program (e.g. // 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. // hello.cpp). Now wxIMPLEMENT_APP should add this code if required.
// For compilers that support it, prefer to use wmain() as this ensures any // For compilers that support it, prefer to use wmain() and let the CRT parse
// Unicode strings can be passed as command line parameters and not just those // the command line for us, for the others parse it ourselves under Windows to
// representable in the current locale. // ensure that wxWidgets console applications accept arbitrary Unicode strings
#if wxUSE_UNICODE && defined(__VISUALC__) // as command line parameters and not just those representable in the current
#define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ // locale (under Unix UTF-8, capable of representing any Unicode string, is
int wmain(int argc, wchar_t **argv) \ // almost always used and there is no way to retrieve the Unicode command line
{ \ // anyhow).
wxDISABLE_DEBUG_SUPPORT(); \ #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() #else // Use standard main()
#define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \ #define wxIMPLEMENT_WXWIN_MAIN_CONSOLE \
int main(int argc, char **argv) \ int main(int argc, char **argv) \

View File

@@ -54,7 +54,7 @@ extern int WXDLLIMPEXP_BASE wxEntry(int& argc, char **argv);
// Under Windows we define additional wxEntry() overloads with signature // Under Windows we define additional wxEntry() overloads with signature
// compatible with WinMain() and not the traditional main(). // compatible with WinMain() and not the traditional main().
#if wxUSE_GUI && defined(__WINDOWS__) #ifdef __WINDOWS__
#include "wx/msw/init.h" #include "wx/msw/init.h"
#endif #endif

View File

@@ -15,6 +15,14 @@
// Windows-specific wxEntry() overload and wxIMPLEMENT_WXWIN_MAIN definition // 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() // we need HINSTANCE declaration to define WinMain()
#include "wx/msw/wrapwin.h" #include "wx/msw/wrapwin.h"
@@ -81,5 +89,6 @@ extern WXDLLIMPEXP_CORE int
} \ } \
wxIMPLEMENT_WXWIN_MAIN_BORLAND_NONSTANDARD wxIMPLEMENT_WXWIN_MAIN_BORLAND_NONSTANDARD
#endif // wxUSE_GUI
#endif // _WX_MSW_INIT_H_ #endif // _WX_MSW_INIT_H_

View File

@@ -29,7 +29,10 @@
#include "wx/utils.h" #include "wx/utils.h"
#endif //WX_PRECOMP #endif //WX_PRECOMP
#include "wx/cmdline.h" // wxCmdLineParser is only used when we can't use ::CommandLineToArgvW().
#if !wxUSE_UNICODE
#include "wx/cmdline.h"
#endif
#include "wx/dynlib.h" #include "wx/dynlib.h"
#include "wx/msw/private.h" #include "wx/msw/private.h"
@@ -194,8 +197,6 @@ int wxEntry(int& argc, wxChar **argv)
#endif // wxUSE_BASE #endif // wxUSE_BASE
#if wxUSE_GUI
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Windows-specific wxEntry // Windows-specific wxEntry
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -204,8 +205,33 @@ struct wxMSWCommandLineArguments
{ {
wxMSWCommandLineArguments() { argc = 0; argv = NULL; } wxMSWCommandLineArguments() { argc = 0; argv = NULL; }
void Init(const wxArrayString& args) // Initialize this object from the current process command line.
//
// In Unicode build prefer to use the standard function for tokenizing the
// command line, but we can't use it with narrow strings, so use our own
// approximation instead then.
#if wxUSE_UNICODE
void Init()
{ {
argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
}
~wxMSWCommandLineArguments()
{
if ( argc )
::LocalFree(argv);
}
#else // !wxUSE_UNICODE
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(); argc = args.size();
// +1 here for the terminating NULL // +1 here for the terminating NULL
@@ -232,6 +258,7 @@ struct wxMSWCommandLineArguments
wxDELETEA(argv); wxDELETEA(argv);
argc = 0; argc = 0;
} }
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
int argc; int argc;
wxChar **argv; wxChar **argv;
@@ -239,6 +266,8 @@ struct wxMSWCommandLineArguments
static wxMSWCommandLineArguments wxArgs; static wxMSWCommandLineArguments wxArgs;
#if wxUSE_GUI
// common part of wxMSW-specific wxEntryStart() and wxEntry() overloads // common part of wxMSW-specific wxEntryStart() and wxEntry() overloads
static bool static bool
wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow) wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
@@ -249,20 +278,7 @@ wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
wxApp::m_nCmdShow = nCmdShow; wxApp::m_nCmdShow = nCmdShow;
#endif #endif
// parse the command line: we can't use pCmdLine in Unicode build so it is wxArgs.Init();
// 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);
return true; return true;
} }
@@ -289,7 +305,16 @@ WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
return wxEntry(wxArgs.argc, wxArgs.argv); 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 // global HINSTANCE