From 608718dd9c89dbe1a3be9297fa5957eb5909a873 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 29 Aug 2021 00:38:36 +0200 Subject: [PATCH] Separate creating wxUILocaleImpl from using it Add Use() virtual function which can be used if the newly created wxUILocaleImpl object should be used as the default UI locale. Currently Use() is always called after creating a new wxUILocaleImpl, so adding a separate function just seems to complicate matters needlessly, but this won't be the case any more soon, when wxUILocaleImpl could be created for using them for other purposes than making them the default. No real changes yet. --- include/wx/private/uilocale.h | 11 ++++- src/common/uilocale.cpp | 7 ++++ src/msw/uilocale.cpp | 9 +++- src/osx/core/uilocale.mm | 8 ++++ src/unix/uilocale.cpp | 78 +++++++++++++++++++++-------------- 5 files changed, 80 insertions(+), 33 deletions(-) diff --git a/include/wx/private/uilocale.h b/include/wx/private/uilocale.h index bfa6f318ea..af8e3dcedc 100644 --- a/include/wx/private/uilocale.h +++ b/include/wx/private/uilocale.h @@ -33,8 +33,8 @@ public: // It may return NULL in case of failure. static wxUILocaleImpl* CreateUserDefault(); - // This function exists only for wxLocale compatibility and sets the locale - // corresponding to the given language. + // This function exists only for wxLocale compatibility and creates the + // locale corresponding to the given language. // // The language passed to this function is a valid language, i.e. neither // wxLANGUAGE_UNKNOWN nor wxLANGUAGE_DEFAULT. @@ -42,6 +42,13 @@ public: // It may return NULL in case of failure. static wxUILocaleImpl* CreateForLanguage(const wxLanguageInfo& info); + // Use this locale in the UI. + // + // This is not implemented for all platforms, notably not for Mac where the + // UI locale is determined at application startup, and so this function + // always returns false there. + virtual bool Use() = 0; + // Functions corresponding to wxUILocale ones. virtual wxString GetName() const = 0; virtual wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const = 0; diff --git a/src/common/uilocale.cpp b/src/common/uilocale.cpp index 4843f823e5..0cd095c879 100644 --- a/src/common/uilocale.cpp +++ b/src/common/uilocale.cpp @@ -48,6 +48,7 @@ bool wxUILocale::UseDefault() if ( !impl ) return false; + impl->Use(); ms_current.SetImpl(impl); return true; @@ -60,6 +61,12 @@ bool wxUILocale::UseLanguage(const wxLanguageInfo& info) if ( !impl ) return false; + if ( !impl->Use() ) + { + delete impl; + return false; + } + ms_current.SetImpl(impl); return true; diff --git a/src/msw/uilocale.cpp b/src/msw/uilocale.cpp index fa942fc7b9..be2583eba3 100644 --- a/src/msw/uilocale.cpp +++ b/src/msw/uilocale.cpp @@ -142,7 +142,14 @@ public: explicit wxUILocaleImplLCID(LCID lcid) : m_lcid(lcid) { - wxUseLCID(lcid); + } + + bool Use() wxOVERRIDE + { + wxUseLCID(m_lcid); + + // As long as we use a valid LCID (and we always do), it shouldn't fail. + return true; } wxString GetName() const wxOVERRIDE diff --git a/src/osx/core/uilocale.mm b/src/osx/core/uilocale.mm index 63d21ce6d8..7c9625ec28 100644 --- a/src/osx/core/uilocale.mm +++ b/src/osx/core/uilocale.mm @@ -87,6 +87,7 @@ public: return new wxUILocaleImplCF(cfloc); } + bool Use() wxOVERRIDE; wxString GetName() const wxOVERRIDE; wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE; @@ -102,6 +103,13 @@ private: // implementation // ============================================================================ +bool +wxUILocaleImplCF::Use() +{ + // There is no way to start using a locale other than default. + return false; +} + wxString wxUILocaleImplCF::GetName() const { diff --git a/src/unix/uilocale.cpp b/src/unix/uilocale.cpp index 405f53df89..eccb44594d 100644 --- a/src/unix/uilocale.cpp +++ b/src/unix/uilocale.cpp @@ -43,11 +43,16 @@ class wxUILocaleImplUnix : public wxUILocaleImpl public: // Locale argument may be NULL to not change it at all. explicit wxUILocaleImplUnix(const char* locale); + ~wxUILocaleImplUnix() wxOVERRIDE; + bool Use() wxOVERRIDE; wxString GetName() const wxOVERRIDE; wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE; private: + // This pointer is owned by this class and may be NULL. + char* const m_name; + wxDECLARE_NO_COPY_CLASS(wxUILocaleImplUnix); }; @@ -142,15 +147,54 @@ const char *wxSetlocaleTryAll(int c, const wxString& lc) // ---------------------------------------------------------------------------- wxUILocaleImplUnix::wxUILocaleImplUnix(const char* locale) + : m_name(locale ? strdup(locale) : NULL) { - if ( locale ) - setlocale(LC_ALL, locale); +} + +wxUILocaleImplUnix::~wxUILocaleImplUnix() +{ + free(m_name); +} + +bool +wxUILocaleImplUnix::Use() +{ + if ( !m_name ) + { + // This is the default locale, it is already in use. + return true; + } + + const wxString& shortName = wxString::FromAscii(m_name); + + if ( !wxSetlocaleTryAll(LC_ALL, shortName) ) + { + // Some C libraries (namely glibc) still use old ISO 639, + // so will translate the abbrev for them + wxString localeAlt; + const wxString& langOnly = ExtractLang(shortName); + if ( langOnly == wxS("he") ) + localeAlt = wxS("iw") + ExtractNotLang(shortName); + else if ( langOnly == wxS("id") ) + localeAlt = wxS("in") + ExtractNotLang(shortName); + else if ( langOnly == wxS("yi") ) + localeAlt = wxS("ji") + ExtractNotLang(shortName); + else if ( langOnly == wxS("nb") ) + localeAlt = wxS("no_NO"); + else if ( langOnly == wxS("nn") ) + localeAlt = wxS("no_NY"); + + if ( localeAlt.empty() || !wxSetlocaleTryAll(LC_ALL, localeAlt) ) + return false; + } + + return true; } wxString wxUILocaleImplUnix::GetName() const { - return wxString::FromAscii(setlocale(LC_ALL, NULL)); + return wxString::FromAscii(m_name ? m_name : setlocale(LC_ALL, NULL)); } wxString @@ -217,33 +261,7 @@ wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault() /* static */ wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info) { - // Set the locale before creating the wxUILocaleImplUnix object in order to - // check if we succeed in doing it. - - const wxString& shortName = info.CanonicalName; - - if ( !wxSetlocaleTryAll(LC_ALL, shortName) ) - { - // Some C libraries (namely glibc) still use old ISO 639, - // so will translate the abbrev for them - wxString localeAlt; - const wxString& langOnly = ExtractLang(shortName); - if ( langOnly == wxS("he") ) - localeAlt = wxS("iw") + ExtractNotLang(shortName); - else if ( langOnly == wxS("id") ) - localeAlt = wxS("in") + ExtractNotLang(shortName); - else if ( langOnly == wxS("yi") ) - localeAlt = wxS("ji") + ExtractNotLang(shortName); - else if ( langOnly == wxS("nb") ) - localeAlt = wxS("no_NO"); - else if ( langOnly == wxS("nn") ) - localeAlt = wxS("no_NY"); - - if ( localeAlt.empty() || !wxSetlocaleTryAll(LC_ALL, localeAlt) ) - return NULL; - } - - return new wxUILocaleImplUnix(NULL); + return new wxUILocaleImplUnix(info.CanonicalName); } #endif // wxUSE_INTL