summaryrefslogtreecommitdiffstats
path: root/win/tclWin32Dll.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2018-11-15 08:19:24 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2018-11-15 08:19:24 (GMT)
commit9214af654398982e16186d0ae70f37b3580f0295 (patch)
tree131e8376cbc6f60ee9617b3ba92204a08ae41e29 /win/tclWin32Dll.c
parenta69045247e1387fc673deb432549cb266e5009ee (diff)
parent65ae2c205ec2dfe95ce012b45d5d3adc07370685 (diff)
downloadtcl-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.c92
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
}
/*