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";


Reply via email to