| Ticket UUID: | 18f35ed566d96f9d3d55e99e0af3ef8f10faf7 | |||
| Title: | [text]: "display lineend" lands inside a multi-byte character, so [get] returns half a character | |||
| Type: | Bug | Version: | 8.6.18, 9.0.5, 9.1.0 | |
| Submitter: | serhiy.storchaka | Created on: | 2026-10-18 12:57:39 | |
| Subsystem: | 18. [text] | Assigned To: | jan.nijtmans | |
| Priority: | 5 Medium | Severity: | Minor | |
| Status: | Closed | Last Modified: | 2026-10-22 17:06:15 | |
| Resolution: | Fixed | Closed By: | jan.nijtmans | |
| Closed on: | 2026-10-22 17:06:15 | |||
| Description: |
In a text widget, the index display lineend lands in the middle of a character when the display line ends with a character that takes more than one byte in UTF-8: pack [text .t -width 1 -wrap char] .t insert end "aäb" update .t get "1.1 display linestart" "1.1 display lineend" returns à (U+00C3, the first byte of the UTF-8 encoding of ä), instead of ä. [.t index "1.1 display lineend"] says 1.2, and [.t get 1.1 1.2] correctly returns ä. [.t dump -text] gives à as well. TkTextFindDisplayLineEnd() in generic/tkTextDisp.c computes the end as the start of the next display line minus one byte (TkTextIndexBackBytes(textPtr, &nextLineStart, 1, indexPtr)). That is right when the display line ends with a space or a newline, as it usually does, but not when it ends inside a word with a multi-byte character, as with -wrap char or a word longer than the width. This is the cause of Tcl ticket 1943546fff (2008): a script stepping through an unmapped -wrap word text by display lines got the lone byte from [.t get], and [puts] failed with "invalid argument". An unmapped text widget was laid out at 1x1 pixels, so every character was a display line of its own. Since [7d8d10e4a9] (now on all branches, not yet in a release) the requested size is used, which hides that script, but not the bug. Seen with 8.6.18, 9.0.5 and 9.1.0. | |||
| User Comments: |
jan.nijtmans added on 2026-10-22 17:06:15:
Fixed in [1a277e8621|trunk], core-9-0-branch and core-8-6-branch Many thanks! serhiy.storchaka added on 2026-10-18 13:06:02: Fix in branch text-display-lineend-multibyte: move back one character instead of one byte from the start of the next display line. Note that the end of a display line is the index of its last character, so with the example [.t index "1.1 display lineend"] is now 1.1, and [.t get "1.1 display linestart" "1.1 display lineend"] returns an empty string, as for ASCII text; [.t get "1.1 display linestart" "1.1 display lineend +1c"] returns ä. | |||
Home
Timeline
Branches
Tags
Forum
Tickets
Download
Wiki