diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-11-15 08:19:24 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-11-15 08:19:24 (GMT) |
commit | 9214af654398982e16186d0ae70f37b3580f0295 (patch) | |
tree | 131e8376cbc6f60ee9617b3ba92204a08ae41e29 /win/tclWin32Dll.c | |
parent | a69045247e1387fc673deb432549cb266e5009ee (diff) | |
parent | 65ae2c205ec2dfe95ce012b45d5d3adc07370685 (diff) | |
download | tcl-9214af654398982e16186d0ae70f37b3580f0295.zip tcl-9214af654398982e16186d0ae70f37b3580f0295.tar.gz tcl-9214af654398982e16186d0ae70f37b3580f0295.tar.bz2 |
Merge 8.7
Fix Tcl_InitStringRep() signature in line with TIP #494, so it can handle lengths >2Gb on 64-bit platforms
Various other code cleanups, unnecessary type-casts e.o.
Diffstat (limited to 'win/tclWin32Dll.c')
-rw-r--r-- | win/tclWin32Dll.c | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index ef8d54a..ff29309 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -471,11 +471,68 @@ Tcl_WinUtfToTChar( Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { +#if TCL_UTF_MAX > 4 + Tcl_UniChar ch = 0; + TCHAR *w, *wString; + const char *p, *end; + int oldLength; +#endif + Tcl_DStringInit(dsPtr); if (!string) { return NULL; } +#if TCL_UTF_MAX > 4 + + if (len < 0) { + len = strlen(string); + } + + /* + * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in + * bytes. + */ + + oldLength = Tcl_DStringLength(dsPtr); + + Tcl_DStringSetLength(dsPtr, + oldLength + (int) ((len + 1) * sizeof(TCHAR))); + wString = (TCHAR *) (Tcl_DStringValue(dsPtr) + oldLength); + + w = wString; + p = string; + end = string + len - 4; + while (p < end) { + p += TclUtfToUniChar(p, &ch); + if (ch > 0xFFFF) { + *w++ = (wchar_t) (0xD800 + ((ch -= 0x10000) >> 10)); + *w++ = (wchar_t) (0xDC00 | (ch & 0x3FF)); + } else { + *w++ = ch; + } + } + end += 4; + while (p < end) { + if (Tcl_UtfCharComplete(p, end-p)) { + p += TclUtfToUniChar(p, &ch); + } else { + ch = UCHAR(*p++); + } + if (ch > 0xFFFF) { + *w++ = (wchar_t) (0xD800 + ((ch -= 0x10000) >> 10)); + *w++ = (wchar_t) (0xDC00 | (ch & 0x3FF)); + } else { + *w++ = ch; + } + } + *w = '\0'; + Tcl_DStringSetLength(dsPtr, + oldLength + ((char *) w - (char *) wString)); + + return wString; +#else return Tcl_UtfToUniCharDString(string, len, dsPtr); +#endif } char * @@ -486,16 +543,47 @@ Tcl_WinTCharToUtf( Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { +#if TCL_UTF_MAX > 4 + const TCHAR *w, *wEnd; + char *p, *result; + int oldLength, blen = 1; +#endif + Tcl_DStringInit(dsPtr); if (!string) { return NULL; } if (len == TCL_AUTO_LENGTH) { - len = wcslen(string); + len = wcslen((TCHAR *)string); } else { len /= 2; } - return Tcl_UniCharToUtfDString(string, len, dsPtr); +#if TCL_UTF_MAX > 4 + oldLength = Tcl_DStringLength(dsPtr); + Tcl_DStringSetLength(dsPtr, oldLength + (len + 1) * 4); + result = Tcl_DStringValue(dsPtr) + oldLength; + + p = result; + wEnd = (TCHAR *)string + len; + for (w = (TCHAR *)string; w < wEnd; ) { + if (!blen && ((*w & 0xFC00) != 0xDC00)) { + /* Special case for handling upper surrogates. */ + p += Tcl_UniCharToUtf(-1, p); + } + blen = Tcl_UniCharToUtf(*w, p); + p += blen; + w++; + } + if (!blen) { + /* Special case for handling upper surrogates. */ + p += Tcl_UniCharToUtf(-1, p); + } + Tcl_DStringSetLength(dsPtr, oldLength + (p - result)); + + return result; +#else + return Tcl_UniCharToUtfDString((Tcl_UniChar *)string, len, dsPtr); +#endif } /* |