2019-06-15 22:22:44 +02:00
|
|
|
#include "vt.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2019-07-15 15:42:00 +02:00
|
|
|
#include <unistd.h>
|
2019-06-15 22:22:44 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
#define LOG_MODULE "vt"
|
2019-07-03 20:21:03 +02:00
|
|
|
#define LOG_ENABLE_DBG 0
|
2019-06-15 22:22:44 +02:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "csi.h"
|
2020-01-12 11:55:22 +01:00
|
|
|
#include "dcs.h"
|
2019-06-17 19:33:10 +02:00
|
|
|
#include "grid.h"
|
2019-07-19 09:55:07 +02:00
|
|
|
#include "osc.h"
|
2019-06-15 22:22:44 +02:00
|
|
|
|
2019-11-30 00:32:34 +01:00
|
|
|
#define min(x, y) ((x) < (y) ? (x) : (y))
|
2019-08-30 22:08:37 +02:00
|
|
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
|
|
|
|
|
2019-11-29 23:59:24 +01:00
|
|
|
#define UNHANDLED() LOG_DBG("unhandled: %s", esc_as_string(term, final))
|
2019-07-30 21:42:46 +02:00
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
/* https://vt100.net/emu/dec_ansi_parser */
|
|
|
|
|
|
|
|
|
|
enum state {
|
|
|
|
|
STATE_GROUND,
|
2019-06-23 13:28:55 +02:00
|
|
|
STATE_ESCAPE,
|
|
|
|
|
STATE_ESCAPE_INTERMEDIATE,
|
|
|
|
|
|
|
|
|
|
STATE_CSI_ENTRY,
|
|
|
|
|
STATE_CSI_PARAM,
|
|
|
|
|
STATE_CSI_INTERMEDIATE,
|
|
|
|
|
STATE_CSI_IGNORE,
|
|
|
|
|
|
|
|
|
|
STATE_OSC_STRING,
|
|
|
|
|
|
|
|
|
|
STATE_DCS_ENTRY,
|
|
|
|
|
STATE_DCS_PARAM,
|
|
|
|
|
STATE_DCS_INTERMEDIATE,
|
|
|
|
|
STATE_DCS_IGNORE,
|
|
|
|
|
STATE_DCS_PASSTHROUGH,
|
2019-06-15 22:22:44 +02:00
|
|
|
|
2019-06-23 13:28:55 +02:00
|
|
|
STATE_SOS_PM_APC_STRING,
|
|
|
|
|
|
2019-12-20 22:10:27 +01:00
|
|
|
STATE_UTF8_COLLECT_1,
|
|
|
|
|
STATE_UTF8_COLLECT_2,
|
|
|
|
|
STATE_UTF8_COLLECT_3,
|
2019-06-15 22:22:44 +02:00
|
|
|
};
|
|
|
|
|
|
2019-11-05 13:55:43 +01:00
|
|
|
#if defined(_DEBUG) && defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG && 0
|
2019-06-15 22:22:44 +02:00
|
|
|
static const char *const state_names[] = {
|
|
|
|
|
[STATE_GROUND] = "ground",
|
|
|
|
|
|
2019-06-23 13:28:55 +02:00
|
|
|
[STATE_ESCAPE] = "escape",
|
|
|
|
|
[STATE_ESCAPE_INTERMEDIATE] = "escape intermediate",
|
|
|
|
|
|
|
|
|
|
[STATE_CSI_ENTRY] = "CSI entry",
|
|
|
|
|
[STATE_CSI_PARAM] = "CSI param",
|
|
|
|
|
[STATE_CSI_INTERMEDIATE] = "CSI intermediate",
|
|
|
|
|
[STATE_CSI_IGNORE] = "CSI ignore",
|
|
|
|
|
|
|
|
|
|
[STATE_OSC_STRING] = "OSC string",
|
|
|
|
|
|
|
|
|
|
[STATE_DCS_ENTRY] = "DCS entry",
|
|
|
|
|
[STATE_DCS_PARAM] = "DCS param",
|
|
|
|
|
[STATE_DCS_INTERMEDIATE] = "DCS intermediate",
|
|
|
|
|
[STATE_DCS_IGNORE] = "DCS ignore",
|
|
|
|
|
[STATE_DCS_PASSTHROUGH] = "DCS passthrough",
|
|
|
|
|
|
|
|
|
|
[STATE_SOS_PM_APC_STRING] = "sos/pm/apc string",
|
|
|
|
|
|
2019-12-20 22:10:27 +01:00
|
|
|
[STATE_UTF8_COLLECT_1] = "UTF8 collect (1 left)",
|
|
|
|
|
[STATE_UTF8_COLLECT_2] = "UTF8 collect (2 left)",
|
|
|
|
|
[STATE_UTF8_COLLECT_3] = "UTF8 collect (3 left)",
|
2019-06-15 22:22:44 +02:00
|
|
|
};
|
2019-12-20 22:10:27 +01:00
|
|
|
#endif
|
2019-06-15 22:22:44 +02:00
|
|
|
|
2019-11-30 00:02:19 +01:00
|
|
|
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
2019-07-04 19:35:01 +02:00
|
|
|
static const char *
|
|
|
|
|
esc_as_string(struct terminal *term, uint8_t final)
|
2019-06-23 13:36:20 +02:00
|
|
|
{
|
2019-07-04 19:35:01 +02:00
|
|
|
static char msg[1024];
|
2019-07-10 16:04:25 +02:00
|
|
|
int c = snprintf(msg, sizeof(msg), "\\E");
|
2019-06-23 13:36:20 +02:00
|
|
|
|
2019-07-19 09:56:59 +02:00
|
|
|
for (size_t i = 0; i < sizeof(term->vt.private) / sizeof(term->vt.private[0]); i++) {
|
|
|
|
|
if (term->vt.private[i] == 0)
|
|
|
|
|
break;
|
|
|
|
|
c += snprintf(&msg[c], sizeof(msg) - c, "%c", term->vt.private[i]);
|
|
|
|
|
}
|
2019-06-23 13:36:20 +02:00
|
|
|
|
2019-07-15 13:39:19 +02:00
|
|
|
assert(term->vt.params.idx == 0);
|
|
|
|
|
|
2019-11-05 10:39:36 +01:00
|
|
|
snprintf(&msg[c], sizeof(msg) - c, "%c", final);
|
2019-07-04 19:35:01 +02:00
|
|
|
return msg;
|
|
|
|
|
|
|
|
|
|
}
|
2019-11-30 00:02:19 +01:00
|
|
|
#endif
|
2019-07-04 19:35:01 +02:00
|
|
|
|
2019-07-07 16:32:18 +02:00
|
|
|
static void
|
2019-12-20 23:27:15 +01:00
|
|
|
action_ignore(struct terminal *term)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_clear(struct terminal *term)
|
|
|
|
|
{
|
|
|
|
|
term->vt.params.idx = 0;
|
|
|
|
|
term->vt.private[0] = 0;
|
|
|
|
|
term->vt.private[1] = 0;
|
|
|
|
|
term->vt.utf8.idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_execute(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
LOG_DBG("execute: 0x%02x", c);
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 7-bit C0 control characters
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
case '\0':
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
/* LF - line feed */
|
|
|
|
|
term_linefeed(term);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\r':
|
|
|
|
|
/* FF - form feed */
|
|
|
|
|
term_cursor_left(term, term->cursor.point.col);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\b':
|
|
|
|
|
/* backspace */
|
|
|
|
|
term_cursor_left(term, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\x07':
|
|
|
|
|
/* BEL */
|
|
|
|
|
// LOG_INFO("BELL");
|
|
|
|
|
// term_flash(term, 50);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\x09': {
|
|
|
|
|
/* HT - horizontal tab */
|
|
|
|
|
int new_col = term->cols - 1;
|
|
|
|
|
tll_foreach(term->tab_stops, it) {
|
|
|
|
|
if (it->item > term->cursor.point.col) {
|
|
|
|
|
new_col = it->item;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert(new_col >= term->cursor.point.col);
|
|
|
|
|
term_cursor_right(term, new_col - term->cursor.point.col);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '\x0b':
|
|
|
|
|
/* VT - vertical tab */
|
|
|
|
|
term_cursor_down(term, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\x0e':
|
|
|
|
|
/* SO - shift out */
|
|
|
|
|
term->charsets.selected = 1; /* G1 */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\x0f':
|
|
|
|
|
/* SI - shift in */
|
|
|
|
|
term->charsets.selected = 0; /* G0 */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 8-bit C1 control characters
|
|
|
|
|
*
|
|
|
|
|
* We ignore these, but keep them here for reference, along
|
|
|
|
|
* with their corresponding 7-bit variants.
|
|
|
|
|
*
|
|
|
|
|
* As far as I can tell, XTerm also ignores these _when in
|
|
|
|
|
* UTF-8 mode_. Which would be the normal mode of operation
|
|
|
|
|
* these days. And since we _only_ support UTF-8...
|
|
|
|
|
*/
|
|
|
|
|
#if 0
|
|
|
|
|
case '\x84': /* IND -> ESC D */
|
|
|
|
|
case '\x85': /* NEL -> ESC E */
|
|
|
|
|
case '\x88': /* Tab Set -> ESC H */
|
|
|
|
|
case '\x8d': /* RI -> ESC M */
|
|
|
|
|
case '\x8e': /* SS2 -> ESC N */
|
|
|
|
|
case '\x8f': /* SS3 -> ESC O */
|
|
|
|
|
case '\x90': /* DCS -> ESC P */
|
|
|
|
|
case '\x96': /* SPA -> ESC V */
|
|
|
|
|
case '\x97': /* EPA -> ESC W */
|
|
|
|
|
case '\x98': /* SOS -> ESC X */
|
|
|
|
|
case '\x9a': /* DECID -> ESC Z (obsolete form of CSI c) */
|
|
|
|
|
case '\x9b': /* CSI -> ESC [ */
|
|
|
|
|
case '\x9c': /* ST -> ESC \ */
|
|
|
|
|
case '\x9d': /* OSC -> ESC ] */
|
|
|
|
|
case '\x9e': /* PM -> ESC ^ */
|
|
|
|
|
case '\x9f': /* APC -> ESC _ */
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_print(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
/* 0x60 - 0x7e */
|
|
|
|
|
static const wchar_t vt100_0[] = {
|
|
|
|
|
L'◆', L'▒', L'␉', L'␌', L'␍', L'␊', L'°', L'±', /* ` - g */
|
|
|
|
|
L'', L'␋', L'┘', L'┐', L'┌', L'└', L'┼', L'⎺', /* h - o */
|
|
|
|
|
L'⎻', L'─', L'⎼', L'⎽', L'├', L'┤', L'┴', L'┬', /* p - w */
|
|
|
|
|
L'│', L'≤', L'≥', L'π', L'≠', L'£', L'·', /* x - ~ */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (unlikely(term->charsets.set[term->charsets.selected] == CHARSET_GRAPHIC) &&
|
|
|
|
|
c >= 0x60 && c <= 0x7e)
|
|
|
|
|
{
|
2020-01-20 18:34:32 +01:00
|
|
|
term_print(term, vt100_0[c - 0x60], 1);
|
2019-12-20 23:27:15 +01:00
|
|
|
} else {
|
2020-01-20 18:34:32 +01:00
|
|
|
term_print(term, c, 1);
|
2019-12-20 23:27:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_param(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
if (term->vt.params.idx == 0) {
|
|
|
|
|
struct vt_param *param = &term->vt.params.v[0];
|
|
|
|
|
param->value = 0;
|
|
|
|
|
param->sub.idx = 0;
|
|
|
|
|
term->vt.params.idx = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c == ';') {
|
|
|
|
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx++];
|
|
|
|
|
param->value = 0;
|
|
|
|
|
param->sub.idx = 0;
|
|
|
|
|
} else if (c == ':') {
|
|
|
|
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
|
|
|
param->sub.value[param->sub.idx++] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
assert(term->vt.params.idx >= 0);
|
|
|
|
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
|
|
|
|
|
|
|
|
unsigned *value = param->sub.idx > 0
|
|
|
|
|
? ¶m->sub.value[param->sub.idx - 1]
|
|
|
|
|
: ¶m->value;
|
|
|
|
|
|
|
|
|
|
*value *= 10;
|
|
|
|
|
*value += c - '0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_collect(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
LOG_DBG("collect");
|
|
|
|
|
if (term->vt.private[0] == 0)
|
|
|
|
|
term->vt.private[0] = c;
|
|
|
|
|
else if (term->vt.private[1] == 0)
|
|
|
|
|
term->vt.private[1] = c;
|
|
|
|
|
else
|
|
|
|
|
LOG_DBG("only two private/intermediate characters supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_esc_dispatch(struct terminal *term, uint8_t final)
|
2019-07-04 19:35:01 +02:00
|
|
|
{
|
|
|
|
|
LOG_DBG("ESC: %s", esc_as_string(term, final));
|
2019-06-23 13:36:20 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
switch (term->vt.private[0]) {
|
|
|
|
|
case 0:
|
|
|
|
|
switch (final) {
|
|
|
|
|
case '7':
|
|
|
|
|
term->saved_cursor = term->cursor;
|
|
|
|
|
term->vt.saved_attrs = term->vt.attrs;
|
2019-11-17 10:02:46 +01:00
|
|
|
term->saved_charsets = term->charsets;
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
2019-07-17 10:39:38 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case '8':
|
|
|
|
|
term_restore_cursor(term);
|
|
|
|
|
term->vt.attrs = term->vt.saved_attrs;
|
2019-11-17 10:02:46 +01:00
|
|
|
term->charsets = term->saved_charsets;
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
2019-06-29 20:49:00 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'c':
|
|
|
|
|
term_reset(term, true);
|
|
|
|
|
break;
|
2019-06-29 20:49:00 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'D':
|
|
|
|
|
term_linefeed(term);
|
|
|
|
|
break;
|
2019-07-10 16:05:19 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'E':
|
|
|
|
|
term_linefeed(term);
|
2019-11-17 09:44:31 +01:00
|
|
|
term_cursor_left(term, term->cursor.point.col);
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
2019-07-18 19:25:53 +02:00
|
|
|
|
2019-11-16 10:57:11 +01:00
|
|
|
case 'H':
|
|
|
|
|
tll_foreach(term->tab_stops, it) {
|
2019-11-17 09:44:31 +01:00
|
|
|
if (it->item >= term->cursor.point.col) {
|
|
|
|
|
tll_insert_before(term->tab_stops, it, term->cursor.point.col);
|
2019-11-16 10:57:11 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-17 09:44:31 +01:00
|
|
|
tll_push_back(term->tab_stops, term->cursor.point.col);
|
2019-11-16 10:57:11 +01:00
|
|
|
break;
|
|
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'M':
|
|
|
|
|
term_reverse_index(term);
|
|
|
|
|
break;
|
2019-07-10 16:05:01 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'N':
|
|
|
|
|
/* SS2 - Single Shift 2 */
|
2019-11-17 09:59:12 +01:00
|
|
|
term->charsets.selected = 2; /* G2 */
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
2019-07-18 19:25:53 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'O':
|
|
|
|
|
/* SS3 - Single Shift 3 */
|
2019-11-17 09:59:12 +01:00
|
|
|
term->charsets.selected = 3; /* G3 */
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
2019-07-18 19:25:53 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case '\\':
|
|
|
|
|
/* ST - String Terminator */
|
|
|
|
|
break;
|
2019-07-10 16:05:19 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case '=':
|
|
|
|
|
term->keypad_keys_mode = KEYPAD_APPLICATION;
|
|
|
|
|
break;
|
2019-07-03 16:21:26 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case '>':
|
|
|
|
|
term->keypad_keys_mode = KEYPAD_NUMERICAL;
|
|
|
|
|
break;
|
2019-07-03 16:21:26 +02:00
|
|
|
|
|
|
|
|
default:
|
2019-07-30 21:42:46 +02:00
|
|
|
UNHANDLED();
|
2019-07-07 16:32:18 +02:00
|
|
|
break;
|
2019-07-03 16:21:26 +02:00
|
|
|
}
|
2019-11-05 11:32:56 +01:00
|
|
|
break; /* private[0] == 0 */
|
|
|
|
|
|
|
|
|
|
case '(':
|
|
|
|
|
case ')':
|
|
|
|
|
case '*':
|
|
|
|
|
case '+':
|
|
|
|
|
switch (final) {
|
|
|
|
|
case '0': {
|
|
|
|
|
char priv = term->vt.private[0];
|
|
|
|
|
ssize_t idx = priv ==
|
|
|
|
|
'(' ? 0 :
|
|
|
|
|
')' ? 1 :
|
|
|
|
|
'*' ? 2 :
|
|
|
|
|
'+' ? 3 : -1;
|
|
|
|
|
assert(idx != -1);
|
2019-11-17 09:59:12 +01:00
|
|
|
term->charsets.set[idx] = CHARSET_GRAPHIC;
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2019-06-29 20:49:00 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case 'B': {
|
|
|
|
|
char priv = term->vt.private[0];
|
|
|
|
|
ssize_t idx = priv ==
|
|
|
|
|
'(' ? 0 :
|
|
|
|
|
')' ? 1 :
|
|
|
|
|
'*' ? 2 :
|
|
|
|
|
'+' ? 3 : -1;
|
|
|
|
|
assert(idx != -1);
|
2019-11-17 09:59:12 +01:00
|
|
|
term->charsets.set[idx] = CHARSET_ASCII;
|
2019-06-23 13:36:20 +02:00
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-23 13:36:20 +02:00
|
|
|
break;
|
|
|
|
|
|
2019-11-05 11:32:56 +01:00
|
|
|
case '#':
|
|
|
|
|
switch (final) {
|
|
|
|
|
case '8':
|
|
|
|
|
for (int r = 0; r < term->rows; r++) {
|
2019-11-14 11:08:49 +01:00
|
|
|
struct row *row = grid_row(term->grid, r);
|
2019-11-05 11:32:56 +01:00
|
|
|
for (int c = 0; c < term->cols; c++) {
|
|
|
|
|
row->cells[c].wc = L'E';
|
|
|
|
|
row->cells[c].attrs.clean = 0;
|
|
|
|
|
}
|
|
|
|
|
row->dirty = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break; /* private[0] == '#' */
|
|
|
|
|
|
2019-07-07 16:32:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_csi_dispatch(struct terminal *term, uint8_t c)
|
2019-11-17 17:22:16 +01:00
|
|
|
{
|
2019-12-20 23:27:15 +01:00
|
|
|
csi_dispatch(term, c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_osc_start(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
term->vt.osc.idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_osc_end(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
if (!osc_ensure_size(term, term->vt.osc.idx + 1))
|
2019-11-30 00:32:34 +01:00
|
|
|
return;
|
2019-12-20 23:27:15 +01:00
|
|
|
term->vt.osc.data[term->vt.osc.idx] = '\0';
|
|
|
|
|
osc_dispatch(term);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_osc_put(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
if (!osc_ensure_size(term, term->vt.osc.idx + 1))
|
2019-11-30 00:32:34 +01:00
|
|
|
return;
|
2019-12-20 23:27:15 +01:00
|
|
|
term->vt.osc.data[term->vt.osc.idx++] = c;
|
|
|
|
|
}
|
2019-11-30 00:32:34 +01:00
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_hook(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
2020-01-12 11:55:22 +01:00
|
|
|
dcs_hook(term, c);
|
2019-11-17 17:22:16 +01:00
|
|
|
}
|
|
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_unhook(struct terminal *term, uint8_t c)
|
2019-07-07 16:32:18 +02:00
|
|
|
{
|
2020-01-12 11:55:22 +01:00
|
|
|
dcs_unhook(term);
|
2019-07-07 16:32:18 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_put(struct terminal *term, uint8_t c)
|
2019-07-07 16:32:18 +02:00
|
|
|
{
|
2020-01-12 11:55:22 +01:00
|
|
|
dcs_put(term, c);
|
2019-12-20 23:27:15 +01:00
|
|
|
}
|
2019-11-30 00:15:05 +01:00
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_utf8_2_entry(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
term->vt.utf8.idx = 0;
|
|
|
|
|
term->vt.utf8.left = 2;
|
|
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = c;
|
|
|
|
|
term->vt.utf8.left--;
|
|
|
|
|
}
|
2019-11-30 00:15:05 +01:00
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
static void
|
|
|
|
|
action_utf8_3_entry(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
term->vt.utf8.idx = 0;
|
|
|
|
|
term->vt.utf8.left = 3;
|
|
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = c;
|
|
|
|
|
term->vt.utf8.left--;
|
2019-07-07 16:32:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-12-20 23:27:15 +01:00
|
|
|
action_utf8_4_entry(struct terminal *term, uint8_t c)
|
|
|
|
|
{
|
|
|
|
|
term->vt.utf8.idx = 0;
|
|
|
|
|
term->vt.utf8.left = 4;
|
|
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = c;
|
|
|
|
|
term->vt.utf8.left--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
action_utf8_print(struct terminal *term, uint8_t c)
|
2019-07-07 16:32:18 +02:00
|
|
|
{
|
2019-08-30 22:08:37 +02:00
|
|
|
/* Convert to wchar */
|
|
|
|
|
mbstate_t ps = {0};
|
|
|
|
|
wchar_t wc;
|
2020-01-23 17:39:25 +01:00
|
|
|
size_t count = mbrtowc(
|
|
|
|
|
&wc, (const char *)term->vt.utf8.data, term->vt.utf8.idx, &ps);
|
|
|
|
|
|
|
|
|
|
if ((ssize_t)count < 0)
|
2019-08-30 22:08:37 +02:00
|
|
|
wc = 0;
|
|
|
|
|
|
|
|
|
|
/* Reset VT utf8 state */
|
2019-07-07 16:32:18 +02:00
|
|
|
term->vt.utf8.idx = 0;
|
|
|
|
|
|
2020-01-20 18:34:32 +01:00
|
|
|
int width = wcwidth(wc);
|
|
|
|
|
term_print(term, wc, width);
|
2019-06-23 13:36:20 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-20 19:16:52 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_ground_switch(struct terminal *term, uint8_t data)
|
2019-12-20 19:16:52 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 19:16:52 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x7f: action_print(term, data); return STATE_GROUND;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0xc0 ... 0xdf: action_utf8_2_entry(term, data); return STATE_UTF8_COLLECT_1;
|
|
|
|
|
case 0xe0 ... 0xef: action_utf8_3_entry(term, data); return STATE_UTF8_COLLECT_2;
|
|
|
|
|
case 0xf0 ... 0xf7: action_utf8_4_entry(term, data); return STATE_UTF8_COLLECT_3;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
2019-12-20 23:27:15 +01:00
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_GROUND;
|
2019-12-20 19:16:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_escape_switch(struct terminal *term, uint8_t data)
|
2019-12-20 19:16:52 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 19:16:52 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_ESCAPE;
|
2019-12-20 23:38:16 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_ESCAPE_INTERMEDIATE;
|
|
|
|
|
case 0x30 ... 0x4f: action_esc_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x50: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x51 ... 0x57: action_esc_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x58: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x59: action_esc_dispatch(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x5a: action_esc_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x5b: action_clear(term); return STATE_CSI_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x5c: action_esc_dispatch(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x5d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x5e ... 0x5f: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x60 ... 0x7e: action_esc_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_ESCAPE;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_ESCAPE;
|
2019-12-20 19:16:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_escape_intermediate_switch(struct terminal *term, uint8_t data)
|
2019-12-20 19:16:52 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 19:16:52 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_ESCAPE_INTERMEDIATE;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_ESCAPE_INTERMEDIATE;
|
|
|
|
|
case 0x30 ... 0x7e: action_esc_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_ESCAPE_INTERMEDIATE;
|
2019-12-20 19:16:52 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_ESCAPE_INTERMEDIATE;
|
2019-12-20 19:16:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 20:57:38 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_csi_entry_switch(struct terminal *term, uint8_t data)
|
2019-12-20 20:57:38 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 20:57:38 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_CSI_ENTRY;
|
2019-12-20 20:57:38 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
|
|
|
|
case 0x30 ... 0x39: action_param(term, data); return STATE_CSI_PARAM;
|
2020-01-26 00:44:53 +01:00
|
|
|
case 0x3a ... 0x3b: action_param(term, data); return STATE_CSI_PARAM;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x3c ... 0x3f: action_collect(term, data); return STATE_CSI_PARAM;
|
|
|
|
|
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_CSI_ENTRY;
|
2019-12-20 20:57:38 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_CSI_ENTRY;
|
2019-12-20 20:57:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 21:04:47 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_csi_param_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:04:47 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:04:47 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_CSI_PARAM;
|
2019-12-20 21:04:47 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
2019-12-20 21:04:47 +01:00
|
|
|
|
|
|
|
|
case 0x30 ... 0x39:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x3a ... 0x3b: action_param(term, data); return STATE_CSI_PARAM;
|
2019-12-20 21:04:47 +01:00
|
|
|
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x3c ... 0x3f: return STATE_CSI_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_CSI_PARAM;
|
2019-12-20 21:04:47 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_CSI_PARAM;
|
2019-12-20 21:04:47 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 21:09:00 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_csi_intermediate_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:09:00 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:09:00 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_CSI_INTERMEDIATE;
|
2019-12-20 21:09:00 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x30 ... 0x3f: return STATE_CSI_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_CSI_INTERMEDIATE;
|
2019-12-20 21:09:00 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_CSI_INTERMEDIATE;
|
2019-12-20 21:09:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 21:13:06 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_csi_ignore_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:13:06 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:13:06 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x1f: action_execute(term, data); return STATE_CSI_IGNORE;
|
2019-12-20 21:13:06 +01:00
|
|
|
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x20 ... 0x3f: action_ignore(term); return STATE_CSI_IGNORE;
|
|
|
|
|
case 0x40 ... 0x7e: return STATE_GROUND;
|
|
|
|
|
case 0x7f: action_ignore(term); return STATE_CSI_IGNORE;
|
2019-12-20 21:13:06 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_CSI_IGNORE;
|
2019-12-20 21:13:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 21:48:04 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_osc_string_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Note: original was 20-7f, but I changed to 20-ff to include utf-8. Don't forget to add EXECUTE to 8-bit C1 if we implement that. */
|
2019-12-20 23:59:23 +01:00
|
|
|
default: action_osc_put(term, data); return STATE_OSC_STRING;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x07: action_osc_end(term, data); return STATE_GROUND;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
case 0x00 ... 0x06:
|
|
|
|
|
case 0x08 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1c ... 0x1f: action_ignore(term); return STATE_OSC_STRING;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
case 0x18:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1a: action_osc_end(term, data); action_execute(term, data); return STATE_GROUND;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1b: action_osc_end(term, data); action_clear(term); return STATE_ESCAPE;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_dcs_entry_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1c ... 0x1f: action_ignore(term); return STATE_DCS_ENTRY;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
|
|
|
|
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x3a: return STATE_DCS_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x3b: action_param(term, data); return STATE_DCS_PARAM;
|
|
|
|
|
case 0x3c ... 0x3f: action_collect(term, data); return STATE_DCS_PARAM;
|
|
|
|
|
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_DCS_ENTRY;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_DCS_ENTRY;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_dcs_param_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1c ... 0x1f: action_ignore(term); return STATE_DCS_PARAM;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
|
|
|
|
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x3a: return STATE_DCS_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x3b: action_param(term, data); return STATE_DCS_PARAM;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x3c ... 0x3f: return STATE_DCS_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_DCS_PARAM;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_DCS_PARAM;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_dcs_intermediate_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1c ... 0x1f: action_ignore(term); return STATE_DCS_INTERMEDIATE;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x30 ... 0x3f: return STATE_DCS_IGNORE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_DCS_INTERMEDIATE;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_DCS_INTERMEDIATE;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_dcs_ignore_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
|
|
|
|
case 0x1c ... 0x1f:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x20 ... 0x7f: action_ignore(term); return STATE_DCS_IGNORE;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_DCS_IGNORE;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_dcs_passthrough_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:48:04 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:48:04 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x1c ... 0x7e: action_put(term, data); return STATE_DCS_PASSTHROUGH;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x7f: action_ignore(term); return STATE_DCS_PASSTHROUGH;
|
2019-12-20 21:48:04 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1b: action_unhook(term, data); action_clear(term); return STATE_ESCAPE;
|
|
|
|
|
case 0x80 ... 0x8f: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x90: action_unhook(term, data); action_clear(term); return STATE_DCS_ENTRY;
|
|
|
|
|
case 0x91 ... 0x97: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x98: action_unhook(term, data); return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
case 0x99: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_unhook(term, data); action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9b: action_unhook(term, data); action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: action_unhook(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9d: action_unhook(term, data); action_osc_start(term, data); return STATE_OSC_STRING;
|
|
|
|
|
case 0x9e ... 0x9f: action_unhook(term, data); return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
|
|
|
|
|
default: return STATE_DCS_PASSTHROUGH;
|
2019-12-20 21:48:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 21:50:54 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_sos_pm_apc_string_switch(struct terminal *term, uint8_t data)
|
2019-12-20 21:50:54 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
switch (data) {
|
2019-12-20 23:38:16 +01:00
|
|
|
/* exit current enter new state */
|
2019-12-20 21:50:54 +01:00
|
|
|
case 0x00 ... 0x17:
|
|
|
|
|
case 0x19:
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1c ... 0x7f: action_ignore(term); return STATE_SOS_PM_APC_STRING;
|
2019-12-20 21:50:54 +01:00
|
|
|
|
|
|
|
|
/* Anywhere */
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x18: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x1a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x1b: action_clear(term); return STATE_ESCAPE;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x80 ... 0x8f: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x90: action_clear(term); return STATE_DCS_ENTRY;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x91 ... 0x97: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x98: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x99: action_execute(term, data); return STATE_GROUND;
|
|
|
|
|
case 0x9a: action_execute(term, data); return STATE_GROUND;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9b: action_clear(term); return STATE_CSI_ENTRY;
|
|
|
|
|
case 0x9c: return STATE_GROUND;
|
2019-12-20 23:59:23 +01:00
|
|
|
case 0x9d: action_osc_start(term, data); return STATE_OSC_STRING;
|
2019-12-20 23:38:16 +01:00
|
|
|
case 0x9e ... 0x9f: return STATE_SOS_PM_APC_STRING;
|
|
|
|
|
|
|
|
|
|
default: return STATE_SOS_PM_APC_STRING;
|
2019-12-20 21:50:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 22:10:27 +01:00
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_utf8_collect_1_switch(struct terminal *term, uint8_t data)
|
2019-12-20 22:10:27 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = data;
|
2019-12-20 22:10:27 +01:00
|
|
|
term->vt.utf8.left--;
|
|
|
|
|
|
|
|
|
|
assert(term->vt.utf8.left == 0);
|
2019-12-20 23:59:23 +01:00
|
|
|
action_utf8_print(term, data);
|
2019-12-20 22:10:27 +01:00
|
|
|
return STATE_GROUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_utf8_collect_2_switch(struct terminal *term, uint8_t data)
|
2019-12-20 22:10:27 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = data;
|
2019-12-20 22:10:27 +01:00
|
|
|
term->vt.utf8.left--;
|
|
|
|
|
|
|
|
|
|
assert(term->vt.utf8.left == 1);
|
|
|
|
|
return STATE_UTF8_COLLECT_1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum state
|
2019-12-20 23:59:23 +01:00
|
|
|
state_utf8_collect_3_switch(struct terminal *term, uint8_t data)
|
2019-12-20 22:10:27 +01:00
|
|
|
{
|
2019-12-20 23:59:23 +01:00
|
|
|
term->vt.utf8.data[term->vt.utf8.idx++] = data;
|
2019-12-20 22:10:27 +01:00
|
|
|
term->vt.utf8.left--;
|
|
|
|
|
|
|
|
|
|
assert(term->vt.utf8.left == 2);
|
|
|
|
|
return STATE_UTF8_COLLECT_2;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
void
|
|
|
|
|
vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
|
|
|
|
{
|
2019-12-20 23:00:07 +01:00
|
|
|
enum state current_state = term->vt.state;
|
|
|
|
|
|
|
|
|
|
const uint8_t *p = data;
|
2019-12-20 23:59:23 +01:00
|
|
|
for (size_t i = 0; i < len; i++, p++) {
|
|
|
|
|
switch (current_state) {
|
|
|
|
|
case STATE_GROUND: current_state = state_ground_switch(term, *p); break;
|
|
|
|
|
case STATE_ESCAPE: current_state = state_escape_switch(term, *p); break;
|
|
|
|
|
case STATE_ESCAPE_INTERMEDIATE: current_state = state_escape_intermediate_switch(term, *p); break;
|
|
|
|
|
case STATE_CSI_ENTRY: current_state = state_csi_entry_switch(term, *p); break;
|
|
|
|
|
case STATE_CSI_PARAM: current_state = state_csi_param_switch(term, *p); break;
|
|
|
|
|
case STATE_CSI_INTERMEDIATE: current_state = state_csi_intermediate_switch(term, *p); break;
|
|
|
|
|
case STATE_CSI_IGNORE: current_state = state_csi_ignore_switch(term, *p); break;
|
|
|
|
|
case STATE_OSC_STRING: current_state = state_osc_string_switch(term, *p); break;
|
|
|
|
|
case STATE_DCS_ENTRY: current_state = state_dcs_entry_switch(term, *p); break;
|
|
|
|
|
case STATE_DCS_PARAM: current_state = state_dcs_param_switch(term, *p); break;
|
|
|
|
|
case STATE_DCS_INTERMEDIATE: current_state = state_dcs_intermediate_switch(term, *p); break;
|
|
|
|
|
case STATE_DCS_IGNORE: current_state = state_dcs_ignore_switch(term, *p); break;
|
|
|
|
|
case STATE_DCS_PASSTHROUGH: current_state = state_dcs_passthrough_switch(term, *p); break;
|
|
|
|
|
case STATE_SOS_PM_APC_STRING: current_state = state_sos_pm_apc_string_switch(term, *p); break;
|
|
|
|
|
|
|
|
|
|
case STATE_UTF8_COLLECT_1: current_state = state_utf8_collect_1_switch(term, *p); break;
|
|
|
|
|
case STATE_UTF8_COLLECT_2: current_state = state_utf8_collect_2_switch(term, *p); break;
|
|
|
|
|
case STATE_UTF8_COLLECT_3: current_state = state_utf8_collect_3_switch(term, *p); break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 22:12:35 +01:00
|
|
|
|
|
|
|
|
term->vt.state = current_state;
|
2019-06-15 22:22:44 +02:00
|
|
|
}
|