Create a Function to Check for Key Press in Unix Using Ncurses

Create a function to check for key press in Unix using ncurses

You can use the nodelay() function to turn getch() into a non-blocking call, which returns ERR if no key-press is available. If a key-press is available, it is pulled from the input queue, but you can push it back onto the queue if you like with ungetch().

#include <ncurses.h>
#include <unistd.h> /* only for sleep() */

int kbhit(void)
{
int ch = getch();

if (ch != ERR) {
ungetch(ch);
return 1;
} else {
return 0;
}
}

int main(void)
{
initscr();

cbreak();
noecho();
nodelay(stdscr, TRUE);

scrollok(stdscr, TRUE);
while (1) {
if (kbhit()) {
printw("Key pressed! It was: %d\n", getch());
refresh();
} else {
printw("No key pressed yet...\n");
refresh();
sleep(1);
}
}
}

Python ncurses: Doesn't show screen until first key-press, even though refresh is first

The docs are broken. I'd used curses back in the day, but libncurses is new to me.

My first hint came from ncurses(3):

The ncurses library permits manipulation of data structures, called windows, which can be thought of as two-dimensional arrays of characters representing all or part of a CRT screen. A default window called stdscr, which is the size of the terminal screen, is supplied. Others may be created with newwin.

Special windows called pads may also be manipulated. These are windows which are not constrained to the size of the screen and whose contents need not be completely displayed.

But then refresh(3) got decidedly evasive:

The routine wrefresh works by first calling wnoutrefresh, which copies the named window to the virtual screen, and then calling doupdate, which compares the virtual screen to the physical screen and does the actual update. … The phrase "copies the named window to the virtual screen" above is ambiguous. What actually happens is that all touched (changed) lines in the window are copied to the virtual screen. This affects programs that use overlapping windows; it means that if two windows overlap, you can refresh them in either order and the overlap region will be modified only when it is explicitly changed. [emphasis mine]

which prompted me to try adding

stdscr.refresh()

after your pad.refresh() which worked. And then I moved it further up start() to see if it was really needed on every pad modification. I moved it all the way up to the first point there is a stdscr to work with yielding:

def start(stdscr):
stdscr.refresh()
curses.curs_set(0)

which smacks of voodoo programming, but I'm not going to look at the innards of a 20-year old library made to cope with glass ttys to try to grok it.

Using kbhit() and getch() on Linux

The ncurses howto cited above can be helpful. Here is an example illustrating how ncurses could be used like the conio example:

#include <ncurses.h>

int
main()
{
initscr();
cbreak();
noecho();
scrollok(stdscr, TRUE);
nodelay(stdscr, TRUE);
while (true) {
if (getch() == 'g') {
printw("You pressed G\n");
}
napms(500);
printw("Running\n");
}
}

Note that with ncurses, the iostream header is not used. That is because mixing stdio with ncurses can have unexpected results.

ncurses, by the way, defines TRUE and FALSE. A correctly configured ncurses will use the same data-type for ncurses' bool as the C++ compiler used for configuring ncurses.

How do determine key presses in C++

There is this tutorial on ncurses. NCURSES Programming HOWTO. I have confirmed that on my MacBook Pro, Mavericks 10.9.1, with the Xcode Command Line Tools installation, that the ncurses.h is a symbolic link to curses.h, both located in /usr/include. This is the NCURSES Introduction page.

I have not created a specific class myself. However, some searching on /dev/input/eventX, where X seems to be either a zero or one finds these two separate posts:Read from /dev/input and linux keypress events.



Related Topics



Leave a reply



Submit