Question

I wrote a getch function for program. I couldn't use curses as it breaks the terminal for iostream I already use. The code:

inline std::string getch() {
    char inp[4];
    system("stty raw");
    inp[0] = std::cin.get();
    if(inp[0] == 27 && (inp[1] = std::cin.get()) != std::char_traits<char>::eof()) {
        std::cin>>inp[2];
        inp[3] = '\0';
    }
    else {
        inp[1] = '\0';
    }
    system("stty cooked echo");
    return std::string(inp);
}

I know it would be better to use termios.h instead of system calls. Everything works fine except if ESC key. I'm trying to capture arrows which are string of for example "\1B[A". When I detect ESC as first character I also read the second two to get full key code. The problem is that it shouldn't occur when I press ESC as it's code is 1B alone. The cin.get() should return EOF when the buffer is empty during read, but it simply stops.

Is there a way to read ESC key on linux without using curses? Why my solution isn't working?

Thanks

Was it helpful?

Solution

After many hours of searching I found the solution. I had to use read function from unistd.h It fills an array of given size, with characters from the input. When a key is pressed the buffer is filled with all read characters (works also on multiple keys). So an ESC has simply {27,0,0,...,0} and arrow {27,'[','A',0,0,...,0}. I've rewritten my function using termios.h and put in library, so anyone can benefit.

Here is the code: readkey on github

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top