]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/cmdline.cpp
Return NULL from wxWindow::GetCapture() when the capture is being lost.
[wxWidgets.git] / src / common / cmdline.cpp
index 30bf7f09d6e50d1db4b6b8a767d3e475592c0649..e8892831ac90a1f71d1914d7aa51b37818134297 100644 (file)
@@ -4,7 +4,6 @@
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     05.01.00
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     05.01.00
-// RCS-ID:      $Id$
 // Copyright:   (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 // Copyright:   (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 #if wxUSE_CMDLINE_PARSER
 
 #include <ctype.h>
 #if wxUSE_CMDLINE_PARSER
 
 #include <ctype.h>
+#include <locale.h>             // for LC_ALL
 
 #include "wx/datetime.h"
 #include "wx/msgout.h"
 #include "wx/filename.h"
 #include "wx/apptrait.h"
 
 #include "wx/datetime.h"
 #include "wx/msgout.h"
 #include "wx/filename.h"
 #include "wx/apptrait.h"
+#include "wx/scopeguard.h"
 
 // ----------------------------------------------------------------------------
 // private functions
 
 // ----------------------------------------------------------------------------
 // private functions
 
 static wxString GetTypeName(wxCmdLineParamType type);
 
 
 static wxString GetTypeName(wxCmdLineParamType type);
 
-static wxString GetOptionName(const wxChar *p, const wxChar *allowedChars);
+static wxString GetOptionName(wxString::const_iterator p,
+                              wxString::const_iterator end,
+                              const wxChar *allowedChars);
 
 
-static wxString GetShortOptionName(const wxChar *p);
+static wxString GetShortOptionName(wxString::const_iterator p,
+                                   wxString::const_iterator end);
 
 
-static wxString GetLongOptionName(const wxChar *p);
+static wxString GetLongOptionName(wxString::const_iterator p,
+                                  wxString::const_iterator end);
 
 // ----------------------------------------------------------------------------
 // private structs
 
 // ----------------------------------------------------------------------------
 // private structs
@@ -69,21 +74,27 @@ struct wxCmdLineOption
                     wxCmdLineParamType typ,
                     int fl)
     {
                     wxCmdLineParamType typ,
                     int fl)
     {
-        wxASSERT_MSG( !shrt.empty() || !lng.empty(),
-                      _T("option should have at least one name") );
+        // wxCMD_LINE_USAGE_TEXT uses only description, shortName and longName is empty
+        if ( k != wxCMD_LINE_USAGE_TEXT )
+        {
+            wxASSERT_MSG
+            (
+                !shrt.empty() || !lng.empty(),
+                 wxT("option should have at least one name")
+            );
 
 
-        wxASSERT_MSG
+            wxASSERT_MSG
             (
             (
-                GetShortOptionName(shrt).Len() == shrt.Len(),
+                GetShortOptionName(shrt.begin(), shrt.end()).Len() == shrt.Len(),
                 wxT("Short option contains invalid characters")
             );
 
                 wxT("Short option contains invalid characters")
             );
 
-        wxASSERT_MSG
+            wxASSERT_MSG
             (
             (
-                GetLongOptionName(lng).Len() == lng.Len(),
+                GetLongOptionName(lng.begin(), lng.end()).Len() == lng.Len(),
                 wxT("Long option contains invalid characters")
             );
                 wxT("Long option contains invalid characters")
             );
-
+        }
 
         kind = k;
 
 
         kind = k;
 
@@ -94,7 +105,7 @@ struct wxCmdLineOption
         type = typ;
         flags = fl;
 
         type = typ;
         flags = fl;
 
-        m_hasVal = false;
+        Reset();
     }
 
     // can't use union easily here, so just store all possible data fields, we
     }
 
     // can't use union easily here, so just store all possible data fields, we
@@ -104,9 +115,11 @@ struct wxCmdLineOption
 
     void Check(wxCmdLineParamType WXUNUSED_UNLESS_DEBUG(typ)) const
     {
 
     void Check(wxCmdLineParamType WXUNUSED_UNLESS_DEBUG(typ)) const
     {
-        wxASSERT_MSG( type == typ, _T("type mismatch in wxCmdLineOption") );
+        wxASSERT_MSG( type == typ, wxT("type mismatch in wxCmdLineOption") );
     }
 
     }
 
+    double GetDoubleVal() const
+        { Check(wxCMD_LINE_VAL_DOUBLE); return m_doubleVal; }
     long GetLongVal() const
         { Check(wxCMD_LINE_VAL_NUMBER); return m_longVal; }
     const wxString& GetStrVal() const
     long GetLongVal() const
         { Check(wxCMD_LINE_VAL_NUMBER); return m_longVal; }
     const wxString& GetStrVal() const
@@ -116,6 +129,8 @@ struct wxCmdLineOption
         { Check(wxCMD_LINE_VAL_DATE);   return m_dateVal; }
 #endif // wxUSE_DATETIME
 
         { Check(wxCMD_LINE_VAL_DATE);   return m_dateVal; }
 #endif // wxUSE_DATETIME
 
+    void SetDoubleVal(double val)
+        { Check(wxCMD_LINE_VAL_DOUBLE); m_doubleVal = val; m_hasVal = true; }
     void SetLongVal(long val)
         { Check(wxCMD_LINE_VAL_NUMBER); m_longVal = val; m_hasVal = true; }
     void SetStrVal(const wxString& val)
     void SetLongVal(long val)
         { Check(wxCMD_LINE_VAL_NUMBER); m_longVal = val; m_hasVal = true; }
     void SetStrVal(const wxString& val)
@@ -125,9 +140,19 @@ struct wxCmdLineOption
         { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = true; }
 #endif // wxUSE_DATETIME
 
         { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = true; }
 #endif // wxUSE_DATETIME
 
-    void SetHasValue(bool hasValue = true) { m_hasVal = hasValue; }
+    void SetHasValue() { m_hasVal = true; }
     bool HasValue() const { return m_hasVal; }
 
     bool HasValue() const { return m_hasVal; }
 
+    void SetNegated() { m_isNegated = true; }
+    bool IsNegated() const { return m_isNegated; }
+
+    // Reset to the initial state, called before parsing another command line.
+    void Reset()
+    {
+        m_hasVal =
+        m_isNegated = false;
+    }
+
 public:
     wxCmdLineEntryType kind;
     wxString shortName,
 public:
     wxCmdLineEntryType kind;
     wxString shortName,
@@ -138,7 +163,9 @@ public:
 
 private:
     bool m_hasVal;
 
 private:
     bool m_hasVal;
+    bool m_isNegated;
 
 
+    double m_doubleVal;
     long m_longVal;
     wxString m_strVal;
 #if wxUSE_DATETIME
     long m_longVal;
     wxString m_strVal;
 #if wxUSE_DATETIME
@@ -189,6 +216,7 @@ struct wxCmdLineParserData
     void SetArguments(int argc, char **argv);
 #if wxUSE_UNICODE
     void SetArguments(int argc, wxChar **argv);
     void SetArguments(int argc, char **argv);
 #if wxUSE_UNICODE
     void SetArguments(int argc, wxChar **argv);
+    void SetArguments(int argc, const wxCmdLineArgsArray& argv);
 #endif // wxUSE_UNICODE
     void SetArguments(const wxString& cmdline);
 
 #endif // wxUSE_UNICODE
     void SetArguments(const wxString& cmdline);
 
@@ -208,19 +236,51 @@ wxCmdLineParserData::wxCmdLineParserData()
 {
     m_enableLongOptions = true;
 #ifdef __UNIX_LIKE__
 {
     m_enableLongOptions = true;
 #ifdef __UNIX_LIKE__
-    m_switchChars = _T("-");
+    m_switchChars = wxT("-");
 #else // !Unix
 #else // !Unix
-    m_switchChars = _T("/-");
+    m_switchChars = wxT("/-");
 #endif
 }
 
 #endif
 }
 
+namespace
+{
+
+// Small helper function setting locale for all categories.
+//
+// We define it because wxSetlocale() can't be easily used with wxScopeGuard as
+// it has several overloads -- while this one can.
+inline char *SetAllLocaleFacets(const char *loc)
+{
+    return wxSetlocale(LC_ALL, loc);
+}
+
+} // private namespace
+
 void wxCmdLineParserData::SetArguments(int argc, char **argv)
 {
     m_arguments.clear();
 
 void wxCmdLineParserData::SetArguments(int argc, char **argv)
 {
     m_arguments.clear();
 
+    // Command-line arguments are supposed to be in the user locale encoding
+    // (what else?) but wxLocale probably wasn't initialized yet as we're
+    // called early during the program startup and so our locale might not have
+    // been set from the environment yet. To work around this problem we
+    // temporarily change the locale here. The only drawback is that changing
+    // the locale is thread-unsafe but precisely because we're called so early
+    // it's hopefully safe to assume that no other threads had been created yet.
+    char * const locOld = SetAllLocaleFacets("");
+    wxON_BLOCK_EXIT1( SetAllLocaleFacets, locOld );
+
     for ( int n = 0; n < argc; n++ )
     {
     for ( int n = 0; n < argc; n++ )
     {
-        m_arguments.push_back(wxString::FromAscii(argv[n]));
+        // try to interpret the string as being in the current locale
+        wxString arg(argv[n]);
+
+        // but just in case we guessed wrongly and the conversion failed, do
+        // try to salvage at least something
+        if ( arg.empty() && argv[n][0] != '\0' )
+            arg = wxString(argv[n], wxConvISO8859_1);
+
+        m_arguments.push_back(arg);
     }
 }
 
     }
 }
 
@@ -236,6 +296,12 @@ void wxCmdLineParserData::SetArguments(int argc, wxChar **argv)
     }
 }
 
     }
 }
 
+void wxCmdLineParserData::SetArguments(int WXUNUSED(argc),
+                                       const wxCmdLineArgsArray& argv)
+{
+    m_arguments = argv.GetArguments();
+}
+
 #endif // wxUSE_UNICODE
 
 void wxCmdLineParserData::SetArguments(const wxString& cmdLine)
 #endif // wxUSE_UNICODE
 
 void wxCmdLineParserData::SetArguments(const wxString& cmdLine)
@@ -306,6 +372,11 @@ void wxCmdLineParser::SetCmdLine(int argc, wxChar **argv)
     m_data->SetArguments(argc, argv);
 }
 
     m_data->SetArguments(argc, argv);
 }
 
+void wxCmdLineParser::SetCmdLine(int argc, const wxCmdLineArgsArray& argv)
+{
+    m_data->SetArguments(argc, argv);
+}
+
 #endif // wxUSE_UNICODE
 
 void wxCmdLineParser::SetCmdLine(const wxString& cmdline)
 #endif // wxUSE_UNICODE
 
 void wxCmdLineParser::SetCmdLine(const wxString& cmdline)
@@ -332,7 +403,7 @@ void wxCmdLineParser::EnableLongOptions(bool enable)
     m_data->m_enableLongOptions = enable;
 }
 
     m_data->m_enableLongOptions = enable;
 }
 
-bool wxCmdLineParser::AreLongOptionsEnabled()
+bool wxCmdLineParser::AreLongOptionsEnabled() const
 {
     return m_data->m_enableLongOptions;
 }
 {
     return m_data->m_enableLongOptions;
 }
@@ -353,21 +424,28 @@ void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc *desc)
         switch ( desc->kind )
         {
             case wxCMD_LINE_SWITCH:
         switch ( desc->kind )
         {
             case wxCMD_LINE_SWITCH:
-                AddSwitch(desc->shortName, desc->longName, desc->description,
+                AddSwitch(desc->shortName, desc->longName,
+                          wxGetTranslation(desc->description),
                           desc->flags);
                 break;
 
             case wxCMD_LINE_OPTION:
                           desc->flags);
                 break;
 
             case wxCMD_LINE_OPTION:
-                AddOption(desc->shortName, desc->longName, desc->description,
+                AddOption(desc->shortName, desc->longName,
+                          wxGetTranslation(desc->description),
                           desc->type, desc->flags);
                 break;
 
             case wxCMD_LINE_PARAM:
                           desc->type, desc->flags);
                 break;
 
             case wxCMD_LINE_PARAM:
-                AddParam(desc->description, desc->type, desc->flags);
+                AddParam(wxGetTranslation(desc->description),
+                         desc->type, desc->flags);
+                break;
+
+            case wxCMD_LINE_USAGE_TEXT:
+                AddUsageText(wxGetTranslation(desc->description));
                 break;
 
             default:
                 break;
 
             default:
-                wxFAIL_MSG( _T("unknown command line entry type") );
+                wxFAIL_MSG( wxT("unknown command line entry type") );
                 // still fall through
 
             case wxCMD_LINE_NONE:
                 // still fall through
 
             case wxCMD_LINE_NONE:
@@ -382,7 +460,7 @@ void wxCmdLineParser::AddSwitch(const wxString& shortName,
                                 int flags)
 {
     wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
                                 int flags)
 {
     wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
-                  _T("duplicate switch") );
+                  wxT("duplicate switch") );
 
     wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_SWITCH,
                                                   shortName, longName, desc,
 
     wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_SWITCH,
                                                   shortName, longName, desc,
@@ -398,7 +476,7 @@ void wxCmdLineParser::AddOption(const wxString& shortName,
                                 int flags)
 {
     wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
                                 int flags)
 {
     wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
-                  _T("duplicate option") );
+                  wxT("duplicate option") );
 
     wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_OPTION,
                                                   shortName, longName, desc,
 
     wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_OPTION,
                                                   shortName, longName, desc,
@@ -413,44 +491,60 @@ void wxCmdLineParser::AddParam(const wxString& desc,
 {
     // do some consistency checks: a required parameter can't follow an
     // optional one and nothing should follow a parameter with MULTIPLE flag
 {
     // do some consistency checks: a required parameter can't follow an
     // optional one and nothing should follow a parameter with MULTIPLE flag
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
     if ( !m_data->m_paramDesc.IsEmpty() )
     {
         wxCmdLineParam& param = m_data->m_paramDesc.Last();
 
         wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE),
     if ( !m_data->m_paramDesc.IsEmpty() )
     {
         wxCmdLineParam& param = m_data->m_paramDesc.Last();
 
         wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE),
-                      _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
+                      wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
 
         if ( !(flags & wxCMD_LINE_PARAM_OPTIONAL) )
         {
             wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL),
 
         if ( !(flags & wxCMD_LINE_PARAM_OPTIONAL) )
         {
             wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL),
-                          _T("a required parameter can't follow an optional one") );
+                          wxT("a required parameter can't follow an optional one") );
         }
     }
         }
     }
-#endif // Debug
+#endif // wxDEBUG_LEVEL
 
     wxCmdLineParam *param = new wxCmdLineParam(desc, type, flags);
 
     m_data->m_paramDesc.Add(param);
 }
 
 
     wxCmdLineParam *param = new wxCmdLineParam(desc, type, flags);
 
     m_data->m_paramDesc.Add(param);
 }
 
+void wxCmdLineParser::AddUsageText(const wxString& text)
+{
+    wxASSERT_MSG( !text.empty(), wxT("text can't be empty") );
+
+    wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_USAGE_TEXT,
+                                                  wxEmptyString, wxEmptyString,
+                                                  text, wxCMD_LINE_VAL_NONE, 0);
+
+    m_data->m_options.Add(option);
+}
+
 // ----------------------------------------------------------------------------
 // access to parse command line
 // ----------------------------------------------------------------------------
 
 bool wxCmdLineParser::Found(const wxString& name) const
 // ----------------------------------------------------------------------------
 // access to parse command line
 // ----------------------------------------------------------------------------
 
 bool wxCmdLineParser::Found(const wxString& name) const
+{
+    return FoundSwitch(name) != wxCMD_SWITCH_NOT_FOUND;
+}
+
+wxCmdLineSwitchState wxCmdLineParser::FoundSwitch(const wxString& name) const
 {
     int i = m_data->FindOption(name);
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
 {
     int i = m_data->FindOption(name);
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
-    wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown switch") );
+    wxCHECK_MSG( i != wxNOT_FOUND, wxCMD_SWITCH_NOT_FOUND, wxT("unknown switch") );
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
-        return false;
+        return wxCMD_SWITCH_NOT_FOUND;
 
 
-    return true;
+    return opt.IsNegated() ? wxCMD_SWITCH_OFF : wxCMD_SWITCH_ON;
 }
 
 bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
 }
 
 bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
@@ -459,13 +553,13 @@ bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
-    wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
+    wxCHECK_MSG( i != wxNOT_FOUND, false, wxT("unknown option") );
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
-    wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
+    wxCHECK_MSG( value, false, wxT("NULL pointer in wxCmdLineOption::Found") );
 
     *value = opt.GetStrVal();
 
 
     *value = opt.GetStrVal();
 
@@ -478,19 +572,38 @@ bool wxCmdLineParser::Found(const wxString& name, long *value) const
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
-    wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
+    wxCHECK_MSG( i != wxNOT_FOUND, false, wxT("unknown option") );
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
-    wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
+    wxCHECK_MSG( value, false, wxT("NULL pointer in wxCmdLineOption::Found") );
 
     *value = opt.GetLongVal();
 
     return true;
 }
 
 
     *value = opt.GetLongVal();
 
     return true;
 }
 
+bool wxCmdLineParser::Found(const wxString& name, double *value) const
+{
+    int i = m_data->FindOption(name);
+    if ( i == wxNOT_FOUND )
+        i = m_data->FindOptionByLongName(name);
+
+    wxCHECK_MSG( i != wxNOT_FOUND, false, wxT("unknown option") );
+
+    wxCmdLineOption& opt = m_data->m_options[(size_t)i];
+    if ( !opt.HasValue() )
+        return false;
+
+    wxCHECK_MSG( value, false, wxT("NULL pointer in wxCmdLineOption::Found") );
+
+    *value = opt.GetDoubleVal();
+
+    return true;
+}
+
 #if wxUSE_DATETIME
 bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
 {
 #if wxUSE_DATETIME
 bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
 {
@@ -498,13 +611,13 @@ bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
-    wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
+    wxCHECK_MSG( i != wxNOT_FOUND, false, wxT("unknown option") );
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
         return false;
 
-    wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
+    wxCHECK_MSG( value, false, wxT("NULL pointer in wxCmdLineOption::Found") );
 
     *value = opt.GetDateVal();
 
 
     *value = opt.GetDateVal();
 
@@ -519,7 +632,7 @@ size_t wxCmdLineParser::GetParamCount() const
 
 wxString wxCmdLineParser::GetParam(size_t n) const
 {
 
 wxString wxCmdLineParser::GetParam(size_t n) const
 {
-    wxCHECK_MSG( n < GetParamCount(), wxEmptyString, _T("invalid param index") );
+    wxCHECK_MSG( n < GetParamCount(), wxEmptyString, wxT("invalid param index") );
 
     return m_data->m_parameters[n];
 }
 
     return m_data->m_parameters[n];
 }
@@ -529,8 +642,7 @@ void wxCmdLineParser::Reset()
 {
     for ( size_t i = 0; i < m_data->m_options.GetCount(); i++ )
     {
 {
     for ( size_t i = 0; i < m_data->m_options.GetCount(); i++ )
     {
-        wxCmdLineOption& opt = m_data->m_options[i];
-        opt.SetHasValue(false);
+        m_data->m_options[i].Reset();
     }
 }
 
     }
 }
 
@@ -563,41 +675,84 @@ int wxCmdLineParser::Parse(bool showUsage)
         // special case: "--" should be discarded and all following arguments
         // should be considered as parameters, even if they start with '-' and
         // not like options (this is POSIX-like)
         // special case: "--" should be discarded and all following arguments
         // should be considered as parameters, even if they start with '-' and
         // not like options (this is POSIX-like)
-        if ( arg == _T("--") )
+        if ( arg == wxT("--") )
         {
             maybeOption = false;
 
             continue;
         }
         {
             maybeOption = false;
 
             continue;
         }
-
+#ifdef __WXOSX__
+        if ( arg == wxT("-ApplePersistenceIgnoreState") )
+        {
+            maybeOption = false;
+            
+            continue;
+        }
+#endif
+        
         // empty argument or just '-' is not an option but a parameter
         if ( maybeOption && arg.length() > 1 &&
         // empty argument or just '-' is not an option but a parameter
         if ( maybeOption && arg.length() > 1 &&
-                wxStrchr(m_data->m_switchChars, arg[0u]) )
+                // FIXME-UTF8: use wc_str() after removing ANSI build
+                wxStrchr(m_data->m_switchChars.c_str(), arg[0u]) )
         {
             bool isLong;
             wxString name;
             int optInd = wxNOT_FOUND;   // init to suppress warnings
 
             // an option or a switch: find whether it's a long or a short one
         {
             bool isLong;
             wxString name;
             int optInd = wxNOT_FOUND;   // init to suppress warnings
 
             // an option or a switch: find whether it's a long or a short one
-            if ( arg[0u] == _T('-') && arg[1u] == _T('-') )
+            if ( arg.length() >= 3 && arg[0u] == wxT('-') && arg[1u] == wxT('-') )
             {
                 // a long one
                 isLong = true;
 
                 // Skip leading "--"
             {
                 // a long one
                 isLong = true;
 
                 // Skip leading "--"
-                const wxChar *p = arg.c_str() + 2;
+                wxString::const_iterator p = arg.begin() + 2;
 
                 bool longOptionsEnabled = AreLongOptionsEnabled();
 
 
                 bool longOptionsEnabled = AreLongOptionsEnabled();
 
-                name = GetLongOptionName(p);
+                name = GetLongOptionName(p, arg.end());
 
                 if (longOptionsEnabled)
                 {
 
                 if (longOptionsEnabled)
                 {
+                    wxString errorOpt;
+
                     optInd = m_data->FindOptionByLongName(name);
                     if ( optInd == wxNOT_FOUND )
                     {
                     optInd = m_data->FindOptionByLongName(name);
                     if ( optInd == wxNOT_FOUND )
                     {
-                        errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str())
-                                 << _T('\n');
+                        // Check if this could be a negatable long option.
+                        if ( name.Last() == '-' )
+                        {
+                            name.RemoveLast();
+
+                            optInd = m_data->FindOptionByLongName(name);
+                            if ( optInd != wxNOT_FOUND )
+                            {
+                                if ( !(m_data->m_options[optInd].flags &
+                                        wxCMD_LINE_SWITCH_NEGATABLE) )
+                                {
+                                    errorOpt.Printf
+                                             (
+                                              _("Option '%s' can't be negated"),
+                                              name
+                                             );
+                                    optInd = wxNOT_FOUND;
+                                }
+                            }
+                        }
+
+                        if ( optInd == wxNOT_FOUND )
+                        {
+                            if ( errorOpt.empty() )
+                            {
+                                errorOpt.Printf
+                                         (
+                                          _("Unknown long option '%s'"),
+                                          name
+                                         );
+                            }
+
+                            errorMsg << errorOpt << wxT('\n');
+                        }
                     }
                 }
                 else
                     }
                 }
                 else
@@ -607,7 +762,7 @@ int wxCmdLineParser::Parse(bool showUsage)
                     // Print the argument including leading "--"
                     name.Prepend( wxT("--") );
                     errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
                     // Print the argument including leading "--"
                     name.Prepend( wxT("--") );
                     errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
-                             << _T('\n');
+                             << wxT('\n');
                 }
 
             }
                 }
 
             }
@@ -617,9 +772,9 @@ int wxCmdLineParser::Parse(bool showUsage)
 
                 // a short one: as they can be cumulated, we try to find the
                 // longest substring which is a valid option
 
                 // a short one: as they can be cumulated, we try to find the
                 // longest substring which is a valid option
-                const wxChar *p = arg.c_str() + 1;
+                wxString::const_iterator p = arg.begin() + 1;
 
 
-                name = GetShortOptionName(p);
+                name = GetShortOptionName(p, arg.end());
 
                 size_t len = name.length();
                 do
 
                 size_t len = name.length();
                 do
@@ -629,7 +784,7 @@ int wxCmdLineParser::Parse(bool showUsage)
                         // we couldn't find a valid option name in the
                         // beginning of this string
                         errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
                         // we couldn't find a valid option name in the
                         // beginning of this string
                         errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
-                                 << _T('\n');
+                                 << wxT('\n');
 
                         break;
                     }
 
                         break;
                     }
@@ -656,6 +811,14 @@ int wxCmdLineParser::Parse(bool showUsage)
                     if ( m_data->m_options[(size_t)optInd].kind
                             == wxCMD_LINE_SWITCH )
                     {
                     if ( m_data->m_options[(size_t)optInd].kind
                             == wxCMD_LINE_SWITCH )
                     {
+                        // if the switch is negatable and it is just followed
+                        // by '-' the '-' is considered to be part of this
+                        // switch
+                        if ( (m_data->m_options[(size_t)optInd].flags &
+                                    wxCMD_LINE_SWITCH_NEGATABLE) &&
+                                arg[len] == '-' )
+                            ++len;
+
                         // pretend that all the rest of the argument is the
                         // next argument, in fact
                         wxString arg2 = arg[0u];
                         // pretend that all the rest of the argument is the
                         // next argument, in fact
                         wxString arg2 = arg[0u];
@@ -664,6 +827,10 @@ int wxCmdLineParser::Parse(bool showUsage)
                         m_data->m_arguments.insert
                             (m_data->m_arguments.begin() + n + 1, arg2);
                         count++;
                         m_data->m_arguments.insert
                             (m_data->m_arguments.begin() + n + 1, arg2);
                         count++;
+
+                        // only leave the part which wasn't extracted into the
+                        // next argument in this one
+                        arg = arg.Left(len + 1);
                     }
                     //else: it's our value, we'll deal with it below
                 }
                     }
                     //else: it's our value, we'll deal with it below
                 }
@@ -679,24 +846,31 @@ int wxCmdLineParser::Parse(bool showUsage)
             // look at what follows:
 
             // +1 for leading '-'
             // look at what follows:
 
             // +1 for leading '-'
-            const wxChar *p = arg.c_str() + 1 + name.length();
+            wxString::const_iterator p = arg.begin() + 1 + name.length();
+            wxString::const_iterator end = arg.end();
+
             if ( isLong )
             if ( isLong )
-                p++;    // for another leading '-'
+                ++p;    // for another leading '-'
 
             wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
             if ( opt.kind == wxCMD_LINE_SWITCH )
             {
                 // we must check that there is no value following the switch
 
             wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
             if ( opt.kind == wxCMD_LINE_SWITCH )
             {
                 // we must check that there is no value following the switch
-                if ( *p != _T('\0') )
+                bool negated = (opt.flags & wxCMD_LINE_SWITCH_NEGATABLE) &&
+                                    p != arg.end() && *p == '-';
+
+                if ( !negated && p != arg.end() )
                 {
                     errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str())
                 {
                     errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str())
-                             << _T('\n');
+                             << wxT('\n');
                     ok = false;
                 }
                 else // no value, as expected
                 {
                     // nothing more to do
                     opt.SetHasValue();
                     ok = false;
                 }
                 else // no value, as expected
                 {
                     // nothing more to do
                     opt.SetHasValue();
+                    if ( negated )
+                        opt.SetNegated();
 
                     if ( opt.flags & wxCMD_LINE_OPTION_HELP )
                     {
 
                     if ( opt.flags & wxCMD_LINE_OPTION_HELP )
                     {
@@ -709,66 +883,53 @@ int wxCmdLineParser::Parse(bool showUsage)
             }
             else // it's an option. not a switch
             {
             }
             else // it's an option. not a switch
             {
-                // get the value
-                if ( isLong )
-                {
-                    if ( *p++ != _T('=') )
-                    {
-                        errorMsg << wxString::Format(_("Option '%s' requires a value, '=' expected."), name.c_str())
-                                 << _T('\n');
-
-                        ok = false;
-                    }
-                }
-                else // short option
+                switch ( p == end ? '\0' : (*p).GetValue() )
                 {
                 {
-                    switch ( *p )
-                    {
-                        case _T('='):
-                        case _T(':'):
-                            // the value follows
-                            p++;
-                            break;
-
-                        case 0:
-                            // the value is in the next argument
-                            if ( ++n == count )
-                            {
-                                // ... but there is none
-                                errorMsg << wxString::Format(_("Option '%s' requires a value."),
-                                                             name.c_str())
-                                         << _T('\n');
-
-                                ok = false;
-                            }
-                            else
-                            {
-                                // ... take it from there
-                                p = m_data->m_arguments[n].c_str();
-                            }
-                            break;
+                    case '=':
+                    case ':':
+                        // the value follows
+                        ++p;
+                        break;
 
 
-                        default:
-                            // the value is right here: this may be legal or
-                            // not depending on the option style
-                            if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
-                            {
-                                errorMsg << wxString::Format(_("Separator expected after the option '%s'."),
-                                                             name.c_str())
-                                        << _T('\n');
+                    case '\0':
+                        // the value is in the next argument
+                        if ( ++n == count )
+                        {
+                            // ... but there is none
+                            errorMsg << wxString::Format(_("Option '%s' requires a value."),
+                                                         name.c_str())
+                                     << wxT('\n');
+
+                            ok = false;
+                        }
+                        else
+                        {
+                            // ... take it from there
+                            p = m_data->m_arguments[n].begin();
+                            end = m_data->m_arguments[n].end();
+                        }
+                        break;
 
 
-                                ok = false;
-                            }
-                    }
+                    default:
+                        // the value is right here: this may be legal or
+                        // not depending on the option style
+                        if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
+                        {
+                            errorMsg << wxString::Format(_("Separator expected after the option '%s'."),
+                                                         name.c_str())
+                                    << wxT('\n');
+
+                            ok = false;
+                        }
                 }
 
                 if ( ok )
                 {
                 }
 
                 if ( ok )
                 {
-                    wxString value = p;
+                    wxString value(p, end);
                     switch ( opt.type )
                     {
                         default:
                     switch ( opt.type )
                     {
                         default:
-                            wxFAIL_MSG( _T("unknown option type") );
+                            wxFAIL_MSG( wxT("unknown option type") );
                             // still fall through
 
                         case wxCMD_LINE_VAL_STRING:
                             // still fall through
 
                         case wxCMD_LINE_VAL_STRING:
@@ -786,7 +947,25 @@ int wxCmdLineParser::Parse(bool showUsage)
                                 {
                                     errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
                                                                  value.c_str(), name.c_str())
                                 {
                                     errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
                                                                  value.c_str(), name.c_str())
-                                             << _T('\n');
+                                             << wxT('\n');
+
+                                    ok = false;
+                                }
+                            }
+                            break;
+
+                        case wxCMD_LINE_VAL_DOUBLE:
+                            {
+                                double val;
+                                if ( value.ToDouble(&val) )
+                                {
+                                    opt.SetDoubleVal(val);
+                                }
+                                else
+                                {
+                                    errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
+                                                                 value.c_str(), name.c_str())
+                                             << wxT('\n');
 
                                     ok = false;
                                 }
 
                                     ok = false;
                                 }
@@ -797,12 +976,12 @@ int wxCmdLineParser::Parse(bool showUsage)
                         case wxCMD_LINE_VAL_DATE:
                             {
                                 wxDateTime dt;
                         case wxCMD_LINE_VAL_DATE:
                             {
                                 wxDateTime dt;
-                                const wxChar *res = dt.ParseDate(value);
-                                if ( !res || *res )
+                                wxString::const_iterator endDate;
+                                if ( !dt.ParseDate(value, &endDate) || endDate != value.end() )
                                 {
                                     errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
                                                                  name.c_str(), value.c_str())
                                 {
                                     errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
                                                                  name.c_str(), value.c_str())
-                                             << _T('\n');
+                                             << wxT('\n');
 
                                     ok = false;
                                 }
 
                                     ok = false;
                                 }
@@ -834,7 +1013,7 @@ int wxCmdLineParser::Parse(bool showUsage)
                 else
                 {
                     wxASSERT_MSG( currentParam == countParam - 1,
                 else
                 {
                     wxASSERT_MSG( currentParam == countParam - 1,
-                                  _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
+                                  wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
 
                     // remember that we did have this last repeatable parameter
                     hadRepeatableParam = true;
 
                     // remember that we did have this last repeatable parameter
                     hadRepeatableParam = true;
@@ -843,7 +1022,7 @@ int wxCmdLineParser::Parse(bool showUsage)
             else
             {
                 errorMsg << wxString::Format(_("Unexpected parameter '%s'"), arg.c_str())
             else
             {
                 errorMsg << wxString::Format(_("Unexpected parameter '%s'"), arg.c_str())
-                         << _T('\n');
+                         << wxT('\n');
 
                 ok = false;
             }
 
                 ok = false;
             }
@@ -881,7 +1060,7 @@ int wxCmdLineParser::Parse(bool showUsage)
 
                 errorMsg << wxString::Format(_("The value for the option '%s' must be specified."),
                                              optName.c_str())
 
                 errorMsg << wxString::Format(_("The value for the option '%s' must be specified."),
                                              optName.c_str())
-                         << _T('\n');
+                         << wxT('\n');
 
                 ok = false;
             }
 
                 ok = false;
             }
@@ -903,7 +1082,7 @@ int wxCmdLineParser::Parse(bool showUsage)
             {
                 errorMsg << wxString::Format(_("The required parameter '%s' was not specified."),
                                              param.description.c_str())
             {
                 errorMsg << wxString::Format(_("The required parameter '%s' was not specified."),
                                              param.description.c_str())
-                         << _T('\n');
+                         << wxT('\n');
 
                 ok = false;
             }
 
                 ok = false;
             }
@@ -925,7 +1104,7 @@ int wxCmdLineParser::Parse(bool showUsage)
         }
         else
         {
         }
         else
         {
-            wxFAIL_MSG( _T("no wxMessageOutput object?") );
+            wxFAIL_MSG( wxT("no wxMessageOutput object?") );
         }
     }
 
         }
     }
 
@@ -936,7 +1115,7 @@ int wxCmdLineParser::Parse(bool showUsage)
 // give the usage message
 // ----------------------------------------------------------------------------
 
 // give the usage message
 // ----------------------------------------------------------------------------
 
-void wxCmdLineParser::Usage()
+void wxCmdLineParser::Usage() const
 {
     wxMessageOutput* msgOut = wxMessageOutput::Get();
     if ( msgOut )
 {
     wxMessageOutput* msgOut = wxMessageOutput::Get();
     if ( msgOut )
@@ -945,11 +1124,11 @@ void wxCmdLineParser::Usage()
     }
     else
     {
     }
     else
     {
-        wxFAIL_MSG( _T("no wxMessageOutput object?") );
+        wxFAIL_MSG( wxT("no wxMessageOutput object?") );
     }
 }
 
     }
 }
 
-wxString wxCmdLineParser::GetUsageString()
+wxString wxCmdLineParser::GetUsageString() const
 {
     wxString appname;
     if ( m_data->m_arguments.empty() )
 {
     wxString appname;
     if ( m_data->m_arguments.empty() )
@@ -970,14 +1149,14 @@ wxString wxCmdLineParser::GetUsageString()
 
     if ( !m_data->m_logo.empty() )
     {
 
     if ( !m_data->m_logo.empty() )
     {
-        usage << m_data->m_logo << _T('\n');
+        usage << m_data->m_logo << wxT('\n');
     }
 
     usage << wxString::Format(_("Usage: %s"), appname.c_str());
 
     // the switch char is usually '-' but this can be changed with
     // SetSwitchChars() and then the first one of possible chars is used
     }
 
     usage << wxString::Format(_("Usage: %s"), appname.c_str());
 
     // the switch char is usually '-' but this can be changed with
     // SetSwitchChars() and then the first one of possible chars is used
-    wxChar chSwitch = !m_data->m_switchChars ? _T('-')
+    wxChar chSwitch = !m_data->m_switchChars ? wxT('-')
                                              : m_data->m_switchChars[0u];
 
     bool areLongOptionsEnabled = AreLongOptionsEnabled();
                                              : m_data->m_switchChars[0u];
 
     bool areLongOptionsEnabled = AreLongOptionsEnabled();
@@ -985,58 +1164,63 @@ wxString wxCmdLineParser::GetUsageString()
     for ( n = 0; n < count; n++ )
     {
         wxCmdLineOption& opt = m_data->m_options[n];
     for ( n = 0; n < count; n++ )
     {
         wxCmdLineOption& opt = m_data->m_options[n];
+        wxString option, negator;
 
 
-        usage << _T(' ');
-        if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
+        if ( opt.kind != wxCMD_LINE_USAGE_TEXT )
         {
         {
-            usage << _T('[');
-        }
+            usage << wxT(' ');
+            if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
+            {
+                usage << wxT('[');
+            }
 
 
-        if ( !opt.shortName.empty() )
-        {
-            usage << chSwitch << opt.shortName;
-        }
-        else if ( areLongOptionsEnabled && !opt.longName.empty() )
-        {
-            usage << _T("--") << opt.longName;
-        }
-        else
-        {
-            if (!opt.longName.empty())
+            if ( opt.flags & wxCMD_LINE_SWITCH_NEGATABLE )
+                negator = wxT("[-]");
+
+            if ( !opt.shortName.empty() )
+            {
+                usage << chSwitch << opt.shortName << negator;
+            }
+            else if ( areLongOptionsEnabled && !opt.longName.empty() )
             {
             {
-                wxFAIL_MSG( wxT("option with only a long name while long ")
-                            wxT("options are disabled") );
+                usage << wxT("--") << opt.longName << negator;
             }
             else
             {
             }
             else
             {
-                wxFAIL_MSG( _T("option without neither short nor long name") );
+                if (!opt.longName.empty())
+                {
+                    wxFAIL_MSG( wxT("option with only a long name while long ")
+                                wxT("options are disabled") );
+                }
+                else
+                {
+                    wxFAIL_MSG( wxT("option without neither short nor long name") );
+                }
             }
             }
-        }
-
-        wxString option;
 
 
-        if ( !opt.shortName.empty() )
-        {
-            option << _T("  ") << chSwitch << opt.shortName;
-        }
+            if ( !opt.shortName.empty() )
+            {
+                option << wxT("  ") << chSwitch << opt.shortName;
+            }
 
 
-        if ( areLongOptionsEnabled && !opt.longName.empty() )
-        {
-            option << (option.empty() ? _T("  ") : _T(", "))
-                   << _T("--") << opt.longName;
-        }
+            if ( areLongOptionsEnabled && !opt.longName.empty() )
+            {
+                option << (option.empty() ? wxT("  ") : wxT(", "))
+                       << wxT("--") << opt.longName;
+            }
 
 
-        if ( opt.kind != wxCMD_LINE_SWITCH )
-        {
-            wxString val;
-            val << _T('<') << GetTypeName(opt.type) << _T('>');
-            usage << _T(' ') << val;
-            option << (!opt.longName ? _T(':') : _T('=')) << val;
-        }
+            if ( opt.kind != wxCMD_LINE_SWITCH )
+            {
+                wxString val;
+                val << wxT('<') << GetTypeName(opt.type) << wxT('>');
+                usage << wxT(' ') << val;
+                option << (!opt.longName ? wxT(':') : wxT('=')) << val;
+            }
 
 
-        if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
-        {
-            usage << _T(']');
+            if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
+            {
+                usage << wxT(']');
+            }
         }
 
         namesOptions.push_back(option);
         }
 
         namesOptions.push_back(option);
@@ -1048,26 +1232,26 @@ wxString wxCmdLineParser::GetUsageString()
     {
         wxCmdLineParam& param = m_data->m_paramDesc[n];
 
     {
         wxCmdLineParam& param = m_data->m_paramDesc[n];
 
-        usage << _T(' ');
+        usage << wxT(' ');
         if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
         {
         if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
         {
-            usage << _T('[');
+            usage << wxT('[');
         }
 
         usage << param.description;
 
         if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE )
         {
         }
 
         usage << param.description;
 
         if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE )
         {
-            usage << _T("...");
+            usage << wxT("...");
         }
 
         if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
         {
         }
 
         if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
         {
-            usage << _T(']');
+            usage << wxT(']');
         }
     }
 
         }
     }
 
-    usage << _T('\n');
+    usage << wxT('\n');
 
     // set to number of our own options, not counting the standard ones
     count = namesOptions.size();
 
     // set to number of our own options, not counting the standard ones
     count = namesOptions.size();
@@ -1090,13 +1274,21 @@ wxString wxCmdLineParser::GetUsageString()
     for ( n = 0; n < namesOptions.size(); n++ )
     {
         if ( n == count )
     for ( n = 0; n < namesOptions.size(); n++ )
     {
         if ( n == count )
-            usage << _T('\n') << stdDesc;
+            usage << wxT('\n') << stdDesc;
 
         len = namesOptions[n].length();
 
         len = namesOptions[n].length();
-        usage << namesOptions[n]
-              << wxString(_T(' '), lenMax - len) << _T('\t')
-              << descOptions[n]
-              << _T('\n');
+        // desc contains text if name is empty
+        if (len == 0)
+        {
+            usage << descOptions[n] << wxT('\n');
+        }
+        else
+        {
+            usage << namesOptions[n]
+                  << wxString(wxT(' '), lenMax - len) << wxT('\t')
+                  << descOptions[n]
+                  << wxT('\n');
+        }
     }
 
     return usage;
     }
 
     return usage;
@@ -1112,7 +1304,7 @@ static wxString GetTypeName(wxCmdLineParamType type)
     switch ( type )
     {
         default:
     switch ( type )
     {
         default:
-            wxFAIL_MSG( _T("unknown option type") );
+            wxFAIL_MSG( wxT("unknown option type") );
             // still fall through
 
         case wxCMD_LINE_VAL_STRING:
             // still fall through
 
         case wxCMD_LINE_VAL_STRING:
@@ -1123,6 +1315,10 @@ static wxString GetTypeName(wxCmdLineParamType type)
             s = _("num");
             break;
 
             s = _("num");
             break;
 
+        case wxCMD_LINE_VAL_DOUBLE:
+            s = _("double");
+            break;
+
         case wxCMD_LINE_VAL_DATE:
             s = _("date");
             break;
         case wxCMD_LINE_VAL_DATE:
             s = _("date");
             break;
@@ -1140,12 +1336,13 @@ the parameter allowedChars.
 For example, if p points to "abcde-@-_", and allowedChars is "-_",
 this function returns "abcde-".
 */
 For example, if p points to "abcde-@-_", and allowedChars is "-_",
 this function returns "abcde-".
 */
-static wxString GetOptionName(const wxChar *p,
-    const wxChar *allowedChars)
+static wxString GetOptionName(wxString::const_iterator p,
+                              wxString::const_iterator end,
+                              const wxChar *allowedChars)
 {
     wxString argName;
 
 {
     wxString argName;
 
-    while ( *p && (wxIsalnum(*p) || wxStrchr(allowedChars, *p)) )
+    while ( p != end && (wxIsalnum(*p) || wxStrchr(allowedChars, *p)) )
     {
         argName += *p++;
     }
     {
         argName += *p++;
     }
@@ -1163,14 +1360,16 @@ static wxString GetOptionName(const wxChar *p,
 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
     wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
 
 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
     wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
 
-static wxString GetShortOptionName(const wxChar *p)
+static wxString GetShortOptionName(wxString::const_iterator p,
+                                  wxString::const_iterator end)
 {
 {
-    return GetOptionName(p, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION);
+    return GetOptionName(p, end, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION);
 }
 
 }
 
-static wxString GetLongOptionName(const wxChar *p)
+static wxString GetLongOptionName(wxString::const_iterator p,
+                                  wxString::const_iterator end)
 {
 {
-    return GetOptionName(p, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION);
+    return GetOptionName(p, end, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION);
 }
 
 #endif // wxUSE_CMDLINE_PARSER
 }
 
 #endif // wxUSE_CMDLINE_PARSER
@@ -1185,35 +1384,60 @@ static wxString GetLongOptionName(const wxChar *p)
    Windows conventions for the command line handling, not Unix ones. For
    instance, backslash is not special except when it precedes double quote when
    it does quote it.
    Windows conventions for the command line handling, not Unix ones. For
    instance, backslash is not special except when it precedes double quote when
    it does quote it.
+
+   TODO: Rewrite this to follow the even more complicated rule used by Windows
+         CommandLineToArgv():
+
+    * A string of backslashes not followed by a quotation mark has no special
+      meaning.
+    * An even number of backslashes followed by a quotation mark is treated as
+      pairs of protected backslashes, followed by a word terminator.
+    * An odd number of backslashes followed by a quotation mark is treated as
+      pairs of protected backslashes, followed by a protected quotation mark.
+
+    See http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
+
+    It could also be useful to provide a converse function which is also
+    non-trivial, see
+
+    http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
  */
 
 /* static */
  */
 
 /* static */
-wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxChar *p)
+wxArrayString
+wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline,
+                                     wxCmdLineSplitType type)
 {
     wxArrayString args;
 
     wxString arg;
     arg.reserve(1024);
 
 {
     wxArrayString args;
 
     wxString arg;
     arg.reserve(1024);
 
-    bool isInsideQuotes = false;
+    const wxString::const_iterator end = cmdline.end();
+    wxString::const_iterator p = cmdline.begin();
+
     for ( ;; )
     {
         // skip white space
     for ( ;; )
     {
         // skip white space
-        while ( *p == _T(' ') || *p == _T('\t') )
-            p++;
+        while ( p != end && (*p == ' ' || *p == '\t') )
+            ++p;
 
         // anything left?
 
         // anything left?
-        if ( *p == _T('\0') )
+        if ( p == end )
             break;
 
         // parse this parameter
             break;
 
         // parse this parameter
-        bool endParam = false;
-        bool lastBS = false;
-        for ( arg.clear(); !endParam; p++ )
+        bool lastBS = false,
+             isInsideQuotes = false;
+        wxChar chDelim = '\0';
+        for ( arg.clear(); p != end; ++p )
         {
         {
-            switch ( *p )
+            const wxChar ch = *p;
+
+            if ( type == wxCMD_LINE_SPLIT_DOS )
             {
             {
-                case _T('"'):
+                if ( ch == '"' )
+                {
                     if ( !lastBS )
                     {
                         isInsideQuotes = !isInsideQuotes;
                     if ( !lastBS )
                     {
                         isInsideQuotes = !isInsideQuotes;
@@ -1224,32 +1448,57 @@ wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxChar *p)
                     //else: quote has no special meaning but the backslash
                     //      still remains -- makes no sense but this is what
                     //      Windows does
                     //else: quote has no special meaning but the backslash
                     //      still remains -- makes no sense but this is what
                     //      Windows does
+                }
+                // note that backslash does *not* quote the space, only quotes do
+                else if ( !isInsideQuotes && (ch == ' ' || ch == '\t') )
+                {
+                    ++p;    // skip this space anyhow
                     break;
                     break;
+                }
 
 
-                case _T(' '):
-                case _T('\t'):
-                    // backslash does *not* quote the space, only quotes do
+                lastBS = !lastBS && ch == '\\';
+            }
+            else // type == wxCMD_LINE_SPLIT_UNIX
+            {
+                if ( !lastBS )
+                {
                     if ( isInsideQuotes )
                     {
                     if ( isInsideQuotes )
                     {
-                        // skip assignment below
-                        break;
+                        if ( ch == chDelim )
+                        {
+                            isInsideQuotes = false;
+
+                            continue;   // don't use the quote itself
+                        }
                     }
                     }
-                    // fall through
+                    else // not in quotes and not escaped
+                    {
+                        if ( ch == '\'' || ch == '"' )
+                        {
+                            isInsideQuotes = true;
+                            chDelim = ch;
 
 
-                case _T('\0'):
-                    endParam = true;
+                            continue;   // don't use the quote itself
+                        }
 
 
-                    break;
-            }
+                        if ( ch == ' ' || ch == '\t' )
+                        {
+                            ++p;    // skip this space anyhow
+                            break;
+                        }
+                    }
 
 
-            if ( endParam )
-            {
-                break;
+                    lastBS = ch == '\\';
+                    if ( lastBS )
+                        continue;
+                }
+                else // escaped by backslash, just use as is
+                {
+                    lastBS = false;
+                }
             }
 
             }
 
-            lastBS = *p == _T('\\');
-
-            arg += *p;
+            arg += ch;
         }
 
         args.push_back(arg);
         }
 
         args.push_back(arg);