tvi: restore '*' mark in undo and redo commands - 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 dfba674ea99270a05c441a32a22f2c0ee93b829f
 (DIR) parent 767af123ec819e4a76c8570293c75cdfe456ead6
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Thu,  4 Jun 2015 23:33:19 +0430
       
       vi: restore '*' mark in undo and redo commands
       
       Diffstat:
         M lbuf.c                              |      52 +++++++++++++++++++++++++++----
         M vi.c                                |       7 +++----
       
       2 files changed, 49 insertions(+), 10 deletions(-)
       ---
 (DIR) diff --git a/lbuf.c b/lbuf.c
       t@@ -12,6 +12,7 @@ struct lopt {
                int ins;                /* insertion operation if non-zero */
                int beg, end;
                int seq;                /* operation number */
       +        int *mark, *mark_off;        /* saved marks */
        };
        
        /* line buffers */
       t@@ -39,13 +40,20 @@ struct lbuf *lbuf_make(void)
                return lb;
        }
        
       +static void lopt_done(struct lopt *lo)
       +{
       +        free(lo->buf);
       +        free(lo->mark);
       +        free(lo->mark_off);
       +}
       +
        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++)
       -                free(lb->hist[i].buf);
       +                lopt_done(&lb->hist[i]);
                free(lb->ln);
                free(lb);
        }
       t@@ -121,17 +129,18 @@ static void lbuf_opt(struct lbuf *lb, int ins, int beg, int end)
                int i;
                if (lb->undo) {
                        for (i = 0; i < lb->undo; i++)
       -                        free(lb->hist[i].buf);
       +                        lopt_done(&lb->hist[i]);
                        memmove(lb->hist + 1, lb->hist + lb->undo,
                                (n - lb->undo) * sizeof(lb->hist[0]));
       -                for (i = n - lb->undo + 1; i < n; i++)
       -                        lb->hist[i].buf = NULL;
       +                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;
       -                free(lb->hist[n - 1].buf);
       +                lopt_done(&lb->hist[n - 1]);
                        memmove(lb->hist + 1, lb->hist, (n - 1) * sizeof(lb->hist[0]));
                }
       +        memset(lo, 0, sizeof(*lo));
                lo->ins = ins;
                lo->beg = beg;
                lo->end = end;
       t@@ -163,6 +172,8 @@ void lbuf_rm(struct lbuf *lb, int beg, int end)
        {
                if (end > lb->ln_n)
                        end = lb->ln_n;
       +        if (beg == end)
       +                return;
                lbuf_opt(lb, 0, beg, end);
                lbuf_delete(lb, beg, end);
        }
       t@@ -170,6 +181,8 @@ void lbuf_rm(struct lbuf *lb, int beg, int end)
        void lbuf_put(struct lbuf *lb, int pos, char *s)
        {
                int lb_len = lbuf_len(lb);
       +        if (!*s)
       +                return;
                lbuf_insert(lb, pos, s);
                lbuf_opt(lb, 1, pos, pos + lbuf_len(lb) - lb_len);
        }
       t@@ -219,6 +232,28 @@ static struct lopt *lbuf_lopt(struct lbuf *lb, int i)
                return i >= 0 && i < LEN(lb->hist) && lo->buf ? lo : NULL;
        }
        
       +static void lbuf_savemarks(struct lbuf *lb, struct lopt *lo)
       +{
       +        int i;
       +        lo->mark = malloc(sizeof(lb->mark));
       +        lo->mark_off = malloc(sizeof(lb->mark_off));
       +        for (i = 0; i < LEN(lb->mark); i++)
       +                lo->mark[i] = -1;
       +        lo->mark['*'] = lb->mark['*'];
       +        lo->mark_off['*'] = lb->mark_off['*'];
       +}
       +
       +static void lbuf_loadmarks(struct lbuf *lb, struct lopt *lo)
       +{
       +        int i;
       +        for (i = 0; lo->mark && i < LEN(lb->mark); i++) {
       +                if (lo->mark[i] >= 0) {
       +                        lb->mark[i] = lo->mark[i];
       +                        lb->mark_off[i] = lo->mark_off[i];
       +                }
       +        }
       +}
       +
        int lbuf_undo(struct lbuf *lb)
        {
                struct lopt *lo = lbuf_lopt(lb, lb->undo);
       t@@ -232,6 +267,7 @@ int lbuf_undo(struct lbuf *lb)
                                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;
       t@@ -250,6 +286,7 @@ int lbuf_redo(struct lbuf *lb)
                                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;
       t@@ -267,7 +304,7 @@ void lbuf_saved(struct lbuf *lb, int clear)
                int i;
                if (clear) {
                        for (i = 0; i < LEN(lb->hist); i++)
       -                        free(lb->hist[i].buf);
       +                        lopt_done(&lb->hist[i]);
                        memset(lb->hist, 0, sizeof(lb->hist));
                        lb->undo = 0;
                        lb->useq_last = lb->useq;
       t@@ -278,6 +315,9 @@ 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)
       +                lbuf_savemarks(lb, lo);
                lb->mod_new = 1;
                lb->useq++;
                return lbuf_seq(lb) != lb->useq_zero;
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -990,6 +990,7 @@ static void vi(void)
                                int z, g;
                                if (c <= 0)
                                        continue;
       +                        lbuf_mark(xb, '*', xrow, xoff);
                                switch (c) {
                                case TK_CTL('b'):
                                        if (vi_scrollbackward(MAX(1, vi_arg1) * (xrows - 1)))
       t@@ -1020,8 +1021,7 @@ static void vi(void)
                                        break;
                                case 'u':
                                        if (!lbuf_undo(xb)) {
       -                                        lbuf_jump(xb, '[', &xrow, &xoff);
       -                                        xoff = lbuf_indents(xb, xrow);
       +                                        lbuf_jump(xb, '*', &xrow, &xoff);
                                                redraw = 1;
                                        } else {
                                                snprintf(vi_msg, sizeof(vi_msg), "undo failed\n");
       t@@ -1029,8 +1029,7 @@ static void vi(void)
                                        break;
                                case TK_CTL('r'):
                                        if (!lbuf_redo(xb)) {
       -                                        lbuf_jump(xb, '[', &xrow, &xoff);
       -                                        xoff = lbuf_indents(xb, xrow);
       +                                        lbuf_jump(xb, '*', &xrow, &xoff);
                                                redraw = 1;
                                        } else {
                                                snprintf(vi_msg, sizeof(vi_msg), "redo failed\n");