# HG changeset patch # User Christian Brabandt # Date 1502995504 -7200 # Node ID 69af108df70e0be818aba5dc44885c303861c031 # Parent dcab6d218e965dd9fbc8b8d5f2dc8c23d4175471 patch 8.0.0956: scrolling in a terminal window has flicker commit https://github.com/vim/vim/commit/cfce71710b6a2e1fb7f7f27d2a359e4b926f3af9 Author: Bram Moolenaar Date: Thu Aug 17 20:31:48 2017 +0200 patch 8.0.0956: scrolling in a terminal window has flicker Problem: Scrolling in a terminal hwindow as flicker when the Normal background differs from the terminal window background. Solution: Set the attribute to clear with. diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -2313,7 +2313,7 @@ msg_scroll_up(void) gui_undraw_cursor(); #endif /* scrolling up always works */ - screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); + screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL); if (!can_clear((char_u *)" ")) { @@ -2905,7 +2905,7 @@ do_more_prompt(int typed_char) } if (toscroll == -1 && screen_ins_lines(0, 0, 1, - (int)Rows, NULL) == OK) + (int)Rows, 0, NULL) == OK) { /* display line at top */ (void)disp_sb_line(0, mp); diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -1163,7 +1163,7 @@ curs_columns( if (extra > 0) win_ins_lines(curwin, 0, extra, FALSE, FALSE); else if (extra < 0) - win_del_lines(curwin, 0, -extra, FALSE, FALSE); + win_del_lines(curwin, 0, -extra, FALSE, FALSE, 0); } else curwin->w_skipcol = 0; diff --git a/src/proto/screen.pro b/src/proto/screen.pro --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -45,9 +45,9 @@ void screen_start(void); void windgoto(int row, int col); void setcursor(void); int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear); -int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear); -int screen_ins_lines(int off, int row, int line_count, int end, win_T *wp); -int screen_del_lines(int off, int row, int line_count, int end, int force, win_T *wp); +int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear, int clear_attr); +int screen_ins_lines(int off, int row, int line_count, int end, int clear_attr, win_T *wp); +int screen_del_lines(int off, int row, int line_count, int end, int force, int attr, win_T *wp); int showmode(void); void unshowmode(int force); void clearmode(void); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -151,13 +151,13 @@ static void screen_char(unsigned off, in static void screen_char_2(unsigned off, int row, int col); #endif static void screenclear2(void); -static void lineclear(unsigned off, int width); +static void lineclear(unsigned off, int width, int attr); static void lineinvalid(unsigned off, int width); #ifdef FEAT_WINDOWS static void linecopy(int to, int from, win_T *wp); static void redraw_block(int row, int end, win_T *wp); #endif -static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int del); +static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int del, int clear_attr); static void win_rest_invalid(win_T *wp); static void msg_pos_mode(void); static void recording_mode(int attr); @@ -609,7 +609,8 @@ update_screen(int type_arg) else if (type != CLEAR) { check_for_delay(FALSE); - if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, NULL) == FAIL) + if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, 0, NULL) + == FAIL) type = CLEAR; FOR_ALL_WINDOWS(wp) { @@ -1537,7 +1538,8 @@ win_update(win_T *wp) if (row > 0) { check_for_delay(FALSE); - if (win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK) + if (win_del_lines(wp, 0, row, FALSE, wp == firstwin, 0) + == OK) bot_start = wp->w_height - row; else mid_start = 0; /* redraw all lines */ @@ -2003,7 +2005,7 @@ win_update(win_T *wp) { check_for_delay(FALSE); if (win_del_lines(wp, row, - -xtra_rows, FALSE, FALSE) == FAIL) + -xtra_rows, FALSE, FALSE, 0) == FAIL) mod_bot = MAXLNUM; else bot_start = wp->w_height + xtra_rows; @@ -6773,7 +6775,7 @@ win_redr_status_matches( * no room, scroll the screen one line up. */ if (cmdline_row == Rows - 1) { - screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); + screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL); ++msg_scrolled; } else @@ -9074,7 +9076,7 @@ screenclear2(void) /* blank out ScreenLines */ for (i = 0; i < Rows; ++i) { - lineclear(LineOffset[i], (int)Columns); + lineclear(LineOffset[i], (int)Columns, 0); LineWraps[i] = FALSE; } @@ -9114,7 +9116,7 @@ screenclear2(void) * Clear one line in ScreenLines. */ static void -lineclear(unsigned off, int width) +lineclear(unsigned off, int width, int attr) { (void)vim_memset(ScreenLines + off, ' ', (size_t)width * sizeof(schar_T)); #ifdef FEAT_MBYTE @@ -9122,7 +9124,7 @@ lineclear(unsigned off, int width) (void)vim_memset(ScreenLinesUC + off, 0, (size_t)width * sizeof(u8char_T)); #endif - (void)vim_memset(ScreenAttrs + off, 0, (size_t)width * sizeof(sattr_T)); + (void)vim_memset(ScreenAttrs + off, attr, (size_t)width * sizeof(sattr_T)); } /* @@ -9508,7 +9510,7 @@ win_ins_lines( if (line_count > wp->w_height - row) line_count = wp->w_height - row; - retval = win_do_lines(wp, row, line_count, mayclear, FALSE); + retval = win_do_lines(wp, row, line_count, mayclear, FALSE, 0); if (retval != MAYBE) return retval; @@ -9523,7 +9525,7 @@ win_ins_lines( if (wp->w_next != NULL || wp->w_status_height) { if (screen_del_lines(0, W_WINROW(wp) + wp->w_height - line_count, - line_count, (int)Rows, FALSE, NULL) == OK) + line_count, (int)Rows, FALSE, 0, NULL) == OK) did_delete = TRUE; else if (wp->w_next) return FAIL; @@ -9547,7 +9549,7 @@ win_ins_lines( ' ', ' ', 0); } - if (screen_ins_lines(0, W_WINROW(wp) + row, line_count, (int)Rows, NULL) + if (screen_ins_lines(0, W_WINROW(wp) + row, line_count, (int)Rows, 0, NULL) == FAIL) { /* deletion will have messed up other windows */ @@ -9577,7 +9579,8 @@ win_del_lines( int row, int line_count, int invalid, - int mayclear) + int mayclear, + int clear_attr) /* for clearing lines */ { int retval; @@ -9587,12 +9590,12 @@ win_del_lines( if (line_count > wp->w_height - row) line_count = wp->w_height - row; - retval = win_do_lines(wp, row, line_count, mayclear, TRUE); + retval = win_do_lines(wp, row, line_count, mayclear, TRUE, clear_attr); if (retval != MAYBE) return retval; if (screen_del_lines(0, W_WINROW(wp) + row, line_count, - (int)Rows, FALSE, NULL) == FAIL) + (int)Rows, FALSE, clear_attr, NULL) == FAIL) return FAIL; #ifdef FEAT_WINDOWS @@ -9603,7 +9606,7 @@ win_del_lines( if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1) { if (screen_ins_lines(0, W_WINROW(wp) + wp->w_height - line_count, - line_count, (int)Rows, NULL) == FAIL) + line_count, (int)Rows, clear_attr, NULL) == FAIL) { wp->w_redr_status = TRUE; win_rest_invalid(wp->w_next); @@ -9630,7 +9633,8 @@ win_do_lines( int row, int line_count, int mayclear, - int del) + int del, + int clear_attr) { int retval; @@ -9694,10 +9698,10 @@ win_do_lines( scroll_region_set(wp, row); if (del) retval = screen_del_lines(W_WINROW(wp) + row, 0, line_count, - wp->w_height - row, FALSE, wp); + wp->w_height - row, FALSE, clear_attr, wp); else retval = screen_ins_lines(W_WINROW(wp) + row, 0, line_count, - wp->w_height - row, wp); + wp->w_height - row, clear_attr, wp); #ifdef FEAT_WINDOWS if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL)) #endif @@ -9771,6 +9775,7 @@ screen_ins_lines( int row, int line_count, int end, + int clear_attr, win_T *wp) /* NULL or window to use width from */ { int i; @@ -9851,7 +9856,7 @@ screen_ins_lines( */ if (type == USE_T_CD || type == USE_T_CDL || type == USE_T_CE || type == USE_T_DL) - return screen_del_lines(off, row, line_count, end, FALSE, wp); + return screen_del_lines(off, row, line_count, end, FALSE, 0, wp); /* * If text is retained below the screen, first clear or delete as many @@ -9859,7 +9864,7 @@ screen_ins_lines( * the deleted lines won't later surface during a screen_del_lines. */ if (*T_DB) - screen_del_lines(off, end - line_count, line_count, end, FALSE, wp); + screen_del_lines(off, end - line_count, line_count, end, FALSE, 0, wp); #ifdef FEAT_CLIPBOARD /* Remove a modeless selection when inserting lines halfway the screen @@ -9902,7 +9907,8 @@ screen_ins_lines( linecopy(j + line_count, j, wp); j += line_count; if (can_clear((char_u *)" ")) - lineclear(LineOffset[j] + wp->w_wincol, wp->w_width); + lineclear(LineOffset[j] + wp->w_wincol, wp->w_width, + clear_attr); else lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width); LineWraps[j] = FALSE; @@ -9920,7 +9926,7 @@ screen_ins_lines( LineOffset[j + line_count] = temp; LineWraps[j + line_count] = FALSE; if (can_clear((char_u *)" ")) - lineclear(temp, (int)Columns); + lineclear(temp, (int)Columns, clear_attr); else lineinvalid(temp, (int)Columns); } @@ -9928,6 +9934,8 @@ screen_ins_lines( screen_stop_highlight(); windgoto(cursor_row, 0); + if (clear_attr != 0) + screen_start_highlight(clear_attr); #ifdef FEAT_WINDOWS /* redraw the characters */ @@ -9993,6 +10001,7 @@ screen_del_lines( int line_count, int end, int force, /* even when line_count > p_ttyscroll */ + int clear_attr, /* used for clearing lines */ win_T *wp UNUSED) /* NULL or window to use width from */ { int j; @@ -10136,7 +10145,8 @@ screen_del_lines( linecopy(j - line_count, j, wp); j -= line_count; if (can_clear((char_u *)" ")) - lineclear(LineOffset[j] + wp->w_wincol, wp->w_width); + lineclear(LineOffset[j] + wp->w_wincol, wp->w_width, + clear_attr); else lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width); LineWraps[j] = FALSE; @@ -10155,13 +10165,16 @@ screen_del_lines( LineOffset[j - line_count] = temp; LineWraps[j - line_count] = FALSE; if (can_clear((char_u *)" ")) - lineclear(temp, (int)Columns); + lineclear(temp, (int)Columns, clear_attr); else lineinvalid(temp, (int)Columns); } } - screen_stop_highlight(); + if (screen_attr != clear_attr) + screen_stop_highlight(); + if (clear_attr != 0) + screen_start_highlight(clear_attr); #ifdef FEAT_WINDOWS /* redraw the characters */ diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -1483,6 +1483,169 @@ may_toggle_cursor(term_T *term) } } +/* + * Reverse engineer the RGB value into a cterm color index. + * First color is 1. Return 0 if no match found. + */ + static int +color2index(VTermColor *color, int fg, int *boldp) +{ + int red = color->red; + int blue = color->blue; + int green = color->green; + + /* The argument for lookup_color() is for the color_names[] table. */ + if (red == 0) + { + if (green == 0) + { + if (blue == 0) + return lookup_color(0, fg, boldp) + 1; /* black */ + if (blue == 224) + return lookup_color(1, fg, boldp) + 1; /* dark blue */ + } + else if (green == 224) + { + if (blue == 0) + return lookup_color(2, fg, boldp) + 1; /* dark green */ + if (blue == 224) + return lookup_color(3, fg, boldp) + 1; /* dark cyan */ + } + } + else if (red == 224) + { + if (green == 0) + { + if (blue == 0) + return lookup_color(4, fg, boldp) + 1; /* dark red */ + if (blue == 224) + return lookup_color(5, fg, boldp) + 1; /* dark magenta */ + } + else if (green == 224) + { + if (blue == 0) + return lookup_color(6, fg, boldp) + 1; /* dark yellow / brown */ + if (blue == 224) + return lookup_color(8, fg, boldp) + 1; /* white / light grey */ + } + } + else if (red == 128) + { + if (green == 128 && blue == 128) + return lookup_color(12, fg, boldp) + 1; /* high intensity black / dark grey */ + } + else if (red == 255) + { + if (green == 64) + { + if (blue == 64) + return lookup_color(20, fg, boldp) + 1; /* light red */ + if (blue == 255) + return lookup_color(22, fg, boldp) + 1; /* light magenta */ + } + else if (green == 255) + { + if (blue == 64) + return lookup_color(24, fg, boldp) + 1; /* yellow */ + if (blue == 255) + return lookup_color(26, fg, boldp) + 1; /* white */ + } + } + else if (red == 64) + { + if (green == 64) + { + if (blue == 255) + return lookup_color(14, fg, boldp) + 1; /* light blue */ + } + else if (green == 255) + { + if (blue == 64) + return lookup_color(16, fg, boldp) + 1; /* light green */ + if (blue == 255) + return lookup_color(18, fg, boldp) + 1; /* light cyan */ + } + } + if (t_colors >= 256) + { + if (red == blue && red == green) + { + /* 24-color greyscale */ + static int cutoff[23] = { + 0x05, 0x10, 0x1B, 0x26, 0x31, 0x3C, 0x47, 0x52, + 0x5D, 0x68, 0x73, 0x7F, 0x8A, 0x95, 0xA0, 0xAB, + 0xB6, 0xC1, 0xCC, 0xD7, 0xE2, 0xED, 0xF9}; + int i; + + for (i = 0; i < 23; ++i) + if (red < cutoff[i]) + return i + 233; + return 256; + } + + /* 216-color cube */ + return 17 + ((red + 25) / 0x33) * 36 + + ((green + 25) / 0x33) * 6 + + (blue + 25) / 0x33; + } + return 0; +} + +/* + * Convert the attributes of a vterm cell into an attribute index. + */ + static int +cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg) +{ + int attr = 0; + + if (cellattrs.bold) + attr |= HL_BOLD; + if (cellattrs.underline) + attr |= HL_UNDERLINE; + if (cellattrs.italic) + attr |= HL_ITALIC; + if (cellattrs.strike) + attr |= HL_STANDOUT; + if (cellattrs.reverse) + attr |= HL_INVERSE; + +#ifdef FEAT_GUI + if (gui.in_use) + { + guicolor_T fg, bg; + + fg = gui_mch_get_rgb_color(cellfg.red, cellfg.green, cellfg.blue); + bg = gui_mch_get_rgb_color(cellbg.red, cellbg.green, cellbg.blue); + return get_gui_attr_idx(attr, fg, bg); + } + else +#endif +#ifdef FEAT_TERMGUICOLORS + if (p_tgc) + { + guicolor_T fg, bg; + + fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, cellfg.blue); + bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, cellbg.blue); + + return get_tgc_attr_idx(attr, fg, bg); + } + else +#endif + { + int bold = MAYBE; + int fg = color2index(&cellfg, TRUE, &bold); + int bg = color2index(&cellbg, FALSE, &bold); + + /* with 8 colors set the bold attribute to get a bright foreground */ + if (bold == TRUE) + attr |= HL_BOLD; + return get_cterm_attr_idx(attr, fg, bg); + } + return 0; +} + static int handle_damage(VTermRect rect, void *user) { @@ -1498,18 +1661,32 @@ handle_damage(VTermRect rect, void *user handle_moverect(VTermRect dest, VTermRect src, void *user) { term_T *term = (term_T *)user; - win_T *wp; - + + /* Scrolling up is done much more efficiently by deleting lines instead of + * redrawing the text. */ if (dest.start_col == src.start_col && dest.end_col == src.end_col && dest.start_row < src.start_row) + { + win_T *wp; + VTermColor fg, bg; + VTermScreenCellAttrs attr; + int clear_attr; + + /* Set the color to clear lines with. */ + vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), + &fg, &bg); + vim_memset(&attr, 0, sizeof(attr)); + clear_attr = cell2attr(attr, fg, bg); + FOR_ALL_WINDOWS(wp) { if (wp->w_buffer == term->tl_buffer) - /* scrolling up is much more efficient when deleting lines */ win_del_lines(wp, dest.start_row, - src.start_row - dest.start_row, FALSE, FALSE); + src.start_row - dest.start_row, FALSE, FALSE, + clear_attr); } + } redraw_buf_later(term->tl_buffer, NOT_VALID); return 1; } @@ -1774,169 +1951,6 @@ term_channel_closed(channel_T *ch) } /* - * Reverse engineer the RGB value into a cterm color index. - * First color is 1. Return 0 if no match found. - */ - static int -color2index(VTermColor *color, int fg, int *boldp) -{ - int red = color->red; - int blue = color->blue; - int green = color->green; - - /* The argument for lookup_color() is for the color_names[] table. */ - if (red == 0) - { - if (green == 0) - { - if (blue == 0) - return lookup_color(0, fg, boldp) + 1; /* black */ - if (blue == 224) - return lookup_color(1, fg, boldp) + 1; /* dark blue */ - } - else if (green == 224) - { - if (blue == 0) - return lookup_color(2, fg, boldp) + 1; /* dark green */ - if (blue == 224) - return lookup_color(3, fg, boldp) + 1; /* dark cyan */ - } - } - else if (red == 224) - { - if (green == 0) - { - if (blue == 0) - return lookup_color(4, fg, boldp) + 1; /* dark red */ - if (blue == 224) - return lookup_color(5, fg, boldp) + 1; /* dark magenta */ - } - else if (green == 224) - { - if (blue == 0) - return lookup_color(6, fg, boldp) + 1; /* dark yellow / brown */ - if (blue == 224) - return lookup_color(8, fg, boldp) + 1; /* white / light grey */ - } - } - else if (red == 128) - { - if (green == 128 && blue == 128) - return lookup_color(12, fg, boldp) + 1; /* high intensity black / dark grey */ - } - else if (red == 255) - { - if (green == 64) - { - if (blue == 64) - return lookup_color(20, fg, boldp) + 1; /* light red */ - if (blue == 255) - return lookup_color(22, fg, boldp) + 1; /* light magenta */ - } - else if (green == 255) - { - if (blue == 64) - return lookup_color(24, fg, boldp) + 1; /* yellow */ - if (blue == 255) - return lookup_color(26, fg, boldp) + 1; /* white */ - } - } - else if (red == 64) - { - if (green == 64) - { - if (blue == 255) - return lookup_color(14, fg, boldp) + 1; /* light blue */ - } - else if (green == 255) - { - if (blue == 64) - return lookup_color(16, fg, boldp) + 1; /* light green */ - if (blue == 255) - return lookup_color(18, fg, boldp) + 1; /* light cyan */ - } - } - if (t_colors >= 256) - { - if (red == blue && red == green) - { - /* 24-color greyscale */ - static int cutoff[23] = { - 0x05, 0x10, 0x1B, 0x26, 0x31, 0x3C, 0x47, 0x52, - 0x5D, 0x68, 0x73, 0x7F, 0x8A, 0x95, 0xA0, 0xAB, - 0xB6, 0xC1, 0xCC, 0xD7, 0xE2, 0xED, 0xF9}; - int i; - - for (i = 0; i < 23; ++i) - if (red < cutoff[i]) - return i + 233; - return 256; - } - - /* 216-color cube */ - return 17 + ((red + 25) / 0x33) * 36 - + ((green + 25) / 0x33) * 6 - + (blue + 25) / 0x33; - } - return 0; -} - -/* - * Convert the attributes of a vterm cell into an attribute index. - */ - static int -cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg) -{ - int attr = 0; - - if (cellattrs.bold) - attr |= HL_BOLD; - if (cellattrs.underline) - attr |= HL_UNDERLINE; - if (cellattrs.italic) - attr |= HL_ITALIC; - if (cellattrs.strike) - attr |= HL_STANDOUT; - if (cellattrs.reverse) - attr |= HL_INVERSE; - -#ifdef FEAT_GUI - if (gui.in_use) - { - guicolor_T fg, bg; - - fg = gui_mch_get_rgb_color(cellfg.red, cellfg.green, cellfg.blue); - bg = gui_mch_get_rgb_color(cellbg.red, cellbg.green, cellbg.blue); - return get_gui_attr_idx(attr, fg, bg); - } - else -#endif -#ifdef FEAT_TERMGUICOLORS - if (p_tgc) - { - guicolor_T fg, bg; - - fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, cellfg.blue); - bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, cellbg.blue); - - return get_tgc_attr_idx(attr, fg, bg); - } - else -#endif - { - int bold = MAYBE; - int fg = color2index(&cellfg, TRUE, &bold); - int bg = color2index(&cellbg, FALSE, &bold); - - /* with 8 colors set the bold attribute to get a bright foreground */ - if (bold == TRUE) - attr |= HL_BOLD; - return get_cterm_attr_idx(attr, fg, bg); - } - return 0; -} - -/* * Called to update a window that contains an active terminal. * Returns FAIL when there is no terminal running in this window or in * Terminal-Normal mode. diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 956, +/**/ 955, /**/ 954,