Tk Source Code

Check-in [7f62ccc3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Various cleanups in Unicode handling. Note that without Xft on X11 we don't have Emoji.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | core-8-6-branch
Files: files | file ages | folders
SHA3-256: 7f62ccc3c60ebc55d27b6413a152af627822848cf7de16254394d29e117fa66b
User & Date: jan.nijtmans 2019-11-26 20:33:36.240
Context
2019-11-26
20:35
Horrible windows-specific workaround against SendInput not moving the mouse on Win10 when both input.mi.dx and input.mi.dy are zero) - this must be a Windows bug. bind-34.3 now passes on Win10 check-in: 4202ddbd user: jan.nijtmans tags: core-8-6-branch
20:33
Various cleanups in Unicode handling. Note that without Xft on X11 we don't have Emoji. check-in: 7f62ccc3 user: jan.nijtmans tags: core-8-6-branch
2019-11-25
12:47
Fix [a953736b54]: Potential wrong use of TkKeyEvent check-in: be77d20c user: jan.nijtmans tags: core-8-6-branch
2019-11-22
08:48
Merge 8.6 Closed-Leaf check-in: b35590d9 user: jan.nijtmans tags: utf-16-for-X11
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tkEntry.c.
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
    /*
     * If we're displaying a special character instead of the value of the
     * entry, recompute the displayString.
     */

    if (entryPtr->showChar != NULL) {
	int ch;
	char buf[6];
	int size;

	/*
	 * Normalize the special character so we can safely duplicate it in
	 * the display string. If we didn't do this, then two malformed
	 * characters might end up looking like one valid UTF character in the
	 * resulting string.







|







1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
    /*
     * If we're displaying a special character instead of the value of the
     * entry, recompute the displayString.
     */

    if (entryPtr->showChar != NULL) {
	int ch;
	char buf[4];
	int size;

	/*
	 * Normalize the special character so we can safely duplicate it in
	 * the display string. If we didn't do this, then two malformed
	 * characters might end up looking like one valid UTF character in the
	 * resulting string.
Changes to generic/tkUtil.c.
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
 *
 *---------------------------------------------------------------------------
 */

int
TkUtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)		/* Filled with the Tcl_UniChar represented by
			 * the UTF-8 string. */
{
    Tcl_UniChar uniChar = 0;

    int len = Tcl_UtfToUniChar(src, &uniChar);
    if ((uniChar & 0xfc00) == 0xd800) {
	Tcl_UniChar high = uniChar;
	/* This can only happen if Tcl is compiled with TCL_UTF_MAX=4,
	 * or when a high surrogate character is detected in UTF-8 form */
	int len2 = Tcl_UtfToUniChar(src+len, &uniChar);
	if ((uniChar & 0xfc00) == 0xdc00) {
	    *chPtr = (((high & 0x3ff) << 10) | (uniChar & 0x3ff)) + 0x10000;
	    len += len2;
	} else {
	    *chPtr = high;
	}
    } else {
	*chPtr = uniChar;
    }

    return len;
}

/*
 *---------------------------------------------------------------------------
 *
 * TkUniCharToUtf --







|





|
|


|
|
|
|
<
<

<
<

>







1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232


1233


1234
1235
1236
1237
1238
1239
1240
1241
1242
 *
 *---------------------------------------------------------------------------
 */

int
TkUtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)		/* Filled with the Unicode value represented by
			 * the UTF-8 string. */
{
    Tcl_UniChar uniChar = 0;

    int len = Tcl_UtfToUniChar(src, &uniChar);
    if ((uniChar & 0xFC00) == 0xD800) {
	Tcl_UniChar low = uniChar;
	/* This can only happen if Tcl is compiled with TCL_UTF_MAX=4,
	 * or when a high surrogate character is detected in UTF-8 form */
	int len2 = Tcl_UtfToUniChar(src+len, &low);
	if ((uniChar & 0xFC00) == 0xDC00) {
	    *chPtr = (((uniChar & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000;
	    return len + len2;


	}


    }
    *chPtr = uniChar;
    return len;
}

/*
 *---------------------------------------------------------------------------
 *
 * TkUniCharToUtf --
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270


1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int TkUniCharToUtf(int ch, char *buf)
{
    int size = Tcl_UniCharToUtf(ch, buf);
    if ((((unsigned)(ch - 0x10000) <= 0xFFFFF)) && (size < 4)) {
	/* Hey, this is wrong, we must be running TCL_UTF_MAX==3
	 * The best thing we can do is spit out a 4-byte UTF-8 character */
	buf[3] = (char) ((ch | 0x80) & 0xBF);
	buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
	buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 18) | 0xF0);
	size = 4;


    }
    return size;
}


#endif
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







<
|
<
|
|
|
|
|
|
>
>

<











1252
1253
1254
1255
1256
1257
1258

1259

1260
1261
1262
1263
1264
1265
1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int TkUniCharToUtf(int ch, char *buf)
{

    if (((unsigned)(ch - 0x10000) <= 0xFFFFF)) {

	/* Spit out a 4-byte UTF-8 character */
	*buf++ = (char) ((ch >> 18) | 0xF0);
	*buf++ = (char) (((ch >> 12) | 0x80) & 0xBF);
	*buf++ = (char) (((ch >> 6) | 0x80) & 0xBF);
	*buf = (char) ((ch | 0x80) & 0xBF);
	return 4;
    } else {
	return Tcl_UniCharToUtf(ch, buf);
    }

}


#endif
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/ttk/ttkEntry.c.
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
 * 	Used to compute the displayString if -show is non-NULL.
 */
static char *EntryDisplayString(const char *showChar, int numChars)
{
    char *displayString, *p;
    int size;
    int ch;
    char buf[6];

    TkUtfToUniChar(showChar, &ch);
    size = TkUniCharToUtf(ch, buf);
    p = displayString = ckalloc(numChars * size + 1);

    while (numChars--) {
	memcpy(p, buf, size);







|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
 * 	Used to compute the displayString if -show is non-NULL.
 */
static char *EntryDisplayString(const char *showChar, int numChars)
{
    char *displayString, *p;
    int size;
    int ch;
    char buf[4];

    TkUtfToUniChar(showChar, &ch);
    size = TkUniCharToUtf(ch, buf);
    p = displayString = ckalloc(numChars * size + 1);

    while (numChars--) {
	memcpy(p, buf, size);
Changes to library/demos/unicodeout.tcl.
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139

140
141
142
143
144
    # Using standard text characters
    addSample $w Arabic \
	    "\u0627\u0644\u0643\u0644\u0645\u0629 " \
	    "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"
}
addSample $w "Trad. Chinese"  "\u4E2D\u570B\u7684\u6F22\u5B57"
addSample $w "Simpl. Chinese" "\u6C49\u8BED"
addSample $w French "Langue fran\u00E7aise"
addSample $w Greek \
	 "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE " \
	 "\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1"
if {[usePresentationFormsFor Hebrew]} {
    # Visual order (pre-layouted)
    addSample $w Hebrew \
	    "\u05EA\u05D9\u05E8\u05D1\u05E2 \u05D1\u05EA\u05DB"
} else {
    # Standard logical order
    addSample $w Hebrew \
	    "\u05DB\u05EA\u05D1 \u05E2\u05D1\u05E8\u05D9\u05EA"
}
addSample $w Hindi \
    "\u0939\u093f\u0928\u094d\u0926\u0940 \u092d\u093e\u0937\u093e"
addSample $w Icelandic "\u00CDslenska"
addSample $w Japanese \
	 "\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, " \
	 "\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA"
addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
addSample $w Russian \
	"\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"

if {[package vsatisfies [package provide Tcl] 8.7-]} {
    addSample $w Emoji \
	    "\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1"
} elseif {([tk windowingsystem] ne "x11") || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))} {
    addSample $w Emoji \
	    "\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1"

}

## We're done processing, so change things back to normal running...
destroy $w.wait
$w conf -cursor $oldCursor







|

|
|










|
|

|
|



>
|
|
|
|
|
|
>





105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    # Using standard text characters
    addSample $w Arabic \
	    "\u0627\u0644\u0643\u0644\u0645\u0629 " \
	    "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"
}
addSample $w "Trad. Chinese"  "\u4E2D\u570B\u7684\u6F22\u5B57"
addSample $w "Simpl. Chinese" "\u6C49\u8BED"
addSample $w French "Langue fran\xE7aise"
addSample $w Greek \
	"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE " \
	"\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1"
if {[usePresentationFormsFor Hebrew]} {
    # Visual order (pre-layouted)
    addSample $w Hebrew \
	    "\u05EA\u05D9\u05E8\u05D1\u05E2 \u05D1\u05EA\u05DB"
} else {
    # Standard logical order
    addSample $w Hebrew \
	    "\u05DB\u05EA\u05D1 \u05E2\u05D1\u05E8\u05D9\u05EA"
}
addSample $w Hindi \
    "\u0939\u093F\u0928\u094D\u0926\u0940 \u092D\u093E\u0937\u093E"
addSample $w Icelandic "\xCDslenska"
addSample $w Japanese \
	"\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, " \
	"\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA"
addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
addSample $w Russian \
	"\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"
if {([tk windowingsystem] ne "x11") || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))} {
    if {[package vsatisfies [package provide Tcl] 8.7-]} {
	addSample $w Emoji \
		"\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1"
    } else {
	addSample $w Emoji \
		"\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1"
    }
}

## We're done processing, so change things back to normal running...
destroy $w.wait
$w conf -cursor $oldCursor
Changes to unix/tkUnixFont.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkUnixInt.h"
#include "tkFont.h"
#include <netinet/in.h>		/* for htons() prototype */
#include <arpa/inet.h>		/* inet_ntoa() */

/*
 * The preferred font encodings.
 */

static const char *const encodingList[] = {
    "iso8859-1", "jis0208", "jis0212", NULL







<
<







8
9
10
11
12
13
14


15
16
17
18
19
20
21
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkUnixInt.h"
#include "tkFont.h"



/*
 * The preferred font encodings.
 */

static const char *const encodingList[] = {
    "iso8859-1", "jis0208", "jis0212", NULL
483
484
485
486
487
488
489
490
491

492



493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517



518
519
520


521
522


523
524

525
526
527
528
529
530
531
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    char *dstEnd, *dstStart;
    int result, numChars;





    result = TCL_OK;

    /* check alignment with ucs-2 (2 == sizeof(UCS-2)) */
    if ((srcLen % 2) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;
    }
    /* If last code point is a high surrogate, we cannot handle that yet */
    if ((srcLen >= 2) && ((src[srcLen - 2] & 0xFC) == 0xD8)) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen -= 2;
    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}




	/*
	 * Need to swap byte-order on little-endian machines (x86) for
	 * UCS-2BE. We know this is an LE->BE swap.


	 */



	dst += Tcl_UniCharToUtf(htons(*((short *)src)), dst);
	src += 2 /* sizeof(UCS-2) */;

    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}







|
|
>

>
>
>

















|

|





>
>
>

<
<
>
>

|
>
>
|
<
>







481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523


524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    const char *dstEnd, *dstStart;
    int result, numChars, charLimit = INT_MAX;
    unsigned short ch;

    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }
    result = TCL_OK;

    /* check alignment with ucs-2 (2 == sizeof(UCS-2)) */
    if ((srcLen % 2) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;
    }
    /* If last code point is a high surrogate, we cannot handle that yet */
    if ((srcLen >= 2) && ((src[srcLen - 2] & 0xFC) == 0xD8)) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen -= 2;
    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - 4;

    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}

	ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF);
	src += 2 /* sizeof(UTF-16) */;

	/*


	 * Special case for 1-byte utf chars for speed. Make sure we work with
	 * unsigned short-size data.
	 */
	if (ch && ch < 0x80) {
	    *dst++ = (ch & 0xFF);
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);

	}
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;
    Tcl_UniChar *chPtr = (Tcl_UniChar *)statePtr;

    if (flags & TCL_ENCODING_START) {
	*statePtr = 0;
    }

    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if (!(flags & TCL_ENCODING_END)) {
	srcClose -= TCL_UTF_MAX;
    }

    dstStart = dst;
    dstEnd = dst + dstLen - 2 /* sizeof(UCS-2) */;

    result = TCL_OK;
    for (numChars = 0; src < srcEnd; numChars++) {
	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */
	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	src += Tcl_UtfToUniChar(src, chPtr);

	/*
	 * Ensure big-endianness (store big bits first).
	 * XXX: This hard-codes the assumed size of Tcl_UniChar as 2. Make
	 * sure to work in char* for Tcl_UtfToUniChar alignment. [Bug 1122671]
	 */


	*dst++ = (char)(*chPtr >> 8);
	*dst++ = (char)*chPtr;
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}








<
|
<
<
<





|



















|



<
<


<
|
|







579
580
581
582
583
584
585

586



587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615


616
617

618
619
620
621
622
623
624
625
626
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;

    int ch;




    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if (!(flags & TCL_ENCODING_END)) {
	srcClose -= 6;
    }

    dstStart = dst;
    dstEnd = dst + dstLen - 2 /* sizeof(UCS-2) */;

    result = TCL_OK;
    for (numChars = 0; src < srcEnd; numChars++) {
	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */
	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	src += TkUtfToUniChar(src, &ch);

	/*
	 * Ensure big-endianness (store big bits first).


	 */


	*dst++ = (char)(ch >> 8);
	*dst++ = (char)ch;
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

Changes to win/tkWinFont.c.
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
    SubFont *subFontPtr,	/* Contains font mapping cache to be
				 * updated. */
    int row)			/* Index of the page to be loaded into the
				 * cache. */
{
    FontFamily *familyPtr;
    Tcl_Encoding encoding;
    char src[XMaxTransChars], buf[16];
    USHORT *startCount, *endCount;
    int i, j, bitOffset, end, segCount;

    subFontPtr->fontMap[row] = ckalloc(FONTMAP_BITSPERPAGE / 8);
    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);

    familyPtr = subFontPtr->familyPtr;
    encoding = familyPtr->encoding;








|

|







2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
    SubFont *subFontPtr,	/* Contains font mapping cache to be
				 * updated. */
    int row)			/* Index of the page to be loaded into the
				 * cache. */
{
    FontFamily *familyPtr;
    Tcl_Encoding encoding;
    int i, j, bitOffset, end, segCount;
    USHORT *startCount, *endCount;
    char buf[16], src[4];

    subFontPtr->fontMap[row] = ckalloc(FONTMAP_BITSPERPAGE / 8);
    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);

    familyPtr = subFontPtr->familyPtr;
    encoding = familyPtr->encoding;

Changes to win/tkWinKey.c.
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
    TkWindow *winPtr,		/* Window where event occurred: needed to get
				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    XKeyEvent *keyEv = &eventPtr->xkey;
    char buf[6];
    int len;


    Tcl_DStringInit(dsPtr);
    if (keyEv->send_event == -1) {
	if (keyEv->nbytes > 0) {
	    Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(),
		    keyEv->trans_chars, keyEv->nbytes, dsPtr);
	}







<

>







93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
    TkWindow *winPtr,		/* Window where event occurred: needed to get
				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    XKeyEvent *keyEv = &eventPtr->xkey;

    int len;
    char buf[4];

    Tcl_DStringInit(dsPtr);
    if (keyEv->send_event == -1) {
	if (keyEv->nbytes > 0) {
	    Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(),
		    keyEv->trans_chars, keyEv->nbytes, dsPtr);
	}
Changes to win/tkWinX.c.
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
	 * for system messages, because those were presumably generated as an
	 * Alt-char sequence (e.g. accelerator keys).
	 */

	if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
	    xkey->state = 0;
	}
	xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
	xkey->nbytes++;

	if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
	    /*
	     * Some "addon" input devices, such as the popular PenPower
	     * Chinese writing pad, generate 16 bit values in WM_CHAR messages
	     * (instead of passing them in two separate WM_CHAR messages
	     * containing two 8-bit values.







|
<







1474
1475
1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
	 * for system messages, because those were presumably generated as an
	 * Alt-char sequence (e.g. accelerator keys).
	 */

	if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
	    xkey->state = 0;
	}
	xkey->trans_chars[xkey->nbytes++] = (char) msg.wParam;


	if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
	    /*
	     * Some "addon" input devices, such as the popular PenPower
	     * Chinese writing pad, generate 16 bit values in WM_CHAR messages
	     * (instead of passing them in two separate WM_CHAR messages
	     * containing two 8-bit values.