]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
No res-include for rpmspec wx24dsp
[wxWidgets.git] / src / common / strconv.cpp
index 50571277e74f536f153cef1b21b928c5e0516b72..76282821dbe1bd887e5d727add6bee9f62c2d382 100644 (file)
@@ -70,6 +70,7 @@
 
 #ifdef HAVE_ICONV
     #include <iconv.h>
+    #include "wx/thread.h"
 #endif
 
 #include "wx/encconv.h"
@@ -402,7 +403,6 @@ static const unsigned char utf7unb64[] =
 
 size_t wxMBConvUTF7::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 {
-
     size_t len = 0;
 
     while (*psz && ((!buf) || (len < n)))
@@ -492,8 +492,7 @@ static const unsigned char utf7encode[128] =
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3
 };
 
-size_t wxMBConvUTF7::WC2MB(char *buf, const wchar_t 
-*psz, size_t n) const
+size_t wxMBConvUTF7::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 {
 
 
@@ -1148,12 +1147,13 @@ size_t wxMBConvUTF32swap::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 
 #ifdef HAVE_ICONV
 
-// VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with E2BIG
-//     if output buffer is _exactly_ as big as needed. Such case is (unless there's
-//     yet another bug in glibc) the only case when iconv() returns with (size_t)-1
-//     (which means error) and says there are 0 bytes left in the input buffer --
-//     when _real_ error occurs, bytes-left-in-input buffer is non-zero. Hence,
-//     this alternative test for iconv() failure.
+// VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with
+//     E2BIG if output buffer is _exactly_ as big as needed. Such case is
+//     (unless there's yet another bug in glibc) the only case when iconv()
+//     returns with (size_t)-1 (which means error) and says there are 0 bytes
+//     left in the input buffer -- when _real_ error occurs,
+//     bytes-left-in-input buffer is non-zero. Hence, this alternative test for
+//     iconv() failure.
 //     [This bug does not appear in glibc 2.2.]
 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1
 #define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \
@@ -1185,6 +1185,10 @@ protected:
     // the other direction
     iconv_t m2w,
             w2m;
+#if wxUSE_THREADS
+    // guards access to m2w and w2m objects
+    wxMutex m_iconvMutex;
+#endif
 
 private:
     // the name (for iconv_open()) of a wide char charset -- if none is
@@ -1296,6 +1300,16 @@ wxMBConv_iconv::~wxMBConv_iconv()
 
 size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 {
+#if wxUSE_THREADS
+    // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle.
+    //     Unfortunately there is a couple of global wxCSConv objects such as
+    //     wxConvLocal that are used all over wx code, so we have to make sure
+    //     the handle is used by at most one thread at the time. Otherwise
+    //     only a few wx classes would be safe to use from non-main threads
+    //     as MB<->WC conversion would fail "randomly".
+    wxMutexLocker lock(wxConstCast(this, wxMBConv_iconv)->m_iconvMutex);
+#endif
     size_t inbuf = strlen(psz);
     size_t outbuf = n * SIZEOF_WCHAR_T;
     size_t res, cres;
@@ -1353,6 +1367,11 @@ size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 
 size_t wxMBConv_iconv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 {
+#if wxUSE_THREADS
+    // NB: explained in MB2WC
+    wxMutexLocker lock(wxConstCast(this, wxMBConv_iconv)->m_iconvMutex);
+#endif
+    
     size_t inbuf = wxWcslen(psz) * SIZEOF_WCHAR_T;
     size_t outbuf = n;
     size_t res, cres;
@@ -1456,10 +1475,20 @@ public:
         // and break the library itself, e.g. wxTextInputStream::NextChar()
         // wouldn't work if reading an incomplete MB char didn't result in an
         // error
+        //
+        // note however that using MB_ERR_INVALID_CHARS with CP_UTF7 results in
+        // an error (tested under Windows Server 2003) and apparently it is
+        // done on purpose, i.e. the function accepts any input in this case
+        // and although I'd prefer to return error on ill-formed output, our
+        // own wxMBConvUTF7 doesn't detect errors (e.g. lone "+" which is
+        // explicitly ill-formed according to RFC 2152) neither so we don't
+        // even have any fallback here...
+        int flags = m_CodePage == CP_UTF7 ? 0 : MB_ERR_INVALID_CHARS;
+
         const size_t len = ::MultiByteToWideChar
                              (
                                 m_CodePage,     // code page
-                                MB_ERR_INVALID_CHARS, // flags: fall on error
+                                flags,          // flags: fall on error
                                 psz,            // input string
                                 -1,             // its length (NUL-terminated)
                                 buf,            // output string
@@ -1867,10 +1896,12 @@ public:
         Init(CFStringGetSystemEncoding()) ;
     }
 
+#if wxUSE_FONTMAP
     wxMBConv_cocoa(const wxChar* name)
     {
         Init( wxCFStringEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name, false) ) ) ;
     }
+#endif
 
     wxMBConv_cocoa(wxFontEncoding encoding)
     {
@@ -2013,10 +2044,12 @@ public:
         Init(CFStringGetSystemEncoding()) ;
     }
 
+#if wxUSE_FONTMAP
     wxMBConv_mac(const wxChar* name)
     {
         Init( wxMacGetSystemEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name, false) ) ) ;
     }
+#endif
 
     wxMBConv_mac(wxFontEncoding encoding)
     {
@@ -2195,7 +2228,10 @@ public:
     {
         size_t inbuf = strlen(psz);
         if (buf)
-            m2w.Convert(psz,buf);
+        {
+            if (!m2w.Convert(psz,buf))
+                return (size_t)-1;
+        }
         return inbuf;
     }
 
@@ -2203,7 +2239,10 @@ public:
     {
         const size_t inbuf = wxWcslen(psz);
         if (buf)
-            w2m.Convert(psz,buf);
+        {
+            if (!w2m.Convert(psz,buf))
+                return (size_t)-1;
+        }
 
         return inbuf;
     }
@@ -2360,8 +2399,12 @@ wxMBConv *wxCSConv::DoCreate() const
         if ( m_name || ( m_encoding < wxFONTENCODING_UTF16BE ) )
         {
 
+#if wxUSE_FONTMAP
             wxMBConv_mac *conv = m_name ? new wxMBConv_mac(m_name)
                                         : new wxMBConv_mac(m_encoding);
+#else
+            wxMBConv_mac *conv = new wxMBConv_mac(m_encoding);
+#endif
             if ( conv->IsOk() )
                  return conv;
 
@@ -2374,8 +2417,12 @@ wxMBConv *wxCSConv::DoCreate() const
         if ( m_name || ( m_encoding <= wxFONTENCODING_UTF16 ) )
         {
 
+#if wxUSE_FONTMAP
             wxMBConv_cocoa *conv = m_name ? new wxMBConv_cocoa(m_name)
                                           : new wxMBConv_cocoa(m_encoding);
+#else
+            wxMBConv_cocoa *conv = new wxMBConv_cocoa(m_encoding);
+#endif
             if ( conv->IsOk() )
                  return conv;