@@ -8,50 +8,59 @@ import (
88 "iter"
99 "strings"
1010 "unicode"
11-
12- "github.com/rivo/uniseg"
1311)
1412
1513func removeSpaceAtLineTail (str string ) string {
1614 return strings .TrimRightFunc (str , unicode .IsSpace )
1715}
1816
19- func lines (text string , width int ) iter.Seq [string ] {
17+ func sanitizeUTF8 (s string ) string {
18+ var b strings.Builder
19+ for _ , r := range s {
20+ b .WriteRune (r )
21+ }
22+ return b .String ()
23+ }
24+
25+ func (c * Context ) lines (text string , width int ) iter.Seq [string ] {
2026 return func (yield func (string ) bool ) {
27+ seg := c .pushSegmenter ()
28+ defer c .popSegmenter ()
29+
30+ if err := seg .InitWithString (text ); err != nil {
31+ text = sanitizeUTF8 (text )
32+ if err := seg .InitWithString (text ); err != nil {
33+ panic ("debugui: segmenter.InitWithString failed even after sanitizing: " + err .Error ())
34+ }
35+ }
36+
2137 var line string
22- var word string
23- state := - 1
24- for len (text ) > 0 {
25- cluster , nextText , boundaries , nextState := uniseg .StepString (text , state )
26- switch m := boundaries & uniseg .MaskLine ; m {
27- default :
28- word += cluster
29- case uniseg .LineCanBreak , uniseg .LineMustBreak :
30- if line == "" {
31- line += word + cluster
32- } else {
33- if l := removeSpaceAtLineTail (line + word + cluster ); textWidth (l ) > width {
34- if ! yield (removeSpaceAtLineTail (line )) {
35- return
36- }
37- line = word + cluster
38- } else {
39- line += word + cluster
40- }
41- }
42- word = ""
43- if m == uniseg .LineMustBreak {
38+ it := seg .LineIterator ()
39+ for it .Next () {
40+ l := it .Line ()
41+ segment := text [l .OffsetInBytes : l .OffsetInBytes + l .LengthInBytes ]
42+
43+ if line == "" {
44+ line = segment
45+ } else {
46+ if trimmed := removeSpaceAtLineTail (line + segment ); textWidth (trimmed ) > width {
4447 if ! yield (removeSpaceAtLineTail (line )) {
4548 return
4649 }
47- line = ""
50+ line = segment
51+ } else {
52+ line += segment
53+ }
54+ }
55+
56+ if l .IsMandatoryBreak {
57+ if ! yield (removeSpaceAtLineTail (line )) {
58+ return
4859 }
60+ line = ""
4961 }
50- state = nextState
51- text = nextText
5262 }
5363
54- line += word
5564 if len (line ) > 0 {
5665 if ! yield (removeSpaceAtLineTail (line )) {
5766 return
@@ -63,7 +72,7 @@ func lines(text string, width int) iter.Seq[string] {
6372// Text creates a text label.
6473func (c * Context ) Text (text string ) {
6574 c .GridCell (func (bounds image.Rectangle ) {
66- for line := range lines (text , bounds .Dx ()- c .style ().padding ) {
75+ for line := range c . lines (text , bounds .Dx ()- c .style ().padding ) {
6776 _ , _ = c .widget (widgetID {}, 0 , nil , nil , func (bounds image.Rectangle ) {
6877 c .drawWidgetText (line , bounds , colorText , 0 )
6978 })
0 commit comments