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);
