aboutsummaryrefslogtreecommitdiff
path: root/src/vterm
diff options
context:
space:
mode:
Diffstat (limited to 'src/vterm')
-rw-r--r--src/vterm/LICENSE23
-rw-r--r--src/vterm/encoding.c230
-rw-r--r--src/vterm/encoding/DECdrawing.inc36
-rw-r--r--src/vterm/encoding/uk.inc6
-rw-r--r--src/vterm/keyboard.c225
-rw-r--r--src/vterm/mouse.c99
-rw-r--r--src/vterm/parser.c408
-rw-r--r--src/vterm/pen.c678
-rw-r--r--src/vterm/rect.h56
-rw-r--r--src/vterm/screen.c1174
-rw-r--r--src/vterm/state.c2281
-rw-r--r--src/vterm/vterm.c432
-rw-r--r--src/vterm/vterm.h638
-rw-r--r--src/vterm/vterm_internal.h298
-rw-r--r--src/vterm/vterm_keycodes.h61
15 files changed, 0 insertions, 6645 deletions
diff --git a/src/vterm/LICENSE b/src/vterm/LICENSE
deleted file mode 100644
index 0d051634b2..0000000000
--- a/src/vterm/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-The MIT License
-
-Copyright (c) 2008 Paul Evans <leonerd@leonerd.org.uk>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/src/vterm/encoding.c b/src/vterm/encoding.c
deleted file mode 100644
index 434ac3f99b..0000000000
--- a/src/vterm/encoding.c
+++ /dev/null
@@ -1,230 +0,0 @@
-#include "vterm_internal.h"
-
-#define UNICODE_INVALID 0xFFFD
-
-#if defined(DEBUG) && DEBUG > 1
-# define DEBUG_PRINT_UTF8
-#endif
-
-struct UTF8DecoderData {
- // number of bytes remaining in this codepoint
- int bytes_remaining;
-
- // number of bytes total in this codepoint once it's finished
- // (for detecting overlongs)
- int bytes_total;
-
- int this_cp;
-};
-
-static void init_utf8(VTermEncoding *enc, void *data_)
-{
- struct UTF8DecoderData *data = data_;
-
- data->bytes_remaining = 0;
- data->bytes_total = 0;
-}
-
-static void decode_utf8(VTermEncoding *enc, void *data_,
- uint32_t cp[], int *cpi, int cplen,
- const char bytes[], size_t *pos, size_t bytelen)
-{
- struct UTF8DecoderData *data = data_;
-
-#ifdef DEBUG_PRINT_UTF8
- printf("BEGIN UTF-8\n");
-#endif
-
- for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
- unsigned char c = bytes[*pos];
-
-#ifdef DEBUG_PRINT_UTF8
- printf(" pos=%zd c=%02x rem=%d\n", *pos, c, data->bytes_remaining);
-#endif
-
- if(c < 0x20) // C0
- return;
-
- else if(c >= 0x20 && c < 0x7f) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- cp[(*cpi)++] = c;
-#ifdef DEBUG_PRINT_UTF8
- printf(" UTF-8 char: U+%04x\n", c);
-#endif
- data->bytes_remaining = 0;
- }
-
- else if(c == 0x7f) // DEL
- return;
-
- else if(c >= 0x80 && c < 0xc0) {
- if(!data->bytes_remaining) {
- cp[(*cpi)++] = UNICODE_INVALID;
- continue;
- }
-
- data->this_cp <<= 6;
- data->this_cp |= c & 0x3f;
- data->bytes_remaining--;
-
- if(!data->bytes_remaining) {
-#ifdef DEBUG_PRINT_UTF8
- printf(" UTF-8 raw char U+%04x bytelen=%d ", data->this_cp, data->bytes_total);
-#endif
- // Check for overlong sequences
- switch(data->bytes_total) {
- case 2:
- if(data->this_cp < 0x0080) data->this_cp = UNICODE_INVALID;
- break;
- case 3:
- if(data->this_cp < 0x0800) data->this_cp = UNICODE_INVALID;
- break;
- case 4:
- if(data->this_cp < 0x10000) data->this_cp = UNICODE_INVALID;
- break;
- case 5:
- if(data->this_cp < 0x200000) data->this_cp = UNICODE_INVALID;
- break;
- case 6:
- if(data->this_cp < 0x4000000) data->this_cp = UNICODE_INVALID;
- break;
- }
- // Now look for plain invalid ones
- if((data->this_cp >= 0xD800 && data->this_cp <= 0xDFFF) ||
- data->this_cp == 0xFFFE ||
- data->this_cp == 0xFFFF)
- data->this_cp = UNICODE_INVALID;
-#ifdef DEBUG_PRINT_UTF8
- printf(" char: U+%04x\n", data->this_cp);
-#endif
- cp[(*cpi)++] = data->this_cp;
- }
- }
-
- else if(c >= 0xc0 && c < 0xe0) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- data->this_cp = c & 0x1f;
- data->bytes_total = 2;
- data->bytes_remaining = 1;
- }
-
- else if(c >= 0xe0 && c < 0xf0) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- data->this_cp = c & 0x0f;
- data->bytes_total = 3;
- data->bytes_remaining = 2;
- }
-
- else if(c >= 0xf0 && c < 0xf8) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- data->this_cp = c & 0x07;
- data->bytes_total = 4;
- data->bytes_remaining = 3;
- }
-
- else if(c >= 0xf8 && c < 0xfc) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- data->this_cp = c & 0x03;
- data->bytes_total = 5;
- data->bytes_remaining = 4;
- }
-
- else if(c >= 0xfc && c < 0xfe) {
- if(data->bytes_remaining)
- cp[(*cpi)++] = UNICODE_INVALID;
-
- data->this_cp = c & 0x01;
- data->bytes_total = 6;
- data->bytes_remaining = 5;
- }
-
- else {
- cp[(*cpi)++] = UNICODE_INVALID;
- }
- }
-}
-
-static VTermEncoding encoding_utf8 = {
- .init = &init_utf8,
- .decode = &decode_utf8,
-};
-
-static void decode_usascii(VTermEncoding *enc, void *data,
- uint32_t cp[], int *cpi, int cplen,
- const char bytes[], size_t *pos, size_t bytelen)
-{
- int is_gr = bytes[*pos] & 0x80;
-
- for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
- unsigned char c = bytes[*pos] ^ is_gr;
-
- if(c < 0x20 || c == 0x7f || c >= 0x80)
- return;
-
- cp[(*cpi)++] = c;
- }
-}
-
-static VTermEncoding encoding_usascii = {
- .decode = &decode_usascii,
-};
-
-struct StaticTableEncoding {
- const VTermEncoding enc;
- const uint32_t chars[128];
-};
-
-static void decode_table(VTermEncoding *enc, void *data,
- uint32_t cp[], int *cpi, int cplen,
- const char bytes[], size_t *pos, size_t bytelen)
-{
- struct StaticTableEncoding *table = (struct StaticTableEncoding *)enc;
- int is_gr = bytes[*pos] & 0x80;
-
- for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
- unsigned char c = bytes[*pos] ^ is_gr;
-
- if(c < 0x20 || c == 0x7f || c >= 0x80)
- return;
-
- if(table->chars[c])
- cp[(*cpi)++] = table->chars[c];
- else
- cp[(*cpi)++] = c;
- }
-}
-
-#include "encoding/DECdrawing.inc"
-#include "encoding/uk.inc"
-
-static struct {
- VTermEncodingType type;
- char designation;
- VTermEncoding *enc;
-}
-encodings[] = {
- { ENC_UTF8, 'u', &encoding_utf8 },
- { ENC_SINGLE_94, '0', (VTermEncoding*)&encoding_DECdrawing },
- { ENC_SINGLE_94, 'A', (VTermEncoding*)&encoding_uk },
- { ENC_SINGLE_94, 'B', &encoding_usascii },
- { 0 },
-};
-
-/* This ought to be INTERNAL but isn't because it's used by unit testing */
-VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
-{
- for(int i = 0; encodings[i].designation; i++)
- if(encodings[i].type == type && encodings[i].designation == designation)
- return encodings[i].enc;
- return NULL;
-}
diff --git a/src/vterm/encoding/DECdrawing.inc b/src/vterm/encoding/DECdrawing.inc
deleted file mode 100644
index 627397bcc2..0000000000
--- a/src/vterm/encoding/DECdrawing.inc
+++ /dev/null
@@ -1,36 +0,0 @@
-static const struct StaticTableEncoding encoding_DECdrawing = {
- { .decode = &decode_table },
- {
- [0x60] = 0x25C6, // BLACK DIAMOND
- [0x61] = 0x2592, // MEDIUM SHADE (checkerboard)
- [0x62] = 0x2409, // SYMBOL FOR HORIZONTAL TAB
- [0x63] = 0x240C, // SYMBOL FOR FORM FEED
- [0x64] = 0x240D, // SYMBOL FOR CARRIAGE RETURN
- [0x65] = 0x240A, // SYMBOL FOR LINE FEED
- [0x66] = 0x00B0, // DEGREE SIGN
- [0x67] = 0x00B1, // PLUS-MINUS SIGN (plus or minus)
- [0x68] = 0x2424, // SYMBOL FOR NEW LINE
- [0x69] = 0x240B, // SYMBOL FOR VERTICAL TAB
- [0x6a] = 0x2518, // BOX DRAWINGS LIGHT UP AND LEFT (bottom-right corner)
- [0x6b] = 0x2510, // BOX DRAWINGS LIGHT DOWN AND LEFT (top-right corner)
- [0x6c] = 0x250C, // BOX DRAWINGS LIGHT DOWN AND RIGHT (top-left corner)
- [0x6d] = 0x2514, // BOX DRAWINGS LIGHT UP AND RIGHT (bottom-left corner)
- [0x6e] = 0x253C, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL (crossing lines)
- [0x6f] = 0x23BA, // HORIZONTAL SCAN LINE-1
- [0x70] = 0x23BB, // HORIZONTAL SCAN LINE-3
- [0x71] = 0x2500, // BOX DRAWINGS LIGHT HORIZONTAL
- [0x72] = 0x23BC, // HORIZONTAL SCAN LINE-7
- [0x73] = 0x23BD, // HORIZONTAL SCAN LINE-9
- [0x74] = 0x251C, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
- [0x75] = 0x2524, // BOX DRAWINGS LIGHT VERTICAL AND LEFT
- [0x76] = 0x2534, // BOX DRAWINGS LIGHT UP AND HORIZONTAL
- [0x77] = 0x252C, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
- [0x78] = 0x2502, // BOX DRAWINGS LIGHT VERTICAL
- [0x79] = 0x2A7D, // LESS-THAN OR SLANTED EQUAL-TO
- [0x7a] = 0x2A7E, // GREATER-THAN OR SLANTED EQUAL-TO
- [0x7b] = 0x03C0, // GREEK SMALL LETTER PI
- [0x7c] = 0x2260, // NOT EQUAL TO
- [0x7d] = 0x00A3, // POUND SIGN
- [0x7e] = 0x00B7, // MIDDLE DOT
- }
-};
diff --git a/src/vterm/encoding/uk.inc b/src/vterm/encoding/uk.inc
deleted file mode 100644
index 5c7700226b..0000000000
--- a/src/vterm/encoding/uk.inc
+++ /dev/null
@@ -1,6 +0,0 @@
-static const struct StaticTableEncoding encoding_uk = {
- { .decode = &decode_table },
- {
- [0x23] = 0x00a3, // £
- }
-};
diff --git a/src/vterm/keyboard.c b/src/vterm/keyboard.c
deleted file mode 100644
index 7e062c8c02..0000000000
--- a/src/vterm/keyboard.c
+++ /dev/null
@@ -1,225 +0,0 @@
-#include "vterm_internal.h"
-#include <stdio.h>
-
-#include "nvim/tui/termkey/termkey.h"
-
-void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
-{
- /* The shift modifier is never important for Unicode characters
- * apart from Space
- */
- if(c != ' ')
- mod &= ~VTERM_MOD_SHIFT;
-
- if(mod == 0) {
- // Normal text - ignore just shift
- char str[6];
- int seqlen = fill_utf8(c, str);
- vterm_push_output_bytes(vt, str, seqlen);
- return;
- }
-
- int needs_CSIu;
- switch(c) {
- /* Special Ctrl- letters that can't be represented elsewise */
- case 'i': case 'j': case 'm': case '[':
- needs_CSIu = 1;
- break;
- /* Ctrl-\ ] ^ _ don't need CSUu */
- case '\\': case ']': case '^': case '_':
- needs_CSIu = 0;
- break;
- /* Shift-space needs CSIu */
- case ' ':
- needs_CSIu = !!(mod & VTERM_MOD_SHIFT);
- break;
- /* All other characters needs CSIu except for letters a-z */
- default:
- needs_CSIu = (c < 'a' || c > 'z');
- }
-
- /* ALT we can just prefix with ESC; anything else requires CSI u */
- if(needs_CSIu && (mod & ~VTERM_MOD_ALT)) {
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1);
- return;
- }
-
- if(mod & VTERM_MOD_CTRL)
- c &= 0x1f;
-
- vterm_push_output_sprintf(vt, "%s%c", mod & VTERM_MOD_ALT ? ESC_S : "", c);
-}
-
-typedef struct {
- enum {
- KEYCODE_NONE,
- KEYCODE_LITERAL,
- KEYCODE_TAB,
- KEYCODE_ENTER,
- KEYCODE_SS3,
- KEYCODE_CSI,
- KEYCODE_CSI_CURSOR,
- KEYCODE_CSINUM,
- KEYCODE_KEYPAD,
- } type;
- char literal;
- int csinum;
-} keycodes_s;
-
-static keycodes_s keycodes[] = {
- { KEYCODE_NONE }, // NONE
-
- { KEYCODE_ENTER, '\r' }, // ENTER
- { KEYCODE_TAB, '\t' }, // TAB
- { KEYCODE_LITERAL, '\x7f' }, // BACKSPACE == ASCII DEL
- { KEYCODE_LITERAL, '\x1b' }, // ESCAPE
-
- { KEYCODE_CSI_CURSOR, 'A' }, // UP
- { KEYCODE_CSI_CURSOR, 'B' }, // DOWN
- { KEYCODE_CSI_CURSOR, 'D' }, // LEFT
- { KEYCODE_CSI_CURSOR, 'C' }, // RIGHT
-
- { KEYCODE_CSINUM, '~', 2 }, // INS
- { KEYCODE_CSINUM, '~', 3 }, // DEL
- { KEYCODE_CSI_CURSOR, 'H' }, // HOME
- { KEYCODE_CSI_CURSOR, 'F' }, // END
- { KEYCODE_CSINUM, '~', 5 }, // PAGEUP
- { KEYCODE_CSINUM, '~', 6 }, // PAGEDOWN
-};
-
-static keycodes_s keycodes_fn[] = {
- { KEYCODE_NONE }, // F0 - shouldn't happen
- { KEYCODE_SS3, 'P' }, // F1
- { KEYCODE_SS3, 'Q' }, // F2
- { KEYCODE_SS3, 'R' }, // F3
- { KEYCODE_SS3, 'S' }, // F4
- { KEYCODE_CSINUM, '~', 15 }, // F5
- { KEYCODE_CSINUM, '~', 17 }, // F6
- { KEYCODE_CSINUM, '~', 18 }, // F7
- { KEYCODE_CSINUM, '~', 19 }, // F8
- { KEYCODE_CSINUM, '~', 20 }, // F9
- { KEYCODE_CSINUM, '~', 21 }, // F10
- { KEYCODE_CSINUM, '~', 23 }, // F11
- { KEYCODE_CSINUM, '~', 24 }, // F12
-};
-
-static keycodes_s keycodes_kp[] = {
- { KEYCODE_KEYPAD, '0', 'p' }, // KP_0
- { KEYCODE_KEYPAD, '1', 'q' }, // KP_1
- { KEYCODE_KEYPAD, '2', 'r' }, // KP_2
- { KEYCODE_KEYPAD, '3', 's' }, // KP_3
- { KEYCODE_KEYPAD, '4', 't' }, // KP_4
- { KEYCODE_KEYPAD, '5', 'u' }, // KP_5
- { KEYCODE_KEYPAD, '6', 'v' }, // KP_6
- { KEYCODE_KEYPAD, '7', 'w' }, // KP_7
- { KEYCODE_KEYPAD, '8', 'x' }, // KP_8
- { KEYCODE_KEYPAD, '9', 'y' }, // KP_9
- { KEYCODE_KEYPAD, '*', 'j' }, // KP_MULT
- { KEYCODE_KEYPAD, '+', 'k' }, // KP_PLUS
- { KEYCODE_KEYPAD, ',', 'l' }, // KP_COMMA
- { KEYCODE_KEYPAD, '-', 'm' }, // KP_MINUS
- { KEYCODE_KEYPAD, '.', 'n' }, // KP_PERIOD
- { KEYCODE_KEYPAD, '/', 'o' }, // KP_DIVIDE
- { KEYCODE_KEYPAD, '\n', 'M' }, // KP_ENTER
- { KEYCODE_KEYPAD, '=', 'X' }, // KP_EQUAL
-};
-
-void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
-{
- if(key == VTERM_KEY_NONE)
- return;
-
- keycodes_s k;
- if(key < VTERM_KEY_FUNCTION_0) {
- if(key >= sizeof(keycodes)/sizeof(keycodes[0]))
- return;
- k = keycodes[key];
- }
- else if(key >= VTERM_KEY_FUNCTION_0 && key <= VTERM_KEY_FUNCTION_MAX) {
- if((key - VTERM_KEY_FUNCTION_0) >= sizeof(keycodes_fn)/sizeof(keycodes_fn[0]))
- return;
- k = keycodes_fn[key - VTERM_KEY_FUNCTION_0];
- }
- else if(key >= VTERM_KEY_KP_0) {
- if((key - VTERM_KEY_KP_0) >= sizeof(keycodes_kp)/sizeof(keycodes_kp[0]))
- return;
- k = keycodes_kp[key - VTERM_KEY_KP_0];
- }
-
- switch(k.type) {
- case KEYCODE_NONE:
- break;
-
- case KEYCODE_TAB:
- /* Shift-Tab is CSI Z but plain Tab is 0x09 */
- if(mod == VTERM_MOD_SHIFT)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z");
- else if(mod & VTERM_MOD_SHIFT)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%dZ", mod+1);
- else
- goto case_LITERAL;
- break;
-
- case KEYCODE_ENTER:
- /* Enter is CRLF in newline mode, but just LF in linefeed */
- if(vt->state->mode.newline)
- vterm_push_output_sprintf(vt, "\r\n");
- else
- goto case_LITERAL;
- break;
-
- case KEYCODE_LITERAL: case_LITERAL:
- if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL))
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", k.literal, mod+1);
- else
- vterm_push_output_sprintf(vt, mod & VTERM_MOD_ALT ? ESC_S "%c" : "%c", k.literal);
- break;
-
- case KEYCODE_SS3: case_SS3:
- if(mod == 0)
- vterm_push_output_sprintf_ctrl(vt, C1_SS3, "%c", k.literal);
- else
- goto case_CSI;
- break;
-
- case KEYCODE_CSI: case_CSI:
- if(mod == 0)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%c", k.literal);
- else
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%d%c", mod + 1, k.literal);
- break;
-
- case KEYCODE_CSINUM:
- if(mod == 0)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d%c", k.csinum, k.literal);
- else
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%d%c", k.csinum, mod + 1, k.literal);
- break;
-
- case KEYCODE_CSI_CURSOR:
- if(vt->state->mode.cursor)
- goto case_SS3;
- else
- goto case_CSI;
-
- case KEYCODE_KEYPAD:
- if(vt->state->mode.keypad) {
- k.literal = k.csinum;
- goto case_SS3;
- }
- else
- goto case_LITERAL;
- }
-}
-
-void vterm_keyboard_start_paste(VTerm *vt)
-{
- if(vt->state->mode.bracketpaste)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "200~");
-}
-
-void vterm_keyboard_end_paste(VTerm *vt)
-{
- if(vt->state->mode.bracketpaste)
- vterm_push_output_sprintf_ctrl(vt, C1_CSI, "201~");
-}
diff --git a/src/vterm/mouse.c b/src/vterm/mouse.c
deleted file mode 100644
index a9d3fe4ca9..0000000000
--- a/src/vterm/mouse.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include "vterm_internal.h"
-
-#include "nvim/tui/termkey/termkey.h"
-
-static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row)
-{
- modifiers <<= 2;
-
- switch(state->mouse_protocol) {
- case MOUSE_X10:
- if(col + 0x21 > 0xff)
- col = 0xff - 0x21;
- if(row + 0x21 > 0xff)
- row = 0xff - 0x21;
-
- if(!pressed)
- code = 3;
-
- vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c",
- (code | modifiers) + 0x20, col + 0x21, row + 0x21);
- break;
-
- case MOUSE_UTF8:
- {
- char utf8[18]; size_t len = 0;
-
- if(!pressed)
- code = 3;
-
- len += fill_utf8((code | modifiers) + 0x20, utf8 + len);
- len += fill_utf8(col + 0x21, utf8 + len);
- len += fill_utf8(row + 0x21, utf8 + len);
- utf8[len] = 0;
-
- vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8);
- }
- break;
-
- case MOUSE_SGR:
- vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c",
- code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm');
- break;
-
- case MOUSE_RXVT:
- if(!pressed)
- code = 3;
-
- vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM",
- code | modifiers, col + 1, row + 1);
- break;
- }
-}
-
-void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod)
-{
- VTermState *state = vt->state;
-
- if(col == state->mouse_col && row == state->mouse_row)
- return;
-
- state->mouse_col = col;
- state->mouse_row = row;
-
- if((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) ||
- (state->mouse_flags & MOUSE_WANT_MOVE)) {
- int button = state->mouse_buttons & 0x01 ? 1 :
- state->mouse_buttons & 0x02 ? 2 :
- state->mouse_buttons & 0x04 ? 3 : 4;
- output_mouse(state, button-1 + 0x20, 1, mod, col, row);
- }
-}
-
-void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
-{
- VTermState *state = vt->state;
-
- int old_buttons = state->mouse_buttons;
-
- if(button > 0 && button <= 3) {
- if(pressed)
- state->mouse_buttons |= (1 << (button-1));
- else
- state->mouse_buttons &= ~(1 << (button-1));
- }
-
- /* Most of the time we don't get button releases from 4/5 */
- if(state->mouse_buttons == old_buttons && button < 4)
- return;
-
- if(!state->mouse_flags)
- return;
-
- if(button < 4) {
- output_mouse(state, button-1, pressed, mod, state->mouse_col, state->mouse_row);
- }
- else if(button < 8) {
- output_mouse(state, button-4 + 0x40, pressed, mod, state->mouse_col, state->mouse_row);
- }
-}
diff --git a/src/vterm/parser.c b/src/vterm/parser.c
deleted file mode 100644
index 84d017a791..0000000000
--- a/src/vterm/parser.c
+++ /dev/null
@@ -1,408 +0,0 @@
-#include "vterm_internal.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#undef DEBUG_PARSER
-
-static bool is_intermed(unsigned char c)
-{
- return c >= 0x20 && c <= 0x2f;
-}
-
-static void do_control(VTerm *vt, unsigned char control)
-{
- if(vt->parser.callbacks && vt->parser.callbacks->control)
- if((*vt->parser.callbacks->control)(control, vt->parser.cbdata))
- return;
-
- DEBUG_LOG("libvterm: Unhandled control 0x%02x\n", control);
-}
-
-static void do_csi(VTerm *vt, char command)
-{
-#ifdef DEBUG_PARSER
- printf("Parsed CSI args as:\n", arglen, args);
- printf(" leader: %s\n", vt->parser.v.csi.leader);
- for(int argi = 0; argi < vt->parser.v.csi.argi; argi++) {
- printf(" %lu", CSI_ARG(vt->parser.v.csi.args[argi]));
- if(!CSI_ARG_HAS_MORE(vt->parser.v.csi.args[argi]))
- printf("\n");
- printf(" intermed: %s\n", vt->parser.intermed);
- }
-#endif
-
- if(vt->parser.callbacks && vt->parser.callbacks->csi)
- if((*vt->parser.callbacks->csi)(
- vt->parser.v.csi.leaderlen ? vt->parser.v.csi.leader : NULL,
- vt->parser.v.csi.args,
- vt->parser.v.csi.argi,
- vt->parser.intermedlen ? vt->parser.intermed : NULL,
- command,
- vt->parser.cbdata))
- return;
-
- DEBUG_LOG("libvterm: Unhandled CSI %c\n", command);
-}
-
-static void do_escape(VTerm *vt, char command)
-{
- char seq[INTERMED_MAX+1];
-
- size_t len = vt->parser.intermedlen;
- strncpy(seq, vt->parser.intermed, len);
- seq[len++] = command;
- seq[len] = 0;
-
- if(vt->parser.callbacks && vt->parser.callbacks->escape)
- if((*vt->parser.callbacks->escape)(seq, len, vt->parser.cbdata))
- return;
-
- DEBUG_LOG("libvterm: Unhandled escape ESC 0x%02x\n", command);
-}
-
-static void string_fragment(VTerm *vt, const char *str, size_t len, bool final)
-{
- VTermStringFragment frag = {
- .str = str,
- .len = len,
- .initial = vt->parser.string_initial,
- .final = final,
- };
-
- switch(vt->parser.state) {
- case OSC:
- if(vt->parser.callbacks && vt->parser.callbacks->osc)
- (*vt->parser.callbacks->osc)(vt->parser.v.osc.command, frag, vt->parser.cbdata);
- break;
-
- case DCS:
- if(vt->parser.callbacks && vt->parser.callbacks->dcs)
- (*vt->parser.callbacks->dcs)(vt->parser.v.dcs.command, vt->parser.v.dcs.commandlen, frag, vt->parser.cbdata);
- break;
-
- case APC:
- if(vt->parser.callbacks && vt->parser.callbacks->apc)
- (*vt->parser.callbacks->apc)(frag, vt->parser.cbdata);
- break;
-
- case PM:
- if(vt->parser.callbacks && vt->parser.callbacks->pm)
- (*vt->parser.callbacks->pm)(frag, vt->parser.cbdata);
- break;
-
- case SOS:
- if(vt->parser.callbacks && vt->parser.callbacks->sos)
- (*vt->parser.callbacks->sos)(frag, vt->parser.cbdata);
- break;
-
- case NORMAL:
- case CSI_LEADER:
- case CSI_ARGS:
- case CSI_INTERMED:
- case OSC_COMMAND:
- case DCS_COMMAND:
- break;
- }
-
- vt->parser.string_initial = false;
-}
-
-size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
-{
- size_t pos = 0;
- const char *string_start;
-
- switch(vt->parser.state) {
- case NORMAL:
- case CSI_LEADER:
- case CSI_ARGS:
- case CSI_INTERMED:
- case OSC_COMMAND:
- case DCS_COMMAND:
- string_start = NULL;
- break;
- case OSC:
- case DCS:
- case APC:
- case PM:
- case SOS:
- string_start = bytes;
- break;
- }
-
-#define ENTER_STATE(st) do { vt->parser.state = st; string_start = NULL; } while(0)
-#define ENTER_NORMAL_STATE() ENTER_STATE(NORMAL)
-
-#define IS_STRING_STATE() (vt->parser.state >= OSC_COMMAND)
-
- for( ; pos < len; pos++) {
- unsigned char c = bytes[pos];
- bool c1_allowed = !vt->mode.utf8;
-
- if(c == 0x00 || c == 0x7f) { // NUL, DEL
- if(IS_STRING_STATE()) {
- string_fragment(vt, string_start, bytes + pos - string_start, false);
- string_start = bytes + pos + 1;
- }
- if(vt->parser.emit_nul)
- do_control(vt, c);
- continue;
- }
- if(c == 0x18 || c == 0x1a) { // CAN, SUB
- vt->parser.in_esc = false;
- ENTER_NORMAL_STATE();
- if(vt->parser.emit_nul)
- do_control(vt, c);
- continue;
- }
- else if(c == 0x1b) { // ESC
- vt->parser.intermedlen = 0;
- if(!IS_STRING_STATE())
- vt->parser.state = NORMAL;
- vt->parser.in_esc = true;
- continue;
- }
- else if(c == 0x07 && // BEL, can stand for ST in OSC or DCS state
- IS_STRING_STATE()) {
- // fallthrough
- }
- else if(c < 0x20) { // other C0
- if(vt->parser.state == SOS)
- continue; // All other C0s permitted in SOS
-
- if(IS_STRING_STATE())
- string_fragment(vt, string_start, bytes + pos - string_start, false);
- do_control(vt, c);
- if(IS_STRING_STATE())
- string_start = bytes + pos + 1;
- continue;
- }
- // else fallthrough
-
- size_t string_len = bytes + pos - string_start;
-
- if(vt->parser.in_esc) {
- // Hoist an ESC letter into a C1 if we're not in a string mode
- // Always accept ESC \ == ST even in string mode
- if(!vt->parser.intermedlen &&
- c >= 0x40 && c < 0x60 &&
- ((!IS_STRING_STATE() || c == 0x5c))) {
- c += 0x40;
- c1_allowed = true;
- if(string_len) {
- assert(string_len > 0);
- string_len -= 1;
- }
- vt->parser.in_esc = false;
- }
- else {
- string_start = NULL;
- vt->parser.state = NORMAL;
- }
- }
-
- switch(vt->parser.state) {
- case CSI_LEADER:
- /* Extract leader bytes 0x3c to 0x3f */
- if(c >= 0x3c && c <= 0x3f) {
- if(vt->parser.v.csi.leaderlen < CSI_LEADER_MAX-1)
- vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen++] = c;
- break;
- }
-
- /* else fallthrough */
- vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen] = 0;
-
- vt->parser.v.csi.argi = 0;
- vt->parser.v.csi.args[0] = CSI_ARG_MISSING;
- vt->parser.state = CSI_ARGS;
-
- /* fallthrough */
- case CSI_ARGS:
- /* Numerical value of argument */
- if(c >= '0' && c <= '9') {
- if(vt->parser.v.csi.args[vt->parser.v.csi.argi] == CSI_ARG_MISSING)
- vt->parser.v.csi.args[vt->parser.v.csi.argi] = 0;
- vt->parser.v.csi.args[vt->parser.v.csi.argi] *= 10;
- vt->parser.v.csi.args[vt->parser.v.csi.argi] += c - '0';
- break;
- }
- if(c == ':') {
- vt->parser.v.csi.args[vt->parser.v.csi.argi] |= CSI_ARG_FLAG_MORE;
- c = ';';
- }
- if(c == ';') {
- vt->parser.v.csi.argi++;
- vt->parser.v.csi.args[vt->parser.v.csi.argi] = CSI_ARG_MISSING;
- break;
- }
-
- /* else fallthrough */
- vt->parser.v.csi.argi++;
- vt->parser.intermedlen = 0;
- vt->parser.state = CSI_INTERMED;
- case CSI_INTERMED:
- if(is_intermed(c)) {
- if(vt->parser.intermedlen < INTERMED_MAX-1)
- vt->parser.intermed[vt->parser.intermedlen++] = c;
- break;
- }
- else if(c == 0x1b) {
- /* ESC in CSI cancels */
- }
- else if(c >= 0x40 && c <= 0x7e) {
- vt->parser.intermed[vt->parser.intermedlen] = 0;
- do_csi(vt, c);
- }
- /* else was invalid CSI */
-
- ENTER_NORMAL_STATE();
- break;
-
- case OSC_COMMAND:
- /* Numerical value of command */
- if(c >= '0' && c <= '9') {
- if(vt->parser.v.osc.command == -1)
- vt->parser.v.osc.command = 0;
- else
- vt->parser.v.osc.command *= 10;
- vt->parser.v.osc.command += c - '0';
- break;
- }
- if(c == ';') {
- vt->parser.state = OSC;
- string_start = bytes + pos + 1;
- break;
- }
-
- /* else fallthrough */
- string_start = bytes + pos;
- string_len = 0;
- vt->parser.state = OSC;
- goto string_state;
-
- case DCS_COMMAND:
- if(vt->parser.v.dcs.commandlen < CSI_LEADER_MAX)
- vt->parser.v.dcs.command[vt->parser.v.dcs.commandlen++] = c;
-
- if(c >= 0x40 && c<= 0x7e) {
- string_start = bytes + pos + 1;
- vt->parser.state = DCS;
- }
- break;
-
-string_state:
- case OSC:
- case DCS:
- case APC:
- case PM:
- case SOS:
- if(c == 0x07 || (c1_allowed && c == 0x9c)) {
- string_fragment(vt, string_start, string_len, true);
- ENTER_NORMAL_STATE();
- }
- break;
-
- case NORMAL:
- if(vt->parser.in_esc) {
- if(is_intermed(c)) {
- if(vt->parser.intermedlen < INTERMED_MAX-1)
- vt->parser.intermed[vt->parser.intermedlen++] = c;
- }
- else if(c >= 0x30 && c < 0x7f) {
- do_escape(vt, c);
- vt->parser.in_esc = 0;
- ENTER_NORMAL_STATE();
- }
- else {
- DEBUG_LOG("TODO: Unhandled byte %02x in Escape\n", c);
- }
- break;
- }
- if(c1_allowed && c >= 0x80 && c < 0xa0) {
- switch(c) {
- case 0x90: // DCS
- vt->parser.string_initial = true;
- vt->parser.v.dcs.commandlen = 0;
- ENTER_STATE(DCS_COMMAND);
- break;
- case 0x98: // SOS
- vt->parser.string_initial = true;
- ENTER_STATE(SOS);
- string_start = bytes + pos + 1;
- string_len = 0;
- break;
- case 0x9b: // CSI
- vt->parser.v.csi.leaderlen = 0;
- ENTER_STATE(CSI_LEADER);
- break;
- case 0x9d: // OSC
- vt->parser.v.osc.command = -1;
- vt->parser.string_initial = true;
- string_start = bytes + pos + 1;
- ENTER_STATE(OSC_COMMAND);
- break;
- case 0x9e: // PM
- vt->parser.string_initial = true;
- ENTER_STATE(PM);
- string_start = bytes + pos + 1;
- string_len = 0;
- break;
- case 0x9f: // APC
- vt->parser.string_initial = true;
- ENTER_STATE(APC);
- string_start = bytes + pos + 1;
- string_len = 0;
- break;
- default:
- do_control(vt, c);
- break;
- }
- }
- else {
- size_t eaten = 0;
- if(vt->parser.callbacks && vt->parser.callbacks->text)
- eaten = (*vt->parser.callbacks->text)(bytes + pos, len - pos, vt->par