// Purpose: xlocale wrappers/impl to provide some xlocale wrappers
// Author: Brian Vanderburg II, Vadim Zeitlin
// Created: 2008-01-07
-// RCS-ID: $Id$
// Copyright: (c) 2008 Brian Vanderburg II
// 2008 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
#include "wx/xlocale.h"
+#include <errno.h>
+#include <locale.h>
+
// ----------------------------------------------------------------------------
// module globals
// ----------------------------------------------------------------------------
// This is the C locale object, it is created on demand
static wxXLocale *gs_cLocale = NULL;
+wxXLocale wxNullXLocale;
+
+
// ============================================================================
// implementation
// ============================================================================
{
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<wxXLocaleCTag *>(NULL) );
}
return *gs_cLocale;
}
+#ifdef wxHAS_XLOCALE_SUPPORT
+
wxXLocale::wxXLocale(wxLanguage lang)
{
const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang);
}
else
{
- Init(info->CanonicalName);
+ Init(info->GetLocaleName().c_str());
}
}
-#ifdef wxHAS_XLOCALE_SUPPORT
-
#if wxCHECK_VISUALC_VERSION(8)
// ----------------------------------------------------------------------------
void wxXLocale::Init(const char *loc)
{
+ if (!loc || *loc == '\0')
+ return;
+
m_locale = _create_locale(LC_ALL, loc);
}
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()
#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,
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';
}
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';
}
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