diff --git a/docs/changes.txt b/docs/changes.txt index 9d7803fa97..20e5bc2354 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -580,6 +580,7 @@ Major new features in this release All: - Fix wxMBConvUTF8::ToWChar() for non-NUL-terminated strings (andyr). +- Fix length returned from wxMBConvUTF16::ToWChar(NULL) (Thomas Goyne). - Fix wxSocket::WaitForAccept() in non-main thread (Hajo Kirchhoff). - Fix memory overallocation in wxVector::reserve() (Nigel Paton). - Fix `wx-config --libs` in monolithic build. diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 6c671f0d9f..b2eaa71576 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -1638,14 +1638,6 @@ wxMBConvUTF16straight::ToWChar(wchar_t *dst, size_t dstLen, return wxCONV_FAILED; const size_t inLen = srcLen / BYTES_PER_CHAR; - if ( !dst ) - { - // optimization: return maximal space which could be needed for this - // string even if the real size could be smaller if the buffer contains - // any surrogates - return inLen; - } - size_t outLen = 0; const wxUint16 *inBuff = reinterpret_cast(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) @@ -1654,10 +1646,15 @@ wxMBConvUTF16straight::ToWChar(wchar_t *dst, size_t dstLen, if ( !inBuff ) return wxCONV_FAILED; - if ( ++outLen > dstLen ) - return wxCONV_FAILED; + outLen++; - *dst++ = ch; + if ( dst ) + { + if ( outLen > dstLen ) + return wxCONV_FAILED; + + *dst++ = ch; + } } @@ -1711,14 +1708,6 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen, return wxCONV_FAILED; const size_t inLen = srcLen / BYTES_PER_CHAR; - if ( !dst ) - { - // optimization: return maximal space which could be needed for this - // string even if the real size could be smaller if the buffer contains - // any surrogates - return inLen; - } - size_t outLen = 0; const wxUint16 *inBuff = reinterpret_cast(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) @@ -1737,10 +1726,15 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen, if ( numChars == 2 ) inBuff++; - if ( ++outLen > dstLen ) - return wxCONV_FAILED; + outLen++; - *dst++ = ch; + if ( dst ) + { + if ( outLen > dstLen ) + return wxCONV_FAILED; + + *dst++ = ch; + } } diff --git a/tests/strings/unicode.cpp b/tests/strings/unicode.cpp index 2fd2ad3a6a..d6e28164d7 100644 --- a/tests/strings/unicode.cpp +++ b/tests/strings/unicode.cpp @@ -389,6 +389,11 @@ void UnicodeTestCase::ConversionUTF16() size_t len; conv.cMB2WC("\x01\0\0B\0C" /* A macron BC */, 6, &len); CPPUNIT_ASSERT_EQUAL( 3, len ); + + // Another one: verify that the length of the resulting string is computed + // correctly when there is a surrogate in the input. + wxMBConvUTF16BE().cMB2WC("\xd8\x03\xdc\x01" /* OLD TURKIC LETTER YENISEI A */, wxNO_LEN, &len); + CPPUNIT_ASSERT_EQUAL( 1, len ); } void UnicodeTestCase::ConversionUTF32()