diff options
author | Alex Auvolat <alex@adnab.me> | 2015-03-14 16:16:53 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2015-03-14 16:16:53 +0100 |
commit | 57c5eceb846f3109d017b4e6d4cbd7c507c0d098 (patch) | |
tree | d4aa0917310a5ad7925736f9dadc07bcb5734383 /src/sysbin/terminal/main.c | |
parent | f574c22f86d90f735107fda199bb5b4982cd9621 (diff) | |
download | kogata-57c5eceb846f3109d017b4e6d4cbd7c507c0d098.tar.gz kogata-57c5eceb846f3109d017b4e6d4cbd7c507c0d098.zip |
Begin implement escape sequence handling in terminal.
Diffstat (limited to 'src/sysbin/terminal/main.c')
-rw-r--r-- | src/sysbin/terminal/main.c | 209 |
1 files changed, 164 insertions, 45 deletions
diff --git a/src/sysbin/terminal/main.c b/src/sysbin/terminal/main.c index 1174305..f0e77e3 100644 --- a/src/sysbin/terminal/main.c +++ b/src/sysbin/terminal/main.c @@ -7,6 +7,27 @@ #include <draw.h> #include <keyboard.h> +#define NCOLORS 16 + +const int vga_colors[NCOLORS] = { + 0x000000, + 0x0000AA, + 0x00AA00, + 0x00AAAA, + 0xAA0000, + 0xAA00AA, + 0xAA5500, + 0xAAAAAA, + 0x555555, + 0x5555FF, + 0x55FF55, + 0x55FFFF, + 0xFF5555, + 0xFF55FF, + 0xFFFF55, + 0xFFFFFF, +}; + typedef char tchar_t; typedef struct { @@ -18,7 +39,12 @@ typedef struct { font_t *font; int cw, ch; // size of a character - color_t fg, bg; + + color_t colors[NCOLORS]; + color_t fg, bg, csr_bg; + + char esc_seq[10]; // current escape sequence + int esc_seq_len; // current escape sequence length keyboard_t *kb; @@ -32,16 +58,17 @@ typedef struct { char wr_c_buf; } term_t; -void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m); -void c_key_down(gip_handler_t *s, gip_msg_header *p); -void c_key_up(gip_handler_t *s, gip_msg_header *p); -void c_unknown_msg(gip_handler_t *s, gip_msg_header *p); -void c_fd_error(gip_handler_t *s); +void gip_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m); +void gip_key_down(gip_handler_t *s, gip_msg_header *p); +void gip_key_up(gip_handler_t *s, gip_msg_header *p); +void gip_unknown_msg(gip_handler_t *s, gip_msg_header *p); +void gip_fd_error(gip_handler_t *s); + +void gip_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata); void term_on_rd_c(mainloop_fd_t *fd); void term_app_on_error(mainloop_fd_t *fd); -void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata); gip_handler_callbacks_t term_gip_cb = { .reset = 0, @@ -52,13 +79,13 @@ gip_handler_callbacks_t term_gip_cb = { .disable_features = 0, .query_mode = 0, .set_mode = 0, - .buffer_info = c_buffer_info, + .buffer_info = gip_buffer_info, .mode_info = 0, .buffer_damage = 0, - .key_down = c_key_down, - .key_up = c_key_up, - .unknown_msg = c_unknown_msg, - .fd_error = c_fd_error, + .key_down = gip_key_down, + .key_up = gip_key_up, + .unknown_msg = gip_unknown_msg, + .fd_error = gip_fd_error, }; @@ -89,7 +116,7 @@ int main(int argc, char **argv) { mainloop_expect(&term.app, &term.rd_c_buf, 1, term_on_rd_c); gip_msg_header reset_msg = { .code = GIPC_RESET, .arg = 0 }; - gip_cmd(h, &reset_msg, 0, c_async_initiate, 0); + gip_cmd(h, &reset_msg, 0, gip_async_initiate, 0); mainloop_run(); @@ -100,7 +127,7 @@ int main(int argc, char **argv) { void term_draw_c(term_t *t, int l, int c) { color_t bg = t->bg; - if (l == t->csrl && c == t->csrc) bg = g_color_rgb(t->fb, 0, 100, 0); + if (l == t->csrl && c == t->csrc) bg = t->csr_bg; char ss[2]; ss[0] = t->scr_chars[l * t->w + c]; @@ -120,6 +147,13 @@ void term_move_cursor(term_t *t, int l, int c) { term_draw_c(t, l, c); } +void term_put_at(term_t *t, int l, int c, tchar_t ch) { + if (t->scr_chars[l * t->w + c] == ch) return; + + t->scr_chars[l * t->w + c] = ch; + term_draw_c(t, l, c); +} + void term_clear_screen(term_t *t) { t->csr_visible = true; @@ -146,32 +180,111 @@ void term_scroll1(term_t *t) { } void term_putc(term_t *t, int c) { - int nl = t->csrl, nc = t->csrc; - if (c == '\n') { - nl++; nc = 0; - } else if (c == '\b') { - if (nc > 0) { - nc--; - } else { + if (t->esc_seq_len > 0 || c == '\e') { + t->esc_seq[t->esc_seq_len++] = c; + + // parse escape sequence + if (t->esc_seq_len >= 2) { + if (t->esc_seq[1] == '[') { + int n = 0, m = -1; + int i = 2; + for (; i < t->esc_seq_len && t->esc_seq[i] >= '0' && t->esc_seq[i] <= '9'; i++) { + n = (n * 10) + (t->esc_seq[i] - '0'); + } + if (i == t->esc_seq_len) return; // incomplete sequence + if (t->esc_seq[i] == ';') { + i++; + m = 0; + for (; i < t->esc_seq_len && t->esc_seq[i] >= '0' && t->esc_seq[i] <= '9'; i++) { + m = (m * 10) + (t->esc_seq[i] - 0); + } + if (i == t->esc_seq_len) return; // incomplete sequence + } + // TODO implement escape sequence handling + if (t->esc_seq[i] == 'A') { + // move cursor up + } else if (t->esc_seq[i] == 'B') { + // move cursor down + } else if (t->esc_seq[i] == 'C') { + // move cursor forward + } else if (t->esc_seq[i] == 'D') { + // move cursor back + } else if (t->esc_seq[i] == 'E') { + // move cursor n lines down to begin of line + } else if (t->esc_seq[i] == 'F') { + // move cursor n lines up to begin of line + } else if (t->esc_seq[i] == 'H' || t->esc_seq[i] == 'f') { + // move cursor to position (n, m) + } else if (t->esc_seq[i] == 'J' || t->esc_seq[i] == 'K') { + // erase data/line + } else if (t->esc_seq[i] == 'S') { + // scroll up n lines + } else if (t->esc_seq[i] == 'T') { + // scroll down n lines + } else if (t->esc_seq[i] == 'm') { + // select graphic rendition (ie color) + if (n == 0) { + t->fg = t->colors[7]; + t->bg = t->colors[0]; + } else if (n >= 30 && n <= 37) { + t->fg = t->colors[n - 30]; + } else if (n == 39) { + t->fg = t->colors[7]; + } else if (n >= 40 && n <= 47) { + t->bg = t->colors[n - 40]; + } else if (n == 49) { + t->bg = t->colors[0]; + } + } else if (t->esc_seq[i] == 'n') { + // device status report + } else if (t->esc_seq[i] == 's') { + // save cursor position + } else if (t->esc_seq[i] == 'p') { + // restore cursor position + } + } + t->esc_seq_len = 0; // sequence finished + } + } else { + int nl = t->csrl, nc = t->csrc; + if (c == '\n') { + nl++; nc = 0; + } else if (c == '\r') { + while (nc > 0) { + nc--; + term_put_at(t, nl, nc, ' '); + } + nc = 0; + } else if (c == '\f') { + term_clear_screen(t); + return; + } else if (c == '\b') { + if (nc > 0) { + nc--; + } else { + nl--; + nc = t->w - 1; + } + term_put_at(t, nl, nc, ' '); + } else if (c == '\t') { + while (nc % 8 != 0) { + term_put_at(t, nl, nc, ' '); + nc++; + } + } else if (c >= ' ' && c < 128) { + term_put_at(t, nl, nc, c); + nc++; + } + if (nc >= t->w) { + nc = 0; + nl++; + } + if (nl >= t->h) { + term_scroll1(t); nl--; - nc = t->w - 1; } - t->scr_chars[nl * t->w + nc] = ' '; - } else if (c == '\t') { - while (nc % 4 != 0) nc++; - } else if (c >= ' ' && c < 128) { - t->scr_chars[nl * t->w + nc] = c; - nc++; - } - if (nc >= t->w) { - nc = 0; - nl++; + term_move_cursor(t, nl, nc); } - if (nl >= t->h) { - term_scroll1(t); - nl--; - } - term_move_cursor(t, nl, nc); } void term_puts(term_t *t, char* s) { @@ -183,7 +296,7 @@ void term_puts(term_t *t, char* s) { // GIP client connection -void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) { +void gip_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) { dbg_printf("[terminal] Got buffer info msg\n"); term_t *c = (term_t*)s->data; @@ -215,8 +328,14 @@ void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) c->fb = g_fb_from_file(c->fd, &m->geom); if (c->fb != 0) { - c->bg = g_color_rgb(c->fb, 0, 0, 0); - c->fg = g_color_rgb(c->fb, 200, 200, 200); + for (int i = 0; i < NCOLORS; i++) { + c->colors[i] = g_color_rgb(c->fb, (vga_colors[i] >> 16) & 0xFF, + (vga_colors[i] >> 8) & 0xFF, vga_colors[i] & 0xFF); + } + c->bg = c->colors[0]; + c->fg = c->colors[7]; + c->csr_bg = c->colors[2]; + term_clear_screen(c); mainloop_rm_fd(&c->app); @@ -228,7 +347,7 @@ void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) } } -void c_key_down(gip_handler_t *s, gip_msg_header *p) { +void gip_key_down(gip_handler_t *s, gip_msg_header *p) { term_t *c = (term_t*)s->data; key_t k = keyboard_press(c->kb, p->arg); @@ -244,17 +363,17 @@ void c_key_down(gip_handler_t *s, gip_msg_header *p) { mainloop_nonblocking_write(&c->app, &c->wr_c_buf, 1, false); } -void c_key_up(gip_handler_t *s, gip_msg_header *p) { +void gip_key_up(gip_handler_t *s, gip_msg_header *p) { term_t *c = (term_t*)s->data; keyboard_release(c->kb, p->arg); } -void c_unknown_msg(gip_handler_t *s, gip_msg_header *p) { +void gip_unknown_msg(gip_handler_t *s, gip_msg_header *p) { // TODO } -void c_fd_error(gip_handler_t *s) { +void gip_fd_error(gip_handler_t *s) { // TODO } @@ -268,7 +387,7 @@ void term_app_on_error(mainloop_fd_t *fd) { // TODO } -void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata) { +void gip_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata) { term_t *c = (term_t*)s->data; c->sv_features = p->arg; |