tvi: rely on line offset instead of column number - 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 bdbc8d37c53bd7702979786c58354bbf2ef6990e
(DIR) parent 2dc24f819262d48c8a7f6b2d1ce6a7fe992b4310
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
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(-)
---
(DIR) 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
(DIR) 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);
(DIR) 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 *off)
+{
+ 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)))
+ *row += dir;
+ while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *row)))
+ *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 *off)
+{
+ 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, 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)
+ 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, row, off))
+ return 1;
+ return 0;
+}
(DIR) 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 screen */
- 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)
(DIR) 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)
(DIR) diff --git a/vi.c b/vi.c
t@@ -20,6 +20,7 @@ static int vi_charcmd; /* the character finding command */
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 cmd, int n)
+static int vi_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *row, int *off)
{
- 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 *len)
-{
- 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 *col)
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_len(xb))
+ *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_len(xb))
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 dir)
-{
- 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)), dir);
- 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, *col)), dir))
- 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)))
- *row += dir;
- while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *row)))
- *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 col)
}
/* 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, int r2, int l2)
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 *l2, int closed)
-{
- 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 lnmode, int closed)
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, int *col)
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), 0, l1);
- 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), 0, o1);
+ 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_indents(ln);
post = ln && cmd != 'o' && cmd != 'O' ? uc_sub(ln, off, -1) : uc_dup("\n");
- 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 - 1);
+ 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), ncol);
- }
+ 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 - 1)))
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 - 1)))
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),
(DIR) 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;