Merge pull request #25395 from bfredl/line_buf2

refactor(grid): unify the two put-text-on-the-screen code paths
This commit is contained in:
bfredl 2023-09-29 17:54:05 +02:00 committed by GitHub
commit dd872cbb44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 201 additions and 247 deletions

View File

@ -608,7 +608,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
grid_line_fill(clen, Columns, fillchar, attr);
grid_line_flush(false);
grid_line_flush();
}
win_redraw_last_status(topframe);

View File

@ -1825,7 +1825,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|| (number_only && wlv.draw_state > WL_STC))
&& wlv.filler_todo <= 0) {
draw_virt_text(wp, buf, win_col_offset, &wlv.col, wp->w_p_rl ? -1 : grid->cols, wlv.row);
grid_put_linebuf(grid, wlv.row, 0, wlv.col, -grid->cols, wp->w_p_rl, wp, bg_attr, false);
win_put_linebuf(wp, wlv.row, 0, wlv.col, -grid->cols, bg_attr, false);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
if (wp->w_p_cuc) {
@ -2956,7 +2956,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wp->w_p_rl ? -1 : grid->cols, 0, wp->w_p_rl);
}
draw_virt_text(wp, buf, win_col_offset, &wlv.col, wp->w_p_rl ? -1 : grid->cols, wlv.row);
grid_put_linebuf(grid, wlv.row, 0, wlv.col, grid->cols, wp->w_p_rl, wp, bg_attr, false);
win_put_linebuf(wp, wlv.row, 0, wlv.col, grid->cols, bg_attr, false);
wlv.row++;
// Update w_cline_height and w_cline_folded if the cursor line was
@ -3229,7 +3229,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
draw_virt_text(wp, buf, win_col_offset, &draw_col, wp->w_p_rl ? -1 : grid->cols, wlv.row);
}
grid_put_linebuf(grid, wlv.row, 0, draw_col, grid->cols, wp->w_p_rl, wp, bg_attr, wrap);
win_put_linebuf(wp, wlv.row, 0, draw_col, grid->cols, bg_attr, wrap);
if (wrap) {
ScreenGrid *current_grid = grid;
int current_row = wlv.row, dummy_col = 0; // dummy_col unused
@ -3297,3 +3297,37 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
xfree(wlv.saved_p_extra_free);
return wlv.row;
}
static void win_put_linebuf(win_T *wp, int row, int coloff, int endcol, int clear_width,
int bg_attr, bool wrap)
{
ScreenGrid *grid = &wp->w_grid;
// Take care of putting "<<<" on the first line for 'smoothscroll'.
if (row == 0 && wp->w_skipcol > 0
// do not overwrite the 'showbreak' text with "<<<"
&& *get_showbreak_value(wp) == NUL
// do not overwrite the 'listchars' "precedes" text with "<<<"
&& !(wp->w_p_list && wp->w_p_lcs_chars.prec != 0)) {
int off = 0;
if (wp->w_p_nu && wp->w_p_rnu) {
// do not overwrite the line number, change "123 text" to "123<<<xt".
while (off < grid->cols && ascii_isdigit(schar_get_ascii(linebuf_char[off]))) {
off++;
}
}
for (int i = 0; i < 3 && off < grid->cols; i++) {
if (off + 1 < grid->cols && linebuf_char[off + 1] == NUL) {
// When the first half of a double-width character is
// overwritten, change the second half to a space.
linebuf_char[off + 1] = schar_from_ascii(' ');
}
linebuf_char[off] = schar_from_ascii('<');
linebuf_attr[off] = HL_ATTR(HLF_AT);
off++;
}
}
grid_put_linebuf(grid, row, coloff, 0, endcol, clear_width, wp->w_p_rl, bg_attr, wrap, false);
}

View File

@ -771,20 +771,20 @@ static void win_redr_border(win_T *wp)
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
}
grid_line_flush(false);
grid_line_flush();
}
for (int i = 0; i < irow; i++) {
if (adj[3]) {
grid_line_start(grid, i + adj[0]);
grid_line_put_schar(0, chars[7], attrs[7]);
grid_line_flush(false);
grid_line_flush();
}
if (adj[1]) {
int ic = (i == 0 && !adj[0] && chars[2]) ? 2 : 3;
grid_line_start(grid, i + adj[0]);
grid_line_put_schar(icol + adj[3], chars[ic], attrs[ic]);
grid_line_flush(false);
grid_line_flush();
}
}
@ -807,7 +807,7 @@ static void win_redr_border(win_T *wp)
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
}
grid_line_flush(false);
grid_line_flush();
}
}
@ -1098,7 +1098,7 @@ int showmode(void)
&& !(p_ch == 0 && !ui_has(kUIMessages))) {
grid_line_start(&msg_grid_adj, Rows - 1);
win_redr_ruler(ruler_win);
grid_line_flush(false);
grid_line_flush();
}
redraw_cmdline = false;
@ -1370,25 +1370,25 @@ static void draw_sep_connectors_win(win_T *wp)
bool bot_left = !(win_at_bottom || win_at_left);
bool bot_right = !(win_at_bottom || win_at_right);
if (top_left || top_right) {
if (top_left) {
grid_line_start(&default_grid, wp->w_winrow - 1);
if (top_left) {
grid_line_put_schar(wp->w_wincol - 1, get_corner_sep_connector(wp, WC_TOP_LEFT), hl);
}
if (top_right) {
grid_line_put_schar(W_ENDCOL(wp), get_corner_sep_connector(wp, WC_TOP_RIGHT), hl);
}
grid_line_flush(false);
grid_line_put_schar(wp->w_wincol - 1, get_corner_sep_connector(wp, WC_TOP_LEFT), hl);
grid_line_flush();
}
if (bot_left || bot_right) {
if (top_right) {
grid_line_start(&default_grid, wp->w_winrow - 1);
grid_line_put_schar(W_ENDCOL(wp), get_corner_sep_connector(wp, WC_TOP_RIGHT), hl);
grid_line_flush();
}
if (bot_left) {
grid_line_start(&default_grid, W_ENDROW(wp));
if (bot_left) {
grid_line_put_schar(wp->w_wincol - 1, get_corner_sep_connector(wp, WC_BOTTOM_LEFT), hl);
}
if (bot_right) {
grid_line_put_schar(W_ENDCOL(wp), get_corner_sep_connector(wp, WC_BOTTOM_RIGHT), hl);
}
grid_line_flush(false);
grid_line_put_schar(wp->w_wincol - 1, get_corner_sep_connector(wp, WC_BOTTOM_LEFT), hl);
grid_line_flush();
}
if (bot_right) {
grid_line_start(&default_grid, W_ENDROW(wp));
grid_line_put_schar(W_ENDCOL(wp), get_corner_sep_connector(wp, WC_BOTTOM_RIGHT), hl);
grid_line_flush();
}
}
@ -2394,8 +2394,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
int symbol = wp->w_p_fcs_chars.lastline;
// Last line isn't finished: Display "@@@" at the end.
grid_fill(&wp->w_grid, wp->w_grid.rows - 1, wp->w_grid.rows,
MAX(start_col, 0), wp->w_grid.cols, symbol, symbol, at_attr);
// TODO(bfredl): this display ">@@@" when ">" was a left-halve
// maybe "@@@@" is preferred when this happens.
grid_line_start(&wp->w_grid, wp->w_grid.rows - 1);
grid_line_fill(MAX(start_col, 0), wp->w_grid.cols, symbol, at_attr);
grid_line_flush();
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else {

View File

@ -190,21 +190,16 @@ void grid_invalidate(ScreenGrid *grid)
(void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->rows * (size_t)grid->cols);
}
bool grid_invalid_row(ScreenGrid *grid, int row)
static bool grid_invalid_row(ScreenGrid *grid, int row)
{
return grid->attrs[grid->line_offset[row]] < 0;
}
static int line_off2cells(schar_T *line, size_t off, size_t max_off)
{
return (off + 1 < max_off && line[off + 1] == 0) ? 2 : 1;
}
/// Return number of display cells for char at grid->chars[off].
/// We make sure that the offset used is less than "max_off".
static int grid_off2cells(ScreenGrid *grid, size_t off, size_t max_off)
{
return line_off2cells(grid->chars, off, max_off);
return (off + 1 < max_off && grid->chars[off + 1] == 0) ? 2 : 1;
}
/// Return true if the character at "row"/"col" on the screen is the left side
@ -261,18 +256,12 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp)
schar_get(bytes, grid->chars[off]);
}
static bool check_grid(ScreenGrid *grid, int row, int col)
{
grid_adjust(&grid, &row, &col);
// Safety check. The check for negative row and column is to fix issue
// vim/vim#4102. TODO(neovim): find out why row/col could be negative.
if (grid->chars == NULL
|| row >= grid->rows || row < 0
|| col >= grid->cols || col < 0) {
return false;
}
return true;
}
static ScreenGrid *grid_line_grid = NULL;
static int grid_line_row = -1;
static int grid_line_coloff = 0;
static int grid_line_maxcol = 0;
static int grid_line_first = INT_MAX;
static int grid_line_last = 0;
/// put string 'text' on the window grid at position 'row' and 'col', with
/// attributes 'attr', and update contents of 'grid'
@ -280,26 +269,32 @@ static bool check_grid(ScreenGrid *grid, int row, int col)
/// Note: only outputs within one row!
int grid_puts(ScreenGrid *grid, const char *text, int textlen, int row, int col, int attr)
{
if (!check_grid(grid, row, col)) {
grid_line_start(grid, row);
// Safety check. The check for negative row and column is to fix issue
// vim/vim#4102. TODO(neovim): find out why row/col could be negative.
int off_col = grid_line_coloff + col;
if (grid_line_grid->chars == NULL
|| grid_line_row >= grid_line_grid->rows || grid_line_row < 0
|| off_col >= grid_line_grid->cols || off_col < 0) {
if (rdb_flags & RDB_INVALID) {
abort();
} else {
grid_line_grid = NULL;
return 0;
}
return 0;
}
grid_line_start(grid, row);
int len = grid_line_puts(col, text, textlen, attr);
grid_line_flush(true);
if (grid_line_last > grid_line_first) {
// TODO(bfredl): this is bullshit. message.c should manage its own cursor movements
int col_pos = MIN(grid_line_coloff + grid_line_last, grid_line_grid->cols - 1);
ui_grid_cursor_goto(grid_line_grid->handle, grid_line_row, col_pos);
}
grid_line_flush();
return len;
}
static ScreenGrid *grid_line_grid = NULL;
static int grid_line_row = -1;
static int grid_line_coloff = 0;
static int grid_line_first = INT_MAX;
static int grid_line_last = 0;
static bool grid_line_was_invalid = false;
/// Start a group of grid_line_puts calls that builds a single grid line.
///
/// Must be matched with a grid_line_flush call before moving to
@ -308,56 +303,46 @@ void grid_line_start(ScreenGrid *grid, int row)
{
int col = 0;
grid_adjust(&grid, &row, &col);
assert(grid_line_row == -1);
assert(grid_line_grid == NULL);
grid_line_row = row;
grid_line_grid = grid;
grid_line_coloff = col;
// TODO(bfredl): ugly hackaround, will be fixed in STAGE 2
grid_line_was_invalid = grid != &default_grid && grid_invalid_row(grid, row);
grid_line_first = (int)linebuf_size;
grid_line_maxcol = grid->cols - grid_line_coloff;
grid_line_last = 0;
}
void grid_line_put_schar(int col, schar_T schar, int attr)
{
assert(grid_line_row >= 0);
ScreenGrid *grid = grid_line_grid;
assert(grid_line_grid);
size_t off = grid->line_offset[grid_line_row] + (size_t)col;
if (grid->attrs[off] != attr || grid->chars[off] != schar || rdb_flags & RDB_NODELTA) {
grid->chars[off] = schar;
grid->attrs[off] = attr;
linebuf_char[col] = schar;
linebuf_attr[col] = attr;
grid_line_first = MIN(grid_line_first, col);
// TODO(bfredl): Y U NO DOUBLEWIDTH?
grid_line_last = MAX(grid_line_last, col + 1);
}
grid->vcols[off] = -1;
grid_line_first = MIN(grid_line_first, col);
// TODO(bfredl): Y U NO DOUBLEWIDTH?
grid_line_last = MAX(grid_line_last, col + 1);
linebuf_vcol[col] = -1;
}
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
/// a NUL.
int grid_line_puts(int col, const char *text, int textlen, int attr)
{
size_t off;
const char *ptr = text;
int len = textlen;
int c;
size_t max_off;
int u8cc[MAX_MCO];
bool clear_next_cell = false;
int prev_c = 0; // previous Arabic character
int pc, nc, nc1;
int pcc[MAX_MCO];
assert(grid_line_row >= 0);
ScreenGrid *grid = grid_line_grid;
int row = grid_line_row;
col += grid_line_coloff;
assert(grid_line_grid);
off = grid->line_offset[row] + (size_t)col;
int start_col = col;
max_off = grid->line_offset[row] + (size_t)grid->cols;
while (col < grid->cols
int max_col = grid_line_maxcol;
while (col < max_col
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL) {
c = (unsigned char)(*ptr);
@ -394,7 +379,7 @@ int grid_line_puts(int col, const char *text, int textlen, int attr)
} else {
prev_c = u8c;
}
if (col + mbyte_cells > grid->cols) {
if (col + mbyte_cells > max_col) {
// Only 1 cell left, but character requires 2 cells:
// display a '>' in the last column to avoid wrapping. */
c = '>';
@ -408,55 +393,29 @@ int grid_line_puts(int col, const char *text, int textlen, int attr)
// an edge case, treat it as such..
buf = schar_from_cc(u8c, u8cc);
int need_redraw = grid->chars[off] != buf
|| (mbyte_cells == 2 && grid->chars[off + 1] != 0)
|| grid->attrs[off] != attr
|| exmode_active
|| rdb_flags & RDB_NODELTA;
if (need_redraw) {
// When at the end of the text and overwriting a two-cell
// character with a one-cell character, need to clear the next
// cell. Also when overwriting the left half of a two-cell char
// with the right half of a two-cell char. Do this only once
// (utf8_off2cells() may return 2 on the right half).
if (clear_next_cell) {
clear_next_cell = false;
} else if ((len < 0 ? ptr[mbyte_blen] == NUL : ptr + mbyte_blen >= text + len)
&& ((mbyte_cells == 1
&& grid_off2cells(grid, off, max_off) > 1)
|| (mbyte_cells == 2
&& grid_off2cells(grid, off, max_off) == 1
&& grid_off2cells(grid, off + 1, max_off) > 1))) {
clear_next_cell = true;
}
// When at the start of the text and overwriting the right half of a
// two-cell character in the same grid, truncate that into a '>'.
if (ptr == text && col > 0 && grid->chars[off] == 0) {
grid->chars[off - 1] = schar_from_ascii('>');
}
grid->chars[off] = buf;
grid->attrs[off] = attr;
grid->vcols[off] = -1;
if (mbyte_cells == 2) {
grid->chars[off + 1] = 0;
grid->attrs[off + 1] = attr;
grid->vcols[off + 1] = -1;
}
grid_line_first = MIN(grid_line_first, col);
grid_line_last = MAX(grid_line_last, col + mbyte_cells);
// When at the start of the text and overwriting the right half of a
// two-cell character in the same grid, truncate that into a '>'.
if (ptr == text && col > grid_line_first && col < grid_line_last
&& linebuf_char[col] == 0) {
linebuf_char[col - 1] = schar_from_ascii('>');
}
linebuf_char[col] = buf;
linebuf_attr[col] = attr;
linebuf_vcol[col] = -1;
if (mbyte_cells == 2) {
linebuf_char[col + 1] = 0;
linebuf_attr[col + 1] = attr;
linebuf_vcol[col + 1] = -1;
}
off += (size_t)mbyte_cells;
col += mbyte_cells;
ptr += mbyte_blen;
if (clear_next_cell) {
// This only happens at the end, display one space next.
ptr = " ";
len = -1;
}
}
if (col > start_col) {
grid_line_first = MIN(grid_line_first, start_col);
grid_line_last = MAX(grid_line_last, col);
}
return col - start_col;
@ -464,56 +423,30 @@ int grid_line_puts(int col, const char *text, int textlen, int attr)
void grid_line_fill(int start_col, int end_col, int c, int attr)
{
ScreenGrid *grid = grid_line_grid;
size_t lineoff = grid->line_offset[grid_line_row];
start_col += grid_line_coloff;
end_col += grid_line_coloff;
schar_T sc = schar_from_char(c);
for (int col = start_col; col < end_col; col++) {
size_t off = lineoff + (size_t)col;
if (grid->chars[off] != sc || grid->attrs[off] != attr || rdb_flags & RDB_NODELTA) {
grid->chars[off] = sc;
grid->attrs[off] = attr;
grid_line_first = MIN(grid_line_first, col);
grid_line_last = MAX(grid_line_last, col + 1);
}
grid->vcols[off] = -1;
linebuf_char[col] = sc;
linebuf_attr[col] = attr;
linebuf_vcol[col] = -1;
}
grid_line_first = MIN(grid_line_first, start_col);
grid_line_last = MAX(grid_line_last, end_col);
}
/// End a group of grid_line_puts calls and send the screen buffer to the UI layer.
///
/// @param set_cursor Move the visible cursor to the end of the changed region.
/// This is a workaround for not yet refactored code paths
/// and shouldn't be used in new code.
void grid_line_flush(bool set_cursor)
void grid_line_flush(void)
{
assert(grid_line_row != -1);
if (grid_line_first < grid_line_last) {
// When drawing over the right half of a double-wide char clear out the
// left half. Only needed in a terminal.
if (grid_line_was_invalid && grid_line_first == 0) {
// redraw the previous cell, make it empty
grid_line_first = -1;
}
if (set_cursor) {
ui_grid_cursor_goto(grid_line_grid->handle, grid_line_row,
MIN(grid_line_last, grid_line_grid->cols - 1));
}
if (!grid_line_grid->throttled) {
ui_line(grid_line_grid, grid_line_row, grid_line_first, grid_line_last,
grid_line_last, 0, false);
} else if (grid_line_grid->dirty_col) {
if (grid_line_last > grid_line_grid->dirty_col[grid_line_row]) {
grid_line_grid->dirty_col[grid_line_row] = grid_line_last;
}
}
grid_line_first = INT_MAX;
grid_line_last = 0;
}
grid_line_row = -1;
ScreenGrid *grid = grid_line_grid;
grid_line_grid = NULL;
if (!(grid_line_first < grid_line_last)) {
return;
}
int row = grid_line_row;
bool invalid_row = grid != &default_grid && grid_invalid_row(grid, row) && grid_line_first == 0;
grid_put_linebuf(grid, row, grid_line_coloff, grid_line_first, grid_line_last, grid_line_last,
false, 0, false, invalid_row);
}
/// Fill the grid from "start_row" to "end_row" (exclusive), from "start_col"
@ -607,13 +540,14 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
/// - the attributes are different
/// - the character is multi-byte and the next byte is different
/// - the character is two cells wide and the second cell differs.
static int grid_char_needs_redraw(ScreenGrid *grid, size_t off_from, size_t off_to, int cols)
static int grid_char_needs_redraw(ScreenGrid *grid, int col, size_t off_to, int cols)
{
return (cols > 0
&& ((linebuf_char[off_from] != grid->chars[off_to]
|| linebuf_attr[off_from] != grid->attrs[off_to]
|| (line_off2cells(linebuf_char, off_from, off_from + (size_t)cols) > 1
&& linebuf_char[off_from + 1] != grid->chars[off_to + 1]))
&& ((linebuf_char[col] != grid->chars[off_to]
|| linebuf_attr[col] != grid->attrs[off_to]
|| (cols > 1 && linebuf_char[col + 1] == 0
&& linebuf_char[col + 1] != grid->chars[off_to + 1]))
|| exmode_active // TODO(bfredl): what in the actual fuck
|| rdb_flags & RDB_NODELTA));
}
@ -623,30 +557,27 @@ static int grid_char_needs_redraw(ScreenGrid *grid, size_t off_from, size_t off_
/// "endcol" gives the columns where valid characters are.
/// "clear_width" is the width of the window. It's > 0 if the rest of the line
/// needs to be cleared, negative otherwise.
/// "rlflag" is true in a rightleft window:
/// "rl" is true for rightleft text, like a window with 'rightleft' option set
/// When true and "clear_width" > 0, clear columns 0 to "endcol"
/// When false and "clear_width" > 0, clear columns "endcol" to "clear_width"
/// If "wrap" is true, then hint to the UI that "row" contains a line
/// which has wrapped into the next row.
void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int clear_width,
int rlflag, win_T *wp, int bg_attr, bool wrap)
void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol, int clear_width,
int rl, int bg_attr, bool wrap, bool invalid_row)
{
int col = 0;
bool redraw_next; // redraw_this for next character
bool clear_next = false;
bool topline = row == 0;
int char_cells; // 1: normal char
// 2: occupies two display cells
int start_dirty = -1, end_dirty = 0;
assert(row < grid->rows);
assert(0 <= row && row < grid->rows);
// TODO(bfredl): check all callsites and eliminate
// Check for illegal col, just in case
if (endcol > grid->cols) {
endcol = grid->cols;
}
const size_t max_off_from = (size_t)grid->cols;
grid_adjust(&grid, &row, &coloff);
// Safety check. Avoids clang warnings down the call stack.
@ -655,45 +586,21 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
return;
}
size_t off_from = 0;
size_t off_to = grid->line_offset[row] + (size_t)coloff;
const size_t max_off_to = grid->line_offset[row] + (size_t)grid->cols;
// Take care of putting "<<<" on the first line for 'smoothscroll'.
if (topline && wp->w_skipcol > 0
// do not overwrite the 'showbreak' text with "<<<"
&& *get_showbreak_value(wp) == NUL
// do not overwrite the 'listchars' "precedes" text with "<<<"
&& !(wp->w_p_list && wp->w_p_lcs_chars.prec != 0)) {
size_t off = 0;
size_t skip = 0;
if (wp->w_p_nu && wp->w_p_rnu) {
// do not overwrite the line number, change "123 text" to
// "123<<<xt".
while (skip < max_off_from && ascii_isdigit(schar_get_ascii(linebuf_char[off]))) {
off++;
skip++;
}
}
for (size_t i = 0; i < 3 && i + skip < max_off_from; i++) {
if (line_off2cells(linebuf_char, off, max_off_from) > 1) {
// When the first half of a double-width character is
// overwritten, change the second half to a space.
linebuf_char[off + 1] = schar_from_ascii(' ');
}
linebuf_char[off] = schar_from_ascii('<');
linebuf_attr[off] = HL_ATTR(HLF_AT);
off++;
}
// When at the start of the text and overwriting the right half of a
// two-cell character in the same grid, truncate that into a '>'.
if (col > 0 && grid->chars[off_to + (size_t)col] == 0) {
linebuf_char[col - 1] = schar_from_ascii('>');
col--;
}
if (rlflag) {
if (rl) {
// Clear rest first, because it's left of the text.
if (clear_width > 0) {
while (col <= endcol && grid->chars[off_to] == schar_from_ascii(' ')
&& grid->attrs[off_to] == bg_attr) {
off_to++;
while (col <= endcol && grid->chars[off_to + (size_t)col] == schar_from_ascii(' ')
&& grid->attrs[off_to + (size_t)col] == bg_attr) {
col++;
}
if (col <= endcol) {
@ -701,28 +608,26 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
}
}
col = endcol + 1;
off_to = grid->line_offset[row] + (size_t)col + (size_t)coloff;
off_from += (size_t)col;
endcol = (clear_width > 0 ? clear_width : -clear_width);
}
if (bg_attr) {
assert(off_from == (size_t)col);
for (int c = col; c < endcol; c++) {
linebuf_attr[c] = hl_combine_attr(bg_attr, linebuf_attr[c]);
}
}
redraw_next = grid_char_needs_redraw(grid, off_from, off_to, endcol - col);
redraw_next = grid_char_needs_redraw(grid, col, (size_t)col + off_to, endcol - col);
while (col < endcol) {
char_cells = 1;
if (col + 1 < endcol) {
char_cells = line_off2cells(linebuf_char, off_from, max_off_from);
if (col + 1 < endcol && linebuf_char[col + 1] == 0) {
char_cells = 2;
}
bool redraw_this = redraw_next; // Does character need redraw?
redraw_next = grid_char_needs_redraw(grid, off_from + (size_t)char_cells,
off_to + (size_t)char_cells,
size_t off = (size_t)col + off_to;
redraw_next = grid_char_needs_redraw(grid, col + char_cells,
off + (size_t)char_cells,
endcol - col - char_cells);
if (redraw_this) {
@ -737,53 +642,52 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
// char over the left half of an existing one
if (col + char_cells == endcol
&& ((char_cells == 1
&& grid_off2cells(grid, off_to, max_off_to) > 1)
&& grid_off2cells(grid, off, max_off_to) > 1)
|| (char_cells == 2
&& grid_off2cells(grid, off_to, max_off_to) == 1
&& grid_off2cells(grid, off_to + 1, max_off_to) > 1))) {
&& grid_off2cells(grid, off, max_off_to) == 1
&& grid_off2cells(grid, off + 1, max_off_to) > 1))) {
clear_next = true;
}
grid->chars[off_to] = linebuf_char[off_from];
grid->chars[off] = linebuf_char[col];
if (char_cells == 2) {
grid->chars[off_to + 1] = linebuf_char[off_from + 1];
grid->chars[off + 1] = linebuf_char[col + 1];
}
grid->attrs[off_to] = linebuf_attr[off_from];
grid->attrs[off] = linebuf_attr[col];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2) {
grid->attrs[off_to + 1] = linebuf_attr[off_from];
grid->attrs[off + 1] = linebuf_attr[col];
}
}
grid->vcols[off_to] = linebuf_vcol[off_from];
grid->vcols[off] = linebuf_vcol[col];
if (char_cells == 2) {
grid->vcols[off_to + 1] = linebuf_vcol[off_from + 1];
grid->vcols[off + 1] = linebuf_vcol[col + 1];
}
off_to += (size_t)char_cells;
off_from += (size_t)char_cells;
col += char_cells;
}
if (clear_next) {
// Clear the second half of a double-wide character of which the left
// half was overwritten with a single-wide character.
grid->chars[off_to] = schar_from_ascii(' ');
grid->chars[(size_t)col + off_to] = schar_from_ascii(' ');
end_dirty++;
}
int clear_end = -1;
if (clear_width > 0 && !rlflag) {
if (clear_width > 0 && !rl) {
// blank out the rest of the line
// TODO(bfredl): we could cache winline widths
while (col < clear_width) {
if (grid->chars[off_to] != schar_from_ascii(' ')
|| grid->attrs[off_to] != bg_attr
size_t off = (size_t)col + off_to;
if (grid->chars[off] != schar_from_ascii(' ')
|| grid->attrs[off] != bg_attr
|| rdb_flags & RDB_NODELTA) {
grid->chars[off_to] = schar_from_ascii(' ');
grid->attrs[off_to] = bg_attr;
grid->chars[off] = schar_from_ascii(' ');
grid->attrs[off] = bg_attr;
if (start_dirty == -1) {
start_dirty = col;
end_dirty = col;
@ -792,9 +696,8 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
}
clear_end = col + 1;
}
grid->vcols[off_to] = MAXCOL;
grid->vcols[off] = MAXCOL;
col++;
off_to++;
}
}
@ -805,8 +708,22 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
start_dirty = end_dirty;
}
if (clear_end > start_dirty) {
ui_line(grid, row, coloff + start_dirty, coloff + end_dirty, coloff + clear_end,
bg_attr, wrap);
if (!grid->throttled) {
int start_pos = coloff + start_dirty;
// When drawing over the right half of a double-wide char clear out the
// left half. Only needed in a terminal.
if (invalid_row && start_pos == 0) {
start_pos = -1;
}
ui_line(grid, row, start_pos, coloff + end_dirty, coloff + clear_end,
bg_attr, wrap);
} else if (grid->dirty_col) {
// TODO(bfredl): really get rid of the extra psuedo terminal in message.c
// by using a linebuf_char copy for "throttled message line"
if (clear_end > grid->dirty_col[row]) {
grid->dirty_col[row] = clear_end;
}
}
}
}

View File

@ -2087,7 +2087,7 @@ static void display_showcmd(void)
// clear the rest of an old message by outputting up to SHOWCMD_COLS spaces
grid_line_puts(sc_col + len, (char *)" " + len, -1, HL_ATTR(HLF_MSG));
grid_line_flush(false);
grid_line_flush();
}
/// When "check" is false, prepare for commands that scroll the window.

View File

@ -655,7 +655,7 @@ void pum_redraw(void)
i >= thumb_pos && i < thumb_pos + thumb_height ? attr_thumb : attr_scroll);
}
}
grid_line_flush(false);
grid_line_flush();
row++;
}
}

View File

@ -171,7 +171,7 @@ void win_redr_status(win_T *wp)
}
}
grid_line_flush(false);
grid_line_flush();
}
// May need to draw the character below the vertical separator.
@ -449,7 +449,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
grid_line_fill(col, maxcol, fillchar, curattr);
if (!draw_ruler) {
grid_line_flush(false);
grid_line_flush();
}
// Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking
@ -861,7 +861,7 @@ void draw_tabline(void)
};
}
grid_line_flush(false);
grid_line_flush();
}
// Reset the flag here again, in case evaluating 'tabline' causes it to be