tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

curses bug - incorrect curx at end of line



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);
}


Home | Main Index | Thread Index | Old Index