X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f5fb6871865e08929a113dc23f8741023fdcae72..718903fe6402bb374a801e43e856b02204401204:/src/common/strconv.cpp?ds=sidebyside diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 56e2894bd3..521b70e56f 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -70,6 +70,7 @@ #ifdef HAVE_ICONV #include + #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))) @@ -436,7 +436,7 @@ size_t wxMBConvUTF7::MB2WC(wchar_t *buf, const char *psz, size_t n) const d += cc; for (l += 6; l >= 8; lsb = !lsb) { - c = (d >> (l -= 8)) % 256; + c = (unsigned char)((d >> (l -= 8)) % 256); if (lsb) { if (buf) @@ -445,7 +445,7 @@ size_t wxMBConvUTF7::MB2WC(wchar_t *buf, const char *psz, size_t n) const } else if (buf) - *buf = c << 8; + *buf = (wchar_t)(c << 8); } } if (*psz == '-') @@ -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 { @@ -510,7 +509,7 @@ size_t wxMBConvUTF7::WC2MB(char *buf, const wchar_t len++; } #ifndef WC_UTF16 - else if (((wxUint16)cc) > 0xffff) + else if (((wxUint32)cc) > 0xffff) { // no surrogate pair generation (yet?) return (size_t)-1; @@ -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 @@ -2013,10 +2042,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 +2226,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 +2237,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 +2397,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;