From 8b20212ee2364c87802796ae624968570e5075e8 Mon Sep 17 00:00:00 2001
From: Hadeed Ahmad <hadeedji@gmail.com>
Date: Wed, 23 Aug 2023 21:36:42 +0500
Subject: [PATCH] Finish some of chapter 3

---
 Makefile |  2 +-
 kilo.c   | 67 +++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/Makefile b/Makefile
index d262ca6..3c24b12 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CCFLAGS := -Wall -Wextra -Wpedantic -Werror -std=c99
+CCFLAGS := -Wall -Wextra -Wpedantic -Werror -std=c99 -D_DEFAULT_SOURCE
 
 kilo: kilo.c
 	$(CC) $(CCFLAGS) kilo.c -o kilo
diff --git a/kilo.c b/kilo.c
index 3af5156..05dca6d 100644
--- a/kilo.c
+++ b/kilo.c
@@ -5,11 +5,18 @@
 #include <termios.h>
 #include <unistd.h>
 
+#define CTRL_KEY(key) ((key) & 0x1f)
 
 struct termios orig_termios;
 
+void editor_clear_screen() {
+    write(STDIN_FILENO, "\x1b[2J", 4);
+    write(STDIN_FILENO, "\x1b[H", 3);
+}
 
 void die(const char *s) {
+    editor_clear_screen();
+
     perror(s);
     exit(1);
 }
@@ -24,30 +31,60 @@ void enable_raw_mode() {
     atexit(disable_raw_mode);
 
     struct termios raw = orig_termios;
-    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
-    raw.c_oflag &= ~(OPOST);
-    raw.c_cflag |= (CS8);
-    raw.c_lflag &= ~(ECHO | ICANON | ISIG);
-    raw.c_cc[VMIN] = 0;
-    raw.c_cc[VTIME] = 1;
+    cfmakeraw(&raw);
 
     if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) die("tcsetattr");
 }
 
+char editor_read_key() {
+    char c = '\0';
+
+    while (c == '\0')
+        read(STDIN_FILENO, &c, 1);
+
+    return c;
+}
+
+void editor_draw_rows() {
+    int rows = 24;
+    for (int y = 0; y < rows - 1; y++)
+        write(STDIN_FILENO, "~\r\n", 3);
+    write(STDIN_FILENO, "~", 1);
+}
+
+void editor_redraw_screen() {
+    editor_clear_screen();
+
+    editor_draw_rows();
+
+    write(STDIN_FILENO, "\x1b[H", 3);
+}
+
+void editor_process_key() {
+    char c;
+    read(STDIN_FILENO, &c, 1);
+
+    switch (c) {
+        case CTRL_KEY('Q'):
+            editor_clear_screen();
+            exit(0);
+            break;
+        default:
+            printf("%d\r\n", c);
+            break;
+    }
+}
 
 int main() {
+    if (!isatty(STDIN_FILENO)) {
+        printf("kilo only supports a terminal at standard in. Exiting.");
+        exit(1);
+    }
 
     enable_raw_mode();
     while (1) {
-        char c = '\0';
-        if (read(STDIN_FILENO, &c, 1) == -1 && errno != EAGAIN) die("read");
-
-        if (iscntrl(c))
-            printf("%d\r\n", c);
-        else
-            printf("%d ('%c')\r\n", c, c);
-
-        if (c == 'q') break;
+        editor_redraw_screen();
+        editor_process_key();
     }
 
     return 0;