# HG changeset patch # User Bram Moolenaar # Date 1589832003 -7200 # Node ID dc88c690f19b9ee58c2a31663ed8b879758afd92 # Parent ee70957e66eab5a0215c3b82f30a7b11640c9c60 patch 8.2.0795: libvterm code lags behind the upstream version Commit: https://github.com/vim/vim/commit/88d68de95da70d0f89a5246f58355d72e9c17db4 Author: Bram Moolenaar Date: Mon May 18 21:51:01 2020 +0200 patch 8.2.0795: libvterm code lags behind the upstream version Problem: Libvterm code lags behind the upstream version. Solution: Include revisions 748 - 754. diff --git a/src/libvterm/include/vterm.h b/src/libvterm/include/vterm.h --- a/src/libvterm/include/vterm.h +++ b/src/libvterm/include/vterm.h @@ -170,8 +170,9 @@ typedef struct { } VTermGlyphInfo; typedef struct { - unsigned int doublewidth:1; // DECDWL or DECDHL line - unsigned int doubleheight:2; // DECDHL line (1=top 2=bottom) + unsigned int doublewidth:1; /* DECDWL or DECDHL line */ + unsigned int doubleheight:2; /* DECDHL line (1=top 2=bottom) */ + unsigned int continuation:1; /* Line is a flow continuation of the previous */ } VTermLineInfo; typedef struct { diff --git a/src/libvterm/src/screen.c b/src/libvterm/src/screen.c --- a/src/libvterm/src/screen.c +++ b/src/libvterm/src/screen.c @@ -488,24 +488,9 @@ static void resize_buffer(VTermScreen *s ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, sizeof(ScreenCell) * new_rows * new_cols); /* Find the final row of old buffer content */ - int old_row; + int old_row = old_rows - 1; + int new_row = new_rows - 1; int col; - int new_row; - - for(old_row = old_rows - 1; old_row > 0; old_row--) { - if(active && (old_row == screen->state->pos.row)) - /* The line with the active cursor is never "blank" */ - goto found_oldrow; - for(col = 0; col < old_cols; col++) - if(old_buffer[old_row * old_cols + col].chars[0]) - /* This row is not blank */ - goto found_oldrow; - } - old_row = 0; -found_oldrow: - ; - - new_row = new_rows - 1; while(new_row >= 0 && old_row >= 0) { for(col = 0; col < old_cols && col < new_cols; col++) @@ -515,6 +500,15 @@ found_oldrow: old_row--; new_row--; + + if(new_row < 0 && old_row >= 0 && + new_buffer[(new_rows - 1) * new_cols].chars[0] == 0 && + (!active || statefields->pos.row < (new_rows - 1))) { + int moverows = new_rows - 1; + memmove(&new_buffer[1 * new_cols], &new_buffer[0], moverows * new_cols * sizeof(ScreenCell)); + + new_row++; + } } if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) { @@ -877,7 +871,6 @@ VTermScreen *vterm_obtain_screen(VTerm * void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen) { - if(!screen->buffers[BUFIDX_ALTSCREEN] && altscreen) { int rows, cols; vterm_get_size(screen->vt, &rows, &cols); diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c --- a/src/libvterm/src/state.c +++ b/src/libvterm/src/state.c @@ -44,6 +44,15 @@ static void updatecursor(VTermState *sta static void erase(VTermState *state, VTermRect rect, int selective) { + if(rect.end_col == state->cols) { + int row; + /* If we're erasing the final cells of any lines, cancel the continuation + * marker on the subsequent line + */ + for(row = rect.start_row + 1; row < rect.end_row + 1 && row < state->rows; row++) + state->lineinfo[row].continuation = 0; + } + if(state->callbacks && state->callbacks->erase) if((*state->callbacks->erase)(rect, selective, state->cbdata)) return; @@ -78,11 +87,13 @@ static VTermState *vterm_state_new(VTerm state->tabstops = vterm_allocator_malloc(state->vt, (state->cols + 7) / 8); - state->lineinfos[BUFIDX_PRIMARY] = vterm_allocator_malloc(state->vt, state->rows * sizeof(VTermLineInfo)); + state->lineinfos[BUFIDX_PRIMARY] = vterm_allocator_malloc(state->vt, state->rows * sizeof(VTermLineInfo)); + /* TODO: Make an 'enable' function */ + state->lineinfos[BUFIDX_ALTSCREEN] = vterm_allocator_malloc(state->vt, state->rows * sizeof(VTermLineInfo)); state->lineinfo = state->lineinfos[BUFIDX_PRIMARY]; state->encoding_utf8.enc = vterm_lookup_encoding(ENC_UTF8, 'u'); - if(*state->encoding_utf8.enc->init) + if(state->encoding_utf8.enc->init) (*state->encoding_utf8.enc->init)(state->encoding_utf8.enc, state->encoding_utf8.data); return state; @@ -121,20 +132,21 @@ static void scroll(VTermState *state, VT if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) { int height = rect.end_row - rect.start_row - abs(downward); int row; + VTermLineInfo zeroLineInfo = { 0 }; if(downward > 0) { memmove(state->lineinfo + rect.start_row, state->lineinfo + rect.start_row + downward, height * sizeof(state->lineinfo[0])); for(row = rect.end_row - downward; row < rect.end_row; row++) - state->lineinfo[row] = (VTermLineInfo){ 0 }; + state->lineinfo[row] = zeroLineInfo; } else { memmove(state->lineinfo + rect.start_row - downward, state->lineinfo + rect.start_row, height * sizeof(state->lineinfo[0])); for(row = rect.start_row; row < rect.start_row - downward; row++) - state->lineinfo[row] = (VTermLineInfo){ 0 }; + state->lineinfo[row] = zeroLineInfo; } } @@ -388,6 +400,7 @@ static int on_text(const char bytes[], s linefeed(state); state->pos.col = 0; state->at_phantom = 0; + state->lineinfo[state->pos.row].continuation = 1; } if(state->mode.insert) { @@ -1752,13 +1765,15 @@ static int on_resize(int rows, int cols, } if(rows != state->rows) { - for(int bufidx = BUFIDX_PRIMARY; bufidx <= BUFIDX_ALTSCREEN; bufidx++) { + int bufidx; + for(bufidx = BUFIDX_PRIMARY; bufidx <= BUFIDX_ALTSCREEN; bufidx++) { int row; VTermLineInfo *oldlineinfo = state->lineinfos[bufidx]; + VTermLineInfo *newlineinfo; if(!oldlineinfo) continue; - VTermLineInfo *newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo)); + newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo)); for(row = 0; row < state->rows && row < rows; row++) { newlineinfo[row] = oldlineinfo[row]; @@ -1994,8 +2009,6 @@ int vterm_state_set_termprop(VTermState return 1; case VTERM_PROP_ALTSCREEN: state->mode.alt_screen = val->boolean; - if(state->mode.alt_screen && !state->lineinfos[BUFIDX_ALTSCREEN]) - state->lineinfos[BUFIDX_ALTSCREEN] = vterm_allocator_malloc(state->vt, state->rows * sizeof(VTermLineInfo)); state->lineinfo = state->lineinfos[state->mode.alt_screen ? BUFIDX_ALTSCREEN : BUFIDX_PRIMARY]; if(state->mode.alt_screen) { VTermRect rect = {0, 0, 0, 0}; diff --git a/src/libvterm/t/32state_flow.test b/src/libvterm/t/32state_flow.test new file mode 100644 --- /dev/null +++ b/src/libvterm/t/32state_flow.test @@ -0,0 +1,28 @@ +INIT +WANTSTATE + +# Many of these test cases inspired by +# https://blueprints.launchpad.net/libvterm/+spec/reflow-cases + +!Spillover text marks continuation on second line +RESET +PUSH "A"x100 +PUSH "\r\n" + ?lineinfo 0 = + ?lineinfo 1 = cont + +!CRLF in column 80 does not mark continuation +RESET +PUSH "B"x80 +PUSH "\r\n" +PUSH "B"x20 +PUSH "\r\n" + ?lineinfo 0 = + ?lineinfo 1 = + +!EL cancels continuation of following line +RESET +PUSH "D"x100 + ?lineinfo 1 = cont +PUSH "\eM\e[79G\e[K" + ?lineinfo 1 = diff --git a/src/libvterm/t/60screen_ascii.test b/src/libvterm/t/60screen_ascii.test --- a/src/libvterm/t/60screen_ascii.test +++ b/src/libvterm/t/60screen_ascii.test @@ -1,12 +1,12 @@ INIT -WANTSCREEN c +WANTSCREEN ac !Get RESET PUSH "ABC" movecursor 0,3 - ?screen_chars 0,0,1,3 = 0x41,0x42,0x43 - ?screen_chars 0,0,1,80 = 0x41,0x42,0x43 + ?screen_chars 0,0,1,3 = "ABC" + ?screen_chars 0,0,1,80 = "ABC" ?screen_text 0,0,1,3 = 0x41,0x42,0x43 ?screen_text 0,0,1,80 = 0x41,0x42,0x43 ?screen_cell 0,0 = {0x41} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0) @@ -18,11 +18,11 @@ PUSH "ABC" ?screen_eol 0,3 = 1 PUSH "\e[H" movecursor 0,0 - ?screen_chars 0,0,1,80 = 0x41,0x42,0x43 + ?screen_chars 0,0,1,80 = "ABC" ?screen_text 0,0,1,80 = 0x41,0x42,0x43 PUSH "E" movecursor 0,1 - ?screen_chars 0,0,1,80 = 0x45,0x42,0x43 + ?screen_chars 0,0,1,80 = "EBC" ?screen_text 0,0,1,80 = 0x45,0x42,0x43 WANTSCREEN -c @@ -37,33 +37,33 @@ PUSH "ABCDE\e[H\e[K" RESET PUSH "ABC\e[H\e[@" PUSH "1" - ?screen_chars 0,0,1,80 = 0x31,0x41,0x42,0x43 + ?screen_chars 0,0,1,80 = "1ABC" RESET PUSH "ABC\e[H\e[P" - ?screen_chars 0,0,1,1 = 0x42 - ?screen_chars 0,1,1,2 = 0x43 - ?screen_chars 0,0,1,80 = 0x42,0x43 + ?screen_chars 0,0,1,1 = "B" + ?screen_chars 0,1,1,2 = "C" + ?screen_chars 0,0,1,80 = "BC" !Space padding RESET PUSH "Hello\e[CWorld" - ?screen_chars 0,0,1,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64 + ?screen_chars 0,0,1,80 = "Hello World" ?screen_text 0,0,1,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64 !Linefeed padding RESET PUSH "Hello\r\nWorld" - ?screen_chars 0,0,2,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x0a,0x57,0x6f,0x72,0x6c,0x64 + ?screen_chars 0,0,2,80 = "Hello\nWorld" ?screen_text 0,0,2,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x0a,0x57,0x6f,0x72,0x6c,0x64 !Altscreen RESET PUSH "P" - ?screen_chars 0,0,1,80 = 0x50 + ?screen_chars 0,0,1,80 = "P" PUSH "\e[?1049h" ?screen_chars 0,0,1,80 = PUSH "\e[2K\e[HA" - ?screen_chars 0,0,1,80 = 0x41 + ?screen_chars 0,0,1,80 = "A" PUSH "\e[?1049l" - ?screen_chars 0,0,1,80 = 0x50 + ?screen_chars 0,0,1,80 = "P" diff --git a/src/libvterm/t/62screen_damage.test b/src/libvterm/t/62screen_damage.test --- a/src/libvterm/t/62screen_damage.test +++ b/src/libvterm/t/62screen_damage.test @@ -1,5 +1,5 @@ INIT -WANTSCREEN Db +WANTSCREEN aDb !Putglyph RESET @@ -152,4 +152,4 @@ PUSH "\e[25H\r\nABCDE\b\b\b\e[2P\r\n" DAMAGEFLUSH moverect 1..25,0..80 -> 0..24,0..80 damage 24..25,0..80 - ?screen_chars 23,0,24,5 = 0x41,0x42,0x45 + ?screen_chars 23,0,24,5 = "ABE" diff --git a/src/libvterm/t/63screen_resize.test b/src/libvterm/t/63screen_resize.test --- a/src/libvterm/t/63screen_resize.test +++ b/src/libvterm/t/63screen_resize.test @@ -6,42 +6,42 @@ WANTSCREEN RESET RESIZE 25,80 PUSH "AB\r\nCD" - ?screen_chars 0,0,1,80 = 0x41,0x42 - ?screen_chars 1,0,2,80 = 0x43,0x44 + ?screen_chars 0,0,1,80 = "AB" + ?screen_chars 1,0,2,80 = "CD" RESIZE 25,100 - ?screen_chars 0,0,1,100 = 0x41,0x42 - ?screen_chars 1,0,2,100 = 0x43,0x44 + ?screen_chars 0,0,1,100 = "AB" + ?screen_chars 1,0,2,100 = "CD" !Resize wider allows print in new area RESET RESIZE 25,80 PUSH "AB\e[79GCD" - ?screen_chars 0,0,1,2 = 0x41,0x42 - ?screen_chars 0,78,1,80 = 0x43,0x44 + ?screen_chars 0,0,1,2 = "AB" + ?screen_chars 0,78,1,80 = "CD" RESIZE 25,100 - ?screen_chars 0,0,1,2 = 0x41,0x42 - ?screen_chars 0,78,1,80 = 0x43,0x44 + ?screen_chars 0,0,1,2 = "AB" + ?screen_chars 0,78,1,80 = "CD" PUSH "E" - ?screen_chars 0,78,1,81 = 0x43,0x44,0x45 + ?screen_chars 0,78,1,81 = "CDE" !Resize shorter with blanks just truncates RESET RESIZE 25,80 PUSH "Top\e[10HLine 10" - ?screen_chars 0,0,1,80 = 0x54,0x6f,0x70 - ?screen_chars 9,0,10,80 = 0x4c,0x69,0x6e,0x65,0x20,0x31,0x30 + ?screen_chars 0,0,1,80 = "Top" + ?screen_chars 9,0,10,80 = "Line 10" ?cursor = 9,7 RESIZE 20,80 - ?screen_chars 0,0,1,80 = 0x54,0x6f,0x70 - ?screen_chars 9,0,10,80 = 0x4c,0x69,0x6e,0x65,0x20,0x31,0x30 + ?screen_chars 0,0,1,80 = "Top" + ?screen_chars 9,0,10,80 = "Line 10" ?cursor = 9,7 !Resize shorter with content must scroll RESET RESIZE 25,80 PUSH "Top\e[25HLine 25\e[15H" - ?screen_chars 0,0,1,80 = 0x54,0x6f,0x70 - ?screen_chars 24,0,25,80 = 0x4c,0x69,0x6e,0x65,0x20,0x32,0x35 + ?screen_chars 0,0,1,80 = "Top" + ?screen_chars 24,0,25,80 = "Line 25" ?cursor = 14,0 WANTSCREEN b RESIZE 20,80 @@ -51,7 +51,7 @@ RESIZE 20,80 sb_pushline 80 = sb_pushline 80 = ?screen_chars 0,0,1,80 = - ?screen_chars 19,0,20,80 = 0x4c,0x69,0x6e,0x65,0x20,0x32,0x35 + ?screen_chars 19,0,20,80 = "Line 25" ?cursor = 9,0 !Resize shorter does not lose line with cursor @@ -62,11 +62,11 @@ RESIZE 25,80 WANTSCREEN b PUSH "\e[24HLine 24\r\nLine 25\r\n" sb_pushline 80 = - ?screen_chars 23,0,24,10 = 0x4c,0x69,0x6e,0x65,0x20,0x32,0x35 + ?screen_chars 23,0,24,10 = "Line 25" ?cursor = 24,0 RESIZE 24,80 sb_pushline 80 = - ?screen_chars 22,0,23,10 = 0x4c,0x69,0x6e,0x65,0x20,0x32,0x35 + ?screen_chars 22,0,23,10 = "Line 25" ?cursor = 23,0 !Resize taller attempts to pop scrollback @@ -74,8 +74,8 @@ RESET WANTSCREEN -b RESIZE 25,80 PUSH "Line 1\e[25HBottom\e[15H" - ?screen_chars 0,0,1,80 = 0x4c,0x69,0x6e,0x65,0x20,0x31 - ?screen_chars 24,0,25,80 = 0x42,0x6f,0x74,0x74,0x6f,0x6d + ?screen_chars 0,0,1,80 = "Line 1" + ?screen_chars 24,0,25,80 = "Bottom" ?cursor = 14,0 WANTSCREEN b RESIZE 30,80 @@ -84,7 +84,18 @@ RESIZE 30,80 sb_popline 80 sb_popline 80 sb_popline 80 - ?screen_chars 0,0,1,80 = 0x41,0x42,0x43,0x44,0x45 - ?screen_chars 5,0,6,80 = 0x4c,0x69,0x6e,0x65,0x20,0x31 - ?screen_chars 29,0,30,80 = 0x42,0x6f,0x74,0x74,0x6f,0x6d + ?screen_chars 0,0,1,80 = "ABCDE" + ?screen_chars 5,0,6,80 = "Line 1" + ?screen_chars 29,0,30,80 = "Bottom" ?cursor = 19,0 +WANTSCREEN -b + +!Resize can operate on altscreen +RESET +WANTSCREEN a +RESIZE 25,80 +PUSH "Main screen\e[?1049h\e[HAlt screen" +RESIZE 30,80 + ?screen_chars 0,0,1,3 = "Alt" +PUSH "\e[?1049l" + ?screen_chars 0,0,1,3 = "Mai" diff --git a/src/libvterm/t/harness.c b/src/libvterm/t/harness.c --- a/src/libvterm/t/harness.c +++ b/src/libvterm/t/harness.c @@ -540,7 +540,6 @@ int main(int argc UNUSED, char **argv UN int sense = 1; if(!screen) screen = vterm_obtain_screen(vt); - vterm_screen_enable_altscreen(screen, 1); vterm_screen_set_callbacks(screen, &screen_cbs, NULL); while(line[i] == ' ') @@ -550,6 +549,9 @@ int main(int argc UNUSED, char **argv UN case '-': sense = 0; break; + case 'a': + vterm_screen_enable_altscreen(screen, 1); + break; case 'd': want_screen_damage = sense; break; @@ -805,6 +807,25 @@ int main(int argc UNUSED, char **argv UN else printf("?\n"); } + else if(strstartswith(line, "?lineinfo ")) { + char *linep = line + 10; + int row; + const VTermLineInfo *info; + while(linep[0] == ' ') + linep++; + if(sscanf(linep, "%d", &row) < 1) { + printf("! lineinfo unrecognised input\n"); + goto abort_line; + } + info = vterm_state_get_lineinfo(state, row); + if(info->doublewidth) + printf("dwl "); + if(info->doubleheight) + printf("dhl "); + if(info->continuation) + printf("cont "); + printf("\n"); + } else if(strstartswith(line, "?screen_chars ")) { char *linep = line + 13; VTermRect rect; diff --git a/src/libvterm/t/run-test.pl b/src/libvterm/t/run-test.pl --- a/src/libvterm/t/run-test.pl +++ b/src/libvterm/t/run-test.pl @@ -28,6 +28,8 @@ my $exitcode = 0; my $command; my @expect; +my $linenum = 0; + sub do_onetest { $hin->print( "$command\n" ); @@ -41,7 +43,7 @@ sub do_onetest chomp $outline; if( !@expect ) { - print "# Test failed\n" unless $fail_printed++; + print "# line $linenum: Test failed\n" unless $fail_printed++; print "# expected nothing more\n" . "# Actual: $outline\n"; next; @@ -51,13 +53,13 @@ sub do_onetest next if $expectation eq $outline; - print "# Test failed\n" unless $fail_printed++; + print "# line $linenum: Test failed\n" unless $fail_printed++; print "# Expected: $expectation\n" . "# Actual: $outline\n"; } if( @expect ) { - print "# Test failed\n" unless $fail_printed++; + print "# line $linenum: Test failed\n" unless $fail_printed++; print "# Expected: $_\n" . "# didn't happen\n" for @expect; } @@ -133,7 +135,7 @@ sub do_line $response = pack "C*", map hex, split m/,/, $response; if( $response ne $want ) { - print "# Assert ?screen_row $row failed:\n" . + print "# line $linenum: Assert ?screen_row $row failed:\n" . "# Expected: $want\n" . "# Actual: $response\n"; $exitcode = 1; @@ -144,14 +146,20 @@ sub do_line do_onetest if defined $command; my ( $assertion ) = $1 =~ m/^(.*)\s+=/; + my $expectation = $line; $hin->print( "\?$assertion\n" ); my $response = <$hout>; defined $response or wait, die "Test harness failed - $?\n"; chomp $response; $response =~ s/^\s+|\s+$//g; - if( $response ne $line ) { - print "# Assert $assertion failed:\n" . - "# Expected: $line\n" . + # Some convenience formatting + if( $assertion =~ m/^screen_chars/ and $expectation =~ m/^"/ ) { + $expectation = join ",", map sprintf("0x%02x", ord $_), split m//, eval($expectation); + } + + if( $response ne $expectation ) { + print "# line $linenum: Assert $assertion failed:\n" . + "# Expected: $expectation\n" . "# Actual: $response\n"; $exitcode = 1; } @@ -176,6 +184,7 @@ sub do_line open my $test, "<", $ARGV[0] or die "Cannot open test script $ARGV[0] - $!"; while( my $line = <$test> ) { + $linenum++; $line =~ s/^\s+//; chomp $line; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 795, +/**/ 794, /**/ 793,