summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2016-10-17 17:19:09 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2016-10-17 17:19:09 +0000
commite61386490fa7a28320b137657136ce4550bfe91c (patch)
treea31e1adb6a01ea9e85b187d2b26d450f92aa6e9d /bin
parent2873a1e3c73c06c265b58eade4dddc1e3043e002 (diff)
Make sure the cursor goes to the first byte of a UTF-8 character
and not to a continuation byte for these commands: b B e E w W | Let {e,E}ndword return the position after the word because that is easier to handle in the caller. OK tb@ czarkoff@
Diffstat (limited to 'bin')
-rw-r--r--bin/ksh/vi.c140
1 files changed, 78 insertions, 62 deletions
diff --git a/bin/ksh/vi.c b/bin/ksh/vi.c
index 56260197978..ccef8777462 100644
--- a/bin/ksh/vi.c
+++ b/bin/ksh/vi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vi.c,v 1.40 2016/10/11 19:52:54 schwarze Exp $ */
+/* $OpenBSD: vi.c,v 1.41 2016/10/17 17:19:08 schwarze Exp $ */
/*
* vi command editing
@@ -708,7 +708,8 @@ vi_cmd(int argcnt, const char *cmd)
if (is_move(*cmd)) {
if ((cur = domove(argcnt, cmd, 0)) >= 0) {
if (cur == es->linelen && cur != 0)
- cur--;
+ while (isu8cont(es->cbuf[--cur]))
+ continue;
es->cursor = cur;
} else
return -1;
@@ -1180,19 +1181,13 @@ domove(int argcnt, const char *cmd, int sub)
break;
case 'e':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- ncursor = endword(argcnt);
- if (sub && ncursor < es->linelen)
- ncursor++;
- break;
-
case 'E':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
- ncursor = Endword(argcnt);
- if (sub && ncursor < es->linelen)
- ncursor++;
+ ncursor = (*cmd == 'e' ? endword : Endword)(argcnt);
+ if (!sub)
+ while (isu8cont((unsigned char)es->cbuf[--ncursor]))
+ continue;
break;
case 'f':
@@ -1266,6 +1261,8 @@ domove(int argcnt, const char *cmd, int sub)
ncursor = es->linelen;
if (ncursor)
ncursor--;
+ while (isu8cont(es->cbuf[ncursor]))
+ ncursor--;
break;
case '$':
@@ -1526,80 +1523,100 @@ findch(int ch, int cnt, int forw, int incl)
return ncursor;
}
+/* Move right one character, and then to the beginning of the next word. */
static int
forwword(int argcnt)
{
- int ncursor;
+ int ncursor, skip_space, want_letnum;
+ unsigned char uc;
ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
- if (letnum(es->cbuf[ncursor]))
- while (letnum(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
- ncursor++;
- else if (!isspace((unsigned char)es->cbuf[ncursor]))
- while (!letnum(es->cbuf[ncursor]) &&
- !isspace((unsigned char)es->cbuf[ncursor]) &&
- ncursor < es->linelen)
- ncursor++;
- while (isspace((unsigned char)es->cbuf[ncursor]) &&
- ncursor < es->linelen)
- ncursor++;
+ skip_space = 0;
+ want_letnum = -1;
+ ncursor--;
+ while (++ncursor < es->linelen) {
+ uc = es->cbuf[ncursor];
+ if (isspace(uc)) {
+ skip_space = 1;
+ continue;
+ } else if (skip_space)
+ break;
+ if (uc & 0x80)
+ continue;
+ if (want_letnum == -1)
+ want_letnum = letnum(uc);
+ else if (want_letnum != letnum(uc))
+ break;
+ }
}
return ncursor;
}
+/* Move left one character, and then to the beginning of the word. */
static int
backword(int argcnt)
{
- int ncursor;
+ int ncursor, skip_space, want_letnum;
+ unsigned char uc;
ncursor = es->cursor;
while (ncursor > 0 && argcnt--) {
- while (--ncursor > 0 && isspace((unsigned char)es->cbuf[ncursor]))
- ;
- if (ncursor > 0) {
- if (letnum(es->cbuf[ncursor]))
- while (--ncursor >= 0 &&
- letnum(es->cbuf[ncursor]))
- ;
- else
- while (--ncursor >= 0 &&
- !letnum(es->cbuf[ncursor]) &&
- !isspace((unsigned char)es->cbuf[ncursor]))
- ;
- ncursor++;
+ skip_space = 1;
+ want_letnum = -1;
+ while (ncursor-- > 0) {
+ uc = es->cbuf[ncursor];
+ if (isspace(uc)) {
+ if (skip_space)
+ continue;
+ else
+ break;
+ }
+ skip_space = 0;
+ if (uc & 0x80)
+ continue;
+ if (want_letnum == -1)
+ want_letnum = letnum(uc);
+ else if (want_letnum != letnum(uc))
+ break;
}
+ ncursor++;
}
return ncursor;
}
+/* Move right one character, and then to the byte after the word. */
static int
endword(int argcnt)
{
- int ncursor;
+ int ncursor, skip_space, want_letnum;
+ unsigned char uc;
ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
- while (++ncursor < es->linelen - 1 &&
- isspace((unsigned char)es->cbuf[ncursor]))
- ;
- if (ncursor < es->linelen - 1) {
- if (letnum(es->cbuf[ncursor]))
- while (++ncursor < es->linelen &&
- letnum(es->cbuf[ncursor]))
- ;
- else
- while (++ncursor < es->linelen &&
- !letnum(es->cbuf[ncursor]) &&
- !isspace((unsigned char)es->cbuf[ncursor]))
- ;
- ncursor--;
+ skip_space = 1;
+ want_letnum = -1;
+ while (++ncursor < es->linelen) {
+ uc = es->cbuf[ncursor];
+ if (isspace(uc)) {
+ if (skip_space)
+ continue;
+ else
+ break;
+ }
+ skip_space = 0;
+ if (uc & 0x80)
+ continue;
+ if (want_letnum == -1)
+ want_letnum = letnum(uc);
+ else if (want_letnum != letnum(uc))
+ break;
}
}
return ncursor;
}
+/* Move right one character, and then to the beginning of the next big word. */
static int
Forwword(int argcnt)
{
@@ -1617,6 +1634,7 @@ Forwword(int argcnt)
return ncursor;
}
+/* Move left one character, and then to the beginning of the big word. */
static int
Backword(int argcnt)
{
@@ -1635,22 +1653,20 @@ Backword(int argcnt)
return ncursor;
}
+/* Move right one character, and then to the byte after the big word. */
static int
Endword(int argcnt)
{
int ncursor;
ncursor = es->cursor;
- while (ncursor < es->linelen - 1 && argcnt--) {
- while (++ncursor < es->linelen - 1 &&
+ while (ncursor < es->linelen && argcnt--) {
+ while (++ncursor < es->linelen &&
isspace((unsigned char)es->cbuf[ncursor]))
;
- if (ncursor < es->linelen - 1) {
- while (++ncursor < es->linelen &&
- !isspace((unsigned char)es->cbuf[ncursor]))
- ;
- ncursor--;
- }
+ while (ncursor < es->linelen &&
+ !isspace((unsigned char)es->cbuf[ncursor]))
+ ncursor++;
}
return ncursor;
}