diff --git a/include/wx/private/localeset.h b/include/wx/private/localeset.h index 0320d34e9f..769af1a1ab 100644 --- a/include/wx/private/localeset.h +++ b/include/wx/private/localeset.h @@ -46,4 +46,22 @@ private: wxDECLARE_NO_COPY_CLASS(wxCLocaleSetter); }; +// This function must be called on program startup and after changing +// locale to ensure LC_CTYPE is set correctly under macOS (it does nothing +// under the other platforms currently). +inline void wxEnsureLocaleIsCompatibleWithCRT() +{ +#if defined(__WXOSX__) + // In OS X and iOS, wchar_t CRT functions convert to char* and fail under + // some locales. The safest fix is to set LC_CTYPE to UTF-8 to ensure that + // they can handle any input. + // + // Note that this must be done for any app, Cocoa or console, whether or + // not it uses wxLocale. + // + // See https://stackoverflow.com/questions/11713745/why-does-the-printf-family-of-functions-care-about-locale + setlocale(LC_CTYPE, "UTF-8"); +#endif // defined(__WXOSX__) +} + #endif // _WX_PRIVATE_LOCALESET_H_ diff --git a/src/common/init.cpp b/src/common/init.cpp index f7d5682f83..e3b315d28b 100644 --- a/src/common/init.cpp +++ b/src/common/init.cpp @@ -23,7 +23,6 @@ #include "wx/app.h" #include "wx/filefn.h" #include "wx/log.h" - #include "wx/intl.h" #include "wx/module.h" #endif @@ -50,9 +49,7 @@ #endif // wxCrtSetDbgFlag #endif // __WINDOWS__ -#if defined(__WXOSX__) - #include -#endif +#include "wx/private/localeset.h" #include @@ -217,17 +214,9 @@ static void FreeConvertedArgs() // initialization which is always done (not customizable) before wxApp creation static bool DoCommonPreInit() { -#if defined(__WXOSX__) - // In OS X and iOS, wchar_t CRT functions convert to char* and fail under - // some locales. The safest fix is to set LC_CTYPE to UTF-8 to ensure that - // they can handle any input. - // - // Note that this must be done for any app, Cocoa or console, whether or - // not it uses wxLocale. - // - // See https://stackoverflow.com/questions/11713745/why-does-the-printf-family-of-functions-care-about-locale - setlocale(LC_CTYPE, "UTF-8"); -#endif // defined(__WXOSX__) + // This is necessary even for the default locale, see comments in this + // function. + wxEnsureLocaleIsCompatibleWithCRT(); #if wxUSE_LOG // Reset logging in case we were cleaned up and are being reinitialized. diff --git a/src/common/intl.cpp b/src/common/intl.cpp index c00ee62e3f..2a7f1bbebb 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -52,6 +52,7 @@ #include "wx/hashset.h" #include "wx/uilocale.h" +#include "wx/private/localeset.h" #include "wx/private/uilocale.h" #ifdef __WIN32__ @@ -396,11 +397,8 @@ bool wxLocale::DoCommonPostInit(bool success, t->AddStdCatalog(); } -#if defined(__WXOSX__) - // LC_CTYPE is set in DoCommonPreInit() (see init.cpp). Set it again here, - // in case its value was changed/lost during wxLocale initialization. - setlocale(LC_CTYPE, "UTF-8"); -#endif // defined(__WXOSX__) + // Do this again here in case LC_CTYPE was changed by setlocale(). + wxEnsureLocaleIsCompatibleWithCRT(); return success; }