Leave NULL impl pointer in wxUILocale if locale is not supported
This finally seems better than always creating some kind of impl object, even if the locale isn't supported at all and makes all ports behave consistently, as previously CreateForLocale() only returned NULL in wxOSX implementation if the locale was unrecognized, but now all ports do this (at least when locale_t and related functions are available under Unix). Also stop returning bool from Use(), as this resulted in initializing wxLocale with any non-default language to fail under Mac: just ignore the error here, as we always did it until now, because there is nothing we can do about it anyhow.
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
#include "wx/localedefs.h"
|
||||
#include "wx/string.h"
|
||||
|
||||
// Function returning hard-coded values for the "C" locale.
|
||||
wxString wxGetStdCLocaleInfo(wxLocaleInfo index, wxLocaleCategory cat);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxUILocaleImpl provides the implementation of public wxUILocale functions
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -53,9 +56,9 @@ public:
|
||||
// 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;
|
||||
// UI locale is determined at application startup, but we can't do anything
|
||||
// about it anyhow, so we don't even bother returning an error code from it.
|
||||
virtual void Use() = 0;
|
||||
|
||||
// Functions corresponding to wxUILocale ones.
|
||||
virtual wxString GetName() const = 0;
|
||||
|
@@ -65,7 +65,7 @@ public:
|
||||
|
||||
private:
|
||||
// Default ctor is private and exists only for implementation reasons,
|
||||
// wxUILocale objects can't be invalid.
|
||||
// creating invalid wxUILocale objects doesn't make much sense.
|
||||
wxUILocale() : m_impl(NULL) { }
|
||||
|
||||
// Used by UseDefault().
|
||||
|
@@ -86,12 +86,7 @@ bool wxUILocale::UseLanguage(const wxLanguageInfo& info)
|
||||
if ( !impl )
|
||||
return false;
|
||||
|
||||
if ( !impl->Use() )
|
||||
{
|
||||
delete impl;
|
||||
return false;
|
||||
}
|
||||
|
||||
impl->Use();
|
||||
ms_current.SetImpl(impl);
|
||||
|
||||
return true;
|
||||
@@ -112,8 +107,6 @@ const wxUILocale& wxUILocale::GetCurrent()
|
||||
wxUILocale::wxUILocale(const wxLocaleIdent& localeId)
|
||||
{
|
||||
m_impl = wxUILocaleImpl::CreateForLocale(localeId);
|
||||
if ( !m_impl )
|
||||
m_impl = wxUILocaleImpl::CreateStdC();
|
||||
}
|
||||
|
||||
void wxUILocale::SetImpl(wxUILocaleImpl* impl)
|
||||
@@ -125,11 +118,17 @@ void wxUILocale::SetImpl(wxUILocaleImpl* impl)
|
||||
|
||||
wxString wxUILocale::GetName() const
|
||||
{
|
||||
if ( !m_impl )
|
||||
return wxString();
|
||||
|
||||
return m_impl->GetName();
|
||||
}
|
||||
|
||||
wxString wxUILocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
||||
{
|
||||
if ( !m_impl )
|
||||
return wxGetStdCLocaleInfo(index, cat);
|
||||
|
||||
return m_impl->GetInfo(index, cat);
|
||||
}
|
||||
|
||||
@@ -138,6 +137,17 @@ wxUILocale::CompareStrings(const wxString& lhs,
|
||||
const wxString& rhs,
|
||||
int flags) const
|
||||
{
|
||||
if ( !m_impl )
|
||||
{
|
||||
const int rc = flags & wxCompare_CaseInsensitive ? lhs.CmpNoCase(rhs)
|
||||
: lhs.Cmp(rhs);
|
||||
if ( rc < 0 )
|
||||
return -1;
|
||||
if ( rc > 0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_impl->CompareStrings(lhs, rhs, flags);
|
||||
}
|
||||
|
||||
|
@@ -114,12 +114,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool Use() wxOVERRIDE
|
||||
void 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
|
||||
@@ -200,18 +197,31 @@ public:
|
||||
return s_canUse == 1;
|
||||
}
|
||||
|
||||
// Note that "name" can be NULL here (LOCALE_NAME_USER_DEFAULT).
|
||||
explicit wxUILocaleImplName(const wchar_t* name)
|
||||
: m_name(name ? wxStrdup(name) : NULL)
|
||||
// Create object corresponding to the default user locale.
|
||||
static wxUILocaleImplName* CreateDefault()
|
||||
{
|
||||
return new wxUILocaleImplName(LOCALE_NAME_USER_DEFAULT);
|
||||
}
|
||||
|
||||
// Create object corresponding to the given locale, return NULL if not
|
||||
// supported.
|
||||
static wxUILocaleImplName* Create(const wchar_t* name)
|
||||
{
|
||||
// Getting the locale name seems to be the simplest way to see if it's
|
||||
// really supported: unknown locale result in an error here.
|
||||
if ( !ms_GetLocaleInfoEx(name, LOCALE_SNAME, NULL, 0) )
|
||||
return NULL;
|
||||
|
||||
return new wxUILocaleImplName(name);
|
||||
}
|
||||
|
||||
|
||||
~wxUILocaleImplName() wxOVERRIDE
|
||||
{
|
||||
free(const_cast<wchar_t*>(m_name));
|
||||
}
|
||||
|
||||
bool Use() wxOVERRIDE
|
||||
void Use() wxOVERRIDE
|
||||
{
|
||||
// Construct a double NUL-terminated buffer.
|
||||
wchar_t buf[256];
|
||||
@@ -224,9 +234,7 @@ public:
|
||||
ULONG num = 1;
|
||||
|
||||
if ( !ms_SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, buf, &num) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
wxLogLastError(wxT("SetThreadPreferredUILanguages"));
|
||||
}
|
||||
|
||||
wxString GetName() const wxOVERRIDE
|
||||
@@ -331,6 +339,15 @@ private:
|
||||
LPARAM);
|
||||
static CompareStringEx_t ms_CompareStringEx;
|
||||
|
||||
|
||||
// Ctor is private, use CreateDefault() or Create() instead.
|
||||
//
|
||||
// Note that "name" can be NULL here (LOCALE_NAME_USER_DEFAULT).
|
||||
explicit wxUILocaleImplName(const wchar_t* name)
|
||||
: m_name(name ? wxStrdup(name) : NULL)
|
||||
{
|
||||
}
|
||||
|
||||
wxString DoGetInfo(LCTYPE lctype) const
|
||||
{
|
||||
wchar_t buf[256];
|
||||
@@ -366,7 +383,7 @@ wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
|
||||
return new wxUILocaleImplLCID(lcid);
|
||||
}
|
||||
|
||||
return new wxUILocaleImplName(L"en-US");
|
||||
return wxUILocaleImplName::Create(L"en-US");
|
||||
}
|
||||
|
||||
/* static */
|
||||
@@ -375,7 +392,7 @@ wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
|
||||
if ( !wxUILocaleImplName::CanUse() )
|
||||
return new wxUILocaleImplLCID(LOCALE_USER_DEFAULT);
|
||||
|
||||
return new wxUILocaleImplName(LOCALE_NAME_USER_DEFAULT);
|
||||
return wxUILocaleImplName::CreateDefault();
|
||||
}
|
||||
|
||||
/* static */
|
||||
@@ -403,7 +420,7 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locId)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new wxUILocaleImplName(locId.GetName());
|
||||
return wxUILocaleImplName::Create(locId.GetName().wc_str());
|
||||
}
|
||||
|
||||
#endif // wxUSE_INTL
|
||||
|
@@ -88,7 +88,7 @@ public:
|
||||
return new wxUILocaleImplCF(cfloc);
|
||||
}
|
||||
|
||||
bool Use() wxOVERRIDE;
|
||||
void Use() wxOVERRIDE;
|
||||
wxString GetName() const wxOVERRIDE;
|
||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||
@@ -106,11 +106,11 @@ private:
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
bool
|
||||
void
|
||||
wxUILocaleImplCF::Use()
|
||||
{
|
||||
// There is no way to start using a locale other than default.
|
||||
return false;
|
||||
// There is no way to start using a locale other than default, so there is
|
||||
// nothing to do here.
|
||||
}
|
||||
|
||||
wxString
|
||||
|
@@ -41,10 +41,16 @@ namespace
|
||||
class wxUILocaleImplUnix : public wxUILocaleImpl
|
||||
{
|
||||
public:
|
||||
explicit wxUILocaleImplUnix(wxLocaleIdent locId);
|
||||
// If "loc" is non-NULL, this object takes ownership of it and will free it.
|
||||
explicit wxUILocaleImplUnix(wxLocaleIdent locId
|
||||
#ifdef HAVE_LOCALE_T
|
||||
, locale_t loc = NULL
|
||||
#endif // HAVE_LOCALE_T
|
||||
);
|
||||
~wxUILocaleImplUnix() wxOVERRIDE;
|
||||
|
||||
bool Use() wxOVERRIDE;
|
||||
void Use() wxOVERRIDE;
|
||||
|
||||
wxString GetName() const wxOVERRIDE;
|
||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||
@@ -56,12 +62,6 @@ private:
|
||||
const char* GetLangInfo(nl_item item) const;
|
||||
#endif // HAVE_LANGINFO_H
|
||||
|
||||
#ifdef HAVE_LOCALE_T
|
||||
// On success, set m_locale and change m_locId to the given one.
|
||||
// Otherwise just return false.
|
||||
bool TryCreateLocale(const wxLocaleIdent& locId);
|
||||
#endif // HAVE_LOCALE_T
|
||||
|
||||
wxLocaleIdent m_locId;
|
||||
|
||||
#ifdef HAVE_LOCALE_T
|
||||
@@ -72,6 +72,16 @@ private:
|
||||
wxDECLARE_NO_COPY_CLASS(wxUILocaleImplUnix);
|
||||
};
|
||||
|
||||
#ifdef HAVE_LOCALE_T
|
||||
|
||||
// Simple wrapper around newlocale().
|
||||
inline locale_t TryCreateLocale(const wxLocaleIdent& locId)
|
||||
{
|
||||
return newlocale(LC_ALL_MASK, locId.GetName().mb_str(), NULL);
|
||||
}
|
||||
|
||||
#endif // HAVE_LOCALE_T
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ============================================================================
|
||||
@@ -162,56 +172,16 @@ const char *wxSetlocaleTryAll(int c, const wxString& lc)
|
||||
// wxUILocale implementation for Unix
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxUILocaleImplUnix::wxUILocaleImplUnix(wxLocaleIdent locId
|
||||
#ifdef HAVE_LOCALE_T
|
||||
|
||||
bool
|
||||
wxUILocaleImplUnix::TryCreateLocale(const wxLocaleIdent& locId)
|
||||
{
|
||||
m_locale = newlocale(LC_ALL_MASK, locId.GetName(), NULL);
|
||||
if ( !m_locale )
|
||||
return false;
|
||||
|
||||
m_locId = locId;
|
||||
return true;
|
||||
}
|
||||
|
||||
, locale_t loc
|
||||
#endif // HAVE_LOCALE_T
|
||||
|
||||
wxUILocaleImplUnix::wxUILocaleImplUnix(wxLocaleIdent locId)
|
||||
)
|
||||
: m_locId(locId)
|
||||
{
|
||||
#ifdef HAVE_LOCALE_T
|
||||
if ( !TryCreateLocale(locId) )
|
||||
{
|
||||
// Try to find a variant of this locale available on this system: first
|
||||
// of all, using just the language, without the territory, typically
|
||||
// does _not_ work under Linux, so try adding one if we don't have it.
|
||||
if ( locId.GetRegion().empty() )
|
||||
{
|
||||
const wxLanguageInfo* const info =
|
||||
wxLocale::FindLanguageInfo(locId.GetLanguage());
|
||||
if ( info )
|
||||
{
|
||||
wxString region = info->CanonicalName.AfterFirst('_');
|
||||
if ( !region.empty() )
|
||||
{
|
||||
// We never have encoding in our canonical names, but we
|
||||
// can have modifiers, so get rid of them if necessary.
|
||||
region = region.BeforeFirst('@');
|
||||
|
||||
TryCreateLocale(locId.Region(region));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And sometimes the locale without encoding is not available, but one
|
||||
// with UTF-8 encoding is, so try this too.
|
||||
if ( !m_locale && locId.GetCharset().empty() )
|
||||
{
|
||||
TryCreateLocale(locId.Charset("UTF-8"));
|
||||
}
|
||||
}
|
||||
, m_locale(loc)
|
||||
#endif // HAVE_LOCALE_T
|
||||
{
|
||||
}
|
||||
|
||||
wxUILocaleImplUnix::~wxUILocaleImplUnix()
|
||||
@@ -222,13 +192,13 @@ wxUILocaleImplUnix::~wxUILocaleImplUnix()
|
||||
#endif // HAVE_LOCALE_T
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
wxUILocaleImplUnix::Use()
|
||||
{
|
||||
if ( m_locId.IsDefault() )
|
||||
{
|
||||
// This is the default locale, it is already in use.
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
const wxString& shortName = m_locId.GetName();
|
||||
@@ -250,11 +220,9 @@ wxUILocaleImplUnix::Use()
|
||||
else if ( langOnly == wxS("nn") )
|
||||
localeAlt = wxS("no_NY");
|
||||
|
||||
if ( localeAlt.empty() || !wxSetlocaleTryAll(LC_ALL, localeAlt) )
|
||||
return false;
|
||||
if ( !localeAlt.empty() )
|
||||
wxSetlocaleTryAll(LC_ALL, localeAlt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString
|
||||
@@ -363,9 +331,53 @@ wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
|
||||
}
|
||||
|
||||
/* static */
|
||||
wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locId)
|
||||
wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locIdOrig)
|
||||
{
|
||||
return new wxUILocaleImplUnix(locId);
|
||||
#ifdef HAVE_LOCALE_T
|
||||
// Make a copy of it because it can be modified below.
|
||||
wxLocaleIdent locId = locIdOrig;
|
||||
|
||||
locale_t loc = TryCreateLocale(locId);
|
||||
if ( !loc )
|
||||
{
|
||||
// Try to find a variant of this locale available on this system: first
|
||||
// of all, using just the language, without the territory, typically
|
||||
// does _not_ work under Linux, so try adding one if we don't have it.
|
||||
if ( locId.GetRegion().empty() )
|
||||
{
|
||||
const wxLanguageInfo* const info =
|
||||
wxLocale::FindLanguageInfo(locId.GetLanguage());
|
||||
if ( info )
|
||||
{
|
||||
wxString region = info->CanonicalName.AfterFirst('_');
|
||||
if ( !region.empty() )
|
||||
{
|
||||
// We never have encoding in our canonical names, but we
|
||||
// can have modifiers, so get rid of them if necessary.
|
||||
region = region.BeforeFirst('@');
|
||||
|
||||
loc = TryCreateLocale(locId.Region(region));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And sometimes the locale without encoding is not available, but one
|
||||
// with UTF-8 encoding is, so try this too.
|
||||
if ( !loc && locId.GetCharset().empty() )
|
||||
{
|
||||
loc = TryCreateLocale(locId.Charset("UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
if ( !loc )
|
||||
return NULL;
|
||||
|
||||
return new wxUILocaleImplUnix(locId, loc);
|
||||
#else // !HAVE_LOCALE_T
|
||||
// We can't check locale availability without changing it in this case, so
|
||||
// just assume it's valid.
|
||||
return new wxUILocaleImplUnix(locIdOrig);
|
||||
#endif // HAVE_LOCALE_T/!HAVE_LOCALE_T
|
||||
}
|
||||
|
||||
#endif // wxUSE_INTL
|
||||
|
Reference in New Issue
Block a user