-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcelldata.go
More file actions
148 lines (133 loc) · 3.86 KB
/
celldata.go
File metadata and controls
148 lines (133 loc) · 3.86 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package xterm
// Ported from xterm.js src/common/buffer/CellData.ts.
import "unicode/utf8"
// CellData represents a single cell in the terminal buffer.
// It embeds AttributeData for fg/bg/extended and adds content + combined data.
type CellData struct {
AttributeData
Content uint32
CombinedData string
}
// NewCellData creates a zero-valued CellData with initialized extended attrs.
func NewCellData() *CellData {
return &CellData{
AttributeData: DefaultAttrData(),
}
}
// CellDataFromCharData creates a CellData from a legacy CharData tuple.
func CellDataFromCharData(cd CharData) *CellData {
c := NewCellData()
c.SetFromCharData(cd)
return c
}
// IsCombined returns non-zero if the cell contains combined/multi-codepoint content.
func (c *CellData) IsCombined() uint32 {
return c.Content & ContentIsCombinedMask
}
// GetWidth returns the display width of the cell (0, 1, or 2).
func (c *CellData) GetWidth() int {
return int(c.Content >> ContentWidthShift)
}
// GetChars returns the string representation of the cell content.
func (c *CellData) GetChars() string {
if c.Content&ContentIsCombinedMask != 0 {
return c.CombinedData
}
cp := c.Content & ContentCodepointMask
if cp != 0 {
return string(rune(cp))
}
return ""
}
// GetCode returns the codepoint of the cell. For combined strings, returns
// the codepoint of the last character (matching xterm.js behavior).
func (c *CellData) GetCode() uint32 {
if c.IsCombined() != 0 {
if len(c.CombinedData) == 0 {
return 0
}
// Get the last rune
var lastRune rune
for i := 0; i < len(c.CombinedData); {
r, size := utf8.DecodeRuneInString(c.CombinedData[i:])
lastRune = r
i += size
}
return uint32(lastRune)
}
return c.Content & ContentCodepointMask
}
// SetFromCharData populates the cell from a legacy CharData tuple.
func (c *CellData) SetFromCharData(cd CharData) {
c.Fg = CharDataAttr(cd)
c.Bg = 0
ch := CharDataChar(cd)
width := CharDataWidth(cd)
combined := false
runes := []rune(ch)
if len(runes) > 2 {
combined = true
} else if len(runes) == 2 {
// Check for surrogate pair (already decoded in Go, so this is a 2-rune string).
// In Go, strings are UTF-8 and runes are already full codepoints.
// A 2-rune string is always "combined" in Go since surrogates don't exist.
combined = true
} else if len(runes) == 1 {
c.Content = uint32(runes[0]) | (uint32(width) << ContentWidthShift)
} else {
// empty string
c.Content = uint32(width) << ContentWidthShift
}
if combined {
c.CombinedData = ch
c.Content = ContentIsCombinedMask | (uint32(width) << ContentWidthShift)
}
}
// AttributesEqual returns true if this cell has the same visual attributes as other.
// Compares fg/bg color and mode, all text decoration flags, and underline style/color.
func (c *CellData) AttributesEqual(other *CellData) bool {
if c.GetFgColorMode() != other.GetFgColorMode() || c.GetFgColor() != other.GetFgColor() {
return false
}
if c.GetBgColorMode() != other.GetBgColorMode() || c.GetBgColor() != other.GetBgColor() {
return false
}
if c.IsInverse() != other.IsInverse() {
return false
}
if c.IsBold() != other.IsBold() {
return false
}
if c.IsUnderline() != other.IsUnderline() {
return false
}
if c.IsOverline() != other.IsOverline() {
return false
}
if c.IsBlink() != other.IsBlink() {
return false
}
if c.IsInvisible() != other.IsInvisible() {
return false
}
if c.IsItalic() != other.IsItalic() {
return false
}
if c.IsDim() != other.IsDim() {
return false
}
if c.IsStrikethrough() != other.IsStrikethrough() {
return false
}
if c.GetUnderlineStyle() != other.GetUnderlineStyle() {
return false
}
if c.GetUnderlineColor() != other.GetUnderlineColor() {
return false
}
return true
}
// GetAsCharData returns the cell as a legacy CharData tuple.
func (c *CellData) GetAsCharData() CharData {
return NewCharData(c.Fg, c.GetChars(), c.GetWidth(), c.GetCode())
}