From 1c8af332cf677db4e2df521e102af3a3fe070be0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 26 Apr 2021 11:59:43 +0100 Subject: [PATCH] Only set wxLocale as active once it has been fully initialized Previously wxLocale object was set as the global local as soon as it was created, even when the default ctor was used, i.e. the locale wasn't really changed at all. This was always wrong, but only started to result in visible problems since the changes of c6d6ec9295 (Merge branch 'msw-fix-decimal-point' of https://github.com/vslavik/wxWidgets, 2021-04-18) as we now could use the existing but not yet active locale when checking for the decimal separator mismatch, resulting in spurious asserts. Fix this by postponing the call to wxSetLocale() and the rest of what was previously done in the ctor until Init() is called (which is done by all non default ctors). Closes https://github.com/wxWidgets/wxWidgets/pull/2350 Closes #19154. --- include/wx/intl.h | 7 ++--- src/common/intl.cpp | 65 +++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/include/wx/intl.h b/include/wx/intl.h index c551042754..2ce148dd54 100644 --- a/include/wx/intl.h +++ b/include/wx/intl.h @@ -333,8 +333,8 @@ public: static void DestroyLanguagesDB(); private: - // This method is trivial and just updates the corresponding member - // variables without doing anything else. + // This method updates the member fields when this locale is actually set + // as active. void DoInit(const wxString& name, const wxString& shortName, int language); @@ -343,7 +343,8 @@ private: // m_langugagesInfo, called by InitLanguagesDB static void InitLanguagesDB(); - // initialize the member fields to default values + // This method is trivial and just initializes the member fields to default + // values. void DoCommonInit(); // After trying to set locale, call this method to give the appropriate diff --git a/src/common/intl.cpp b/src/common/intl.cpp index 6ec7ed6f28..fbead9f5d2 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -248,36 +248,15 @@ wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL; void wxLocale::DoCommonInit() { - // Store the current locale in order to be able to restore it in the dtor. - m_pszOldLocale = wxSetlocale(LC_ALL, NULL); - if ( m_pszOldLocale ) - m_pszOldLocale = wxStrdup(m_pszOldLocale); + m_language = wxLANGUAGE_UNKNOWN; + + m_pszOldLocale = NULL; + m_pOldLocale = NULL; #ifdef __WIN32__ - m_oldLCID = ::GetThreadLocale(); + m_oldLCID = 0; #endif - m_pOldLocale = wxSetLocale(this); - - // Set translations object, but only if the user didn't do so yet. - // This is to preserve compatibility with wx-2.8 where wxLocale was - // the only API for translations. wxLocale works as a stack, with - // latest-created one being the active one: - // wxLocale loc_fr(wxLANGUAGE_FRENCH); - // // _() returns French - // { - // wxLocale loc_cs(wxLANGUAGE_CZECH); - // // _() returns Czech - // } - // // _() returns French again - wxTranslations *oldTrans = wxTranslations::Get(); - if ( !oldTrans || - (m_pOldLocale && oldTrans == &m_pOldLocale->m_translations) ) - { - wxTranslations::SetNonOwned(&m_translations); - } - - m_language = wxLANGUAGE_UNKNOWN; m_initialized = false; } @@ -356,6 +335,35 @@ void wxLocale::DoInit(const wxString& name, m_strLocale = name; m_strShort = shortName; m_language = language; + + // Store the current locale in order to be able to restore it in the dtor. + m_pszOldLocale = wxSetlocale(LC_ALL, NULL); + if ( m_pszOldLocale ) + m_pszOldLocale = wxStrdup(m_pszOldLocale); + +#ifdef __WIN32__ + m_oldLCID = ::GetThreadLocale(); +#endif + + m_pOldLocale = wxSetLocale(this); + + // Set translations object, but only if the user didn't do so yet. + // This is to preserve compatibility with wx-2.8 where wxLocale was + // the only API for translations. wxLocale works as a stack, with + // latest-created one being the active one: + // wxLocale loc_fr(wxLANGUAGE_FRENCH); + // // _() returns French + // { + // wxLocale loc_cs(wxLANGUAGE_CZECH); + // // _() returns Czech + // } + // // _() returns French again + wxTranslations *oldTrans = wxTranslations::Get(); + if ( !oldTrans || + (m_pOldLocale && oldTrans == &m_pOldLocale->m_translations) ) + { + wxTranslations::SetNonOwned(&m_translations); + } } bool wxLocale::DoCommonPostInit(bool success, @@ -1082,6 +1090,11 @@ wxString wxLocale::GetSysName() const // clean up wxLocale::~wxLocale() { + // Nothing here needs to be done if the object had never been initialized + // successfully. + if ( !m_initialized ) + return; + // Restore old translations object. // See DoCommonInit() for explanation of why this is needed for backward // compatibility.