fixed win32 code to not use MB_ERR_INVALID_CHARS on win version where it isn't available; roundtrip check is used instead

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37830 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2006-03-06 17:36:36 +00:00
parent 818f394678
commit 8902898054

View File

@@ -1652,7 +1652,28 @@ public:
// 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;
//
// Moreover, MB_ERR_INVALID_CHARS is only supported on Win 2K SP4 or
// Win XP or newer and if it is specified on older versions, conversion
// from CP_UTF8 (which can have flags only 0 or MB_ERR_INVALID_CHARS)
// fails. So we can only use the flag on newer Windows versions.
// Additionally, the flag is not supported by UTF7, symbol and CJK
// encodings. See here:
// http://blogs.msdn.com/michkap/archive/2005/04/19/409566.aspx
// http://msdn.microsoft.com/library/en-us/intl/unicode_17si.asp
int flags = 0;
if ( m_CodePage != CP_UTF7 && m_CodePage != CP_SYMBOL &&
m_CodePage < 50000 &&
IsAtLeastWin2kSP4() )
{
flags = MB_ERR_INVALID_CHARS;
}
else if ( m_CodePage == CP_UTF8 )
{
// Avoid round-trip in the special case of UTF-8 by using our
// own UTF-8 conversion code:
return wxMBConvUTF8().MB2WC(buf, psz, n);
}
const size_t len = ::MultiByteToWideChar
(
@@ -1663,11 +1684,40 @@ public:
buf, // output string
buf ? n : 0 // size of output buffer
);
if ( !len )
{
// function totally failed
return (size_t)-1;
}
// if we were really converting and didn't use MB_ERR_INVALID_CHARS,
// check if we succeeded, by doing a double trip:
if ( !flags && buf )
{
wxCharBuffer mbBuf(n);
if ( ::WideCharToMultiByte
(
m_CodePage,
0,
buf,
-1,
mbBuf.data(),
n,
NULL,
NULL
) == 0 ||
strcmp(mbBuf, psz) != 0 )
{
// we didn't obtain the same thing we started from, hence
// the conversion was lossy and we consider that it failed
return (size_t)-1;
}
}
// note that it returns count of written chars for buf != NULL and size
// of the needed buffer for buf == NULL so in either case the length of
// the string (which never includes the terminating NUL) is one less
return len ? len - 1 : (size_t)-1;
return len - 1;
}
size_t WC2MB(char *buf, const wchar_t *pwz, size_t n) const
@@ -1782,6 +1832,29 @@ private:
return s_isWin98Or2k == 1;
}
static bool IsAtLeastWin2kSP4()
{
static int s_isAtLeastWin2kSP4 = -1;
if ( s_isAtLeastWin2kSP4 == -1 )
{
OSVERSIONINFOEX ver;
memset(&ver, 0, sizeof(ver));
ver.dwOSVersionInfoSize = sizeof(ver);
GetVersionEx((OSVERSIONINFO*)&ver);
s_isAtLeastWin2kSP4 =
((ver.dwMajorVersion > 5) || // Vista+
(ver.dwMajorVersion == 5 && ver.dwMinorVersion > 0) || // XP/2003
(ver.dwMajorVersion == 5 && ver.dwMinorVersion == 0 &&
ver.wServicePackMajor >= 4)) // 2000 SP4+
? 1 : 0;
}
return s_isAtLeastWin2kSP4 == 1;
}
long m_CodePage;
};