X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/51725fc0c294f3c3f636710745539cd2041d8d8b..ce7fe42e848cc0c9058dae906c3a7bded50681e6:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 6505ae15e1..73fe64d115 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -28,8 +28,6 @@ #include "wx/strconv.h" -#if wxUSE_WCHAR_T - #ifndef __WXWINCE__ #include #endif @@ -57,7 +55,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 +140,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(*pSrc), out); if ( n == wxCONV_FAILED ) *pSrc = NULL; else @@ -216,7 +214,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 +256,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 +272,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 +321,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 +344,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; @@ -428,7 +460,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 ) @@ -490,6 +521,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 // ---------------------------------------------------------------------------- @@ -512,8 +579,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); @@ -584,7 +651,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(&m_stateDecoder); // also save the old state to be able to rollback to it on error stateOrig = m_stateDecoder; @@ -771,7 +838,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(&m_stateEncoder); } EncoderState& state = *statePtr; @@ -927,7 +994,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 @@ -1047,7 +1114,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 @@ -1077,6 +1144,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; @@ -1137,7 +1206,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; } @@ -1162,7 +1231,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; @@ -1296,10 +1368,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) @@ -1315,7 +1394,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; @@ -1383,10 +1465,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; - return len + 1; + // And count it in any case. + len++; + } + + return len; } // ============================================================================ @@ -1407,7 +1496,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(src); for ( srcLen = 1; *inBuff++; srcLen++ ) ; @@ -1491,7 +1580,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(src); for ( size_t n = 0; n < srcLen; n++, inBuff++ ) { *dst++ = wxUINT16_SWAP_ALWAYS(*inBuff); @@ -1515,7 +1604,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(dst); for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ ) { *outBuff++ = wxUINT16_SWAP_ALWAYS(*src); @@ -1549,7 +1638,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(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) { const wxUint32 ch = wxDecodeSurrogate(&inBuff); @@ -1574,10 +1663,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(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; @@ -1622,7 +1711,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(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) { wxUint32 ch; @@ -1657,10 +1746,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(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; @@ -1708,7 +1797,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(src); for ( srcLen = 1; *inBuff++; srcLen++ ) ; @@ -1739,12 +1828,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(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; @@ -1786,7 +1875,7 @@ wxMBConvUTF32straight::FromWChar(char *dst, size_t dstLen, return srcLen * BYTES_PER_CHAR; } - wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst); + wxUint32 *outBuff = reinterpret_cast(dst); size_t outLen = 0; for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; ) { @@ -1817,12 +1906,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(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; @@ -1864,7 +1953,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen, return srcLen*BYTES_PER_CHAR; } - wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst); + wxUint32 *outBuff = reinterpret_cast(dst); size_t outLen = 0; for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; ) { @@ -1949,7 +2038,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(src); for ( size_t n = 0; n < srcLen; n++, inBuff++ ) { *dst++ = wxUINT32_SWAP_ALWAYS(*inBuff); @@ -1973,7 +2062,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(dst); for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ ) { *outBuff++ = wxUINT32_SWAP_ALWAYS(*src); @@ -2045,7 +2134,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; } @@ -2075,7 +2164,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 @@ -2099,28 +2188,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 ) @@ -2131,19 +2220,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); @@ -2190,8 +2279,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) wxT("iconv wchar_t charset is \"%s\"%s"), ms_wcCharsetName.empty() ? wxString("") : ms_wcCharsetName, - ms_wcNeedsSwap ? _T(" (needs swap)") - : _T("")); + ms_wcNeedsSwap ? wxT(" (needs swap)") + : wxT("")); } else // we already have ms_wcCharsetName { @@ -2216,6 +2305,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) wxMBConv_iconv::~wxMBConv_iconv() { + free(const_cast(m_name)); + if ( m2w != ICONV_T_INVALID ) iconv_close(m2w); if ( w2m != ICONV_T_INVALID ) @@ -2300,7 +2391,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 @@ -2367,7 +2458,7 @@ 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 { @@ -2667,7 +2758,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; @@ -2714,7 +2805,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; @@ -2849,7 +2940,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 @@ -2875,7 +2966,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) @@ -2888,34 +3013,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() @@ -2929,7 +3048,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) @@ -2937,7 +3058,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; } @@ -2945,19 +3068,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 @@ -2980,8 +3099,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; @@ -3033,7 +3151,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 @@ -3056,7 +3174,7 @@ wxMBConv *wxCSConv::DoCreate() const delete conv; } - gs_nameCache[encoding] = _T(""); // cache the failure + gs_nameCache[encoding] = wxT(""); // cache the failure } } #endif // wxUSE_FONTMAP @@ -3146,62 +3264,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 @@ -3214,8 +3288,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); @@ -3238,8 +3310,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); @@ -3275,12 +3345,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; @@ -3289,12 +3355,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; @@ -3364,8 +3426,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 @@ -3386,8 +3455,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 @@ -3397,14 +3467,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