...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package tcell
16
17 import (
18 "os"
19
20 runewidth "github.com/mattn/go-runewidth"
21 )
22
23 type cell struct {
24 currMain rune
25 currComb []rune
26 currStyle Style
27 lastMain rune
28 lastStyle Style
29 lastComb []rune
30 width int
31 }
32
33
34
35
36
37
38
39 type CellBuffer struct {
40 w int
41 h int
42 cells []cell
43 }
44
45
46
47 func (cb *CellBuffer) SetContent(x int, y int,
48 mainc rune, combc []rune, style Style) {
49
50 if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
51 c := &cb.cells[(y*cb.w)+x]
52
53 for i := 1; i < c.width; i++ {
54 cb.SetDirty(x+i, y, true)
55 }
56
57 c.currComb = append([]rune{}, combc...)
58
59 if c.currMain != mainc {
60 c.width = runewidth.RuneWidth(mainc)
61 }
62 c.currMain = mainc
63 c.currStyle = style
64 }
65 }
66
67
68
69
70
71 func (cb *CellBuffer) GetContent(x, y int) (rune, []rune, Style, int) {
72 var mainc rune
73 var combc []rune
74 var style Style
75 var width int
76 if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
77 c := &cb.cells[(y*cb.w)+x]
78 mainc, combc, style = c.currMain, c.currComb, c.currStyle
79 if width = c.width; width == 0 || mainc < ' ' {
80 width = 1
81 mainc = ' '
82 }
83 }
84 return mainc, combc, style, width
85 }
86
87
88 func (cb *CellBuffer) Size() (int, int) {
89 return cb.w, cb.h
90 }
91
92
93 func (cb *CellBuffer) Invalidate() {
94 for i := range cb.cells {
95 cb.cells[i].lastMain = rune(0)
96 }
97 }
98
99
100
101
102
103 func (cb *CellBuffer) Dirty(x, y int) bool {
104 if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
105 c := &cb.cells[(y*cb.w)+x]
106 if c.lastMain == rune(0) {
107 return true
108 }
109 if c.lastMain != c.currMain {
110 return true
111 }
112 if c.lastStyle != c.currStyle {
113 return true
114 }
115 if len(c.lastComb) != len(c.currComb) {
116 return true
117 }
118 for i := range c.lastComb {
119 if c.lastComb[i] != c.currComb[i] {
120 return true
121 }
122 }
123 }
124 return false
125 }
126
127
128
129
130 func (cb *CellBuffer) SetDirty(x, y int, dirty bool) {
131 if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
132 c := &cb.cells[(y*cb.w)+x]
133 if dirty {
134 c.lastMain = rune(0)
135 } else {
136 if c.currMain == rune(0) {
137 c.currMain = ' '
138 }
139 c.lastMain = c.currMain
140 c.lastComb = c.currComb
141 c.lastStyle = c.currStyle
142 }
143 }
144 }
145
146
147
148
149 func (cb *CellBuffer) Resize(w, h int) {
150
151 if cb.h == h && cb.w == w {
152 return
153 }
154
155 newc := make([]cell, w*h)
156 for y := 0; y < h && y < cb.h; y++ {
157 for x := 0; x < w && x < cb.w; x++ {
158 oc := &cb.cells[(y*cb.w)+x]
159 nc := &newc[(y*w)+x]
160 nc.currMain = oc.currMain
161 nc.currComb = oc.currComb
162 nc.currStyle = oc.currStyle
163 nc.width = oc.width
164 nc.lastMain = rune(0)
165 }
166 }
167 cb.cells = newc
168 cb.h = h
169 cb.w = w
170 }
171
172
173
174
175 func (cb *CellBuffer) Fill(r rune, style Style) {
176 for i := range cb.cells {
177 c := &cb.cells[i]
178 c.currMain = r
179 c.currComb = nil
180 c.currStyle = style
181 c.width = 1
182 }
183 }
184
185 var runeConfig *runewidth.Condition
186
187 func init() {
188
189
190
191 if os.Getenv("RUNEWIDTH_EASTASIAN") == "" {
192 runewidth.DefaultCondition.EastAsianWidth = false
193 }
194
195
196
197
198 if os.Getenv("TCELL_MINIMIZE") == "" {
199 runewidth.CreateLUT()
200 }
201 }
202
View as plain text