diff --git a/include/wx/intl.h b/include/wx/intl.h index 39296b090cec..47b699397055 100644 --- a/include/wx/intl.h +++ b/include/wx/intl.h @@ -360,6 +360,10 @@ class WXDLLIMPEXP_BASE wxLocale const wxString& shortName, bool bLoadDefault); + // Converts a grouping format string returned by localeconv() + // to the kind used on Windows platform + static wxString StandardizeGroupingString(wxString g); + wxString m_strLocale, // this locale name m_strShort; // short name for the locale diff --git a/interface/wx/numformatter.h b/interface/wx/numformatter.h index 23aa6a193219..eed96cf7b463 100644 --- a/interface/wx/numformatter.h +++ b/interface/wx/numformatter.h @@ -140,6 +140,8 @@ class wxNumberFormatter Points to the variable receiving the grouping format string if it is used by the current locale. May be @NULL if only the function return value is needed. + + @since 3.1.4 */ static bool GetThousandsSeparatorAndGroupingIfUsed(wxChar *sep, wxString *gr); diff --git a/src/common/intl.cpp b/src/common/intl.cpp index a86405bb2f52..7b88280c274b 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -1717,7 +1717,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) return "."; case wxLOCALE_GROUPING: - return "\3\0"; + return "3;0"; case wxLOCALE_SHORT_DATE_FMT: return "%m/%d/%y"; @@ -1778,7 +1778,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat)) break; case wxLOCALE_GROUPING: - cfstr = CFStringCreateWithCString(NULL, "\3\0", kCFStringEncodingASCII); + cfstr = CFStringCreateWithCString(NULL, "3;0", kCFStringEncodingASCII); break; case wxLOCALE_SHORT_DATE_FMT: @@ -1911,6 +1911,32 @@ wxString GetDateFormatFromLangInfo(wxLocaleInfo index) } // anonymous namespace +// Convert a grouping format string returned by localeconv() to +// a standardized format. Our standard format is the one used on +// Windows SGROUPING. Here we convert char sized integers to ASCII +// characters. That is, for example '\3' becomes '3'. We also add +// the a ';' delimiter between each number. A '\0' or a CHAR_MAX +// signifies the end of the argument string. If the argument string +// ends with a '\0' then we insert a '0' to the return string. +// The return string will be NULL terminated. + +/* static */ +wxString wxLocale::StandardizeGroupingString(wxString g) +{ + wxString s = ""; + int i; + for (i = 0; g[i] != '\0' && g[i] != CHAR_MAX; i++) + { + s.Append((char)((int)g[i] + (int)'0')); + s.Append(';'); + } + if (g[i] == '\0') + s.Append('0'); + else + s.RemoveLast(); // Remove extra ; + return s; +} + /* static */ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) { @@ -1943,9 +1969,9 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) case wxLOCALE_GROUPING: if ( cat == wxLOCALE_CAT_NUMBER ) - return lc->grouping; + return StandardizeGroupingString(lc->grouping); else if ( cat == wxLOCALE_CAT_MONEY ) - return lc->mon_grouping; + return StandardizeGroupingString(lc->mon_grouping); wxFAIL_MSG( "invalid wxLocaleCategory" ); break; diff --git a/src/common/numformatter.cpp b/src/common/numformatter.cpp index 426268676110..175d36d7d539 100644 --- a/src/common/numformatter.cpp +++ b/src/common/numformatter.cpp @@ -278,25 +278,29 @@ void wxNumberFormatter::AddThousandsSeparators(wxString& s) // before their start. const size_t start = s.find_first_of("0123456789"); - // We get the grouping style from locale. This is represented by a character - // array where each element is the number of digits in a group starting - // from the right of the number. If the last element in the grouping is a 0 - // then the last but one element is the number used for grouping the - // remaining digits. If the last element is CHAR_MAX then no grouping is - // done for the remaining digits. + // We get the grouping style from locale. This is represented by a ';' + // delimited character array where each element is the number of digits + // in a group starting from the right of the number. If the last element + // in the grouping is a 0 then the last but one element is the number + // used for grouping the remaining digits. size_t i = 0; - while((grouping[i] != '\0') && (grouping[i] != CHAR_MAX) && (pos > start + (size_t)grouping[i])) + while((grouping[i] != '\0') && (grouping[i] != '0')) { - pos -= (size_t)grouping[i]; - s.insert(pos, thousandsSep); + if (grouping[i] != ';') + { + if (pos <= start + (size_t)(grouping[i] - '0')) + break; + pos -= (size_t)(grouping[i] - '0'); + s.insert(pos, thousandsSep); + } i++; } - if ( grouping[i] == '\0' && i > 0 ) + if ( grouping[i] == '0' && i > 0 ) { - while ( pos > start + (size_t)grouping[i - 1] ) + while ( pos > start + (size_t)(grouping[i - 2] - '0')) { - pos -= (size_t)grouping[i - 1]; + pos -= (size_t)(grouping[i - 2] - '0'); s.insert(pos, thousandsSep); } }