9fans.net/go@v0.0.7/cmd/acme/internal/file/file.go (about) 1 // #include <u.h> 2 // #include <libc.h> 3 // #include <draw.h> 4 // #include <thread.h> 5 // #include <cursor.h> 6 // #include <mouse.h> 7 // #include <keyboard.h> 8 // #include <frame.h> 9 // #include <fcall.h> 10 // #include <plumb.h> 11 // #include <libsec.h> 12 // #include "dat.h" 13 // #include "fns.h" 14 15 /* 16 * Structure of Undo list: 17 * The Undo structure follows any associated data, so the list 18 * can be read backwards: read the structure, then read whatever 19 * data is associated (insert string, file name) and precedes it. 20 * The structure includes the previous value of the modify bit 21 * and a sequence number; successive Undo structures with the 22 * same sequence number represent simultaneous changes. 23 */ 24 25 package file 26 27 import ( 28 "fmt" 29 "os" 30 "reflect" 31 "unsafe" 32 33 "9fans.net/go/cmd/acme/internal/bufs" 34 "9fans.net/go/cmd/acme/internal/disk" 35 "9fans.net/go/cmd/acme/internal/runes" 36 "9fans.net/go/cmd/acme/internal/util" 37 ) 38 39 type File struct { 40 view View 41 b disk.Buffer 42 delta disk.Buffer 43 epsilon disk.Buffer 44 name []rune 45 seq int 46 mod bool 47 } 48 49 func (f *File) SetView(v View) { f.view = v } 50 51 type View interface { 52 Insert(int, []rune) 53 Delete(int, int) 54 } 55 56 const ( 57 typeEmpty = 0 58 typeNull = '-' 59 typeDelete = 'd' 60 typeInsert = 'i' 61 typeReplace = 'r' 62 typeFilename = 'f' 63 ) 64 65 type undo struct { 66 typ int 67 mod bool 68 seq int 69 p0 int 70 n int 71 } 72 73 const undoSize = int(unsafe.Sizeof(undo{})) / runes.RuneSize 74 75 func undorunes(u *undo) []rune { 76 var r []rune 77 h := (*reflect.SliceHeader)(unsafe.Pointer(&r)) 78 h.Data = uintptr(unsafe.Pointer(u)) 79 h.Len = undoSize 80 h.Cap = undoSize 81 return r 82 } 83 84 func (f *File) Len() int { return f.b.Len() } 85 86 func (f *File) CanUndo() bool { return f.delta.Len() > 0 } 87 88 func (f *File) CanRedo() bool { return f.epsilon.Len() > 0 } 89 90 func (f *File) Mod() bool { return f.mod } 91 92 func (f *File) SetMod(b bool) { f.mod = b } 93 94 var Seq int 95 96 func (f *File) Seq() int { return f.seq } 97 98 func (f *File) SetSeq(seq int) { f.seq = seq } 99 100 func (f *File) Mark() { 101 if f.epsilon.Len() != 0 { 102 f.epsilon.Delete(0, f.epsilon.Len()) 103 } 104 f.seq = Seq 105 } 106 107 func (f *File) Read(pos int, data []rune) { f.b.Read(pos, data) } 108 109 func (f *File) Insert(p0 int, s []rune) { 110 if p0 > f.b.Len() { 111 util.Fatal("internal error: fileinsert") 112 } 113 if f.seq > 0 { 114 f.uninsert(&f.delta, p0, len(s)) 115 } 116 f.b.Insert(p0, s) 117 if len(s) != 0 { 118 f.mod = true 119 } 120 } 121 122 func (f *File) uninsert(delta *disk.Buffer, p0, ns int) { 123 var u undo 124 /* undo an insertion by deleting */ 125 u.typ = typeDelete 126 u.mod = f.mod 127 u.seq = f.seq 128 u.p0 = p0 129 u.n = ns 130 delta.Insert(delta.Len(), undorunes(&u)) 131 } 132 133 func (f *File) Delete(p0, p1 int) { 134 if !(p0 <= p1 && p0 <= f.b.Len()) || !(p1 <= f.b.Len()) { 135 util.Fatal("internal error: filedelete") 136 } 137 if f.seq > 0 { 138 f.undelete(&f.delta, p0, p1) 139 } 140 f.b.Delete(p0, p1) 141 if p1 > p0 { 142 f.mod = true 143 } 144 } 145 146 func (f *File) undelete(delta *disk.Buffer, p0, p1 int) { 147 var u undo 148 /* undo a deletion by inserting */ 149 u.typ = typeInsert 150 u.mod = f.mod 151 u.seq = f.seq 152 u.p0 = p0 153 u.n = p1 - p0 154 buf := bufs.AllocRunes() 155 var n int 156 for i := p0; i < p1; i += n { 157 n = p1 - i 158 if n > bufs.RuneLen { 159 n = bufs.RuneLen 160 } 161 f.b.Read(i, buf[:n]) 162 delta.Insert(delta.Len(), buf[:n]) 163 } 164 bufs.FreeRunes(buf) 165 delta.Insert(delta.Len(), undorunes(&u)) 166 } 167 168 func (f *File) Name() []rune { return f.name } 169 170 func (f *File) SetName(name []rune) { 171 if f.seq > 0 { 172 f.unsetname(&f.delta) 173 } 174 f.name = runes.Clone(name) 175 } 176 177 func (f *File) unsetname(delta *disk.Buffer) { 178 var u undo 179 /* undo a file name change by restoring old name */ 180 u.typ = typeFilename 181 u.mod = f.mod 182 u.seq = f.seq 183 u.p0 = 0 /* unused */ 184 u.n = len(f.name) 185 if len(f.name) != 0 { 186 delta.Insert(delta.Len(), f.name) 187 } 188 delta.Insert(delta.Len(), undorunes(&u)) 189 } 190 191 /* return sequence number of pending redo */ 192 func (f *File) RedoSeq() int { 193 delta := &f.epsilon 194 if delta.Len() == 0 { 195 return 0 196 } 197 var u undo 198 delta.Read(delta.Len()-undoSize, undorunes(&u)) 199 return u.seq 200 } 201 202 func (f *File) Undo(isundo bool, q0p, q1p *int) { 203 var stop int 204 var delta *disk.Buffer 205 var epsilon *disk.Buffer 206 if isundo { 207 /* undo; reverse delta onto epsilon, seq decreases */ 208 delta = &f.delta 209 epsilon = &f.epsilon 210 stop = f.seq 211 } else { 212 /* redo; reverse epsilon onto delta, seq increases */ 213 delta = &f.epsilon 214 epsilon = &f.delta 215 stop = 0 /* don't know yet */ 216 } 217 218 buf := bufs.AllocRunes() 219 for delta.Len() > 0 { 220 up := delta.Len() - undoSize 221 var u undo 222 delta.Read(up, undorunes(&u)) 223 if isundo { 224 if u.seq < stop { 225 f.seq = u.seq 226 goto Return 227 } 228 } else { 229 if stop == 0 { 230 stop = u.seq 231 } 232 if u.seq > stop { 233 goto Return 234 } 235 } 236 var n int 237 var i int 238 switch u.typ { 239 default: 240 fmt.Fprintf(os.Stderr, "undo: %#x\n", u.typ) 241 panic("undo") 242 243 case typeDelete: 244 f.seq = u.seq 245 f.undelete(epsilon, u.p0, u.p0+u.n) 246 f.mod = u.mod 247 f.b.Delete(u.p0, u.p0+u.n) 248 f.view.Delete(u.p0, u.p0+u.n) 249 *q0p = u.p0 250 *q1p = u.p0 251 252 case typeInsert: 253 f.seq = u.seq 254 f.uninsert(epsilon, u.p0, u.n) 255 f.mod = u.mod 256 up -= u.n 257 for i = 0; i < u.n; i += n { 258 n = u.n - i 259 if n > bufs.RuneLen { 260 n = bufs.RuneLen 261 } 262 delta.Read(up+i, buf[:n]) 263 f.b.Insert(u.p0+i, buf[:n]) 264 f.view.Insert(u.p0+i, buf[:n]) 265 } 266 *q0p = u.p0 267 *q1p = u.p0 + u.n 268 269 case typeFilename: 270 f.seq = u.seq 271 f.unsetname(epsilon) 272 f.mod = u.mod 273 up -= u.n 274 if u.n == 0 { 275 f.name = nil 276 } else { 277 f.name = make([]rune, u.n) 278 } 279 delta.Read(up, f.name) 280 } 281 delta.Delete(up, delta.Len()) 282 } 283 if isundo { 284 f.seq = 0 285 } 286 Return: 287 bufs.FreeRunes(buf) 288 } 289 290 func (f *File) ResetLogs() { 291 f.delta.Reset() 292 f.epsilon.Reset() 293 f.seq = 0 294 } 295 296 func (f *File) Truncate() { f.b.Reset() } 297 298 func (f *File) Close() { 299 f.name = nil 300 f.view = nil 301 f.b.Close() 302 f.delta.Close() 303 f.epsilon.Close() 304 }