]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
Fix for #15520: wxRichTextCtrl: Drawing the selection doesn't respect its container...
[wxWidgets.git] / src / common / strconv.cpp
index ae7fa502312f48e87f978f5959ed97f42dac9763..a4331280112c1c263723b020ba66134f9c472cf2 100644 (file)
@@ -5,7 +5,6 @@
 //              Ryan Norton, Fredrik Roubert (UTF7)
 // Modified by:
 // Created:     29/01/98
-// RCS-ID:      $Id$
 // Copyright:   (c) 1999 Ove Kaaven, Robert Roebling, Vaclav Slavik
 //              (c) 2000-2003 Vadim Zeitlin
 //              (c) 2004 Ryan Norton, Fredrik Roubert
@@ -28,8 +27,6 @@
 
 #include "wx/strconv.h"
 
-#if wxUSE_WCHAR_T
-
 #ifndef __WXWINCE__
 #include <errno.h>
 #endif
@@ -57,7 +54,7 @@
 #endif //def __DARWIN__
 
 
-#define TRACE_STRCONV _T("strconv")
+#define TRACE_STRCONV wxT("strconv")
 
 // WC_UTF16 is defined only if sizeof(wchar_t) == 2, otherwise it's supposed to
 // be 4 bytes
@@ -142,7 +139,7 @@ static wxUint32 wxDecodeSurrogate(const wxDecodeSurrogate_t **pSrc)
 {
     wxUint32 out;
     const size_t
-        n = decode_utf16(wx_reinterpret_cast(const wxUint16 *, *pSrc), out);
+        n = decode_utf16(reinterpret_cast<const wxUint16 *>(*pSrc), out);
     if ( n == wxCONV_FAILED )
         *pSrc = NULL;
     else
@@ -216,7 +213,7 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
     // all the complication come from the fact that this function, for
     // historical reasons, must behave in 2 subtly different ways when it's
     // called with a fixed number of characters and when it's called for the
-    // entire NUL-terminated string: in the former case (srcEnd == NULL) we
+    // entire NUL-terminated string: in the former case (srcEnd != NULL) we
     // must count all characters we convert, NUL or not; but in the latter we
     // do not count the trailing NUL -- but still count all the NULs inside the
     // string
@@ -258,11 +255,13 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
         if ( !srcEnd )
         {
             // we convert just one chunk in this case as this is the entire
-            // string anyhow
+            // string anyhow (and we don't count the trailing NUL in this case)
             break;
         }
 
-        // advance the input pointer past the end of this chunk
+        // advance the input pointer past the end of this chunk: notice that we
+        // will always stop before srcEnd because we know that the chunk is
+        // always properly NUL-terminated
         while ( NotAllNULs(src, nulLen) )
         {
             // notice that we must skip over multiple bytes here as we suppose
@@ -272,23 +271,20 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
             src += nulLen;
         }
 
-        src += nulLen; // skipping over its terminator as well
+        // if the buffer ends before this NUL, we shouldn't count it in our
+        // output so skip the code below
+        if ( src == srcEnd )
+            break;
+
+        // do count this terminator as it's inside the buffer we convert
+        dstWritten++;
+        if ( dst )
+            dst++;
+
+        src += nulLen; // skip the terminator itself
 
-        // note that ">=" (and not just "==") is needed here as the terminator
-        // we skipped just above could be inside or just after the buffer
-        // delimited by srcEnd
         if ( src >= srcEnd )
             break;
-
-        // if we got here then this wasn't the last chunk in this string and
-        // hence we must count an extra char for L'\0' even when converting a
-        // fixed number of characters
-        if ( srcEnd )
-        {
-            dstWritten++;
-            if ( dst )
-                dst++;
-        }
     }
 
     return dstWritten;
@@ -324,16 +320,22 @@ wxMBConv::FromWChar(char *dst, size_t dstLen,
     const size_t lenNul = GetMBNulLen();
     for ( const wchar_t * const srcEnd = src + srcLen;
           src < srcEnd;
-          src += wxWcslen(src) + 1 /* skip L'\0' too */ )
+          src++ /* skip L'\0' too */ )
     {
         // try to convert the current chunk
         size_t lenChunk = WC2MB(NULL, src, 0);
-
         if ( lenChunk == wxCONV_FAILED )
             return wxCONV_FAILED;
 
         dstWritten += lenChunk;
-        if ( isNulTerminated )
+
+        const wchar_t * const
+            chunkEnd = isNulTerminated ? srcEnd - 1 : src + wxWcslen(src);
+
+        // our return value accounts for the trailing NUL(s), unlike that of
+        // WC2MB(), however don't do it for the last NUL we artificially added
+        // ourselves above
+        if ( chunkEnd < srcEnd )
             dstWritten += lenNul;
 
         if ( dst )
@@ -341,13 +343,42 @@ wxMBConv::FromWChar(char *dst, size_t dstLen,
             if ( dstWritten > dstLen )
                 return wxCONV_FAILED;
 
-            if ( WC2MB(dst, src, lenChunk + lenNul) == wxCONV_FAILED )
+            // if we know that there is enough space in the destination buffer
+            // (because we accounted for lenNul in dstWritten above), we can
+            // convert directly in place -- but otherwise we need another
+            // temporary buffer to ensure that we don't overwrite the output
+            wxCharBuffer dstBuf;
+            char *dstTmp;
+            if ( chunkEnd == srcEnd )
+            {
+                dstBuf = wxCharBuffer(lenChunk + lenNul - 1);
+                dstTmp = dstBuf.data();
+            }
+            else
+            {
+                dstTmp = dst;
+            }
+
+            if ( WC2MB(dstTmp, src, lenChunk + lenNul) == wxCONV_FAILED )
                 return wxCONV_FAILED;
 
+            if ( dstTmp != dst )
+            {
+                // copy everything up to but excluding the terminating NUL(s)
+                // into the real output buffer
+                memcpy(dst, dstTmp, lenChunk);
+
+                // micro-optimization: if dstTmp != dst it means that chunkEnd
+                // == srcEnd and so we're done, no need to update anything below
+                break;
+            }
+
             dst += lenChunk;
-            if ( isNulTerminated )
+            if ( chunkEnd < srcEnd )
                 dst += lenNul;
         }
+
+        src = chunkEnd;
     }
 
     return dstWritten;
@@ -355,9 +386,7 @@ wxMBConv::FromWChar(char *dst, size_t dstLen,
 
 size_t wxMBConv::MB2WC(wchar_t *outBuff, const char *inBuff, size_t outLen) const
 {
-    // add 1 to available buffer length because MB2WC() parameter counts the
-    // number of non-NUL characters while ToWChar() counts everything
-    size_t rc = ToWChar(outBuff, outLen + 1, inBuff);
+    size_t rc = ToWChar(outBuff, outLen, inBuff);
     if ( rc != wxCONV_FAILED )
     {
         // ToWChar() returns the buffer length, i.e. including the trailing
@@ -370,12 +399,10 @@ size_t wxMBConv::MB2WC(wchar_t *outBuff, const char *inBuff, size_t outLen) cons
 
 size_t wxMBConv::WC2MB(char *outBuff, const wchar_t *inBuff, size_t outLen) const
 {
-    const size_t nulLen = GetMBNulLen();
-
-    size_t rc = FromWChar(outBuff, outLen + nulLen, inBuff);
+    size_t rc = FromWChar(outBuff, outLen, inBuff);
     if ( rc != wxCONV_FAILED )
     {
-        rc -= nulLen;
+        rc -= GetMBNulLen();
     }
 
     return rc;
@@ -432,7 +459,6 @@ wxMBConv::cMB2WC(const char *inBuff, size_t inLen, size_t *outLen) const
         // because we want the buffer to always be NUL-terminated, even if the
         // input isn't (as otherwise the caller has no way to know its length)
         wxWCharBuffer wbuf(dstLen);
-        wbuf.data()[dstLen] = L'\0';
         if ( ToWChar(wbuf.data(), dstLen, inBuff, inLen) != wxCONV_FAILED )
         {
             if ( outLen )
@@ -494,6 +520,42 @@ wxMBConv::cWC2MB(const wchar_t *inBuff, size_t inLen, size_t *outLen) const
     return wxCharBuffer();
 }
 
+const wxWCharBuffer wxMBConv::cMB2WC(const wxScopedCharBuffer& buf) const
+{
+    const size_t srcLen = buf.length();
+    if ( srcLen )
+    {
+        const size_t dstLen = ToWChar(NULL, 0, buf, srcLen);
+        if ( dstLen != wxCONV_FAILED )
+        {
+            wxWCharBuffer wbuf(dstLen);
+            wbuf.data()[dstLen] = L'\0';
+            if ( ToWChar(wbuf.data(), dstLen, buf, srcLen) != wxCONV_FAILED )
+                return wbuf;
+        }
+    }
+
+    return wxScopedWCharBuffer::CreateNonOwned(L"", 0);
+}
+
+const wxCharBuffer wxMBConv::cWC2MB(const wxScopedWCharBuffer& wbuf) const
+{
+    const size_t srcLen = wbuf.length();
+    if ( srcLen )
+    {
+        const size_t dstLen = FromWChar(NULL, 0, wbuf, srcLen);
+        if ( dstLen != wxCONV_FAILED )
+        {
+            wxCharBuffer buf(dstLen);
+            buf.data()[dstLen] = '\0';
+            if ( FromWChar(buf.data(), dstLen, wbuf, srcLen) != wxCONV_FAILED )
+                return buf;
+        }
+    }
+
+    return wxScopedCharBuffer::CreateNonOwned("", 0);
+}
+
 // ----------------------------------------------------------------------------
 // wxMBConvLibc
 // ----------------------------------------------------------------------------
@@ -516,8 +578,8 @@ size_t wxMBConvLibc::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 
 wxConvBrokenFileNames::wxConvBrokenFileNames(const wxString& charset)
 {
-    if ( wxStricmp(charset, _T("UTF-8")) == 0 ||
-         wxStricmp(charset, _T("UTF8")) == 0  )
+    if ( wxStricmp(charset, wxT("UTF-8")) == 0 ||
+         wxStricmp(charset, wxT("UTF8")) == 0  )
         m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA);
     else
         m_conv = new wxCSConv(charset);
@@ -588,7 +650,7 @@ size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen,
     }
     else // when working with partial strings we do use the shift state
     {
-        statePtr = wx_const_cast(DecoderState *, &m_stateDecoder);
+        statePtr = const_cast<DecoderState *>(&m_stateDecoder);
 
         // also save the old state to be able to rollback to it on error
         stateOrig = m_stateDecoder;
@@ -775,7 +837,7 @@ size_t wxMBConvUTF7::FromWChar(char *dst, size_t dstLen,
     else // do use the mode we left the output in previously
     {
         stateOrig = m_stateEncoder;
-        statePtr = wx_const_cast(EncoderState *, &m_stateEncoder);
+        statePtr = const_cast<EncoderState *>(&m_stateEncoder);
     }
 
     EncoderState& state = *statePtr;
@@ -931,7 +993,7 @@ wxMBConvStrictUTF8::ToWChar(wchar_t *dst, size_t dstLen,
 
     for ( const char *p = src; ; p++ )
     {
-        if ( !(srcLen == wxNO_LEN ? *p : srcLen) )
+        if ( (srcLen == wxNO_LEN ? !*p : !srcLen) )
         {
             // all done successfully, just add the trailing NULL if we are not
             // using explicit length
@@ -1051,7 +1113,7 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen,
 
     for ( const wchar_t *wp = src; ; wp++ )
     {
-        if ( !(srcLen == wxNO_LEN ? *wp : srcLen) )
+        if ( (srcLen == wxNO_LEN ? !*wp : !srcLen) )
         {
             // all done successfully, just add the trailing NULL if we are not
             // using explicit length
@@ -1081,6 +1143,8 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen,
         {
             // skip the next char too as we decoded a surrogate
             wp++;
+            if ( srcLen != wxNO_LEN )
+                srcLen--;
         }
 #else // wchar_t is UTF-32
         code = *wp & 0x7fffffff;
@@ -1141,7 +1205,7 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen,
         }
         else
         {
-            wxFAIL_MSG( _T("trying to encode undefined Unicode character") );
+            wxFAIL_MSG( wxT("trying to encode undefined Unicode character") );
             break;
         }
 
@@ -1166,7 +1230,10 @@ size_t wxMBConvUTF8::ToWChar(wchar_t *buf, size_t n,
 
     size_t len = 0;
 
-    while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
+    // The length can be either given explicitly or computed implicitly for the
+    // NUL-terminated strings.
+    const bool isNulTerminated = srcLen == wxNO_LEN;
+    while ((isNulTerminated ? *psz : srcLen--) && ((!buf) || (len < n)))
     {
         const char *opsz = psz;
         bool invalid = false;
@@ -1300,10 +1367,17 @@ size_t wxMBConvUTF8::ToWChar(wchar_t *buf, size_t n,
         }
     }
 
-    if (srcLen == wxNO_LEN && buf && (len < n))
-        *buf = 0;
+    if ( isNulTerminated )
+    {
+        // Add the trailing NUL in this case if we have a large enough buffer.
+        if ( buf && (len < n) )
+            *buf = 0;
+
+        // And count it in any case.
+        len++;
+    }
 
-    return len + 1;
+    return len;
 }
 
 static inline bool isoctal(wchar_t wch)
@@ -1319,7 +1393,10 @@ size_t wxMBConvUTF8::FromWChar(char *buf, size_t n,
 
     size_t len = 0;
 
-    while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
+    // The length can be either given explicitly or computed implicitly for the
+    // NUL-terminated strings.
+    const bool isNulTerminated = srcLen == wxNO_LEN;
+    while ((isNulTerminated ? *psz : srcLen--) && ((!buf) || (len < n)))
     {
         wxUint32 cc;
 
@@ -1387,10 +1464,17 @@ size_t wxMBConvUTF8::FromWChar(char *buf, size_t n,
         }
     }
 
-    if (srcLen == wxNO_LEN && buf && (len < n))
-        *buf = 0;
+    if ( isNulTerminated )
+    {
+        // Add the trailing NUL in this case if we have a large enough buffer.
+        if ( buf && (len < n) )
+            *buf = 0;
+
+        // And count it in any case.
+        len++;
+    }
 
-    return len + 1;
+    return len;
 }
 
 // ============================================================================
@@ -1411,7 +1495,7 @@ size_t wxMBConvUTF16Base::GetLength(const char *src, size_t srcLen)
     if ( srcLen == wxNO_LEN )
     {
         // count the number of bytes in input, including the trailing NULs
-        const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src);
+        const wxUint16 *inBuff = reinterpret_cast<const wxUint16 *>(src);
         for ( srcLen = 1; *inBuff++; srcLen++ )
             ;
 
@@ -1495,7 +1579,7 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen,
         if ( dstLen < srcLen )
             return wxCONV_FAILED;
 
-        const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src);
+        const wxUint16 *inBuff = reinterpret_cast<const wxUint16 *>(src);
         for ( size_t n = 0; n < srcLen; n++, inBuff++ )
         {
             *dst++ = wxUINT16_SWAP_ALWAYS(*inBuff);
@@ -1519,7 +1603,7 @@ wxMBConvUTF16swap::FromWChar(char *dst, size_t dstLen,
         if ( dstLen < srcLen )
             return wxCONV_FAILED;
 
-        wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst);
+        wxUint16 *outBuff = reinterpret_cast<wxUint16 *>(dst);
         for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ )
         {
             *outBuff++ = wxUINT16_SWAP_ALWAYS(*src);
@@ -1553,7 +1637,7 @@ wxMBConvUTF16straight::ToWChar(wchar_t *dst, size_t dstLen,
     }
 
     size_t outLen = 0;
-    const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src);
+    const wxUint16 *inBuff = reinterpret_cast<const wxUint16 *>(src);
     for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; )
     {
         const wxUint32 ch = wxDecodeSurrogate(&inBuff);
@@ -1578,10 +1662,10 @@ wxMBConvUTF16straight::FromWChar(char *dst, size_t dstLen,
         srcLen = wxWcslen(src) + 1;
 
     size_t outLen = 0;
-    wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst);
+    wxUint16 *outBuff = reinterpret_cast<wxUint16 *>(dst);
     for ( size_t n = 0; n < srcLen; n++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*src++, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1626,7 +1710,7 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen,
     }
 
     size_t outLen = 0;
-    const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src);
+    const wxUint16 *inBuff = reinterpret_cast<const wxUint16 *>(src);
     for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; )
     {
         wxUint32 ch;
@@ -1661,10 +1745,10 @@ wxMBConvUTF16swap::FromWChar(char *dst, size_t dstLen,
         srcLen = wxWcslen(src) + 1;
 
     size_t outLen = 0;
-    wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst);
+    wxUint16 *outBuff = reinterpret_cast<wxUint16 *>(dst);
     for ( const wchar_t *srcEnd = src + srcLen; src < srcEnd; src++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*src, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1712,7 +1796,7 @@ size_t wxMBConvUTF32Base::GetLength(const char *src, size_t srcLen)
     if ( srcLen == wxNO_LEN )
     {
         // count the number of bytes in input, including the trailing NULs
-        const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src);
+        const wxUint32 *inBuff = reinterpret_cast<const wxUint32 *>(src);
         for ( srcLen = 1; *inBuff++; srcLen++ )
             ;
 
@@ -1743,12 +1827,12 @@ wxMBConvUTF32straight::ToWChar(wchar_t *dst, size_t dstLen,
     if ( srcLen == wxNO_LEN )
         return wxCONV_FAILED;
 
-    const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src);
+    const wxUint32 *inBuff = reinterpret_cast<const wxUint32 *>(src);
     const size_t inLen = srcLen / BYTES_PER_CHAR;
     size_t outLen = 0;
     for ( size_t n = 0; n < inLen; n++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*inBuff++, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1790,7 +1874,7 @@ wxMBConvUTF32straight::FromWChar(char *dst, size_t dstLen,
         return srcLen * BYTES_PER_CHAR;
     }
 
-    wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst);
+    wxUint32 *outBuff = reinterpret_cast<wxUint32 *>(dst);
     size_t outLen = 0;
     for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; )
     {
@@ -1821,12 +1905,12 @@ wxMBConvUTF32swap::ToWChar(wchar_t *dst, size_t dstLen,
     if ( srcLen == wxNO_LEN )
         return wxCONV_FAILED;
 
-    const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src);
+    const wxUint32 *inBuff = reinterpret_cast<const wxUint32 *>(src);
     const size_t inLen = srcLen / BYTES_PER_CHAR;
     size_t outLen = 0;
     for ( size_t n = 0; n < inLen; n++, inBuff++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(wxUINT32_SWAP_ALWAYS(*inBuff), cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1868,7 +1952,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen,
         return srcLen*BYTES_PER_CHAR;
     }
 
-    wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst);
+    wxUint32 *outBuff = reinterpret_cast<wxUint32 *>(dst);
     size_t outLen = 0;
     for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; )
     {
@@ -1953,7 +2037,7 @@ wxMBConvUTF32swap::ToWChar(wchar_t *dst, size_t dstLen,
         if ( dstLen < srcLen )
             return wxCONV_FAILED;
 
-        const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src);
+        const wxUint32 *inBuff = reinterpret_cast<const wxUint32 *>(src);
         for ( size_t n = 0; n < srcLen; n++, inBuff++ )
         {
             *dst++ = wxUINT32_SWAP_ALWAYS(*inBuff);
@@ -1977,7 +2061,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen,
         if ( dstLen < srcLen )
             return wxCONV_FAILED;
 
-        wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst);
+        wxUint32 *outBuff = reinterpret_cast<wxUint32 *>(dst);
         for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ )
         {
             *outBuff++ = wxUINT32_SWAP_ALWAYS(*src);
@@ -2049,7 +2133,7 @@ public:
 
     virtual wxMBConv *Clone() const
     {
-        wxMBConv_iconv *p = new wxMBConv_iconv(m_name.ToAscii());
+        wxMBConv_iconv *p = new wxMBConv_iconv(m_name);
         p->m_minMBCharWidth = m_minMBCharWidth;
         return p;
     }
@@ -2079,7 +2163,7 @@ private:
 
 
     // name of the encoding handled by this conversion
-    wxString m_name;
+    const char *m_name;
 
     // cached result of GetMBNulLen(); set to 0 meaning "unknown"
     // initially
@@ -2103,28 +2187,28 @@ wxString wxMBConv_iconv::ms_wcCharsetName;
 bool wxMBConv_iconv::ms_wcNeedsSwap = false;
 
 wxMBConv_iconv::wxMBConv_iconv(const char *name)
-              : m_name(name)
+              : m_name(wxStrdup(name))
 {
     m_minMBCharWidth = 0;
 
     // check for charset that represents wchar_t:
     if ( ms_wcCharsetName.empty() )
     {
-        wxLogTrace(TRACE_STRCONV, _T("Looking for wide char codeset:"));
+        wxLogTrace(TRACE_STRCONV, wxT("Looking for wide char codeset:"));
 
 #if wxUSE_FONTMAP
-        const wxChar **names = wxFontMapperBase::GetAllEncodingNames(WC_ENC);
+        const wxChar *const *names = wxFontMapperBase::GetAllEncodingNames(WC_ENC);
 #else // !wxUSE_FONTMAP
-        static const wxChar *names_static[] =
+        static const wxChar *const names_static[] =
         {
 #if SIZEOF_WCHAR_T == 4
-            _T("UCS-4"),
-#elif SIZEOF_WCHAR_T = 2
-            _T("UCS-2"),
+            wxT("UCS-4"),
+#elif SIZEOF_WCHAR_T == 2
+            wxT("UCS-2"),
 #endif
             NULL
         };
-        const wxChar **names = names_static;
+        const wxChar *const *names = names_static;
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
 
         for ( ; *names && ms_wcCharsetName.empty(); ++names )
@@ -2135,19 +2219,19 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name)
             wxString nameXE(nameCS);
 
 #ifdef WORDS_BIGENDIAN
-                nameXE += _T("BE");
+                nameXE += wxT("BE");
 #else // little endian
-                nameXE += _T("LE");
+                nameXE += wxT("LE");
 #endif
 
-            wxLogTrace(TRACE_STRCONV, _T("  trying charset \"%s\""),
+            wxLogTrace(TRACE_STRCONV, wxT("  trying charset \"%s\""),
                        nameXE.c_str());
 
             m2w = iconv_open(nameXE.ToAscii(), name);
             if ( m2w == ICONV_T_INVALID )
             {
                 // try charset w/o bytesex info (e.g. "UCS4")
-                wxLogTrace(TRACE_STRCONV, _T("  trying charset \"%s\""),
+                wxLogTrace(TRACE_STRCONV, wxT("  trying charset \"%s\""),
                            nameCS.c_str());
                 m2w = iconv_open(nameCS.ToAscii(), name);
 
@@ -2194,8 +2278,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name)
                    wxT("iconv wchar_t charset is \"%s\"%s"),
                    ms_wcCharsetName.empty() ? wxString("<none>")
                                             : ms_wcCharsetName,
-                   ms_wcNeedsSwap ? _T(" (needs swap)")
-                                  : _T(""));
+                   ms_wcNeedsSwap ? wxT(" (needs swap)")
+                                  : wxT(""));
     }
     else // we already have ms_wcCharsetName
     {
@@ -2220,6 +2304,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name)
 
 wxMBConv_iconv::~wxMBConv_iconv()
 {
+    free(const_cast<char *>(m_name));
+
     if ( m2w != ICONV_T_INVALID )
         iconv_close(m2w);
     if ( w2m != ICONV_T_INVALID )
@@ -2304,7 +2390,7 @@ wxMBConv_iconv::ToWChar(wchar_t *dst, size_t dstLen,
     else // no destination buffer
     {
         // convert using temp buffer to calculate the size of the buffer needed
-        wchar_t tbuf[8];
+        wchar_t tbuf[256];
         res = 0;
 
         do
@@ -2351,13 +2437,12 @@ size_t wxMBConv_iconv::FromWChar(char *dst, size_t dstLen,
     if (ms_wcNeedsSwap)
     {
         // need to copy to temp buffer to switch endianness
-        // (doing WC_BSWAP twice on the original buffer won't help, as it
+        // (doing WC_BSWAP twice on the original buffer won't work, as it
         //  could be in read-only memory, or be accessed in some other thread)
-        tmpbuf = (wchar_t *)malloc(inbuflen + SIZEOF_WCHAR_T);
+        tmpbuf = (wchar_t *)malloc(inbuflen);
         for ( size_t i = 0; i < srcLen; i++ )
             tmpbuf[i] = WC_BSWAP(src[i]);
 
-        tmpbuf[srcLen] = L'\0';
         src = tmpbuf;
     }
 
@@ -2372,16 +2457,16 @@ size_t wxMBConv_iconv::FromWChar(char *dst, size_t dstLen,
     else // no destination buffer
     {
         // convert using temp buffer to calculate the size of the buffer needed
-        char tbuf[16];
+        char tbuf[256];
         res = 0;
         do
         {
             dst = tbuf;
-            outbuflen = 16;
+            outbuflen = WXSIZEOF(tbuf);
 
             cres = iconv(w2m, ICONV_CHAR_CAST(&inbuf), &inbuflen, &dst, &outbuflen);
 
-            res += 16 - outbuflen;
+            res += WXSIZEOF(tbuf) - outbuflen;
         }
         while ((cres == (size_t)-1) && (errno == E2BIG));
     }
@@ -2672,7 +2757,7 @@ public:
             switch ( len )
             {
                 default:
-                    wxLogDebug(_T("Unexpected NUL length %d"), len);
+                    wxLogDebug(wxT("Unexpected NUL length %d"), len);
                     self->m_minMBCharWidth = (size_t)-1;
                     break;
 
@@ -2719,7 +2804,7 @@ private:
                     break;
             }
 
-            wxASSERT_MSG( s_isWin98Or2k != -1, _T("should be set above") );
+            wxASSERT_MSG( s_isWin98Or2k != -1, wxT("should be set above") );
         }
 
         return s_isWin98Or2k == 1;
@@ -2854,7 +2939,7 @@ private:
     // were we initialized successfully?
     bool m_ok;
 
-    DECLARE_NO_COPY_CLASS(wxMBConv_wxwin)
+    wxDECLARE_NO_COPY_CLASS(wxMBConv_wxwin);
 };
 
 // make the constructors available for unit testing
@@ -2880,7 +2965,41 @@ void wxCSConv::Init()
 {
     m_name = NULL;
     m_convReal =  NULL;
-    m_deferred = true;
+}
+
+void wxCSConv::SetEncoding(wxFontEncoding encoding)
+{
+    switch ( encoding )
+    {
+        case wxFONTENCODING_MAX:
+        case wxFONTENCODING_SYSTEM:
+            if ( m_name )
+            {
+                // It's ok to not have encoding value if we have a name for it.
+                m_encoding = wxFONTENCODING_SYSTEM;
+            }
+            else // No name neither.
+            {
+                // Fall back to the system default encoding in this case (not
+                // sure how much sense does this make but this is how the old
+                // code used to behave).
+#if wxUSE_INTL
+                m_encoding = wxLocale::GetSystemEncoding();
+                if ( m_encoding == wxFONTENCODING_SYSTEM )
+#endif // wxUSE_INTL
+                    m_encoding = wxFONTENCODING_ISO8859_1;
+            }
+            break;
+
+        case wxFONTENCODING_DEFAULT:
+            // wxFONTENCODING_DEFAULT is same as US-ASCII in this context
+            m_encoding = wxFONTENCODING_ISO8859_1;
+            break;
+
+        default:
+            // Just use the provided encoding.
+            m_encoding = encoding;
+    }
 }
 
 wxCSConv::wxCSConv(const wxString& charset)
@@ -2893,34 +3012,28 @@ wxCSConv::wxCSConv(const wxString& charset)
     }
 
 #if wxUSE_FONTMAP
-    m_encoding = wxFontMapperBase::GetEncodingFromName(charset);
-    if ( m_encoding == wxFONTENCODING_MAX )
-    {
-        // set to unknown/invalid value
-        m_encoding = wxFONTENCODING_SYSTEM;
-    }
-    else if ( m_encoding == wxFONTENCODING_DEFAULT )
-    {
-        // wxFONTENCODING_DEFAULT is same as US-ASCII in this context
-        m_encoding = wxFONTENCODING_ISO8859_1;
-    }
+    SetEncoding(wxFontMapperBase::GetEncodingFromName(charset));
 #else
-    m_encoding = wxFONTENCODING_SYSTEM;
+    SetEncoding(wxFONTENCODING_SYSTEM);
 #endif
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv::wxCSConv(wxFontEncoding encoding)
 {
     if ( encoding == wxFONTENCODING_MAX || encoding == wxFONTENCODING_DEFAULT )
     {
-        wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
+        wxFAIL_MSG( wxT("invalid encoding value in wxCSConv ctor") );
 
         encoding = wxFONTENCODING_SYSTEM;
     }
 
     Init();
 
-    m_encoding = encoding;
+    SetEncoding(encoding);
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv::~wxCSConv()
@@ -2934,7 +3047,9 @@ wxCSConv::wxCSConv(const wxCSConv& conv)
     Init();
 
     SetName(conv.m_name);
-    m_encoding = conv.m_encoding;
+    SetEncoding(conv.m_encoding);
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
@@ -2942,7 +3057,9 @@ wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
     Clear();
 
     SetName(conv.m_name);
-    m_encoding = conv.m_encoding;
+    SetEncoding(conv.m_encoding);
+
+    m_convReal = DoCreate();
 
     return *this;
 }
@@ -2950,19 +3067,15 @@ wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
 void wxCSConv::Clear()
 {
     free(m_name);
-    delete m_convReal;
-
     m_name = NULL;
-    m_convReal = NULL;
+
+    wxDELETE(m_convReal);
 }
 
 void wxCSConv::SetName(const char *charset)
 {
-    if (charset)
-    {
+    if ( charset )
         m_name = wxStrdup(charset);
-        m_deferred = true;
-    }
 }
 
 #if wxUSE_FONTMAP
@@ -2985,8 +3098,7 @@ wxMBConv *wxCSConv::DoCreate() const
     // check for the special case of ASCII or ISO8859-1 charset: as we have
     // special knowledge of it anyhow, we don't need to create a special
     // conversion object
-    if ( m_encoding == wxFONTENCODING_ISO8859_1 ||
-            m_encoding == wxFONTENCODING_DEFAULT )
+    if ( m_encoding == wxFONTENCODING_ISO8859_1 )
     {
         // don't convert at all
         return NULL;
@@ -3038,7 +3150,7 @@ wxMBConv *wxCSConv::DoCreate() const
                 delete conv;
             }
 
-            const wxChar** names = wxFontMapperBase::GetAllEncodingNames(encoding);
+            const wxChar* const* names = wxFontMapperBase::GetAllEncodingNames(encoding);
             // CS : in case this does not return valid names (eg for MacRoman)
             // encoding got a 'failure' entry in the cache all the same,
             // although it just has to be created using a different method, so
@@ -3061,7 +3173,7 @@ wxMBConv *wxCSConv::DoCreate() const
                     delete conv;
                 }
 
-                gs_nameCache[encoding] = _T(""); // cache the failure
+                gs_nameCache[encoding] = wxT(""); // cache the failure
             }
         }
 #endif // wxUSE_FONTMAP
@@ -3151,62 +3263,18 @@ wxMBConv *wxCSConv::DoCreate() const
 
         delete conv;
     }
-#endif // wxUSE_FONTMAP
 
-    // NB: This is a hack to prevent deadlock. What could otherwise happen
-    //     in Unicode build: wxConvLocal creation ends up being here
-    //     because of some failure and logs the error. But wxLog will try to
-    //     attach a timestamp, for which it will need wxConvLocal (to convert
-    //     time to char* and then wchar_t*), but that fails, tries to log the
-    //     error, but wxLog has an (already locked) critical section that
-    //     guards the static buffer.
-    static bool alreadyLoggingError = false;
-    if (!alreadyLoggingError)
-    {
-        alreadyLoggingError = true;
-        wxLogError(_("Cannot convert from the charset '%s'!"),
-                   m_name ? m_name
-                      :
-#if wxUSE_FONTMAP
-                         (const char*)wxFontMapperBase::GetEncodingDescription(m_encoding).ToAscii()
-#else // !wxUSE_FONTMAP
-                         (const char*)wxString::Format(_("encoding %i"), m_encoding).ToAscii()
-#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
-              );
-
-        alreadyLoggingError = false;
-    }
+    wxLogTrace(TRACE_STRCONV,
+               wxT("encoding \"%s\" is not supported by this system"),
+               (m_name ? wxString(m_name)
+                       : wxFontMapperBase::GetEncodingName(m_encoding)));
+#endif // wxUSE_FONTMAP
 
     return NULL;
 }
 
-void wxCSConv::CreateConvIfNeeded() const
-{
-    if ( m_deferred )
-    {
-        wxCSConv *self = (wxCSConv *)this; // const_cast
-
-        // if we don't have neither the name nor the encoding, use the default
-        // encoding for this system
-        if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM )
-        {
-#if wxUSE_INTL
-            self->m_encoding = wxLocale::GetSystemEncoding();
-#else
-            // fallback to some reasonable default:
-            self->m_encoding = wxFONTENCODING_ISO8859_1;
-#endif // wxUSE_INTL
-        }
-
-        self->m_convReal = DoCreate();
-        self->m_deferred = false;
-    }
-}
-
 bool wxCSConv::IsOk() const
 {
-    CreateConvIfNeeded();
-
     // special case: no convReal created for wxFONTENCODING_ISO8859_1
     if ( m_encoding == wxFONTENCODING_ISO8859_1 )
         return true; // always ok as we do it ourselves
@@ -3219,8 +3287,6 @@ bool wxCSConv::IsOk() const
 size_t wxCSConv::ToWChar(wchar_t *dst, size_t dstLen,
                          const char *src, size_t srcLen) const
 {
-    CreateConvIfNeeded();
-
     if (m_convReal)
         return m_convReal->ToWChar(dst, dstLen, src, srcLen);
 
@@ -3243,8 +3309,6 @@ size_t wxCSConv::ToWChar(wchar_t *dst, size_t dstLen,
 size_t wxCSConv::FromWChar(char *dst, size_t dstLen,
                            const wchar_t *src, size_t srcLen) const
 {
-    CreateConvIfNeeded();
-
     if (m_convReal)
         return m_convReal->FromWChar(dst, dstLen, src, srcLen);
 
@@ -3280,12 +3344,8 @@ size_t wxCSConv::FromWChar(char *dst, size_t dstLen,
 
 size_t wxCSConv::GetMBNulLen() const
 {
-    CreateConvIfNeeded();
-
     if ( m_convReal )
-    {
         return m_convReal->GetMBNulLen();
-    }
 
     // otherwise, we are ISO-8859-1
     return 1;
@@ -3294,12 +3354,8 @@ size_t wxCSConv::GetMBNulLen() const
 #if wxUSE_UNICODE_UTF8
 bool wxCSConv::IsUTF8() const
 {
-    CreateConvIfNeeded();
-
     if ( m_convReal )
-    {
         return m_convReal->IsUTF8();
-    }
 
     // otherwise, we are ISO-8859-1
     return false;
@@ -3369,8 +3425,15 @@ wxCharBuffer wxSafeConvertWX2MB(const wchar_t *ws)
 #define WX_DEFINE_GLOBAL_CONV(klass, name, ctor_args) \
     WX_DEFINE_GLOBAL_CONV2(klass, klass, name, ctor_args)
 
+#ifdef __INTELC__
+    // disable warning "variable 'xxx' was declared but never referenced"
+    #pragma warning(disable: 177)
+#endif // Intel C++
+
 #ifdef __WINDOWS__
     WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_win32, wxConvLibc, wxEMPTY_PARAMETER_VALUE);
+#elif 0 // defined(__WXOSX__)
+    WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_cf, wxConvLibc,  (wxFONTENCODING_UTF8));
 #else
     WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConvLibc, wxConvLibc, wxEMPTY_PARAMETER_VALUE);
 #endif
@@ -3391,8 +3454,9 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = wxGet_wxConvLibcPtr();
 WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvUI = wxGet_wxConvLocalPtr();
 
 #ifdef __DARWIN__
-// The xnu kernel always communicates file paths in decomposed UTF-8.
-// WARNING: Are we sure that CFString's conversion will cause decomposition?
+// It is important to use this conversion object under Darwin as it ensures
+// that Unicode strings are (re)composed correctly even though xnu kernel uses
+// decomposed form internally (at least for the file names).
 static wxMBConv_cf wxConvMacUTF8DObj(wxFONTENCODING_UTF8);
 #endif
 
@@ -3402,14 +3466,3 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName =
 #else // !__DARWIN__
                                     wxGet_wxConvLibcPtr();
 #endif // __DARWIN__/!__DARWIN__
-
-#else // !wxUSE_WCHAR_T
-
-// FIXME-UTF8: remove this, wxUSE_WCHAR_T is required now
-// stand-ins in absence of wchar_t
-WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc,
-                                wxConvISO8859_1,
-                                wxConvLocal,
-                                wxConvUTF8;
-
-#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T