[C++] switch(), ncurses and arrow keys causing odd behaviour

7769a20efe5b89925498160b24b76c05
0
Hertta 101 Dec 30, 2009 at 03:50

EDIT: Got it solved! Solution at the end of the post.

Well, I am working on a roguelike game in which I stumbled upon some odd behaviour from ncurses’ side.

Given the following code:

#include <ncurses.h>
#include <string>
#include <sstream>

bool running;
void handle_keyboard();

int main() {
    std::stringstream ss;
    std::string msg;
    initscr();
    raw();
    noecho();
    curs_set(0);
    int loop_no=0;
    running=true;
    while(running) {
    
        handle_keyboard();
        clear;
        ss << "Loop no. " << loop_no;
        msg = ss.str();
        mvprintw(1,1, msg.c_str());
        ss.str("");
        loop_no++;
    
    }
    endwin();
    return 0;

}

void handle_keyboard() {

    static char ch;
    ch = getch();
    switch(ch) {
        case 'q':
            running = false;
            break;
        default:
            break;
    }

}

the problem happens when I press arrow keys(Edit: also includes F1-F12 keys, pg up, pg down, end, home etc. keys). What happens, is that it seems as if the getch() function does not stop the execution for the 4 cycles to come. As in, the next 2 getch() functions do nothing. They are skipped. Which results in “skipped” cycles in the main loop.

The output is something like this:
if using other than arrow keys:
Loop no. 1
Loop no. 2
Loop no. 3
… etc

if using arrow keys:
loop no. 2
loop no. 5
loop no. 8
loop no. 11
loop no. 14

I have no clue(Might be related to enabling keypad with keypad() function though, no luck with trial-and-error so far.) why this happens. I have no proper workarounds how to prevent this. (Calling getch() twice after the ‘bug’ happens does fix it partly, however it adds two key stroke ‘delay’ to any key presses, so it’s not a viable workaround.)

Tested on Linux(ArchLinux with 2.6.31 kernel) with gcc(4.4.2) and ncruses 5.7.20081102.

Any thoughts?


Solved it. Solution was to enable keypad after calling initscr(). I tried to do it with “keypad(0, true);”, but I had to use “keypad(stdscr, true);” instead. Now it works great.

2 Replies

Please log in or register to post a reply.

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 30, 2009 at 05:51

I’ve never used ncurses, but aren’t you printing to the same screen location every time? Aren’t those numbers in front of the mvprint argument the screen location? It seems like the output would keep overlapping and you appear to be clearing the screen each time. How can you get the information you describe? But if it is, I would think you would need a debugger and some stops to tell what’s going on.

Oh, just noticed the solved it.

7769a20efe5b89925498160b24b76c05
0
Hertta 101 Dec 30, 2009 at 14:44

Actually you’re right. I didn’t notice it in my test case. However as long as it prints on top of the old text there’s no problem with it. :)