patch 8.2.3666: libvterm is outdated
Problem: Libvterm is outdated. Solution: Include patches from revision 769 to revision 789.
This commit is contained in:
1
Filelist
1
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 \
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -4,228 +4,275 @@ between states.
|
||||
1 = VT100
|
||||
2 = VT220
|
||||
3 = VT320
|
||||
x = xterm
|
||||
|
||||
C0 controls
|
||||
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 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)
|
||||
123 0x7f = DEL (ignored)
|
||||
|
||||
C1 controls
|
||||
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)
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
OSCs
|
||||
|
||||
OSC 0; = Set icon name and title
|
||||
OSC 1; = Set icon name
|
||||
OSC 2; = Set title
|
||||
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
|
||||
Standard modes
|
||||
|
||||
23 SM 4 = IRM
|
||||
123 SM 20 = NLM, linefeed/newline
|
||||
23x SM 4 = IRM
|
||||
123x SM 20 = NLM, linefeed/newline
|
||||
|
||||
DEC modes
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@ -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
|
||||
// ------------
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
state->tmp.selection.state = SELECTION_SET;
|
||||
}
|
||||
|
||||
buffer = state->selection.buffer;
|
||||
bufcur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(n)
|
||||
state->tmp.selection.recvpartial = (n << 24) | x;
|
||||
}
|
||||
}
|
||||
|
||||
static int on_osc(int command, VTermStringFragment frag, void *user)
|
||||
{
|
||||
VTermState *state = user;
|
||||
@ -1656,6 +1828,12 @@ static int on_osc(int command, VTermStringFragment frag, void *user)
|
||||
settermprop_string(state, VTERM_PROP_CURSORCOLOR, frag);
|
||||
return 1;
|
||||
|
||||
case 52:
|
||||
if(state->selection.callbacks)
|
||||
osc_selection(state, frag);
|
||||
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if(state->fallbacks && state->fallbacks->osc)
|
||||
if((*state->fallbacks->osc)(command, frag, state->fbdata))
|
||||
@ -1718,12 +1896,14 @@ static void request_status_string(VTermState *state, VTermStringFragment frag)
|
||||
|
||||
case 'r':
|
||||
// Query DECSTBM
|
||||
vterm_push_output_sprintf_dcs(vt, "1$r%d;%dr", state->scrollregion_top+1, SCROLLREGION_BOTTOM(state));
|
||||
vterm_push_output_sprintf_str(vt, C1_DCS, TRUE,
|
||||
"1$r%d;%dr", state->scrollregion_top+1, SCROLLREGION_BOTTOM(state));
|
||||
return;
|
||||
|
||||
case 's':
|
||||
// Query DECSLRM
|
||||
vterm_push_output_sprintf_dcs(vt, "1$r%d;%ds", SCROLLREGION_LEFT(state)+1, SCROLLREGION_RIGHT(state));
|
||||
vterm_push_output_sprintf_str(vt, C1_DCS, TRUE,
|
||||
"1$r%d;%ds", SCROLLREGION_LEFT(state)+1, SCROLLREGION_RIGHT(state));
|
||||
return;
|
||||
|
||||
case ' '|('q'<<8): {
|
||||
@ -1736,17 +1916,19 @@ static void request_status_string(VTermState *state, VTermStringFragment frag)
|
||||
}
|
||||
if(state->mode.cursor_blink)
|
||||
reply--;
|
||||
vterm_push_output_sprintf_dcs(vt, "1$r%d q", reply);
|
||||
vterm_push_output_sprintf_str(vt, C1_DCS, TRUE,
|
||||
"1$r%d q", reply);
|
||||
return;
|
||||
}
|
||||
|
||||
case '\"'|('q'<<8):
|
||||
// Query DECSCA
|
||||
vterm_push_output_sprintf_dcs(vt, "1$r%d\"q", state->protected_cell ? 1 : 2);
|
||||
vterm_push_output_sprintf_str(vt, C1_DCS, TRUE,
|
||||
"1$r%d\"q", state->protected_cell ? 1 : 2);
|
||||
return;
|
||||
}
|
||||
|
||||
vterm_push_output_sprintf_dcs(state->vt, "0$r%s", tmp);
|
||||
vterm_push_output_sprintf_str(state->vt, C1_DCS, TRUE, "0$r%s", tmp);
|
||||
}
|
||||
|
||||
static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
|
||||
@ -1765,6 +1947,42 @@ static int on_dcs(const char *command, size_t commandlen, VTermStringFragment fr
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_apc(VTermStringFragment frag, void *user)
|
||||
{
|
||||
VTermState *state = user;
|
||||
|
||||
if(state->fallbacks && state->fallbacks->apc)
|
||||
if((*state->fallbacks->apc)(frag, state->fbdata))
|
||||
return 1;
|
||||
|
||||
/* No DEBUG_LOG because all APCs are unhandled */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_pm(VTermStringFragment frag, void *user)
|
||||
{
|
||||
VTermState *state = user;
|
||||
|
||||
if(state->fallbacks && state->fallbacks->pm)
|
||||
if((*state->fallbacks->pm)(frag, state->fbdata))
|
||||
return 1;
|
||||
|
||||
/* No DEBUG_LOG because all PMs are unhandled */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_sos(VTermStringFragment frag, void *user)
|
||||
{
|
||||
VTermState *state = user;
|
||||
|
||||
if(state->fallbacks && state->fallbacks->sos)
|
||||
if((*state->fallbacks->sos)(frag, state->fbdata))
|
||||
return 1;
|
||||
|
||||
/* No DEBUG_LOG because all SOSs are unhandled */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_resize(int rows, int cols, void *user)
|
||||
{
|
||||
VTermState *state = user;
|
||||
@ -1866,6 +2084,9 @@ static const VTermParserCallbacks parser_callbacks = {
|
||||
on_csi, // csi
|
||||
on_osc, // osc
|
||||
on_dcs, // dcs
|
||||
on_apc, // apc
|
||||
on_pm, // pm
|
||||
on_sos, // sos
|
||||
on_resize // resize
|
||||
};
|
||||
|
||||
@ -1909,6 +2130,8 @@ void vterm_state_reset(VTermState *state, int hard)
|
||||
state->mode.bracketpaste = 0;
|
||||
state->mode.report_focus = 0;
|
||||
|
||||
state->mouse_flags = 0;
|
||||
|
||||
state->vt->mode.ctrl8bit = 0;
|
||||
|
||||
{
|
||||
@ -2087,3 +2310,96 @@ const VTermLineInfo *vterm_state_get_lineinfo(const VTermState *state, int row)
|
||||
{
|
||||
return state->lineinfo + row;
|
||||
}
|
||||
|
||||
void vterm_state_set_selection_callbacks(VTermState *state, const VTermSelectionCallbacks *callbacks, void *user,
|
||||
char *buffer, size_t buflen)
|
||||
{
|
||||
if(buflen && !buffer)
|
||||
buffer = vterm_allocator_malloc(state->vt, buflen);
|
||||
|
||||
state->selection.callbacks = callbacks;
|
||||
state->selection.user = user;
|
||||
state->selection.buffer = buffer;
|
||||
state->selection.buflen = buflen;
|
||||
}
|
||||
|
||||
void vterm_state_send_selection(VTermState *state, VTermSelectionMask mask, VTermStringFragment frag)
|
||||
{
|
||||
VTerm *vt = state->vt;
|
||||
|
||||
if(frag.initial) {
|
||||
/* TODO: support sending more than one mask bit */
|
||||
static char selection_chars[] = "cpqs";
|
||||
int idx;
|
||||
for(idx = 0; idx < 4; idx++)
|
||||
if(mask & (1 << idx))
|
||||
break;
|
||||
|
||||
vterm_push_output_sprintf_str(vt, C1_OSC, FALSE, "52;%c;", selection_chars[idx]);
|
||||
|
||||
state->tmp.selection.sendpartial = 0;
|
||||
}
|
||||
|
||||
if(frag.len) {
|
||||
size_t bufcur = 0;
|
||||
char *buffer = state->selection.buffer;
|
||||
|
||||
uint32_t x = 0;
|
||||
int n = 0;
|
||||
|
||||
if(state->tmp.selection.sendpartial) {
|
||||
n = state->tmp.selection.sendpartial >> 24;
|
||||
x = state->tmp.selection.sendpartial & 0xFFFFFF;
|
||||
|
||||
state->tmp.selection.sendpartial = 0;
|
||||
}
|
||||
|
||||
while((state->selection.buflen - bufcur) >= 4 && frag.len) {
|
||||
x = (x << 8) | frag.str[0];
|
||||
n++;
|
||||
frag.str++, frag.len--;
|
||||
|
||||
if(n == 3) {
|
||||
buffer[0] = base64_one((x >> 18) & 0x3F);
|
||||
buffer[1] = base64_one((x >> 12) & 0x3F);
|
||||
buffer[2] = base64_one((x >> 6) & 0x3F);
|
||||
buffer[3] = base64_one((x >> 0) & 0x3F);
|
||||
|
||||
buffer += 4, bufcur += 4;
|
||||
x = 0;
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if(!frag.len || (state->selection.buflen - bufcur) < 4) {
|
||||
if(bufcur)
|
||||
vterm_push_output_bytes(vt, state->selection.buffer, bufcur);
|
||||
|
||||
buffer = state->selection.buffer;
|
||||
bufcur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(n)
|
||||
state->tmp.selection.sendpartial = (n << 24) | x;
|
||||
}
|
||||
|
||||
if(frag.final) {
|
||||
if(state->tmp.selection.sendpartial) {
|
||||
int n = state->tmp.selection.sendpartial >> 24;
|
||||
uint32_t x = state->tmp.selection.sendpartial & 0xFFFFFF;
|
||||
char *buffer = state->selection.buffer;
|
||||
|
||||
/* n is either 1 or 2 now */
|
||||
x <<= (n == 1) ? 16 : 8;
|
||||
|
||||
buffer[0] = base64_one((x >> 18) & 0x3F);
|
||||
buffer[1] = base64_one((x >> 12) & 0x3F);
|
||||
buffer[2] = (n == 1) ? '=' : base64_one((x >> 6) & 0x3F);
|
||||
buffer[3] = '=';
|
||||
|
||||
vterm_push_output_sprintf_str(vt, 0, TRUE, "%.*s", 4, buffer);
|
||||
}
|
||||
else
|
||||
vterm_push_output_sprintf_str(vt, 0, TRUE, "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,27 +200,35 @@ INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, cons
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
INTERNAL void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...)
|
||||
INTERNAL void vterm_push_output_sprintf_str(VTerm *vt, unsigned char ctrl, int term, const char *fmt, ...)
|
||||
{
|
||||
size_t cur;
|
||||
va_list args;
|
||||
|
||||
cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
|
||||
vt->mode.ctrl8bit ? "\x90" : ESC_S "P"); // DCS
|
||||
if(ctrl) {
|
||||
if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
|
||||
cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
|
||||
ESC_S "%c", ctrl - 0x40);
|
||||
else
|
||||
cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
|
||||
"%c", ctrl);
|
||||
|
||||
if(cur >= vt->tmpbuffer_len)
|
||||
return;
|
||||
vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
|
||||
if(cur >= vt->tmpbuffer_len)
|
||||
return;
|
||||
vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
vterm_push_output_vsprintf(vt, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
|
||||
vt->mode.ctrl8bit ? "\x9C" : ESC_S "\\"); // ST
|
||||
if(cur >= vt->tmpbuffer_len)
|
||||
return;
|
||||
vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
|
||||
if(term) {
|
||||
cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
|
||||
vt->mode.ctrl8bit ? "\x9C" : ESC_S "\\"); // ST
|
||||
if(cur >= vt->tmpbuffer_len)
|
||||
return;
|
||||
vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
|
||||
}
|
||||
}
|
||||
|
||||
size_t vterm_output_get_buffer_size(const VTerm *vt)
|
||||
|
||||
@ -154,7 +154,26 @@ struct VTermState
|
||||
/* Temporary state for DECRQSS parsing */
|
||||
union {
|
||||
char decrqss[4];
|
||||
struct {
|
||||
uint16_t mask;
|
||||
enum {
|
||||
SELECTION_INITIAL,
|
||||
SELECTION_SELECTED,
|
||||
SELECTION_QUERY,
|
||||
SELECTION_SET_INITIAL,
|
||||
SELECTION_SET,
|
||||
} state : 8;
|
||||
uint32_t recvpartial;
|
||||
uint32_t sendpartial;
|
||||
} selection;
|
||||
} tmp;
|
||||
|
||||
struct {
|
||||
const VTermSelectionCallbacks *callbacks;
|
||||
void *user;
|
||||
char *buffer;
|
||||
size_t buflen;
|
||||
} selection;
|
||||
};
|
||||
|
||||
struct VTerm
|
||||
@ -181,6 +200,9 @@ struct VTerm
|
||||
OSC_COMMAND,
|
||||
OSC,
|
||||
DCS,
|
||||
APC,
|
||||
PM,
|
||||
SOS,
|
||||
} state;
|
||||
|
||||
unsigned int in_esc : 1;
|
||||
@ -248,7 +270,7 @@ void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len);
|
||||
void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args);
|
||||
void vterm_push_output_sprintf(VTerm *vt, const char *format, ...);
|
||||
void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...);
|
||||
void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...);
|
||||
void vterm_push_output_sprintf_str(VTerm *vt, unsigned char ctrl, int term, const char *fmt, ...);
|
||||
|
||||
void vterm_state_free(VTermState *state);
|
||||
|
||||
|
||||
@ -17,15 +17,15 @@ PUSH "\x1f"
|
||||
PUSH "\x83"
|
||||
control 0x83
|
||||
|
||||
PUSH "\x9f"
|
||||
control 0x9f
|
||||
PUSH "\x99"
|
||||
control 0x99
|
||||
|
||||
!C1 7bit
|
||||
PUSH "\e\x43"
|
||||
control 0x83
|
||||
|
||||
PUSH "\e\x5f"
|
||||
control 0x9f
|
||||
PUSH "\e\x59"
|
||||
control 0x99
|
||||
|
||||
!High bytes
|
||||
PUSH "\xa0\xcc\xfe"
|
||||
@ -184,6 +184,12 @@ PUSH "\ePHello\e\\"
|
||||
PUSH "\x{90}Hello\x9c"
|
||||
dcs ["Hello"]
|
||||
|
||||
!Split write of 7bit ST
|
||||
PUSH "\ePABC\e"
|
||||
dcs ["ABC"
|
||||
PUSH "\\"
|
||||
dcs ]
|
||||
|
||||
!Escape cancels DCS, starts Escape
|
||||
PUSH "\ePSomething\e9"
|
||||
escape "9"
|
||||
@ -198,6 +204,48 @@ PUSH "\ePBy\ne\x07"
|
||||
control 10
|
||||
dcs "e"]
|
||||
|
||||
!APC BEL
|
||||
PUSH "\e_Hello\x07"
|
||||
apc ["Hello"]
|
||||
|
||||
!APC ST (7bit)
|
||||
PUSH "\e_Hello\e\\"
|
||||
apc ["Hello"]
|
||||
|
||||
!APC ST (8bit)
|
||||
PUSH "\x{9f}Hello\x9c"
|
||||
apc ["Hello"]
|
||||
|
||||
!PM BEL
|
||||
PUSH "\e^Hello\x07"
|
||||
pm ["Hello"]
|
||||
|
||||
!PM ST (7bit)
|
||||
PUSH "\e^Hello\e\\"
|
||||
pm ["Hello"]
|
||||
|
||||
!PM ST (8bit)
|
||||
PUSH "\x{9e}Hello\x9c"
|
||||
pm ["Hello"]
|
||||
|
||||
!SOS BEL
|
||||
PUSH "\eXHello\x07"
|
||||
sos ["Hello"]
|
||||
|
||||
!SOS ST (7bit)
|
||||
PUSH "\eXHello\e\\"
|
||||
sos ["Hello"]
|
||||
|
||||
!SOS ST (8bit)
|
||||
PUSH "\x{98}Hello\x9c"
|
||||
sos ["Hello"]
|
||||
|
||||
!SOS can contain any C0 or C1 code
|
||||
PUSH "\eXABC\x01DEF\e\\"
|
||||
sos ["ABC\x01DEF"]
|
||||
PUSH "\eXABC\x99DEF\e\\"
|
||||
sos ["ABC\x{99}DEF"]
|
||||
|
||||
!NUL ignored
|
||||
PUSH "\x{00}"
|
||||
|
||||
|
||||
@ -170,3 +170,12 @@ PUSH "\e[?1006\$p"
|
||||
output "\e[?1006;2\$y"
|
||||
PUSH "\e[?1015\$p"
|
||||
output "\e[?1015;1\$y"
|
||||
|
||||
!Mouse disabled reports nothing
|
||||
RESET
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
MOUSEMOVE 0,0 0
|
||||
MOUSEBTN d 1 0
|
||||
MOUSEBTN u 1 0
|
||||
|
||||
@ -17,3 +17,15 @@ PUSH "\e]27;Something\e\\"
|
||||
!Unrecognised DCS
|
||||
PUSH "\ePz123\e\\"
|
||||
dcs ["z123"]
|
||||
|
||||
!Unrecognised APC
|
||||
PUSH "\e_z123\e\\"
|
||||
apc ["z123"]
|
||||
|
||||
!Unrecognised PM
|
||||
PUSH "\e^z123\e\\"
|
||||
pm ["z123"]
|
||||
|
||||
!Unrecognised SOS
|
||||
PUSH "\eXz123\e\\"
|
||||
sos ["z123"]
|
||||
|
||||
55
src/libvterm/t/40state_selection.test
Normal file
55
src/libvterm/t/40state_selection.test
Normal file
@ -0,0 +1,55 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE
|
||||
|
||||
!Set clipboard; final chunk len 4
|
||||
PUSH "\e]52;c;SGVsbG8s\e\\"
|
||||
selection-set mask=0001 ["Hello,"]
|
||||
|
||||
!Set clipboard; final chunk len 3
|
||||
PUSH "\e]52;c;SGVsbG8sIHc=\e\\"
|
||||
selection-set mask=0001 ["Hello, w"]
|
||||
|
||||
!Set clipboard; final chunk len 2
|
||||
PUSH "\e]52;c;SGVsbG8sIHdvcmxkCg==\e\\"
|
||||
selection-set mask=0001 ["Hello, world\n"]
|
||||
|
||||
!Set clipboard; split between chunks
|
||||
PUSH "\e]52;c;SGVs"
|
||||
selection-set mask=0001 ["Hel"
|
||||
PUSH "bG8s\e\\"
|
||||
selection-set mask=0001 "lo,"]
|
||||
|
||||
!Set clipboard; split within chunk
|
||||
PUSH "\e]52;c;SGVsbG"
|
||||
selection-set mask=0001 ["Hel"
|
||||
PUSH "8s\e\\"
|
||||
selection-set mask=0001 "lo,"]
|
||||
|
||||
!Query clipboard
|
||||
PUSH "\e]52;c;?\e\\"
|
||||
selection-query mask=0001
|
||||
|
||||
!Send clipboard; final chunk len 4
|
||||
SELECTION 1 ["Hello,"]
|
||||
output "\e]52;c;SGVsbG8s\e\\"
|
||||
|
||||
!Send clipboard; final chunk len 3
|
||||
SELECTION 1 ["Hello, w"]
|
||||
output "\e]52;c;SGVsbG8sIHc=\e\\"
|
||||
|
||||
!Send clipboard; final chunk len 2
|
||||
SELECTION 1 ["Hello, world\n"]
|
||||
output "\e]52;c;SGVsbG8sIHdvcmxkCg==\e\\"
|
||||
|
||||
!Send clipboard; split between chunks
|
||||
SELECTION 1 ["Hel"
|
||||
output "\e]52;c;SGVs"
|
||||
SELECTION 1 "lo,"]
|
||||
output "bG8s\e\\"
|
||||
|
||||
!Send clipboard; split within chunk
|
||||
SELECTION 1 ["Hello"
|
||||
output "\e]52;c;SGVs"
|
||||
SELECTION 1 ","]
|
||||
output "bG8s\e\\"
|
||||
@ -13,7 +13,8 @@ static size_t inplace_hex2bytes(char *s)
|
||||
|
||||
while(*inpos) {
|
||||
unsigned int ch;
|
||||
sscanf(inpos, "%2x", &ch);
|
||||
if(sscanf(inpos, "%2x", &ch) < 1)
|
||||
break;
|
||||
*outpos = ch;
|
||||
outpos += 1; inpos += 2;
|
||||
}
|
||||
@ -98,7 +99,7 @@ static void term_output(const char *s, size_t len, void *user UNUSED)
|
||||
static void printhex(const char *s, size_t len)
|
||||
{
|
||||
while(len--)
|
||||
printf("%02x", (s++)[0]);
|
||||
printf("%02x", (uint8_t)(s++)[0]);
|
||||
}
|
||||
|
||||
static int parser_text(const char bytes[], size_t len, void *user UNUSED)
|
||||
@ -216,6 +217,57 @@ static int parser_dcs(const char *command, size_t commandlen, VTermStringFragmen
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_apc(VTermStringFragment frag, void *user UNUSED)
|
||||
{
|
||||
printf("apc ");
|
||||
|
||||
if(frag.initial)
|
||||
printf("[");
|
||||
|
||||
printhex(frag.str, frag.len);
|
||||
|
||||
if(frag.final)
|
||||
printf("]");
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_pm(VTermStringFragment frag, void *user UNUSED)
|
||||
{
|
||||
printf("pm ");
|
||||
|
||||
if(frag.initial)
|
||||
printf("[");
|
||||
|
||||
printhex(frag.str, frag.len);
|
||||
|
||||
if(frag.final)
|
||||
printf("]");
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_sos(VTermStringFragment frag, void *user UNUSED)
|
||||
{
|
||||
printf("sos ");
|
||||
|
||||
if(frag.initial)
|
||||
printf("[");
|
||||
|
||||
printhex(frag.str, frag.len);
|
||||
|
||||
if(frag.final)
|
||||
printf("]");
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermParserCallbacks parser_cbs = {
|
||||
parser_text, // text
|
||||
parser_control, // control
|
||||
@ -223,6 +275,9 @@ static VTermParserCallbacks parser_cbs = {
|
||||
parser_csi, // csi
|
||||
parser_osc, // osc
|
||||
parser_dcs, // dcs
|
||||
parser_apc, // apc
|
||||
parser_pm, // pm
|
||||
parser_sos, // sos
|
||||
NULL // resize
|
||||
};
|
||||
|
||||
@ -230,7 +285,10 @@ static VTermStateFallbacks fallbacks = {
|
||||
parser_control, // control
|
||||
parser_csi, // csi
|
||||
parser_osc, // osc
|
||||
parser_dcs // dcs
|
||||
parser_dcs, // dcs
|
||||
parser_apc, // dcs
|
||||
parser_pm, // pm
|
||||
parser_sos // sos
|
||||
};
|
||||
|
||||
/* These callbacks are shared by State and Screen */
|
||||
@ -414,6 +472,31 @@ VTermStateCallbacks state_cbs = {
|
||||
state_setlineinfo, // setlineinfo
|
||||
};
|
||||
|
||||
static int selection_set(VTermSelectionMask mask, VTermStringFragment frag, void *user UNUSED)
|
||||
{
|
||||
printf("selection-set mask=%04X ", mask);
|
||||
if(frag.initial)
|
||||
printf("[");
|
||||
printhex(frag.str, frag.len);
|
||||
if(frag.final)
|
||||
printf("]");
|
||||
printf("\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int selection_query(VTermSelectionMask mask, void *user UNUSED)
|
||||
{
|
||||
printf("selection-query mask=%04X\n", mask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
VTermSelectionCallbacks selection_cbs = {
|
||||
.set = selection_set,
|
||||
.query = selection_query,
|
||||
};
|
||||
|
||||
static int want_screen_damage = 0;
|
||||
static int want_screen_damage_cells = 0;
|
||||
static int screen_damage(VTermRect rect, void *user UNUSED)
|
||||
@ -555,6 +638,7 @@ int main(int argc UNUSED, char **argv UNUSED)
|
||||
if(!state) {
|
||||
state = vterm_obtain_state(vt);
|
||||
vterm_state_set_callbacks(state, &state_cbs, NULL);
|
||||
vterm_state_set_selection_callbacks(state, &selection_cbs, NULL, NULL, 1024);
|
||||
vterm_state_set_bold_highbright(state, 1);
|
||||
vterm_state_reset(state, 1);
|
||||
}
|
||||
@ -768,6 +852,32 @@ int main(int argc UNUSED, char **argv UNUSED)
|
||||
vterm_mouse_button(vt, button, (press == 'd' || press == 'D'), mod);
|
||||
}
|
||||
|
||||
else if(strstartswith(line, "SELECTION ")) {
|
||||
char *linep = line + 10;
|
||||
unsigned int mask;
|
||||
int len;
|
||||
VTermStringFragment frag = { 0 };
|
||||
sscanf(linep, "%x%n", &mask, &len);
|
||||
linep += len;
|
||||
while(linep[0] == ' ')
|
||||
linep++;
|
||||
if(linep[0] == '[') {
|
||||
frag.initial = TRUE;
|
||||
linep++;
|
||||
while(linep[0] == ' ')
|
||||
linep++;
|
||||
}
|
||||
frag.len = inplace_hex2bytes(linep);
|
||||
frag.str = linep;
|
||||
linep += frag.len * 2;
|
||||
while(linep[0] == ' ')
|
||||
linep++;
|
||||
if(linep[0] == ']') {
|
||||
frag.final = TRUE;
|
||||
}
|
||||
vterm_state_send_selection(state, mask, frag);
|
||||
}
|
||||
|
||||
else if(strstartswith(line, "DAMAGEMERGE ")) {
|
||||
char *linep = line + 12;
|
||||
while(linep[0] == ' ')
|
||||
|
||||
@ -85,6 +85,11 @@ sub do_line
|
||||
my $string = eval($2);
|
||||
$line = "$1 " . unpack "H*", $string;
|
||||
}
|
||||
elsif( $line =~ m/^(SELECTION \d+) +(\[?)(.*?)(\]?)$/ ) {
|
||||
# we're evil
|
||||
my $string = eval($3);
|
||||
$line = "$1 $2 " . unpack( "H*", $string ) . " $4";
|
||||
}
|
||||
|
||||
do_onetest if defined $command;
|
||||
|
||||
@ -113,15 +118,18 @@ sub do_line
|
||||
|
||||
$line = "$cmd $initial" . join( "", map sprintf("%02x", $_), unpack "C*", length $data ? eval($data) : "" ) . "$final";
|
||||
}
|
||||
elsif( $line =~ m/^(escape|dcs) (\[?)(.*?)(\]?)$/ ) {
|
||||
$line = "$1 $2" . join( "", map sprintf("%02x", $_), unpack "C*", eval($3) ) . "$4";
|
||||
elsif( $line =~ m/^(escape|dcs|apc|pm|sos) (\[?)(.*?)(\]?)$/ ) {
|
||||
$line = "$1 $2" . join( "", map sprintf("%02x", $_), unpack "C*", length $3 ? eval($3) : "" ) . "$4";
|
||||
}
|
||||
elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) {
|
||||
$line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . " $2";
|
||||
}
|
||||
elsif( $line =~ m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|settermprop|setmousefunc) / ) {
|
||||
elsif( $line =~ m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|settermprop|setmousefunc|selection-query) / ) {
|
||||
# no conversion
|
||||
}
|
||||
elsif( $line =~ m/^(selection-set) (.*?) (\[?)(.*?)(\]?)$/ ) {
|
||||
$line = "$1 $2 $3" . join( "", map sprintf("%02x", $_), unpack "C*", eval($4) ) . "$5";
|
||||
}
|
||||
else {
|
||||
warn "Unrecognised test expectation '$line'\n";
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
prefix=@PREFIX@
|
||||
libdir=@LIBDIR@
|
||||
includedir=${prefix}/include
|
||||
includedir=@INCDIR@
|
||||
|
||||
Name: vterm
|
||||
Description: Abstract VT220/Xterm/ECMA-48 emulation library
|
||||
|
||||
@ -4526,7 +4526,10 @@ static VTermStateFallbacks state_fallbacks = {
|
||||
NULL, // control
|
||||
parse_csi, // csi
|
||||
parse_osc, // osc
|
||||
NULL // dcs
|
||||
NULL, // dcs
|
||||
NULL, // apc
|
||||
NULL, // pm
|
||||
NULL // sos
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -757,6 +757,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
3666,
|
||||
/**/
|
||||
3665,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user