From 6d5f5b9f7a716f7ca19a43f0d2357887e020d641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jun 2019 18:57:12 +0200 Subject: [PATCH] wip: vt parsing --- csi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- main.c | 17 ++++++------ terminal.h | 1 + vt.c | 15 ++++++++-- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/csi.c b/csi.c index 0720e67d..15e364f5 100644 --- a/csi.c +++ b/csi.c @@ -1,5 +1,10 @@ #include "csi.h" +#include +#include +#include +#include + #define LOG_MODULE "csi" #define LOG_ENABLE_DBG 1 #include "log.h" @@ -69,6 +74,21 @@ csi_sgr(struct terminal *term) return true; } +static bool +erase(struct terminal *term, int start, int end) +{ + for (int i = start; i < end; i++) { + struct cell *cell = &term->grid.cells[i]; + memset(cell, 0, sizeof(*cell)); + cell->attrs.foreground = term->grid.foreground; + cell->attrs.background = term->grid.background; + cell->dirty = true; + term->grid.dirty = true; + } + + return true; +} + bool csi_dispatch(struct terminal *term, uint8_t final) { @@ -79,9 +99,63 @@ csi_dispatch(struct terminal *term, uint8_t final) LOG_DBG(" #%zu: %u", j, term->vt.params.v[i].sub.value[j]); } - if (final == 'm' && term->vt.intermediates.idx == 0) { - return csi_sgr(term); + if (term->vt.intermediates.idx == 0) { + switch (final) { + case 'c': + write(term->ptmx, "\033[?6c", 5); + return true; + + case 'm': + return csi_sgr(term); + + case 'J': { + assert(term->vt.params.idx == 0); + int start = term->grid.cursor / term->grid.cols * term->grid.cols; + int end = term->grid.cols * term->grid.rows; + return erase(term, start, end); + } + + case 'K': { + assert(term->vt.params.idx == 0); + int start = term->grid.cursor; + int end = (start + term->grid.cols - 1) / term->grid.cols * term->grid.cols - 1; + assert(start <= end); + assert((end + 1) % term->grid.cols == 0); + + return erase(term, start, end); + } + + case 'C': { + int count = term->vt.params.idx > 0 ? term->vt.params.v[0].value : 1; + int new_cursor = term->grid.cursor + count; + term->grid.cells[term->grid.cursor].dirty = true; + term->grid.cells[new_cursor].dirty = true; + term->grid.cursor = new_cursor; + term->grid.dirty = true; + return true; + } + + case 'D': { + int count = term->vt.params.idx > 0 ? term->vt.params.v[0].value : 1; + int new_cursor = term->grid.cursor - count; + term->grid.cells[term->grid.cursor].dirty = true; + term->grid.cells[new_cursor].dirty = true; + term->grid.cursor = new_cursor; + term->grid.dirty = true; + return true; + } + + default: + LOG_ERR("CSI: unimplemented final: %c", final); + abort(); + } + } else { + LOG_ERR("CSI: unimplemented: intermediates: %.*s", + (int)term->vt.intermediates.idx, + term->vt.intermediates.data); + //abort(); + return true; } - return true; + return false; } diff --git a/main.c b/main.c index e339ea61..bc47420f 100644 --- a/main.c +++ b/main.c @@ -40,7 +40,6 @@ struct wayland { struct context { bool quit; - int ptmx; cairo_scaled_font_t *font; cairo_font_extents_t fextents; @@ -213,7 +212,7 @@ resize(struct context *c, int width, int height) setenv("LINES", rows_s, 1); /* SIignal TIOCSWINSZ */ - if (ioctl(c->ptmx, TIOCSWINSZ, + if (ioctl(c->term.ptmx, TIOCSWINSZ, &(struct winsize){ .ws_row = c->term.grid.rows, .ws_col = c->term.grid.cols, @@ -380,8 +379,8 @@ main(int argc, const char *const *argv) struct context c = { .quit = false, - .ptmx = posix_openpt(O_RDWR | O_NOCTTY), .term = { + .ptmx = posix_openpt(O_RDWR | O_NOCTTY), .vt = { .state = 1, }, @@ -401,7 +400,7 @@ main(int argc, const char *const *argv) c.fextents.height, c.fextents.max_x_advance); assert(c.fextents.max_y_advance == 0); - if (c.ptmx == -1) { + if (c.term.ptmx == -1) { LOG_ERRNO("failed to open pseudo terminal"); goto out; } @@ -468,7 +467,7 @@ main(int argc, const char *const *argv) case 0: /* Child */ - slave_spawn(c.ptmx); + slave_spawn(c.term.ptmx); assert(false); break; @@ -480,7 +479,7 @@ main(int argc, const char *const *argv) while (true) { struct pollfd fds[] = { {.fd = wl_display_get_fd(c.wl.display), .events = POLLIN}, - {.fd = c.ptmx, .events = POLLIN}, + {.fd = c.term.ptmx, .events = POLLIN}, }; wl_display_flush(c.wl.display); @@ -501,7 +500,7 @@ main(int argc, const char *const *argv) if (fds[1].revents & POLLIN) { uint8_t data[1024]; - ssize_t count = read(c.ptmx, data, sizeof(data)); + ssize_t count = read(c.term.ptmx, data, sizeof(data)); if (count < 0) { LOG_ERRNO("failed to read from pseudo terminal"); break; @@ -544,8 +543,8 @@ out: if (c.font != NULL) cairo_scaled_font_destroy(c.font); - if (c.ptmx != -1) - close(c.ptmx); + if (c.term.ptmx != -1) + close(c.term.ptmx); cairo_debug_reset_static_data(); return ret; diff --git a/terminal.h b/terminal.h index d5f9ef34..bc0bca56 100644 --- a/terminal.h +++ b/terminal.h @@ -68,6 +68,7 @@ struct vt { }; struct terminal { + int ptmx; struct vt vt; struct grid grid; }; diff --git a/vt.c b/vt.c index 086ce071..3b6d98c3 100644 --- a/vt.c +++ b/vt.c @@ -160,8 +160,17 @@ action(struct terminal *term, enum action action, uint8_t c) term->grid.cells[term->grid.cursor].dirty = true; term->grid.cursor = term->grid.cursor / term->grid.cols * term->grid.cols; term->grid.cells[term->grid.cursor].dirty = true; + term->grid.dirty = true; + break; + + case '\b': + term->grid.cells[term->grid.cursor].dirty = true; + term->grid.cursor--; + term->grid.cells[term->grid.cursor].dirty = true; + term->grid.dirty = true; break; } + return true; case ACTION_CLEAR: @@ -301,8 +310,10 @@ vt_from_slave(struct terminal *term, const uint8_t *data, size_t len) abort(); if (transition->state != STATE_SAME) { - LOG_DBG("transition: %s -> %s", state_names[current_state], - state_names[transition->state]); + /* + * LOG_DBG("transition: %s -> %s", state_names[current_state], + * state_names[transition->state]); + */ term->vt.state = transition->state; enum action entry_action = entry_actions[transition->state];