Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

curses library: why does getch() clear my screen?

I'm trying to learn the curses library (pdcurses, as I'm in Windows OS), with C++. I have a program that displays 3 windows, then a while loop to do some processing based in key presses captured by getch(). The loop gets exited when the F1 key is pressed.

However, despite refreshing all three windows with wrefresh(), nothing appears before I enter my first key press. Without the while loop, everything is displayed fine. I've made numerous tests and it's like the first call to getch() will completely clear the screen, but not the subsequent ones.

My question is: what did I miss? At first, I was thinking that maybe getch() was calling an implicit refresh(), but then why do subsequent calls to it not have the same behaviour?

Thank you very much in advance for your help.

Here is the code.

#include <curses.h>

int main()
{
    initscr();
    raw();
    keypad(stdscr, TRUE);
    noecho();
    curs_set(0);

    WINDOW *wmap, *wlog, *wlegend;
    int pressed_key;
    int map_cursor_y = 10, map_cursor_x = 32;

    wlog = newwin(5, 65, 0, 15);
    wlegend = newwin(25, 15, 0, 0);
    wmap = newwin(20, 65, 5, 15);

    box(wmap, 0 , 0);
    box(wlog, 0 , 0);
    box(wlegend, 0 , 0);

    mvwprintw(wlog, 1, 1, "this is the log window");
    mvwprintw(wlegend, 1, 1, "legends");
    mvwaddch(wmap, map_cursor_y, map_cursor_x, '@');

    wrefresh(wlog);
    wrefresh(wmap);
    wrefresh(wlegend);

    while ((pressed_key = getch()) != KEY_F(1))
    {
         /* process keys to move the @ cursor (left out because irrelevant) */

         box(wmap, 0 , 0);
         box(wlog, 0 , 0);
         box(wlegend, 0 , 0);
         wrefresh(wmap);
         wrefresh(wlog);
         wrefresh(wlegend);
    }

    endwin();
    return 0;
}
like image 564
user2948911 Avatar asked Nov 03 '13 00:11

user2948911


People also ask

Does python curses work on Windows?

The Windows version of Python doesn't include the curses module. A ported version called UniCurses is available. You could also try the Console module written by Fredrik Lundh, which doesn't use the same API as curses but provides cursor-addressable text output and full support for mouse and keyboard input.

What does curses wrapper do?

The wrapper() function takes a callable object and does the initializations described above, also initializing colors if color support is present. wrapper() then runs your provided callable. Once the callable returns, wrapper() will restore the original state of the terminal.


1 Answers

Your first instinct was correct: getch() does an implicit refresh(). Specifically, getch() is equivalent to wgetch(stdscr), so it's an implicit wrefresh(stdscr) -- updating a window (stdscr) that you're not otherwise using, that just happens to fill the screen. The reason that subsequent calls have no effect from that point on, is that stdscr is already up to date, as far as curses is concerned, since you never write to it after that (never mind that its contents have been overwritten on the actual screen).

The solution is either to call refresh() explicitly at the top, before you begin drawing; or, my preference, to call wgetch() on a different window (whichever is most appropriate), instead of getch(), and ignore the existence of stdscr entirely. Just remember that all the functions that don't let you specify a window -- getch(), refresh(), etc. -- are really calls to their "w" equivalents, with stdscr as the implicit window parameter.

like image 113
William McBrine Avatar answered Sep 23 '22 05:09

William McBrine