mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
performance improvements
* action() returns void - this gets rid of checks in vt_from_slave() * split up ACTION_PRINT into ACTION_PRINT (ASCII) and ACTION_UTF8_PRINT ACTION_PRINT is on the hot path, and we want it streamlined. * Remove run-time checkout for unimplemented state transitions, as we shouldn't have any of those left. * Don't re-load current VT state on each iteration in vt_from_slave()
This commit is contained in:
parent
050f7ea6ea
commit
d63629b370
5 changed files with 164 additions and 132 deletions
50
csi.c
50
csi.c
|
|
@ -91,12 +91,12 @@ sgr_reset(struct terminal *term)
|
||||||
term->vt.attrs.background = term->background;
|
term->vt.attrs.background = term->background;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
csi_sgr(struct terminal *term)
|
csi_sgr(struct terminal *term)
|
||||||
{
|
{
|
||||||
if (term->vt.params.idx == 0) {
|
if (term->vt.params.idx == 0) {
|
||||||
sgr_reset(term);
|
sgr_reset(term);
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < term->vt.params.idx; i++) {
|
for (size_t i = 0; i < term->vt.params.idx; i++) {
|
||||||
|
|
@ -162,7 +162,8 @@ csi_sgr(struct terminal *term)
|
||||||
i += 4;
|
i += 4;
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("invalid CSI SGR sequence");
|
LOG_ERR("invalid CSI SGR sequence");
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +209,8 @@ csi_sgr(struct terminal *term)
|
||||||
i += 4;
|
i += 4;
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("invalid CSI SGR sequence");
|
LOG_ERR("invalid CSI SGR sequence");
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -245,11 +247,10 @@ csi_sgr(struct terminal *term)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("unimplemented: CSI: SGR: %u", term->vt.params.v[i].value);
|
LOG_ERR("unimplemented: CSI: SGR: %u", term->vt.params.v[i].value);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -279,7 +280,7 @@ csi_as_string(struct terminal *term, uint8_t final)
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
csi_dispatch(struct terminal *term, uint8_t final)
|
csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
{
|
{
|
||||||
LOG_DBG("CSI: %s", csi_as_string(term, final));
|
LOG_DBG("CSI: %s", csi_as_string(term, final));
|
||||||
|
|
@ -287,7 +288,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
if (term->vt.intermediates.idx == 0) {
|
if (term->vt.intermediates.idx == 0) {
|
||||||
switch (final) {
|
switch (final) {
|
||||||
case 'c':
|
case 'c':
|
||||||
return write(term->ptmx, "\033[?6c", 5) == 5;
|
write(term->ptmx, "\033[?6c", 5);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'd': {
|
case 'd': {
|
||||||
/* VPA - vertical line position absolute */
|
/* VPA - vertical line position absolute */
|
||||||
|
|
@ -297,7 +299,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
return csi_sgr(term);
|
csi_sgr(term);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
term_cursor_up(term, param_get(term, 0, 1));
|
term_cursor_up(term, param_get(term, 0, 1));
|
||||||
|
|
@ -359,7 +362,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
default:
|
default:
|
||||||
LOG_ERR("CSI: %s: invalid argument: %d",
|
LOG_ERR("CSI: %s: invalid argument: %d",
|
||||||
csi_as_string(term, final), param);
|
csi_as_string(term, final), param);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
term_erase(term, start, end);
|
term_erase(term, start, end);
|
||||||
|
|
@ -394,7 +398,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
default:
|
default:
|
||||||
LOG_ERR("CSI: %s: invalid argument: %d",
|
LOG_ERR("CSI: %s: invalid argument: %d",
|
||||||
csi_as_string(term, final), param);
|
csi_as_string(term, final), param);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
term_erase(term, start, end);
|
term_erase(term, start, end);
|
||||||
|
|
@ -513,7 +518,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
* should provide our own terminfo with *only* \e[?1049h
|
* should provide our own terminfo with *only* \e[?1049h
|
||||||
* (and \e[?1049l for rmcup)
|
* (and \e[?1049l for rmcup)
|
||||||
*/
|
*/
|
||||||
LOG_WARN("ignoring CSI with final 't'");
|
LOG_WARN("ignoring CSI: %s", csi_as_string(term, final));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': {
|
case 'n': {
|
||||||
|
|
@ -536,13 +541,12 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
default:
|
default:
|
||||||
LOG_ERR("unimplemented: CSI: %s, parameter = %d",
|
LOG_ERR("unimplemented: CSI: %s, parameter = %d",
|
||||||
csi_as_string(term, final), param);
|
csi_as_string(term, final), param);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("CSI: %s: missing parameter", csi_as_string(term, final));
|
LOG_ERR("CSI: %s: missing parameter", csi_as_string(term, final));
|
||||||
return false;
|
abort();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -561,8 +565,6 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (term->vt.intermediates.idx == 1 &&
|
else if (term->vt.intermediates.idx == 1 &&
|
||||||
|
|
@ -746,8 +748,6 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (term->vt.intermediates.idx == 1 &&
|
else if (term->vt.intermediates.idx == 1 &&
|
||||||
|
|
@ -759,10 +759,12 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
LOG_ERR(
|
LOG_ERR(
|
||||||
"unimplemented: send device attributes with param = %d",
|
"unimplemented: send device attributes with param = %d",
|
||||||
param);
|
param);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return write(term->ptmx, "\033[?6c", 5) == 5;
|
write(term->ptmx, "\033[?6c", 5);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -775,6 +777,4 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
LOG_ERR("unimplemented: CSI: %s", csi_as_string(term, final));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
csi.h
2
csi.h
|
|
@ -3,4 +3,4 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
bool csi_dispatch(struct terminal *term, uint8_t final);
|
void csi_dispatch(struct terminal *term, uint8_t final);
|
||||||
|
|
|
||||||
9
osc.c
9
osc.c
|
|
@ -7,7 +7,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
bool
|
void
|
||||||
osc_dispatch(struct terminal *term)
|
osc_dispatch(struct terminal *term)
|
||||||
{
|
{
|
||||||
int param = 0;
|
int param = 0;
|
||||||
|
|
@ -24,7 +24,7 @@ osc_dispatch(struct terminal *term)
|
||||||
if (!isdigit(c)) {
|
if (!isdigit(c)) {
|
||||||
LOG_ERR("OSC: invalid parameter: %.*s",
|
LOG_ERR("OSC: invalid parameter: %.*s",
|
||||||
(int)term->vt.osc.idx, term->vt.osc.data);
|
(int)term->vt.osc.idx, term->vt.osc.data);
|
||||||
return false;
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
param *= 10;
|
param *= 10;
|
||||||
|
|
@ -47,8 +47,7 @@ osc_dispatch(struct terminal *term)
|
||||||
default:
|
default:
|
||||||
LOG_ERR("unimplemented: OSC: %.*s",
|
LOG_ERR("unimplemented: OSC: %.*s",
|
||||||
(int)term->vt.osc.idx, term->vt.osc.data);
|
(int)term->vt.osc.idx, term->vt.osc.data);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
osc.h
2
osc.h
|
|
@ -3,4 +3,4 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
bool osc_dispatch(struct terminal *term);
|
void osc_dispatch(struct terminal *term);
|
||||||
|
|
|
||||||
233
vt.c
233
vt.c
|
|
@ -63,8 +63,10 @@ enum action {
|
||||||
ACTION_UTF8_3_ENTRY,
|
ACTION_UTF8_3_ENTRY,
|
||||||
ACTION_UTF8_4_ENTRY,
|
ACTION_UTF8_4_ENTRY,
|
||||||
ACTION_UTF8_COLLECT,
|
ACTION_UTF8_COLLECT,
|
||||||
|
ACTION_UTF8_PRINT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
static const char *const state_names[] = {
|
static const char *const state_names[] = {
|
||||||
[STATE_SAME] = "no change",
|
[STATE_SAME] = "no change",
|
||||||
[STATE_GROUND] = "ground",
|
[STATE_GROUND] = "ground",
|
||||||
|
|
@ -89,7 +91,7 @@ static const char *const state_names[] = {
|
||||||
|
|
||||||
[STATE_UTF8_COLLECT] = "UTF-8",
|
[STATE_UTF8_COLLECT] = "UTF-8",
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
static const char *const action_names[] __attribute__((unused)) = {
|
static const char *const action_names[] __attribute__((unused)) = {
|
||||||
[ACTION_NONE] = "no action",
|
[ACTION_NONE] = "no action",
|
||||||
[ACTION_IGNORE] = "ignore",
|
[ACTION_IGNORE] = "ignore",
|
||||||
|
|
@ -111,6 +113,7 @@ static const char *const action_names[] __attribute__((unused)) = {
|
||||||
[ACTION_UTF8_3_ENTRY] = "UTF-8 (3 chars) begin",
|
[ACTION_UTF8_3_ENTRY] = "UTF-8 (3 chars) begin",
|
||||||
[ACTION_UTF8_4_ENTRY] = "UTF-8 (4 chars) begin",
|
[ACTION_UTF8_4_ENTRY] = "UTF-8 (4 chars) begin",
|
||||||
[ACTION_UTF8_COLLECT] = "UTF-8 collect",
|
[ACTION_UTF8_COLLECT] = "UTF-8 collect",
|
||||||
|
[ACTION_UTF8_PRINT] = "UTF-8 print",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct state_transition {
|
struct state_transition {
|
||||||
|
|
@ -566,7 +569,7 @@ esc_as_string(struct terminal *term, uint8_t final)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
esc_dispatch(struct terminal *term, uint8_t final)
|
esc_dispatch(struct terminal *term, uint8_t final)
|
||||||
{
|
{
|
||||||
LOG_DBG("ESC: %s", esc_as_string(term, final));
|
LOG_DBG("ESC: %s", esc_as_string(term, final));
|
||||||
|
|
@ -594,7 +597,8 @@ esc_dispatch(struct terminal *term, uint8_t final)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("%s: invalid charset identifier", esc_as_string(term, final));
|
LOG_ERR("%s: invalid charset identifier", esc_as_string(term, final));
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -611,7 +615,8 @@ esc_dispatch(struct terminal *term, uint8_t final)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("%s: invalid charset identifier", esc_as_string(term, final));
|
LOG_ERR("%s: invalid charset identifier", esc_as_string(term, final));
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -633,16 +638,104 @@ esc_dispatch(struct terminal *term, uint8_t final)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("unimplemented: ESC: %s", esc_as_string(term, final));
|
LOG_ERR("unimplemented: ESC: %s", esc_as_string(term, final));
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static inline void
|
||||||
action(struct terminal *term, enum action action, uint8_t c)
|
pre_print(struct terminal *term)
|
||||||
{
|
{
|
||||||
switch (action) {
|
if (unlikely(term->print_needs_wrap) && term->auto_margin) {
|
||||||
|
if (term->cursor.row == term->scroll_region.end - 1) {
|
||||||
|
term_scroll(term, 1);
|
||||||
|
term_cursor_to(term, term->cursor.row, 0);
|
||||||
|
} else
|
||||||
|
term_cursor_to(term, term->cursor.row + 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
post_print(struct terminal *term)
|
||||||
|
{
|
||||||
|
if (term->cursor.col < term->cols - 1)
|
||||||
|
term_cursor_right(term, 1);
|
||||||
|
else
|
||||||
|
term->print_needs_wrap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
print_insert(struct terminal *term)
|
||||||
|
{
|
||||||
|
if (unlikely(term->insert_mode)) {
|
||||||
|
assert(false && "untested");
|
||||||
|
grid_memmove(
|
||||||
|
term->grid, term->cursor.linear + 1, term->cursor.linear,
|
||||||
|
term->cols - term->cursor.col - 1);
|
||||||
|
term_damage_update(
|
||||||
|
term, term->cursor.linear + 1, term->cols - term->cursor.col - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action_print_utf8(struct terminal *term)
|
||||||
|
{
|
||||||
|
pre_print(term);
|
||||||
|
|
||||||
|
struct cell *cell = &term->grid->cur_line[term->cursor.col];
|
||||||
|
term_damage_update(term, term->cursor.linear, 1);
|
||||||
|
|
||||||
|
print_insert(term);
|
||||||
|
|
||||||
|
//LOG_DBG("print: UTF8: %.*s", (int)term->vt.utf8.idx, term->vt.utf8.data);
|
||||||
|
memcpy(cell->c, term->vt.utf8.data, term->vt.utf8.idx);
|
||||||
|
cell->c[term->vt.utf8.idx] = '\0';
|
||||||
|
term->vt.utf8.idx = 0;
|
||||||
|
|
||||||
|
cell->attrs = term->vt.attrs;
|
||||||
|
post_print(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action_print(struct terminal *term, uint8_t c)
|
||||||
|
{
|
||||||
|
pre_print(term);
|
||||||
|
|
||||||
|
struct cell *cell = &term->grid->cur_line[term->cursor.col];
|
||||||
|
term_damage_update(term, term->cursor.linear, 1);
|
||||||
|
|
||||||
|
print_insert(term);
|
||||||
|
|
||||||
|
static const char *const vt100_0[62] = { /* 0x41 - 0x7e */
|
||||||
|
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */
|
||||||
|
"◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */
|
||||||
|
"", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */
|
||||||
|
"⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
|
||||||
|
"│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
|
||||||
|
};
|
||||||
|
|
||||||
|
if (unlikely(term->charset[term->selected_charset] == CHARSET_GRAPHIC) &&
|
||||||
|
c >= 0x41 && c <= 0x7e)
|
||||||
|
{
|
||||||
|
strcpy(cell->c, vt100_0[c - 0x41]);
|
||||||
|
} else {
|
||||||
|
//LOG_DBG("print: ASCII: %c", c);
|
||||||
|
cell->c[0] = c;
|
||||||
|
cell->c[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->attrs = term->vt.attrs;
|
||||||
|
|
||||||
|
post_print(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action(struct terminal *term, enum action _action, uint8_t c)
|
||||||
|
{
|
||||||
|
switch (_action) {
|
||||||
case ACTION_NONE:
|
case ACTION_NONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -685,10 +778,11 @@ action(struct terminal *term, enum action action, uint8_t c)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("execute: unimplemented: %c (0x%02x)", c, c);
|
LOG_ERR("execute: unimplemented: %c (0x%02x)", c, c);
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
|
|
||||||
case ACTION_CLEAR:
|
case ACTION_CLEAR:
|
||||||
memset(&term->vt.params, 0, sizeof(term->vt.params));
|
memset(&term->vt.params, 0, sizeof(term->vt.params));
|
||||||
|
|
@ -697,64 +791,13 @@ action(struct terminal *term, enum action action, uint8_t c)
|
||||||
term->vt.utf8.idx = 0;
|
term->vt.utf8.idx = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_PRINT: {
|
case ACTION_PRINT:
|
||||||
if (unlikely(term->print_needs_wrap) && term->auto_margin) {
|
action_print(term, c);
|
||||||
if (term->cursor.row == term->scroll_region.end - 1) {
|
break;
|
||||||
term_scroll(term, 1);
|
|
||||||
term_cursor_to(term, term->cursor.row, 0);
|
case ACTION_UTF8_PRINT:
|
||||||
} else
|
action_print_utf8(term);
|
||||||
term_cursor_to(term, term->cursor.row + 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cell *cell = &term->grid->cur_line[term->cursor.col];
|
|
||||||
term_damage_update(term, term->cursor.linear, 1);
|
|
||||||
|
|
||||||
if (unlikely(term->insert_mode)) {
|
|
||||||
assert(false && "untested");
|
|
||||||
grid_memmove(
|
|
||||||
term->grid, term->cursor.linear + 1, term->cursor.linear,
|
|
||||||
term->cols - term->cursor.col - 1);
|
|
||||||
term_damage_update(
|
|
||||||
term, term->cursor.linear + 1, term->cols - term->cursor.col - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (term->vt.utf8.idx > 0) {
|
|
||||||
//LOG_DBG("print: UTF8: %.*s", (int)term->vt.utf8.idx, term->vt.utf8.data);
|
|
||||||
memcpy(cell->c, term->vt.utf8.data, term->vt.utf8.idx);
|
|
||||||
cell->c[term->vt.utf8.idx] = '\0';
|
|
||||||
term->vt.utf8.idx = 0;
|
|
||||||
} else {
|
|
||||||
static const char *const vt100_0[62] = { /* 0x41 - 0x7e */
|
|
||||||
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
|
|
||||||
0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */
|
|
||||||
"◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */
|
|
||||||
"", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */
|
|
||||||
"⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
|
|
||||||
"│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
|
|
||||||
};
|
|
||||||
|
|
||||||
if (unlikely(term->charset[term->selected_charset] == CHARSET_GRAPHIC) &&
|
|
||||||
c >= 0x41 && c <= 0x7e)
|
|
||||||
{
|
|
||||||
strcpy(cell->c, vt100_0[c - 0x41]);
|
|
||||||
} else {
|
|
||||||
//LOG_DBG("print: ASCII: %c", c);
|
|
||||||
cell->c[0] = c;
|
|
||||||
cell->c[1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cell->attrs = term->vt.attrs;
|
|
||||||
|
|
||||||
if (term->cursor.col < term->cols - 1)
|
|
||||||
term_cursor_right(term, 1);
|
|
||||||
else
|
|
||||||
term->print_needs_wrap = true;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case ACTION_PARAM:{
|
case ACTION_PARAM:{
|
||||||
if (term->vt.params.idx == 0)
|
if (term->vt.params.idx == 0)
|
||||||
|
|
@ -785,14 +828,16 @@ action(struct terminal *term, enum action action, uint8_t c)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
LOG_ERR("unimplemented: action ESC dispatch");
|
LOG_ERR("unimplemented: action ESC dispatch");
|
||||||
return false;
|
abort();
|
||||||
|
break;
|
||||||
|
|
||||||
case ACTION_ESC_DISPATCH:
|
case ACTION_ESC_DISPATCH:
|
||||||
return esc_dispatch(term, c);
|
esc_dispatch(term, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_CSI_DISPATCH:
|
case ACTION_CSI_DISPATCH:
|
||||||
return csi_dispatch(term, c);
|
csi_dispatch(term, c);
|
||||||
|
break;
|
||||||
|
|
||||||
case ACTION_OSC_START:
|
case ACTION_OSC_START:
|
||||||
term->vt.osc.idx = 0;
|
term->vt.osc.idx = 0;
|
||||||
|
|
@ -806,13 +851,14 @@ action(struct terminal *term, enum action action, uint8_t c)
|
||||||
case ACTION_OSC_END:
|
case ACTION_OSC_END:
|
||||||
assert(term->vt.osc.idx < sizeof(term->vt.osc.data));
|
assert(term->vt.osc.idx < sizeof(term->vt.osc.data));
|
||||||
term->vt.osc.data[term->vt.osc.idx] = '\0';
|
term->vt.osc.data[term->vt.osc.idx] = '\0';
|
||||||
return osc_dispatch(term);
|
osc_dispatch(term);
|
||||||
|
break;
|
||||||
|
|
||||||
case ACTION_HOOK:
|
case ACTION_HOOK:
|
||||||
case ACTION_UNHOOK:
|
case ACTION_UNHOOK:
|
||||||
case ACTION_PUT:
|
case ACTION_PUT:
|
||||||
LOG_ERR("unimplemented: action %s", action_names[action]);
|
LOG_ERR("unimplemented: action %s", action_names[_action]);
|
||||||
return false;
|
abort();
|
||||||
|
|
||||||
case ACTION_UTF8_2_ENTRY:
|
case ACTION_UTF8_2_ENTRY:
|
||||||
term->vt.utf8.idx = 0;
|
term->vt.utf8.idx = 0;
|
||||||
|
|
@ -837,51 +883,38 @@ action(struct terminal *term, enum action action, uint8_t c)
|
||||||
|
|
||||||
case ACTION_UTF8_COLLECT:
|
case ACTION_UTF8_COLLECT:
|
||||||
term->vt.utf8.data[term->vt.utf8.idx++] = c;
|
term->vt.utf8.data[term->vt.utf8.idx++] = c;
|
||||||
if (--term->vt.utf8.left == 0)
|
if (--term->vt.utf8.left == 0) {
|
||||||
term->vt.state = STATE_GROUND;
|
term->vt.state = STATE_GROUND;
|
||||||
|
action_print_utf8(term);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
//int cursor = term->grid.cursor;
|
//LOG_DBG("input: 0x%02x", data[i]);
|
||||||
|
enum state current_state = term->vt.state;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
//LOG_DBG("input: 0x%02x", data[i]);
|
|
||||||
enum state current_state = term->vt.state;
|
|
||||||
|
|
||||||
if (current_state == STATE_UTF8_COLLECT) {
|
if (current_state == STATE_UTF8_COLLECT) {
|
||||||
if (!action(term, ACTION_UTF8_COLLECT, data[i]))
|
action(term, ACTION_UTF8_COLLECT, data[i]);
|
||||||
abort();
|
|
||||||
|
|
||||||
current_state = term->vt.state;
|
current_state = term->vt.state;
|
||||||
if (current_state == STATE_UTF8_COLLECT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!action(term, ACTION_PRINT, 0))
|
|
||||||
abort();
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct state_transition *transition = &states[current_state][data[i]];
|
const struct state_transition *transition = &states[current_state][data[i]];
|
||||||
if (transition->action == ACTION_NONE && transition->state == STATE_SAME) {
|
assert(transition->action != ACTION_NONE || transition->state != STATE_SAME);
|
||||||
LOG_ERR("unimplemented transition from %s: 0x%02x",
|
|
||||||
state_names[current_state], data[i]);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transition->state != STATE_SAME) {
|
if (transition->state != STATE_SAME) {
|
||||||
enum action exit_action = exit_actions[current_state];
|
enum action exit_action = exit_actions[current_state];
|
||||||
if (exit_action != ACTION_NONE && !action(term, exit_action, data[i]))
|
action(term, exit_action, data[i]);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!action(term, transition->action, data[i]))
|
action(term, transition->action, data[i]);
|
||||||
abort();
|
|
||||||
|
|
||||||
if (transition->state != STATE_SAME) {
|
if (transition->state != STATE_SAME) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -889,10 +922,10 @@ vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
||||||
* state_names[transition->state]);
|
* state_names[transition->state]);
|
||||||
*/
|
*/
|
||||||
term->vt.state = transition->state;
|
term->vt.state = transition->state;
|
||||||
|
current_state = transition->state;
|
||||||
|
|
||||||
enum action entry_action = entry_actions[transition->state];
|
enum action entry_action = entry_actions[transition->state];
|
||||||
if (entry_action != ACTION_NONE && !action(term, entry_action, data[i]))
|
action(term, entry_action, data[i]);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue