From 5cda660e6eff46cb5460ba01f276214563077e77 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 2 Dec 2023 17:33:55 -0600 Subject: [PATCH] app: slim down window.go by moving editorState to separate file Signed-off-by: Elias Naur --- app/ime.go | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ app/window.go | 110 ---------------------------------------------- 2 files changed, 118 insertions(+), 110 deletions(-) create mode 100644 app/ime.go diff --git a/app/ime.go b/app/ime.go new file mode 100644 index 00000000..909228c2 --- /dev/null +++ b/app/ime.go @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: Unlicense OR MIT +package app + +import ( + "unicode" + "unicode/utf16" + + "gioui.org/io/input" + "gioui.org/io/key" +) + +type editorState struct { + input.EditorState + compose key.Range +} + +func (e *editorState) Replace(r key.Range, text string) { + if r.Start > r.End { + r.Start, r.End = r.End, r.Start + } + runes := []rune(text) + newEnd := r.Start + len(runes) + adjust := func(pos int) int { + switch { + case newEnd < pos && pos <= r.End: + return newEnd + case r.End < pos: + diff := newEnd - r.End + return pos + diff + } + return pos + } + e.Selection.Start = adjust(e.Selection.Start) + e.Selection.End = adjust(e.Selection.End) + if e.compose.Start != -1 { + e.compose.Start = adjust(e.compose.Start) + e.compose.End = adjust(e.compose.End) + } + s := e.Snippet + if r.End < s.Start || r.Start > s.End { + // Discard snippet if it doesn't overlap with replacement. + s = key.Snippet{ + Range: key.Range{ + Start: r.Start, + End: r.Start, + }, + } + } + var newSnippet []rune + snippet := []rune(s.Text) + // Append first part of existing snippet. + if end := r.Start - s.Start; end > 0 { + newSnippet = append(newSnippet, snippet[:end]...) + } + // Append replacement. + newSnippet = append(newSnippet, runes...) + // Append last part of existing snippet. + if start := r.End; start < s.End { + newSnippet = append(newSnippet, snippet[start-s.Start:]...) + } + // Adjust snippet range to include replacement. + if r.Start < s.Start { + s.Start = r.Start + } + s.End = s.Start + len(newSnippet) + s.Text = string(newSnippet) + e.Snippet = s +} + +// UTF16Index converts the given index in runes into an index in utf16 characters. +func (e *editorState) UTF16Index(runes int) int { + if runes == -1 { + return -1 + } + if runes < e.Snippet.Start { + // Assume runes before sippet are one UTF-16 character each. + return runes + } + chars := e.Snippet.Start + runes -= e.Snippet.Start + for _, r := range e.Snippet.Text { + if runes == 0 { + break + } + runes-- + chars++ + if r1, _ := utf16.EncodeRune(r); r1 != unicode.ReplacementChar { + chars++ + } + } + // Assume runes after snippets are one UTF-16 character each. + return chars + runes +} + +// RunesIndex converts the given index in utf16 characters to an index in runes. +func (e *editorState) RunesIndex(chars int) int { + if chars == -1 { + return -1 + } + if chars < e.Snippet.Start { + // Assume runes before offset are one UTF-16 character each. + return chars + } + runes := e.Snippet.Start + chars -= e.Snippet.Start + for _, r := range e.Snippet.Text { + if chars == 0 { + break + } + chars-- + runes++ + if r1, _ := utf16.EncodeRune(r); r1 != unicode.ReplacementChar { + chars-- + } + } + // Assume runes after snippets are one UTF-16 character each. + return runes + chars +} diff --git a/app/window.go b/app/window.go index 19bf5504..a37620e1 100644 --- a/app/window.go +++ b/app/window.go @@ -9,8 +9,6 @@ import ( "image/color" "runtime" "time" - "unicode" - "unicode/utf16" "unicode/utf8" "gioui.org/f32" @@ -120,11 +118,6 @@ type Window struct { } } -type editorState struct { - input.EditorState - compose key.Range -} - type callbacks struct { w *Window d driver @@ -592,109 +585,6 @@ func (c *callbacks) ActionAt(p f32.Point) (system.Action, bool) { return c.w.queue.ActionAt(p) } -func (e *editorState) Replace(r key.Range, text string) { - if r.Start > r.End { - r.Start, r.End = r.End, r.Start - } - runes := []rune(text) - newEnd := r.Start + len(runes) - adjust := func(pos int) int { - switch { - case newEnd < pos && pos <= r.End: - return newEnd - case r.End < pos: - diff := newEnd - r.End - return pos + diff - } - return pos - } - e.Selection.Start = adjust(e.Selection.Start) - e.Selection.End = adjust(e.Selection.End) - if e.compose.Start != -1 { - e.compose.Start = adjust(e.compose.Start) - e.compose.End = adjust(e.compose.End) - } - s := e.Snippet - if r.End < s.Start || r.Start > s.End { - // Discard snippet if it doesn't overlap with replacement. - s = key.Snippet{ - Range: key.Range{ - Start: r.Start, - End: r.Start, - }, - } - } - var newSnippet []rune - snippet := []rune(s.Text) - // Append first part of existing snippet. - if end := r.Start - s.Start; end > 0 { - newSnippet = append(newSnippet, snippet[:end]...) - } - // Append replacement. - newSnippet = append(newSnippet, runes...) - // Append last part of existing snippet. - if start := r.End; start < s.End { - newSnippet = append(newSnippet, snippet[start-s.Start:]...) - } - // Adjust snippet range to include replacement. - if r.Start < s.Start { - s.Start = r.Start - } - s.End = s.Start + len(newSnippet) - s.Text = string(newSnippet) - e.Snippet = s -} - -// UTF16Index converts the given index in runes into an index in utf16 characters. -func (e *editorState) UTF16Index(runes int) int { - if runes == -1 { - return -1 - } - if runes < e.Snippet.Start { - // Assume runes before sippet are one UTF-16 character each. - return runes - } - chars := e.Snippet.Start - runes -= e.Snippet.Start - for _, r := range e.Snippet.Text { - if runes == 0 { - break - } - runes-- - chars++ - if r1, _ := utf16.EncodeRune(r); r1 != unicode.ReplacementChar { - chars++ - } - } - // Assume runes after snippets are one UTF-16 character each. - return chars + runes -} - -// RunesIndex converts the given index in utf16 characters to an index in runes. -func (e *editorState) RunesIndex(chars int) int { - if chars == -1 { - return -1 - } - if chars < e.Snippet.Start { - // Assume runes before offset are one UTF-16 character each. - return chars - } - runes := e.Snippet.Start - chars -= e.Snippet.Start - for _, r := range e.Snippet.Text { - if chars == 0 { - break - } - chars-- - runes++ - if r1, _ := utf16.EncodeRune(r); r1 != unicode.ReplacementChar { - chars-- - } - } - // Assume runes after snippets are one UTF-16 character each. - return runes + chars -} - func (w *Window) waitAck(d driver) { for { select {