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);