Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wclrtoeol() erases character at the end of the window #324

Open
rhaberkorn opened this issue Sep 21, 2024 · 6 comments
Open

wclrtoeol() erases character at the end of the window #324

rhaberkorn opened this issue Sep 21, 2024 · 6 comments

Comments

@rhaberkorn
Copy link

In the following example, the last "X" got erased,
apparently by wclrtoeol():

#include <curses.h>

int main(void)
{
	initscr();
	refresh(); // erases screen

	WINDOW *win = newwin(1,0,0,0);
	mvwaddstr(win, 0, getmaxx(win)-3, "XXX");
	wclrtoeol(win); // try to comment this out!
	wrefresh(win);
	
	getch();
	endwin();
	return 0;
}

Interestingly this works as expected when writing directly to stdscr at the line end.

@rhaberkorn
Copy link
Author

That's how it looks like in ncurses:

screenshot-1727196207

@Bill-Gray
Copy link
Owner

I see what you mean. The behavior is identical in PDCursesMod and in PDCurses, so this may be of interest to @wmcbrine.

In PDCurses*, you get 'XX' and a blank at the end of the line, and the cursor ends up at the start of that same line. Make the window more than one line high, and you get the same thing, but the 'X' is not erased.

In ncurses, you get 'XXX' and the cursor remains at the end of the line, blinking over the final 'X'. Make the window more than one line high, and the cursor moves to the start of the next line.

More generally, it appears that in ncurses, the cursor gets moved around to be after the 'XXX' (or left in the final position of the window if that's where the third 'X' ends up). In PDCurses*, the screen cursor doesn't move. (Obviously, the window cursor is getting moved around.)

@rhaberkorn
Copy link
Author

Question is whether you consider this a bug or just a given difference in implementation.

@Bill-Gray
Copy link
Owner

I think the following example may get us down to the underlying issue :

#include <curses.h>

int main( void)
{
   initscr();
   refresh( );

   WINDOW *win = newwin(0, 0, 0, 0);
   wmove( win, LINES / 2, COLS / 2);
   wrefresh( win);
   getch();
   endwin();
   return 0;
}

With ncurses, this shows the cursor at the middle of the screen (wmove() is affecting the screen cursor, not just the window cursor). In PDCurses*, the screen cursor is unaffected.

I don't know which is correct. I doubt it would be considered a difference in implementation; my bet is that either we're wrong or that ncurses is.

A comment in move.c says that "this does not move the physical cursor of the terminal until refresh() is called". Which does imply that wmove() ought to move the cursor when you do call refresh (i.e., that ncurses has it right).

@Bill-Gray
Copy link
Owner

Okay, I think I see a bit more about what's going on here. In the code just above this, insert nap(2000); between the wrefresh(win); and getch(); lines. In PDCurses*, you'll see the cursor go to the center (when wrefresh(win) is called). Wait two seconds, and it'll move to the upper left corner (when getch(); is called.)

getch() translates to wgetch(stdscr). stdscr is getting refreshed, and when a window is refreshed, the physical cursor is left where that window's cursor is (unless leaveok() has been called... not the case here).

The thing that puzzles me is that the refresh is only supposed to happen if the window has changed (identical code is in PDCursesMod). So presumably, the window has gotten touched somewhere along the line. Will investigate... though may be a while. Mostly writing this so I'll have some record of the above to jog my memory in a few days.

If you use wgetch(win); instead of getch(), the cursor is left where it's supposed to be, because stdscr never enters the picture. In that case, you can even leave out the wrefresh( win); it'll get called, as it should be, as part of wgetch(win).

@Bill-Gray
Copy link
Owner

I think we have two issues here, not one.

First, there's the problem of handling what happens when you add a character at the lower right corner of the window (which we do with the third 'X' above). Both PDCurses* and ncurses output the character and don't advance the cursor. ncurses, though, must have some sort of logic to recognize that it's "gone past the end of the window", and that subsequent clearing to end of line or end of window should do nothing. PDCurses* doesn't.

The second issue (the one I leapt onto immediately, thinking it was the only issue) is of what happens when you move the cursor in a window, do an update of that window, and then do a getch(). In PDCurses*, you may well have moved the cursor within the window (set its _curx and _cury members to new values), and the physical cursor will have moved to match when you wrefresh()ed that window. But stdscr->_curx and stdscr->cury have been left unchanged; when you call getch(), a.k.a. wgetch( stdscr), the cursor gets moved to those (unchanged) values. In my example above, it moves the physical cursor from the middle of the screen (where it was in the allocated window) to the top left (where it was in stdscr, and we never moved it.)

I don't see an easy solution to either issue. The second may very well be implementation-specific (i.e., we can ignore it). On the first issue, though, I have to say that it seems to me that (as in your example) if you put 'XXX' in the last three cells of a window, wclrtoeol(win); should do nothing. So, still pondering this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants