Hello community, here is the log from the commit of package libvterm for openSUSE:Factory checked in at 2020-01-12 23:24:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libvterm (Old) and /work/SRC/openSUSE:Factory/.libvterm.new.6675 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libvterm" Sun Jan 12 23:24:03 2020 rev:7 rq:763368 version:0.1.3+bzr762 Changes: -------- --- /work/SRC/openSUSE:Factory/libvterm/libvterm.changes 2019-09-20 14:51:50.850898722 +0200 +++ /work/SRC/openSUSE:Factory/.libvterm.new.6675/libvterm.changes 2020-01-12 23:26:05.434853994 +0100 @@ -1,0 +2,16 @@ +Sat Jan 11 21:25:32 CET 2020 - Matej Cepl <[email protected]> + +- Update to 0.1.3+bzr762: + - Merge bugfixes up to v0.1.3 + - Partial bugfix for uncleared area after resize (thanks Jörg + Richter) + - Recognise SGR 8 for conceal (thanks Jörg Richter) + - Define a new dedicated 'state fallbacks' struct rather than + abusing the parser callbacks one + - New string-handling API that streams in possibly-multiple + fragments + - Remember to length-check accesses at cell->chars[] because it + is not necessarily zero-terminated (LP 1846869) + - fix memory leak of vt->tmpbuffer (LP 1843449) + +------------------------------------------------------------------- Old: ---- libvterm-0~bzr755.tar.gz New: ---- libvterm-0~bzr762.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libvterm.spec ++++++ --- /var/tmp/diff_new_pack.fbga7C/_old 2020-01-12 23:26:06.462854375 +0100 +++ /var/tmp/diff_new_pack.fbga7C/_new 2020-01-12 23:26:06.466854376 +0100 @@ -1,7 +1,7 @@ # # spec file for package libvterm # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,16 +17,16 @@ %define sover 0 -%define relno 755 +%define relno 762 Name: libvterm -Version: 0.1+bzr755 +Version: 0.1.3+bzr762 Release: 0 Summary: An abstract library implementation of a VT220/xterm/ECMA-48 terminal emulator License: MIT Group: Development/Libraries/C and C++ URL: https://launchpad.net/libvterm -# https://bazaar.launchpad.net/~libvterm/libvterm/trunk/tarball/%{relno} +# https://bazaar.launchpad.net/~libvterm/libvterm/trunk/tarball/%%{relno} Source: %{name}-0~bzr%{relno}.tar.gz BuildRequires: libtool BuildRequires: pkgconfig ++++++ libvterm-0~bzr755.tar.gz -> libvterm-0~bzr762.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/bin/unterm.c new/~libvterm/libvterm/trunk/bin/unterm.c --- old/~libvterm/libvterm/trunk/bin/unterm.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/bin/unterm.c 2020-01-11 21:23:33.000000000 +0100 @@ -96,6 +96,11 @@ if(prevcell->attrs.reverse && !cell->attrs.reverse) sgr[sgri++] = 27; + if(!prevcell->attrs.conceal && cell->attrs.conceal) + sgr[sgri++] = 8; + if(prevcell->attrs.conceal && !cell->attrs.conceal) + sgr[sgri++] = 28; + if(!prevcell->attrs.strike && cell->attrs.strike) sgr[sgri++] = 9; if(prevcell->attrs.strike && !cell->attrs.strike) @@ -143,7 +148,7 @@ case FORMAT_SGR: if(prevcell->attrs.bold || prevcell->attrs.underline || prevcell->attrs.italic || prevcell->attrs.blink || prevcell->attrs.reverse || prevcell->attrs.strike || - prevcell->attrs.font) + prevcell->attrs.conceal || prevcell->attrs.font) printf("\x1b[m"); break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/bin/vterm-dump.c new/~libvterm/libvterm/trunk/bin/vterm-dump.c --- old/~libvterm/libvterm/trunk/bin/vterm-dump.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/bin/vterm-dump.c 2020-01-11 21:23:33.000000000 +0100 @@ -154,16 +154,32 @@ return 1; } -static int parser_osc(const char *command, size_t cmdlen, void *user) +static int parser_osc(int command, VTermStringFragment frag, void *user) { - printf("%sOSC %.*s%s", special_begin, (int)cmdlen, command, special_end); + if(frag.initial) { + if(command == -1) + printf("%sOSC ", special_begin); + else + printf("%sOSC %d;", special_begin, command); + } + + printf("%.*s", (int)frag.len, frag.str); + + if(frag.final) + printf("%s", special_end); return 1; } -static int parser_dcs(const char *command, size_t cmdlen, void *user) +static int parser_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user) { - printf("%sDCS %.*s%s", special_begin, (int)cmdlen, command, special_end); + if(frag.initial) + printf("%sDCS %.*s", special_begin, (int)commandlen, command); + + printf("%.*s", (int)frag.len, frag.str); + + if(frag.final) + printf("%s", special_end); return 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/doc/seqs.txt new/~libvterm/libvterm/trunk/doc/seqs.txt --- old/~libvterm/libvterm/trunk/doc/seqs.txt 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/doc/seqs.txt 2020-01-11 21:23:33.000000000 +0100 @@ -170,6 +170,7 @@ 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 @@ -178,6 +179,7 @@ 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/include/vterm.h new/~libvterm/libvterm/trunk/include/vterm.h --- old/~libvterm/libvterm/trunk/include/vterm.h 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/include/vterm.h 2020-01-11 21:23:33.000000000 +0100 @@ -211,10 +211,17 @@ VTERM_N_VALUETYPES } VTermValueType; +typedef struct { + const char *str; + size_t len : 30; + bool initial : 1; + bool final : 1; +} VTermStringFragment; + typedef union { int boolean; int number; - char *string; + VTermStringFragment string; VTermColor color; } VTermValue; @@ -225,6 +232,7 @@ VTERM_ATTR_ITALIC, // bool: 3, 23 VTERM_ATTR_BLINK, // bool: 5, 25 VTERM_ATTR_REVERSE, // bool: 7, 27 + VTERM_ATTR_CONCEAL, // bool: 8, 28 VTERM_ATTR_STRIKE, // bool: 9, 29 VTERM_ATTR_FONT, // number: 10-19 VTERM_ATTR_FOREGROUND, // color: 30-39 90-97 @@ -360,8 +368,8 @@ int (*control)(unsigned char control, void *user); int (*escape)(const char *bytes, size_t len, void *user); int (*csi)(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user); - int (*osc)(const char *command, size_t cmdlen, void *user); - int (*dcs)(const char *command, size_t cmdlen, void *user); + int (*osc)(int command, VTermStringFragment frag, void *user); + int (*dcs)(const char *command, size_t commandlen, VTermStringFragment frag, void *user); int (*resize)(int rows, int cols, void *user); } VTermParserCallbacks; @@ -386,13 +394,19 @@ int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user); } VTermStateCallbacks; +typedef struct { + int (*control)(unsigned char control, void *user); + 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); +} VTermStateFallbacks; + VTermState *vterm_obtain_state(VTerm *vt); void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user); void *vterm_state_get_cbdata(VTermState *state); -// Only invokes control, csi, osc, dcs -void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermParserCallbacks *fallbacks, void *user); +void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermStateFallbacks *fallbacks, void *user); void *vterm_state_get_unrecognised_fbdata(VTermState *state); void vterm_state_reset(VTermState *state, int hard); @@ -430,6 +444,7 @@ unsigned int italic : 1; unsigned int blink : 1; unsigned int reverse : 1; + unsigned int conceal : 1; unsigned int strike : 1; unsigned int font : 4; /* 0 to 9 */ unsigned int dwl : 1; /* On a DECDWL or DECDHL line */ @@ -467,8 +482,7 @@ void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user); void *vterm_screen_get_cbdata(VTermScreen *screen); -// Only invokes control, csi, osc, dcs -void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermParserCallbacks *fallbacks, void *user); +void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user); void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen); void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen); @@ -501,8 +515,9 @@ VTERM_ATTR_FONT_MASK = 1 << 6, VTERM_ATTR_FOREGROUND_MASK = 1 << 7, VTERM_ATTR_BACKGROUND_MASK = 1 << 8, + VTERM_ATTR_CONCEAL_MASK = 1 << 9, - VTERM_ALL_ATTRS_MASK = (1 << 9) - 1 + VTERM_ALL_ATTRS_MASK = (1 << 10) - 1 } VTermAttrMask; int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/parser.c new/~libvterm/libvterm/trunk/src/parser.c --- old/~libvterm/libvterm/trunk/src/parser.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/parser.c 2020-01-11 21:23:33.000000000 +0100 @@ -23,10 +23,10 @@ { #ifdef DEBUG_PARSER printf("Parsed CSI args as:\n", arglen, args); - printf(" leader: %s\n", vt->parser.csi_leader); - for(int argi = 0; argi < vt->parser.csi_argi; argi++) { - printf(" %lu", CSI_ARG(vt->parser.csi_args[argi])); - if(!CSI_ARG_HAS_MORE(vt->parser.csi_args[argi])) + printf(" leader: %s\n", vt->parser.v.csi.leader); + for(int argi = 0; argi < vt->parser.v.csi.argi; argi++) { + printf(" %lu", CSI_ARG(vt->parser.v.csi.args[argi])); + if(!CSI_ARG_HAS_MORE(vt->parser.v.csi.args[argi])) printf("\n"); printf(" intermed: %s\n", vt->parser.intermed); } @@ -34,9 +34,9 @@ if(vt->parser.callbacks && vt->parser.callbacks->csi) if((*vt->parser.callbacks->csi)( - vt->parser.csi_leaderlen ? vt->parser.csi_leader : NULL, - vt->parser.csi_args, - vt->parser.csi_argi, + vt->parser.v.csi.leaderlen ? vt->parser.v.csi.leader : NULL, + vt->parser.v.csi.args, + vt->parser.v.csi.argi, vt->parser.intermedlen ? vt->parser.intermed : NULL, command, vt->parser.cbdata)) @@ -61,65 +61,36 @@ DEBUG_LOG("libvterm: Unhandled escape ESC 0x%02x\n", command); } -static void append_strbuffer(VTerm *vt, const char *str, size_t len) +static void string_fragment(VTerm *vt, const char *str, size_t len, bool final) { - if(len > vt->parser.strbuffer_len - vt->parser.strbuffer_cur) { - len = vt->parser.strbuffer_len - vt->parser.strbuffer_cur; - DEBUG_LOG("Truncating strbuffer preserve to %zd bytes\n", len); - } - - if(len > 0) { - strncpy(vt->parser.strbuffer + vt->parser.strbuffer_cur, str, len); - vt->parser.strbuffer_cur += len; - } -} - -static void start_string(VTerm *vt, VTermParserStringType type) -{ - vt->parser.stringtype = type; - - vt->parser.strbuffer_cur = 0; -} + VTermStringFragment frag = { + .str = str, + .len = len, + .initial = vt->parser.string_initial, + .final = final, + }; -static void more_string(VTerm *vt, const char *str, size_t len) -{ - append_strbuffer(vt, str, len); -} + switch(vt->parser.state) { + case OSC: + if(vt->parser.callbacks && vt->parser.callbacks->osc) + (*vt->parser.callbacks->osc)(vt->parser.v.osc.command, frag, vt->parser.cbdata); + break; -static void done_string(VTerm *vt, const char *str, size_t len) -{ - if(vt->parser.strbuffer_cur) { - if(str) - append_strbuffer(vt, str, len); + case DCS: + if(len && 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; - str = vt->parser.strbuffer; - len = vt->parser.strbuffer_cur; - } - else if(!str) { - DEBUG_LOG("parser.c: TODO: No strbuffer _and_ no final fragment???\n"); - len = 0; + case NORMAL: + case CSI_LEADER: + case CSI_ARGS: + case CSI_INTERMED: + case OSC_COMMAND: + case DCS_COMMAND: + break; } - switch(vt->parser.stringtype) { - case VTERM_PARSER_OSC: - if(vt->parser.callbacks && vt->parser.callbacks->osc) - if((*vt->parser.callbacks->osc)(str, len, vt->parser.cbdata)) - return; - - DEBUG_LOG("libvterm: Unhandled OSC %.*s\n", (int)len, str); - return; - - case VTERM_PARSER_DCS: - if(vt->parser.callbacks && vt->parser.callbacks->dcs) - if((*vt->parser.callbacks->dcs)(str, len, vt->parser.cbdata)) - return; - - DEBUG_LOG("libvterm: Unhandled DCS %.*s\n", (int)len, str); - return; - - case VTERM_N_PARSER_TYPES: - return; - } + vt->parser.string_initial = false; } size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) @@ -132,136 +103,113 @@ case CSI_LEADER: case CSI_ARGS: case CSI_INTERMED: - case ESC: + case OSC_COMMAND: + case DCS_COMMAND: string_start = NULL; break; - case STRING: - case ESC_IN_STRING: + case OSC: + case DCS: string_start = bytes; break; } -#define ENTER_STRING_STATE(st) do { vt->parser.state = STRING; string_start = bytes + pos + 1; } while(0) #define ENTER_STATE(st) do { vt->parser.state = st; string_start = NULL; } while(0) #define ENTER_NORMAL_STATE() ENTER_STATE(NORMAL) for( ; pos < len; pos++) { unsigned char c = bytes[pos]; + bool c1_allowed = !vt->mode.utf8; if(c == 0x00 || c == 0x7f) { // NUL, DEL - if(vt->parser.state >= STRING) { - more_string(vt, string_start, bytes + pos - string_start); + if(vt->parser.state >= OSC) { + string_fragment(vt, string_start, bytes + pos - string_start, false); string_start = bytes + pos + 1; } continue; } if(c == 0x18 || c == 0x1a) { // CAN, SUB + vt->parser.in_esc = false; ENTER_NORMAL_STATE(); continue; } else if(c == 0x1b) { // ESC vt->parser.intermedlen = 0; - if(vt->parser.state == STRING) - vt->parser.state = ESC_IN_STRING; - else - ENTER_STATE(ESC); + if(vt->parser.state < OSC) + vt->parser.state = NORMAL; + vt->parser.in_esc = true; continue; } else if(c == 0x07 && // BEL, can stand for ST in OSC or DCS state - vt->parser.state == STRING) { + vt->parser.state >= OSC) { // fallthrough } else if(c < 0x20) { // other C0 - if(vt->parser.state >= STRING) - more_string(vt, string_start, bytes + pos - string_start); + if(vt->parser.state >= OSC) + string_fragment(vt, string_start, bytes + pos - string_start, false); do_control(vt, c); - if(vt->parser.state >= STRING) + if(vt->parser.state >= OSC) string_start = bytes + pos + 1; continue; } // else fallthrough - switch(vt->parser.state) { - case ESC_IN_STRING: - if(c == 0x5c) { // ST - vt->parser.state = STRING; - done_string(vt, string_start, bytes + pos - string_start - 1); - ENTER_NORMAL_STATE(); - break; - } - vt->parser.state = ESC; - // else fallthrough + size_t string_len = bytes + pos - string_start; - case ESC: - switch(c) { - case 0x50: // DCS - start_string(vt, VTERM_PARSER_DCS); - ENTER_STRING_STATE(); - break; - case 0x5b: // CSI - vt->parser.csi_leaderlen = 0; - ENTER_STATE(CSI_LEADER); - break; - case 0x5d: // OSC - start_string(vt, VTERM_PARSER_OSC); - ENTER_STRING_STATE(); - break; - default: - if(is_intermed(c)) { - if(vt->parser.intermedlen < INTERMED_MAX-1) - vt->parser.intermed[vt->parser.intermedlen++] = c; - } - else if(!vt->parser.intermedlen && c >= 0x40 && c < 0x60) { - do_control(vt, c + 0x40); - ENTER_NORMAL_STATE(); - } - else if(c >= 0x30 && c < 0x7f) { - do_escape(vt, c); - ENTER_NORMAL_STATE(); - } - else { - DEBUG_LOG("TODO: Unhandled byte %02x in Escape\n", c); - } + if(vt->parser.in_esc) { + // Hoist an ESC letter into a C1 if we're not in a string mode + // Always accept ESC \ == ST even in string mode + if(!vt->parser.intermedlen && + c >= 0x40 && c < 0x60 && + ((vt->parser.state < OSC || c == 0x5c))) { + c += 0x40; + c1_allowed = true; + string_len -= 1; + vt->parser.in_esc = false; } - break; + else { + string_start = NULL; + vt->parser.state = NORMAL; + } + } + switch(vt->parser.state) { case CSI_LEADER: /* Extract leader bytes 0x3c to 0x3f */ if(c >= 0x3c && c <= 0x3f) { - if(vt->parser.csi_leaderlen < CSI_LEADER_MAX-1) - vt->parser.csi_leader[vt->parser.csi_leaderlen++] = c; + if(vt->parser.v.csi.leaderlen < CSI_LEADER_MAX-1) + vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen++] = c; break; } /* else fallthrough */ - vt->parser.csi_leader[vt->parser.csi_leaderlen] = 0; + vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen] = 0; - vt->parser.csi_argi = 0; - vt->parser.csi_args[0] = CSI_ARG_MISSING; + vt->parser.v.csi.argi = 0; + vt->parser.v.csi.args[0] = CSI_ARG_MISSING; vt->parser.state = CSI_ARGS; /* fallthrough */ case CSI_ARGS: /* Numerical value of argument */ if(c >= '0' && c <= '9') { - if(vt->parser.csi_args[vt->parser.csi_argi] == CSI_ARG_MISSING) - vt->parser.csi_args[vt->parser.csi_argi] = 0; - vt->parser.csi_args[vt->parser.csi_argi] *= 10; - vt->parser.csi_args[vt->parser.csi_argi] += c - '0'; + if(vt->parser.v.csi.args[vt->parser.v.csi.argi] == CSI_ARG_MISSING) + vt->parser.v.csi.args[vt->parser.v.csi.argi] = 0; + vt->parser.v.csi.args[vt->parser.v.csi.argi] *= 10; + vt->parser.v.csi.args[vt->parser.v.csi.argi] += c - '0'; break; } if(c == ':') { - vt->parser.csi_args[vt->parser.csi_argi] |= CSI_ARG_FLAG_MORE; + vt->parser.v.csi.args[vt->parser.v.csi.argi] |= CSI_ARG_FLAG_MORE; c = ';'; } if(c == ';') { - vt->parser.csi_argi++; - vt->parser.csi_args[vt->parser.csi_argi] = CSI_ARG_MISSING; + vt->parser.v.csi.argi++; + vt->parser.v.csi.args[vt->parser.v.csi.argi] = CSI_ARG_MISSING; break; } /* else fallthrough */ - vt->parser.csi_argi++; + vt->parser.v.csi.argi++; vt->parser.intermedlen = 0; vt->parser.state = CSI_INTERMED; case CSI_INTERMED: @@ -282,26 +230,77 @@ ENTER_NORMAL_STATE(); break; - case STRING: - if(c == 0x07 || (c == 0x9c && !vt->mode.utf8)) { - done_string(vt, string_start, bytes + pos - string_start); + case OSC_COMMAND: + /* Numerical value of command */ + if(c >= '0' && c <= '9') { + if(vt->parser.v.osc.command == -1) + vt->parser.v.osc.command = 0; + else + vt->parser.v.osc.command *= 10; + vt->parser.v.osc.command += c - '0'; + break; + } + if(c == ';') { + vt->parser.state = OSC; + string_start = bytes + pos + 1; + break; + } + + /* else fallthrough */ + string_start = bytes + pos; + vt->parser.state = OSC; + goto string_state; + + case DCS_COMMAND: + if(vt->parser.v.dcs.commandlen < CSI_LEADER_MAX) + vt->parser.v.dcs.command[vt->parser.v.dcs.commandlen++] = c; + + if(c >= 0x40 && c<= 0x7e) { + string_start = bytes + pos + 1; + vt->parser.state = DCS; + } + break; + +string_state: + case OSC: + case DCS: + if(c == 0x07 || (c1_allowed && c == 0x9c)) { + string_fragment(vt, string_start, string_len, true); ENTER_NORMAL_STATE(); } break; case NORMAL: - if(c >= 0x80 && c < 0xa0 && !vt->mode.utf8) { + if(vt->parser.in_esc) { + if(is_intermed(c)) { + if(vt->parser.intermedlen < INTERMED_MAX-1) + vt->parser.intermed[vt->parser.intermedlen++] = c; + } + else if(c >= 0x30 && c < 0x7f) { + do_escape(vt, c); + vt->parser.in_esc = 0; + ENTER_NORMAL_STATE(); + } + else { + DEBUG_LOG("TODO: Unhandled byte %02x in Escape\n", c); + } + break; + } + if(c1_allowed && c >= 0x80 && c < 0xa0) { switch(c) { case 0x90: // DCS - start_string(vt, VTERM_PARSER_DCS); - ENTER_STRING_STATE(); + vt->parser.string_initial = true; + vt->parser.v.dcs.commandlen = 0; + ENTER_STATE(DCS_COMMAND); break; case 0x9b: // CSI + vt->parser.v.csi.leaderlen = 0; ENTER_STATE(CSI_LEADER); break; case 0x9d: // OSC - start_string(vt, VTERM_PARSER_OSC); - ENTER_STRING_STATE(); + vt->parser.v.osc.command = -1; + vt->parser.string_initial = true; + ENTER_STATE(OSC_COMMAND); break; default: do_control(vt, c); @@ -325,6 +324,9 @@ } } + if(string_start) + string_fragment(vt, string_start, bytes + pos - string_start, false); + return len; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/pen.c new/~libvterm/libvterm/trunk/src/pen.c --- old/~libvterm/libvterm/trunk/src/pen.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/pen.c 2020-01-11 21:23:33.000000000 +0100 @@ -174,6 +174,7 @@ state->pen.italic = 0; setpenattr_bool(state, VTERM_ATTR_ITALIC, 0); state->pen.blink = 0; setpenattr_bool(state, VTERM_ATTR_BLINK, 0); state->pen.reverse = 0; setpenattr_bool(state, VTERM_ATTR_REVERSE, 0); + state->pen.conceal = 0; setpenattr_bool(state, VTERM_ATTR_CONCEAL, 0); state->pen.strike = 0; setpenattr_bool(state, VTERM_ATTR_STRIKE, 0); state->pen.font = 0; setpenattr_int( state, VTERM_ATTR_FONT, 0); @@ -194,6 +195,7 @@ setpenattr_bool(state, VTERM_ATTR_ITALIC, state->pen.italic); setpenattr_bool(state, VTERM_ATTR_BLINK, state->pen.blink); setpenattr_bool(state, VTERM_ATTR_REVERSE, state->pen.reverse); + setpenattr_bool(state, VTERM_ATTR_CONCEAL, state->pen.conceal); setpenattr_bool(state, VTERM_ATTR_STRIKE, state->pen.strike); setpenattr_int( state, VTERM_ATTR_FONT, state->pen.font); setpenattr_col( state, VTERM_ATTR_FOREGROUND, state->pen.fg); @@ -329,6 +331,11 @@ setpenattr_bool(state, VTERM_ATTR_REVERSE, 1); break; + case 8: // Conceal on + state->pen.conceal = 1; + setpenattr_bool(state, VTERM_ATTR_CONCEAL, 1); + break; + case 9: // Strikethrough on state->pen.strike = 1; setpenattr_bool(state, VTERM_ATTR_STRIKE, 1); @@ -370,6 +377,11 @@ setpenattr_bool(state, VTERM_ATTR_REVERSE, 0); break; + case 28: // Conceal off (Reveal) + state->pen.conceal = 0; + setpenattr_bool(state, VTERM_ATTR_CONCEAL, 0); + break; + case 29: // Strikethrough off state->pen.strike = 0; setpenattr_bool(state, VTERM_ATTR_STRIKE, 0); @@ -491,6 +503,9 @@ if(state->pen.reverse) args[argi++] = 7; + if(state->pen.conceal) + args[argi++] = 8; + if(state->pen.strike) args[argi++] = 9; @@ -530,6 +545,10 @@ val->boolean = state->pen.reverse; return 1; + case VTERM_ATTR_CONCEAL: + val->boolean = state->pen.conceal; + return 1; + case VTERM_ATTR_STRIKE: val->boolean = state->pen.strike; return 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/screen.c new/~libvterm/libvterm/trunk/src/screen.c --- old/~libvterm/libvterm/trunk/src/screen.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/screen.c 2020-01-11 21:23:33.000000000 +0100 @@ -20,6 +20,7 @@ unsigned int italic : 1; unsigned int blink : 1; unsigned int reverse : 1; + unsigned int conceal : 1; unsigned int strike : 1; unsigned int font : 4; /* 0 to 9 */ @@ -412,6 +413,9 @@ case VTERM_ATTR_REVERSE: screen->pen.reverse = val->boolean; return 1; + case VTERM_ATTR_CONCEAL: + screen->pen.conceal = val->boolean; + return 1; case VTERM_ATTR_STRIKE: screen->pen.strike = val->boolean; return 1; @@ -522,7 +526,7 @@ VTermScreenCell *src = &screen->sb_buffer[pos.col]; ScreenCell *dst = &new_buffer[pos.row * new_cols + pos.col]; - for(int i = 0; ; i++) { + for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) { dst->chars[i] = src->chars[i]; if(!src->chars[i]) break; @@ -533,6 +537,7 @@ dst->pen.italic = src->attrs.italic; dst->pen.blink = src->attrs.blink; dst->pen.reverse = src->attrs.reverse ^ screen->global_reverse; + dst->pen.conceal = src->attrs.conceal; dst->pen.strike = src->attrs.strike; dst->pen.font = src->attrs.font; @@ -542,6 +547,8 @@ if(src->width == 2 && pos.col < (new_cols-1)) (dst + 1)->chars[0] = (uint32_t) -1; } + for( ; pos.col < new_cols; pos.col++) + clearcell(screen, &new_buffer[pos.row * new_cols + pos.col]); new_row--; if(active) @@ -773,7 +780,7 @@ if(!intcell) return 0; - for(int i = 0; ; i++) { + for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) { cell->chars[i] = intcell->chars[i]; if(!intcell->chars[i]) break; @@ -784,6 +791,7 @@ cell->attrs.italic = intcell->pen.italic; cell->attrs.blink = intcell->pen.blink; cell->attrs.reverse = intcell->pen.reverse ^ screen->global_reverse; + cell->attrs.conceal = intcell->pen.conceal; cell->attrs.strike = intcell->pen.strike; cell->attrs.font = intcell->pen.font; @@ -846,7 +854,7 @@ return screen->cbdata; } -void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermParserCallbacks *fallbacks, void *user) +void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermStateFallbacks *fallbacks, void *user) { vterm_state_set_unrecognised_fallbacks(screen->state, fallbacks, user); } @@ -891,6 +899,8 @@ return 1; if((attrs & VTERM_ATTR_REVERSE_MASK) && (a->pen.reverse != b->pen.reverse)) return 1; + if((attrs & VTERM_ATTR_CONCEAL_MASK) && (a->pen.conceal != b->pen.conceal)) + return 1; if((attrs & VTERM_ATTR_STRIKE_MASK) && (a->pen.strike != b->pen.strike)) return 1; if((attrs & VTERM_ATTR_FONT_MASK) && (a->pen.font != b->pen.font)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/state.c new/~libvterm/libvterm/trunk/src/state.c --- old/~libvterm/libvterm/trunk/src/state.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/state.c 2020-01-11 21:23:33.000000000 +0100 @@ -547,13 +547,9 @@ return vterm_state_set_termprop(state, prop, &val); } -static int settermprop_string(VTermState *state, VTermProp prop, const char *str, size_t len) +static int settermprop_string(VTermState *state, VTermProp prop, VTermStringFragment frag) { - char strvalue[len+1]; - strncpy(strvalue, str, len); - strvalue[len] = 0; - - VTermValue val = { .string = strvalue }; + VTermValue val = { .string = frag }; return vterm_state_set_termprop(state, prop, &val); } @@ -1416,6 +1412,14 @@ state->scrollregion_bottom = -1; } + // Setting the scrolling region restores the cursor to the home position + state->pos.row = 0; + state->pos.col = 0; + if(state->mode.origin) { + state->pos.row += state->scrollregion_top; + state->pos.col += SCROLLREGION_LEFT(state); + } + break; case 0x73: // DECSLRM - DEC custom @@ -1437,6 +1441,14 @@ state->scrollregion_right = -1; } + // Setting the scrolling region restores the cursor to the home position + state->pos.row = 0; + state->pos.col = 0; + if(state->mode.origin) { + state->pos.row += state->scrollregion_top; + state->pos.col += SCROLLREGION_LEFT(state); + } + break; case INTERMED('\'', 0x7D): // DECIC @@ -1516,78 +1528,97 @@ return 1; } -static int on_osc(const char *command, size_t cmdlen, void *user) +static int on_osc(int command, VTermStringFragment frag, void *user) { VTermState *state = user; - if(cmdlen < 2) - return 0; + switch(command) { + case 0: + settermprop_string(state, VTERM_PROP_ICONNAME, frag); + settermprop_string(state, VTERM_PROP_TITLE, frag); + return 1; - if(strneq(command, "0;", 2)) { - settermprop_string(state, VTERM_PROP_ICONNAME, command + 2, cmdlen - 2); - settermprop_string(state, VTERM_PROP_TITLE, command + 2, cmdlen - 2); - return 1; - } - else if(strneq(command, "1;", 2)) { - settermprop_string(state, VTERM_PROP_ICONNAME, command + 2, cmdlen - 2); - return 1; - } - else if(strneq(command, "2;", 2)) { - settermprop_string(state, VTERM_PROP_TITLE, command + 2, cmdlen - 2); - return 1; - } - else if(state->fallbacks && state->fallbacks->osc) - if((*state->fallbacks->osc)(command, cmdlen, state->fbdata)) + case 1: + settermprop_string(state, VTERM_PROP_ICONNAME, frag); + return 1; + + case 2: + settermprop_string(state, VTERM_PROP_TITLE, frag); return 1; + default: + if(state->fallbacks && state->fallbacks->osc) + if((*state->fallbacks->osc)(command, frag, state->fbdata)) + return 1; + } + return 0; } -static void request_status_string(VTermState *state, const char *command, size_t cmdlen) +static void request_status_string(VTermState *state, VTermStringFragment frag) { VTerm *vt = state->vt; - if(cmdlen == 1) - switch(command[0]) { - case 'm': // Query SGR - { - long args[20]; - int argc = vterm_state_getpen(state, args, sizeof(args)/sizeof(args[0])); - size_t cur = 0; - - cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, - vt->mode.ctrl8bit ? "\x90" "1$r" : ESC_S "P" "1$r"); // DCS 1$r ... - if(cur >= vt->tmpbuffer_len) - return; - - for(int argi = 0; argi < argc; argi++) { - cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, - argi == argc - 1 ? "%ld" : - CSI_ARG_HAS_MORE(args[argi]) ? "%ld:" : - "%ld;", - CSI_ARG(args[argi])); - if(cur >= vt->tmpbuffer_len) - return; - } - - cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, - vt->mode.ctrl8bit ? "m" "\x9C" : "m" ESC_S "\\"); // ... m ST - if(cur >= vt->tmpbuffer_len) - return; + char *tmp = state->tmp.decrqss; - vterm_push_output_bytes(vt, vt->tmpbuffer, cur); - } - return; - case 'r': // Query DECSTBM - vterm_push_output_sprintf_dcs(vt, "1$r%d;%dr", state->scrollregion_top+1, SCROLLREGION_BOTTOM(state)); + if(frag.initial) + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + + int i = 0; + while(i < sizeof(state->tmp.decrqss)-1 && tmp[i]) + i++; + while(i < sizeof(state->tmp.decrqss)-1 && frag.len--) + tmp[i++] = (frag.str++)[0]; + tmp[i] = 0; + + if(!frag.final) + return; + + fprintf(stderr, "DECRQSS on <%s>\n", tmp); + + switch(tmp[0] | tmp[1]<<8 | tmp[2]<<16) { + case 'm': { + // Query SGR + long args[20]; + int argc = vterm_state_getpen(state, args, sizeof(args)/sizeof(args[0])); + size_t cur = 0; + + cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, + vt->mode.ctrl8bit ? "\x90" "1$r" : ESC_S "P" "1$r"); // DCS 1$r ... + if(cur >= vt->tmpbuffer_len) return; - case 's': // Query DECSLRM - vterm_push_output_sprintf_dcs(vt, "1$r%d;%ds", SCROLLREGION_LEFT(state)+1, SCROLLREGION_RIGHT(state)); + + for(int argi = 0; argi < argc; argi++) { + cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, + argi == argc - 1 ? "%ld" : + CSI_ARG_HAS_MORE(args[argi]) ? "%ld:" : + "%ld;", + CSI_ARG(args[argi])); + if(cur >= vt->tmpbuffer_len) + return; + } + + cur += snprintf(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur, + vt->mode.ctrl8bit ? "m" "\x9C" : "m" ESC_S "\\"); // ... m ST + if(cur >= vt->tmpbuffer_len) return; + + vterm_push_output_bytes(vt, vt->tmpbuffer, cur); + return; } - if(cmdlen == 2) { - if(strneq(command, " q", 2)) { + case 'r': + // Query DECSTBM + vterm_push_output_sprintf_dcs(vt, "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)); + return; + + case ' '|('q'<<8): { + // Query DECSCUSR int reply; switch(state->mode.cursor_shape) { case VTERM_PROP_CURSORSHAPE_BLOCK: reply = 2; break; @@ -1599,27 +1630,29 @@ vterm_push_output_sprintf_dcs(vt, "1$r%d q", reply); return; } - else if(strneq(command, "\"q", 2)) { + + case '\"'|('q'<<8): + // Query DECSCA vterm_push_output_sprintf_dcs(vt, "1$r%d\"q", state->protected_cell ? 1 : 2); return; - } } - vterm_push_output_sprintf_dcs(state->vt, "0$r%.s", (int)cmdlen, command); + vterm_push_output_sprintf_dcs(state->vt, "0$r%s", tmp); } -static int on_dcs(const char *command, size_t cmdlen, void *user) +static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user) { VTermState *state = user; - if(cmdlen >= 2 && strneq(command, "$q", 2)) { - request_status_string(state, command+2, cmdlen-2); + if(commandlen == 2 && strneq(command, "$q", 2)) { + request_status_string(state, frag); return 1; } else if(state->fallbacks && state->fallbacks->dcs) - if((*state->fallbacks->dcs)(command, cmdlen, state->fbdata)) + if((*state->fallbacks->dcs)(command, commandlen, frag, state->fbdata)) return 1; + DEBUG_LOG("libvterm: Unhandled DCS %.*s\n", (int)commandlen, command); return 0; } @@ -1824,7 +1857,7 @@ return state->cbdata; } -void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermParserCallbacks *fallbacks, void *user) +void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermStateFallbacks *fallbacks, void *user) { if(fallbacks) { state->fallbacks = fallbacks; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/vterm.c new/~libvterm/libvterm/trunk/src/vterm.c --- old/~libvterm/libvterm/trunk/src/vterm.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/vterm.c 2020-01-11 21:23:33.000000000 +0100 @@ -48,10 +48,6 @@ vt->parser.callbacks = NULL; vt->parser.cbdata = NULL; - vt->parser.strbuffer_len = 64; - vt->parser.strbuffer_cur = 0; - vt->parser.strbuffer = vterm_allocator_malloc(vt, vt->parser.strbuffer_len); - vt->outfunc = NULL; vt->outdata = NULL; @@ -73,8 +69,8 @@ if(vt->state) vterm_state_free(vt->state); - vterm_allocator_free(vt, vt->parser.strbuffer); vterm_allocator_free(vt, vt->outbuffer); + vterm_allocator_free(vt, vt->tmpbuffer); vterm_allocator_free(vt, vt); } @@ -244,6 +240,7 @@ case VTERM_ATTR_ITALIC: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_BLINK: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_REVERSE: return VTERM_VALUETYPE_BOOL; + case VTERM_ATTR_CONCEAL: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_STRIKE: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_FONT: return VTERM_VALUETYPE_INT; case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/src/vterm_internal.h new/~libvterm/libvterm/trunk/src/vterm_internal.h --- old/~libvterm/libvterm/trunk/src/vterm_internal.h 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/src/vterm_internal.h 2020-01-11 21:23:33.000000000 +0100 @@ -45,6 +45,7 @@ unsigned int italic:1; unsigned int blink:1; unsigned int reverse:1; + unsigned int conceal:1; unsigned int strike:1; unsigned int font:4; /* To store 0-9 */ }; @@ -56,7 +57,7 @@ const VTermStateCallbacks *callbacks; void *cbdata; - const VTermParserCallbacks *fallbacks; + const VTermStateFallbacks *fallbacks; void *fbdata; int rows; @@ -143,14 +144,12 @@ unsigned int cursor_shape:2; } mode; } saved; -}; - -typedef enum { - VTERM_PARSER_OSC, - VTERM_PARSER_DCS, - VTERM_N_PARSER_TYPES -} VTermParserStringType; + /* Temporary state for DECRQSS parsing */ + union { + char decrqss[4]; + } tmp; +}; struct VTerm { @@ -171,28 +170,39 @@ CSI_LEADER, CSI_ARGS, CSI_INTERMED, - ESC, + OSC_COMMAND, + DCS_COMMAND, /* below here are the "string states" */ - STRING, - ESC_IN_STRING, + OSC, + DCS, } state; + bool in_esc : 1; + int intermedlen; char intermed[INTERMED_MAX]; - int csi_leaderlen; - char csi_leader[CSI_LEADER_MAX]; - - int csi_argi; - long csi_args[CSI_ARGS_MAX]; + union { + struct { + int leaderlen; + char leader[CSI_LEADER_MAX]; + + int argi; + long args[CSI_ARGS_MAX]; + } csi; + struct { + int command; + } osc; + struct { + int commandlen; + char command[CSI_LEADER_MAX]; + } dcs; + } v; const VTermParserCallbacks *callbacks; void *cbdata; - VTermParserStringType stringtype; - char *strbuffer; - size_t strbuffer_len; - size_t strbuffer_cur; + bool string_initial; } parser; /* len == malloc()ed size; cur == number of valid bytes */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/02parser.test new/~libvterm/libvterm/trunk/t/02parser.test --- old/~libvterm/libvterm/trunk/t/02parser.test 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/02parser.test 2020-01-11 21:23:33.000000000 +0100 @@ -132,15 +132,23 @@ !OSC BEL PUSH "\e]1;Hello\x07" - osc "1;Hello" + osc [1 "Hello"] !OSC ST (7bit) PUSH "\e]1;Hello\e\\" - osc "1;Hello" + osc [1 "Hello"] !OSC ST (8bit) PUSH "\x{9d}1;Hello\x9c" - osc "1;Hello" + osc [1 "Hello"] + +!OSC in parts +PUSH "\e]52;abc" + osc [52 "abc" +PUSH "def" + osc "def" +PUSH "ghi\e\\" + osc "ghi"] !Escape cancels OSC, starts Escape PUSH "\e]Something\e9" @@ -152,20 +160,21 @@ !C0 in OSC interrupts and continues PUSH "\e]2;\nBye\x07" + osc [2 "" control 10 - osc "2;Bye" + osc "Bye"] !DCS BEL PUSH "\ePHello\x07" - dcs "Hello" + dcs ["Hello"] !DCS ST (7bit) PUSH "\ePHello\e\\" - dcs "Hello" + dcs ["Hello"] !DCS ST (8bit) PUSH "\x{90}Hello\x9c" - dcs "Hello" + dcs ["Hello"] !Escape cancels DCS, starts Escape PUSH "\ePSomething\e9" @@ -177,8 +186,9 @@ !C0 in OSC interrupts and continues PUSH "\ePBy\ne\x07" + dcs ["By" control 10 - dcs "Bye" + dcs "e"] !NUL ignored PUSH "\x{00}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/12state_scroll.test new/~libvterm/libvterm/trunk/t/12state_scroll.test --- old/~libvterm/libvterm/trunk/t/12state_scroll.test 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/12state_scroll.test 2020-01-11 21:23:33.000000000 +0100 @@ -40,8 +40,8 @@ ?cursor = 20,0 !Index in DECSTBM -PUSH "\e[10H" PUSH "\e[9;10r" +PUSH "\e[10H" PUSH "\eM" ?cursor = 8,0 PUSH "\eM" @@ -148,3 +148,9 @@ moverect 0..23,0..80 -> 2..25,0..80 erase 0..2,0..80 ?cursor = 0,0 + +!DECSTBM resets cursor position +PUSH "\e[5;5H" + ?cursor = 4,4 +PUSH "\e[r" + ?cursor = 0,0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/18state_termprops.test new/~libvterm/libvterm/trunk/t/18state_termprops.test --- old/~libvterm/libvterm/trunk/t/18state_termprops.test 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/18state_termprops.test 2020-01-11 21:23:33.000000000 +0100 @@ -33,4 +33,10 @@ !Title PUSH "\e]2;Here is my title\a" - settermprop 4 "Here is my title" + settermprop 4 ["Here is my title"] + +!Title split write +PUSH "\e]2;Here is" + settermprop 4 ["Here is" +PUSH " another title\a" + settermprop 4 " another title"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/29state_fallback.test new/~libvterm/libvterm/trunk/t/29state_fallback.test --- old/~libvterm/libvterm/trunk/t/29state_fallback.test 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/29state_fallback.test 2020-01-11 21:23:33.000000000 +0100 @@ -12,8 +12,8 @@ !Unrecognised OSC PUSH "\e]27;Something\e\\" - osc "27;Something" + osc [27 "Something"] !Unrecognised DCS PUSH "\ePz123\e\\" - dcs "z123" + dcs ["z123"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/68screen_termprops.test new/~libvterm/libvterm/trunk/t/68screen_termprops.test --- old/~libvterm/libvterm/trunk/t/68screen_termprops.test 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/68screen_termprops.test 2020-01-11 21:23:33.000000000 +0100 @@ -14,4 +14,4 @@ !Title PUSH "\e]2;Here is my title\a" - settermprop 4 "Here is my title" + settermprop 4 ["Here is my title"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/harness.c new/~libvterm/libvterm/trunk/t/harness.c --- old/~libvterm/libvterm/trunk/t/harness.c 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/harness.c 2020-01-11 21:23:33.000000000 +0100 @@ -92,6 +92,12 @@ printf("%x%s", (unsigned char)s[i], i < len-1 ? "," : "\n"); } +static void printhex(const char *s, size_t len) +{ + while(len--) + printf("%02x", (s++)[0]); +} + static int parser_text(const char bytes[], size_t len, void *user) { printf("text "); @@ -126,8 +132,7 @@ } printf("escape "); - for(int i = 0; i < len; i++) - printf("%02x", bytes[i]); + printhex(bytes, len); printf("\n"); return len; @@ -163,21 +168,42 @@ return 1; } -static int parser_osc(const char *command, size_t cmdlen, void *user) +static int parser_osc(int command, VTermStringFragment frag, void *user) { printf("osc "); - for(int i = 0; i < cmdlen; i++) - printf("%02x", command[i]); + + if(frag.initial) { + if(command == -1) + printf("["); + else + printf("[%d;", command); + } + + printhex(frag.str, frag.len); + + if(frag.final) + printf("]"); + printf("\n"); return 1; } -static int parser_dcs(const char *command, size_t cmdlen, void *user) +static int parser_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user) { printf("dcs "); - for(int i = 0; i < cmdlen; i++) - printf("%02x", command[i]); + + if(frag.initial) { + printf("["); + for(int i = 0; i < commandlen; i++) + printf("%02x", command[i]); + } + + printhex(frag.str, frag.len); + + if(frag.final) + printf("]"); + printf("\n"); return 1; @@ -192,6 +218,13 @@ .dcs = parser_dcs, }; +static VTermStateFallbacks fallbacks = { + .control = parser_control, + .csi = parser_csi, + .osc = parser_osc, + .dcs = parser_dcs, +}; + /* These callbacks are shared by State and Screen */ static int want_movecursor = 0; @@ -247,7 +280,8 @@ printf("settermprop %d %d\n", prop, val->number); return 1; case VTERM_VALUETYPE_STRING: - printf("settermprop %d \"%s\"\n", prop, val->string); + printf("settermprop %d %s\"%.*s\"%s\n", prop, + val->string.initial ? "[" : "", val->string.len, val->string.str, val->string.final ? "]" : ""); return 1; case VTERM_VALUETYPE_COLOR: printf("settermprop %d ", prop); @@ -271,7 +305,7 @@ return 1; printf("putglyph "); - for(int i = 0; info->chars[i]; i++) + for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL && info->chars[i]; i++) printf(i ? ",%x" : "%x", info->chars[i]); printf(" %d %d,%d", info->width, pos.row, pos.col); if(info->protected_cell) @@ -304,6 +338,7 @@ int italic; int blink; int reverse; + int conceal; int strike; int font; VTermColor foreground; @@ -327,6 +362,9 @@ case VTERM_ATTR_REVERSE: state_pen.reverse = val->boolean; break; + case VTERM_ATTR_CONCEAL: + state_pen.conceal = val->boolean; + break; case VTERM_ATTR_STRIKE: state_pen.strike = val->boolean; break; @@ -517,7 +555,7 @@ want_settermprop = sense; break; case 'f': - vterm_state_set_unrecognised_fallbacks(state, sense ? &parser_cbs : NULL, NULL); + vterm_state_set_unrecognised_fallbacks(state, sense ? &fallbacks : NULL, NULL); break; default: fprintf(stderr, "Unrecognised WANTSTATE flag '%c'\n", line[i]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/~libvterm/libvterm/trunk/t/run-test.pl new/~libvterm/libvterm/trunk/t/run-test.pl --- old/~libvterm/libvterm/trunk/t/run-test.pl 2019-09-11 23:36:58.000000000 +0200 +++ new/~libvterm/libvterm/trunk/t/run-test.pl 2020-01-11 21:23:33.000000000 +0100 @@ -107,8 +107,15 @@ elsif( $line =~ m/^csi (\S+) (.*)$/ ) { $line = sprintf "csi %02x %s", eval($1), $2; # TODO } - elsif( $line =~ m/^(escape|osc|dcs) (.*)$/ ) { - $line = "$1 " . join "", map sprintf("%02x", $_), unpack "C*", eval($2); + elsif( $line =~ m/^(osc) (\[\d+)? *(.*?)(\]?)$/ ) { + my ( $cmd, $initial, $data, $final ) = ( $1, $2, $3, $4 ); + $initial //= ""; + $initial .= ";" if $initial =~ m/\d+/; + + $line = "$cmd $initial" . join( "", map sprintf("%02x", $_), unpack "C*", eval($data) ) . "$final"; + } + elsif( $line =~ m/^(escape|dcs) (\[?)(.*?)(\]?)$/ ) { + $line = "$1 $2" . join( "", map sprintf("%02x", $_), unpack "C*", eval($3) ) . "$4"; } elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) { $line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . " $2";
