readline: Initial implementation

This commit is contained in:
mintsuki 2020-10-27 08:09:27 +01:00
parent b8b7a798d4
commit 530b4a8f3b
8 changed files with 124 additions and 82 deletions

Binary file not shown.

View File

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

View File

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

100
stage2/lib/readline.c Normal file
View File

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

8
stage2/lib/readline.h Normal file
View File

@ -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

View File

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

View File

@ -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

View File

@ -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;
}