diff options
-rw-r--r-- | Filelist | 1 | ||||
-rw-r--r-- | src/libvterm/Makefile | 4 | ||||
-rw-r--r-- | src/libvterm/doc/seqs.txt | 483 | ||||
-rw-r--r-- | src/libvterm/include/vterm.h | 27 | ||||
-rw-r--r-- | src/libvterm/src/mouse.c | 3 | ||||
-rw-r--r-- | src/libvterm/src/parser.c | 55 | ||||
-rw-r--r-- | src/libvterm/src/state.c | 326 | ||||
-rw-r--r-- | src/libvterm/src/vterm.c | 32 | ||||
-rw-r--r-- | src/libvterm/src/vterm_internal.h | 24 | ||||
-rw-r--r-- | src/libvterm/t/02parser.test | 56 | ||||
-rw-r--r-- | src/libvterm/t/17state_mouse.test | 9 | ||||
-rw-r--r-- | src/libvterm/t/29state_fallback.test | 12 | ||||
-rw-r--r-- | src/libvterm/t/40state_selection.test | 55 | ||||
-rw-r--r-- | src/libvterm/t/harness.c | 116 | ||||
-rw-r--r-- | src/libvterm/t/run-test.pl | 14 | ||||
-rw-r--r-- | src/libvterm/vterm.pc.in | 3 | ||||
-rw-r--r-- | src/terminal.c | 5 | ||||
-rw-r--r-- | src/version.c | 2 |
18 files changed, 971 insertions, 256 deletions
@@ -377,6 +377,7 @@ SRC_ALL = \ src/libvterm/t/30state_pen.test \ src/libvterm/t/31state_rep.test \ src/libvterm/t/32state_flow.test \ + src/libvterm/t/40state_selection.test \ src/libvterm/t/60screen_ascii.test \ src/libvterm/t/61screen_unicode.test \ src/libvterm/t/62screen_damage.test \ diff --git a/src/libvterm/Makefile b/src/libvterm/Makefile index be01dd0705..2f83e0d68c 100644 --- a/src/libvterm/Makefile +++ b/src/libvterm/Makefile @@ -37,7 +37,7 @@ INCFILES=$(TBLFILES:.tbl=.inc) HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES) VERSION_MAJOR=0 -VERSION_MINOR=1 +VERSION_MINOR=2 VERSION_CURRENT=0 VERSION_REVISION=0 @@ -97,7 +97,7 @@ install-inc: install -d $(DESTDIR)$(INCDIR) install -m644 $(HFILES) $(DESTDIR)$(INCDIR) install -d $(DESTDIR)$(LIBDIR)/pkgconfig - sed -e "s,@PREFIX@,$(PREFIX)," -e "s,@LIBDIR@,$(LIBDIR)," -e "s,@VERSION@,$(VERSION)," <vterm.pc.in >$(DESTDIR)$(LIBDIR)/pkgconfig/vterm.pc + sed -e "s,@INCDIR@,$(INCDIR)," -e "s,@LIBDIR@,$(LIBDIR)," -e "s,@VERSION@,$(VERSION)," <vterm.pc.in >$(DESTDIR)$(LIBDIR)/pkgconfig/vterm.pc install-lib: $(LIBRARY) install -d $(DESTDIR)$(LIBDIR) diff --git a/src/libvterm/doc/seqs.txt b/src/libvterm/doc/seqs.txt index aa15fec3df..7f21367e92 100644 --- a/src/libvterm/doc/seqs.txt +++ b/src/libvterm/doc/seqs.txt @@ -4,228 +4,275 @@ between states. 1 = VT100 2 = VT220 3 = VT320 +x = xterm - C0 controls - -123 0x00 = NUL -123 0x07 = BEL -123 0x08 = BS -123 0x09 = HT -123 0x0A = LF -123 0x0B = VT -123 0x0C = FF -123 0x0D = CR -123 0x0E = LS1 -123 0x0F = LS0 - (0x18 = CAN) - (0x1A = SUB) - (0x1B = ESC) - -123 0x7f = DEL (ignored) - - C1 controls - -123 0x84 = IND -123 0x85 = NEL -123 0x88 = HTS -123 0x8D = RI - 23 0x8e = SS2 - 23 0x8f = SS3 - (0x90 = DCS) - (0x9B = CSI) - (0x9C = ST) - (0x9D = OSC) - - Escape sequences - - excluding sequences that are C1 aliases - -123 ESC () = SCS, select character set (G0, G1) - 23 ESC *+ = SCS, select character set (G2, G3) -123 ESC 7 = DECSC - save cursor -123 ESC 8 = DECRC - restore cursor -123 ESC # 3 = DECDHL, double-height line (top half) -123 ESC # 4 = DECDHL, double-height line (bottom half) -123 ESC # 5 = DECSWL, single-width single-height line -123 ESC # 6 = DECDWL, double-width single-height line -123 ESC # 8 = DECALN -123 ESC < = Ignored (used by VT100 to exit VT52 mode) -123 ESC = = DECKPAM, keypad application mode -123 ESC > = DECKPNM, keypad numeric mode - 23 ESC Sp F = S7C1T - 23 ESC Sp G = S8C1T - (ESC P = DCS) - (ESC [ = CSI) - (ESC \ = ST) - (ESC ] = OSC) -123 ESC c = RIS, reset initial state - 3 ESC n = LS2 - 3 ESC o = LS3 - 3 ESC ~ = LS1R - 3 ESC } = LS2R - 3 ESC | = LS3R - - DCSes - - 3 DCS $ q ST = DECRQSS - 3 m = Request SGR - Sp q = Request DECSCUSR - 3 " q = Request DECSCA - 3 r = Request DECSTBM - s = Request DECSLRM - - CSIs - 23 CSI @ = ICH -123 CSI A = CUU -123 CSI B = CUD -123 CSI C = CUF -123 CSI D = CUB - CSI E = CNL - CSI F = CPL - CSI G = CHA -123 CSI H = CUP - CSI I = CHT -123 CSI J = ED - 23 CSI ? J = DECSED, selective erase in display -123 CSI K = EL - 23 CSI ? K = DECSEL, selective erase in line - 23 CSI L = IL - 23 CSI M = DL - 23 CSI P = DCH - CSI S = SU - CSI T = SD - 23 CSI X = ECH - CSI Z = CBT - CSI ` = HPA - CSI a = HPR - CSI b = REP -123 CSI c = DA, device attributes -123 0 = DA - 23 CSI > c = DECSDA - 23 0 = SDA - CSI d = VPA - CSI e = VPR -123 CSI f = HVP -123 CSI g = TBC -123 CSI h = SM, Set mode -123 CSI ? h = DECSM, DEC set mode - CSI j = HPB - CSI k = VPB -123 CSI l = RM, Reset mode -123 CSI ? l = DECRM, DEC reset mode -123 CSI m = SGR, Set Graphic Rendition -123 CSI n = DSR, Device Status Report - 23 5 = operating status - 23 6 = CPR = cursor position - 23 CSI ? n = DECDSR; behaves as DSR but uses CSI ? instead of CSI to respond - 23 CSI ! p = DECSTR, soft terminal reset - 3 CSI ? $ p = DECRQM, request mode - CSI Sp q = DECSCUSR (odd numbers blink, even numbers solid) - 1 or 2 = block - 3 or 4 = underline - 5 or 6 = I-beam to left - 23 CSI " q = DECSCA, select character attributes -123 CSI r = DECSTBM - CSI s = DECSLRM - CSI ' } = DECIC - CSI ' ~ = DECDC - - OSCs - - OSC 0; = Set icon name and title - OSC 1; = Set icon name - OSC 2; = Set title - - Standard modes - - 23 SM 4 = IRM -123 SM 20 = NLM, linefeed/newline - - DEC modes - -123 DECSM 1 = DECCKM, cursor keys -123 DECSM 5 = DECSCNM, screen -123 DECSM 6 = DECOM, origin -123 DECSM 7 = DECAWM, autowrap - DECSM 12 = Cursor blink - 23 DECSM 25 = DECTCEM, text cursor enable - DECSM 69 = DECVSSM, vertical screen split - DECSM 1000 = Mouse click/release tracking - DECSM 1002 = Mouse click/release/drag tracking - DECSM 1003 = Mouse all movements tracking - DECSM 1004 = Focus in/out reporting - DECSM 1005 = Mouse protocol extended (UTF-8) - not recommended - DECSM 1006 = Mouse protocol SGR - DECSM 1015 = Mouse protocol rxvt - DECSM 1047 = Altscreen - DECSM 1048 = Save cursor - DECSM 1049 = 1047 + 1048 - DECSM 2004 = Bracketed paste - - Graphic Renditions - -123 SGR 0 = Reset -123 SGR 1 = Bold on - SGR 3 = Italic on -123 SGR 4 = Underline single - SGR 4:x = Underline style -123 SGR 5 = Blink on -123 SGR 7 = Reverse on - SGR 8 = Conceal on - SGR 9 = Strikethrough on - SGR 10-19 = Select font - SGR 21 = Underline double - 23 SGR 22 = Bold off - SGR 23 = Italic off - 23 SGR 24 = Underline off - 23 SGR 25 = Blink off - 23 SGR 27 = Reverse off - SGR 28 = Conceal off - SGR 29 = Strikethrough off - SGR 30-37 = Foreground ANSI - SGR 38 = Foreground alternative palette - SGR 39 = Foreground default - SGR 40-47 = Background ANSI - SGR 48 = Background alternative palette - SGR 49 = Background default - SGR 90-97 = Foreground ANSI high-intensity - SGR 100-107 = Background ANSI high-intensity + C0 controls + +123 0x00 = NUL +123x 0x07 = BEL +123x 0x08 = BS +123x 0x09 = HT +123x 0x0A = LF +123x 0x0B = VT +123x 0x0C = FF +123x 0x0D = CR +123x 0x0E = LS1 +123x 0x0F = LS0 + (0x18 = CAN) + (0x1A = SUB) + (0x1B = ESC) + +123 0x7f = DEL (ignored) + + C1 controls + +123x 0x84 = IND +123x 0x85 = NEL +123x 0x88 = HTS +123x 0x8D = RI + 23x 0x8E = SS2 + 23x 0x8F = SS3 + (0x90 = DCS) + (0x98 = SOS) + (0x9B = CSI) + (0x9C = ST) + (0x9D = OSC) + (0x9E = PM) + (0x9F = APC) + + Escape sequences + - excluding sequences that are C1 aliases + +123x ESC ( = SCS, select character set G0 +123x ESC ) = SCS, select character set G1 + 23x ESC * = SCS, select character set G2 + 23x ESC + = SCS, select character set G3 +123x ESC 7 = DECSC - save cursor +123x ESC 8 = DECRC - restore cursor +123x ESC # 3 = DECDHL, double-height line (top half) +123x ESC # 4 = DECDHL, double-height line (bottom half) +123x ESC # 5 = DECSWL, single-width single-height line +123x ESC # 6 = DECDWL, double-width single-height line +123x ESC # 8 = DECALN +123 ESC < = Ignored (used by VT100 to exit VT52 mode) +123x ESC = = DECKPAM, keypad application mode +123x ESC > = DECKPNM, keypad numeric mode + 23x ESC Sp F = S7C1T + 23x ESC Sp G = S8C1T + (ESC P = DCS) + (ESC X = SOS) + (ESC [ = CSI) + (ESC \ = ST) + (ESC ] = OSC) + (ESC ^ = PM) + (ESC _ = APC) +123x ESC c = RIS, reset initial state + 3x ESC n = LS2 + 3x ESC o = LS3 + 3x ESC | = LS3R + 3x ESC } = LS2R + 3x ESC ~ = LS1R + + DCSes + + 3x DCS $ q ST = DECRQSS + 3x m = Request SGR + x Sp q = Request DECSCUSR + 3x " q = Request DECSCA + 3x r = Request DECSTBM + x s = Request DECSLRM + + CSIs + 23x CSI @ = ICH +123x CSI A = CUU +123x CSI B = CUD +123x CSI C = CUF +123x CSI D = CUB + x CSI E = CNL + x CSI F = CPL + x CSI G = CHA +123x CSI H = CUP + x CSI I = CHT +123x CSI J = ED + 23x CSI ? J = DECSED, selective erase in display +123x CSI K = EL + 23x CSI ? K = DECSEL, selective erase in line + 23x CSI L = IL + 23x CSI M = DL + 23x CSI P = DCH + x CSI S = SU + x CSI T = SD + 23x CSI X = ECH + x CSI Z = CBT + x CSI ` = HPA + x CSI a = HPR + x CSI b = REP +123x CSI c = DA, device attributes +123 0 = DA + 23x CSI > c = DECSDA + 23 0 = SDA + x CSI d = VPA + x CSI e = VPR +123x CSI f = HVP +123x CSI g = TBC +123x CSI h = SM, Set mode +123x CSI ? h = DECSM, DEC set mode + CSI j = HPB + CSI k = VPB +123x CSI l = RM, Reset mode +123x CSI ? l = DECRM, DEC reset mode +123x CSI m = SGR, Set Graphic Rendition +123x CSI n = DSR, Device Status Report + 23x 5 = operating status + 23x 6 = CPR = cursor position + 23x CSI ? n = DECDSR; behaves as DSR but uses CSI ? instead of CSI to respond + 23x CSI ! p = DECSTR, soft terminal reset + 3x CSI ? $ p = DECRQM, request private mode + x CSI Sp q = DECSCUSR (odd numbers blink, even numbers solid) + 1 or 2 = block + 3 or 4 = underline + 5 or 6 = I-beam to left + 23x CSI " q = DECSCA, select character attributes +123x CSI r = DECSTBM + x CSI s = DECSLRM + x CSI ' } = DECIC + x CSI ' ~ = DECDC + + OSCs + + x OSC 0; = Set icon name and title + x OSC 1; = Set icon name + x OSC 2; = Set title + x OSC 52; = Selection management + + Standard modes + + 23x SM 4 = IRM +123x SM 20 = NLM, linefeed/newline + + DEC modes + +123x DECSM 1 = DECCKM, cursor keys +123x DECSM 5 = DECSCNM, screen +123x DECSM 6 = DECOM, origin +123x DECSM 7 = DECAWM, autowrap + x DECSM 12 = Cursor blink + 23x DECSM 25 = DECTCEM, text cursor enable + x DECSM 69 = DECVSSM, vertical screen split + x DECSM 1000 = Mouse click/release tracking + x DECSM 1002 = Mouse click/release/drag tracking + x DECSM 1003 = Mouse all movements tracking + x DECSM 1004 = Focus in/out reporting + x DECSM 1005 = Mouse protocol extended (UTF-8) - not recommended + x DECSM 1006 = Mouse protocol SGR + x DECSM 1015 = Mouse protocol rxvt + x DECSM 1047 = Altscreen + x DECSM 1048 = Save cursor + x DECSM 1049 = 1047 + 1048 + x DECSM 2004 = Bracketed paste + + Graphic Renditions + +123x SGR 0 = Reset +123x SGR 1 = Bold on + x SGR 3 = Italic on +123x SGR 4 = Underline single + SGR 4:x = Underline style +123x SGR 5 = Blink on +123x SGR 7 = Reverse on + x SGR 8 = Conceal on + x SGR 9 = Strikethrough on + SGR 10-19 = Select font + x SGR 21 = Underline double + 23x SGR 22 = Bold off + x SGR 23 = Italic off + 23x SGR 24 = Underline off + 23x SGR 25 = Blink off + 23x SGR 27 = Reverse off + x SGR 28 = Conceal off + x SGR 29 = Strikethrough off + x SGR 30-37 = Foreground ANSI + x SGR 38 = Foreground alternative palette + x SGR 39 = Foreground default + x SGR 40-47 = Background ANSI + x SGR 48 = Background alternative palette + x SGR 49 = Background default + x SGR 90-97 = Foreground ANSI high-intensity + x SGR 100-107 = Background ANSI high-intensity The state storage used by ESC 7 and DECSM 1048/1049 is shared. - Unimplemented sequences: + Unimplemented sequences: The following sequences are not recognised by libvterm. -123 0x05 = ENQ - 3 0x11 = DC1 (XON) - 3 0x13 = DC3 (XOFF) -12 ESC Z = DECID, identify terminal - DCS $ q = [DECRQSS] - 3 " p = Request DECSCL - 3 $ } = Request DECSASD - 3 $ ~ = Request DECSSDT - 23 DCS { = DECDLD, down-line-loadable character set - 23 DCS | = DECUDK, user-defined key - 23 CSI i = DEC printer control - 23 CSI " p = DECSCL, set compatibility level -1 CSI q = DECLL, load LEDs - 3 CSI $ u = DECRQTSR, request terminal state report - 3 1 = terminal state report - 3 CSI & u = DECRQUPSS, request user-preferred supplemental set - 3 CSI $ w = DECRQPSR, request presentation state report - 3 1 = cursor information report - 3 2 = tab stop report -1 CSI x = DECREQTPARM, request terminal parameters -123 CSI y = DECTST, invoke confidence test - 3 CSI $ } = DECSASD, select active status display - 3 CSI $ ~ = DECSSDT, select status line type - 23 SM 2 = KAM, keyboard action -123 SM 12 = SRM, send/receive -123 DECSM 2 = DECANM, ANSI/VT52 -123 DECSM 3 = DECCOLM, 132 column -123 DECSM 4 = DECSCLM, scrolling -123 DECSM 8 = DECARM, auto-repeat -12 DECSM 9 = DECINLM, interlace - 23 DECSM 18 = DECPFF, print form feed - 23 DECSM 19 = DECPEX, print extent - 23 DECSM 42 = DECNRCM, national/multinational character +123x 0x05 = ENQ + 3 0x11 = DC1 (XON) + 3 0x13 = DC3 (XOFF) + x ESC % @ = Select default character set + x ESC % G = Select UTF-8 character set + x ESC 6 = DECBI, Back Index +12 ESC Z = DECID, identify terminal + x DCS + Q = XTGETXRES, Request resource values + DCS $ q = [DECRQSS] + 3x " p = Request DECSCL + x t = Request DECSLPP + x $ | = Request DECSCPP + x * | = Request DECSLNS + 3 $ } = Request DECSASD + 3 $ ~ = Request DECSSDT + x DCS + p = XTSETTCAP, set termcap/terminfo data + x DCS + q = XTGETTCAP, request termcap/terminfo + 23 DCS { = DECDLD, down-line-loadable character set + 23x DCS | = DECUDK, user-defined key + x CSI Sp @ = Shift left columns + x CSI Sp A = Shift right columns + x CSI # P = XTPUSHCOLORS, push current dynamic colours to stack + x CSI # Q = XTPOPCOLORS, pop dynamic colours from stack + x CSI # R = XTREPORTCOLORS, report current entry on palette stack + x CSI ? S = XTSMGRAPHICS, set/request graphics attribute + x CSI > T = XTRMTITLE, reset title mode features + 23x CSI i = DEC printer control + x CSI > m = XTMODKEYS, set key modifier options + x CSI > n = (XTMODKEYS), reset key modifier options + x CSI $ p = DECRQM, request ANSI mode + 23x CSI " p = DECSCL, set compatibility level + x CSI > p = XTSMPOINTER, set resource value pointer mode +1 x CSI q = DECLL, load LEDs + x CSI ? r = XTRESTORE, restore DEC private mode values + x CSI $ r = DECCARA, change attributes in rectangular area + x CSI > s = XTSHIFTESCAPE, set/reset shift-escape options + x CSI ? s = XTSAVE, save DEC private mode values + x CSI t = XTWINOPS, window operations + x CSI > t = XTSMTITLE, set title mode features + x CSI $ t = DECRARA, reset attributes in rectangular area + 3 CSI $ u = DECRQTSR, request terminal state report + 3 1 = terminal state report + 3 CSI & u = DECRQUPSS, request user-preferred supplemental set + x CSI $ v = DECCRA, copy rectangular area + 3x CSI $ w = DECRQPSR, request presentation state report + 3x 1 = cursor information report + 3x 2 = tab stop report + x CSI ' w = DECEFR, enable filter rectangle +1 x CSI x = DECREQTPARM, request terminal parameters + x CSI * x = DECSACE, select attribute change extent + x CSI $ x = DECFRA, fill rectangular area +123 CSI y = DECTST, invoke confidence test + x CSI $ z = DECERA, erase rectangular area + x CSI # { = XTPUSHSGR, push video attributes onto stack + x CSI $ { = DECSERA, selective erase in rectangular area + x CSI # | = XTREPORTSGR, report selected graphic rendition + x CSI $ | = DECSCPP, select columns per page + x CSI # } = XTPOPSGR, pop video attributes from stack + 3 CSI $ } = DECSASD, select active status display + 3 CSI $ ~ = DECSSDT, select status line type + 23 SM 2 = KAM, keyboard action +123 SM 12 = SRM, send/receive +123 DECSM 2 = DECANM, ANSI/VT52 +123 DECSM 3 = DECCOLM, 132 column +123 DECSM 4 = DECSCLM, scrolling +123 DECSM 8 = DECARM, auto-repeat +12 DECSM 9 = DECINLM, interlace + 23 DECSM 18 = DECPFF, print form feed + 23 DECSM 19 = DECPEX, print extent + 23 DECSM 42 = DECNRCM, national/multinational character diff --git a/src/libvterm/include/vterm.h b/src/libvterm/include/vterm.h index 9873b6d555..d553fbd51a 100644 --- a/src/libvterm/include/vterm.h +++ b/src/libvterm/include/vterm.h @@ -17,10 +17,11 @@ extern "C" { // from stdint.h typedef unsigned char uint8_t; +typedef unsigned short uint16_t; typedef unsigned int uint32_t; #define VTERM_VERSION_MAJOR 0 -#define VTERM_VERSION_MINOR 1 +#define VTERM_VERSION_MINOR 2 #define VTERM_CHECK_VERSION \ vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR) @@ -267,6 +268,14 @@ enum { VTERM_N_PROP_MOUSES }; +typedef enum { + VTERM_SELECTION_CLIPBOARD = (1<<0), + VTERM_SELECTION_PRIMARY = (1<<1), + VTERM_SELECTION_SECONDARY = (1<<2), + VTERM_SELECTION_SELECT = (1<<3), + VTERM_SELECTION_CUT0 = (1<<4), /* also CUT1 .. CUT7 by bitshifting */ +} VTermSelectionMask; + typedef struct { const uint32_t *chars; int width; @@ -375,6 +384,9 @@ typedef struct { int (*csi)(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user); int (*osc)(int command, VTermStringFragment frag, void *user); int (*dcs)(const char *command, size_t commandlen, VTermStringFragment frag, void *user); + int (*apc)(VTermStringFragment frag, void *user); + int (*pm)(VTermStringFragment frag, void *user); + int (*sos)(VTermStringFragment frag, void *user); int (*resize)(int rows, int cols, void *user); } VTermParserCallbacks; @@ -419,8 +431,16 @@ typedef struct { int (*csi)(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user); int (*osc)(int command, VTermStringFragment frag, void *user); int (*dcs)(const char *command, size_t commandlen, VTermStringFragment frag, void *user); + int (*apc)(VTermStringFragment frag, void *user); + int (*pm)(VTermStringFragment frag, void *user); + int (*sos)(VTermStringFragment frag, void *user); } VTermStateFallbacks; +typedef struct { + int (*set)(VTermSelectionMask mask, VTermStringFragment frag, void *user); + int (*query)(VTermSelectionMask mask, void *user); +} VTermSelectionCallbacks; + VTermState *vterm_obtain_state(VTerm *vt); void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user); @@ -457,6 +477,11 @@ const VTermLineInfo *vterm_state_get_lineinfo(const VTermState *state, int row); */ void vterm_state_convert_color_to_rgb(const VTermState *state, VTermColor *col); +void vterm_state_set_selection_callbacks(VTermState *state, const VTermSelectionCallbacks *callbacks, void *user, + char *buffer, size_t buflen); + +void vterm_state_send_selection(VTermState *state, VTermSelectionMask mask, VTermStringFragment frag); + // ------------ // Screen layer // ------------ diff --git a/src/libvterm/src/mouse.c b/src/libvterm/src/mouse.c index ed60b0147d..5f35d56488 100644 --- a/src/libvterm/src/mouse.c +++ b/src/libvterm/src/mouse.c @@ -89,6 +89,9 @@ void vterm_mouse_button(VTerm *vt, int button, int pressed, VTermModifier mod) if (!(state->mouse_flags & MOUSE_WANT_CLICK)) return; + if(!state->mouse_flags) + return; + if(button < 4) { output_mouse(state, button-1, pressed, mod, state->mouse_col, state->mouse_row); } diff --git a/src/libvterm/src/parser.c b/src/libvterm/src/parser.c index 490f5ce1bb..0d4422cf49 100644 --- a/src/libvterm/src/parser.c +++ b/src/libvterm/src/parser.c @@ -77,10 +77,25 @@ static void string_fragment(VTerm *vt, const char *str, size_t len, int final) break; case DCS: - if(len && vt->parser.callbacks && vt->parser.callbacks->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: @@ -112,6 +127,9 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) break; case OSC: case DCS: + case APC: + case PM: + case SOS: string_start = bytes; break; } @@ -150,6 +168,9 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) // fallthrough } else if(c < 0x20) { // other C0 + if(vt->parser.state == SOS) + continue; // All other C0s permitted in SOS + if(vterm_get_special_pty_type() == 2) { if(c == 0x08) // BS // Set the trick for BS output after a sequence, to delay backspace @@ -176,7 +197,8 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) ((!IS_STRING_STATE() || c == 0x5c))) { c += 0x40; c1_allowed = TRUE; - string_len -= 1; + if(string_len) + string_len -= 1; vt->parser.in_esc = FALSE; } else { @@ -279,6 +301,9 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) 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(); @@ -308,6 +333,12 @@ string_state: 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); @@ -318,6 +349,18 @@ string_state: 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; @@ -340,8 +383,12 @@ string_state: } } - if(string_start) - string_fragment(vt, string_start, bytes + pos - string_start, FALSE); + if(string_start) { + size_t string_len = bytes + pos - string_start; + if(vt->parser.in_esc) + string_len -= 1; + string_fragment(vt, string_start, string_len, FALSE); + } return len; } diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c index afb188c7e2..e3c76bc1a1 100644 --- a/src/libvterm/src/state.c +++ b/src/libvterm/src/state.c @@ -79,6 +79,10 @@ static VTermState *vterm_state_new(VTerm *vt) state->callbacks = NULL; state->cbdata = NULL; + state->selection.callbacks = NULL; + state->selection.user = NULL; + state->selection.buffer = NULL; + vterm_state_newpen(state); state->bold_is_highbright = 0; @@ -1615,6 +1619,174 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha return 1; } +static char base64_one(uint8_t b) +{ + if(b < 26) + return 'A' + b; + else if(b < 52) + return 'a' + b - 26; + else if(b < 62) + return '0' + b - 52; + else if(b == 62) + return '+'; + else if(b == 63) + return '/'; + return 0; +} + +static uint8_t unbase64one(char c) +{ + if(c >= 'A' && c <= 'Z') + return c - 'A'; + else if(c >= 'a' && c <= 'z') + return c - 'a' + 26; + else if(c >= '0' && c <= '9') + return c - '0' + 52; + else if(c == '+') + return 62; + else if(c == '/') + return 63; + + return 0xFF; +} + +static void osc_selection(VTermState *state, VTermStringFragment frag) +{ + if(frag.initial) { + state->tmp.selection.mask = 0; + state->tmp.selection.state = SELECTION_INITIAL; + } + + while(!state->tmp.selection.state && frag.len) { + /* Parse selection parameter */ + switch(frag.str[0]) { + case 'c': + state->tmp.selection.mask |= VTERM_SELECTION_CLIPBOARD; + break; + case 'p': + state->tmp.selection.mask |= VTERM_SELECTION_PRIMARY; + break; + case 'q': + state->tmp.selection.mask |= VTERM_SELECTION_SECONDARY; + break; + case 's': + state->tmp.selection.mask |= VTERM_SELECTION_SELECT; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + state->tmp.selection.mask |= (VTERM_SELECTION_CUT0 << (frag.str[0] - '0')); + break; + + case ';': + state->tmp.selection.state = SELECTION_SELECTED; + if(!state->tmp.selection.mask) + state->tmp.selection.mask = VTERM_SELECTION_SELECT|VTERM_SELECTION_CUT0; + break; + } + + frag.str++; + frag.len--; + } + + if(!frag.len) + return; + + if(state->tmp.selection.state == SELECTION_SELECTED) { + if(frag.str[0] == '?') { + state->tmp.selection.state = SELECTION_QUERY; + } + else { + state->tmp.selection.state = SELECTION_SET_INITIAL; + state->tmp.selection.recvpartial = 0; + } + } + + if(state->tmp.selection.state == SELECTION_QUERY) { + if(state->selection.callbacks->query) + (*state->selection.callbacks->query)(state->tmp.selection.mask, state->selection.user); + return; + } + + if(state->selection.callbacks->set) { + size_t bufcur = 0; + char *buffer = state->selection.buffer; + + uint32_t x = 0; /* Current decoding value */ + int n = 0; /* Number of sextets consumed */ + + if(state->tmp.selection.recvpartial) { + n = state->tmp.selection.recvpartial >> 24; + x = state->tmp.selection.recvpartial & 0x03FFFF; /* could be up to 18 bits of state in here */ + + state->tmp.selection.recvpartial = 0; + } + + while((state->selection.buflen - bufcur) >= 3 && frag.len) { + if(frag.str[0] == '=') { + if(n == 2) { + buffer[0] = (x >> 4) & 0xFF; + buffer += 1, bufcur += 1; + } + if(n == 3) { + buffer[0] = (x >> 10) & 0xFF; + buffer[1] = (x >> 2) & 0xFF; + buffer += 2, bufcur += 2; + } + + while(frag.len && frag.str[0] == '=') + frag.str++, frag.len--; + + n = 0; + } + else { + uint8_t b = unbase64one(frag.str[0]); + if(b == 0xFF) { + DEBUG_LOG1("base64decode bad input %02X\n", (uint8_t)frag.str[0]); + } + else { + x = (x << 6) | b; + n++; + } + frag.str++, frag.len--; + + if(n == 4) { + buffer[0] = (x >> 16) & 0xFF; + buffer[1] = (x >> 8) & 0xFF; + buffer[2] = (x >> 0) & 0xFF; + + buffer += 3, bufcur += 3; + x = 0; + n = 0; + } + } + + if(!frag.len || (state->selection.buflen - bufcur) < 3) { + if(bufcur) { + (*state->selection.callbacks->set)(state->tmp.selection.mask, (VTermStringFragment){ + .str = state->selection.buffer, + .len = bufcur, + .initial = state->tmp.selection.state == SELECTION_SET_INITIAL, + .final = frag.final, + }, state->selection.user); < |