changeset 20480:d0bf39eb2b07 v8.2.0794

patch 8.2.0794: libvterm code lags behind the upstream version Commit: https://github.com/vim/vim/commit/d098b824c10cc20dc55e18c22c4991f61826006e Author: Bram Moolenaar <Bram@vim.org> Date: Mon May 18 21:12:59 2020 +0200 patch 8.2.0794: libvterm code lags behind the upstream version Problem: Libvterm code lags behind the upstream version. Solution: Include revisions 743 - 747.
author Bram Moolenaar <Bram@vim.org>
date Mon, 18 May 2020 21:15:04 +0200
parents c4b13b8932fb
children ee70957e66ea
files src/libvterm/include/vterm.h src/libvterm/src/screen.c src/libvterm/src/state.c src/libvterm/src/vterm_internal.h src/libvterm/t/67screen_dbl_wh.test src/libvterm/t/run-test.pl src/version.c
diffstat 7 files changed, 88 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/libvterm/include/vterm.h
+++ b/src/libvterm/include/vterm.h
@@ -268,6 +268,15 @@ void *vterm_parser_get_cbdata(VTerm *vt)
 // State layer
 // -----------
 
+/* Copies of VTermState fields that the 'resize' callback might have reason to
+ * edit. 'resize' callback gets total control of these fields and may
+ * free-and-reallocate them if required. They will be copied back from the
+ * struct after the callback has returned.
+ */
+typedef struct {
+  VTermPos pos;                /* current cursor position */
+} VTermStateFields;
+
 typedef struct {
   int (*putglyph)(VTermGlyphInfo *info, VTermPos pos, void *user);
   int (*movecursor)(VTermPos pos, VTermPos oldpos, int visible, void *user);
@@ -280,7 +289,7 @@ typedef struct {
   // was accepted, 0 otherwise.
   int (*settermprop)(VTermProp prop, VTermValue *val, void *user);
   int (*bell)(void *user);
-  int (*resize)(int rows, int cols, VTermPos *delta, void *user);
+  int (*resize)(int rows, int cols, VTermStateFields *fields, void *user);
   int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user);
 } VTermStateCallbacks;
 
--- a/src/libvterm/src/screen.c
+++ b/src/libvterm/src/screen.c
@@ -56,8 +56,6 @@ struct VTermScreen
   int global_reverse;
 
   // Primary and Altscreen. buffers[1] is lazily allocated as needed
-#define BUFIDX_PRIMARY   0
-#define BUFIDX_ALTSCREEN 1
   ScreenCell *buffers[2];
 
   // buffer will == buffers[0] or buffers[1], depending on altscreen
@@ -481,7 +479,7 @@ static int bell(void *user)
   return 0;
 }
 
-static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new_cols, int active, VTermPos *delta)
+static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new_cols, int active, VTermStateFields *statefields)
 {
   int old_rows = screen->rows;
   int old_cols = screen->cols;
@@ -524,8 +522,8 @@ found_oldrow:
     int row;
     for(row = 0; row <= old_row; row++)
       sb_pushline_from_row(screen, row);
-    if(delta)
-      delta->row -= (old_row + 1);
+    if(active)
+      statefields->pos.row -= (old_row + 1);
   }
   if(new_row >= 0 && bufidx == BUFIDX_PRIMARY &&
       screen->callbacks && screen->callbacks->sb_popline) {
@@ -563,8 +561,8 @@ found_oldrow:
       }
       new_row--;
 
-      if(delta)
-        delta->row++;
+      if(active)
+        statefields->pos.row++;
     }
   }
 
@@ -590,7 +588,7 @@ found_oldrow:
    */
 }
 
-static int resize(int new_rows, int new_cols, VTermPos *delta, void *user)
+static int resize(int new_rows, int new_cols, VTermStateFields *fields, void *user)
 {
   VTermScreen *screen = user;
 
@@ -606,9 +604,9 @@ static int resize(int new_rows, int new_
     screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * new_cols);
   }
 
-  resize_buffer(screen, 0, new_rows, new_cols, !altscreen_active, altscreen_active ? NULL : delta);
+  resize_buffer(screen, 0, new_rows, new_cols, !altscreen_active, fields);
   if(screen->buffers[BUFIDX_ALTSCREEN])
-    resize_buffer(screen, 1, new_rows, new_cols, altscreen_active, altscreen_active ? delta : NULL);
+    resize_buffer(screen, 1, new_rows, new_cols, altscreen_active, fields);
 
   screen->buffer = altscreen_active ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY];
 
--- a/src/libvterm/src/state.c
+++ b/src/libvterm/src/state.c
@@ -73,13 +73,27 @@ static VTermState *vterm_state_new(VTerm
 
   state->bold_is_highbright = 0;
 
+  state->combine_chars_size = 16;
+  state->combine_chars = vterm_allocator_malloc(state->vt, state->combine_chars_size * sizeof(state->combine_chars[0]));
+
+  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->lineinfo = state->lineinfos[BUFIDX_PRIMARY];
+
+  state->encoding_utf8.enc = vterm_lookup_encoding(ENC_UTF8, 'u');
+  if(*state->encoding_utf8.enc->init)
+    (*state->encoding_utf8.enc->init)(state->encoding_utf8.enc, state->encoding_utf8.data);
+
   return state;
 }
 
 INTERNAL void vterm_state_free(VTermState *state)
 {
   vterm_allocator_free(state->vt, state->tabstops);
-  vterm_allocator_free(state->vt, state->lineinfo);
+  vterm_allocator_free(state->vt, state->lineinfos[BUFIDX_PRIMARY]);
+  if(state->lineinfos[BUFIDX_ALTSCREEN])
+    vterm_allocator_free(state->vt, state->lineinfos[BUFIDX_ALTSCREEN]);
   vterm_allocator_free(state->vt, state->combine_chars);
   vterm_allocator_free(state->vt, state);
 }
@@ -106,15 +120,22 @@ static void scroll(VTermState *state, VT
   // Update lineinfo if full line
   if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
     int height = rect.end_row - rect.start_row - abs(downward);
+    int row;
 
-    if(downward > 0)
+    if(downward > 0) {
       memmove(state->lineinfo + rect.start_row,
               state->lineinfo + rect.start_row + downward,
               height * sizeof(state->lineinfo[0]));
-    else
+      for(row = rect.end_row - downward; row < rect.end_row; row++)
+        state->lineinfo[row] = (VTermLineInfo){ 0 };
+    }
+    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 };
+    }
   }
 
   if(state->callbacks && state->callbacks->scrollrect)
@@ -1701,7 +1722,7 @@ static int on_resize(int rows, int cols,
 {
   VTermState *state = user;
   VTermPos oldpos = state->pos;
-  VTermPos delta = { 0, 0 };
+  VTermStateFields fields;
 
   if(cols != state->cols) {
     int col;
@@ -1731,22 +1752,29 @@ static int on_resize(int rows, int cols,
   }
 
   if(rows != state->rows) {
-    int row;
-    VTermLineInfo *newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo));
-    if (newlineinfo == NULL)
-      return 0;
+    for(int bufidx = BUFIDX_PRIMARY; bufidx <= BUFIDX_ALTSCREEN; bufidx++) {
+      int row;
+      VTermLineInfo *oldlineinfo = state->lineinfos[bufidx];
+      if(!oldlineinfo)
+        continue;
+
+      VTermLineInfo *newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo));
 
-    for(row = 0; row < state->rows && row < rows; row++) {
-      newlineinfo[row] = state->lineinfo[row];
+      for(row = 0; row < state->rows && row < rows; row++) {
+        newlineinfo[row] = oldlineinfo[row];
+      }
+
+      for( ; row < rows; row++) {
+        newlineinfo[row] = (VTermLineInfo){
+          .doublewidth = 0,
+        };
+      }
+
+      vterm_allocator_free(state->vt, state->lineinfos[bufidx]);
+      state->lineinfos[bufidx] = newlineinfo;
     }
 
-    for( ; row < rows; row++) {
-      newlineinfo[row].doublewidth = 0;
-      newlineinfo[row].doubleheight = 0;
-    }
-
-    vterm_allocator_free(state->vt, state->lineinfo);
-    state->lineinfo = newlineinfo;
+    state->lineinfo = state->lineinfos[state->mode.alt_screen ? BUFIDX_ALTSCREEN : BUFIDX_PRIMARY];
   }
 
   state->rows = rows;
@@ -1757,17 +1785,18 @@ static int on_resize(int rows, int cols,
   if(state->scrollregion_right > -1)
     UBOUND(state->scrollregion_right, state->cols);
 
+  fields.pos = state->pos;
+
   if(state->callbacks && state->callbacks->resize)
-    (*state->callbacks->resize)(rows, cols, &delta, state->cbdata);
+    (*state->callbacks->resize)(rows, cols, &fields, state->cbdata);
+
+  state->pos = fields.pos;
 
   if(state->at_phantom && state->pos.col < cols-1) {
     state->at_phantom = 0;
     state->pos.col++;
   }
 
-  state->pos.row += delta.row;
-  state->pos.col += delta.col;
-
   if(state->pos.row >= rows)
     state->pos.row = rows - 1;
   if(state->pos.col >= cols)
@@ -1803,17 +1832,6 @@ VTermState *vterm_obtain_state(VTerm *vt
     return NULL;
   vt->state = state;
 
-  state->combine_chars_size = 16;
-  state->combine_chars = vterm_allocator_malloc(state->vt, state->combine_chars_size * sizeof(state->combine_chars[0]));
-
-  state->tabstops = vterm_allocator_malloc(state->vt, (state->cols + 7) / 8);
-
-  state->lineinfo = vterm_allocator_malloc(state->vt, state->rows * sizeof(VTermLineInfo));
-
-  state->encoding_utf8.enc = vterm_lookup_encoding(ENC_UTF8, 'u');
-  if(*state->encoding_utf8.enc->init != NULL)
-    (*state->encoding_utf8.enc->init)(state->encoding_utf8.enc, state->encoding_utf8.data);
-
   vterm_parser_set_callbacks(vt, &parser_callbacks, state);
 
   return state;
@@ -1976,6 +1994,9 @@ 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};
       rect.end_row = state->rows;
--- a/src/libvterm/src/vterm_internal.h
+++ b/src/libvterm/src/vterm_internal.h
@@ -32,6 +32,9 @@
 #define CSI_ARGS_MAX 16
 #define CSI_LEADER_MAX 16
 
+#define BUFIDX_PRIMARY   0
+#define BUFIDX_ALTSCREEN 1
+
 typedef struct VTermEncoding VTermEncoding;
 
 typedef struct {
@@ -92,6 +95,10 @@ struct VTermState
   // Bitvector of tab stops
   unsigned char *tabstops;
 
+  /* Primary and Altscreen; lineinfos[1] is lazily allocated as needed */
+  VTermLineInfo *lineinfos[2];
+
+  /* lineinfo will == lineinfos[0] or lineinfos[1], depending on altscreen */
   VTermLineInfo *lineinfo;
 #define ROWWIDTH(state,row) ((state)->lineinfo[(row)].doublewidth ? ((state)->cols / 2) : (state)->cols)
 #define THISROWWIDTH(state) ROWWIDTH(state, (state)->pos.row)
--- a/src/libvterm/t/67screen_dbl_wh.test
+++ b/src/libvterm/t/67screen_dbl_wh.test
@@ -30,3 +30,9 @@ PUSH "abcde"
   ?screen_cell 0,0 = {0x61} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
 PUSH "\e#6"
   ?screen_cell 0,0 = {0x61} width=1 attrs={} dwl fg=rgb(240,240,240) bg=rgb(0,0,0)
+
+!DWL doesn't spill over on scroll
+RESET
+PUSH "\e[25H\e#6Final\r\n"
+  ?screen_cell 23,0 = {0x46} width=1 attrs={} dwl fg=rgb(240,240,240) bg=rgb(0,0,0)
+  ?screen_cell 24,0 = {} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
--- a/src/libvterm/t/run-test.pl
+++ b/src/libvterm/t/run-test.pl
@@ -140,14 +140,14 @@ sub do_line
       }
    }
    # Assertions start with '?'
-   elsif( $line =~ s/^\?([a-z]+.*?=)\s+// ) {
+   elsif( $line =~ s/^\?([a-z]+.*?=)\s*// ) {
       do_onetest if defined $command;
 
       my ( $assertion ) = $1 =~ m/^(.*)\s+=/;
 
       $hin->print( "\?$assertion\n" );
       my $response = <$hout>; defined $response or wait, die "Test harness failed - $?\n";
-      chomp $response;
+      chomp $response; $response =~ s/^\s+|\s+$//g;
 
       if( $response ne $line ) {
          print "# Assert $assertion failed:\n" .
--- 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 */
 /**/
+    794,
+/**/
     793,
 /**/
     792,