From d6a967c9d8c6cc6dc8d5792070e2c2349f6ce3d8 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 1 Nov 2019 11:03:25 +0000 Subject: Somewhat more progress on [a179564826]: Tk 8.6: prevent issues when encountering non-BMP Unicode characters. Increase XMaxTransChars from 4 to 7, at the same time reducing the nbytes field from int to unsigned char. This makes more room to NULL-terminate the trans_chars array in the XEvent, even when it's 4 bytes in length. (fully binary compatible, since the nbytes field is not supposed to be accessed externally) --- macosx/tkMacOSXKeyEvent.c | 6 ++---- macosx/tkMacOSXKeyboard.c | 2 +- unix/tkUnixFont.c | 2 +- unix/tkUnixKey.c | 2 +- win/tkWinFont.c | 2 +- win/tkWinKey.c | 2 +- xlib/X11/Xlib.h | 6 +++--- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 7ce8fc8..677f77e 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -603,17 +603,15 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state) memset(xEvent, 0, sizeof(XEvent)); xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - xEvent->xany.send_event = false; xEvent->xany.display = Tk_Display(tkwin); xEvent->xany.window = Tk_WindowId(tkwin); xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0); - xEvent->xkey.subwindow = None; xEvent->xkey.time = TkpGetMS(); xEvent->xkey.state = state; xEvent->xkey.same_screen = true; - xEvent->xkey.trans_chars[0] = 0; - xEvent->xkey.nbytes = 0; + /* No need to initialize other fields implicitly here, + * because of the memset() above. */ } #pragma mark - diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c index 78bda9e..b2c78d3 100644 --- a/macosx/tkMacOSXKeyboard.c +++ b/macosx/tkMacOSXKeyboard.c @@ -720,7 +720,7 @@ TkpSetKeycodeAndState( } if (keysym <= LATIN1_MAX) { - int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars); + int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars); eventPtr->xkey.trans_chars[done] = 0; } else { diff --git a/unix/tkUnixFont.c b/unix/tkUnixFont.c index 1e80231..96b6195 100644 --- a/unix/tkUnixFont.c +++ b/unix/tkUnixFont.c @@ -520,7 +520,7 @@ Ucs2beToUtfProc( * UCS-2BE. We know this is an LE->BE swap. */ - dst += Tcl_UniCharToUtf(htons(*((short *)src)), dst); + dst += TkUniCharToUtf(htons(*((short *)src)), dst); src += 2 /* sizeof(UCS-2) */; } diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c index 6d4d0cf..75d5f6c 100644 --- a/unix/tkUnixKey.c +++ b/unix/tkUnixKey.c @@ -208,7 +208,7 @@ TkpGetString( Tcl_DStringValue(&buf)[len] = '\0'; if (len == 1) { - len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0], + len = TkUniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0], Tcl_DStringValue(dsPtr)); Tcl_DStringSetLength(dsPtr, len); } else { diff --git a/win/tkWinFont.c b/win/tkWinFont.c index 321ecc4..604a667 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -2225,7 +2225,7 @@ FontMapLoadPage( end = (row + 1) << FONTMAP_SHIFT; for (i = row << FONTMAP_SHIFT; i < end; i++) { if (Tcl_UtfToExternal(NULL, encoding, src, - Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL, + TkUniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL, buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) { continue; } diff --git a/win/tkWinKey.c b/win/tkWinKey.c index 234a158..4130579 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -122,7 +122,7 @@ TkpGetString( if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256)) || (keysym == XK_Return) || (keysym == XK_Tab)) { - len = Tcl_UniCharToUtf(keysym & 255, buf); + len = TkUniCharToUtf(keysym & 255, buf); Tcl_DStringAppend(dsPtr, buf, len); } } diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h index 8d8ec68..e8940d9 100644 --- a/xlib/X11/Xlib.h +++ b/xlib/X11/Xlib.h @@ -530,7 +530,7 @@ typedef struct _XDisplay { #endif #ifndef _XEVENT_ -#define XMaxTransChars 4 +#define XMaxTransChars 7 /* * Definitions of specific events. @@ -549,9 +549,9 @@ typedef struct { unsigned int state; /* key or button mask */ unsigned int keycode; /* detail */ Bool same_screen; /* same screen flag */ - char trans_chars[XMaxTransChars]; + char trans_chars[XMaxTransChars]; /* translated characters */ - int nbytes; + unsigned char nbytes; } XKeyEvent; typedef XKeyEvent XKeyPressedEvent; typedef XKeyEvent XKeyReleasedEvent; -- cgit v0.12 From aa42e365e10d36a627c74dd41c016fa92a1e36b6 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 1 Nov 2019 20:54:55 +0000 Subject: The previous commit [65bb96b4] was wrong: it did not take into account the specifics of -displaycolumns or the fact column #0 (the tree) is special. This introduced a regression in the headings activation: they did not de-activate properly when the mouse left the headings. Fix this and document in the code why catching is (much) easier than writing an explicit proc. --- library/ttk/treeview.tcl | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 4158739..df188b7 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -120,9 +120,18 @@ proc ttk::treeview::ActivateHeading {w heading} { variable State if {$w != $State(activeWidget) || $heading != $State(activeHeading)} { - if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {} - && $State(activeHeading) in [$State(activeWidget) cget -displaycolumns]} { - $State(activeWidget) heading $State(activeHeading) state !active + if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} { + # It may happen that $State(activeHeading) no longer corresponds + # to an existing display column. This happens for instance when + # changing -displaycolumns in a bound script when this change + # triggers a event. A proc checking if the display column + # $State(activeHeading) is really still present or not could be + # written but it would need to check several special cases: + # a. -displaycolumns "#all" or being an explicit columns list + # b. column #0 display is not governed by the -displaycolumn + # list but by the value of the -show option + # --> Let's rather catch the following line. + catch {$State(activeWidget) heading $State(activeHeading) state !active} } if {$heading != {}} { $w heading $heading state active -- cgit v0.12