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