X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6e4ae332ac7d85be3592640ffef56a60924cc1c9..603cfe42185349e119ba4c69bd56a79998babcc4:/src/common/xlocale.cpp diff --git a/src/common/xlocale.cpp b/src/common/xlocale.cpp index 1f00c13c98..d0197463f8 100644 --- a/src/common/xlocale.cpp +++ b/src/common/xlocale.cpp @@ -31,6 +31,9 @@ #include "wx/xlocale.h" +#include +#include + // ---------------------------------------------------------------------------- // module globals // ---------------------------------------------------------------------------- @@ -38,6 +41,9 @@ // This is the C locale object, it is created on demand static wxXLocale *gs_cLocale = NULL; +wxXLocale wxNullXLocale; + + // ============================================================================ // implementation // ============================================================================ @@ -71,12 +77,16 @@ wxXLocale& wxXLocale::GetCLocale() { if ( !gs_cLocale ) { - gs_cLocale = new wxXLocale(wx_static_cast(wxXLocaleCTag *, NULL)); + // NOTE: bcc551 has trouble doing static_cast with incomplete + // type definition. reinterpret_cast used as workaround + gs_cLocale = new wxXLocale( reinterpret_cast(NULL) ); } return *gs_cLocale; } +#ifdef wxHAS_XLOCALE_SUPPORT + wxXLocale::wxXLocale(wxLanguage lang) { const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang); @@ -86,12 +96,10 @@ wxXLocale::wxXLocale(wxLanguage lang) } else { - Init(info->CanonicalName); + Init(info->GetLocaleName().c_str()); } } -#ifdef wxHAS_XLOCALE_SUPPORT - #if wxCHECK_VISUALC_VERSION(8) // ---------------------------------------------------------------------------- @@ -100,6 +108,9 @@ wxXLocale::wxXLocale(wxLanguage lang) void wxXLocale::Init(const char *loc) { + if (!loc || *loc == '\0') + return; + m_locale = _create_locale(LC_ALL, loc); } @@ -117,7 +128,38 @@ void wxXLocale::Free() void wxXLocale::Init(const char *loc) { + if (!loc || *loc == '\0') + return; + m_locale = newlocale(LC_ALL_MASK, loc, NULL); + if (!m_locale) + { + // NOTE: here we do something similar to what wxSetLocaleTryUTF8() does + // in wxLocale code (but with newlocale() calls instead of wxSetlocale()) + wxString buf(loc); + wxString buf2; + buf2 = buf + wxS(".UTF-8"); + m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); + if ( !m_locale ) + { + buf2 = buf + wxS(".utf-8"); + m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); + } + if ( !m_locale ) + { + buf2 = buf + wxS(".UTF8"); + m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); + } + if ( !m_locale ) + { + buf2 = buf + wxS(".utf8"); + m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); + } + } + + // TODO: wxLocale performs many more manipulations of the given locale + // string in the attempt to set a valid locale; reusing that code + // (changing it to take a generic wxTryLocale callback) would be nice } void wxXLocale::Free() @@ -155,7 +197,7 @@ void wxXLocale::Free() #define CTYPE_UPPER 0x0200 #define CTYPE_XDIGIT 0x0400 -static unsigned int gs_lookup[] = +static const unsigned int gs_lookup[] = { 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0004, @@ -199,11 +241,11 @@ GEN_ISFUNC(wxIsspace_l, CTYPE_SPACE) GEN_ISFUNC(wxIsupper_l, CTYPE_UPPER) GEN_ISFUNC(wxIsxdigit_l, CTYPE_XDIGIT) -wxUniChar wxTolower_l(const wxUniChar& c, const wxXLocale& loc) +int wxTolower_l(const wxUniChar& c, const wxXLocale& loc) { wxCHECK(loc.IsOk(), false); - if(CTYPE_TEST(c, CTYPE_UPPER)) + if(CTYPE_TEST(c.GetValue(), CTYPE_UPPER)) { return c - 'A' + 'a'; } @@ -211,11 +253,11 @@ wxUniChar wxTolower_l(const wxUniChar& c, const wxXLocale& loc) return c; } -wxUniChar wxToupper_l(const wxUniChar& c, const wxXLocale& loc) +int wxToupper_l(const wxUniChar& c, const wxXLocale& loc) { wxCHECK(loc.IsOk(), false); - if(CTYPE_TEST(c, CTYPE_LOWER)) + if(CTYPE_TEST(c.GetValue(), CTYPE_LOWER)) { return c - 'a' + 'A'; } @@ -223,6 +265,106 @@ wxUniChar wxToupper_l(const wxUniChar& c, const wxXLocale& loc) return c; } + +// ---------------------------------------------------------------------------- +// string --> number conversion functions +// ---------------------------------------------------------------------------- + +/* + WARNING: the implementation of the wxStrtoX_l() functions below is unsafe + in a multi-threaded environment as we temporary change the locale + and if in the meanwhile an other thread performs some locale-dependent + operation, it may get unexpected results... + However this is the best we can do without reinventing the wheel in the + case !wxHAS_XLOCALE_SUPPORT... +*/ + +namespace +{ + +// Helper class that changes LC_NUMERIC facet of the global locale in its ctor +// to "C" locale and restores it in its dtor later. +class CNumericLocaleSetter +{ +public: + CNumericLocaleSetter() + : m_oldLocale(wxStrdupA(setlocale(LC_NUMERIC, NULL))) + { + if ( !wxSetlocale(LC_NUMERIC, "C") ) + { + // Setting locale to "C" should really always work. + wxFAIL_MSG( wxS("Couldn't set LC_NUMERIC to \"C\"") ); + } + } + + ~CNumericLocaleSetter() + { + wxSetlocale(LC_NUMERIC, m_oldLocale); + free(m_oldLocale); + } + +private: + char * const m_oldLocale; + + wxDECLARE_NO_COPY_CLASS(CNumericLocaleSetter); +}; + +} // anonymous namespace + +double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0. ); + + CNumericLocaleSetter locSetter; + + return wxStrtod(str, endptr); +} + +double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0. ); + + CNumericLocaleSetter locSetter; + + return wxStrtod(str, endptr); +} + +long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0 ); + + CNumericLocaleSetter locSetter; + + return wxStrtol(str, endptr, base); +} + +long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0 ); + + CNumericLocaleSetter locSetter; + + return wxStrtol(str, endptr, base); +} + +unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0 ); + + CNumericLocaleSetter locSetter; + + return wxStrtoul(str, endptr, base); +} + +unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc) +{ + wxCHECK( loc.IsOk(), 0 ); + + CNumericLocaleSetter locSetter; + + return wxStrtoul(str, endptr, base); +} + #endif // !defined(wxHAS_XLOCALE_SUPPORT) #endif // wxUSE_XLOCALE