#include #include #include #include #include #include #include #include #include #include <9p.h> #include #include "gui.h" int textdebug; static void dumpop(char* pref, Edit* e) { int nr; nr = e->nr > 3 ? 3 : e->nr; fprint(2, "%s%c%s %3d #%d\t [%.*S]\n", pref, e->end ? '*' : ' ', e->op == Ins ? "ins" : "del", e->pos, e->nr, nr, e->r); } static void dumpedits(Panel* p) { Edit* e; fprint(2, "%s edits:\n", p->name); for (e = p->undos; e && e < p->undo; e++) dumpop("\t", e); fprint(2, "\n"); } Edit* addedit(Panel* p, int op, Rune* r, int nr, int pos) { Edit* e; int nlen; Edit* last; /* merge to succesive inserts into a single one, if feasible. */ if (op == Ins && p->undos && p->undo > p->undos){ last = p->undo - 1; if (last->op == Ins && !last->end && pos == last->pos + last->nr){ nlen = (nr + last->nr) * sizeof(Rune); last->r = erealloc9p(last->r, nlen); memmove(last->r + last->nr, r, nr*sizeof(Rune)); last->nr += nr; return last; } } if (p->undo == p->undos+p->nundos){ if (!(p->nundos%16)) p->undos = erealloc9p(p->undos, (p->nundos+16)*sizeof(Edit)); e = p->undos + p->nundos++; p->undo = p->undos + p->nundos; } else { assert(p->undo && p->undo < p->undos+p->nundos); e = p->undo++; free(e->r); } e->r = emalloc9p(nr * sizeof(Rune)); memmove(e->r, r, nr*sizeof(Rune)); e->nr = nr; e->pos= pos; e->op= op; e->end = 0; if (textdebug) dumpedits(p); return e; } void newedit(Panel* p) { Edit* e; if (p->undo && p->undo > p->undos){ e = p->undo-1; e->end = 1; } } int hasedits(Panel* p) { if (!p->undo) return 0; return (p->undo - p->undos) != p->cundo; } void setnoedits(Panel* p) { if (!p->undo) p->cundo = 0; else p->cundo = p->undo - p->undos; } void cleanedits(Panel* p) { int i; for (i = 0; i < p->nundos; i++){ free(p->undos[i].r); } free(p->undos); p->undos = p->undo = nil; p->nundos = 0; p->cundo = 0; if (textdebug) dumpedits(p); } static int undo1(Panel* p) { int r; p->undo--; r = p->undo->pos; if (p->undo->op == Ins){ textdel(p, p->undo->r, p->undo->nr, p->undo->pos); filltext(p); } else textins(p, p->undo->r, p->undo->nr, p->undo->pos); return r; } int undo(Panel* p, int* ppos) { Edit* e; int some; int pos; some = 0; while(p->undo && p->undo > p->undos){ pos = undo1(p); if (ppos) *ppos = pos; some++; if (p->undo > p->undos){ e = p->undo - 1; if (e->end) break; } } return some; } static int redo1(Panel* p) { int r; r = p->undo->pos; if (p->undo->op == Ins) textins(p, p->undo->r, p->undo->nr, p->undo->pos); else { textdel(p, p->undo->r, p->undo->nr, p->undo->pos); filltext(p); } p->undo++; return r; } int redo(Panel* p, int* ppos) { Edit* e; int last; int some; int pos; e = p->undos + p->nundos; for(last = some = 0; !last && p->undo && p->undo < e; some++){ last = p->undo->end; pos = redo1(p); if (ppos) *ppos = pos; } return some; }