Reading ESC on Linux during unbuffered input in C

927 views Asked by At

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

1

There are 1 answers

1
pkubik On BEST ANSWER

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