13e12c5d1SDavid du Colombier #include "sam.h"
27dd7cddfSDavid du Colombier
33e12c5d1SDavid du Colombier /*
47dd7cddfSDavid du Colombier * Structure of Undo list:
57dd7cddfSDavid du Colombier * The Undo structure follows any associated data, so the list
67dd7cddfSDavid du Colombier * can be read backwards: read the structure, then read whatever
77dd7cddfSDavid du Colombier * data is associated (insert string, file name) and precedes it.
87dd7cddfSDavid du Colombier * The structure includes the previous value of the modify bit
97dd7cddfSDavid du Colombier * and a sequence number; successive Undo structures with the
107dd7cddfSDavid du Colombier * same sequence number represent simultaneous changes.
113e12c5d1SDavid du Colombier */
123e12c5d1SDavid du Colombier
137dd7cddfSDavid du Colombier typedef struct Undo Undo;
147dd7cddfSDavid du Colombier typedef struct Merge Merge;
153e12c5d1SDavid du Colombier
167dd7cddfSDavid du Colombier struct Undo
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier short type; /* Delete, Insert, Filename, Dot, Mark */
197dd7cddfSDavid du Colombier short mod; /* modify bit */
207dd7cddfSDavid du Colombier uint seq; /* sequence number */
217dd7cddfSDavid du Colombier uint p0; /* location of change (unused in f) */
227dd7cddfSDavid du Colombier uint n; /* # runes in string or file name */
233e12c5d1SDavid du Colombier };
243e12c5d1SDavid du Colombier
257dd7cddfSDavid du Colombier struct Merge
263e12c5d1SDavid du Colombier {
277dd7cddfSDavid du Colombier File *f;
287dd7cddfSDavid du Colombier uint seq; /* of logged change */
297dd7cddfSDavid du Colombier uint p0; /* location of change (unused in f) */
307dd7cddfSDavid du Colombier uint n; /* # runes to delete */
317dd7cddfSDavid du Colombier uint nbuf; /* # runes to insert */
327dd7cddfSDavid du Colombier Rune buf[RBUFSIZE];
337dd7cddfSDavid du Colombier };
343e12c5d1SDavid du Colombier
357dd7cddfSDavid du Colombier enum
363e12c5d1SDavid du Colombier {
377dd7cddfSDavid du Colombier Maxmerge = 50,
387dd7cddfSDavid du Colombier Undosize = sizeof(Undo)/sizeof(Rune),
397dd7cddfSDavid du Colombier };
403e12c5d1SDavid du Colombier
417dd7cddfSDavid du Colombier static Merge merge;
423e12c5d1SDavid du Colombier
433e12c5d1SDavid du Colombier File*
fileopen(void)447dd7cddfSDavid du Colombier fileopen(void)
453e12c5d1SDavid du Colombier {
463e12c5d1SDavid du Colombier File *f;
473e12c5d1SDavid du Colombier
483e12c5d1SDavid du Colombier f = emalloc(sizeof(File));
493e12c5d1SDavid du Colombier f->dot.f = f;
503e12c5d1SDavid du Colombier f->ndot.f = f;
517dd7cddfSDavid du Colombier f->seq = 0;
527dd7cddfSDavid du Colombier f->mod = FALSE;
537dd7cddfSDavid du Colombier f->unread = TRUE;
543e12c5d1SDavid du Colombier Strinit0(&f->name);
557dd7cddfSDavid du Colombier return f;
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier int
fileisdirty(File * f)597dd7cddfSDavid du Colombier fileisdirty(File *f)
607dd7cddfSDavid du Colombier {
617dd7cddfSDavid du Colombier return f->seq != f->cleanseq;
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier static void
wrinsert(Buffer * delta,int seq,int mod,uint p0,Rune * s,uint ns)657dd7cddfSDavid du Colombier wrinsert(Buffer *delta, int seq, int mod, uint p0, Rune *s, uint ns)
667dd7cddfSDavid du Colombier {
677dd7cddfSDavid du Colombier Undo u;
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier u.type = Insert;
707dd7cddfSDavid du Colombier u.mod = mod;
717dd7cddfSDavid du Colombier u.seq = seq;
727dd7cddfSDavid du Colombier u.p0 = p0;
737dd7cddfSDavid du Colombier u.n = ns;
747dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, s, ns);
757dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
767dd7cddfSDavid du Colombier }
777dd7cddfSDavid du Colombier
787dd7cddfSDavid du Colombier static void
wrdelete(Buffer * delta,int seq,int mod,uint p0,uint p1)797dd7cddfSDavid du Colombier wrdelete(Buffer *delta, int seq, int mod, uint p0, uint p1)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier Undo u;
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier u.type = Delete;
847dd7cddfSDavid du Colombier u.mod = mod;
857dd7cddfSDavid du Colombier u.seq = seq;
867dd7cddfSDavid du Colombier u.p0 = p0;
877dd7cddfSDavid du Colombier u.n = p1 - p0;
887dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier void
flushmerge(void)927dd7cddfSDavid du Colombier flushmerge(void)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier File *f;
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier f = merge.f;
977dd7cddfSDavid du Colombier if(f == nil)
987dd7cddfSDavid du Colombier return;
997dd7cddfSDavid du Colombier if(merge.seq != f->seq)
1007dd7cddfSDavid du Colombier panic("flushmerge seq mismatch");
1017dd7cddfSDavid du Colombier if(merge.n != 0)
1027dd7cddfSDavid du Colombier wrdelete(&f->epsilon, f->seq, TRUE, merge.p0, merge.p0+merge.n);
1037dd7cddfSDavid du Colombier if(merge.nbuf != 0)
1047dd7cddfSDavid du Colombier wrinsert(&f->epsilon, f->seq, TRUE, merge.p0+merge.n, merge.buf, merge.nbuf);
1057dd7cddfSDavid du Colombier merge.f = nil;
1067dd7cddfSDavid du Colombier merge.n = 0;
1077dd7cddfSDavid du Colombier merge.nbuf = 0;
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier void
mergeextend(File * f,uint p0)1117dd7cddfSDavid du Colombier mergeextend(File *f, uint p0)
1127dd7cddfSDavid du Colombier {
1137dd7cddfSDavid du Colombier uint mp0n;
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier mp0n = merge.p0+merge.n;
1167dd7cddfSDavid du Colombier if(mp0n != p0){
1177dd7cddfSDavid du Colombier bufread(f, mp0n, merge.buf+merge.nbuf, p0-mp0n);
1187dd7cddfSDavid du Colombier merge.nbuf += p0-mp0n;
1197dd7cddfSDavid du Colombier merge.n = p0-merge.p0;
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier /*
1247dd7cddfSDavid du Colombier * like fileundelete, but get the data from arguments
1257dd7cddfSDavid du Colombier */
1267dd7cddfSDavid du Colombier void
loginsert(File * f,uint p0,Rune * s,uint ns)1277dd7cddfSDavid du Colombier loginsert(File *f, uint p0, Rune *s, uint ns)
1287dd7cddfSDavid du Colombier {
1297dd7cddfSDavid du Colombier if(f->rescuing)
1307dd7cddfSDavid du Colombier return;
1317dd7cddfSDavid du Colombier if(ns == 0)
1327dd7cddfSDavid du Colombier return;
133c93608ccSDavid du Colombier if(ns>STRSIZE)
1347dd7cddfSDavid du Colombier panic("loginsert");
1357dd7cddfSDavid du Colombier if(f->seq < seq)
1367dd7cddfSDavid du Colombier filemark(f);
1377dd7cddfSDavid du Colombier if(p0 < f->hiposn)
1387dd7cddfSDavid du Colombier error(Esequence);
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier if(merge.f != f
1417dd7cddfSDavid du Colombier || p0-(merge.p0+merge.n)>Maxmerge /* too far */
142*047f1f95SDavid du Colombier || merge.nbuf+((p0+ns)-(merge.p0+merge.n))>=RBUFSIZE) /* too long */
1437dd7cddfSDavid du Colombier flushmerge();
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier if(ns>=RBUFSIZE){
1467dd7cddfSDavid du Colombier if(!(merge.n == 0 && merge.nbuf == 0 && merge.f == nil))
1477dd7cddfSDavid du Colombier panic("loginsert bad merge state");
1487dd7cddfSDavid du Colombier wrinsert(&f->epsilon, f->seq, TRUE, p0, s, ns);
1497dd7cddfSDavid du Colombier }else{
1507dd7cddfSDavid du Colombier if(merge.f != f){
1517dd7cddfSDavid du Colombier merge.f = f;
1527dd7cddfSDavid du Colombier merge.p0 = p0;
1537dd7cddfSDavid du Colombier merge.seq = f->seq;
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier mergeextend(f, p0);
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier /* append string to merge */
1587dd7cddfSDavid du Colombier runemove(merge.buf+merge.nbuf, s, ns);
1597dd7cddfSDavid du Colombier merge.nbuf += ns;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier f->hiposn = p0;
1637dd7cddfSDavid du Colombier if(!f->unread && !f->mod)
1647dd7cddfSDavid du Colombier state(f, Dirty);
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier void
logdelete(File * f,uint p0,uint p1)1687dd7cddfSDavid du Colombier logdelete(File *f, uint p0, uint p1)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier if(f->rescuing)
1717dd7cddfSDavid du Colombier return;
1727dd7cddfSDavid du Colombier if(p0 == p1)
1737dd7cddfSDavid du Colombier return;
1747dd7cddfSDavid du Colombier if(f->seq < seq)
1757dd7cddfSDavid du Colombier filemark(f);
1766b6b9ac8SDavid du Colombier if(p0 < f->hiposn)
1777dd7cddfSDavid du Colombier error(Esequence);
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier if(merge.f != f
1807dd7cddfSDavid du Colombier || p0-(merge.p0+merge.n)>Maxmerge /* too far */
181*047f1f95SDavid du Colombier || merge.nbuf+(p0-(merge.p0+merge.n))>=RBUFSIZE){ /* too long */
1827dd7cddfSDavid du Colombier flushmerge();
1837dd7cddfSDavid du Colombier merge.f = f;
1847dd7cddfSDavid du Colombier merge.p0 = p0;
1857dd7cddfSDavid du Colombier merge.seq = f->seq;
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier mergeextend(f, p0);
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier /* add to deletion */
1917dd7cddfSDavid du Colombier merge.n = p1-merge.p0;
1927dd7cddfSDavid du Colombier
1937dd7cddfSDavid du Colombier f->hiposn = p1;
1947dd7cddfSDavid du Colombier if(!f->unread && !f->mod)
1957dd7cddfSDavid du Colombier state(f, Dirty);
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier /*
1997dd7cddfSDavid du Colombier * like fileunsetname, but get the data from arguments
2007dd7cddfSDavid du Colombier */
2017dd7cddfSDavid du Colombier void
logsetname(File * f,String * s)2027dd7cddfSDavid du Colombier logsetname(File *f, String *s)
2037dd7cddfSDavid du Colombier {
2047dd7cddfSDavid du Colombier Undo u;
2057dd7cddfSDavid du Colombier Buffer *delta;
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier if(f->rescuing)
2087dd7cddfSDavid du Colombier return;
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier if(f->unread){ /* This is setting initial file name */
2117dd7cddfSDavid du Colombier filesetname(f, s);
2127dd7cddfSDavid du Colombier return;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier if(f->seq < seq)
2167dd7cddfSDavid du Colombier filemark(f);
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier /* undo a file name change by restoring old name */
2197dd7cddfSDavid du Colombier delta = &f->epsilon;
2207dd7cddfSDavid du Colombier u.type = Filename;
2217dd7cddfSDavid du Colombier u.mod = TRUE;
2227dd7cddfSDavid du Colombier u.seq = f->seq;
2237dd7cddfSDavid du Colombier u.p0 = 0; /* unused */
2247dd7cddfSDavid du Colombier u.n = s->n;
2257dd7cddfSDavid du Colombier if(s->n)
2267dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, s->s, s->n);
2277dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
2287dd7cddfSDavid du Colombier if(!f->unread && !f->mod)
2297dd7cddfSDavid du Colombier state(f, Dirty);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier #ifdef NOTEXT
2337dd7cddfSDavid du Colombier File*
fileaddtext(File * f,Text * t)2347dd7cddfSDavid du Colombier fileaddtext(File *f, Text *t)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier if(f == nil){
2377dd7cddfSDavid du Colombier f = emalloc(sizeof(File));
2387dd7cddfSDavid du Colombier f->unread = TRUE;
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
2417dd7cddfSDavid du Colombier f->text[f->ntext++] = t;
2427dd7cddfSDavid du Colombier f->curtext = t;
2433e12c5d1SDavid du Colombier return f;
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier
2463e12c5d1SDavid du Colombier void
filedeltext(File * f,Text * t)2477dd7cddfSDavid du Colombier filedeltext(File *f, Text *t)
2483e12c5d1SDavid du Colombier {
2497dd7cddfSDavid du Colombier int i;
2507dd7cddfSDavid du Colombier
2517dd7cddfSDavid du Colombier for(i=0; i<f->ntext; i++)
2527dd7cddfSDavid du Colombier if(f->text[i] == t)
2537dd7cddfSDavid du Colombier goto Found;
2547dd7cddfSDavid du Colombier panic("can't find text in filedeltext");
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier Found:
2577dd7cddfSDavid du Colombier f->ntext--;
2587dd7cddfSDavid du Colombier if(f->ntext == 0){
2597dd7cddfSDavid du Colombier fileclose(f);
2607dd7cddfSDavid du Colombier return;
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
2637dd7cddfSDavid du Colombier if(f->curtext == t)
2647dd7cddfSDavid du Colombier f->curtext = f->text[0];
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier #endif
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier void
fileuninsert(File * f,Buffer * delta,uint p0,uint ns)2697dd7cddfSDavid du Colombier fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
2707dd7cddfSDavid du Colombier {
2717dd7cddfSDavid du Colombier Undo u;
2727dd7cddfSDavid du Colombier
2737dd7cddfSDavid du Colombier /* undo an insertion by deleting */
2747dd7cddfSDavid du Colombier u.type = Delete;
2757dd7cddfSDavid du Colombier u.mod = f->mod;
2767dd7cddfSDavid du Colombier u.seq = f->seq;
2777dd7cddfSDavid du Colombier u.p0 = p0;
2787dd7cddfSDavid du Colombier u.n = ns;
2797dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier
2827dd7cddfSDavid du Colombier void
fileundelete(File * f,Buffer * delta,uint p0,uint p1)2837dd7cddfSDavid du Colombier fileundelete(File *f, Buffer *delta, uint p0, uint p1)
2847dd7cddfSDavid du Colombier {
2857dd7cddfSDavid du Colombier Undo u;
2867dd7cddfSDavid du Colombier Rune *buf;
2877dd7cddfSDavid du Colombier uint i, n;
2887dd7cddfSDavid du Colombier
2897dd7cddfSDavid du Colombier /* undo a deletion by inserting */
2907dd7cddfSDavid du Colombier u.type = Insert;
2917dd7cddfSDavid du Colombier u.mod = f->mod;
2927dd7cddfSDavid du Colombier u.seq = f->seq;
2937dd7cddfSDavid du Colombier u.p0 = p0;
2947dd7cddfSDavid du Colombier u.n = p1-p0;
2957dd7cddfSDavid du Colombier buf = fbufalloc();
2967dd7cddfSDavid du Colombier for(i=p0; i<p1; i+=n){
2977dd7cddfSDavid du Colombier n = p1 - i;
2987dd7cddfSDavid du Colombier if(n > RBUFSIZE)
2997dd7cddfSDavid du Colombier n = RBUFSIZE;
3007dd7cddfSDavid du Colombier bufread(f, i, buf, n);
3017dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, buf, n);
3027dd7cddfSDavid du Colombier }
3037dd7cddfSDavid du Colombier fbuffree(buf);
3047dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier }
3077dd7cddfSDavid du Colombier
3087dd7cddfSDavid du Colombier int
filereadc(File * f,uint q)3097dd7cddfSDavid du Colombier filereadc(File *f, uint q)
3107dd7cddfSDavid du Colombier {
3117dd7cddfSDavid du Colombier Rune r;
3127dd7cddfSDavid du Colombier
3137dd7cddfSDavid du Colombier if(q >= f->nc)
3147dd7cddfSDavid du Colombier return -1;
3157dd7cddfSDavid du Colombier bufread(f, q, &r, 1);
3167dd7cddfSDavid du Colombier return r;
3177dd7cddfSDavid du Colombier }
3187dd7cddfSDavid du Colombier
3197dd7cddfSDavid du Colombier void
filesetname(File * f,String * s)3207dd7cddfSDavid du Colombier filesetname(File *f, String *s)
3217dd7cddfSDavid du Colombier {
3227dd7cddfSDavid du Colombier if(!f->unread) /* This is setting initial file name */
3237dd7cddfSDavid du Colombier fileunsetname(f, &f->delta);
3247dd7cddfSDavid du Colombier Strduplstr(&f->name, s);
3257dd7cddfSDavid du Colombier sortname(f);
3267dd7cddfSDavid du Colombier f->unread = TRUE;
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier void
fileunsetname(File * f,Buffer * delta)3307dd7cddfSDavid du Colombier fileunsetname(File *f, Buffer *delta)
3317dd7cddfSDavid du Colombier {
3327dd7cddfSDavid du Colombier String s;
3337dd7cddfSDavid du Colombier Undo u;
3347dd7cddfSDavid du Colombier
3357dd7cddfSDavid du Colombier /* undo a file name change by restoring old name */
3367dd7cddfSDavid du Colombier u.type = Filename;
3377dd7cddfSDavid du Colombier u.mod = f->mod;
3387dd7cddfSDavid du Colombier u.seq = f->seq;
3397dd7cddfSDavid du Colombier u.p0 = 0; /* unused */
3407dd7cddfSDavid du Colombier Strinit(&s);
3417dd7cddfSDavid du Colombier Strduplstr(&s, &f->name);
3427dd7cddfSDavid du Colombier fullname(&s);
3437dd7cddfSDavid du Colombier u.n = s.n;
3447dd7cddfSDavid du Colombier if(s.n)
3457dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, s.s, s.n);
3467dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
3477dd7cddfSDavid du Colombier Strclose(&s);
3487dd7cddfSDavid du Colombier }
3497dd7cddfSDavid du Colombier
3507dd7cddfSDavid du Colombier void
fileunsetdot(File * f,Buffer * delta,Range dot)3517dd7cddfSDavid du Colombier fileunsetdot(File *f, Buffer *delta, Range dot)
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier Undo u;
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier u.type = Dot;
3567dd7cddfSDavid du Colombier u.mod = f->mod;
3577dd7cddfSDavid du Colombier u.seq = f->seq;
3587dd7cddfSDavid du Colombier u.p0 = dot.p1;
3597dd7cddfSDavid du Colombier u.n = dot.p2 - dot.p1;
3607dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier
3637dd7cddfSDavid du Colombier void
fileunsetmark(File * f,Buffer * delta,Range mark)3647dd7cddfSDavid du Colombier fileunsetmark(File *f, Buffer *delta, Range mark)
3657dd7cddfSDavid du Colombier {
3667dd7cddfSDavid du Colombier Undo u;
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier u.type = Mark;
3697dd7cddfSDavid du Colombier u.mod = f->mod;
3707dd7cddfSDavid du Colombier u.seq = f->seq;
3717dd7cddfSDavid du Colombier u.p0 = mark.p1;
3727dd7cddfSDavid du Colombier u.n = mark.p2 - mark.p1;
3737dd7cddfSDavid du Colombier bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier uint
fileload(File * f,uint p0,int fd,int * nulls)3777dd7cddfSDavid du Colombier fileload(File *f, uint p0, int fd, int *nulls)
3787dd7cddfSDavid du Colombier {
3797dd7cddfSDavid du Colombier if(f->seq > 0)
3807dd7cddfSDavid du Colombier panic("undo in file.load unimplemented");
3817dd7cddfSDavid du Colombier return bufload(f, p0, fd, nulls);
3827dd7cddfSDavid du Colombier }
3837dd7cddfSDavid du Colombier
3847dd7cddfSDavid du Colombier int
fileupdate(File * f,int notrans,int toterm)3857dd7cddfSDavid du Colombier fileupdate(File *f, int notrans, int toterm)
3867dd7cddfSDavid du Colombier {
3877dd7cddfSDavid du Colombier uint p1, p2;
3887dd7cddfSDavid du Colombier int mod;
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier if(f->rescuing)
3917dd7cddfSDavid du Colombier return FALSE;
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier flushmerge();
3947dd7cddfSDavid du Colombier
3957dd7cddfSDavid du Colombier /*
3967dd7cddfSDavid du Colombier * fix the modification bit
3977dd7cddfSDavid du Colombier * subtle point: don't save it away in the log.
3987dd7cddfSDavid du Colombier *
3997dd7cddfSDavid du Colombier * if another change is made, the correct f->mod
4007dd7cddfSDavid du Colombier * state is saved in the undo log by filemark
4017dd7cddfSDavid du Colombier * when setting the dot and mark.
4027dd7cddfSDavid du Colombier *
4037dd7cddfSDavid du Colombier * if the change is undone, the correct state is
4047dd7cddfSDavid du Colombier * saved from f in the fileun... routines.
4057dd7cddfSDavid du Colombier */
4067dd7cddfSDavid du Colombier mod = f->mod;
4077dd7cddfSDavid du Colombier f->mod = f->prevmod;
4087dd7cddfSDavid du Colombier if(f == cmd)
4097dd7cddfSDavid du Colombier notrans = TRUE;
4107dd7cddfSDavid du Colombier else{
4117dd7cddfSDavid du Colombier fileunsetdot(f, &f->delta, f->prevdot);
4127dd7cddfSDavid du Colombier fileunsetmark(f, &f->delta, f->prevmark);
4137dd7cddfSDavid du Colombier }
4147dd7cddfSDavid du Colombier f->dot = f->ndot;
4157dd7cddfSDavid du Colombier fileundo(f, FALSE, !notrans, &p1, &p2, toterm);
4167dd7cddfSDavid du Colombier f->mod = mod;
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier if(f->delta.nc == 0)
4197dd7cddfSDavid du Colombier f->seq = 0;
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier if(f == cmd)
4227dd7cddfSDavid du Colombier return FALSE;
4237dd7cddfSDavid du Colombier
4247dd7cddfSDavid du Colombier if(f->mod){
4257dd7cddfSDavid du Colombier f->closeok = 0;
4267dd7cddfSDavid du Colombier quitok = 0;
4277dd7cddfSDavid du Colombier }else
4287dd7cddfSDavid du Colombier f->closeok = 1;
4297dd7cddfSDavid du Colombier return TRUE;
4307dd7cddfSDavid du Colombier }
4317dd7cddfSDavid du Colombier
4327dd7cddfSDavid du Colombier long
prevseq(Buffer * b)4337dd7cddfSDavid du Colombier prevseq(Buffer *b)
4347dd7cddfSDavid du Colombier {
4357dd7cddfSDavid du Colombier Undo u;
4367dd7cddfSDavid du Colombier uint up;
4377dd7cddfSDavid du Colombier
4387dd7cddfSDavid du Colombier up = b->nc;
4397dd7cddfSDavid du Colombier if(up == 0)
4407dd7cddfSDavid du Colombier return 0;
4417dd7cddfSDavid du Colombier up -= Undosize;
4427dd7cddfSDavid du Colombier bufread(b, up, (Rune*)&u, Undosize);
4437dd7cddfSDavid du Colombier return u.seq;
4447dd7cddfSDavid du Colombier }
4457dd7cddfSDavid du Colombier
4467dd7cddfSDavid du Colombier long
undoseq(File * f,int isundo)4477dd7cddfSDavid du Colombier undoseq(File *f, int isundo)
4487dd7cddfSDavid du Colombier {
4497dd7cddfSDavid du Colombier if(isundo)
4507dd7cddfSDavid du Colombier return f->seq;
4517dd7cddfSDavid du Colombier
4527dd7cddfSDavid du Colombier return prevseq(&f->epsilon);
4537dd7cddfSDavid du Colombier }
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier void
fileundo(File * f,int isundo,int canredo,uint * q0p,uint * q1p,int flag)4567dd7cddfSDavid du Colombier fileundo(File *f, int isundo, int canredo, uint *q0p, uint *q1p, int flag)
4577dd7cddfSDavid du Colombier {
4587dd7cddfSDavid du Colombier Undo u;
4597dd7cddfSDavid du Colombier Rune *buf;
4607dd7cddfSDavid du Colombier uint i, n, up;
4617dd7cddfSDavid du Colombier uint stop;
4627dd7cddfSDavid du Colombier Buffer *delta, *epsilon;
4637dd7cddfSDavid du Colombier
4647dd7cddfSDavid du Colombier if(isundo){
4657dd7cddfSDavid du Colombier /* undo; reverse delta onto epsilon, seq decreases */
4667dd7cddfSDavid du Colombier delta = &f->delta;
4677dd7cddfSDavid du Colombier epsilon = &f->epsilon;
4687dd7cddfSDavid du Colombier stop = f->seq;
4697dd7cddfSDavid du Colombier }else{
4707dd7cddfSDavid du Colombier /* redo; reverse epsilon onto delta, seq increases */
4717dd7cddfSDavid du Colombier delta = &f->epsilon;
4727dd7cddfSDavid du Colombier epsilon = &f->delta;
4737dd7cddfSDavid du Colombier stop = 0; /* don't know yet */
4747dd7cddfSDavid du Colombier }
4757dd7cddfSDavid du Colombier
4767dd7cddfSDavid du Colombier raspstart(f);
4777dd7cddfSDavid du Colombier while(delta->nc > 0){
47854d47c71SDavid du Colombier /* rasp and buffer are in sync; sync with wire if needed */
47954d47c71SDavid du Colombier if(needoutflush())
48054d47c71SDavid du Colombier raspflush(f);
4817dd7cddfSDavid du Colombier up = delta->nc-Undosize;
4827dd7cddfSDavid du Colombier bufread(delta, up, (Rune*)&u, Undosize);
4837dd7cddfSDavid du Colombier if(isundo){
4847dd7cddfSDavid du Colombier if(u.seq < stop){
4857dd7cddfSDavid du Colombier f->seq = u.seq;
4867dd7cddfSDavid du Colombier raspdone(f, flag);
4877dd7cddfSDavid du Colombier return;
4887dd7cddfSDavid du Colombier }
4897dd7cddfSDavid du Colombier }else{
4907dd7cddfSDavid du Colombier if(stop == 0)
4917dd7cddfSDavid du Colombier stop = u.seq;
4927dd7cddfSDavid du Colombier if(u.seq > stop){
4937dd7cddfSDavid du Colombier raspdone(f, flag);
4947dd7cddfSDavid du Colombier return;
4957dd7cddfSDavid du Colombier }
4967dd7cddfSDavid du Colombier }
4977dd7cddfSDavid du Colombier switch(u.type){
4987dd7cddfSDavid du Colombier default:
4997dd7cddfSDavid du Colombier panic("undo unknown u.type");
5007dd7cddfSDavid du Colombier break;
5017dd7cddfSDavid du Colombier
5027dd7cddfSDavid du Colombier case Delete:
5037dd7cddfSDavid du Colombier f->seq = u.seq;
5047dd7cddfSDavid du Colombier if(canredo)
5057dd7cddfSDavid du Colombier fileundelete(f, epsilon, u.p0, u.p0+u.n);
5067dd7cddfSDavid du Colombier f->mod = u.mod;
5077dd7cddfSDavid du Colombier bufdelete(f, u.p0, u.p0+u.n);
5087dd7cddfSDavid du Colombier raspdelete(f, u.p0, u.p0+u.n, flag);
5097dd7cddfSDavid du Colombier *q0p = u.p0;
5107dd7cddfSDavid du Colombier *q1p = u.p0;
5117dd7cddfSDavid du Colombier break;
5127dd7cddfSDavid du Colombier
5137dd7cddfSDavid du Colombier case Insert:
5147dd7cddfSDavid du Colombier f->seq = u.seq;
5157dd7cddfSDavid du Colombier if(canredo)
5167dd7cddfSDavid du Colombier fileuninsert(f, epsilon, u.p0, u.n);
5177dd7cddfSDavid du Colombier f->mod = u.mod;
5187dd7cddfSDavid du Colombier up -= u.n;
5197dd7cddfSDavid du Colombier buf = fbufalloc();
5207dd7cddfSDavid du Colombier for(i=0; i<u.n; i+=n){
5217dd7cddfSDavid du Colombier n = u.n - i;
5227dd7cddfSDavid du Colombier if(n > RBUFSIZE)
5237dd7cddfSDavid du Colombier n = RBUFSIZE;
5247dd7cddfSDavid du Colombier bufread(delta, up+i, buf, n);
5257dd7cddfSDavid du Colombier bufinsert(f, u.p0+i, buf, n);
5267dd7cddfSDavid du Colombier raspinsert(f, u.p0+i, buf, n, flag);
5277dd7cddfSDavid du Colombier }
5287dd7cddfSDavid du Colombier fbuffree(buf);
5297dd7cddfSDavid du Colombier *q0p = u.p0;
5307dd7cddfSDavid du Colombier *q1p = u.p0+u.n;
5317dd7cddfSDavid du Colombier break;
5327dd7cddfSDavid du Colombier
5337dd7cddfSDavid du Colombier case Filename:
5347dd7cddfSDavid du Colombier f->seq = u.seq;
5357dd7cddfSDavid du Colombier if(canredo)
5367dd7cddfSDavid du Colombier fileunsetname(f, epsilon);
5377dd7cddfSDavid du Colombier f->mod = u.mod;
5387dd7cddfSDavid du Colombier up -= u.n;
5397dd7cddfSDavid du Colombier
5407dd7cddfSDavid du Colombier Strinsure(&f->name, u.n+1);
5417dd7cddfSDavid du Colombier bufread(delta, up, f->name.s, u.n);
5427dd7cddfSDavid du Colombier f->name.s[u.n] = 0;
5437dd7cddfSDavid du Colombier f->name.n = u.n;
5447dd7cddfSDavid du Colombier fixname(&f->name);
5457dd7cddfSDavid du Colombier sortname(f);
5467dd7cddfSDavid du Colombier break;
5477dd7cddfSDavid du Colombier case Dot:
5487dd7cddfSDavid du Colombier f->seq = u.seq;
5497dd7cddfSDavid du Colombier if(canredo)
5507dd7cddfSDavid du Colombier fileunsetdot(f, epsilon, f->dot.r);
5517dd7cddfSDavid du Colombier f->mod = u.mod;
5527dd7cddfSDavid du Colombier f->dot.r.p1 = u.p0;
5537dd7cddfSDavid du Colombier f->dot.r.p2 = u.p0 + u.n;
5547dd7cddfSDavid du Colombier break;
5557dd7cddfSDavid du Colombier case Mark:
5567dd7cddfSDavid du Colombier f->seq = u.seq;
5577dd7cddfSDavid du Colombier if(canredo)
5587dd7cddfSDavid du Colombier fileunsetmark(f, epsilon, f->mark);
5597dd7cddfSDavid du Colombier f->mod = u.mod;
5607dd7cddfSDavid du Colombier f->mark.p1 = u.p0;
5617dd7cddfSDavid du Colombier f->mark.p2 = u.p0 + u.n;
5627dd7cddfSDavid du Colombier break;
5637dd7cddfSDavid du Colombier }
5647dd7cddfSDavid du Colombier bufdelete(delta, up, delta->nc);
5657dd7cddfSDavid du Colombier }
5667dd7cddfSDavid du Colombier if(isundo)
5677dd7cddfSDavid du Colombier f->seq = 0;
5687dd7cddfSDavid du Colombier raspdone(f, flag);
5697dd7cddfSDavid du Colombier }
5707dd7cddfSDavid du Colombier
5717dd7cddfSDavid du Colombier void
filereset(File * f)5727dd7cddfSDavid du Colombier filereset(File *f)
5737dd7cddfSDavid du Colombier {
5747dd7cddfSDavid du Colombier bufreset(&f->delta);
5757dd7cddfSDavid du Colombier bufreset(&f->epsilon);
5767dd7cddfSDavid du Colombier f->seq = 0;
5777dd7cddfSDavid du Colombier }
5787dd7cddfSDavid du Colombier
5797dd7cddfSDavid du Colombier void
fileclose(File * f)5807dd7cddfSDavid du Colombier fileclose(File *f)
5817dd7cddfSDavid du Colombier {
5823e12c5d1SDavid du Colombier Strclose(&f->name);
5837dd7cddfSDavid du Colombier bufclose(f);
5847dd7cddfSDavid du Colombier bufclose(&f->delta);
5857dd7cddfSDavid du Colombier bufclose(&f->epsilon);
5863e12c5d1SDavid du Colombier if(f->rasp)
5873e12c5d1SDavid du Colombier listfree(f->rasp);
5883e12c5d1SDavid du Colombier free(f);
5893e12c5d1SDavid du Colombier }
5903e12c5d1SDavid du Colombier
5913e12c5d1SDavid du Colombier void
filemark(File * f)5927dd7cddfSDavid du Colombier filemark(File *f)
5933e12c5d1SDavid du Colombier {
5943e12c5d1SDavid du Colombier
5957dd7cddfSDavid du Colombier if(f->unread)
596bd389b36SDavid du Colombier return;
5977dd7cddfSDavid du Colombier if(f->epsilon.nc)
5987dd7cddfSDavid du Colombier bufdelete(&f->epsilon, 0, f->epsilon.nc);
5997dd7cddfSDavid du Colombier
6007dd7cddfSDavid du Colombier if(f != cmd){
6017dd7cddfSDavid du Colombier f->prevdot = f->dot.r;
6027dd7cddfSDavid du Colombier f->prevmark = f->mark;
6037dd7cddfSDavid du Colombier f->prevseq = f->seq;
6047dd7cddfSDavid du Colombier f->prevmod = f->mod;
6053e12c5d1SDavid du Colombier }
6063e12c5d1SDavid du Colombier
6077dd7cddfSDavid du Colombier f->ndot = f->dot;
6087dd7cddfSDavid du Colombier f->seq = seq;
6097dd7cddfSDavid du Colombier f->hiposn = 0;
6103e12c5d1SDavid du Colombier }
611