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.
25 typedef struct Undo Undo;
28 short type; /* Delete, Insert, Filename */
29 short mod; /* modify bit */
30 uint seq; /* sequence number */
31 uint p0; /* location of change (unused in f) */
32 uint n; /* # runes in string or file name */
37 Undosize = sizeof(Undo)/sizeof(Rune)
41 fileaddtext(File *f, Text *t)
44 f = emalloc(sizeof(File));
47 f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
48 f->text[f->ntext++] = t;
54 filedeltext(File *f, Text *t)
58 for(i=0; i<f->ntext; i++)
61 error("can't find text in filedeltext");
69 memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
71 f->curtext = f->text[0];
75 fileinsert(File *f, uint p0, Rune *s, uint ns)
78 error("internal error: fileinsert");
80 fileuninsert(f, &f->delta, p0, ns);
81 bufinsert(&f->b, p0, s, ns);
87 fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
91 /* undo an insertion by deleting */
97 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
101 filedelete(File *f, uint p0, uint p1)
103 if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc))
104 error("internal error: filedelete");
106 fileundelete(f, &f->delta, p0, p1);
107 bufdelete(&f->b, p0, p1);
113 fileundelete(File *f, Buffer *delta, uint p0, uint p1)
119 /* undo a deletion by inserting */
126 for(i=p0; i<p1; i+=n){
130 bufread(&f->b, i, buf, n);
131 bufinsert(delta, delta->nc, buf, n);
134 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
139 filesetname(File *f, Rune *name, int n)
142 fileunsetname(f, &f->delta);
144 f->name = runemalloc(n);
145 runemove(f->name, name, n);
151 fileunsetname(File *f, Buffer *delta)
155 /* undo a file name change by restoring old name */
159 u.p0 = 0; /* unused */
162 bufinsert(delta, delta->nc, f->name, f->nname);
163 bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
167 fileload(File *f, uint p0, int fd, int *nulls, DigestState *h)
170 error("undo in file.load unimplemented");
171 return bufload(&f->b, p0, fd, nulls, h);
174 /* return sequence number of pending redo */
184 bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize);
189 fileundo(File *f, int isundo, uint *q0p, uint *q1p)
195 Buffer *delta, *epsilon;
198 /* undo; reverse delta onto epsilon, seq decreases */
200 epsilon = &f->epsilon;
203 /* redo; reverse epsilon onto delta, seq increases */
206 stop = 0; /* don't know yet */
210 while(delta->nc > 0){
211 up = delta->nc-Undosize;
212 bufread(delta, up, (Rune*)&u, Undosize);
226 fprint(2, "undo: 0x%ux\n", u.type);
232 fileundelete(f, epsilon, u.p0, u.p0+u.n);
234 bufdelete(&f->b, u.p0, u.p0+u.n);
235 for(j=0; j<f->ntext; j++)
236 textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
243 fileuninsert(f, epsilon, u.p0, u.n);
246 for(i=0; i<u.n; i+=n){
250 bufread(delta, up+i, buf, n);
251 bufinsert(&f->b, u.p0+i, buf, n);
252 for(j=0; j<f->ntext; j++)
253 textinsert(f->text[j], u.p0+i, buf, n, FALSE);
261 fileunsetname(f, epsilon);
268 f->name = runemalloc(u.n);
269 bufread(delta, up, f->name, u.n);
273 bufdelete(delta, up, delta->nc);
285 bufreset(&f->epsilon);
300 bufclose(&f->epsilon);
309 bufdelete(&f->epsilon, 0, f->epsilon.nc);