Hey Walter,

Thanks for the report.

On Thu, Apr 03, 2025 at 02:55:11PM +0200, Walter Alejandro Iglesias wrote:
> Using vi mode in ksh I noticed that the command endword (vi.c) gets
> staked when the last character in a word is a UTF-8 character.
> 
> To reproduce:
> 
> In the line bellow, using vi mode, first move your cursor to the first
> character, then hit "e" several times.  You'll see the cursor get
> stacked in the euro sign.
> 
>   $ word word€ word
>              ^ this is an euro sign.

It also happens with E command.

> The following diff is one of my intuitive C newbie solutions, some
> expert will surely find a better one.

The patch isn't correct: you're calling isspace (expects a character)
with the result of isu8cont (which is a boolean).

The right places to fix this seem to be endword and Endword. The patch
below fixes the issue for me. The approach taken is first skipping all
the UTF-8 continuation bytes after the cursor, before considering
skipping spaces.

OK? Too close for release?

        Lucas


diff refs/heads/master 6fa8b54754b6fba159a065d3fc32b57caae81275
commit - 58fd8d0bdc1e6222119987e7aaad111eae245668
commit + 6fa8b54754b6fba159a065d3fc32b57caae81275
blob - cdda9cb24b1a4a395547e081ff3adca380d3b6c1
blob + 7f09c75e44c37f7ecc247df5ac187b4816a99cc3
--- bin/ksh/vi.c
+++ bin/ksh/vi.c
@@ -1590,15 +1590,18 @@ backword(int argcnt)
 static int
 endword(int argcnt)
 {
-       int ncursor, skip_space, want_letnum;
+       int ncursor, skip_space, skip_utf8_cont, want_letnum;
        unsigned char uc;
 
        ncursor = es->cursor;
        while (ncursor < es->linelen && argcnt--) {
-               skip_space = 1;
+               skip_space = skip_utf8_cont = 1;
                want_letnum = -1;
                while (++ncursor < es->linelen) {
                        uc = es->cbuf[ncursor];
+                       if (isu8cont(uc))
+                               continue;
+                       skip_utf8_cont = 0;
                        if (isspace(uc)) {
                                if (skip_space)
                                        continue;
@@ -1663,6 +1666,9 @@ Endword(int argcnt)
        ncursor = es->cursor;
        while (ncursor < es->linelen && argcnt--) {
                while (++ncursor < es->linelen &&
+                   isu8cont((unsigned char)es->cbuf[ncursor]))
+                       ;
+               while (++ncursor < es->linelen &&
                    isspace((unsigned char)es->cbuf[ncursor]))
                        ;
                while (ncursor < es->linelen &&

Reply via email to