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
index 62e6bfe..57f33dd 100644
--- a/src/message.c
+++ b/src/message.c
@@ -2313,7 +2313,7 @@
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 @@
}
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
index f058b73..a5ba011 100644
--- a/src/move.c
+++ b/src/move.c
@@ -1163,7 +1163,7 @@
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
index d560b7e..4e89293 100644
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -45,9 +45,9 @@
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
index 55440f4..54ba957 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -151,13 +151,13 @@
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 @@
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 @@
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 @@
{
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 @@
* 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 @@
/* 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 @@
* 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 @@
(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 @@
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 @@
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 @@
' ', ' ', 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 @@
int row,
int line_count,
int invalid,
- int mayclear)
+ int mayclear,
+ int clear_attr) /* for clearing lines */
{
int retval;
@@ -9587,12 +9590,12 @@
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 @@
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 @@
int row,
int line_count,
int mayclear,
- int del)
+ int del,
+ int clear_attr)
{
int retval;
@@ -9694,10 +9698,10 @@
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 @@
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 @@
*/
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 @@
* 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 @@
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 @@
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_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 @@
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 @@
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 @@
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
index 304a7ba..5878db7 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -1483,6 +1483,169 @@
}
}
+/*
+ * 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_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 @@
}
/*
- * 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
index 9859b4a..f02af88 100644
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 956,
+/**/
955,
/**/
954,