From 1f1f979c1bfd00f2da554d2dd6604f75d4f47d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=96R=C3=96SK=C5=90I=20Andr=C3=A1s?= Date: Sun, 12 Apr 2020 21:17:06 +0200 Subject: [PATCH] TextArea: use [][]rune instead of []string in linesModel This way GetCell() will get full runes, not just bytes. Now accent characters will show properly Adjust SetLines() and Init() to work on [][]rune instead of []string --- views/textarea.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/views/textarea.go b/views/textarea.go index 0efacc7..529eb4a 100644 --- a/views/textarea.go +++ b/views/textarea.go @@ -33,7 +33,7 @@ type TextArea struct { } type linesModel struct { - lines []string + runes [][]rune width int height int x int @@ -44,12 +44,11 @@ type linesModel struct { } func (m *linesModel) GetCell(x, y int) (rune, tcell.Style, []rune, int) { - var ch rune - if x < 0 || y < 0 || y >= len(m.lines) || x >= len(m.lines[y]) { - return ch, m.style, nil, 1 + if x < 0 || y < 0 || y >= m.height || x >= len(m.runes[y]) { + return 0, m.style, nil, 1 } // XXX: extend this to support combining and full width chars - return rune(m.lines[y][x]), m.style, nil, 1 + return m.runes[y][x], m.style, nil, 1 } func (m *linesModel) GetBounds() (int, int) { @@ -91,14 +90,22 @@ func (m *linesModel) GetCursor() (int, int, bool, bool) { func (ta *TextArea) SetLines(lines []string) { ta.Init() m := ta.model - m.width = 0 - m.height = len(lines) - m.lines = append([]string{}, lines...) - for _, l := range lines { - if len(l) > m.width { - m.width = len(l) + + // extend slice before using m.runes[row] to avoid panic + slice := make([][]rune, len(lines)) + m.runes = append(m.runes, slice...) + + for row, line := range lines { + for _, ch := range line { + m.runes[row] = append(m.runes[row], ch) + } + if len(m.runes[row]) > m.width { + m.width = len(m.runes[row]) } } + + m.height = len(m.runes) + ta.CellView.SetModel(m) } @@ -132,7 +139,7 @@ func (ta *TextArea) SetContent(text string) { // Init initializes the TextArea. func (ta *TextArea) Init() { ta.once.Do(func() { - lm := &linesModel{lines: []string{}, width: 0} + lm := &linesModel{runes: [][]rune{}, width: 0} ta.model = lm ta.CellView.Init() ta.CellView.SetModel(lm)