/
delete.go
174 lines (149 loc) · 4.38 KB
/
delete.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
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package frame
import (
"image"
)
func (f *frameimpl) Delete(p0, p1 int) int {
f.lk.Lock()
defer f.lk.Unlock()
return f.deleteimpl(p0, p1)
}
// TODO(rjk): Add doc comments.
func (f *frameimpl) deleteimpl(p0, p1 int) int {
f.validateboxmodel("Frame.Delete Start p0=%d p1=%d", p0, p1)
defer f.validateboxmodel("Frame.Delete Start p0=%d p1=%d", p0, p1)
if p1 > f.nchars {
p1 = f.nchars - 1
}
if p0 >= f.nchars || p0 == p1 || f.background == nil {
return 0
}
n0 := f.findbox(0, 0, p0)
if n0 == len(f.box) {
panic("off end in Frame.Delete")
}
n1 := f.findbox(n0, p0, p1)
pt0 := f.ptofcharnb(p0, n0)
pt1 := f.ptofcharptb(p1, f.rect.Min, 0)
// TODO(rjk): Why do this after the splitting? It has already increased the work by this point?
// There are more boxes. And so drawing will be slower?
// Remove the selection or tick.
f.drawselimpl(f.ptofcharptb(f.sp0, f.rect.Min, 0), f.sp0, f.sp1, false)
nn0 := n0
ppt0 := pt0
f.modified = true
/*
* Invariants:
* - pt0 points to beginning, pt1 points to end
* - n0 is box containing beginning of stuff being deleted
* - n1, b are box containing beginning of stuff to be kept after deletion
* - f->p0 and f->p1 are not adjusted until after all deletion is done
*/
// f.Logboxes("before loop pt0 %v pt1 %v n0 %d n1 %d", pt0, pt1, n0, n1)
var r image.Rectangle
for pt1.X != pt0.X && n1 < len(f.box) {
// f.Logboxes("top of loop pt0 %v pt1 %v n0 %d n1 %d, r %v", pt0, pt1, n0, n1)
b := f.box[n1]
pt0 = f.cklinewrap0(pt0, b)
pt1 = f.cklinewrap(pt1, b)
n, fits := f.canfit(pt0, b)
if !fits {
panic("Frame.delete, canfit fits is false")
}
// r is the rectangle corresponding to the area that must be replaced to update
// the display with the removal of the text.
r.Min = pt0
r.Max = pt0
r.Max.Y += f.defaultfontheight
if b.Nrune > 0 {
w0 := b.Wid
if n != b.Nrune {
f.splitbox(n1, n)
b = f.box[n1]
}
r.Max.X += int(b.Wid)
// log.Printf("draw rect: %v to pt1: %v", r, pt1)
f.background.Draw(r, f.background, nil, pt1)
r.Min.X = r.Max.X
r.Max.X += int(w0 - b.Wid)
if r.Max.X > f.rect.Max.X {
r.Max.X = f.rect.Max.X
}
// Erase the portion of text at the end of the line that should be blank
// now that we've moved the box ending the line over.
// log.Printf("draw rect: %v to pt1: %v", r, pt1)
f.background.Draw(r, f.cols[ColBack], nil, r.Min)
} else {
r.Max.X += f.newwid0(pt0, b)
if r.Max.X > f.rect.Max.X {
r.Max.X = f.rect.Max.X
}
col := f.cols[ColBack]
f.background.Draw(r, col, nil, pt0)
}
pt1 = f.advance(pt1, b)
// newwid updates b with the value computed by newwid0.
// TODO(rjk): make the code cleaner with a side-effect free version.
pt0.X += f.newwid(pt0, b)
f.box[n0] = f.box[n1]
n0++
n1++
}
// log.Printf("after loop pt0 %v pt1 %v n0 %d n1 %d, r %v", pt0, pt1, n0, n1, r)
if n1 == len(f.box) && pt0.X != pt1.X {
f.SelectPaint(pt0, pt1, f.cols[ColBack])
}
if pt1.Y != pt0.Y {
// Blit up the remainder of the text.
// TODO(rjk): Understand this completely
pt2 := f.ptofcharptb(32767, pt1, n1)
if pt2.Y > f.rect.Max.Y {
panic("Frame.ptofchar in Frame.delete")
}
if n1 < len(f.box) {
height := f.defaultfontheight
q0 := pt0.Y + height
q1 := pt1.Y + height
q2 := pt2.Y + height
if q2 > f.rect.Max.Y {
q2 = f.rect.Max.Y
}
f.background.Draw(image.Rect(pt0.X, pt0.Y, pt0.X+(f.rect.Max.X-pt1.X), q0), f.background, nil, pt1)
f.background.Draw(image.Rect(f.rect.Min.X, q0, f.rect.Max.X, q0+(q2-q1)), f.background, nil, image.Pt(f.rect.Min.X, q1))
f.SelectPaint(image.Pt(pt2.X, pt2.Y-(pt1.Y-pt0.Y)), pt2, f.cols[ColBack])
} else {
f.SelectPaint(pt0, pt2, f.cols[ColBack])
}
}
f.closebox(n0, n1-1)
if nn0 > 0 && f.box[nn0-1].Nrune >= 0 && ppt0.X-int(f.box[nn0-1].Wid) >= int(f.rect.Min.X) {
nn0--
ppt0.X -= int(f.box[nn0].Wid)
}
if n0 < len(f.box)-1 {
f.clean(ppt0, nn0, n0+1)
} else {
f.clean(ppt0, nn0, n0)
}
if f.sp1 > p1 {
f.sp1 -= p1 - p0
} else if f.sp1 > p0 {
f.sp1 = p0
}
if f.sp0 > p1 {
f.sp0 -= p1 - p0
} else if f.sp0 > p0 {
f.sp0 = p0
}
f.nchars -= int(p1 - p0)
if f.sp0 == f.sp1 {
f.Tick(f.ptofcharptb(f.sp0, f.rect.Min, 0), true)
}
pt0 = f.ptofcharptb(f.nchars, f.rect.Min, 0)
n := f.nlines
f.nlines = (pt0.Y - f.rect.Min.Y) / f.defaultfontheight
if pt0.X > f.rect.Min.X {
f.nlines++
}
// f.Logboxes("end of delete")
return n - f.nlines
}