Here is a version of the code which I modified to be actual C and not C++, since it was only being C++ out of carelessness with bool true/false and struct keywords.
And oh yeah, don't put this in a header file. Put it in a file called kbhit.c and delete or comment out the test main function. And in a header file just write the line:
int _kbhit(void);
Or you might need:
extern "C" int _kbhit(void);
That's all you need in the header.
/**
Linux (POSIX) implementation of _kbhit().
Morgan McGuire, morgan@cs.brown.edu
*/
#include <stdbool.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int _kbhit(void) {
static bool initialized = false;
if (! initialized) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN_FILENO, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &term);
setbuf(stdin, NULL);
initialized = true;
}
int bytesWaiting;
ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
//////////////////////////////////////////////
// Simple demo of _kbhit()
int main() {
printf("Press any key");
while (! _kbhit()) {
printf(".");
fflush(stdout);
usleep(1000);
}
printf("\nDone.\n");
return 0;
}
It looks correct to me and valgrind does not complain. I don't have Dr. Memory to check with.
How this code works is that it first uses tcgetattr
to read the termios (terminal input output settings, I think) struct. Then it modifies it by unsetting the ICANON bits. Canon is the canonical setting for terminals which includes line buffering. Then it writes the new termios values back to the terminal. with tcsetattr
.
The ioctl
call gets how many bytes are waiting in the buffer. If there's bytes waiting, then someone pressed some kind of keys.