summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Filelist1
-rw-r--r--src/libvterm/Makefile4
-rw-r--r--src/libvterm/doc/seqs.txt483
-rw-r--r--src/libvterm/include/vterm.h27
-rw-r--r--src/libvterm/src/mouse.c3
-rw-r--r--src/libvterm/src/parser.c55
-rw-r--r--src/libvterm/src/state.c326
-rw-r--r--src/libvterm/src/vterm.c32
-rw-r--r--src/libvterm/src/vterm_internal.h24
-rw-r--r--src/libvterm/t/02parser.test56
-rw-r--r--src/libvterm/t/17state_mouse.test9
-rw-r--r--src/libvterm/t/29state_fallback.test12
-rw-r--r--src/libvterm/t/40state_selection.test55
-rw-r--r--src/libvterm/t/harness.c116
-rw-r--r--src/libvterm/t/run-test.pl14
-rw-r--r--src/libvterm/vterm.pc.in3
-rw-r--r--src/terminal.c5
-rw-r--r--src/version.c2
18 files changed, 971 insertions, 256 deletions
diff --git a/Filelist b/Filelist
index 1ab6e1b1c8..f89289d185 100644
--- a/Filelist
+++ b/Filelist
@@ -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