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
|
// own wxMBConvUTF7 doesn't detect errors (e.g. lone "+" which is
|
||||||
// explicitly ill-formed according to RFC 2152) neither so we don't
|
// explicitly ill-formed according to RFC 2152) neither so we don't
|
||||||
// even have any fallback here...
|
// 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
|
const size_t len = ::MultiByteToWideChar
|
||||||
(
|
(
|
||||||
@@ -1663,11 +1684,40 @@ public:
|
|||||||
buf, // output string
|
buf, // output string
|
||||||
buf ? n : 0 // size of output buffer
|
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
|
// 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
|
// 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
|
// 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
|
size_t WC2MB(char *buf, const wchar_t *pwz, size_t n) const
|
||||||
@@ -1782,6 +1832,29 @@ private:
|
|||||||
return s_isWin98Or2k == 1;
|
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;
|
long m_CodePage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user