NetBSD-Bugs archive

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

lib/41223: libcurses: curs_set and move do not cause refresh on getch



>Number:         41223
>Category:       lib
>Synopsis:       libcurses: curs_set and move do not cause refresh on getch
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 15 19:05:00 +0000 2009
>Originator:     Jed Davis
>Release:        NetBSD 5.0_RC2
>Organization:
>Environment:
System: NetBSD planetarium.xlerb.net 5.0_RC2 NetBSD 5.0_RC2 (PLANETAR64) #3: 
Tue Mar 3 21:40:33 EST 2009 
jld%city-of-dreadful-night.xlerb.net@localhost:/usr/local/src/nb-5/sys/arch/amd64/compile/PLANETAR64
 amd64
Architecture: x86_64
Machine: amd64
>Description:

If one of the getch() family of functions is called, and the only
actions since the last refresh() on that window are applications of
curs_set() or move(), then the getch() will not perform the implicit
refresh() that seems to be called for by the documentation and the
standard.

>How-To-Repeat:
I've reproduced this bug on -current and -4 as well as -5.

#include <curses.h>
int main()
{ initscr(); for (;;) { curs_set(0); refresh(); curs_set(1); getch(); } }

#include <curses.h>
int main()
{ initscr(); for (;;) { move(10, 10); refresh(); move(0, 0); getch(); } }

Compare the behavior to that of other curses implementations (e.g.,
ncurses), or the behavior with an explicit refresh() before the getch().

These testcases are reduced from the behavior of the roguelike game
Dungeon Crawl Stone Soup (http://crawl-ref.sf.net/); with NetBSD curses,
the cursor is usually invisible when waiting for input, including the
selection of a location on the screen with the cursor.  The bug with
move is also visible at one point.

>Fix:

The problem seems to be that wgetch (and wget_wch) call wrefresh(win)
only if is_wintouched(win) is true; however, is_wintouched (which is
just the disjunction over all lines of is_linetouched) will be made true
only if characters are actually written to the screen.

Note that while curs_set() writes termcap codes immediately instead of
deferring work to update time, it does so via __cputchar, which is a
stdio buffered write that isn't flushed until the end of do_update.

One fix would be to simply remove the is_wintouched() tests; given
that that should amount to one extra refresh per keypress, and only if
the application is doing no screen output (including echo, I think) in
response, the performance overhead should be negligible.  It would also
be possible to track the cursor dirtiness explicitly, but I'm not sure
it's worth it.



Home | Main Index | Thread Index | Old Index