:: commit ab5b09e2379c90b422ab08ac7a39d6eeed6e4688

mintsuki <mintsuki@protonmail.com> — 2020-01-25 03:49

parents: a9b31d6bfd

Add editing capabilities to gets

diff --git a/src/drivers/vga_textmode.c b/src/drivers/vga_textmode.c
index 8ac334c6..180330d6 100644
--- a/src/drivers/vga_textmode.c
+++ b/src/drivers/vga_textmode.c
@@ -114,11 +114,15 @@ static int text_get_cursor_pos_y(void) {
     return cursor_offset / VD_COLS;
 }
 
-static void text_set_cursor_pos(int x, int y) {
+void text_get_cursor_pos(int *x, int *y) {
+    *x = (cursor_offset % VD_COLS) / 2;
+    *y = cursor_offset / VD_COLS;
+}
+
+void text_set_cursor_pos(int x, int y) {
     clear_cursor();
     cursor_offset = y * VD_COLS + x * 2;
     draw_cursor();
-    return;
 }
 
 void text_write(const char *buf, size_t count) {
@@ -137,7 +141,7 @@ static void text_putchar(char c) {
         case 0x1B:
             escape = 1;
             return;
-        case 0x0A:
+        case '\n':
             if (text_get_cursor_pos_y() == (VD_ROWS - 1)) {
                 clear_cursor();
                 scroll();
@@ -149,11 +153,10 @@ static void text_putchar(char c) {
         case '\r':
             text_set_cursor_pos(0, text_get_cursor_pos_y());
             break;
-        case 0x08:
+        case '\b':
             if (cursor_offset) {
                 clear_cursor();
                 cursor_offset -= 2;
-                video_mem[cursor_offset] = ' ';
                 draw_cursor();
             }
             break;
diff --git a/src/drivers/vga_textmode.h b/src/drivers/vga_textmode.h
index c9dc43f3..76d29e67 100644
--- a/src/drivers/vga_textmode.h
+++ b/src/drivers/vga_textmode.h
@@ -6,4 +6,7 @@
 void init_vga_textmode(void);
 void text_write(const char *, size_t);
 
+void text_get_cursor_pos(int *x, int *y);
+void text_set_cursor_pos(int x, int y);
+
 #endif
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 75b2fe32..55496d6f 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -6,6 +6,7 @@
 #include <lib/real.h>
 #include <sys/interrupt.h>
 #include <lib/libc.h>
+#include <lib/cio.h>
 
 void pit_sleep(uint64_t pit_ticks) {
     uint64_t target = global_pit_tick + pit_ticks;
@@ -33,33 +34,86 @@ uint64_t strtoui(const char *s) {
     return n;
 }
 
-char getchar(void) {
+int getchar(void) {
     struct rm_regs r = {0};
     rm_int(0x16, &r, &r);
+    switch ((r.eax >> 8) & 0xff) {
+        case 0x4b:
+            return GETCHAR_CURSOR_LEFT;
+        case 0x4d:
+            return GETCHAR_CURSOR_RIGHT;
+        case 0x48:
+            return GETCHAR_CURSOR_UP;
+        case 0x50:
+            return GETCHAR_CURSOR_DOWN;
+    }
     return (char)(r.eax & 0xff);
 }
 
+static void gets_reprint_string(int x, int y, const char *s, size_t limit) {
+    int last_x, last_y;
+    text_get_cursor_pos(&last_x, &last_y);
+    text_set_cursor_pos(x, y);
+    for (size_t i = 0; i < limit; i++) {
+        text_write(" ", 1);
+    }
+    text_set_cursor_pos(x, y);
+    text_write(s, strlen(s));
+    text_set_cursor_pos(last_x, last_y);
+}
+
 void gets(const char *orig_str, char *buf, size_t limit) {
     size_t orig_str_len = strlen(orig_str);
     memmove(buf, orig_str, orig_str_len);
-    text_write(orig_str, orig_str_len);
+    buf[orig_str_len] = 0;
+
+    int orig_x, orig_y;
+    text_get_cursor_pos(&orig_x, &orig_y);
+
+    print("%s", buf);
+
     for (size_t i = orig_str_len; ; ) {
-        char c = getchar();
+        int c = getchar();
         switch (c) {
+            case GETCHAR_CURSOR_LEFT:
+                if (i) {
+                    i--;
+                    text_write("\b", 1);
+                }
+                continue;
+            case GETCHAR_CURSOR_RIGHT:
+                if (i < strlen(buf)) {
+                    i++;
+                    text_write(" ", 1);
+                    gets_reprint_string(orig_x, orig_y, buf, limit);
+                }
+                continue;
             case '\b':
                 if (i) {
                     i--;
-                    text_write(&c, 1);
+                    for (size_t j = i; ; j++) {
+                        buf[j] = buf[j+1];
+                        if (!buf[j])
+                            break;
+                    }
+                    text_write("\b", 1);
+                    gets_reprint_string(orig_x, orig_y, buf, limit);
                 }
                 continue;
             case '\r':
-                buf[i] = 0;
                 text_write("\n", 1);
                 return;
-        }
-        if (i < limit-1) {
-            buf[i++] = c;
-            text_write(&c, 1);
+            default:
+                if (strlen(buf) < limit-1) {
+                    for (size_t j = strlen(buf); ; j--) {
+                        buf[j+1] = buf[j];
+                        if (j == i)
+                            break;
+                    }
+                    buf[i++] = c;
+                    text_write(" ", 1);
+                    gets_reprint_string(orig_x, orig_y, buf, limit);
+                }
         }
     }
 }
diff --git a/src/lib/blib.h b/src/lib/blib.h
index 146b406a..24c3ffdd 100644
--- a/src/lib/blib.h
+++ b/src/lib/blib.h
@@ -7,8 +7,13 @@
 void pit_sleep(uint64_t pit_ticks);
 int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks);
 
+#define GETCHAR_CURSOR_LEFT  (-10)
+#define GETCHAR_CURSOR_RIGHT (-11)
+#define GETCHAR_CURSOR_UP    (-12)
+#define GETCHAR_CURSOR_DOWN  (-13)
+
 void print(const char *fmt, ...);
-char getchar(void);
+int getchar(void);
 void gets(const char *orig_str, char *buf, size_t limit);
 uint64_t strtoui(const char *s);
 
tab: 248 wrap: offon