summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/tclStubInit.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index cbf4084..f7b374c 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -188,11 +188,68 @@ Tcl_WinUtfToTChar(
int len,
Tcl_DString *dsPtr)
{
+#if TCL_UTF_MAX > 4
+ Tcl_UniChar ch = 0;
+ wchar_t *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(wchar_t)));
+ wString = (wchar_t *) (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 (char *)wString;
+#else
return (char *)Tcl_UtfToUniCharDString(string, len, dsPtr);
+#endif
}
char *
@@ -201,6 +258,12 @@ Tcl_WinTCharToUtf(
int len,
Tcl_DString *dsPtr)
{
+#if TCL_UTF_MAX > 4
+ const wchar_t *w, *wEnd;
+ char *p, *result;
+ int oldLength, blen = 1;
+#endif
+
Tcl_DStringInit(dsPtr);
if (!string) {
return NULL;
@@ -210,7 +273,32 @@ Tcl_WinTCharToUtf(
} else {
len /= 2;
}
+#if TCL_UTF_MAX > 4
+ oldLength = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, oldLength + (len + 1) * 4);
+ result = Tcl_DStringValue(dsPtr) + oldLength;
+
+ p = result;
+ wEnd = (wchar_t *)string + len;
+ for (w = (wchar_t *)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
}
#if defined(TCL_WIDE_INT_IS_LONG)