changeset 20482:dc88c690f19b v8.2.0795

patch 8.2.0795: libvterm code lags behind the upstream version Commit: https://github.com/vim/vim/commit/88d68de95da70d0f89a5246f58355d72e9c17db4 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Mon, 18 May 2020 22:00:03 +0200
parents ee70957e66ea
children 2949e5d9481f
files src/libvterm/include/vterm.h src/libvterm/src/screen.c src/libvterm/src/state.c src/libvterm/t/32state_flow.test src/libvterm/t/60screen_ascii.test src/libvterm/t/62screen_damage.test src/libvterm/t/63screen_resize.test src/libvterm/t/harness.c src/libvterm/t/run-test.pl src/version.c
diffstat 10 files changed, 153 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- 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 {
--- 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);
--- 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};
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 =
--- 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"
--- 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"
--- 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"
--- 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;
--- 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;
 
--- 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,