diff options
Diffstat (limited to 'src/platform/getch.c')
| -rw-r--r-- | src/platform/getch.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/platform/getch.c b/src/platform/getch.c new file mode 100644 index 0000000..48c846e --- /dev/null +++ b/src/platform/getch.c @@ -0,0 +1,53 @@ +#ifdef _WIN32 +void getch_init(void) {} +#else +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <termios.h> +#include <unistd.h> + +static struct termios default_state = {0}; + +int getch(void) +{ + int ch = 0; + struct termios old = {0}; + fflush(stdout); + + tcgetattr(0, &old); + old.c_lflag &= ~ICANON; + + tcsetattr(0, TCSANOW, &old); + ch = getchar(); + tcsetattr(0, TCSADRAIN, &default_state); + + return ch; +} + +static void get_reset_terminal_state(void) +{ + tcsetattr(0, TCSANOW, &default_state); +} + +static noreturn void get_reset_terminal_state_handler(int sig) +{ + get_reset_terminal_state(); + _Exit(sig); +} + +void getch_init(void) +{ + tcgetattr(0, &default_state); + + atexit(get_reset_terminal_state); + + signal(SIGINT, get_reset_terminal_state_handler); + signal(SIGABRT, get_reset_terminal_state_handler); + signal(SIGFPE, get_reset_terminal_state_handler); + signal(SIGILL, get_reset_terminal_state_handler); + signal(SIGSEGV, get_reset_terminal_state_handler); + signal(SIGTERM, get_reset_terminal_state_handler); +} +#endif /* _WIN32 */ |