]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/datetime.cpp
if we return GetSize() from DoGetBestSize(), remember it as min size as well to preve...
[wxWidgets.git] / src / common / datetime.cpp
index 929490153187d29c7957d96e5faa9152664046c4..d0e828f406564017ac9f62a09dc20ed20610fb49 100644 (file)
@@ -130,7 +130,13 @@ wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter<wxDateTime> , wxFromStringCon
 #if defined(HAVE_STRPTIME) && defined(__DARWIN__) && defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
     // configure detects strptime as linkable because it's in the OS X
     // System library but MSL headers don't declare it.
-    char *strptime(const char *, const char *, struct tm *);
+
+//    char *strptime(const char *, const char *, struct tm *);
+    // However, we DON'T want to just provide it here because we would
+    // crash and/or overwrite data when strptime from OS X tries
+    // to fill in MW's struct tm which is two fields shorter (no TZ stuff)
+    // So for now let's just say we don't have strptime
+    #undef HAVE_STRPTIME
 #endif
 
 #if defined(__MWERKS__) && wxUSE_UNICODE
@@ -2852,10 +2858,12 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
 #ifdef __WINDOWS__
 
-// Get's current locale's date formatting string and stores it in fmt if
-// the locale is set; otherwise or in case of failure, leaves fmt unchanged
-static void GetLocaleDateFormat(wxString *fmt)
+// returns the string containing strftime() format used for short dates in the
+// current locale or an empty string
+static wxString GetLocaleDateFormat()
 {
+    wxString fmtWX;
+
     // there is no setlocale() under Windows CE, so just always query the
     // system there
 #ifndef __WXWINCE__
@@ -2871,45 +2879,139 @@ static void GetLocaleDateFormat(wxString *fmt)
 #else
         LCID lcid = GetThreadLocale();
 #endif
-        wxChar delim[5]; // fields deliminer, 4 chars max
-        if ( GetLocaleInfo(lcid, LOCALE_SDATE, delim, 5) )
+        // according to MSDN 80 chars is max allowed for short date format
+        wxChar fmt[81];
+        if ( ::GetLocaleInfo(lcid, LOCALE_SSHORTDATE, fmt, WXSIZEOF(fmt)) )
         {
-            wxChar centurybuf[2]; // use %y or %Y, 1 char max
-            wxChar century = 'y';
-            if ( GetLocaleInfo(lcid, LOCALE_ICENTURY, centurybuf, 2) )
+            wxChar chLast = _T('\0');
+            size_t lastCount = 0;
+            for ( const wxChar *p = fmt; /* NUL handled inside */; p++ )
             {
-                if ( centurybuf[0] == _T('1') )
-                    century = 'Y';
-                // else 'y' as above
-            }
-
-            wxChar order[2]; // order code, 1 char max
-            if ( GetLocaleInfo(lcid, LOCALE_IDATE, order, 2) )
-            {
-                if ( order[0] == _T('0') ) // M-D-Y
-                {
-                    *fmt = wxString::Format(_T("%%m%s%%d%s%%%c"),
-                                            delim, delim, century);
-                }
-                else if ( order[0] == _T('1') ) // D-M-Y
-                {
-                    *fmt = wxString::Format(_T("%%d%s%%m%s%%%c"),
-                                            delim, delim, century);
-                }
-                else if ( order[0] == _T('2') ) // Y-M-D
+                if ( *p == chLast )
                 {
-                    *fmt = wxString::Format(_T("%%%c%s%%m%s%%d"),
-                                            century, delim, delim);
+                    lastCount++;
+                    continue;
                 }
-                else
+
+                switch ( *p )
                 {
-                    wxFAIL_MSG(_T("unexpected GetLocaleInfo return value"));
+                    // these characters come in groups, start counting them
+                    case _T('d'):
+                    case _T('M'):
+                    case _T('y'):
+                    case _T('g'):
+                        chLast = *p;
+                        lastCount = 1;
+                        break;
+
+                    default:
+                        // first deal with any special characters we have had
+                        if ( lastCount )
+                        {
+                            switch ( chLast )
+                            {
+                                case _T('d'):
+                                    switch ( lastCount )
+                                    {
+                                        case 1: // d
+                                        case 2: // dd
+                                            // these two are the same as we
+                                            // don't distinguish between 1 and
+                                            // 2 digits for days
+                                            fmtWX += _T("%d");
+                                            break;
+
+                                        case 3: // ddd
+                                            fmtWX += _T("%a");
+                                            break;
+
+                                        case 4: // dddd
+                                            fmtWX += _T("%A");
+                                            break;
+
+                                        default:
+                                            wxFAIL_MSG( _T("too many 'd's") );
+                                    }
+                                    break;
+
+                                case _T('M'):
+                                    switch ( lastCount )
+                                    {
+                                        case 1: // M
+                                        case 2: // MM
+                                            // as for 'd' and 'dd' above
+                                            fmtWX += _T("%m");
+                                            break;
+
+                                        case 3:
+                                            fmtWX += _T("%b");
+                                            break;
+
+                                        case 4:
+                                            fmtWX += _T("%B");
+                                            break;
+
+                                        default:
+                                            wxFAIL_MSG( _T("too many 'M's") );
+                                    }
+                                    break;
+
+                                case _T('y'):
+                                    switch ( lastCount )
+                                    {
+                                        case 1: // y
+                                        case 2: // yy
+                                            fmtWX += _T("%y");
+                                            break;
+
+                                        case 4: // yyyy
+                                            fmtWX += _T("%Y");
+                                            break;
+
+                                        default:
+                                            wxFAIL_MSG( _T("wrong number of 'y's") );
+                                    }
+                                    break;
+
+                                case _T('g'):
+                                    // strftime() doesn't have era string,
+                                    // ignore this format
+                                    wxASSERT_MSG( lastCount <= 2,
+                                                  _T("too many 'g's") );
+                                    break;
+
+                                default:
+                                    wxFAIL_MSG( _T("unreachable") );
+                            }
+
+                            chLast = _T('\0');
+                            lastCount = 0;
+                        }
+
+                        // not a special character so must be just a separator,
+                        // treat as is
+                        if ( *p != _T('\0') )
+                        {
+                            if ( *p == _T('%') )
+                            {
+                                // this one needs to be escaped
+                                fmtWX += _T('%');
+                            }
+
+                            fmtWX += *p;
+                        }
                 }
+
+                if ( *p == _T('\0') )
+                    break;
             }
         }
-        // if we failed, leave fmtDate value unchanged and
-        // try our luck with the default set above
+        //else: GetLocaleInfo() failed, leave fmtDate value unchanged and
+        //      try our luck with the default formats
     }
+    //else: default C locale, default formats should work
+
+    return fmtWX;
 }
 
 #endif // __WINDOWS__
@@ -3276,30 +3378,32 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
 
                 {
                     wxDateTime dt;
-
-                    wxString fmtDate, fmtDateAlt;
-
-                    if ( IsWestEuropeanCountry(GetCountry()) ||
-                         GetCountry() == Russia )
-                    {
-                        fmtDate = _T("%d/%m/%y");
-                        fmtDateAlt = _T("%m/%d/%y");
-                    }
-                    else // assume USA
-                    {
-                        fmtDate = _T("%m/%d/%y");
-                        fmtDateAlt = _T("%d/%m/%y");
-                    }
+                    wxString fmtDate,
+                             fmtDateAlt;
 
 #ifdef __WINDOWS__
                     // The above doesn't work for all locales, try to query
                     // Windows for the right way of formatting the date:
-                    GetLocaleDateFormat(&fmtDate);
+                    fmtDate = GetLocaleDateFormat();
+                    if ( fmtDate.empty() )
 #endif
+                    {
+                        if ( IsWestEuropeanCountry(GetCountry()) ||
+                             GetCountry() == Russia )
+                        {
+                            fmtDate = _T("%d/%m/%y");
+                            fmtDateAlt = _T("%m/%d/%y");
+                        }
+                        else // assume USA
+                        {
+                            fmtDate = _T("%m/%d/%y");
+                            fmtDateAlt = _T("%d/%m/%y");
+                        }
+                    }
 
                     const wxChar *result = dt.ParseFormat(input, fmtDate);
 
-                    if ( !result )
+                    if ( !result && !fmtDateAlt.empty() )
                     {
                         // ok, be nice and try another one
                         result = dt.ParseFormat(input, fmtDateAlt);