mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-01 07:15:32 -04:00
wip: vt parsing
This commit is contained in:
parent
733223dd0c
commit
6d5f5b9f7a
4 changed files with 99 additions and 14 deletions
80
csi.c
80
csi.c
|
|
@ -1,5 +1,10 @@
|
||||||
#include "csi.h"
|
#include "csi.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define LOG_MODULE "csi"
|
#define LOG_MODULE "csi"
|
||||||
#define LOG_ENABLE_DBG 1
|
#define LOG_ENABLE_DBG 1
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
@ -69,6 +74,21 @@ csi_sgr(struct terminal *term)
|
||||||
return true;
|
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
|
bool
|
||||||
csi_dispatch(struct terminal *term, uint8_t final)
|
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]);
|
LOG_DBG(" #%zu: %u", j, term->vt.params.v[i].sub.value[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (final == 'm' && term->vt.intermediates.idx == 0) {
|
if (term->vt.intermediates.idx == 0) {
|
||||||
return csi_sgr(term);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
main.c
17
main.c
|
|
@ -40,7 +40,6 @@ struct wayland {
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
bool quit;
|
bool quit;
|
||||||
int ptmx;
|
|
||||||
|
|
||||||
cairo_scaled_font_t *font;
|
cairo_scaled_font_t *font;
|
||||||
cairo_font_extents_t fextents;
|
cairo_font_extents_t fextents;
|
||||||
|
|
@ -213,7 +212,7 @@ resize(struct context *c, int width, int height)
|
||||||
setenv("LINES", rows_s, 1);
|
setenv("LINES", rows_s, 1);
|
||||||
|
|
||||||
/* SIignal TIOCSWINSZ */
|
/* SIignal TIOCSWINSZ */
|
||||||
if (ioctl(c->ptmx, TIOCSWINSZ,
|
if (ioctl(c->term.ptmx, TIOCSWINSZ,
|
||||||
&(struct winsize){
|
&(struct winsize){
|
||||||
.ws_row = c->term.grid.rows,
|
.ws_row = c->term.grid.rows,
|
||||||
.ws_col = c->term.grid.cols,
|
.ws_col = c->term.grid.cols,
|
||||||
|
|
@ -380,8 +379,8 @@ main(int argc, const char *const *argv)
|
||||||
|
|
||||||
struct context c = {
|
struct context c = {
|
||||||
.quit = false,
|
.quit = false,
|
||||||
.ptmx = posix_openpt(O_RDWR | O_NOCTTY),
|
|
||||||
.term = {
|
.term = {
|
||||||
|
.ptmx = posix_openpt(O_RDWR | O_NOCTTY),
|
||||||
.vt = {
|
.vt = {
|
||||||
.state = 1,
|
.state = 1,
|
||||||
},
|
},
|
||||||
|
|
@ -401,7 +400,7 @@ main(int argc, const char *const *argv)
|
||||||
c.fextents.height, c.fextents.max_x_advance);
|
c.fextents.height, c.fextents.max_x_advance);
|
||||||
assert(c.fextents.max_y_advance == 0);
|
assert(c.fextents.max_y_advance == 0);
|
||||||
|
|
||||||
if (c.ptmx == -1) {
|
if (c.term.ptmx == -1) {
|
||||||
LOG_ERRNO("failed to open pseudo terminal");
|
LOG_ERRNO("failed to open pseudo terminal");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -468,7 +467,7 @@ main(int argc, const char *const *argv)
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
/* Child */
|
/* Child */
|
||||||
slave_spawn(c.ptmx);
|
slave_spawn(c.term.ptmx);
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -480,7 +479,7 @@ main(int argc, const char *const *argv)
|
||||||
while (true) {
|
while (true) {
|
||||||
struct pollfd fds[] = {
|
struct pollfd fds[] = {
|
||||||
{.fd = wl_display_get_fd(c.wl.display), .events = POLLIN},
|
{.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);
|
wl_display_flush(c.wl.display);
|
||||||
|
|
@ -501,7 +500,7 @@ main(int argc, const char *const *argv)
|
||||||
|
|
||||||
if (fds[1].revents & POLLIN) {
|
if (fds[1].revents & POLLIN) {
|
||||||
uint8_t data[1024];
|
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) {
|
if (count < 0) {
|
||||||
LOG_ERRNO("failed to read from pseudo terminal");
|
LOG_ERRNO("failed to read from pseudo terminal");
|
||||||
break;
|
break;
|
||||||
|
|
@ -544,8 +543,8 @@ out:
|
||||||
if (c.font != NULL)
|
if (c.font != NULL)
|
||||||
cairo_scaled_font_destroy(c.font);
|
cairo_scaled_font_destroy(c.font);
|
||||||
|
|
||||||
if (c.ptmx != -1)
|
if (c.term.ptmx != -1)
|
||||||
close(c.ptmx);
|
close(c.term.ptmx);
|
||||||
|
|
||||||
cairo_debug_reset_static_data();
|
cairo_debug_reset_static_data();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ struct vt {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct terminal {
|
struct terminal {
|
||||||
|
int ptmx;
|
||||||
struct vt vt;
|
struct vt vt;
|
||||||
struct grid grid;
|
struct grid grid;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
15
vt.c
15
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.cells[term->grid.cursor].dirty = true;
|
||||||
term->grid.cursor = term->grid.cursor / term->grid.cols * term->grid.cols;
|
term->grid.cursor = term->grid.cursor / term->grid.cols * term->grid.cols;
|
||||||
term->grid.cells[term->grid.cursor].dirty = true;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ACTION_CLEAR:
|
case ACTION_CLEAR:
|
||||||
|
|
@ -301,8 +310,10 @@ vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
if (transition->state != STATE_SAME) {
|
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;
|
term->vt.state = transition->state;
|
||||||
|
|
||||||
enum action entry_action = entry_actions[transition->state];
|
enum action entry_action = entry_actions[transition->state];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue