To: vim_dev@googlegroups.com Subject: Patch 8.2.0794 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0794 Problem: Libvterm code lags behind the upstream version. Solution: Include revisions 743 - 747. Files: src/libvterm/src/state.c, src/libvterm/src/screen.c, src/libvterm/src/vterm_internal.h, src/libvterm/include/vterm.h, src/libvterm/t/67screen_dbl_wh.test, src/libvterm/t/run-test.pl *** ../vim-8.2.0793/src/libvterm/src/state.c 2020-05-17 21:50:11.954655960 +0200 --- src/libvterm/src/state.c 2020-05-18 21:04:09.747822993 +0200 *************** *** 73,85 **** state->bold_is_highbright = 0; 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->combine_chars); vterm_allocator_free(state->vt, state); } --- 73,99 ---- 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->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,120 **** // 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); ! if(downward > 0) memmove(state->lineinfo + rect.start_row, state->lineinfo + rect.start_row + downward, height * sizeof(state->lineinfo[0])); ! else memmove(state->lineinfo + rect.start_row - downward, state->lineinfo + rect.start_row, height * sizeof(state->lineinfo[0])); } if(state->callbacks && state->callbacks->scrollrect) --- 120,141 ---- // 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) { 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 }; ! } ! 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,1707 **** { VTermState *state = user; VTermPos oldpos = state->pos; ! VTermPos delta = { 0, 0 }; if(cols != state->cols) { int col; --- 1722,1728 ---- { VTermState *state = user; VTermPos oldpos = state->pos; ! VTermStateFields fields; if(cols != state->cols) { int col; *************** *** 1731,1752 **** } if(rows != state->rows) { ! int row; ! VTermLineInfo *newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo)); ! if (newlineinfo == NULL) ! return 0; ! for(row = 0; row < state->rows && row < rows; row++) { ! newlineinfo[row] = state->lineinfo[row]; ! } ! for( ; row < rows; row++) { ! newlineinfo[row].doublewidth = 0; ! newlineinfo[row].doubleheight = 0; } ! vterm_allocator_free(state->vt, state->lineinfo); ! state->lineinfo = newlineinfo; } state->rows = rows; --- 1752,1780 ---- } if(rows != state->rows) { ! 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] = oldlineinfo[row]; ! } ! ! for( ; row < rows; row++) { ! newlineinfo[row] = (VTermLineInfo){ ! .doublewidth = 0, ! }; ! } ! vterm_allocator_free(state->vt, state->lineinfos[bufidx]); ! state->lineinfos[bufidx] = newlineinfo; } ! state->lineinfo = state->lineinfos[state->mode.alt_screen ? BUFIDX_ALTSCREEN : BUFIDX_PRIMARY]; } state->rows = rows; *************** *** 1757,1773 **** if(state->scrollregion_right > -1) UBOUND(state->scrollregion_right, state->cols); if(state->callbacks && state->callbacks->resize) ! (*state->callbacks->resize)(rows, cols, &delta, state->cbdata); 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) --- 1785,1802 ---- 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, &fields, state->cbdata); ! ! state->pos = fields.pos; if(state->at_phantom && state->pos.col < cols-1) { state->at_phantom = 0; state->pos.col++; } if(state->pos.row >= rows) state->pos.row = rows - 1; if(state->pos.col >= cols) *************** *** 1803,1819 **** 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; --- 1832,1837 ---- *************** *** 1976,1981 **** --- 1994,2002 ---- 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; *** ../vim-8.2.0793/src/libvterm/src/screen.c 2020-05-17 23:00:48.782969093 +0200 --- src/libvterm/src/screen.c 2020-05-18 20:58:33.872732161 +0200 *************** *** 56,63 **** 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 --- 56,61 ---- *************** *** 481,487 **** return 0; } ! static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new_cols, int active, VTermPos *delta) { int old_rows = screen->rows; int old_cols = screen->cols; --- 479,485 ---- return 0; } ! 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,531 **** int row; for(row = 0; row <= old_row; row++) sb_pushline_from_row(screen, row); ! if(delta) ! delta->row -= (old_row + 1); } if(new_row >= 0 && bufidx == BUFIDX_PRIMARY && screen->callbacks && screen->callbacks->sb_popline) { --- 522,529 ---- int row; for(row = 0; row <= old_row; row++) sb_pushline_from_row(screen, row); ! if(active) ! statefields->pos.row -= (old_row + 1); } if(new_row >= 0 && bufidx == BUFIDX_PRIMARY && screen->callbacks && screen->callbacks->sb_popline) { *************** *** 563,570 **** } new_row--; ! if(delta) ! delta->row++; } } --- 561,568 ---- } new_row--; ! if(active) ! statefields->pos.row++; } } *************** *** 590,596 **** */ } ! static int resize(int new_rows, int new_cols, VTermPos *delta, void *user) { VTermScreen *screen = user; --- 588,594 ---- */ } ! static int resize(int new_rows, int new_cols, VTermStateFields *fields, void *user) { VTermScreen *screen = user; *************** *** 606,614 **** 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); if(screen->buffers[BUFIDX_ALTSCREEN]) ! resize_buffer(screen, 1, new_rows, new_cols, altscreen_active, altscreen_active ? delta : NULL); screen->buffer = altscreen_active ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY]; --- 604,612 ---- screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * new_cols); } ! 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, fields); screen->buffer = altscreen_active ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY]; *** ../vim-8.2.0793/src/libvterm/src/vterm_internal.h 2020-05-17 21:50:11.954655960 +0200 --- src/libvterm/src/vterm_internal.h 2020-05-18 20:49:20.050168168 +0200 *************** *** 32,37 **** --- 32,40 ---- #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,97 **** --- 95,104 ---- // 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) *** ../vim-8.2.0793/src/libvterm/include/vterm.h 2020-05-17 22:27:36.728262245 +0200 --- src/libvterm/include/vterm.h 2020-05-18 21:05:45.327553399 +0200 *************** *** 268,273 **** --- 268,282 ---- // 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,286 **** // 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 (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user); } VTermStateCallbacks; --- 289,295 ---- // was accepted, 0 otherwise. int (*settermprop)(VTermProp prop, VTermValue *val, void *user); int (*bell)(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; *** ../vim-8.2.0793/src/libvterm/t/67screen_dbl_wh.test 2020-05-17 16:28:47.087869402 +0200 --- src/libvterm/t/67screen_dbl_wh.test 2020-05-18 21:03:12.755981839 +0200 *************** *** 30,32 **** --- 30,38 ---- ?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) *** ../vim-8.2.0793/src/libvterm/t/run-test.pl 2020-05-17 22:27:36.728262245 +0200 --- src/libvterm/t/run-test.pl 2020-05-18 21:11:03.134635839 +0200 *************** *** 140,153 **** } } # Assertions start with '?' ! 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; if( $response ne $line ) { print "# Assert $assertion failed:\n" . --- 140,153 ---- } } # Assertions start with '?' ! 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; $response =~ s/^\s+|\s+$//g; if( $response ne $line ) { print "# Assert $assertion failed:\n" . *** ../vim-8.2.0793/src/version.c 2020-05-18 20:16:56.617319687 +0200 --- src/version.c 2020-05-18 20:45:11.442967633 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 794, /**/ -- hundred-and-one symptoms of being an internet addict: 132. You come back and check this list every half-hour. /// 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 ///