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:
@@ -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;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user