summary refs log tree commit diff
path: root/src/platform
diff options
context:
space:
mode:
authorNakidai <plaza521@inbox.ru>2024-07-05 07:16:05 +0300
committerNakidai <plaza521@inbox.ru>2024-07-05 07:19:48 +0300
commitaea40f3877e36e95f2a70e3eeb0569fd156e3841 (patch)
treee6bd202ac4e5499db3b9983fc46e3b880a20f5ff /src/platform
parenta9c159f5f7bf3479c3236735960597b4bc36a204 (diff)
download3cl-aea40f3877e36e95f2a70e3eeb0569fd156e3841.tar.gz
3cl-aea40f3877e36e95f2a70e3eeb0569fd156e3841.zip
Add almost all
Only continue operation and "blocks" of code are left. Now I'm gonna
sleep

And yes, I understand that code need to be refactored, and if I will not
get bored with writing this thing I will rewrite it in a better way, cuz
now code is awful
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/getch.c53
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 */