15 * Structure of Undo list:
16 * The Undo structure follows any associated data, so the list
17 * can be read backwards: read the structure, then read whatever
18 * data is associated (insert string, file name) and precedes it.
19 * The structure includes the previous value of the modify bit
20 * and a sequence number; successive Undo structures with the
21 * same sequence number represent simultaneous changes.
24 typedef struct Undo Undo;
27 short type; /* Delete, Insert, Filename */
28 short mod; /* modify bit */
29 uint seq; /* sequence number */
30 uint p0; /* location of change (unused in f) */
31 uint n; /* # runes in string or file name */
36 Undosize = sizeof(Undo)/sizeof(Rune)
40 fileaddtext(File *f, Text *t)
43 f = emalloc(sizeof(File));
46 f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
47 f->text[f->ntext++] = t;
53 filedeltext(File *f, Text *t)
57 for(i=0; i<f->ntext; i++)
60 error("can't find text in filedeltext");
68 memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
70 f->curtext = f->text[0];
74 fileinsert(File *f, uint p0, Rune *s, uint ns)
77 error("internal error: fileinsert");
79 fileuninsert(f, &f->delta, p0, ns);
80 bufinsert(&f->b, p0, s, ns);
86 fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
90 /* undo an insertion by deleting */
96 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
100 filedelete(File *f, uint p0, uint p1)
102 if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc))
103 error("internal error: filedelete");
105 fileundelete(f, &f->delta, p0, p1);
106 bufdelete(&f->b, p0, p1);
112 fileundelete(File *f, Buffer *delta, uint p0, uint p1)
118 /* undo a deletion by inserting */
125 for(i=p0; i<p1; i+=n){
129 bufread(&f->b, i, buf, n);
130 bufinsert(delta, delta->nc, buf, n);
133 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
138 filesetname(File *f, Rune *name, int n)
141 fileunsetname(f, &f->delta);
143 f->name = runemalloc(n);
144 runemove(f->name, name, n);
150 fileunsetname(File *f, Buffer *delta)
154 /* undo a file name change by restoring old name */
158 u.p0 = 0; /* unused */
161 bufinsert(delta, delta->nc, f->name, f->nname);
162 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
166 fileload(File *f, uint p0, int fd, int *nulls)
169 error("undo in file.load unimplemented");
170 return bufload(&f->b, p0, fd, nulls);
173 /* return sequence number of pending redo */
183 bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize);
188 fileundo(File *f, int isundo, uint *q0p, uint *q1p)
194 Buffer *delta, *epsilon;
197 /* undo; reverse delta onto epsilon, seq decreases */
199 epsilon = &f->epsilon;
202 /* redo; reverse epsilon onto delta, seq increases */
205 stop = 0; /* don't know yet */
209 while(delta->nc > 0){
210 up = delta->nc-Undosize;
211 bufread(delta, up, (Rune*)&u, Undosize);
225 fprint(2, "undo: 0x%ux\n", u.type);
231 fileundelete(f, epsilon, u.p0, u.p0+u.n);
233 bufdelete(&f->b, u.p0, u.p0+u.n);
234 for(j=0; j<f->ntext; j++)
235 textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
242 fileuninsert(f, epsilon, u.p0, u.n);
245 for(i=0; i<u.n; i+=n){
249 bufread(delta, up+i, buf, n);
250 bufinsert(&f->b, u.p0+i, buf, n);
251 for(j=0; j<f->ntext; j++)
252 textinsert(f->text[j], u.p0+i, buf, n, FALSE);
260 fileunsetname(f, epsilon);
267 f->name = runemalloc(u.n);
268 bufread(delta, up, f->name, u.n);
272 bufdelete(delta, up, delta->nc);
284 bufreset(&f->epsilon);
299 bufclose(&f->epsilon);
308 bufdelete(&f->epsilon, 0, f->epsilon.nc);