X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4227afa4f748870bbfce75047db465f024e0ac1d..8482e4bdb9928fe9982ac214aee345b19894b39b:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 8597373f54..395c2535ee 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -40,6 +40,9 @@ #ifdef __WXMSW__ #include "wx/msw/private.h" +#endif + +#ifdef __WINDOWS__ #include "wx/msw/missing.h" #endif @@ -69,6 +72,7 @@ #include "wx/encconv.h" #include "wx/fontmap.h" +#include "wx/utils.h" #ifdef __WXMAC__ #include @@ -177,9 +181,11 @@ const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const { // now do the actual conversion wxWCharBuffer buf(nLen); - MB2WC(buf.data(), psz, nLen + 1); // with the trailing NUL - - return buf; + nLen = MB2WC(buf.data(), psz, nLen + 1); // with the trailing NULL + if ( nLen != (size_t)-1 ) + { + return buf; + } } } @@ -196,9 +202,11 @@ const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const if ( nLen != (size_t)-1 ) { wxCharBuffer buf(nLen+3); // space for a wxUint32 trailing zero - WC2MB(buf.data(), pwz, nLen + 4); - - return buf; + nLen = WC2MB(buf.data(), pwz, nLen + 4); + if ( nLen != (size_t)-1 ) + { + return buf; + } } } @@ -951,7 +959,7 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) { ms_wcCharsetName = NULL; - // VS: we must not output an error here, since wxWindows will safely + // VS: we must not output an error here, since wxWidgets will safely // fall back to using wxEncodingConverter. wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name); //wxLogError( @@ -1113,8 +1121,10 @@ size_t wxMBConv_iconv::WC2MB(char *buf, const wchar_t *psz, size_t n) const #ifdef wxHAVE_WIN32_MB2WC // from utils.cpp +#if wxUSE_FONTMAP extern WXDLLIMPEXP_BASE long wxCharsetToCodepage(const wxChar *charset); extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding); +#endif class wxMBConv_win32 : public wxMBConv { @@ -1124,6 +1134,7 @@ public: m_CodePage = CP_ACP; } +#if wxUSE_FONTMAP wxMBConv_win32(const wxChar* name) { m_CodePage = wxCharsetToCodepage(name); @@ -1133,13 +1144,19 @@ public: { m_CodePage = wxEncodingToCodepage(encoding); } +#endif size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const { + // note that we have to use MB_ERR_INVALID_CHARS flag as it without it + // the behaviour is not compatible with the Unix version (using iconv) + // and break the library itself, e.g. wxTextInputStream::NextChar() + // wouldn't work if reading an incomplete MB char didn't result in an + // error const size_t len = ::MultiByteToWideChar ( m_CodePage, // code page - 0, // flags (none) + MB_ERR_INVALID_CHARS, // flags: fall on error psz, // input string -1, // its length (NUL-terminated) buf, // output string @@ -1160,7 +1177,7 @@ public: quality approximations such as turning "1/2" symbol (U+00BD) into "1" for the code pages which don't have it and we, obviously, want to avoid this at any price - + the trouble is that this function does it _silently_, i.e. it won't even tell us whether it did or not... Win98/2000 and higher provide WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and @@ -1285,124 +1302,127 @@ public: wxMBConv_mac(const wxChar* name) { - Init( wxMacGetSystemEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name, FALSE) ) ) ; + Init( wxMacGetSystemEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name, false) ) ) ; } wxMBConv_mac(wxFontEncoding encoding) { - Init( wxMacGetSystemEncFromFontEnc(encoding) ); - } - - ~wxMBConv_mac() - { - OSStatus status = noErr ; - status = TECDisposeConverter(m_MB2WC_converter); - status = TECDisposeConverter(m_WC2MB_converter); - } - - - void Init( TextEncodingBase encoding) - { - OSStatus status = noErr ; - m_char_encoding = encoding ; - m_unicode_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode16BitFormat) ; - - status = TECCreateConverter(&m_MB2WC_converter, - m_char_encoding, - m_unicode_encoding); - status = TECCreateConverter(&m_WC2MB_converter, - m_unicode_encoding, - m_char_encoding); - } - + Init( wxMacGetSystemEncFromFontEnc(encoding) ); + } + + ~wxMBConv_mac() + { + OSStatus status = noErr ; + status = TECDisposeConverter(m_MB2WC_converter); + status = TECDisposeConverter(m_WC2MB_converter); + } + + + void Init( TextEncodingBase encoding) + { + OSStatus status = noErr ; + m_char_encoding = encoding ; + m_unicode_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode16BitFormat) ; + + status = TECCreateConverter(&m_MB2WC_converter, + m_char_encoding, + m_unicode_encoding); + status = TECCreateConverter(&m_WC2MB_converter, + m_unicode_encoding, + m_char_encoding); + } + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const { - OSStatus status = noErr ; - ByteCount byteOutLen ; - ByteCount byteInLen = strlen(psz) ; - wchar_t *tbuf = NULL ; - UniChar* ubuf = NULL ; - size_t res = 0 ; - - if (buf == NULL) - { - n = byteInLen ; - tbuf = (wchar_t*) malloc( n * SIZEOF_WCHAR_T) ; - } - ByteCount byteBufferLen = n * sizeof( UniChar ) ; + OSStatus status = noErr ; + ByteCount byteOutLen ; + ByteCount byteInLen = strlen(psz) ; + wchar_t *tbuf = NULL ; + UniChar* ubuf = NULL ; + size_t res = 0 ; + + if (buf == NULL) + { + n = byteInLen ; + tbuf = (wchar_t*) malloc( n * SIZEOF_WCHAR_T) ; + } + ByteCount byteBufferLen = n * sizeof( UniChar ) ; #if SIZEOF_WCHAR_T == 4 - ubuf = (UniChar*) malloc( byteBufferLen ) ; + ubuf = (UniChar*) malloc( byteBufferLen + 2 ) ; #else - ubuf = (UniChar*) (buf ? buf : tbuf) ; + ubuf = (UniChar*) (buf ? buf : tbuf) ; #endif - status = TECConvertText(m_MB2WC_converter, (ConstTextPtr) psz , byteInLen, &byteInLen, - (TextPtr) ubuf , byteBufferLen, &byteOutLen); + status = TECConvertText(m_MB2WC_converter, (ConstTextPtr) psz , byteInLen, &byteInLen, + (TextPtr) ubuf , byteBufferLen, &byteOutLen); #if SIZEOF_WCHAR_T == 4 - wxMBConvUTF16BE converter ; - res = converter.MB2WC( (buf ? buf : tbuf) , (const char*)ubuf , n ) ; - free( ubuf ) ; + // we have to terminate here, because n might be larger for the trailing zero, and if UniChar + // is not properly terminated we get random characters at the end + ubuf[byteOutLen / sizeof( UniChar ) ] = 0 ; + wxMBConvUTF16BE converter ; + res = converter.MB2WC( (buf ? buf : tbuf) , (const char*)ubuf , n ) ; + free( ubuf ) ; #else - res = byteOutLen / sizeof( UniChar ) ; + res = byteOutLen / sizeof( UniChar ) ; #endif - if ( buf == NULL ) - free(tbuf) ; + if ( buf == NULL ) + free(tbuf) ; if ( buf && res < n) buf[res] = 0; - return res ; + return res ; } size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const - { - OSStatus status = noErr ; - ByteCount byteOutLen ; - ByteCount byteInLen = wxWcslen(psz) * SIZEOF_WCHAR_T ; - - char *tbuf = NULL ; - - if (buf == NULL) - { - // worst case - n = byteInLen * 2 ; - tbuf = (char*) malloc( n ) ; - } - - ByteCount byteBufferLen = n ; - UniChar* ubuf = NULL ; + { + OSStatus status = noErr ; + ByteCount byteOutLen ; + ByteCount byteInLen = wxWcslen(psz) * SIZEOF_WCHAR_T ; + + char *tbuf = NULL ; + + if (buf == NULL) + { + // worst case + n = byteInLen * 2 ; + tbuf = (char*) malloc( n ) ; + } + + ByteCount byteBufferLen = n ; + UniChar* ubuf = NULL ; #if SIZEOF_WCHAR_T == 4 - wxMBConvUTF16BE converter ; - size_t unicharlen = converter.WC2MB( NULL , psz , 0 ) ; - byteInLen = unicharlen ; - ubuf = (UniChar*) malloc( byteInLen + 2 ) ; - converter.WC2MB( (char*) ubuf , psz, unicharlen + 2 ) ; + wxMBConvUTF16BE converter ; + size_t unicharlen = converter.WC2MB( NULL , psz , 0 ) ; + byteInLen = unicharlen ; + ubuf = (UniChar*) malloc( byteInLen + 2 ) ; + converter.WC2MB( (char*) ubuf , psz, unicharlen + 2 ) ; #else - ubuf = (UniChar*) psz ; + ubuf = (UniChar*) psz ; #endif - status = TECConvertText(m_WC2MB_converter, (ConstTextPtr) ubuf , byteInLen, &byteInLen, - (TextPtr) (buf ? buf : tbuf) , byteBufferLen, &byteOutLen); + status = TECConvertText(m_WC2MB_converter, (ConstTextPtr) ubuf , byteInLen, &byteInLen, + (TextPtr) (buf ? buf : tbuf) , byteBufferLen, &byteOutLen); #if SIZEOF_WCHAR_T == 4 - free( ubuf ) ; + free( ubuf ) ; #endif - if ( buf == NULL ) - free(tbuf) ; + if ( buf == NULL ) + free(tbuf) ; - size_t res = byteOutLen ; + size_t res = byteOutLen ; if ( buf && res < n) buf[res] = 0; - return res ; + return res ; } bool IsOk() const { return m_MB2WC_converter != NULL && m_WC2MB_converter != NULL ; } private: - TECObjectRef m_MB2WC_converter ; - TECObjectRef m_WC2MB_converter ; - - TextEncodingBase m_char_encoding ; - TextEncodingBase m_unicode_encoding ; + TECObjectRef m_MB2WC_converter ; + TECObjectRef m_WC2MB_converter ; + + TextEncodingBase m_char_encoding ; + TextEncodingBase m_unicode_encoding ; }; #endif // defined(__WXMAC__) && defined(TARGET_CARBON) @@ -1594,26 +1614,30 @@ wxMBConv *wxCSConv::DoCreate() const #ifdef wxHAVE_WIN32_MB2WC { +#if wxUSE_FONTMAP wxMBConv_win32 *conv = m_name ? new wxMBConv_win32(m_name) : new wxMBConv_win32(m_encoding); if ( conv->IsOk() ) return conv; delete conv; +#else + return NULL; +#endif } #endif // wxHAVE_WIN32_MB2WC -#if defined(__WXMAC__) +#if defined(__WXMAC__) { - if ( m_name || ( m_encoding < wxFONTENCODING_UTF16BE ) ) - { - - wxMBConv_mac *conv = m_name ? new wxMBConv_mac(m_name) - : new wxMBConv_mac(m_encoding); - if ( conv->IsOk() ) - return conv; + if ( m_name || ( m_encoding < wxFONTENCODING_UTF16BE ) ) + { - delete conv; - } + wxMBConv_mac *conv = m_name ? new wxMBConv_mac(m_name) + : new wxMBConv_mac(m_encoding); + if ( conv->IsOk() ) + return conv; + + delete conv; + } } #endif // step (2) @@ -1766,6 +1790,8 @@ size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const #ifdef __WINDOWS__ static wxMBConv_win32 wxConvLibcObj; +#elif defined(__WXMAC__) && !defined(__MACH__) + static wxMBConv_mac wxConvLibcObj ; #else static wxMBConvLibc wxConvLibcObj; #endif