tlbuf: do not limit the size of undo history - neatvi - [fork] simple vi-type editor with UTF-8 support
 (HTM) git clone git://src.adamsgaard.dk/neatvi
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit ffadc288805a68e944bc6739ca3831e2c120dca0
 (DIR) parent 666a00bba9a47618652e7506425c865fabe8e365
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Mon, 29 Jun 2015 18:49:28 +0430
       
       lbuf: do not limit the size of undo history
       
       Tested by Peter Aronoff <peter@aronoff.org>.
       
       Diffstat:
         M lbuf.c                              |      85 ++++++++++++++-----------------
       
       1 file changed, 39 insertions(+), 46 deletions(-)
       ---
 (DIR) diff --git a/lbuf.c b/lbuf.c
       t@@ -19,12 +19,14 @@ struct lopt {
        struct lbuf {
                int mark[NMARKS];        /* mark lines */
                int mark_off[NMARKS];        /* mark line offsets */
       -        struct lopt hist[128];        /* buffer history */
       -        int undo;                /* current index into hist[] */
       +        char **ln;                /* buffer lines */
       +        int ln_n;                /* number of lines in ln[] */
       +        int ln_sz;                /* size of ln[] */
                int useq;                /* current operation sequence */
       -        char **ln;                /* lines */
       -        int ln_n;                /* number of lbuf in l[] */
       -        int ln_sz;                /* size of l[] */
       +        struct lopt *hist;        /* buffer history */
       +        int hist_sz;                /* size of hist[] */
       +        int hist_n;                /* current history head in hist[] */
       +        int hist_u;                /* current undo head in hist[] */
                int mod_new;                /* clear modification marks */
                int useq_zero;                /* useq for lbuf_saved() */
                int useq_last;                /* useq before hist[] */
       t@@ -53,8 +55,9 @@ void lbuf_free(struct lbuf *lb)
                int i;
                for (i = 0; i < lb->ln_n; i++)
                        free(lb->ln[i]);
       -        for (i = 0; i < LEN(lb->hist); i++)
       +        for (i = 0; i < lb->hist_n; i++)
                        lopt_done(&lb->hist[i]);
       +        free(lb->hist);
                free(lb->ln);
                free(lb);
        }
       t@@ -122,29 +125,28 @@ static void lbuf_delete(struct lbuf *lb, int beg, int end)
        /* append undo/redo history */
        static void lbuf_opt(struct lbuf *lb, int ins, int beg, int end)
        {
       -        struct lopt *lo = &lb->hist[0];
       -        int n = LEN(lb->hist);
       +        struct lopt *lo;
                int i;
       -        if (lb->undo) {
       -                for (i = 0; i < lb->undo; i++)
       -                        lopt_done(&lb->hist[i]);
       -                memmove(lb->hist + 1, lb->hist + lb->undo,
       -                        (n - lb->undo) * sizeof(lb->hist[0]));
       -                memset(lb->hist + n - lb->undo + 1, 0,
       -                        (lb->undo - 1) * sizeof(lb->hist[0]));
       -        } else {
       -                if (lb->hist[n - 1].buf)
       -                        lb->useq_last = lb->hist[n - 1].seq;
       -                lopt_done(&lb->hist[n - 1]);
       -                memmove(lb->hist + 1, lb->hist, (n - 1) * sizeof(lb->hist[0]));
       +        for (i = lb->hist_u; i < lb->hist_n; i++)
       +                lopt_done(&lb->hist[i]);
       +        lb->hist_n = lb->hist_u;
       +        if (lb->hist_n == lb->hist_sz) {
       +                int sz = lb->hist_sz + 128;
       +                struct lopt *hist = malloc(sz * sizeof(hist[0]));
       +                memcpy(hist, lb->hist, lb->hist_n * sizeof(hist[0]));
       +                free(lb->hist);
       +                lb->hist = hist;
       +                lb->hist_sz = sz;
                }
       +        lo = &lb->hist[lb->hist_n];
       +        lb->hist_n++;
       +        lb->hist_u = lb->hist_n;
                memset(lo, 0, sizeof(*lo));
                lo->ins = ins;
                lo->beg = beg;
                lo->end = end;
                lo->buf = lbuf_cp(lb, beg, end);
                lo->seq = lb->useq;
       -        lb->undo = 0;
        }
        
        void lbuf_rd(struct lbuf *lbuf, int fd, int pos)
       t@@ -224,12 +226,6 @@ int lbuf_jump(struct lbuf *lbuf, int mark, int *pos, int *off)
                return 0;
        }
        
       -static struct lopt *lbuf_lopt(struct lbuf *lb, int i)
       -{
       -        struct lopt *lo = &lb->hist[i];
       -        return i >= 0 && i < LEN(lb->hist) && lo->buf ? lo : NULL;
       -}
       -
        static void lbuf_savemarks(struct lbuf *lb, struct lopt *lo)
        {
                int i;
       t@@ -254,46 +250,43 @@ static void lbuf_loadmarks(struct lbuf *lb, struct lopt *lo)
        
        int lbuf_undo(struct lbuf *lb)
        {
       -        struct lopt *lo = lbuf_lopt(lb, lb->undo);
       -        int useq = lo ? lo->seq : 0;
       -        if (!lo)
       +        int useq;
       +        if (!lb->hist_u)
                        return 1;
       +        useq = lb->hist[lb->hist_u - 1].seq;
                lb->mod_new = 1;
       -        while (lo && lo->seq == useq) {
       -                lb->undo++;
       +        while (lb->hist_u && lb->hist[lb->hist_u - 1].seq == useq) {
       +                struct lopt *lo = &lb->hist[--(lb->hist_u)];
                        if (lo->ins)
                                lbuf_delete(lb, lo->beg, lo->end);
                        else
                                lbuf_insert(lb, lo->beg, lo->buf);
                        lbuf_loadmarks(lb, lo);
       -                lo = lbuf_lopt(lb, lb->undo);
                }
                return 0;
        }
        
        int lbuf_redo(struct lbuf *lb)
        {
       -        struct lopt *lo = lbuf_lopt(lb, lb->undo - 1);
       -        int useq = lo ? lo->seq : 0;
       -        if (!lo)
       +        int useq;
       +        if (lb->hist_u == lb->hist_n)
                        return 1;
       +        useq = lb->hist[lb->hist_u].seq;
                lb->mod_new = 1;
       -        while (lo && lo->seq == useq) {
       -                lb->undo--;
       +        while (lb->hist_u < lb->hist_n && lb->hist[lb->hist_u].seq == useq) {
       +                struct lopt *lo = &lb->hist[lb->hist_u++];
                        if (lo->ins)
                                lbuf_insert(lb, lo->beg, lo->buf);
                        else
                                lbuf_delete(lb, lo->beg, lo->end);
                        lbuf_loadmarks(lb, lo);
       -                lo = lbuf_lopt(lb, lb->undo - 1);
                }
                return 0;
        }
        
        static int lbuf_seq(struct lbuf *lb)
        {
       -        struct lopt *lo = lbuf_lopt(lb, lb->undo);
       -        return lo ? lo->seq : lb->useq_last;
       +        return lb->hist_u ? lb->hist[lb->hist_u - 1].seq : lb->useq_last;
        }
        
        /* mark buffer as saved and, if clear, clear the undo history */
       t@@ -301,10 +294,10 @@ void lbuf_saved(struct lbuf *lb, int clear)
        {
                int i;
                if (clear) {
       -                for (i = 0; i < LEN(lb->hist); i++)
       +                for (i = 0; i < lb->hist_n; i++)
                                lopt_done(&lb->hist[i]);
       -                memset(lb->hist, 0, sizeof(lb->hist));
       -                lb->undo = 0;
       +                lb->hist_n = 0;
       +                lb->hist_u = 0;
                        lb->useq_last = lb->useq;
                }
                lb->useq_zero = lbuf_seq(lb);
       t@@ -314,8 +307,8 @@ void lbuf_saved(struct lbuf *lb, int clear)
        /* was the file modified since the last lbuf_modreset() */
        int lbuf_modified(struct lbuf *lb)
        {
       -        struct lopt *lo = lbuf_lopt(lb, 0);
       -        if (!lb->undo && lo && !lo->mark)
       +        struct lopt *lo = lb->hist_n ? &lb->hist[lb->hist_n - 1] : NULL;
       +        if (lb->hist_u == lb->hist_n && lo && !lo->mark)
                        lbuf_savemarks(lb, lo);
                lb->mod_new = 1;
                lb->useq++;