123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten/*
223c38816f7c210afae5072fd44658c98fec7e119Glenn KastenC non-blocking keyboard input
323c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenhttp://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input
423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten*/
523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#include <stdlib.h>
723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#include <string.h>
823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#include <sys/select.h>
923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#include <termios.h>
101168fe388b96340ada641b7e0da1ca18b270af3aGlenn Kasten#include <unistd.h>
11d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten#include "getch.h"
1223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
1323c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenstruct termios orig_termios;
1423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
1523c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenvoid reset_terminal_mode()
1623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
1723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    tcsetattr(0, TCSANOW, &orig_termios);
1823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
1923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
2023c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenvoid set_conio_terminal_mode()
2123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
2223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    struct termios new_termios;
2323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
2423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    /* take two copies - one for now, one for later */
2523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    tcgetattr(0, &orig_termios);
2623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    memcpy(&new_termios, &orig_termios, sizeof(new_termios));
2723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
2823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    /* register cleanup handler, and set the new terminal mode */
2923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    atexit(reset_terminal_mode);
3023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    cfmakeraw(&new_termios);
310a66743fb5e46c8d94f13d6170ef405f387f05f6Glenn Kasten    new_termios.c_oflag |= OPOST;
3223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    tcsetattr(0, TCSANOW, &new_termios);
3323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
3423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
3523c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenint kbhit()
3623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
3723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    struct timeval tv = { 0L, 0L };
3823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    fd_set fds;
3923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    FD_ZERO(&fds); // not in original posting to stackoverflow
4023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    FD_SET(0, &fds);
4123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    return select(1, &fds, NULL, NULL, &tv);
4223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
4323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
4423c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenint getch()
4523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
4623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    int r;
4723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    unsigned char c;
4823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    if ((r = read(0, &c, sizeof(c))) < 0) {
4923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        return r;
5023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    } else {
5123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        return c;
5223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
5323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
5423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
5523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#if 0
5623c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenint main(int argc, char *argv[])
5723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
5823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    set_conio_terminal_mode();
5923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
6023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    while (!kbhit()) {
6123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        /* do some work */
6223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
6323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    (void)getch(); /* consume the character */
6423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
6523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#endif
66