-
Notifications
You must be signed in to change notification settings - Fork 26
/
editbox.go
112 lines (95 loc) · 2.52 KB
/
editbox.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package jiraui
import (
"unicode/utf8"
)
const tabstop_length = 8
type EditBox struct {
text []byte
line_voffset int
cursor_boffset int // cursor offset in bytes
cursor_voffset int // visual cursor offset in termbox cells
cursor_coffset int // cursor offset in unicode code points
}
func byte_slice_grow(s []byte, desired_cap int) []byte {
if cap(s) < desired_cap {
ns := make([]byte, len(s), desired_cap)
copy(ns, s)
return ns
}
return s
}
func byte_slice_remove(text []byte, from, to int) []byte {
size := to - from
copy(text[from:], text[to:])
text = text[:len(text)-size]
return text
}
func byte_slice_insert(text []byte, offset int, what []byte) []byte {
n := len(text) + len(what)
text = byte_slice_grow(text, n)
text = text[:n]
copy(text[offset+len(what):], text[offset:])
copy(text[offset:], what)
return text
}
func decodeTermuiKbdStringToRune(str string) rune {
r, _ := utf8.DecodeRuneInString(str) // should be a single rune
return r
}
func (eb *EditBox) InsertRune(r rune) {
var buf [utf8.UTFMax]byte
n := utf8.EncodeRune(buf[:], r)
eb.text = byte_slice_insert(eb.text, eb.cursor_boffset, buf[:n])
eb.MoveCursorOneRuneForward()
}
func (eb *EditBox) DeleteRuneBackward() {
if eb.cursor_boffset == 0 {
return
}
eb.MoveCursorOneRuneBackward()
_, size := eb.RuneUnderCursor()
eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size)
}
func (eb *EditBox) MoveCursorOneRuneBackward() {
if eb.cursor_boffset == 0 {
return
}
_, size := eb.RuneBeforeCursor()
eb.MoveCursorTo(eb.cursor_boffset - size)
}
func (eb *EditBox) MoveCursorOneRuneForward() {
if eb.cursor_boffset == len(eb.text) {
return
}
_, size := eb.RuneUnderCursor()
eb.MoveCursorTo(eb.cursor_boffset + size)
}
func (eb *EditBox) RuneUnderCursor() (rune, int) {
return utf8.DecodeRune(eb.text[eb.cursor_boffset:])
}
func (eb *EditBox) RuneBeforeCursor() (rune, int) {
return utf8.DecodeLastRune(eb.text[:eb.cursor_boffset])
}
func (eb *EditBox) MoveCursorTo(boffset int) {
eb.cursor_boffset = boffset
eb.cursor_voffset, eb.cursor_coffset = voffset_coffset(eb.text, boffset)
}
func (eb *EditBox) MoveCursorToEnd() {
eb.MoveCursorTo(len(eb.text))
}
func rune_advance_len(r rune, pos int) int {
if r == '\t' {
return tabstop_length - pos%tabstop_length
}
return 1
}
func voffset_coffset(text []byte, boffset int) (voffset, coffset int) {
text = text[:boffset]
for len(text) > 0 {
r, size := utf8.DecodeRune(text)
text = text[size:]
coffset += 1
voffset += rune_advance_len(r, voffset)
}
return
}