199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten/*
299478f473889925e07c5a99a344abf16c6e58055Glenn KastenC non-blocking keyboard input
399478f473889925e07c5a99a344abf16c6e58055Glenn Kastenhttp://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input
499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten*/
599478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
699478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include <stdlib.h>
799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include <string.h>
899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include <sys/select.h>
999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include <termios.h>
1099478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include <unistd.h>
1199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#include "getch.h"
1299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
1399478f473889925e07c5a99a344abf16c6e58055Glenn Kastenstruct termios orig_termios;
1499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
1599478f473889925e07c5a99a344abf16c6e58055Glenn Kastenvoid reset_terminal_mode()
1699478f473889925e07c5a99a344abf16c6e58055Glenn Kasten{
1799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    tcsetattr(0, TCSANOW, &orig_termios);
1899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten}
1999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
2099478f473889925e07c5a99a344abf16c6e58055Glenn Kastenvoid set_conio_terminal_mode()
2199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten{
2299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    struct termios new_termios;
2399478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
2499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    /* take two copies - one for now, one for later */
2599478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    tcgetattr(0, &orig_termios);
2699478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    memcpy(&new_termios, &orig_termios, sizeof(new_termios));
2799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
2899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    /* register cleanup handler, and set the new terminal mode */
2999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    atexit(reset_terminal_mode);
3099478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    cfmakeraw(&new_termios);
3199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    new_termios.c_oflag |= OPOST;
3299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    tcsetattr(0, TCSANOW, &new_termios);
3399478f473889925e07c5a99a344abf16c6e58055Glenn Kasten}
3499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
3599478f473889925e07c5a99a344abf16c6e58055Glenn Kastenint kbhit()
3699478f473889925e07c5a99a344abf16c6e58055Glenn Kasten{
3799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    struct timeval tv = { 0L, 0L };
3899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    fd_set fds;
3999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    FD_ZERO(&fds); // not in original posting to stackoverflow
4099478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    FD_SET(0, &fds);
4199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    return select(1, &fds, NULL, NULL, &tv);
4299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten}
4399478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
4499478f473889925e07c5a99a344abf16c6e58055Glenn Kastenint getch()
4599478f473889925e07c5a99a344abf16c6e58055Glenn Kasten{
4699478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    int r;
4799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    unsigned char c;
4899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    if ((r = read(0, &c, sizeof(c))) < 0) {
4999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten        return r;
5099478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    } else {
5199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten        return c;
5299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    }
5399478f473889925e07c5a99a344abf16c6e58055Glenn Kasten}
5499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
5599478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#if 0
5699478f473889925e07c5a99a344abf16c6e58055Glenn Kastenint main(int argc, char *argv[])
5799478f473889925e07c5a99a344abf16c6e58055Glenn Kasten{
5899478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    set_conio_terminal_mode();
5999478f473889925e07c5a99a344abf16c6e58055Glenn Kasten
6099478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    while (!kbhit()) {
6199478f473889925e07c5a99a344abf16c6e58055Glenn Kasten        /* do some work */
6299478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    }
6399478f473889925e07c5a99a344abf16c6e58055Glenn Kasten    (void)getch(); /* consume the character */
6499478f473889925e07c5a99a344abf16c6e58055Glenn Kasten}
6599478f473889925e07c5a99a344abf16c6e58055Glenn Kasten#endif
66