]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/xlocale.cpp
fix typo; wrap lines; add some clarifications
[wxWidgets.git] / src / common / xlocale.cpp
index 1f00c13c9865b74caad7ee0dd9a6f88c586cf4ff..f66b2ab71a31e57ab8a2124f68db8c2782b47da2 100644 (file)
@@ -31,6 +31,8 @@
 
 #include "wx/xlocale.h"
 
+#include <errno.h>
+
 // ----------------------------------------------------------------------------
 // module globals
 // ----------------------------------------------------------------------------
@@ -38,6 +40,9 @@
 // This is the C locale object, it is created on demand
 static wxXLocale *gs_cLocale = NULL;
 
+wxXLocale wxNullXLocale;
+
+
 // ============================================================================
 // implementation
 // ============================================================================
@@ -71,12 +76,14 @@ wxXLocale& wxXLocale::GetCLocale()
 {
     if ( !gs_cLocale )
     {
-        gs_cLocale = new wxXLocale(wx_static_cast(wxXLocaleCTag *, NULL));
+        gs_cLocale = new wxXLocale(static_cast<wxXLocaleCTag *>(NULL));
     }
 
     return *gs_cLocale;
 }
 
+#ifdef wxHAS_XLOCALE_SUPPORT
+
 wxXLocale::wxXLocale(wxLanguage lang)
 {
     const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang);
@@ -86,12 +93,10 @@ wxXLocale::wxXLocale(wxLanguage lang)
     }
     else
     {
-        Init(info->CanonicalName);
+        Init(info->GetLocaleName().c_str());
     }
 }
 
-#ifdef wxHAS_XLOCALE_SUPPORT
-
 #if wxCHECK_VISUALC_VERSION(8)
 
 // ----------------------------------------------------------------------------
@@ -100,6 +105,9 @@ wxXLocale::wxXLocale(wxLanguage lang)
 
 void wxXLocale::Init(const char *loc)
 {
+    if (!loc || *loc == '\0')
+        return;
+
     m_locale = _create_locale(LC_ALL, loc);
 }
 
@@ -117,7 +125,38 @@ void wxXLocale::Free()
 
 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()
@@ -199,11 +238,11 @@ GEN_ISFUNC(wxIsspace_l, CTYPE_SPACE)
 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';
     }
@@ -211,11 +250,11 @@ wxUniChar wxTolower_l(const wxUniChar& c, const wxXLocale& loc)
     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';
     }
@@ -223,6 +262,85 @@ wxUniChar wxToupper_l(const wxUniChar& c, const wxXLocale& loc)
     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...
+*/
+
+#define IMPLEMENT_STRTOX_L_START                                \
+    wxCHECK(loc.IsOk(), 0);                                     \
+                                                                \
+    /* (Try to) temporary set the locale to 'C' */              \
+    const char *oldLocale = wxSetlocale(LC_NUMERIC, "");        \
+    const char *tmp = wxSetlocale(LC_NUMERIC, "C");             \
+    if ( !tmp )                                                 \
+    {                                                           \
+        /* restore the original locale */                       \
+        wxSetlocale(LC_NUMERIC, oldLocale);                     \
+        errno = EINVAL;                                         \
+            /* signal an error (better than nothing) */         \
+        return 0;                                               \
+    }                                                           \
+                                                                \
+
+
+#define IMPLEMENT_STRTOX_L_END                                  \
+    /* restore the original locale */                           \
+    wxSetlocale(LC_NUMERIC, oldLocale);                         \
+    return ret;
+
+double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc)
+{
+    IMPLEMENT_STRTOX_L_START
+    double ret = wxStrtod(str, endptr);
+    IMPLEMENT_STRTOX_L_END
+}
+
+double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc)
+{
+    IMPLEMENT_STRTOX_L_START
+    double ret = wxStrtod(str, endptr);
+    IMPLEMENT_STRTOX_L_END
+}
+
+long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
+{ 
+    IMPLEMENT_STRTOX_L_START
+    long ret = wxStrtol(str, endptr, base);
+    IMPLEMENT_STRTOX_L_END
+}
+
+long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc)
+{
+    IMPLEMENT_STRTOX_L_START
+    long ret = wxStrtol(str, endptr, base);
+    IMPLEMENT_STRTOX_L_END
+}
+
+unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
+{
+    IMPLEMENT_STRTOX_L_START
+    unsigned long ret = wxStrtoul(str, endptr, base);
+    IMPLEMENT_STRTOX_L_END
+}
+
+unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc)
+{
+    IMPLEMENT_STRTOX_L_START
+    unsigned long ret = wxStrtoul(str, endptr, base);
+    IMPLEMENT_STRTOX_L_END
+}
+
+
 #endif // !defined(wxHAS_XLOCALE_SUPPORT)
 
 #endif // wxUSE_XLOCALE