readline: Initial implementation
diff --git a/limine.bin b/limine.bin
index 4293c505..559ba57d 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index d2d2e1a6..1d89e5a5 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -206,71 +206,3 @@ int getchar(void) {
rm_int(0x16, &r, &r);
return getchar_internal(r.eax);
}
-
-static void gets_reprint_string(int x, int y, const char *s, size_t limit) {
- int last_x, last_y;
- get_cursor_pos(&last_x, &last_y);
- set_cursor_pos(x, y);
- for (size_t i = 0; i < limit; i++) {
- term_write(" ", 1);
- }
- set_cursor_pos(x, y);
- term_write(s, strlen(s));
- 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);
- buf[orig_str_len] = 0;
-
- int orig_x, orig_y;
- get_cursor_pos(&orig_x, &orig_y);
-
- print("%s", buf);
-
- for (size_t i = orig_str_len; ; ) {
- int c = getchar();
- switch (c) {
- case GETCHAR_CURSOR_LEFT:
- if (i) {
- i--;
- term_write("\b", 1);
- }
- continue;
- case GETCHAR_CURSOR_RIGHT:
- if (i < strlen(buf)) {
- i++;
- term_write(" ", 1);
- gets_reprint_string(orig_x, orig_y, buf, limit);
- }
- continue;
- case '\b':
- if (i) {
- i--;
- for (size_t j = i; ; j++) {
- buf[j] = buf[j+1];
- if (!buf[j])
- break;
- }
- term_write("\b", 1);
- gets_reprint_string(orig_x, orig_y, buf, limit);
- }
- continue;
- case '\r':
- term_write("\n", 1);
- return;
- 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;
- term_write(" ", 1);
- gets_reprint_string(orig_x, orig_y, buf, limit);
- }
- }
- }
-}
diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h
index 8dc60a53..f36c2dc8 100644
--- a/stage2/lib/blib.h
+++ b/stage2/lib/blib.h
@@ -33,7 +33,6 @@ int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks);
#define GETCHAR_CURSOR_DOWN (-13)
int getchar(void);
-void gets(const char *orig_str, char *buf, size_t limit);
uint64_t strtoui(const char *s);
uint64_t strtoui16(const char *s);
diff --git a/stage2/lib/readline.c b/stage2/lib/readline.c
new file mode 100644
index 00000000..59bfa662
--- /dev/null
+++ b/stage2/lib/readline.c
@@ -0,0 +1,100 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <lib/readline.h>
+#include <lib/libc.h>
+#include <lib/blib.h>
+#include <lib/term.h>
+
+static void reprint_string(int x, int y, const char *s) {
+ int orig_x, orig_y;
+ disable_cursor();
+ get_cursor_pos(&orig_x, &orig_y);
+ set_cursor_pos(x, y);
+ term_write(s, strlen(s));
+ set_cursor_pos(orig_x, orig_y);
+ enable_cursor();
+}
+
+static void cursor_back(void) {
+ int x, y;
+ get_cursor_pos(&x, &y);
+ if (x) {
+ x--;
+ } else if (y) {
+ y--;
+ x = term_cols - 1;
+ }
+ set_cursor_pos(x, y);
+}
+
+static void cursor_fwd(void) {
+ int x, y;
+ get_cursor_pos(&x, &y);
+ if (x < term_cols - 1) {
+ x++;
+ } else if (y < term_rows - 1) {
+ y++;
+ x = 0;
+ }
+ set_cursor_pos(x, y);
+}
+
+void readline(const char *orig_str, char *buf, size_t limit) {
+ size_t orig_str_len = strlen(orig_str);
+ memmove(buf, orig_str, orig_str_len);
+ buf[orig_str_len] = 0;
+
+ int orig_x, orig_y;
+ get_cursor_pos(&orig_x, &orig_y);
+
+ term_write(orig_str, orig_str_len);
+
+ for (size_t i = orig_str_len; ; ) {
+ int c = getchar();
+ switch (c) {
+ case GETCHAR_CURSOR_LEFT:
+ if (i) {
+ i--;
+ cursor_back();
+ }
+ continue;
+ case GETCHAR_CURSOR_RIGHT:
+ if (i < strlen(buf)) {
+ i++;
+ cursor_fwd();
+ }
+ continue;
+ case '\b':
+ if (i) {
+ i--;
+ cursor_back();
+ size_t j;
+ for (j = i; ; j++) {
+ buf[j] = buf[j+1];
+ if (!buf[j]) {
+ buf[j] = ' ';
+ break;
+ }
+ }
+ reprint_string(orig_x, orig_y, buf);
+ buf[j] = 0;
+ }
+ continue;
+ case '\r':
+ term_write("\n", 1);
+ return;
+ 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;
+ i++;
+ cursor_fwd();
+ reprint_string(orig_x, orig_y, buf);
+ }
+ }
+ }
+}
diff --git a/stage2/lib/readline.h b/stage2/lib/readline.h
new file mode 100644
index 00000000..44061fa3
--- /dev/null
+++ b/stage2/lib/readline.h
@@ -0,0 +1,8 @@
+#ifndef __LIB__READLINE_H__
+#define __LIB__READLINE_H__
+
+#include <stddef.h>
+
+void readline(const char *orig_str, char *buf, size_t limit);
+
+#endif
diff --git a/stage2/lib/term.c b/stage2/lib/term.c
index 2eb660a4..17f2f8bf 100644
--- a/stage2/lib/term.c
+++ b/stage2/lib/term.c
@@ -22,11 +22,11 @@ void (*get_cursor_pos)(int *x, int *y);
void (*set_text_fg)(int fg);
void (*set_text_bg)(int bg);
-static int rows, cols;
+int term_rows, term_cols;
void term_vbe(uint32_t *colours, int margin, int margin_gradient, struct image *background) {
term_deinit();
- vbe_tty_init(&rows, &cols, colours, margin, margin_gradient, background);
+ vbe_tty_init(&term_rows, &term_cols, colours, margin, margin_gradient, background);
raw_putchar = vbe_putchar;
clear = vbe_clear;
@@ -42,7 +42,7 @@ void term_vbe(uint32_t *colours, int margin, int margin_gradient, struct image *
void term_textmode(void) {
term_deinit();
- init_vga_textmode(&rows, &cols);
+ init_vga_textmode(&term_rows, &term_cols);
raw_putchar = text_putchar;
clear = text_clear;
@@ -156,16 +156,16 @@ static void escape_parse(char c) {
case 'B':
if (esc_default0)
esc_value0 = 1;
- if ((get_cursor_pos_y() + esc_value0) > (rows - 1))
- esc_value0 = (rows - 1) - get_cursor_pos_y();
+ if ((get_cursor_pos_y() + esc_value0) > (term_rows - 1))
+ esc_value0 = (term_rows - 1) - get_cursor_pos_y();
set_cursor_pos(get_cursor_pos_x(),
get_cursor_pos_y() + esc_value0);
break;
case 'C':
if (esc_default0)
esc_value0 = 1;
- if ((get_cursor_pos_x() + esc_value0) > (cols - 1))
- esc_value0 = (cols - 1) - get_cursor_pos_x();
+ if ((get_cursor_pos_x() + esc_value0) > (term_cols - 1))
+ esc_value0 = (term_cols - 1) - get_cursor_pos_x();
set_cursor_pos(get_cursor_pos_x() + esc_value0,
get_cursor_pos_y());
break;
@@ -184,10 +184,10 @@ static void escape_parse(char c) {
esc_value0 = 0;
if (esc_default1)
esc_value1 = 0;
- if (esc_value1 >= cols)
- esc_value1 = cols - 1;
- if (esc_value0 >= rows)
- esc_value0 = rows - 1;
+ if (esc_value1 >= term_cols)
+ esc_value1 = term_cols - 1;
+ if (esc_value0 >= term_rows)
+ esc_value0 = term_rows - 1;
set_cursor_pos(esc_value1, esc_value0);
break;
case 'm':
@@ -208,7 +208,7 @@ static void escape_parse(char c) {
int x = get_cursor_pos_x();
int y = get_cursor_pos_y();
set_cursor_pos(0, y);
- for (int i = 0; i < cols; i++)
+ for (int i = 0; i < term_cols; i++)
raw_putchar(' ');
set_cursor_pos(x, y);
break;
diff --git a/stage2/lib/term.h b/stage2/lib/term.h
index 9d7e967d..4bde2c32 100644
--- a/stage2/lib/term.h
+++ b/stage2/lib/term.h
@@ -19,4 +19,6 @@ void term_textmode(void);
void term_deinit(void);
void term_write(const char *buf, size_t count);
+extern int term_rows, term_cols;
+
#endif
diff --git a/stage2/menu.c b/stage2/menu.c
index 180eea1f..1952f7d5 100644
--- a/stage2/menu.c
+++ b/stage2/menu.c
@@ -8,6 +8,7 @@
#include <lib/libc.h>
#include <lib/config.h>
#include <lib/term.h>
+#include <lib/readline.h>
#include <mm/pmm.h>
#include <drivers/vbe.h>
@@ -193,7 +194,7 @@ timeout_aborted:
}
}
print("\n\n> ");
- gets(cmdline, cmdline, CMDLINE_MAX);
+ readline(cmdline, cmdline, CMDLINE_MAX);
clear(true);
return cmdline;
}
