9fans.net/go@v0.0.7/cmd/samterm/rasp.go (about) 1 package main 2 3 func rinit(r *Rasp) { 4 r.nrunes = 0 5 r.sect = nil 6 } 7 8 func free(interface{}) {} 9 10 func rclear(r *Rasp) { 11 var ns *Section 12 for s := r.sect; s != nil; s = ns { 13 ns = s.next 14 free(s.text) 15 free(s) 16 } 17 r.sect = nil 18 } 19 20 func rsinsert(r *Rasp, s *Section) *Section { 21 t := new(Section) 22 if r.sect == s { /* includes empty list case: r->sect==s==0 */ 23 r.sect = t 24 t.next = s 25 } else { 26 u := r.sect 27 if u == nil { 28 panic("rsinsert 1") 29 } 30 for { 31 if u.next == s { 32 t.next = s 33 u.next = t 34 goto Return 35 } 36 u = u.next 37 if u == nil { 38 break 39 } 40 } 41 panic("rsinsert 2") 42 } 43 Return: 44 return t 45 } 46 47 func rsdelete(r *Rasp, s *Section) { 48 if s == nil { 49 panic("rsdelete") 50 } 51 if r.sect == s { 52 r.sect = s.next 53 goto Free 54 } 55 for t := r.sect; t != nil; t = t.next { 56 if t.next == s { 57 t.next = s.next 58 goto Free 59 } 60 } 61 panic("rsdelete 2") 62 63 Free: 64 if s.text != nil { 65 free(s.text) 66 } 67 free(s) 68 69 } 70 71 func splitsect(r *Rasp, s *Section, n0 int) { 72 if s == nil { 73 panic("splitsect") 74 } 75 rsinsert(r, s.next) 76 if s.text == nil { 77 s.next.text = nil 78 } else { 79 s.next.text = make([]rune, TBLOCKSIZE) 80 copy(s.next.text, s.text[n0:s.nrunes]) 81 } 82 s.next.nrunes = s.nrunes - n0 83 s.nrunes = n0 84 } 85 86 func findsect(r *Rasp, s *Section, p int, q int) *Section { 87 if s == nil && p != q { 88 panic("findsect") 89 } 90 for ; s != nil && p+s.nrunes <= q; s = s.next { 91 p += s.nrunes 92 } 93 if p != q { 94 splitsect(r, s, q-p) 95 s = s.next 96 } 97 return s 98 } 99 100 func rresize(r *Rasp, a int, old int, new int) { 101 s := findsect(r, r.sect, 0, a) 102 t := findsect(r, s, a, a+old) 103 var ns *Section 104 for ; s != t; s = ns { 105 ns = s.next 106 rsdelete(r, s) 107 } 108 /* now insert the new piece before t */ 109 if new > 0 { 110 ns = rsinsert(r, t) 111 ns.nrunes = new 112 ns.text = nil 113 } 114 r.nrunes += new - old 115 } 116 117 func rdata(r *Rasp, p0 int, p1 int, cp []rune) { 118 s := findsect(r, r.sect, 0, p0) 119 t := findsect(r, s, p0, p1) 120 var ns *Section 121 for ; s != t; s = ns { 122 ns = s.next 123 if s.text != nil { 124 panic("rdata") 125 } 126 rsdelete(r, s) 127 } 128 p1 -= p0 129 s = rsinsert(r, t) 130 s.text = make([]rune, TBLOCKSIZE) 131 copy(s.text, cp[:p1]) 132 s.nrunes = p1 133 } 134 135 func rclean(r *Rasp) { 136 for s := r.sect; s != nil; s = s.next { 137 for s.next != nil && (s.text != nil) == (s.next.text != nil) { 138 if s.text != nil { 139 if s.nrunes+s.next.nrunes > TBLOCKSIZE { 140 break 141 } 142 copy(s.text[s.nrunes:s.nrunes+s.next.nrunes], s.next.text[:s.next.nrunes]) 143 } 144 s.nrunes += s.next.nrunes 145 rsdelete(r, s.next) 146 } 147 } 148 } 149 150 var raspbuf []rune 151 152 func rload(r *Rasp, p0 int, p1 int) []rune { 153 for cap(raspbuf) < p1-p0 { 154 raspbuf = append(raspbuf[:cap(raspbuf)], 0) 155 } 156 157 p := 0 158 s := r.sect 159 for ; s != nil && p+s.nrunes <= p0; s = s.next { 160 p += s.nrunes 161 } 162 nb := 0 163 for p < p1 && s != nil { 164 /* 165 * Subtle and important. If we are preparing to handle an 'rdata' 166 * call, it's because we have an 'rresize' hole here, so the 167 * screen doesn't have data for that space anyway (it got cut 168 * first). So pretend it isn't there. 169 */ 170 if s.text != nil { 171 n := s.nrunes - (p0 - p) 172 if n > p1-p0 { /* all in this section */ 173 n = p1 - p0 174 } 175 copy(raspbuf[nb:nb+n], s.text[p0-p:]) 176 nb += n 177 } 178 p += s.nrunes 179 p0 = p 180 s = s.next 181 } 182 return raspbuf[:nb] 183 } 184 185 func rmissing(r *Rasp, p0 int, p1 int) int { 186 p := 0 187 s := r.sect 188 for ; s != nil && p+s.nrunes <= p0; s = s.next { 189 p += s.nrunes 190 } 191 nm := 0 192 for p < p1 && s != nil { 193 if s.text == nil { 194 n := s.nrunes - (p0 - p) 195 if n > p1-p0 { /* all in this section */ 196 n = p1 - p0 197 } 198 nm += n 199 } 200 p += s.nrunes 201 p0 = p 202 s = s.next 203 } 204 return nm 205 } 206 207 func rcontig(r *Rasp, p0 int, p1 int, text bool) int { 208 p := 0 209 s := r.sect 210 for ; s != nil && p+s.nrunes <= p0; s = s.next { 211 p += s.nrunes 212 } 213 np := 0 214 for p < p1 && s != nil && text == (s.text != nil) { 215 n := s.nrunes - (p0 - p) 216 if n > p1-p0 { /* all in this section */ 217 n = p1 - p0 218 } 219 np += n 220 p += s.nrunes 221 p0 = p 222 s = s.next 223 } 224 return np 225 }