1 b3994ec5 2003-12-11 devnull #include <u.h>
2 b3994ec5 2003-12-11 devnull #include <libc.h>
3 b3994ec5 2003-12-11 devnull #include <draw.h>
4 b3994ec5 2003-12-11 devnull #include <thread.h>
5 b3994ec5 2003-12-11 devnull #include <cursor.h>
6 b3994ec5 2003-12-11 devnull #include <mouse.h>
7 b3994ec5 2003-12-11 devnull #include <keyboard.h>
8 b3994ec5 2003-12-11 devnull #include <frame.h>
9 b3994ec5 2003-12-11 devnull #include <fcall.h>
10 b3994ec5 2003-12-11 devnull #include <plumb.h>
11 b3994ec5 2003-12-11 devnull #include "dat.h"
12 b3994ec5 2003-12-11 devnull #include "fns.h"
15 b3994ec5 2003-12-11 devnull * Structure of Undo list:
16 b3994ec5 2003-12-11 devnull * The Undo structure follows any associated data, so the list
17 b3994ec5 2003-12-11 devnull * can be read backwards: read the structure, then read whatever
18 b3994ec5 2003-12-11 devnull * data is associated (insert string, file name) and precedes it.
19 b3994ec5 2003-12-11 devnull * The structure includes the previous value of the modify bit
20 b3994ec5 2003-12-11 devnull * and a sequence number; successive Undo structures with the
21 b3994ec5 2003-12-11 devnull * same sequence number represent simultaneous changes.
24 b3994ec5 2003-12-11 devnull typedef struct Undo Undo;
25 b3994ec5 2003-12-11 devnull struct Undo
27 b3994ec5 2003-12-11 devnull short type; /* Delete, Insert, Filename */
28 b3994ec5 2003-12-11 devnull short mod; /* modify bit */
29 b3994ec5 2003-12-11 devnull uint seq; /* sequence number */
30 b3994ec5 2003-12-11 devnull uint p0; /* location of change (unused in f) */
31 b3994ec5 2003-12-11 devnull uint n; /* # runes in string or file name */
36 cbeb0b26 2006-04-01 devnull Undosize = sizeof(Undo)/sizeof(Rune)
40 b3994ec5 2003-12-11 devnull fileaddtext(File *f, Text *t)
42 b3994ec5 2003-12-11 devnull if(f == nil){
43 b3994ec5 2003-12-11 devnull f = emalloc(sizeof(File));
44 b3994ec5 2003-12-11 devnull f->unread = TRUE;
46 b3994ec5 2003-12-11 devnull f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
47 b3994ec5 2003-12-11 devnull f->text[f->ntext++] = t;
48 b3994ec5 2003-12-11 devnull f->curtext = t;
49 b3994ec5 2003-12-11 devnull return f;
53 b3994ec5 2003-12-11 devnull filedeltext(File *f, Text *t)
57 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++)
58 b3994ec5 2003-12-11 devnull if(f->text[i] == t)
59 b3994ec5 2003-12-11 devnull goto Found;
60 b3994ec5 2003-12-11 devnull error("can't find text in filedeltext");
63 b3994ec5 2003-12-11 devnull f->ntext--;
64 b3994ec5 2003-12-11 devnull if(f->ntext == 0){
65 b3994ec5 2003-12-11 devnull fileclose(f);
68 b3994ec5 2003-12-11 devnull memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
69 b3994ec5 2003-12-11 devnull if(f->curtext == t)
70 b3994ec5 2003-12-11 devnull f->curtext = f->text[0];
74 b3994ec5 2003-12-11 devnull fileinsert(File *f, uint p0, Rune *s, uint ns)
76 b3994ec5 2003-12-11 devnull if(p0 > f->b.nc)
77 b3994ec5 2003-12-11 devnull error("internal error: fileinsert");
78 b3994ec5 2003-12-11 devnull if(f->seq > 0)
79 b3994ec5 2003-12-11 devnull fileuninsert(f, &f->delta, p0, ns);
80 b3994ec5 2003-12-11 devnull bufinsert(&f->b, p0, s, ns);
82 b3994ec5 2003-12-11 devnull f->mod = TRUE;
86 b3994ec5 2003-12-11 devnull fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
90 b3994ec5 2003-12-11 devnull /* undo an insertion by deleting */
91 b3994ec5 2003-12-11 devnull u.type = Delete;
92 b3994ec5 2003-12-11 devnull u.mod = f->mod;
93 b3994ec5 2003-12-11 devnull u.seq = f->seq;
94 b3994ec5 2003-12-11 devnull u.p0 = p0;
95 b3994ec5 2003-12-11 devnull u.n = ns;
96 b3994ec5 2003-12-11 devnull bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
100 b3994ec5 2003-12-11 devnull filedelete(File *f, uint p0, uint p1)
102 b3994ec5 2003-12-11 devnull if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc))
103 b3994ec5 2003-12-11 devnull error("internal error: filedelete");
104 b3994ec5 2003-12-11 devnull if(f->seq > 0)
105 b3994ec5 2003-12-11 devnull fileundelete(f, &f->delta, p0, p1);
106 b3994ec5 2003-12-11 devnull bufdelete(&f->b, p0, p1);
107 b3994ec5 2003-12-11 devnull if(p1 > p0)
108 b3994ec5 2003-12-11 devnull f->mod = TRUE;
112 b3994ec5 2003-12-11 devnull fileundelete(File *f, Buffer *delta, uint p0, uint p1)
115 b3994ec5 2003-12-11 devnull Rune *buf;
116 b3994ec5 2003-12-11 devnull uint i, n;
118 b3994ec5 2003-12-11 devnull /* undo a deletion by inserting */
119 b3994ec5 2003-12-11 devnull u.type = Insert;
120 b3994ec5 2003-12-11 devnull u.mod = f->mod;
121 b3994ec5 2003-12-11 devnull u.seq = f->seq;
122 b3994ec5 2003-12-11 devnull u.p0 = p0;
123 b3994ec5 2003-12-11 devnull u.n = p1-p0;
124 b3994ec5 2003-12-11 devnull buf = fbufalloc();
125 b3994ec5 2003-12-11 devnull for(i=p0; i<p1; i+=n){
126 b3994ec5 2003-12-11 devnull n = p1 - i;
127 b3994ec5 2003-12-11 devnull if(n > RBUFSIZE)
128 b3994ec5 2003-12-11 devnull n = RBUFSIZE;
129 b3994ec5 2003-12-11 devnull bufread(&f->b, i, buf, n);
130 b3994ec5 2003-12-11 devnull bufinsert(delta, delta->nc, buf, n);
132 b3994ec5 2003-12-11 devnull fbuffree(buf);
133 b3994ec5 2003-12-11 devnull bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
138 b3994ec5 2003-12-11 devnull filesetname(File *f, Rune *name, int n)
140 b3994ec5 2003-12-11 devnull if(f->seq > 0)
141 b3994ec5 2003-12-11 devnull fileunsetname(f, &f->delta);
142 b3994ec5 2003-12-11 devnull free(f->name);
143 b3994ec5 2003-12-11 devnull f->name = runemalloc(n);
144 b3994ec5 2003-12-11 devnull runemove(f->name, name, n);
145 b3994ec5 2003-12-11 devnull f->nname = n;
146 b3994ec5 2003-12-11 devnull f->unread = TRUE;
150 b3994ec5 2003-12-11 devnull fileunsetname(File *f, Buffer *delta)
154 b3994ec5 2003-12-11 devnull /* undo a file name change by restoring old name */
155 b3994ec5 2003-12-11 devnull u.type = Filename;
156 b3994ec5 2003-12-11 devnull u.mod = f->mod;
157 b3994ec5 2003-12-11 devnull u.seq = f->seq;
158 b3994ec5 2003-12-11 devnull u.p0 = 0; /* unused */
159 b3994ec5 2003-12-11 devnull u.n = f->nname;
160 b3994ec5 2003-12-11 devnull if(f->nname)
161 b3994ec5 2003-12-11 devnull bufinsert(delta, delta->nc, f->name, f->nname);
162 b3994ec5 2003-12-11 devnull bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
166 b3994ec5 2003-12-11 devnull fileload(File *f, uint p0, int fd, int *nulls)
168 b3994ec5 2003-12-11 devnull if(f->seq > 0)
169 b3994ec5 2003-12-11 devnull error("undo in file.load unimplemented");
170 b3994ec5 2003-12-11 devnull return bufload(&f->b, p0, fd, nulls);
173 b3994ec5 2003-12-11 devnull /* return sequence number of pending redo */
175 b3994ec5 2003-12-11 devnull fileredoseq(File *f)
178 b3994ec5 2003-12-11 devnull Buffer *delta;
180 b3994ec5 2003-12-11 devnull delta = &f->epsilon;
181 b3994ec5 2003-12-11 devnull if(delta->nc == 0)
182 b3994ec5 2003-12-11 devnull return 0;
183 b3994ec5 2003-12-11 devnull bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize);
184 b3994ec5 2003-12-11 devnull return u.seq;
188 b3994ec5 2003-12-11 devnull fileundo(File *f, int isundo, uint *q0p, uint *q1p)
191 b3994ec5 2003-12-11 devnull Rune *buf;
192 b3994ec5 2003-12-11 devnull uint i, j, n, up;
193 b3994ec5 2003-12-11 devnull uint stop;
194 b3994ec5 2003-12-11 devnull Buffer *delta, *epsilon;
196 b3994ec5 2003-12-11 devnull if(isundo){
197 b3994ec5 2003-12-11 devnull /* undo; reverse delta onto epsilon, seq decreases */
198 b3994ec5 2003-12-11 devnull delta = &f->delta;
199 b3994ec5 2003-12-11 devnull epsilon = &f->epsilon;
200 b3994ec5 2003-12-11 devnull stop = f->seq;
202 b3994ec5 2003-12-11 devnull /* redo; reverse epsilon onto delta, seq increases */
203 b3994ec5 2003-12-11 devnull delta = &f->epsilon;
204 b3994ec5 2003-12-11 devnull epsilon = &f->delta;
205 b3994ec5 2003-12-11 devnull stop = 0; /* don't know yet */
208 b3994ec5 2003-12-11 devnull buf = fbufalloc();
209 b3994ec5 2003-12-11 devnull while(delta->nc > 0){
210 b3994ec5 2003-12-11 devnull up = delta->nc-Undosize;
211 b3994ec5 2003-12-11 devnull bufread(delta, up, (Rune*)&u, Undosize);
212 b3994ec5 2003-12-11 devnull if(isundo){
213 b3994ec5 2003-12-11 devnull if(u.seq < stop){
214 b3994ec5 2003-12-11 devnull f->seq = u.seq;
215 b3994ec5 2003-12-11 devnull goto Return;
218 b3994ec5 2003-12-11 devnull if(stop == 0)
219 b3994ec5 2003-12-11 devnull stop = u.seq;
220 b3994ec5 2003-12-11 devnull if(u.seq > stop)
221 b3994ec5 2003-12-11 devnull goto Return;
223 b3994ec5 2003-12-11 devnull switch(u.type){
224 b3994ec5 2003-12-11 devnull default:
225 b3994ec5 2003-12-11 devnull fprint(2, "undo: 0x%ux\n", u.type);
226 b3994ec5 2003-12-11 devnull abort();
229 b3994ec5 2003-12-11 devnull case Delete:
230 b3994ec5 2003-12-11 devnull f->seq = u.seq;
231 b3994ec5 2003-12-11 devnull fileundelete(f, epsilon, u.p0, u.p0+u.n);
232 b3994ec5 2003-12-11 devnull f->mod = u.mod;
233 b3994ec5 2003-12-11 devnull bufdelete(&f->b, u.p0, u.p0+u.n);
234 b3994ec5 2003-12-11 devnull for(j=0; j<f->ntext; j++)
235 b3994ec5 2003-12-11 devnull textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
236 b3994ec5 2003-12-11 devnull *q0p = u.p0;
237 b3994ec5 2003-12-11 devnull *q1p = u.p0;
240 b3994ec5 2003-12-11 devnull case Insert:
241 b3994ec5 2003-12-11 devnull f->seq = u.seq;
242 b3994ec5 2003-12-11 devnull fileuninsert(f, epsilon, u.p0, u.n);
243 b3994ec5 2003-12-11 devnull f->mod = u.mod;
244 b3994ec5 2003-12-11 devnull up -= u.n;
245 b3994ec5 2003-12-11 devnull for(i=0; i<u.n; i+=n){
246 b3994ec5 2003-12-11 devnull n = u.n - i;
247 b3994ec5 2003-12-11 devnull if(n > RBUFSIZE)
248 b3994ec5 2003-12-11 devnull n = RBUFSIZE;
249 b3994ec5 2003-12-11 devnull bufread(delta, up+i, buf, n);
250 b3994ec5 2003-12-11 devnull bufinsert(&f->b, u.p0+i, buf, n);
251 b3994ec5 2003-12-11 devnull for(j=0; j<f->ntext; j++)
252 b3994ec5 2003-12-11 devnull textinsert(f->text[j], u.p0+i, buf, n, FALSE);
254 b3994ec5 2003-12-11 devnull *q0p = u.p0;
255 b3994ec5 2003-12-11 devnull *q1p = u.p0+u.n;
258 b3994ec5 2003-12-11 devnull case Filename:
259 b3994ec5 2003-12-11 devnull f->seq = u.seq;
260 b3994ec5 2003-12-11 devnull fileunsetname(f, epsilon);
261 b3994ec5 2003-12-11 devnull f->mod = u.mod;
262 b3994ec5 2003-12-11 devnull up -= u.n;
263 b3994ec5 2003-12-11 devnull free(f->name);
264 b3994ec5 2003-12-11 devnull if(u.n == 0)
265 b3994ec5 2003-12-11 devnull f->name = nil;
267 b3994ec5 2003-12-11 devnull f->name = runemalloc(u.n);
268 b3994ec5 2003-12-11 devnull bufread(delta, up, f->name, u.n);
269 b3994ec5 2003-12-11 devnull f->nname = u.n;
272 b3994ec5 2003-12-11 devnull bufdelete(delta, up, delta->nc);
274 b3994ec5 2003-12-11 devnull if(isundo)
275 b3994ec5 2003-12-11 devnull f->seq = 0;
277 b3994ec5 2003-12-11 devnull fbuffree(buf);
281 b3994ec5 2003-12-11 devnull filereset(File *f)
283 b3994ec5 2003-12-11 devnull bufreset(&f->delta);
284 b3994ec5 2003-12-11 devnull bufreset(&f->epsilon);
285 b3994ec5 2003-12-11 devnull f->seq = 0;
289 b3994ec5 2003-12-11 devnull fileclose(File *f)
291 b3994ec5 2003-12-11 devnull free(f->name);
292 b3994ec5 2003-12-11 devnull f->nname = 0;
293 b3994ec5 2003-12-11 devnull f->name = nil;
294 b3994ec5 2003-12-11 devnull free(f->text);
295 b3994ec5 2003-12-11 devnull f->ntext = 0;
296 b3994ec5 2003-12-11 devnull f->text = nil;
297 b3994ec5 2003-12-11 devnull bufclose(&f->b);
298 b3994ec5 2003-12-11 devnull bufclose(&f->delta);
299 b3994ec5 2003-12-11 devnull bufclose(&f->epsilon);
300 b3994ec5 2003-12-11 devnull elogclose(f);
301 b3994ec5 2003-12-11 devnull free(f);
305 b3994ec5 2003-12-11 devnull filemark(File *f)
307 b3994ec5 2003-12-11 devnull if(f->epsilon.nc)
308 b3994ec5 2003-12-11 devnull bufdelete(&f->epsilon, 0, f->epsilon.nc);
309 b3994ec5 2003-12-11 devnull f->seq = seq;