Hi folks,

Every now and then I've seen vi report something like

        Error: move: l(39 + 0) c(90 + 0)

and I've tracked it down to the way that _cursesi_addwchar() and
_cursesi_waddbytes() interact in src/lib/libcurses/addbytes.c .

_cursesi_addwchar() checks to see if the current position is past
the end of the line after it adds a character with this:

        if (*x == win->maxx) {
                (*lnp)->flags |= __ISPASTEOL;
                newx = win->maxx - 1 + win->ch_off;
                if (newx > *(*lnp)->lastchp)
                        *(*lnp)->lastchp = newx;
                __touchline(win, *y, sx, (int) win->maxx - 1);
>>>             win->curx = sx;
        } else {

The "*x" here is passed in from _cursesi_waddbytes().  If the current
position is past the end of the current line it sets win->curx to inside
the window (the >>> line), but leaves *x untouched.  The problem is
that then _cursesi_waddbytes() has a SYNCH_OUT macro afer the call to
_cursesi_addwchar() which does this:

        {win->cury = y; win->curx = x;}

which then sets win->curx back to the still invalid value of x that
_cursesi_addwchar() tried to adjust.

The other way of adding a character, _cursesi_addbyte(), doeasn't have
the same error as it checks for end of line differently.

This patch fixes the problem bu resetting x to a valid value and doesn't
seem to have had any side effects.  Anyone see any problems with
committing this?

Index: addbytes.c
===================================================================
RCS file: /cvsroot/src/lib/libcurses/addbytes.c,v
retrieving revision 1.47
diff -d -p -u -r1.47 addbytes.c
--- addbytes.c  6 Jan 2017 14:25:41 -0000       1.47
+++ addbytes.c  6 Aug 2018 07:38:59 -0000
@@ -582,7 +582,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
                if (newx > *(*lnp)->lastchp)
                        *(*lnp)->lastchp = newx;
                __touchline(win, *y, sx, (int) win->maxx - 1);
-               win->curx = sx;
+               *x = win->curx = sx;
        } else {
                win->curx = *x;

Below is a small test program that shows this failing and is essentially
what vi is doing when it gets the "Error: move" message.

Cheers,
Simon.
--
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
        int x, y, mx, my, ret;
        WINDOW *w;

        w = initscr();
        mx = getmaxx(w);
        my = getmaxy(w);

        move(0, mx - 1);
        addstr(".");
        getyx(w, y, x);
        ret = move(y, x);
        endwin();

        printf("maxx = %d, getyx curx = %d\n", mx, x);
        printf("maxy = %d, getyx cury = %d\n", my, y);
        printf("move(%d, %d) returns %d\n", y, x, ret);

        exit(0);
}

Reply via email to