To: vim_dev@googlegroups.com Subject: Patch 8.2.0798 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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: ]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: ]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: ]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: ]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 -- Bram@Moolenaar.net -- 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 ///