+ switch ( index )
+ {
+ case wxLOCALE_SHORT_DATE_FMT:
+ return LOCALE_SSHORTDATE;
+
+ case wxLOCALE_LONG_DATE_FMT:
+ return LOCALE_SLONGDATE;
+
+ case wxLOCALE_TIME_FMT:
+ return LOCALE_STIMEFORMAT;
+
+ default:
+ wxFAIL_MSG( "no matching LCTYPE" );
+ }
+
+ return 0;
+}
+
+} // anonymous namespace
+
+/* static */
+wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
+{
+ const wxLanguageInfo * const
+ info = wxGetLocale() ? GetLanguageInfo(wxGetLocale()->GetLanguage())
+ : NULL;
+ if ( !info )
+ {
+ // wxSetLocale() hadn't been called yet of failed, hence CRT must be
+ // using "C" locale -- but check it to detect bugs that would happen if
+ // this were not the case.
+ wxASSERT_MSG( strcmp(setlocale(LC_ALL, NULL), "C") == 0,
+ wxS("You probably called setlocale() directly instead ")
+ wxS("of calling wxSetLocale() and now there is a ")
+ wxS("mismatch between C/C++ and Windows locale.\n")
+ wxS("Things are going to break, use wxSetLocale() to ")
+ wxS("avoid this!") );
+
+
+ // Return the hard coded values for C locale. This is really the right
+ // thing to do as there is no LCID we can use in the code below in this
+ // case, even LOCALE_INVARIANT is not quite the same as C locale (the
+ // only difference is that it uses %Y instead of %y in the date format
+ // but this difference is significant enough).
+ switch ( index )
+ {
+ case wxLOCALE_THOUSANDS_SEP:
+ return wxString();
+
+ case wxLOCALE_DECIMAL_POINT:
+ return ".";
+
+ case wxLOCALE_SHORT_DATE_FMT:
+ return "%m/%d/%y";
+
+ case wxLOCALE_LONG_DATE_FMT:
+ return "%A, %B %d, %Y";
+
+ case wxLOCALE_TIME_FMT:
+ return "%H:%M:%S";
+
+ case wxLOCALE_DATE_TIME_FMT:
+ return "%m/%d/%y %H:%M:%S";
+
+ default:
+ wxFAIL_MSG( "unknown wxLocaleInfo" );
+ }
+ }
+
+ const wxUint32 lcid = info->GetLCID();
+
+ wxString str;
+
+ wxChar buf[256];
+ buf[0] = wxT('\0');
+
+ switch ( index )
+ {
+ case wxLOCALE_THOUSANDS_SEP:
+ if ( ::GetLocaleInfo(lcid, LOCALE_STHOUSAND, buf, WXSIZEOF(buf)) )
+ str = buf;
+ break;
+
+ case wxLOCALE_DECIMAL_POINT:
+ if ( ::GetLocaleInfo(lcid,
+ cat == wxLOCALE_CAT_MONEY
+ ? LOCALE_SMONDECIMALSEP
+ : LOCALE_SDECIMAL,
+ buf,
+ WXSIZEOF(buf)) )
+ {
+ str = buf;
+
+ // As we get our decimal point separator from Win32 and not the
+ // CRT there is a possibility of mismatch between them and this
+ // can easily happen if the user code called setlocale()
+ // instead of using wxLocale to change the locale. And this can
+ // result in very strange bugs elsewhere in the code as the
+ // assumptions that formatted strings do use the decimal
+ // separator actually fail, so check for it here.
+ wxASSERT_MSG
+ (
+ wxString::Format("%.3f", 1.23).find(str) != wxString::npos,
+ "Decimal separator mismatch -- did you use setlocale()?"
+ "If so, use wxLocale to change the locale instead."
+ );
+ }
+ break;
+
+ case wxLOCALE_SHORT_DATE_FMT:
+ case wxLOCALE_LONG_DATE_FMT:
+ case wxLOCALE_TIME_FMT:
+ if ( ::GetLocaleInfo(lcid, GetLCTYPEFormatFromLocalInfo(index),
+ buf, WXSIZEOF(buf)) )
+ {
+ return TranslateFromUnicodeFormat(buf);
+ }
+ break;
+
+ case wxLOCALE_DATE_TIME_FMT:
+ // there doesn't seem to be any specific setting for this, so just
+ // combine date and time ones
+ //
+ // we use the short date because this is what "%c" uses by default
+ // ("%#c" uses long date but we have no way to specify the
+ // alternate representation here)
+ {
+ const wxString datefmt = GetInfo(wxLOCALE_SHORT_DATE_FMT);
+ if ( datefmt.empty() )
+ break;
+
+ const wxString timefmt = GetInfo(wxLOCALE_TIME_FMT);
+ if ( timefmt.empty() )
+ break;
+
+ str << datefmt << ' ' << timefmt;
+ }
+ break;
+
+ default:
+ wxFAIL_MSG( "unknown wxLocaleInfo" );
+ }
+
+ return str;
+}
+
+#elif defined(__WXOSX__)
+
+/* static */
+wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
+{
+ CFLocaleRef userLocaleRefRaw;
+ if ( wxGetLocale() )
+ {
+ userLocaleRefRaw = CFLocaleCreate
+ (
+ kCFAllocatorDefault,
+ wxCFStringRef(wxGetLocale()->GetCanonicalName())
+ );
+ }
+ else // no current locale, use the default one
+ {
+ userLocaleRefRaw = CFLocaleCopyCurrent();
+ }
+
+ wxCFRef<CFLocaleRef> userLocaleRef(userLocaleRefRaw);
+
+ CFStringRef cfstr = 0;
+ switch ( index )
+ {
+ case wxLOCALE_THOUSANDS_SEP:
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
+ break;
+
+ case wxLOCALE_DECIMAL_POINT:
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
+ break;
+
+ case wxLOCALE_SHORT_DATE_FMT:
+ case wxLOCALE_LONG_DATE_FMT:
+ case wxLOCALE_DATE_TIME_FMT:
+ case wxLOCALE_TIME_FMT:
+ {
+ CFDateFormatterStyle dateStyle = kCFDateFormatterNoStyle;
+ CFDateFormatterStyle timeStyle = kCFDateFormatterNoStyle;
+ switch (index )
+ {
+ case wxLOCALE_SHORT_DATE_FMT:
+ dateStyle = kCFDateFormatterShortStyle;
+ break;
+ case wxLOCALE_LONG_DATE_FMT:
+ dateStyle = kCFDateFormatterFullStyle;
+ break;
+ case wxLOCALE_DATE_TIME_FMT:
+ dateStyle = kCFDateFormatterFullStyle;
+ timeStyle = kCFDateFormatterMediumStyle;
+ break;
+ case wxLOCALE_TIME_FMT:
+ timeStyle = kCFDateFormatterMediumStyle;
+ break;
+ default:
+ wxFAIL_MSG( "unexpected time locale" );
+ return wxString();
+ }
+ wxCFRef<CFDateFormatterRef> dateFormatter( CFDateFormatterCreate
+ (NULL, userLocaleRef, dateStyle, timeStyle));
+ wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter ));
+ wxString format = TranslateFromUnicodeFormat(cfs.AsString());
+ // we always want full years
+ format.Replace("%y","%Y");
+ return format;
+ }
+ break;
+
+ default:
+ wxFAIL_MSG( "Unknown locale info" );
+ return wxString();
+ }
+
+ wxCFStringRef str(wxCFRetain(cfstr));
+ return str.AsString();