Patch 8.2.0798
Problem:    Libvterm code lags behind the upstream version.
Solution:   Include revisions 755 - 758.
Files:      src/libvterm/t/run-test.pl, src/libvterm/src/screen.c,
            src/libvterm/t/harness.c, src/libvterm/include/vterm.h,
            src/libvterm/src/parser.c, src/libvterm/src/state.c,
            src/libvterm/src/vterm.c, src/libvterm/src/vterm_internal.h,
            src/libvterm/t/02parser.test,
            src/libvterm/t/18state_termprops.test,
            src/libvterm/t/29state_fallback.test,
            src/libvterm/t/68screen_termprops.test, src/terminal.c


*** ../vim-8.2.0797/src/libvterm/t/run-test.pl  2020-05-18 21:50:32.932742338 
+0200
--- src/libvterm/t/run-test.pl  2020-05-19 19:15:23.211486825 +0200
***************
*** 11,17 ****
  my $EXECUTABLE = "t/.libs/harness";
  GetOptions(
     'valgrind|v+' => \$VALGRIND,
!    'executable|e=s' => \$EXECUTABLE
  ) or exit 1;
  
  my ( $hin, $hout, $hpid );
--- 11,18 ----
  my $EXECUTABLE = "t/.libs/harness";
  GetOptions(
     'valgrind|v+' => \$VALGRIND,
!    'executable|e=s' => \$EXECUTABLE,
!    'fail-early|F' => \(my $FAIL_EARLY),
  ) or exit 1;
  
  my ( $hin, $hout, $hpid );
***************
*** 65,70 ****
--- 66,72 ----
     }
  
     $exitcode = 1 if $fail_printed;
+    exit $exitcode if $exitcode and $FAIL_EARLY;
  }
  
  sub do_line
***************
*** 105,112 ****
        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/^putglyph (\S+) (.*)$/ ) {
           $line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . 
" $2";
--- 107,121 ----
        elsif( $line =~ m/^csi (\S+) (.*)$/ ) {
           $line = sprintf "csi %02x %s", eval($1), $2; # TODO
        }
!       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";
***************
*** 139,144 ****
--- 148,154 ----
                 "# Expected: $want\n" .
                 "# Actual:   $response\n";
           $exitcode = 1;
+          exit $exitcode if $exitcode and $FAIL_EARLY;
        }
     }
     # Assertions start with '?'
***************
*** 162,167 ****
--- 172,178 ----
                 "# Expected: $expectation\n" .
                 "# Actual:   $response\n";
           $exitcode = 1;
+          exit $exitcode if $exitcode and $FAIL_EARLY;
        }
     }
     # Test controls start with '$'
*** ../vim-8.2.0797/src/libvterm/src/screen.c   2020-05-18 21:50:32.932742338 
+0200
--- src/libvterm/src/screen.c   2020-05-19 19:10:17.072705379 +0200
***************
*** 533,539 ****
          ScreenCell *dst = &new_buffer[pos.row * new_cols + pos.col];
        int i;
  
!         for(i = 0; ; i++) {
            dst->chars[i] = src->chars[i];
            if(!src->chars[i])
              break;
--- 533,539 ----
          ScreenCell *dst = &new_buffer[pos.row * new_cols + pos.col];
        int i;
  
!         for(i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
            dst->chars[i] = src->chars[i];
            if(!src->chars[i])
              break;
***************
*** 804,810 ****
    if(!intcell)
      return 0;
  
!   for(i = 0; ; i++) {
      cell->chars[i] = intcell->chars[i];
      if(!intcell->chars[i])
        break;
--- 804,810 ----
    if(!intcell)
      return 0;
  
!   for(i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
      cell->chars[i] = intcell->chars[i];
      if(!intcell->chars[i])
        break;
*** ../vim-8.2.0797/src/libvterm/t/harness.c    2020-05-18 21:50:32.932742338 
+0200
--- src/libvterm/t/harness.c    2020-05-19 21:14:58.824143429 +0200
***************
*** 153,173 ****
    return 1;
  }
  
! static int parser_osc(const char *command, size_t cmdlen, void *user UNUSED)
  {
  
    printf("osc ");
!   printhex(command, cmdlen);
    printf("\n");
  
    return 1;
  }
  
! static int parser_dcs(const char *command, size_t cmdlen, void *user UNUSED)
  {
- 
    printf("dcs ");
!   printhex(command, cmdlen);
    printf("\n");
  
    return 1;
--- 153,196 ----
    return 1;
  }
  
! static int parser_osc(int command, VTermStringFragment frag, void *user 
UNUSED)
  {
  
    printf("osc ");
! 
!   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 commandlen, 
VTermStringFragment frag, void *user UNUSED)
  {
    printf("dcs ");
! 
!   if(frag.initial) {
!     size_t i;
!     printf("[");
!     for(i = 0; i < commandlen; i++)
!       printf("%02x", command[i]);
!   }
! 
!   printhex(frag.str, frag.len);
! 
!   if(frag.final)
!     printf("]");
! 
    printf("\n");
  
    return 1;
***************
*** 239,245 ****
      printf("settermprop %d %d\n", prop, val->number);
      return 1;
    case VTERM_VALUETYPE_STRING:
!     printf("settermprop %d \"%s\"\n", prop, val->string);
      return 1;
    case VTERM_VALUETYPE_COLOR:
      printf("settermprop %d rgb(%d,%d,%d)\n", prop, val->color.red, 
val->color.green, val->color.blue);
--- 262,269 ----
      printf("settermprop %d %d\n", prop, val->number);
      return 1;
    case VTERM_VALUETYPE_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 rgb(%d,%d,%d)\n", prop, val->color.red, 
val->color.green, val->color.blue);
***************
*** 262,268 ****
      return 1;
  
    printf("putglyph ");
!   for(i = 0; 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)
--- 286,292 ----
      return 1;
  
    printf("putglyph ");
!   for(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)
*** ../vim-8.2.0797/src/libvterm/include/vterm.h        2020-05-18 
21:50:32.932742338 +0200
--- src/libvterm/include/vterm.h        2020-05-19 19:17:11.043085163 +0200
***************
*** 107,116 ****
    VTERM_N_VALUETYPES
  } VTermValueType;
  
  typedef union {
    int boolean;
    int number;
!   char *string;
    VTermColor color;
  } VTermValue;
  
--- 107,123 ----
    VTERM_N_VALUETYPES
  } VTermValueType;
  
+ typedef struct {
+   const char *str;
+   size_t      len : 30;
+   unsigned int  initial : 1;
+   unsigned int  final : 1;
+ } VTermStringFragment;
+ 
  typedef union {
    int boolean;
    int number;
!   VTermStringFragment string;
    VTermColor color;
  } VTermValue;
  
***************
*** 257,264 ****
    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 (*resize)(int rows, int cols, void *user);
  } VTermParserCallbacks;
  
--- 264,271 ----
    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)(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;
  
*** ../vim-8.2.0797/src/libvterm/src/parser.c   2020-01-08 22:06:11.057866613 
+0100
--- src/libvterm/src/parser.c   2020-05-19 21:09:25.825081936 +0200
***************
*** 23,32 ****
  {
  #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("\n");
    printf(" intermed: %s\n", vt->parser.intermed);
    }
--- 23,32 ----
  {
  #ifdef DEBUG_PARSER
    printf("Parsed CSI args as:\n", arglen, args);
!   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,42 ****
  
    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.intermedlen ? vt->parser.intermed : NULL,
            command,
            vt->parser.cbdata))
--- 34,42 ----
  
    if(vt->parser.callbacks && vt->parser.callbacks->csi)
      if((*vt->parser.callbacks->csi)(
!           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,125 ****
    DEBUG_LOG1("libvterm: Unhandled escape ESC 0x%02x\n", command);
  }
  
! static void append_strbuffer(VTerm *vt, const char *str, size_t len)
  {
!   if(len > vt->parser.strbuffer_len - vt->parser.strbuffer_cur) {
!     len = vt->parser.strbuffer_len - vt->parser.strbuffer_cur;
!     DEBUG_LOG1("Truncating strbuffer preserve to %zu 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;
! }
  
! static void more_string(VTerm *vt, const char *str, size_t len)
! {
!   append_strbuffer(vt, str, len);
! }
  
! static void done_string(VTerm *vt, const char *str, size_t len)
! {
!   if(vt->parser.strbuffer_cur) {
!     if(str)
!       append_strbuffer(vt, str, len);
  
!     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;
    }
  
!   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_LOG2("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_LOG2("libvterm: Unhandled DCS %.*s\n", (int)len, str);
!     return;
! 
!   case VTERM_N_PARSER_TYPES:
!     return;
!   }
  }
  
  size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
--- 61,96 ----
    DEBUG_LOG1("libvterm: Unhandled escape ESC 0x%02x\n", command);
  }
  
! static void string_fragment(VTerm *vt, const char *str, size_t len, int final)
  {
!   VTermStringFragment frag;
  
!   frag.str = str;
!   frag.len = len;
!   frag.initial = vt->parser.string_initial;
!   frag.final = final;
  
!   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;
  
!     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;
  
!     case NORMAL:
!     case CSI_LEADER:
!     case CSI_ARGS:
!     case CSI_INTERMED:
!     case OSC_COMMAND:
!     case DCS_COMMAND:
!       break;
    }
  
!   vt->parser.string_initial = FALSE;
  }
  
  size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
***************
*** 135,177 ****
    case CSI_LEADER:
    case CSI_ARGS:
    case CSI_INTERMED:
!   case ESC:
      string_start = NULL;
      break;
!   case STRING:
!   case ESC_IN_STRING:
      string_start = bytes;
      break;
    }
  
- #define ENTER_STRING_STATE()   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];
  
      if(c == 0x00 || c == 0x7f) { // NUL, DEL
!       if(vt->parser.state >= STRING) {
!         more_string(vt, string_start, bytes + pos - string_start);
          string_start = bytes + pos + 1;
        }
        continue;
      }
      if(c == 0x18 || c == 0x1a) { // CAN, SUB
        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);
        continue;
      }
      else if(c == 0x07 &&  // BEL, can stand for ST in OSC or DCS state
!             vt->parser.state == STRING) {
        // fallthrough
      }
      else if(c < 0x20) { // other C0
--- 106,150 ----
    case CSI_LEADER:
    case CSI_ARGS:
    case CSI_INTERMED:
!   case OSC_COMMAND:
!   case DCS_COMMAND:
      string_start = NULL;
      break;
!   case OSC:
!   case DCS:
      string_start = bytes;
      break;
    }
  
  #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];
+     int c1_allowed = !vt->mode.utf8;
+     size_t string_len;
  
      if(c == 0x00 || c == 0x7f) { // NUL, DEL
!       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 < 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 >= OSC) {
        // fallthrough
      }
      else if(c < 0x20) { // other C0
***************
*** 182,277 ****
            if(pos + 2 < len && bytes[pos + 1] == 0x20 && bytes[pos + 2] == 
0x08)
              vt->in_backspace = 2; // Trigger when count down to 1
        }
!       if(vt->parser.state >= STRING)
!         more_string(vt, string_start, bytes + pos - string_start);
        do_control(vt, c);
!       if(vt->parser.state >= STRING)
          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
  
!     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_LOG1("TODO: Unhandled byte %02x in Escape\n", c);
!         }
        }
!       break;
  
      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;
          break;
        }
  
        // else fallthrough
!       vt->parser.csi_leader[vt->parser.csi_leaderlen] = 0;
  
!       vt->parser.csi_argi = 0;
!       vt->parser.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';
          break;
        }
        if(c == ':') {
!         vt->parser.csi_args[vt->parser.csi_argi] |= CSI_ARG_FLAG_MORE;
          c = ';';
        }
        if(c == ';') {
!         vt->parser.csi_argi++;
!         vt->parser.csi_args[vt->parser.csi_argi] = CSI_ARG_MISSING;
          break;
        }
  
        // else fallthrough
!       vt->parser.csi_argi++;
        vt->parser.intermedlen = 0;
        vt->parser.state = CSI_INTERMED;
        // fallthrough
--- 155,226 ----
            if(pos + 2 < len && bytes[pos + 1] == 0x20 && bytes[pos + 2] == 
0x08)
              vt->in_backspace = 2; // Trigger when count down to 1
        }
!       if(vt->parser.state >= OSC)
!         string_fragment(vt, string_start, bytes + pos - string_start, FALSE);
        do_control(vt, c);
!       if(vt->parser.state >= OSC)
          string_start = bytes + pos + 1;
        continue;
      }
      // else fallthrough
  
!     string_len = bytes + pos - string_start;
  
!     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;
        }
!       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.v.csi.leaderlen < CSI_LEADER_MAX-1)
!           vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen++] = c;
          break;
        }
  
        // else fallthrough
!       vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen] = 0;
  
!       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.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.v.csi.args[vt->parser.v.csi.argi] |= CSI_ARG_FLAG_MORE;
          c = ';';
        }
        if(c == ';') {
!         vt->parser.v.csi.argi++;
!         vt->parser.v.csi.args[vt->parser.v.csi.argi] = CSI_ARG_MISSING;
          break;
        }
  
        // else fallthrough
!       vt->parser.v.csi.argi++;
        vt->parser.intermedlen = 0;
        vt->parser.state = CSI_INTERMED;
        // fallthrough
***************
*** 293,323 ****
        ENTER_NORMAL_STATE();
        break;
  
!     case STRING:
!       if(c == 0x07 || (c == 0x9c && !vt->mode.utf8)) {
!         done_string(vt, string_start, bytes + pos - string_start);
!         ENTER_NORMAL_STATE();
        }
!       else if (pos + 1 == len) {
!       // end of input but OSC string isn't finished yet, copy it to
!       // vt->parser.strbuffer to continue it later
!         more_string(vt, string_start, bytes + pos + 1 - string_start);
        }
        break;
  
      case NORMAL:
!       if(c >= 0x80 && c < 0xa0 && !vt->mode.utf8) {
          switch(c) {
          case 0x90: // DCS
!           start_string(vt, VTERM_PARSER_DCS);
!           ENTER_STRING_STATE();
            break;
          case 0x9b: // CSI
            ENTER_STATE(CSI_LEADER);
            break;
          case 0x9d: // OSC
!           start_string(vt, VTERM_PARSER_OSC);
!           ENTER_STRING_STATE();
            break;
          default:
            do_control(vt, c);
--- 242,318 ----
        ENTER_NORMAL_STATE();
        break;
  
!     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(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_LOG1("TODO: Unhandled byte %02x in Escape\n", c);
!         }
!         break;
!       }
!       if(c1_allowed && c >= 0x80 && c < 0xa0) {
          switch(c) {
          case 0x90: // DCS
!           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
!           vt->parser.v.osc.command = -1;
!           vt->parser.string_initial = TRUE;
!           ENTER_STATE(OSC_COMMAND);
            break;
          default:
            do_control(vt, c);
***************
*** 341,346 ****
--- 336,344 ----
      }
    }
  
+   if(string_start)
+     string_fragment(vt, string_start, bytes + pos - string_start, FALSE);
+ 
    return len;
  }
  
*** ../vim-8.2.0797/src/libvterm/src/state.c    2020-05-19 10:32:59.291518426 
+0200
--- src/libvterm/src/state.c    2020-05-19 21:12:12.744611031 +0200
***************
*** 582,600 ****
    return vterm_state_set_termprop(state, prop, &val);
  }
  
! static int settermprop_string(VTermState *state, VTermProp prop, const char 
*str, size_t len)
  {
-   char *strvalue;
-   int r;
    VTermValue val;
!   strvalue = vterm_allocator_malloc(state->vt, (len+1) * sizeof(char));
!   strncpy(strvalue, str, len);
!   strvalue[len] = 0;
! 
!   val.string = strvalue;
!   r = vterm_state_set_termprop(state, prop, &val);
!   vterm_allocator_free(state->vt, strvalue);
!   return r;
  }
  
  static void savecursor(VTermState *state, int save)
--- 582,593 ----
    return vterm_state_set_termprop(state, prop, &val);
  }
  
! static int settermprop_string(VTermState *state, VTermProp prop, 
VTermStringFragment frag)
  {
    VTermValue val;
! 
!   val.string = frag;
!   return vterm_state_set_termprop(state, prop, &val);
  }
  
  static void savecursor(VTermState *state, int save)
***************
*** 1602,1701 ****
    return 1;
  }
  
! static int on_osc(const char *command, size_t cmdlen, void *user)
  {
    VTermState *state = user;
  
!   if(cmdlen < 2)
!     return 0;
  
!   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(strneq(command, "10;", 3)) {
!     // request foreground color: <Esc>]10;?<0x07>
!     int red = state->default_fg.red;
!     int blue = state->default_fg.blue;
!     int green = state->default_fg.green;
!     vterm_push_output_sprintf_ctrl(state->vt, C1_OSC, 
"10;rgb:%02x%02x/%02x%02x/%02x%02x\x07", red, red, green, green, blue, blue);
!     return 1;
!   }
!   else if(strneq(command, "11;", 3)) {
!     // request background color: <Esc>]11;?<0x07>
!     int red = state->default_bg.red;
!     int blue = state->default_bg.blue;
!     int green = state->default_bg.green;
!     vterm_push_output_sprintf_ctrl(state->vt, C1_OSC, 
"11;rgb:%02x%02x/%02x%02x/%02x%02x\x07", red, red, green, green, blue, blue);
!     return 1;
!   }
!   else if(strneq(command, "12;", 3)) {
!     settermprop_string(state, VTERM_PROP_CURSORCOLOR, command + 3, cmdlen - 
3);
!     return 1;
!   }
!   else if(state->fallbacks && state->fallbacks->osc)
!     if((*state->fallbacks->osc)(command, cmdlen, state->fbdata))
        return 1;
  
    return 0;
  }
  
! static void request_status_string(VTermState *state, const char *command, 
size_t cmdlen)
  {
    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]));
!         int argi;
!           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(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;
!       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;
      }
  
!   if(cmdlen == 2) {
!     if(strneq(command, " q", 2)) {
        int reply;
        switch(state->mode.cursor_shape) {
          case VTERM_PROP_CURSORSHAPE_BLOCK:     reply = 2; break;
--- 1595,1715 ----
    return 1;
  }
  
! static int on_osc(int command, VTermStringFragment frag, void *user)
  {
    VTermState *state = user;
  
!   switch(command) {
!     case 0:
!       settermprop_string(state, VTERM_PROP_ICONNAME, frag);
!       settermprop_string(state, VTERM_PROP_TITLE, frag);
!       return 1;
  
!     case 1:
!       settermprop_string(state, VTERM_PROP_ICONNAME, frag);
        return 1;
  
+     case 2:
+       settermprop_string(state, VTERM_PROP_TITLE, frag);
+       return 1;
+ 
+     case 10:
+       {
+         // request foreground color: <Esc>]10;?<0x07>
+         int red = state->default_fg.red;
+         int blue = state->default_fg.blue;
+         int green = state->default_fg.green;
+         vterm_push_output_sprintf_ctrl(state->vt, C1_OSC, 
"10;rgb:%02x%02x/%02x%02x/%02x%02x\x07", red, red, green, green, blue, blue);
+         return 1;
+       }
+ 
+     case 11:
+       {
+       // request background color: <Esc>]11;?<0x07>
+       int red = state->default_bg.red;
+       int blue = state->default_bg.blue;
+       int green = state->default_bg.green;
+       vterm_push_output_sprintf_ctrl(state->vt, C1_OSC, 
"11;rgb:%02x%02x/%02x%02x/%02x%02x\x07", red, red, green, green, blue, blue);
+       return 1;
+       }
+     case 12:
+       settermprop_string(state, VTERM_PROP_CURSORCOLOR, 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, VTermStringFragment frag)
  {
    VTerm *vt = state->vt;
  
!   char *tmp = state->tmp.decrqss;
!   size_t i = 0;
  
!   if(frag.initial)
!     tmp[0] = tmp[1] = tmp[2] = tmp[3] = 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;
!       int argi;
! 
!       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(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;
      }
  
!     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;
***************
*** 1707,1733 ****
        vterm_push_output_sprintf_dcs(vt, "1$r%d q", reply);
        return;
      }
!     else if(strneq(command, "\"q", 2)) {
        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);
  }
  
! static int on_dcs(const char *command, size_t cmdlen, void *user)
  {
    VTermState *state = user;
  
!   if(cmdlen >= 2 && strneq(command, "$q", 2)) {
!     request_status_string(state, command+2, cmdlen-2);
      return 1;
    }
    else if(state->fallbacks && state->fallbacks->dcs)
!     if((*state->fallbacks->dcs)(command, cmdlen, state->fbdata))
        return 1;
  
    return 0;
  }
  
--- 1721,1749 ----
        vterm_push_output_sprintf_dcs(vt, "1$r%d q", reply);
        return;
      }
! 
!     case '\"'|('q'<<8):
!       // Query DECSCA
        vterm_push_output_sprintf_dcs(vt, "1$r%d\"q", state->protected_cell ? 1 
: 2);
        return;
    }
  
!   vterm_push_output_sprintf_dcs(state->vt, "0$r%s", tmp);
  }
  
! static int on_dcs(const char *command, size_t commandlen, VTermStringFragment 
frag, void *user)
  {
    VTermState *state = user;
  
!   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, commandlen, frag, state->fbdata))
        return 1;
  
+   DEBUG_LOG2("libvterm: Unhandled DCS %.*s\n", (int)commandlen, command);
    return 0;
  }
  
*** ../vim-8.2.0797/src/libvterm/src/vterm.c    2020-05-17 23:34:37.576176126 
+0200
--- src/libvterm/src/vterm.c    2020-05-19 19:40:53.294811735 +0200
***************
*** 55,89 ****
    vt->parser.callbacks = NULL;
    vt->parser.cbdata    = NULL;
  
-   vt->parser.strbuffer_len = 500; // should be able to hold an OSC string
-   vt->parser.strbuffer_cur = 0;
-   vt->parser.strbuffer = vterm_allocator_malloc(vt, vt->parser.strbuffer_len);
-   if (vt->parser.strbuffer == NULL)
-   {
-     vterm_allocator_free(vt, vt);
-     return NULL;
-   }
- 
    vt->outfunc = NULL;
    vt->outdata = NULL;
  
    vt->outbuffer_len = 200;
    vt->outbuffer_cur = 0;
    vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);
-   if (vt->outbuffer == NULL)
-   {
-     vterm_allocator_free(vt, vt->parser.strbuffer);
-     vterm_allocator_free(vt, vt);
-     return NULL;
-   }
  
    vt->tmpbuffer_len = 64;
    vt->tmpbuffer = vterm_allocator_malloc(vt, vt->tmpbuffer_len);
!   if (vt->tmpbuffer == NULL)
    {
-     vterm_allocator_free(vt, vt->parser.strbuffer);
-     vterm_allocator_free(vt, vt);
      vterm_allocator_free(vt, vt->outbuffer);
      return NULL;
    }
  
--- 55,77 ----
    vt->parser.callbacks = NULL;
    vt->parser.cbdata    = NULL;
  
    vt->outfunc = NULL;
    vt->outdata = NULL;
  
    vt->outbuffer_len = 200;
    vt->outbuffer_cur = 0;
    vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);
  
    vt->tmpbuffer_len = 64;
    vt->tmpbuffer = vterm_allocator_malloc(vt, vt->tmpbuffer_len);
! 
!   if (vt->tmpbuffer == NULL
!       || vt->outbuffer == NULL
!       || vt->tmpbuffer == NULL)
    {
      vterm_allocator_free(vt, vt->outbuffer);
+     vterm_allocator_free(vt, vt->tmpbuffer);
+     vterm_allocator_free(vt, vt);
      return NULL;
    }
  
***************
*** 98,104 ****
    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);
  
--- 86,91 ----
*** ../vim-8.2.0797/src/libvterm/src/vterm_internal.h   2020-05-18 
21:12:55.226306815 +0200
--- src/libvterm/src/vterm_internal.h   2020-05-19 19:44:40.386559385 +0200
***************
*** 160,173 ****
        unsigned int cursor_shape:2;
      } mode;
    } saved;
- };
- 
- typedef enum {
-   VTERM_PARSER_OSC,
-   VTERM_PARSER_DCS,
  
!   VTERM_N_PARSER_TYPES
! } VTermParserStringType;
  
  struct VTerm
  {
--- 160,171 ----
        unsigned int cursor_shape:2;
      } mode;
    } saved;
  
!   /* Temporary state for DECRQSS parsing */
!   union {
!     char decrqss[4];
!   } tmp;
! };
  
  struct VTerm
  {
***************
*** 188,215 ****
        CSI_LEADER,
        CSI_ARGS,
        CSI_INTERMED,
!       ESC,
        // below here are the "string states"
!       STRING,
!       ESC_IN_STRING,
      } state;
  
      int intermedlen;
      char intermed[INTERMED_MAX];
  
!     int csi_leaderlen;
!     char csi_leader[CSI_LEADER_MAX];
! 
!     int csi_argi;
!     long csi_args[CSI_ARGS_MAX];
  
      const VTermParserCallbacks *callbacks;
      void *cbdata;
  
!     VTermParserStringType stringtype;
!     char  *strbuffer;
!     size_t strbuffer_len;
!     size_t strbuffer_cur;
    } parser;
  
    // len == malloc()ed size; cur == number of valid bytes
--- 186,224 ----
        CSI_LEADER,
        CSI_ARGS,
        CSI_INTERMED,
!       OSC_COMMAND,
!       DCS_COMMAND,
        // below here are the "string states"
!       OSC,
!       DCS,
      } state;
  
+     unsigned int in_esc : 1;
+ 
      int intermedlen;
      char intermed[INTERMED_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;
  
!     int string_initial;
    } parser;
  
    // len == malloc()ed size; cur == number of valid bytes
*** ../vim-8.2.0797/src/libvterm/t/02parser.test        2017-06-24 
16:44:02.000000000 +0200
--- src/libvterm/t/02parser.test        2020-05-19 19:15:23.211486825 +0200
***************
*** 132,146 ****
  
  !OSC BEL
  PUSH "\e]1;Hello\x07"
!   osc "1;Hello"
  
  !OSC ST (7bit)
  PUSH "\e]1;Hello\e\\"
!   osc "1;Hello"
  
  !OSC ST (8bit)
  PUSH "\x{9d}1;Hello\x9c"
!   osc "1;Hello"
  
  !Escape cancels OSC, starts Escape
  PUSH "\e]Something\e9"
--- 132,154 ----
  
  !OSC BEL
  PUSH "\e]1;Hello\x07"
!   osc [1 "Hello"]
  
  !OSC ST (7bit)
  PUSH "\e]1;Hello\e\\"
!   osc [1 "Hello"]
  
  !OSC ST (8bit)
  PUSH "\x{9d}1;Hello\x9c"
!   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,171 ****
  
  !C0 in OSC interrupts and continues
  PUSH "\e]2;\nBye\x07"
    control 10
!   osc "2;Bye"
  
  !DCS BEL
  PUSH "\ePHello\x07"
!   dcs "Hello"
  
  !DCS ST (7bit)
  PUSH "\ePHello\e\\"
!   dcs "Hello"
  
  !DCS ST (8bit)
  PUSH "\x{90}Hello\x9c"
!   dcs "Hello"
  
  !Escape cancels DCS, starts Escape
  PUSH "\ePSomething\e9"
--- 160,180 ----
  
  !C0 in OSC interrupts and continues
  PUSH "\e]2;\nBye\x07"
+   osc [2 ""
    control 10
!   osc "Bye"]
  
  !DCS BEL
  PUSH "\ePHello\x07"
!   dcs ["Hello"]
  
  !DCS ST (7bit)
  PUSH "\ePHello\e\\"
!   dcs ["Hello"]
  
  !DCS ST (8bit)
  PUSH "\x{90}Hello\x9c"
!   dcs ["Hello"]
  
  !Escape cancels DCS, starts Escape
  PUSH "\ePSomething\e9"
***************
*** 177,184 ****
  
  !C0 in OSC interrupts and continues
  PUSH "\ePBy\ne\x07"
    control 10
!   dcs "Bye"
  
  !NUL ignored
  PUSH "\x{00}"
--- 186,194 ----
  
  !C0 in OSC interrupts and continues
  PUSH "\ePBy\ne\x07"
+   dcs ["By"
    control 10
!   dcs "e"]
  
  !NUL ignored
  PUSH "\x{00}"
*** ../vim-8.2.0797/src/libvterm/t/18state_termprops.test       2017-06-24 
16:44:02.000000000 +0200
--- src/libvterm/t/18state_termprops.test       2020-05-19 19:15:23.211486825 
+0200
***************
*** 33,36 ****
  
  !Title
  PUSH "\e]2;Here is my title\a"
!   settermprop 4 "Here is my title"
--- 33,42 ----
  
  !Title
  PUSH "\e]2;Here is my title\a"
!   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"]
*** ../vim-8.2.0797/src/libvterm/t/29state_fallback.test        2017-06-24 
16:44:02.000000000 +0200
--- src/libvterm/t/29state_fallback.test        2020-05-19 19:15:23.211486825 
+0200
***************
*** 12,19 ****
  
  !Unrecognised OSC
  PUSH "\e]27;Something\e\\"
!   osc "27;Something"
  
  !Unrecognised DCS
  PUSH "\ePz123\e\\"
!   dcs "z123"
--- 12,19 ----
  
  !Unrecognised OSC
  PUSH "\e]27;Something\e\\"
!   osc [27 "Something"]
  
  !Unrecognised DCS
  PUSH "\ePz123\e\\"
!   dcs ["z123"]
*** ../vim-8.2.0797/src/libvterm/t/68screen_termprops.test      2020-05-17 
16:28:47.087869402 +0200
--- src/libvterm/t/68screen_termprops.test      2020-05-19 19:15:23.211486825 
+0200
***************
*** 14,17 ****
  
  !Title
  PUSH "\e]2;Here is my title\a"
!   settermprop 4 "Here is my title"
--- 14,17 ----
  
  !Title
  PUSH "\e]2;Here is my title\a"
!   settermprop 4 ["Here is my title"]
*** ../vim-8.2.0797/src/libvterm/t/harness.c    2020-05-18 21:50:32.932742338 
+0200
--- src/libvterm/t/harness.c    2020-05-19 21:14:58.824143429 +0200
***************
*** 153,173 ****
    return 1;
  }
  
! static int parser_osc(const char *command, size_t cmdlen, void *user UNUSED)
  {
  
    printf("osc ");
!   printhex(command, cmdlen);
    printf("\n");
  
    return 1;
  }
  
! static int parser_dcs(const char *command, size_t cmdlen, void *user UNUSED)
  {
- 
    printf("dcs ");
!   printhex(command, cmdlen);
    printf("\n");
  
    return 1;
--- 153,196 ----
    return 1;
  }
  
! static int parser_osc(int command, VTermStringFragment frag, void *user 
UNUSED)
  {
  
    printf("osc ");
! 
!   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 commandlen, 
VTermStringFragment frag, void *user UNUSED)
  {
    printf("dcs ");
! 
!   if(frag.initial) {
!     size_t i;
!     printf("[");
!     for(i = 0; i < commandlen; i++)
!       printf("%02x", command[i]);
!   }
! 
!   printhex(frag.str, frag.len);
! 
!   if(frag.final)
!     printf("]");
! 
    printf("\n");
  
    return 1;
***************
*** 239,245 ****
      printf("settermprop %d %d\n", prop, val->number);
      return 1;
    case VTERM_VALUETYPE_STRING:
!     printf("settermprop %d \"%s\"\n", prop, val->string);
      return 1;
    case VTERM_VALUETYPE_COLOR:
      printf("settermprop %d rgb(%d,%d,%d)\n", prop, val->color.red, 
val->color.green, val->color.blue);
--- 262,269 ----
      printf("settermprop %d %d\n", prop, val->number);
      return 1;
    case VTERM_VALUETYPE_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 rgb(%d,%d,%d)\n", prop, val->color.red, 
val->color.green, val->color.blue);
***************
*** 262,268 ****
      return 1;
  
    printf("putglyph ");
!   for(i = 0; 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)
--- 286,292 ----
      return 1;
  
    printf("putglyph ");
!   for(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)
*** ../vim-8.2.0797/src/terminal.c      2020-04-26 16:05:58.574358031 +0200
--- src/terminal.c      2020-05-19 21:05:54.929679591 +0200
***************
*** 2998,3019 ****
        void *user)
  {
      term_T    *term = (term_T *)user;
  
      switch (prop)
      {
        case VTERM_PROP_TITLE:
            vim_free(term->tl_title);
            // a blank title isn't useful, make it empty, so that "running" is
            // displayed
!           if (*skipwhite((char_u *)value->string) == NUL)
                term->tl_title = NULL;
            // Same as blank
            else if (term->tl_arg0_cmd != NULL
!                   && STRNCMP(term->tl_arg0_cmd, (char_u *)value->string,
                                          (int)STRLEN(term->tl_arg0_cmd)) == 0)
                term->tl_title = NULL;
            // Empty corrupted data of winpty
!           else if (STRNCMP("  - ", (char_u *)value->string, 4) == 0)
                term->tl_title = NULL;
  #ifdef MSWIN
            else if (!enc_utf8 && enc_codepage > 0)
--- 2998,3024 ----
        void *user)
  {
      term_T    *term = (term_T *)user;
+     char_u    *strval = NULL;
  
      switch (prop)
      {
        case VTERM_PROP_TITLE:
+           strval = vim_strnsave((char_u *)value->string.str,
+                                                      (int)value->string.len);
+           if (strval == NULL)
+               break;
            vim_free(term->tl_title);
            // a blank title isn't useful, make it empty, so that "running" is
            // displayed
!           if (*skipwhite(strval) == NUL)
                term->tl_title = NULL;
            // Same as blank
            else if (term->tl_arg0_cmd != NULL
!                   && STRNCMP(term->tl_arg0_cmd, strval,
                                          (int)STRLEN(term->tl_arg0_cmd)) == 0)
                term->tl_title = NULL;
            // Empty corrupted data of winpty
!           else if (STRNCMP("  - ", strval, 4) == 0)
                term->tl_title = NULL;
  #ifdef MSWIN
            else if (!enc_utf8 && enc_codepage > 0)
***************
*** 3022,3029 ****
                int     length = 0;
  
                MultiByteToWideChar_alloc(CP_UTF8, 0,
!                       (char*)value->string, (int)STRLEN(value->string),
!                                                               &ret, &length);
                if (ret != NULL)
                {
                    WideCharToMultiByte_alloc(enc_codepage, 0,
--- 3027,3034 ----
                int     length = 0;
  
                MultiByteToWideChar_alloc(CP_UTF8, 0,
!                       (char*)value->string.str,
!                                       (int)value->string.len, &ret, &length);
                if (ret != NULL)
                {
                    WideCharToMultiByte_alloc(enc_codepage, 0,
***************
*** 3034,3040 ****
            }
  #endif
            else
!               term->tl_title = vim_strsave((char_u *)value->string);
            VIM_CLEAR(term->tl_status_text);
            if (term == curbuf->b_term)
                maketitle();
--- 3039,3048 ----
            }
  #endif
            else
!           {
!               term->tl_title = vim_strsave(strval);
!               strval = NULL;
!           }
            VIM_CLEAR(term->tl_status_text);
            if (term == curbuf->b_term)
                maketitle();
***************
*** 3057,3063 ****
            break;
  
        case VTERM_PROP_CURSORCOLOR:
!           cursor_color_copy(&term->tl_cursor_color, (char_u*)value->string);
            may_set_cursor_props(term);
            break;
  
--- 3065,3075 ----
            break;
  
        case VTERM_PROP_CURSORCOLOR:
!           strval = vim_strnsave((char_u *)value->string.str,
!                                                      (int)value->string.len);
!           if (strval == NULL)
!               break;
!           cursor_color_copy(&term->tl_cursor_color, strval);
            may_set_cursor_props(term);
            break;
  
***************
*** 3069,3074 ****
--- 3081,3088 ----
        default:
            break;
      }
+     vim_free(strval);
+ 
      // Always return 1, otherwise vterm doesn't store the value internally.
      return 1;
  }
***************
*** 4181,4187 ****
   * We recognize a terminal API command.
   */
      static int
! parse_osc(const char *command, size_t cmdlen, void *user)
  {
      term_T    *term = (term_T *)user;
      js_read_T reader;
--- 4195,4201 ----
   * We recognize a terminal API command.
   */
      static int
! parse_osc(int command, VTermStringFragment frag, void *user)
  {
      term_T    *term = (term_T *)user;
      js_read_T reader;
***************
*** 4190,4199 ****
                                                    : term->tl_job->jv_channel;
  
      // We recognize only OSC 5 1 ; {command}
!     if (cmdlen < 3 || STRNCMP(command, "51;", 3) != 0)
!       return 0; // not handled
  
!     reader.js_buf = vim_strnsave((char_u *)command + 3, (int)(cmdlen - 3));
      if (reader.js_buf == NULL)
        return 1;
      reader.js_fill = NULL;
--- 4204,4213 ----
                                                    : term->tl_job->jv_channel;
  
      // We recognize only OSC 5 1 ; {command}
!     if (command != 51)
!       return 0;
  
!     reader.js_buf = vim_strnsave((char_u *)frag.str, (int)(frag.len));
      if (reader.js_buf == NULL)
        return 1;
      reader.js_fill = NULL;
*** ../vim-8.2.0797/src/version.c       2020-05-19 10:32:59.291518426 +0200
--- src/version.c       2020-05-19 21:17:50.119661570 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     798,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
136. You decide to stay in a low-paying job teaching just for the
     free Internet access.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202005191920.04JJKvDV020329%40masaka.moolenaar.net.

Raspunde prin e-mail lui