tvi: rely on line offset instead of column number - neatvi - [fork] simple vi-t… | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit bdbc8d37c53bd7702979786c58354bbf2ef6990e | |
parent 2dc24f819262d48c8a7f6b2d1ce6a7fe992b4310 | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Thu, 28 May 2015 19:43:35 +0430 | |
vi: rely on line offset instead of column number | |
Diffstat: | |
M Makefile | 2 +- | |
M ex.c | 4 ++-- | |
A mot.c | 186 +++++++++++++++++++++++++++++… | |
M ren.c | 68 ++++-------------------------… | |
M uc.c | 12 +++++++++--- | |
M vi.c | 477 +++++++++++------------------… | |
M vi.h | 16 +++++++++++++--- | |
7 files changed, 382 insertions(+), 383 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
t@@ -2,7 +2,7 @@ CC = cc | |
CFLAGS = -Wall -O2 | |
LDFLAGS = | |
-OBJS = vi.o ex.o lbuf.o sbuf.o ren.o dir.o syn.o reg.o led.o \ | |
+OBJS = vi.o ex.o lbuf.o mot.o sbuf.o ren.o dir.o syn.o reg.o led.o \ | |
uc.o term.o rset.o cmd.o conf.o | |
all: vi | |
diff --git a/ex.c b/ex.c | |
t@@ -17,7 +17,7 @@ int xvis; /* visual mode */ | |
int xai = 1; /* autoindent option */ | |
int xic = 1; /* ignorecase option */ | |
struct lbuf *xb; /* current buffer */ | |
-int xrow, xcol, xtop; /* current row, column, and top row */ | |
+int xrow, xoff, xtop; /* current row, column, and top row */ | |
int xrow_alt; /* alternate row, column, and top row */ | |
int xled = 1; /* use the line editor */ | |
int xdir = +1; /* current direction context */ | |
t@@ -182,7 +182,7 @@ static void ec_edit(char *ec) | |
strcpy(xpath, xpath_tmp); | |
xrow = xrow_alt; | |
xrow_alt = xrow_tmp; | |
- xcol = 0; | |
+ xoff = 0; | |
xtop = 0; | |
} else { | |
strcpy(xpath_alt, xpath); | |
diff --git a/mot.c b/mot.c | |
t@@ -0,0 +1,186 @@ | |
+#include <stdio.h> | |
+#include <string.h> | |
+#include "vi.h" | |
+ | |
+int lbuf_indents(struct lbuf *lb, int r) | |
+{ | |
+ char *ln = lbuf_get(lb, r); | |
+ int o; | |
+ if (!ln) | |
+ return 0; | |
+ for (o = 0; uc_isspace(ln); o++) | |
+ ln = uc_next(ln); | |
+ return o; | |
+} | |
+ | |
+static int uc_nextdir(char **s, char *beg, int dir) | |
+{ | |
+ if (dir < 0) { | |
+ if (*s == beg) | |
+ return 1; | |
+ *s = uc_prev(beg, *s); | |
+ } else { | |
+ *s = uc_next(*s); | |
+ if (!(*s)[0]) | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int lbuf_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *row, int *of… | |
+{ | |
+ char *ln = lbuf_get(lb, *row); | |
+ char *s; | |
+ int dir = (cmd == 'f' || cmd == 't') ? +1 : -1; | |
+ if (!ln) | |
+ return 1; | |
+ if (n < 0) | |
+ dir = -dir; | |
+ if (n < 0) | |
+ n = -n; | |
+ s = uc_chr(ln, *off); | |
+ while (n > 0 && !uc_nextdir(&s, ln, dir)) | |
+ if (uc_code(s) == uc_code(cs)) | |
+ n--; | |
+ if (!n && (cmd == 't' || cmd == 'T')) | |
+ uc_nextdir(&s, ln, -dir); | |
+ if (!n) | |
+ *off = uc_off(ln, s - ln); | |
+ return n != 0; | |
+} | |
+ | |
+int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *o, int *len) | |
+{ | |
+ int offs[2]; | |
+ int found = 0; | |
+ int r0 = *r, o0 = *o; | |
+ int i; | |
+ struct rset *re = rset_make(1, &kw, xic ? RE_ICASE : 0); | |
+ if (!re) | |
+ return 1; | |
+ for (i = r0; !found && i >= 0 && i < lbuf_len(lb); i += dir) { | |
+ char *s = lbuf_get(lb, i); | |
+ int off = dir > 0 && r0 == i ? uc_chr(s, o0 + 1) - s : 0; | |
+ int flg = off ? RE_NOTBOL : 0; | |
+ while (rset_find(re, s + off, 1, offs, flg) >= 0) { | |
+ if (dir < 0 && r0 == i && off + offs[0] >= o0) | |
+ break; | |
+ found = 1; | |
+ *o = uc_off(s, off + offs[0]); | |
+ *r = i; | |
+ *len = offs[1] - offs[0]; | |
+ off += offs[1]; | |
+ if (dir > 0) | |
+ break; | |
+ } | |
+ } | |
+ rset_free(re); | |
+ return !found; | |
+} | |
+ | |
+int lbuf_paragraphbeg(struct lbuf *lb, int dir, int *row, int *off) | |
+{ | |
+ while (*row >= 0 && *row < lbuf_len(lb) && !strcmp("\n", lbuf_get(lb, … | |
+ *row += dir; | |
+ while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *… | |
+ *row += dir; | |
+ *row = MAX(0, MIN(*row, lbuf_len(lb) - 1)); | |
+ *off = 0; | |
+ return 0; | |
+} | |
+ | |
+int lbuf_sectionbeg(struct lbuf *lb, int dir, int *row, int *off) | |
+{ | |
+ *row += dir; | |
+ while (*row >= 0 && *row < lbuf_len(lb) && lbuf_get(lb, *row)[0] != '{… | |
+ *row += dir; | |
+ *row = MAX(0, MIN(*row, lbuf_len(lb) - 1)); | |
+ *off = 0; | |
+ return 0; | |
+} | |
+ | |
+static int lbuf_lnnext(struct lbuf *lb, int dir, int *r, int *o) | |
+{ | |
+ int off = *o + dir; | |
+ if (off < 0 || !lbuf_get(lb, *r) || off >= uc_slen(lbuf_get(lb, *r))) | |
+ return 1; | |
+ *o = off; | |
+ return 0; | |
+} | |
+ | |
+int lbuf_eol(struct lbuf *lb, int row) | |
+{ | |
+ int len = lbuf_get(lb, row) ? uc_slen(lbuf_get(lb, row)) : 0; | |
+ return len ? len - 1 : 0; | |
+} | |
+ | |
+static int lbuf_next(struct lbuf *lb, int dir, int *r, int *o) | |
+{ | |
+ if (dir < 0 && *r >= lbuf_len(lb)) | |
+ *r = MAX(0, lbuf_len(lb) - 1); | |
+ if (lbuf_lnnext(lb, dir, r, o)) { | |
+ if (!lbuf_get(lb, *r + dir)) | |
+ return -1; | |
+ *r += dir; | |
+ *o = dir > 0 ? 0 : lbuf_eol(lb, *r); | |
+ return 0; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+/* return a pointer to the character at visual position c of line r */ | |
+static char *lbuf_chr(struct lbuf *lb, int r, int c) | |
+{ | |
+ char *ln = lbuf_get(lb, r); | |
+ return ln ? uc_chr(ln, c) : ""; | |
+} | |
+ | |
+/* move to the last character of the word */ | |
+static int lbuf_wordlast(struct lbuf *lb, int kind, int dir, int *row, int *of… | |
+{ | |
+ if (!kind || !(uc_kind(lbuf_chr(lb, *row, *off)) & kind)) | |
+ return 0; | |
+ while (uc_kind(lbuf_chr(lb, *row, *off)) & kind) | |
+ if (lbuf_next(lb, dir, row, off)) | |
+ return 1; | |
+ if (!(uc_kind(lbuf_chr(lb, *row, *off)) & kind)) | |
+ lbuf_next(lb, -dir, row, off); | |
+ return 0; | |
+} | |
+ | |
+int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off) | |
+{ | |
+ int nl = 0; | |
+ lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, ro… | |
+ if (lbuf_next(lb, dir, row, off)) | |
+ return 1; | |
+ while (uc_isspace(lbuf_chr(lb, *row, *off))) { | |
+ nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? nl + 1 : 0; | |
+ if (nl == 2) | |
+ return 0; | |
+ if (lbuf_next(lb, dir, row, off)) | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off) | |
+{ | |
+ int nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? -1 : 0; | |
+ if (!uc_isspace(lbuf_chr(lb, *row, *off))) | |
+ if (lbuf_next(lb, dir, row, off)) | |
+ return 1; | |
+ while (uc_isspace(lbuf_chr(lb, *row, *off))) { | |
+ nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n' ? nl + 1 : 0; | |
+ if (nl == 2) { | |
+ if (dir < 0) | |
+ lbuf_next(lb, -dir, row, off); | |
+ return 0; | |
+ } | |
+ if (lbuf_next(lb, dir, row, off)) | |
+ return 1; | |
+ } | |
+ if (lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir… | |
+ return 1; | |
+ return 0; | |
+} | |
diff --git a/ren.c b/ren.c | |
t@@ -102,20 +102,13 @@ int ren_cursor(char *s, int p) | |
return p >= 0 ? p : 0; | |
} | |
-/* real cursor position; never past EOL */ | |
-int ren_noeol(char *s, int p) | |
+/* return an offset before EOL */ | |
+int ren_noeol(char *s, int o) | |
{ | |
- 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; | |
+ int n = s ? uc_slen(s) : 0; | |
+ if (o >= n) | |
+ o = MAX(0, n - 1); | |
+ return o > 0 && uc_chr(s, o)[0] == '\n' ? o - 1 : o; | |
} | |
/* the position of the next character */ | |
t@@ -129,54 +122,7 @@ int ren_next(char *s, int p, int dir) | |
else | |
p = pos_prev(pos, n, p, 0); | |
free(pos); | |
- return p; | |
-} | |
- | |
-static void swap(int *i1, int *i2) | |
-{ | |
- int t = *i1; | |
- *i1 = *i2; | |
- *i2 = t; | |
-} | |
- | |
-/* the region specified by two visual positions */ | |
-int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed) | |
-{ | |
- int *ord; /* ord[i]: the order of the i-th char on the … | |
- int o1, o2; | |
- int beg, end; | |
- int n = uc_slen(s); | |
- int i; | |
- if (c1 == c2 && !closed) { | |
- *l1 = ren_off(s, c1); | |
- *l2 = ren_off(s, c2); | |
- return 0; | |
- } | |
- ord = malloc(n * sizeof(ord[0])); | |
- for (i = 0; i < n; i++) | |
- ord[i] = i; | |
- if (xorder) | |
- dir_reorder(s, ord); | |
- | |
- if (c2 < c1) | |
- swap(&c1, &c2); | |
- if (!closed) | |
- c2 = ren_next(s, c2, -1); | |
- beg = ren_off(s, c1); | |
- end = ren_off(s, c2); | |
- if (end < beg) | |
- swap(&beg, &end); | |
- o1 = ord[beg]; | |
- o2 = ord[end]; | |
- if (o2 < o1) | |
- swap(&o1, &o2); | |
- for (i = beg; i <= end; i++) | |
- if (ord[i] < o1 || ord[i] > o2) | |
- break; | |
- *l1 = beg; | |
- *l2 = i; | |
- free(ord); | |
- return 0; | |
+ return s && uc_chr(s, ren_off(s, p))[0] != '\n' ? p : -1; | |
} | |
static char *ren_placeholder(char *s) | |
diff --git a/uc.c b/uc.c | |
t@@ -57,7 +57,7 @@ char *uc_beg(char *beg, char *s) | |
} | |
/* find the end of the character at s[i] */ | |
-char *uc_end(char *beg, char *s) | |
+char *uc_end(char *s) | |
{ | |
if (!*s || !((unsigned char) *s & 0x80)) | |
return s; | |
t@@ -71,10 +71,16 @@ char *uc_end(char *beg, char *s) | |
/* return a pointer to the character following s */ | |
char *uc_next(char *s) | |
{ | |
- s = uc_end(s, s); | |
+ s = uc_end(s); | |
return *s ? s + 1 : s; | |
} | |
+/* return a pointer to the character preceding s */ | |
+char *uc_prev(char *beg, char *s) | |
+{ | |
+ return s == beg ? beg : uc_beg(beg, s - 1); | |
+} | |
+ | |
int uc_wid(char *s) | |
{ | |
return 1; | |
t@@ -153,7 +159,7 @@ int uc_isprint(char *s) | |
int uc_isalpha(char *s) | |
{ | |
int c = s ? (unsigned char) *s : 0; | |
- return c <= 0x7f && isalpha(c); | |
+ return c > 0x7f || isalpha(c); | |
} | |
int uc_isdigit(char *s) | |
diff --git a/vi.c b/vi.c | |
t@@ -20,6 +20,7 @@ static int vi_charcmd; /* the character findi… | |
static int vi_arg1, vi_arg2; /* the first and second arguments */ | |
static int vi_ybuf; /* current yank buffer */ | |
static char *vi_kmap; /* current insertion keymap */ | |
+static int vi_pcol; /* the column requested by | command */ | |
static void vi_drawmsg(void) | |
{ | |
t@@ -27,7 +28,7 @@ static void vi_drawmsg(void) | |
vi_msg[0] = '\0'; | |
} | |
-static void vi_draw(void) | |
+static void vi_draw(int xcol) | |
{ | |
int i; | |
term_record(); | |
t@@ -121,108 +122,53 @@ static int vi_prefix(void) | |
return n; | |
} | |
-static int lbuf_lnnext(struct lbuf *lb, int *r, int *c, int dir) | |
+static int vi_col2off(struct lbuf *lb, int row, int col) | |
{ | |
- char *ln = lbuf_get(lb, *r); | |
- int col = ln ? ren_next(ln, *c, dir) : -1; | |
- if (col < 0) | |
- return -1; | |
- *c = col; | |
- return 0; | |
+ char *ln = lbuf_get(lb, row); | |
+ return ln ? ren_off(ln, col) : 0; | |
} | |
-static void lbuf_eol(struct lbuf *lb, int *r, int *c, int dir) | |
+static int vi_off2col(struct lbuf *lb, int row, int off) | |
{ | |
- char *ln = lbuf_get(lb, *r); | |
- *c = dir < 0 ? 0 : MAX(0, ren_wid(ln ? ln : "") - 1); | |
+ char *ln = lbuf_get(lb, row); | |
+ return ln ? ren_pos(ln, off) : 0; | |
} | |
-static int lbuf_next(struct lbuf *lb, int *r, int *c, int dir) | |
+static int vi_nextoff(struct lbuf *lb, int dir, int *row, int *off) | |
{ | |
- if (dir < 0 && *r >= lbuf_len(lb)) | |
- *r = MAX(0, lbuf_len(lb) - 1); | |
- if (lbuf_lnnext(lb, r, c, dir)) { | |
- if (!lbuf_get(lb, *r + dir)) | |
- return -1; | |
- *r += dir; | |
- lbuf_eol(lb, r, c, -dir); | |
- return 0; | |
- } | |
+ int o = *off + dir; | |
+ if (o < 0 || !lbuf_get(lb, *row) || o >= uc_slen(lbuf_get(lb, *row))) | |
+ return 1; | |
+ *off = o; | |
return 0; | |
} | |
-/* return a pointer to the character at visual position c of line r */ | |
-static char *lbuf_chr(struct lbuf *lb, int r, int c) | |
-{ | |
- char *ln = lbuf_get(lb, r); | |
- return ln ? uc_chr(ln, ren_off(ln, c)) : ""; | |
-} | |
- | |
-static void lbuf_postindents(struct lbuf *lb, int *r, int *c) | |
+static int vi_nextcol(struct lbuf *lb, int dir, int *row, int *off) | |
{ | |
- lbuf_eol(lb, r, c, -1); | |
- while (uc_isspace(lbuf_chr(lb, *r, *c))) | |
- if (lbuf_lnnext(lb, r, c, +1)) | |
- break; | |
+ char *ln = lbuf_get(lb, *row); | |
+ int col = ln ? ren_pos(ln, *off) : 0; | |
+ int o = ln ? ren_next(ln, col, dir) : -1; | |
+ if (o < 0) | |
+ return -1; | |
+ *off = ren_off(ln, o); | |
+ return 0; | |
} | |
-static int lbuf_findchar(struct lbuf *lb, int *row, int *col, char *cs, int cm… | |
+static int vi_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *row, in… | |
{ | |
- int dir = (cmd == 'f' || cmd == 't') ? +1 : -1; | |
- int c = *col; | |
- if (n < 0) | |
- dir = -dir; | |
- if (n < 0) | |
- n = -n; | |
strcpy(vi_charlast, cs); | |
vi_charcmd = cmd; | |
- while (n > 0 && !lbuf_lnnext(lb, row, &c, dir)) | |
- if (uc_code(lbuf_chr(lb, *row, c)) == uc_code(cs)) | |
- n--; | |
- if (!n) | |
- *col = c; | |
- if (!n && (cmd == 't' || cmd == 'T')) | |
- lbuf_lnnext(lb, row, col, -dir); | |
- return n != 0; | |
+ return lbuf_findchar(lb, cs, cmd, n, row, off); | |
} | |
-static int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *c, int… | |
-{ | |
- int offs[2]; | |
- int found = 0; | |
- int row = *r, col = *c; | |
- int i; | |
- struct rset *re = rset_make(1, &kw, xic ? RE_ICASE : 0); | |
- if (!re) | |
- return 1; | |
- for (i = row; !found && i >= 0 && i < lbuf_len(lb); i += dir) { | |
- char *s = lbuf_get(lb, i); | |
- int off = dir > 0 && row == i ? uc_chr(s, col + 1) - s : 0; | |
- int flg = off ? RE_NOTBOL : 0; | |
- while (rset_find(re, s + off, 1, offs, flg) >= 0) { | |
- if (dir < 0 && row == i && off + offs[0] >= col) | |
- break; | |
- found = 1; | |
- *c = uc_off(s, off + offs[0]); | |
- *r = i; | |
- *len = offs[1] - offs[0]; | |
- off += offs[1]; | |
- if (dir > 0) | |
- break; | |
- } | |
- } | |
- rset_free(re); | |
- return !found; | |
-} | |
- | |
-static int vi_search(int cmd, int cnt, int *row, int *col) | |
+static int vi_search(int cmd, int cnt, int *row, int *off) | |
{ | |
int r = *row; | |
- int c = *col; | |
+ int o = *off; | |
int failed = 0; | |
int len = 0; | |
int i, dir; | |
- char *off = ""; | |
+ char *soff = ""; | |
if (cmd == '/' || cmd == '?') { | |
char sign[4] = {cmd}; | |
char *kw = vi_prompt(sign, &vi_kmap); | |
t@@ -232,7 +178,7 @@ static int vi_search(int cmd, int cnt, int *row, int *col) | |
if (kw[0]) | |
snprintf(vi_findlast, sizeof(vi_findlast), "%s", kw); | |
if (strchr(vi_findlast, cmd)) { | |
- off = strchr(vi_findlast, cmd) + 1; | |
+ soff = strchr(vi_findlast, cmd) + 1; | |
*strchr(vi_findlast, cmd) = '\0'; | |
} | |
free(kw); | |
t@@ -240,26 +186,26 @@ static int vi_search(int cmd, int cnt, int *row, int *co… | |
dir = cmd == 'N' ? -vi_finddir : vi_finddir; | |
if (!vi_findlast[0] || !lbuf_len(xb)) | |
return 1; | |
- c = ren_off(lbuf_get(xb, *row), *col); | |
+ o = *off; | |
for (i = 0; i < cnt; i++) { | |
- if (lbuf_search(xb, vi_findlast, dir, &r, &c, &len)) { | |
+ if (lbuf_search(xb, vi_findlast, dir, &r, &o, &len)) { | |
failed = 1; | |
break; | |
} | |
if (i + 1 < cnt && cmd == '/') | |
- c += len; | |
+ o += len; | |
} | |
if (!failed) { | |
*row = r; | |
- *col = ren_pos(lbuf_get(xb, r), c); | |
- while (off[0] && isspace((unsigned char) off[0])) | |
- off++; | |
- if (off[0]) { | |
- *col = -1; | |
- if (*row + atoi(off) < 0 || *row + atoi(off) >= lbuf_l… | |
+ *off = o; | |
+ while (soff[0] && isspace((unsigned char) soff[0])) | |
+ soff++; | |
+ if (soff[0]) { | |
+ *off = -1; | |
+ if (*row + atoi(soff) < 0 || *row + atoi(soff) >= lbuf… | |
failed = 1; | |
else | |
- *row += atoi(off); | |
+ *row += atoi(soff); | |
} | |
} | |
if (failed) | |
t@@ -267,77 +213,6 @@ static int vi_search(int cmd, int cnt, int *row, int *col) | |
return failed; | |
} | |
-/* move to the last character of the word */ | |
-static int lbuf_wordlast(struct lbuf *lb, int *row, int *col, int kind, int di… | |
-{ | |
- if (!kind || !(uc_kind(lbuf_chr(lb, *row, *col)) & kind)) | |
- return 0; | |
- while (uc_kind(lbuf_chr(lb, *row, *col)) & kind) | |
- if (lbuf_next(lb, row, col, dir)) | |
- return 1; | |
- if (!(uc_kind(lbuf_chr(lb, *row, *col)) & kind)) | |
- lbuf_next(lb, row, col, -dir); | |
- return 0; | |
-} | |
- | |
-static int lbuf_wordbeg(struct lbuf *lb, int *row, int *col, int big, int dir) | |
-{ | |
- int nl = 0; | |
- lbuf_wordlast(lb, row, col, big ? 3 : uc_kind(lbuf_chr(lb, *row, *col)… | |
- if (lbuf_next(lb, row, col, dir)) | |
- return 1; | |
- while (uc_isspace(lbuf_chr(lb, *row, *col))) { | |
- nl = uc_code(lbuf_chr(lb, *row, *col)) == '\n' ? nl + 1 : 0; | |
- if (nl == 2) | |
- return 0; | |
- if (lbuf_next(lb, row, col, dir)) | |
- return 1; | |
- } | |
- return 0; | |
-} | |
- | |
-static int lbuf_wordend(struct lbuf *lb, int *row, int *col, int big, int dir) | |
-{ | |
- int nl = uc_code(lbuf_chr(lb, *row, *col)) == '\n' ? -1 : 0; | |
- if (!uc_isspace(lbuf_chr(lb, *row, *col))) | |
- if (lbuf_next(lb, row, col, dir)) | |
- return 1; | |
- while (uc_isspace(lbuf_chr(lb, *row, *col))) { | |
- nl = uc_code(lbuf_chr(lb, *row, *col)) == '\n' ? nl + 1 : 0; | |
- if (nl == 2) { | |
- if (dir < 0) | |
- lbuf_next(lb, row, col, -dir); | |
- return 0; | |
- } | |
- if (lbuf_next(lb, row, col, dir)) | |
- return 1; | |
- } | |
- if (lbuf_wordlast(lb, row, col, big ? 3 : uc_kind(lbuf_chr(lb, *row, *… | |
- return 1; | |
- return 0; | |
-} | |
- | |
-static int lbuf_paragraphbeg(struct lbuf *lb, int *row, int *col, int dir) | |
-{ | |
- while (*row >= 0 && *row < lbuf_len(lb) && !strcmp("\n", lbuf_get(lb, … | |
- *row += dir; | |
- while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *… | |
- *row += dir; | |
- *row = MAX(0, MIN(*row, lbuf_len(lb) - 1)); | |
- lbuf_eol(lb, row, col, -1); | |
- return 0; | |
-} | |
- | |
-static int lbuf_sectionbeg(struct lbuf *lb, int *row, int *col, int dir) | |
-{ | |
- *row += dir; | |
- while (*row >= 0 && *row < lbuf_len(lb) && lbuf_get(lb, *row)[0] != '{… | |
- *row += dir; | |
- *row = MAX(0, MIN(*row, lbuf_len(lb) - 1)); | |
- lbuf_eol(lb, row, col, -1); | |
- return 0; | |
-} | |
- | |
/* read a line motion */ | |
static int vi_motionln(int *row, int cmd) | |
{ | |
t@@ -356,9 +231,11 @@ static int vi_motionln(int *row, int cmd) | |
*row = MIN(*row + cnt - 1, lbuf_len(xb) - 1); | |
break; | |
case '\'': | |
- if ((mark = vi_read()) > 0 && (isalpha(mark) || mark == '\'')) | |
- if (lbuf_markpos(xb, mark) >= 0) | |
- *row = lbuf_markpos(xb, mark); | |
+ if ((mark = vi_read()) <= 0 || (!isalpha(mark) && mark != '\''… | |
+ return -1; | |
+ if (lbuf_markpos(xb, mark) < 0) | |
+ return -1; | |
+ *row = lbuf_markpos(xb, mark); | |
break; | |
case 'j': | |
*row = MIN(*row + cnt, lbuf_len(xb) - 1); | |
t@@ -398,14 +275,14 @@ static int vi_motionln(int *row, int cmd) | |
return c; | |
} | |
-static char *lbuf_curword(struct lbuf *lb, int row, int col) | |
+static char *vi_curword(struct lbuf *lb, int row, int off) | |
{ | |
struct sbuf *sb; | |
char *ln = lbuf_get(lb, row); | |
char *beg, *end; | |
if (!ln) | |
return NULL; | |
- beg = uc_chr(ln, ren_off(ln, ren_noeol(ln, col))); | |
+ beg = uc_chr(ln, ren_noeol(ln, off)); | |
end = beg; | |
while (*end && uc_kind(end) == 1) | |
end = uc_next(end); | |
t@@ -421,7 +298,7 @@ static char *lbuf_curword(struct lbuf *lb, int row, int co… | |
} | |
/* read a motion */ | |
-static int vi_motion(int *row, int *col) | |
+static int vi_motion(int *row, int *off) | |
{ | |
int cnt = (vi_arg1 ? vi_arg1 : 1) * (vi_arg2 ? vi_arg2 : 1); | |
char *ln = lbuf_get(xb, *row); | |
t@@ -430,157 +307,158 @@ static int vi_motion(int *row, int *col) | |
int mv; | |
int i; | |
if ((mv = vi_motionln(row, 0))) { | |
- *col = -1; | |
+ *off = -1; | |
return mv; | |
} | |
mv = vi_read(); | |
switch (mv) { | |
- case ' ': | |
- for (i = 0; i < cnt; i++) | |
- if (lbuf_lnnext(xb, row, col, 1)) | |
- break; | |
- break; | |
case 'f': | |
if (!(cs = vi_char())) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, cs, mv, cnt)) | |
+ if (vi_findchar(xb, cs, mv, cnt, row, off)) | |
return -1; | |
break; | |
case 'F': | |
if (!(cs = vi_char())) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, cs, mv, cnt)) | |
+ if (vi_findchar(xb, cs, mv, cnt, row, off)) | |
return -1; | |
break; | |
case ';': | |
if (!vi_charlast[0]) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, cnt)) | |
+ if (vi_findchar(xb, vi_charlast, vi_charcmd, cnt, row, off)) | |
return -1; | |
break; | |
case ',': | |
if (!vi_charlast[0]) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, -cnt)) | |
+ if (vi_findchar(xb, vi_charlast, vi_charcmd, -cnt, row, off)) | |
return -1; | |
break; | |
case 'h': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_lnnext(xb, row, col, -1 * dir)) | |
+ if (vi_nextcol(xb, -1 * dir, row, off)) | |
break; | |
break; | |
case 'l': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_lnnext(xb, row, col, +1 * dir)) | |
+ if (vi_nextcol(xb, +1 * dir, row, off)) | |
break; | |
break; | |
case 't': | |
if (!(cs = vi_char())) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, cs, mv, cnt)) | |
+ if (vi_findchar(xb, cs, mv, cnt, row, off)) | |
return -1; | |
break; | |
case 'T': | |
if (!(cs = vi_char())) | |
return -1; | |
- if (lbuf_findchar(xb, row, col, cs, mv, cnt)) | |
+ if (vi_findchar(xb, cs, mv, cnt, row, off)) | |
return -1; | |
break; | |
case 'B': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordend(xb, row, col, 1, -1)) | |
+ if (lbuf_wordend(xb, 1, -1, row, off)) | |
break; | |
break; | |
case 'E': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordend(xb, row, col, 1, +1)) | |
+ if (lbuf_wordend(xb, 1, +1, row, off)) | |
break; | |
break; | |
case 'W': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordbeg(xb, row, col, 1, +1)) | |
+ if (lbuf_wordbeg(xb, 1, +1, row, off)) | |
break; | |
break; | |
case 'b': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordend(xb, row, col, 0, -1)) | |
+ if (lbuf_wordend(xb, 0, -1, row, off)) | |
break; | |
break; | |
case 'e': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordend(xb, row, col, 0, +1)) | |
+ if (lbuf_wordend(xb, 0, +1, row, off)) | |
break; | |
break; | |
case 'w': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_wordbeg(xb, row, col, 0, +1)) | |
+ if (lbuf_wordbeg(xb, 0, +1, row, off)) | |
break; | |
break; | |
case '{': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_paragraphbeg(xb, row, col, -1)) | |
+ if (lbuf_paragraphbeg(xb, -1, row, off)) | |
break; | |
break; | |
case '}': | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_paragraphbeg(xb, row, col, +1)) | |
+ if (lbuf_paragraphbeg(xb, +1, row, off)) | |
break; | |
break; | |
case '[': | |
if (vi_read() != '[') | |
return -1; | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_sectionbeg(xb, row, col, -1)) | |
+ if (lbuf_sectionbeg(xb, -1, row, off)) | |
break; | |
break; | |
case ']': | |
if (vi_read() != ']') | |
return -1; | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_sectionbeg(xb, row, col, +1)) | |
+ if (lbuf_sectionbeg(xb, +1, row, off)) | |
break; | |
break; | |
case '0': | |
- lbuf_eol(xb, row, col, -1); | |
+ *off = 0; | |
break; | |
case '^': | |
- lbuf_postindents(xb, row, col); | |
+ *off = lbuf_indents(xb, *row); | |
break; | |
case '$': | |
- *col = 1024; | |
+ *off = lbuf_eol(xb, *row); | |
break; | |
case '|': | |
- *col = cnt - 1; | |
+ *off = vi_col2off(xb, *row, cnt - 1); | |
+ vi_pcol = cnt - 1; | |
break; | |
case '/': | |
- if (vi_search(mv, cnt, row, col)) | |
+ if (vi_search(mv, cnt, row, off)) | |
return -1; | |
break; | |
case '?': | |
- if (vi_search(mv, cnt, row, col)) | |
+ if (vi_search(mv, cnt, row, off)) | |
return -1; | |
break; | |
case 'n': | |
- if (vi_search(mv, cnt, row, col)) | |
+ if (vi_search(mv, cnt, row, off)) | |
return -1; | |
break; | |
case 'N': | |
- if (vi_search(mv, cnt, row, col)) | |
+ if (vi_search(mv, cnt, row, off)) | |
return -1; | |
break; | |
case TK_CTL('a'): | |
- if (!(cs = lbuf_curword(xb, *row, *col))) | |
+ if (!(cs = vi_curword(xb, *row, *off))) | |
return -1; | |
strcpy(vi_findlast, cs); | |
free(cs); | |
vi_finddir = +1; | |
- if (vi_search('n', cnt, row, col)) | |
+ if (vi_search('n', cnt, row, off)) | |
return -1; | |
break; | |
+ case ' ': | |
+ for (i = 0; i < cnt; i++) | |
+ if (vi_nextoff(xb, +1, row, off)) | |
+ break; | |
+ break; | |
case 127: | |
case TK_CTL('h'): | |
for (i = 0; i < cnt; i++) | |
- if (lbuf_lnnext(xb, row, col, -1)) | |
+ if (vi_nextoff(xb, -1, row, off)) | |
break; | |
break; | |
default: | |
t@@ -597,15 +475,15 @@ static void swap(int *a, int *b) | |
*b = t; | |
} | |
-static char *lbuf_region(struct lbuf *lb, int r1, int l1, int r2, int l2) | |
+static char *lbuf_region(struct lbuf *lb, int r1, int o1, int r2, int o2) | |
{ | |
struct sbuf *sb; | |
char *s1, *s2, *s3; | |
if (r1 == r2) | |
- return uc_sub(lbuf_get(lb, r1), l1, l2); | |
+ return uc_sub(lbuf_get(lb, r1), o1, o2); | |
sb = sbuf_make(); | |
- s1 = uc_sub(lbuf_get(lb, r1), l1, -1); | |
- s3 = uc_sub(lbuf_get(lb, r2), 0, l2); | |
+ s1 = uc_sub(lbuf_get(lb, r1), o1, -1); | |
+ s3 = uc_sub(lbuf_get(lb, r2), 0, o2); | |
s2 = lbuf_cp(lb, r1 + 1, r2); | |
sbuf_str(sb, s1); | |
sbuf_str(sb, s2); | |
t@@ -616,53 +494,25 @@ static char *lbuf_region(struct lbuf *lb, int r1, int l1… | |
return sbuf_done(sb); | |
} | |
-/* insertion offset before or after the given visual position */ | |
-static int vi_insertionoffset(char *s, int c1, int before) | |
-{ | |
- int l; | |
- if (!s || !*s) | |
- return 0; | |
- l = ren_off(s, c1); | |
- return before || s[l] == '\n' ? l : l + 1; | |
-} | |
- | |
-static void vi_commandregion(int *r1, int *r2, int *c1, int *c2, int *l1, int … | |
-{ | |
- if (*r2 < *r1 || (*r2 == *r1 && *c2 < *c1)) { | |
- swap(r1, r2); | |
- swap(c1, c2); | |
- } | |
- *l1 = vi_insertionoffset(lbuf_get(xb, *r1), *c1, 1); | |
- *l2 = vi_insertionoffset(lbuf_get(xb, *r2), *c2, !closed); | |
- if (*r1 == *r2 && lbuf_get(xb, *r1)) | |
- ren_region(lbuf_get(xb, *r1), *c1, *c2, l1, l2, closed); | |
- if (*r1 == *r2 && *l2 < *l1) | |
- swap(l1, l2); | |
-} | |
- | |
-static void vi_yank(int r1, int c1, int r2, int c2, int lnmode, int closed) | |
+static void vi_yank(int r1, int o1, int r2, int o2, int lnmode) | |
{ | |
char *region; | |
- int l1, l2; | |
- vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed); | |
- region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2); | |
+ region = lbuf_region(xb, r1, lnmode ? 0 : o1, r2, lnmode ? -1 : o2); | |
reg_put(vi_ybuf, region, lnmode); | |
free(region); | |
xrow = r1; | |
- xcol = lnmode ? xcol : c1; | |
+ xoff = lnmode ? xoff : o1; | |
} | |
-static void vi_delete(int r1, int c1, int r2, int c2, int lnmode, int closed) | |
+static void vi_delete(int r1, int o1, int r2, int o2, int lnmode) | |
{ | |
char *pref, *post; | |
char *region; | |
- int l1, l2; | |
- vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed); | |
- region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2); | |
+ region = lbuf_region(xb, r1, lnmode ? 0 : o1, r2, lnmode ? -1 : o2); | |
reg_put(vi_ybuf, region, lnmode); | |
free(region); | |
- pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1); | |
- post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1); | |
+ pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, o1); | |
+ post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -1); | |
lbuf_rm(xb, r1, r2 + 1); | |
if (!lnmode) { | |
struct sbuf *sb = sbuf_make(); | |
t@@ -672,9 +522,7 @@ static void vi_delete(int r1, int c1, int r2, int c2, int … | |
sbuf_free(sb); | |
} | |
xrow = r1; | |
- xcol = c1; | |
- if (lnmode) | |
- lbuf_postindents(xb, &xrow, &xcol); | |
+ xoff = lnmode ? lbuf_indents(xb, xrow) : o1; | |
free(pref); | |
free(post); | |
} | |
t@@ -697,12 +545,12 @@ static int indentscopy(char *d, char *s, int len) | |
return i; | |
} | |
-static char *vi_input(char *pref, char *post, int *row, int *col) | |
+static char *vi_input(char *pref, char *post, int *row, int *off) | |
{ | |
char ai[64] = ""; | |
char *rep, *s; | |
struct sbuf *sb; | |
- int last, off; | |
+ int last; | |
if (xai) | |
pref += indentscopy(ai, pref, sizeof(ai)); | |
rep = led_input(pref, post, ai, xai ? sizeof(ai) - 1 : 0, &vi_kmap); | |
t@@ -714,13 +562,12 @@ static char *vi_input(char *pref, char *post, int *row, … | |
sbuf_str(sb, rep); | |
s = sbuf_buf(sb); | |
last = uc_lastline(s) - s; | |
- off = uc_slen(sbuf_buf(sb) + last); | |
+ *off = MAX(0, uc_slen(sbuf_buf(sb) + last) - 1); | |
if (last) | |
while (xai && (post[0] == ' ' || post[0] == '\t')) | |
post++; | |
sbuf_str(sb, post); | |
*row = linecount(sbuf_buf(sb)) - 1; | |
- *col = ren_pos(sbuf_buf(sb) + last, MAX(0, off - 1)); | |
free(rep); | |
return sbuf_done(sb); | |
} | |
t@@ -733,25 +580,23 @@ static char *vi_indents(char *ln) | |
return sbuf_done(sb); | |
} | |
-static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed) | |
+static void vi_change(int r1, int o1, int r2, int o2, int lnmode) | |
{ | |
char *region; | |
- int l1, l2; | |
- int row, col; | |
+ int row, off; | |
char *rep; | |
char *pref, *post; | |
- vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed); | |
- region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2); | |
+ region = lbuf_region(xb, r1, lnmode ? 0 : o1, r2, lnmode ? -1 : o2); | |
reg_put(vi_ybuf, region, lnmode); | |
free(region); | |
- pref = lnmode ? vi_indents(lbuf_get(xb, r1)) : uc_sub(lbuf_get(xb, r1)… | |
- post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1); | |
- rep = vi_input(pref, post, &row, &col); | |
+ pref = lnmode ? vi_indents(lbuf_get(xb, r1)) : uc_sub(lbuf_get(xb, r1)… | |
+ post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -1); | |
+ rep = vi_input(pref, post, &row, &off); | |
if (rep) { | |
lbuf_rm(xb, r1, r2 + 1); | |
lbuf_put(xb, r1, rep); | |
xrow = r1 + row - 1; | |
- xcol = col; | |
+ xoff = off; | |
free(rep); | |
} | |
free(pref); | |
t@@ -766,8 +611,6 @@ static void vi_pipe(int r1, int r2) | |
char *cmd = vi_prompt("!", &kmap); | |
if (!cmd) | |
return; | |
- if (r2 < r1) | |
- swap(&r1, &r2); | |
text = lbuf_cp(xb, r1, r2 + 1); | |
rep = cmd_pipe(cmd, text); | |
if (rep) { | |
t@@ -784,8 +627,6 @@ static void vi_shift(int r1, int r2, int dir) | |
struct sbuf *sb; | |
char *ln; | |
int i; | |
- if (r2 < r1) | |
- swap(&r1, &r2); | |
for (i = r1; i <= r2; i++) { | |
if (!(ln = lbuf_get(xb, i))) | |
continue; | |
t@@ -800,42 +641,49 @@ static void vi_shift(int r1, int r2, int dir) | |
sbuf_free(sb); | |
} | |
xrow = r1; | |
- lbuf_postindents(xb, &xrow, &xcol); | |
+ xoff = lbuf_indents(xb, xrow); | |
} | |
static int vc_motion(int cmd) | |
{ | |
int r1 = xrow, r2 = xrow; /* region rows */ | |
- int c1 = xcol, c2 = xcol; /* visual region columns */ | |
+ int o1 = xoff, o2 = xoff; /* visual region columns */ | |
int lnmode = 0; /* line-based region */ | |
- int closed = 1; /* include the last character */ | |
int mv; | |
vi_arg2 = vi_prefix(); | |
if (vi_arg2 < 0) | |
return 1; | |
- c1 = ren_noeol(lbuf_get(xb, r1), xcol); | |
- c2 = c1; | |
+ o1 = ren_noeol(lbuf_get(xb, r1), o1); | |
+ o2 = o1; | |
if ((mv = vi_motionln(&r2, cmd))) { | |
- c2 = -1; | |
- } else if (!(mv = vi_motion(&r2, &c2))) { | |
+ o2 = -1; | |
+ } else if (!(mv = vi_motion(&r2, &o2))) { | |
vi_read(); | |
return 1; | |
} | |
if (mv < 0) | |
return 1; | |
- if (!strchr("fFtTeE", mv)) | |
- closed = 0; | |
- lnmode = c2 < 0; | |
+ lnmode = o2 < 0; | |
if (lnmode) { | |
- lbuf_eol(xb, &r1, &c1, -1); | |
- lbuf_eol(xb, &r2, &c2, +1); | |
+ o1 = 0; | |
+ o2 = lbuf_eol(xb, r2); | |
} | |
+ if (r1 > r2) { | |
+ swap(&r1, &r2); | |
+ swap(&o1, &o2); | |
+ } | |
+ if (r1 == r2 && o1 > o2) | |
+ swap(&o1, &o2); | |
+ o1 = ren_noeol(lbuf_get(xb, r1), o1); | |
+ if (!lnmode && strchr("fFtTeE", mv)) | |
+ if (o2 < lbuf_eol(xb, r2)) | |
+ o2 = ren_noeol(lbuf_get(xb, r2), o2) + 1; | |
if (cmd == 'y') | |
- vi_yank(r1, c1, r2, c2, lnmode, closed); | |
+ vi_yank(r1, o1, r2, o2, lnmode); | |
if (cmd == 'd') | |
- vi_delete(r1, c1, r2, c2, lnmode, closed); | |
+ vi_delete(r1, o1, r2, o2, lnmode); | |
if (cmd == 'c') | |
- vi_change(r1, c1, r2, c2, lnmode, closed); | |
+ vi_change(r1, o1, r2, o2, lnmode); | |
if (cmd == '!') | |
vi_pipe(r1, r2); | |
if (cmd == '>' || cmd == '<') | |
t@@ -847,24 +695,22 @@ static int vc_insert(int cmd) | |
{ | |
char *pref, *post; | |
char *ln = lbuf_get(xb, xrow); | |
- int row, col, off = 0; | |
+ int row, off = 0; | |
char *rep; | |
if (cmd == 'I') | |
- lbuf_postindents(xb, &xrow, &xcol); | |
- if (cmd == 'A') { | |
- lbuf_eol(xb, &xrow, &xcol, +1); | |
- lbuf_lnnext(xb, &xrow, &xcol, -1); | |
- } | |
- xcol = ren_noeol(ln, xcol); | |
+ xoff = lbuf_indents(xb, xrow); | |
+ if (cmd == 'A') | |
+ xoff = lbuf_eol(xb, xrow); | |
+ xoff = ren_noeol(ln, xoff); | |
if (cmd == 'o') | |
xrow += 1; | |
if (cmd == 'i' || cmd == 'I') | |
- off = vi_insertionoffset(ln, xcol, 1); | |
+ off = xoff; | |
if (cmd == 'a' || cmd == 'A') | |
- off = vi_insertionoffset(ln, xcol, 0); | |
+ off = xoff + 1; | |
pref = ln && cmd != 'o' && cmd != 'O' ? uc_sub(ln, 0, off) : vi_indent… | |
post = ln && cmd != 'o' && cmd != 'O' ? uc_sub(ln, off, -1) : uc_dup("… | |
- rep = vi_input(pref, post, &row, &col); | |
+ rep = vi_input(pref, post, &row, &off); | |
if ((cmd == 'o' || cmd == 'O') && !lbuf_len(xb)) | |
lbuf_put(xb, 0, "\n"); | |
if (rep) { | |
t@@ -872,7 +718,7 @@ static int vc_insert(int cmd) | |
lbuf_rm(xb, xrow, xrow + 1); | |
lbuf_put(xb, xrow, rep); | |
xrow += row - 1; | |
- xcol = col; | |
+ xoff = off; | |
free(rep); | |
} | |
free(pref); | |
t@@ -892,7 +738,7 @@ static int vc_put(int cmd) | |
if (!buf) | |
return 1; | |
ln = lnmode ? NULL : lbuf_get(xb, xrow); | |
- off = vi_insertionoffset(ln, ren_noeol(ln, xcol), cmd == 'P'); | |
+ off = ren_noeol(ln, xoff) + (cmd == 'p'); | |
if (cmd == 'p' && !ln) | |
xrow++; | |
sb = sbuf_make(); | |
t@@ -914,9 +760,9 @@ static int vc_put(int cmd) | |
lbuf_rm(xb, xrow, xrow + 1); | |
lbuf_put(xb, xrow, sbuf_buf(sb)); | |
if (ln) | |
- xcol = ren_pos(lbuf_get(xb, xrow), off + uc_slen(buf) * cnt - … | |
+ xoff = off + uc_slen(buf) * cnt - 1; | |
else | |
- lbuf_postindents(xb, &xrow, &xcol); | |
+ xoff = lbuf_indents(xb, xrow); | |
sbuf_free(sb); | |
return 0; | |
} | |
t@@ -958,7 +804,7 @@ static int vc_join(void) | |
sbuf_chr(sb, '\n'); | |
lbuf_rm(xb, beg, end); | |
lbuf_put(xb, beg, sbuf_buf(sb)); | |
- xcol = ren_pos(sbuf_buf(sb), off); | |
+ xoff = off; | |
sbuf_free(sb); | |
return 0; | |
} | |
t@@ -983,10 +829,10 @@ static int vi_scrollbackward(int cnt) | |
static void vc_status(void) | |
{ | |
- int pos = ren_noeol(lbuf_get(xb, xrow), xcol); | |
+ int col = vi_off2col(xb, xrow, xoff); | |
snprintf(vi_msg, sizeof(vi_msg), "\"%s\" line %d of %d, col %d\n", | |
xpath[0] ? xpath : "unnamed", xrow + 1, lbuf_len(xb), | |
- ren_cursor(lbuf_get(xb, xrow), pos) + 1); | |
+ ren_cursor(lbuf_get(xb, xrow), col) + 1); | |
} | |
static int vc_replace(void) | |
t@@ -1000,7 +846,7 @@ static int vc_replace(void) | |
int off, i; | |
if (!ln || !cs) | |
return 1; | |
- off = ren_off(ln, ren_noeol(ln, xcol)); | |
+ off = ren_noeol(ln, xoff); | |
s = uc_chr(ln, off); | |
for (i = 0; s[0] != '\n' && i < cnt; i++) | |
s = uc_next(s); | |
t@@ -1016,7 +862,7 @@ static int vc_replace(void) | |
lbuf_rm(xb, xrow, xrow + 1); | |
lbuf_put(xb, xrow, sbuf_buf(sb)); | |
off += cnt - 1; | |
- xcol = ren_pos(sbuf_buf(sb), off); | |
+ xoff = off; | |
sbuf_free(sb); | |
free(pref); | |
free(post); | |
t@@ -1025,19 +871,21 @@ static int vc_replace(void) | |
static void vi(void) | |
{ | |
+ int xcol; | |
int mark; | |
char *ln; | |
char *kmap = NULL; | |
term_init(); | |
xtop = 0; | |
xrow = 0; | |
- lbuf_eol(xb, &xrow, &xcol, -1); | |
- vi_draw(); | |
+ xoff = 0; | |
+ xcol = vi_off2col(xb, xrow, xoff); | |
+ vi_draw(xcol); | |
term_pos(xrow, led_pos(lbuf_get(xb, xrow), xcol)); | |
while (!xquit) { | |
int redraw = 0; | |
int nrow = xrow; | |
- int ncol = ren_noeol(lbuf_get(xb, xrow), xcol); | |
+ int noff = ren_noeol(lbuf_get(xb, xrow), xoff); | |
int otop = xtop; | |
int mv, n; | |
vi_arg2 = 0; | |
t@@ -1045,20 +893,20 @@ static void vi(void) | |
vi_arg1 = vi_prefix(); | |
if (!vi_ybuf) | |
vi_ybuf = vi_yankbuf(); | |
- mv = vi_motion(&nrow, &ncol); | |
+ mv = vi_motion(&nrow, &noff); | |
if (mv > 0) { | |
- if (strchr("\'GHML/?{}[]", mv)) | |
+ if (strchr("\'GHML/?{}[]nN", mv)) | |
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), n… | |
- } | |
+ if (noff < 0 && !strchr("jk", mv)) | |
+ noff = lbuf_indents(xb, xrow); | |
+ if (strchr("jk", mv)) | |
+ noff = vi_col2off(xb, xrow, xcol); | |
+ xoff = noff; | |
+ if (!strchr("|jk", mv)) | |
+ xcol = vi_off2col(xb, xrow, noff); | |
+ if (mv == '|') | |
+ xcol = vi_pcol; | |
} else if (mv == 0) { | |
int c = vi_read(); | |
int z; | |
t@@ -1068,13 +916,13 @@ static void vi(void) | |
case TK_CTL('b'): | |
if (vi_scrollbackward(MAX(1, vi_arg1) * (xrows… | |
break; | |
- lbuf_postindents(xb, &xrow, &xcol); | |
+ xoff = lbuf_indents(xb, xrow); | |
redraw = 1; | |
break; | |
case TK_CTL('f'): | |
if (vi_scrollforeward(MAX(1, vi_arg1) * (xrows… | |
break; | |
- lbuf_postindents(xb, &xrow, &xcol); | |
+ xoff = lbuf_indents(xb, xrow); | |
redraw = 1; | |
break; | |
case TK_CTL('e'): | |
t@@ -1219,8 +1067,11 @@ static void vi(void) | |
if (xtop + xrows <= xrow) | |
xtop = xtop + xrows + xrows / 2 <= xrow ? | |
xrow - xrows / 2 : xrow - xrows + 1; | |
+ xoff = ren_noeol(lbuf_get(xb, xrow), xoff); | |
+ if (redraw) | |
+ xcol = vi_off2col(xb, xrow, xoff); | |
if (redraw || xtop != otop) | |
- vi_draw(); | |
+ vi_draw(xcol); | |
if (vi_msg[0]) | |
vi_drawmsg(); | |
term_pos(xrow - xtop, led_pos(lbuf_get(xb, xrow), | |
diff --git a/vi.h b/vi.h | |
t@@ -21,6 +21,15 @@ void lbuf_undo(struct lbuf *lbuf); | |
void lbuf_redo(struct lbuf *lbuf); | |
void lbuf_undomark(struct lbuf *lbuf); | |
void lbuf_undofree(struct lbuf *lbuf); | |
+int lbuf_indents(struct lbuf *lb, int r); | |
+int lbuf_eol(struct lbuf *lb, int r); | |
+/* motions */ | |
+int lbuf_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *r, int *o); | |
+int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *o, int *len); | |
+int lbuf_paragraphbeg(struct lbuf *lb, int dir, int *row, int *off); | |
+int lbuf_sectionbeg(struct lbuf *lb, int dir, int *row, int *off); | |
+int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off); | |
+int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off); | |
/* string buffer, variable-sized string */ | |
struct sbuf *sbuf_make(void); | |
t@@ -83,8 +92,9 @@ int uc_isalpha(char *s); | |
int uc_kind(char *c); | |
char **uc_chop(char *s, int *n); | |
char *uc_next(char *s); | |
+char *uc_prev(char *beg, char *s); | |
char *uc_beg(char *beg, char *s); | |
-char *uc_end(char *beg, char *s); | |
+char *uc_end(char *s); | |
char *uc_shape(char *beg, char *s); | |
char *uc_lastline(char *s); | |
t@@ -130,7 +140,7 @@ char *cmd_pipe(char *cmd, char *s); | |
#define SYN_BD 0x100 | |
#define SYN_IT 0x200 | |
#define SYN_RV 0x400 | |
-#define SYN_ATTR(f, b) (((b) << 16) | (f)) | |
+#define SYN_BGMK(b) ((b) << 16) | |
#define SYN_FG(a) ((a) & 0xffff) | |
#define SYN_BG(a) ((a) >> 16) | |
t@@ -153,7 +163,7 @@ int conf_filetype(int idx, char **ft, char **pat); | |
extern int xvis; | |
extern struct lbuf *xb; | |
extern int xrow; | |
-extern int xcol; | |
+extern int xoff; | |
extern int xtop; | |
extern int xled; | |
extern int xrow_alt; |