tvi: do not move the cursor past EOL - 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 40532b52979509bb1bb5332e8f9bd9bb6e15dc72
 (DIR) parent 0c2fb9f33f08de99cfc4e5b61e14259bbbe2c468
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Sun, 17 May 2015 14:26:11 +0430
       
       vi: do not move the cursor past EOL
       
       Diffstat:
         M ren.c                               |      22 ++++++++++++++++++++--
         M vi.c                                |      27 ++++++++++++++++-----------
         M vi.h                                |       3 ++-
       
       3 files changed, 38 insertions(+), 14 deletions(-)
       ---
 (DIR) diff --git a/ren.c b/ren.c
       t@@ -38,7 +38,7 @@ int ren_wid(char *s)
                return ret;
        }
        
       -/* find the next character after visual position p; if cur start from p itself */
       +/* find the next character after visual position p; if cur, start from p itself */
        static int pos_next(int *pos, int n, int p, int cur)
        {
                int i, ret = -1;
       t@@ -48,7 +48,7 @@ static int pos_next(int *pos, int n, int p, int cur)
                return ret >= 0 ? pos[ret] : -1;
        }
        
       -/* find the previous character after visual position p; if cur start from p itself */
       +/* find the previous character after visual position p; if cur, start from p itself */
        static int pos_prev(int *pos, int n, int p, int cur)
        {
                int i, ret = -1;
       t@@ -93,12 +93,30 @@ int ren_cursor(char *s, int p)
                n = uc_slen(s);
                pos = ren_position(s);
                p = pos_prev(pos, n, p, 1);
       +        if (uc_code(uc_chr(s, ren_off(s, p))) == '\n')
       +                p = pos_prev(pos, n, p, 0);
                next = pos_next(pos, n, p, 0);
                p = (next >= 0 ? next : pos[n]) - 1;
                free(pos);
                return p >= 0 ? p : 0;
        }
        
       +/* real cursor position; never past EOL */
       +int ren_noeol(char *s, int p)
       +{
       +        int n;
       +        int *pos;
       +        if (!s)
       +                return 0;
       +        n = uc_slen(s);
       +        pos = ren_position(s);
       +        p = pos_prev(pos, n, p, 1);
       +        if (uc_code(uc_chr(s, ren_off(s, p))) == '\n')
       +                p = pos_prev(pos, n, p, 0);
       +        free(pos);
       +        return p >= 0 ? p : 0;
       +}
       +
        /* the position of the next character */
        int ren_next(char *s, int p, int dir)
        {
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -529,8 +529,7 @@ static int vi_motion(int *row, int *col)
                        lbuf_postindents(xb, row, col);
                        break;
                case '$':
       -                lbuf_eol(xb, row, col, +1);
       -                lbuf_lnnext(xb, row, col, -1);
       +                *col = 1024;
                        break;
                case '|':
                        *col = cnt - 1;
       t@@ -796,6 +795,8 @@ static int vc_motion(int cmd)
                vi_arg2 = vi_prefix();
                if (vi_arg2 < 0)
                        return 1;
       +        c1 = ren_noeol(lbuf_get(xb, r1), xcol);
       +        c2 = c1;
                if ((mv = vi_motionln(&r2, cmd))) {
                        c2 = -1;
                } else if (!(mv = vi_motion(&r2, &c2))) {
       t@@ -804,7 +805,7 @@ static int vc_motion(int cmd)
                }
                if (mv < 0)
                        return 1;
       -        if (!strchr("fFtTeE$", mv))
       +        if (!strchr("fFtTeE", mv))
                        closed = 0;
                lnmode = c2 < 0;
                if (lnmode) {
       t@@ -1013,23 +1014,27 @@ static void vi(void)
                term_pos(xrow, led_pos(lbuf_get(xb, xrow), xcol));
                while (!xquit) {
                        int redraw = 0;
       -                int orow = xrow;
       -                int ocol = xcol;
       +                int nrow = xrow;
       +                int ncol = ren_noeol(lbuf_get(xb, xrow), xcol);
                        int mv, n;
                        vi_arg2 = 0;
                        vi_ybuf = vi_yankbuf();
                        vi_arg1 = vi_prefix();
                        if (!vi_ybuf)
                                vi_ybuf = vi_yankbuf();
       -                mv = vi_motion(&xrow, &xcol);
       +                mv = vi_motion(&nrow, &ncol);
                        if (mv > 0) {
                                if (strchr("\'GHML/?{}[]", mv))
       -                                lbuf_mark(xb, '\'', orow);
       -                        if (xcol < 0) {
       -                                if (strchr("jk", mv))
       -                                        xcol = ocol;
       -                                else
       +                                lbuf_mark(xb, '\'', xrow);
       +                        xrow = nrow;
       +                        if (ncol < 0) {
       +                                if (!strchr("jk", mv))
                                                lbuf_postindents(xb, &xrow, &xcol);
       +                        } else {
       +                                if (strchr("|$", mv))
       +                                        xcol = ncol;
       +                                else
       +                                        xcol = ren_noeol(lbuf_get(xb, xrow), ncol);
                                }
                        } else if (mv == 0) {
                                int c = vi_read();
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -45,10 +45,11 @@ void rset_free(struct rset *re);
        
        /* rendering lines */
        int *ren_position(char *s);
       -int ren_cursor(char *s, int pos);
        int ren_next(char *s, int p, int dir);
        int ren_eol(char *s, int dir);
        int ren_pos(char *s, int off);
       +int ren_cursor(char *s, int pos);
       +int ren_noeol(char *s, int p);
        int ren_off(char *s, int pos);
        int ren_wid(char *s);
        int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed);