Hi,
I recently encountered a bug in ksh(1)'s emacs mode while running from
xterm(1). How-to reproduce:

1. Insert a sequence containing at least one UTF-8 character until the
   line exceeds the last column, triggering horizontal scroll.

2. Moving backwards using any motion (^A, ^B, ^[b) fails when reaching
   the first visible character triggering backwards horizontal scroll.

It seems like the cause is due to how the column counter works. Every
byte in a UTF-8 character is assumed to occupy one column. The most
reliable way to solve this is probably using wcwidth(3) but that would
require extensive work. However, the same logic found in the x_size
function could instead be used in which a UTF-8 continuation byte is
assumed to not occupy a column.

In the process of fixing this, I found another bug. This does only occur
when the current line exceeds the number of columns and includes UTF-8
characters. How-to reproduce:

1. Use a 80 column wide terminal and ensure your prompt contains at
   least 3 characters:

   PS1='xxx'

2. Insert the following sequence, without the leading spaces:

   รถ a a a a a a a a a a a a a a a a a a a a a a a b b b b b b b b b b b b b b 
b b z

3. Press ^A (beginning-of-line), ^[f (forward-word), ^W (kill-region).
   At this point the prompt gets overwritten.

By invalidating xlp in the x_delete function prior calling x_zots in
which x_lastcp is called causing xlp to be recalculated solves this.

Comments and feedback are much appreciated.

Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.66
diff -u -p -r1.66 emacs.c
--- emacs.c     9 Aug 2016 11:04:46 -0000       1.66
+++ emacs.c     9 May 2017 17:52:37 -0000
@@ -533,6 +533,7 @@ x_delete(int nc, int push)
        }
        memmove(xcp, xcp+nc, xep - xcp + 1);    /* Copies the null */
        x_adj_ok = 0;                   /* don't redraw */
+       xlp_valid = false;
        x_zots(xcp);
        /*
         * if we are already filling the line,
@@ -1909,7 +1910,8 @@ x_e_putc(int c)
                        x_col--;
                        break;
                default:
-                       x_col++;
+                       if (!isu8cont(c))
+                               x_col++;
                        break;
                }
        }

Reply via email to