]> git.saurik.com Git - wxWidgets.git/commitdiff
added code for checking if the current locale is UTF-8 at runtime
authorVáclav Slavík <vslavik@fastmail.fm>
Mon, 23 Apr 2007 20:42:13 +0000 (20:42 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Mon, 23 Apr 2007 20:42:13 +0000 (20:42 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45609 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/chartype.h
include/wx/wxcrt.h
src/common/appbase.cpp
src/common/intl.cpp
src/common/wxcrt.cpp
src/gtk/app.cpp
src/gtk/utilsgtk.cpp

index e5ddbf0c9a19590edb1bd33b1ae2b9d93cd35d69..ea5b9f93c62109e3c5dbfee6ca3cbf03ed3106d4 100644 (file)
 /* depending on the platform, Unicode build can either store wxStrings as
    wchar_t* or UTF-8 encoded char*: */
 #if wxUSE_UNICODE
+    // FIXME-UTF8: what would be better place for this?
+    #if defined(wxUSE_UTF8_LOCALE_ONLY) && !defined(wxUSE_UNICODE_UTF8)
+        #error "wxUSE_UTF8_LOCALE_ONLY only makes sense with wxUSE_UNICODE_UTF8"
+    #endif
+    #ifndef wxUSE_UTF8_LOCALE_ONLY
+        #define wxUSE_UTF8_LOCALE_ONLY 0
+    #endif
+
     #ifndef wxUSE_UNICODE_UTF8
         #define wxUSE_UNICODE_UTF8 0
     #endif
index 461feba702a930f74321569966330f825b5895c4..74a63624d60309d923fc9e1b0294d7b106cdef77 100644 (file)
 
 #include <stdio.h>  /* we use FILE below */
 
+#ifdef __cplusplus
+    #if wxUSE_UNICODE_UTF8
+    // flag indicating whether the current locale uses UTF-8 or not; must be
+    // updated every time the locale is changed!
+    #if !wxUSE_UTF8_LOCALE_ONLY
+    extern WXDLLIMPEXP_BASE bool wxLocaleIsUtf8;
+    #endif
+    // function used to update the flag:
+    extern WXDLLIMPEXP_BASE void wxUpdateLocaleIsUtf8();
+    #else // !wxUSE_UNICODE_UTF8
+    inline WXDLLIMPEXP_BASE void wxUpdateLocaleIsUtf8() {}
+    #endif // wxUSE_UNICODE_UTF8/!wxUSE_UNICODE_UTF8
+#endif // __cplusplus
+
 #if defined(HAVE_STRTOK_R) && defined(__DARWIN__) && defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
     char *strtok_r(char *, const char *, char **);
 #endif
     #define  wxToupper(c) _totupper((wxUChar)(wxChar)(c))
 
     /* locale.h functons */
-    #define  wxSetlocale _tsetlocale
+    #define  wxSetlocale_ _tsetlocale
 
     /* string.h functions */
     #define  wxStrcat    _tcscat
         #define  wxToupper   toupper
 
          /* locale.h functons */
-        #define  wxSetlocale setlocale
+        #define  wxSetlocale_ setlocale
 
          /* string.h functions */
         #define  wxStrcat    strcat
@@ -772,11 +786,14 @@ WXDLLIMPEXP_BASE wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **sa
 #endif
 
 #ifdef __cplusplus
-#ifndef wxSetlocale
-class WXDLLIMPEXP_BASE wxWCharBuffer;
-WXDLLIMPEXP_BASE wxWCharBuffer wxSetlocale(int category, const wxChar *locale);
-#endif
-#endif
+    #ifndef wxSetlocale_
+    class WXDLLIMPEXP_BASE wxWCharBuffer;
+    WXDLLIMPEXP_BASE wxWCharBuffer wxSetlocale_(int category, const wxChar *locale);
+    WXDLLIMPEXP_BASE wxWCharBuffer wxSetlocale(int category, const wxChar *locale);
+    #else
+    WXDLLIMPEXP_BASE const wxChar *wxSetlocale(int category, const wxChar *locale);
+    #endif // defined(wxSetlocale_)
+#endif // __cplusplus
 
 /* stdio.h functions */
 #ifdef wxNEED_WX_STDIO_H
index 53d05a50fd3ff6204aed93c85ba926564458928e..79cfe27e25e76892d352ae00a74083dea5a59f73 100644 (file)
@@ -513,6 +513,7 @@ GSocketGUIFunctionsTable* wxConsoleAppTraitsBase::GetSocketGUIFunctionsTable()
 void wxAppTraitsBase::SetLocale()
 {
     setlocale(LC_ALL, "");
+    wxUpdateLocaleIsUtf8();
 }
 #endif
 
index 7f92290966f291470ca300e2247e854690aed8fc..f8129005d8f1a8e2366da9ca88f6b4502dc373c3 100644 (file)
@@ -1600,10 +1600,14 @@ bool wxLocale::Init(const wxString& name,
 
 
 #if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__)
-static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
+static wxWCharBuffer wxSetlocaleTryUTF8(int c, const wxChar *lc)
 {
-    wxMB2WXbuf l = wxSetlocale(c, lc);
-    if ( !l && lc && lc[0] != 0 )
+    wxMB2WXbuf l;
+
+    // NB: We prefer to set UTF-8 locale if it's possible and only fall back to
+    //     non-UTF-8 locale if it fails
+
+    if ( lc && lc[0] != 0 )
     {
         wxString buf(lc);
         wxString buf2;
@@ -1625,10 +1629,15 @@ static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
             l = wxSetlocale(c, buf2.c_str());
         }
     }
+
+    // if we can't set UTF-8 locale, try non-UTF-8 one:
+    if ( !l )
+        l = wxSetlocale(c, lc);
+
     return l;
 }
 #else
-#define wxSetlocaleTryUTF(c, lc)  wxSetlocale(c, lc)
+#define wxSetlocaleTryUTF8(c, lc)  wxSetlocale(c, lc)
 #endif
 
 bool wxLocale::Init(int language, int flags)
@@ -1666,13 +1675,13 @@ bool wxLocale::Init(int language, int flags)
     if (language != wxLANGUAGE_DEFAULT)
         locale = info->CanonicalName;
 
-    wxMB2WXbuf retloc = wxSetlocaleTryUTF(LC_ALL, locale);
+    wxMB2WXbuf retloc = wxSetlocaleTryUTF8(LC_ALL, locale);
 
     const wxString langOnly = locale.Left(2);
     if ( !retloc )
     {
         // Some C libraries don't like xx_YY form and require xx only
-        retloc = wxSetlocaleTryUTF(LC_ALL, langOnly);
+        retloc = wxSetlocaleTryUTF8(LC_ALL, langOnly);
     }
 
 #if wxUSE_FONTMAP
@@ -1713,9 +1722,9 @@ bool wxLocale::Init(int language, int flags)
 
         if ( !localeAlt.empty() )
         {
-            retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt);
+            retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt);
             if ( !retloc )
-                retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt.Left(2));
+                retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt.Left(2));
         }
     }
 
@@ -2741,11 +2750,11 @@ bool wxLocale::IsAvailable(int lang)
     
     // Test if setting the locale works, then set it back. 
     wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, wxEmptyString);
-    wxMB2WXbuf tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName);
+    wxMB2WXbuf tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName);
     if ( !tmp )
     {
         // Some C libraries don't like xx_YY form and require xx only
-        tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName.Left(2));
+        tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName.Left(2));
         if ( !tmp )
             return false;
     }
index 93b509bdb8f508e0ea30288523aae3864266a901..3d12a3bee776b21d138724a87cea409eedac99e4 100644 (file)
@@ -804,14 +804,30 @@ int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
 }
 #endif
 
-#ifndef wxSetlocale
-WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
+#ifndef wxSetlocale_
+wxWCharBuffer wxSetlocale_(int category, const wxChar *locale)
 {
     char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
 
     return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
 }
-#endif
+
+wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
+{
+    wxWCharBuffer rv = wxSetlocale_(category, locale);
+    if ( rv )
+        wxUpdateLocaleIsUtf8();
+    return rv;
+}
+#else // defined(wxSetlocale_)
+const wxChar *wxSetlocale(int category, const wxChar *locale)
+{
+    const wxChar *rv = wxSetlocale_(category, locale);
+    if ( rv )
+        wxUpdateLocaleIsUtf8();
+    return rv;
+}
+#endif // wxSetlocale_ defined or not
 
 #if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
 WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
@@ -1350,3 +1366,56 @@ int wxRemove(const wxChar *path)
 }
 
 #endif
+
+
+// ----------------------------------------------------------------------------
+// wxLocaleIsUtf8
+// ----------------------------------------------------------------------------
+
+#if wxUSE_UNICODE_UTF8
+
+#if !wxUSE_UTF8_LOCALE_ONLY
+bool wxLocaleIsUtf8 = false; // the safer setting if not known
+#endif
+
+static bool wxIsLocaleUtf8()
+{
+    // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
+    //     because a) it may be unavailable in some builds and b) has slightly
+    //     different semantics (default locale instead of current)
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+    // GNU libc provides current character set this way (this conforms to
+    // Unix98)
+    const char *charset = nl_langinfo(CODESET);
+    if ( charset )
+    {
+        // "UTF-8" is used by modern glibc versions, but test other variants
+        // as well, just in case:
+        return strcmp(charset, "UTF-8") == 0 ||
+               strcmp(charset, "utf-8") == 0 ||
+               strcmp(charset, "UTF8") == 0 ||
+               strcmp(charset, "utf8") == 0;
+    }
+    else // nl_langinfo() failed
+#endif
+    {
+        // we don't know what charset libc is using, so assume the worst
+        // to be safe:
+        return false;
+    }
+}
+
+void wxUpdateLocaleIsUtf8()
+{
+#if wxUSE_UTF8_LOCALE_ONLY
+    if ( !wxIsLocaleUtf8() )
+    {
+        wxLogFatalError(_T("This program requires UTF-8 locale to run."));
+    }
+#else // !wxUSE_UTF8_LOCALE_ONLY
+    wxLocaleIsUtf8 = wxIsLocaleUtf8();
+#endif
+}
+
+#endif // wxUSE_UTF8_LOCALE_ONLY
index 464b36b665ba9e42e830c3e478c13d9d469a52cf..14b556b2e5528546fd63e5c12f54e0e9aacbb424 100644 (file)
@@ -423,6 +423,7 @@ bool wxApp::Initialize(int& argc, wxChar **argv)
 #else
     init_result = gtk_init_check( &argcGTK, &argvGTK );
 #endif
+    wxUpdateLocaleIsUtf8();
 
     if ( argcGTK != argc )
     {
index c0d0309f9532ad008870bb0e8b970137c1ba3f7b..13bc7c448cae90fd89cffe932df7172ce9dda6e9 100644 (file)
@@ -362,6 +362,7 @@ static wxString GetSM()
 void wxGUIAppTraits::SetLocale()
 {
     gtk_set_locale();
+    wxUpdateLocaleIsUtf8();
 }
 #endif