NetBSD-Bugs archive

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

lib/41060: libcurses curs_set() doesn't update properly



>Number:         41060
>Category:       lib
>Synopsis:       libcurses curs_set() doesn't update properly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Mar 22 20:15:00 +0000 2009
>Originator:     Peter Bex
>Release:        NetBSD 4.0.0_PATCH
>Organization:
        
>Environment:
        
        
System: NetBSD frohike.homeunix.org 4.0.0_PATCH NetBSD 4.0.0_PATCH (GENERIC) 
#0: Fri Dec 21 17:12:08 CET 2007 
sjamaan%frohike.homeunix.org@localhost:/usr/obj/sys/arch/amd64/compile/GENERIC 
amd64
Architecture: x86_64
Machine: amd64
>Description:
        When setting the cursor's visibility using curs_set(), the
        cursor does not actually get shown until the screen is 'dirty'.

        This can be seen in programs which disable the cursor globally
        but enable it temporarily when showing a user interaction prompt,
        like for example when you press the colon character (":") in
        audio/cmus from pkgsrc.  The how-to-repeat section also has
        a simplified example that shows the bug in action.

        The bug can be fixed by either calling refresh() or flushing
        the screen's output fd.

>How-To-Repeat:

        This small program first disables the cursor, waits for a
        keypress, then enables the cursor and waits for another
        keypress, and then quits.

        When linking it to devel/ncurses, the program behaves as
        expected: it first shows no cursor, then it shows a cursor
        after the user pressed a key.
        When linking it to NetBSD's native curses, the program never
        shows a cursor.

        If the fflush code is uncommented, it works like the ncurses
        code.  Alternatively, replace fflush() with refresh().

-----------------------------------------
#include <curses.h>
#include <stdio.h>

/* Quick hack to be able to obtain the screen output fd for this test */
struct __screen {
        FILE *infd, *outfd;
};

extern SCREEN *_cursesi_screen;

int main(void)
{
        initscr();
        cbreak();
        noecho();

        curs_set(0);
        /*
         * Comment this out to see the bug,
         * uncomment it to see the correct behaviour
         */
        /* fflush(_cursesi_screen->outfd); */
        getch();
        curs_set(1);
        /*
         * Comment this out to see the bug,
         * uncomment it to see the correct behaviour
         */
        /* fflush(_cursesi_screen->outfd); */
        getch();

        endwin();
        return 0;
}
-----------------------------------------

>Fix:

Here's a possible patch.  Another possible patch would be to touchwin(),
so the code in getch.c:{807,808} causes a refresh to be triggered.
I'm not sure which would be the best solution (I also don't know if
there are other operations that are also missing a "flush" call).

Index: curs_set.c
===================================================================
RCS file: /cvsroot/src/lib/libcurses/curs_set.c,v
retrieving revision 1.8
diff -u -r1.8 curs_set.c
--- curs_set.c  21 Jan 2007 13:25:36 -0000      1.8
+++ curs_set.c  22 Mar 2009 19:28:13 -0000
@@ -59,6 +59,7 @@
 #endif
                                _cursesi_screen->old_mode = 0;
                                tputs(__tc_vi, 0, __cputchar);
+                               fflush(_cursesi_screen->outfd);
                                return old_one;
                        }
                        break;
@@ -70,6 +71,7 @@
 #endif
                                _cursesi_screen->old_mode = 1;
                                tputs(__tc_ve, 0, __cputchar);
+                               fflush(_cursesi_screen->outfd);
                                return old_one;
                        }
                        break;
@@ -82,6 +84,7 @@
 #endif
                                _cursesi_screen->old_mode = 2;
                                tputs(__tc_vs, 0, __cputchar);
+                               fflush(_cursesi_screen->outfd);
                                return old_one;
                        }
                        break;

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index