diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2018-11-03 14:40:22 +0100 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2018-11-11 09:54:03 +0100 |
commit | 520ec3dbfd208c99f9b184ab0a4baeab9a93b556 (patch) | |
tree | a2322de3b3b5bde4eb9ba5157818d537c86db85f | |
parent | f8639dc99cb085432b14da086af316176152bc1f (diff) | |
download | rneovim-520ec3dbfd208c99f9b184ab0a4baeab9a93b556.tar.gz rneovim-520ec3dbfd208c99f9b184ab0a4baeab9a93b556.tar.bz2 rneovim-520ec3dbfd208c99f9b184ab0a4baeab9a93b556.zip |
UI/TUI: improvements and cleanups for scrolling and clearing
- TUI: _never_ rely on BCE for implicit clearing, only explicit commands.
- TUI: use unibi_erase_chars when possible.
- TUI: use end-exclusive ranges for invalid and cleared areas
- screen: scrolling leaves scrolled in aree undefined. This is a
conservative change, a client assuming the old semantics will still
behave correctly.
- screen: factor out vsep handling from line drawing. This is needed
anyway for the multigrid refactor.
- screen: simplifications of win_do_lines
-rw-r--r-- | runtime/doc/ui.txt | 8 | ||||
-rw-r--r-- | src/nvim/message.c | 4 | ||||
-rw-r--r-- | src/nvim/move.c | 4 | ||||
-rw-r--r-- | src/nvim/screen.c | 99 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 153 | ||||
-rw-r--r-- | src/nvim/ugrid.c | 25 | ||||
-rw-r--r-- | src/nvim/ugrid.h | 14 |
7 files changed, 136 insertions, 171 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 3477e53545..c021f236c8 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -325,14 +325,14 @@ numerical highlight `id`:s to the actual attributes. +-------------------------+ src_top | | src (moved up) and dst | | |-------------------------| dst_bot | - | src (cleared) | | + | src (invalid) | | +=========================+ src_bot < If `rows` is less than zero, move a rectangle in the SR down, this can happen while scrolling up. > +=========================+ src_top - | src (cleared) | | + | src (invalid) | | |------------------------ | dst_top | | src (moved down) and dst| | +-------------------------+ src_bot | @@ -348,6 +348,10 @@ numerical highlight `id`:s to the actual attributes. end-exclusive, which is consistent with API conventions, but different from `set_scroll_region` which was end-inclusive. + The scrolled-in area will be filled using |ui-event-grid_line| directly + after the scroll event. The UI thus doesn't need to clear this area as + part of handling the scroll event. + ============================================================================== Legacy Grid Events (cell based) *ui-grid-old* diff --git a/src/nvim/message.c b/src/nvim/message.c index edce30e6fa..10f4905fb2 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1896,6 +1896,9 @@ static void msg_scroll_up(void) } else { screen_del_lines(0, 1, (int)Rows, 0, Columns); } + // TODO(bfredl): when msgsep display is properly batched, this fill should be + // eliminated. + screen_fill(Rows-1, Rows, 0, (int)Columns, ' ', ' ', 0); } /* @@ -2311,6 +2314,7 @@ static int do_more_prompt(int typed_char) if (toscroll == -1 && screen_ins_lines(0, 1, (int)Rows, 0, (int)Columns) == OK) { + screen_fill(0, 1, 0, (int)Columns, ' ', ' ', 0); // display line at top (void)disp_sb_line(0, mp); } else { diff --git a/src/nvim/move.c b/src/nvim/move.c index bddcefc8ec..3a29851ee6 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -918,9 +918,9 @@ void curs_columns( extra = ((int)prev_skipcol - (int)curwin->w_skipcol) / width; if (extra > 0) { - win_ins_lines(curwin, 0, extra, false); + win_ins_lines(curwin, 0, extra); } else if (extra < 0) { - win_del_lines(curwin, 0, -extra, false); + win_del_lines(curwin, 0, -extra); } } else { curwin->w_skipcol = 0; diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 46aa771a89..d1453b56d2 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -888,10 +888,7 @@ static void win_update(win_T *wp) // Try to insert the correct number of lines. // If not the last window, delete the lines at the bottom. // win_ins_lines may fail when the terminal can't do it. - if (i > 0) { - check_for_delay(false); - } - if (win_ins_lines(wp, 0, i, false) == OK) { + if (win_ins_lines(wp, 0, i) == OK) { if (wp->w_lines_valid != 0) { /* Need to update rows that are new, stop at the * first one that scrolled down. */ @@ -949,8 +946,7 @@ static void win_update(win_T *wp) /* ... but don't delete new filler lines. */ row -= wp->w_topfill; if (row > 0) { - check_for_delay(false); - if (win_del_lines(wp, 0, row, false) == OK) { + if (win_del_lines(wp, 0, row) == OK) { bot_start = wp->w_height - row; } else { mid_start = 0; // redraw all lines @@ -1305,8 +1301,7 @@ static void win_update(win_T *wp) if (row - xtra_rows >= wp->w_height - 2) { mod_bot = MAXLNUM; } else { - check_for_delay(false); - if (win_del_lines(wp, row, -xtra_rows, false) == FAIL) { + if (win_del_lines(wp, row, -xtra_rows) == FAIL) { mod_bot = MAXLNUM; } else { bot_start = wp->w_height + xtra_rows; @@ -1319,8 +1314,7 @@ static void win_update(win_T *wp) if (row + xtra_rows >= wp->w_height - 2) { mod_bot = MAXLNUM; } else { - check_for_delay(false); - if (win_ins_lines(wp, row + old_rows, xtra_rows, false) == FAIL) { + if (win_ins_lines(wp, row + old_rows, xtra_rows) == FAIL) { mod_bot = MAXLNUM; } else if (top_end > row + old_rows) { // Scrolled the part at the top that requires @@ -1513,8 +1507,7 @@ static void win_update(win_T *wp) wp->w_botline = lnum; } } else { - draw_vsep_win(wp, row); - if (eof) { /* we hit the end of the file */ + if (eof) { // we hit the end of the file wp->w_botline = buf->b_ml.ml_line_count + 1; j = diff_check_fill(wp, wp->w_botline); if (j > 0 && !wp->w_botfill) { @@ -1538,6 +1531,10 @@ static void win_update(win_T *wp) win_draw_end(wp, fill_eob, ' ', row, wp->w_height, HLF_EOB); } + if (wp->w_redr_type >= REDRAW_TOP) { + draw_vsep_win(wp, 0); + } + /* Reset the type of redrawing required, the window has been updated. */ wp->w_redr_type = 0; wp->w_old_topfill = wp->w_topfill; @@ -4262,7 +4259,6 @@ win_line ( && filler_todo <= 0 ) { win_draw_end(wp, '@', ' ', row, wp->w_height, HLF_AT); - draw_vsep_win(wp, row); row = endrow; } @@ -4348,7 +4344,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, unsigned max_off_from; unsigned max_off_to; int col = 0; - int hl; bool redraw_this; // Does character need redraw? bool redraw_next; // redraw_this for next character bool clear_next = false; @@ -4474,24 +4469,10 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, } } - if (clear_width > 0) { - // For a window that's left of another, draw the separator char. - if (col + coloff < Columns && wp->w_vsep_width > 0) { - int c = fillchar_vsep(wp, &hl); - schar_T sc; - schar_from_char(sc, c); - - if (schar_cmp(ScreenLines[off_to], sc) - || ScreenAttrs[off_to] != hl) { - schar_copy(ScreenLines[off_to], sc); - ScreenAttrs[off_to] = hl; - if (start_dirty == -1) { - start_dirty = col; - } - end_dirty = col+1; - } - } else - LineWraps[row] = FALSE; + if (clear_width > 0 || wp->w_width != Columns) { + // If we cleared after the end of the line, it did not wrap. + // For vsplit, line wrapping is not possible. + LineWraps[row] = false; } if (clear_end < end_dirty) { @@ -6071,10 +6052,10 @@ static void screenclear2(void) return; } - /* blank out ScreenLines */ - for (i = 0; i < Rows; ++i) { - lineclear(LineOffset[i], (int)Columns); - LineWraps[i] = FALSE; + // blank out ScreenLines + for (i = 0; i < Rows; i++) { + lineclear(LineOffset[i], (int)Columns, true); + LineWraps[i] = false; } ui_call_grid_clear(1); // clear the display @@ -6098,12 +6079,13 @@ static void screenclear2(void) /* * Clear one line in ScreenLines. */ -static void lineclear(unsigned off, int width) +static void lineclear(unsigned off, int width, bool valid) { for (int col = 0; col < width; col++) { schar_from_ascii(ScreenLines[off + col], ' '); } - (void)memset(ScreenAttrs + off, 0, (size_t)width * sizeof(sattr_T)); + int fill = valid ? 0 : -1; + (void)memset(ScreenAttrs + off, fill, (size_t)width * sizeof(sattr_T)); } /// Copy part of a Screenline for vertically split window. @@ -6139,53 +6121,36 @@ void setcursor(void) } /// Insert 'line_count' lines at 'row' in window 'wp'. -/// If 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. -/// If 'mayclear' is TRUE the screen will be cleared if it is faster than -/// scrolling. /// Returns FAIL if the lines are not inserted, OK for success. -int win_ins_lines(win_T *wp, int row, int line_count, int invalid) +int win_ins_lines(win_T *wp, int row, int line_count) { - if (wp->w_height < 5) { - return FAIL; - } - - return win_do_lines(wp, row, line_count, invalid, false); + return win_do_lines(wp, row, line_count, false); } /// Delete "line_count" window lines at "row" in window "wp". -/// If "invalid" is TRUE curwin->w_lines[] is invalidated. -/// If "mayclear" is TRUE the screen will be cleared if it is faster than -/// scrolling /// Return OK for success, FAIL if the lines are not deleted. -int win_del_lines(win_T *wp, int row, int line_count, int invalid) +int win_del_lines(win_T *wp, int row, int line_count) { - return win_do_lines(wp, row, line_count, invalid, true); + return win_do_lines(wp, row, line_count, true); } // Common code for win_ins_lines() and win_del_lines(). // Returns OK or FAIL when the work has been done. -static int win_do_lines(win_T *wp, int row, int line_count, - int invalid, int del) +static int win_do_lines(win_T *wp, int row, int line_count, int del) { - if (invalid) { - wp->w_lines_valid = 0; - } - if (!redrawing() || line_count <= 0) { return FAIL; } - // Delete all remaining lines + // No lines are being moved, just draw over the entire area if (row + line_count >= wp->w_height) { - screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height, - wp->w_wincol, W_ENDCOL(wp), - ' ', ' ', 0); return OK; } // when scrolling, the message on the command line should be cleared, // otherwise it will stay there forever. - clear_cmdline = TRUE; + check_for_delay(false); + clear_cmdline = true; int retval; if (del) { @@ -6237,7 +6202,7 @@ int screen_ins_lines(int row, int line_count, int end, int col, int width) linecopy(j + line_count, j, col, width); } j += line_count; - lineclear(LineOffset[j] + col, width); + lineclear(LineOffset[j] + col, width, false); LineWraps[j] = false; } else { j = end - 1 - i; @@ -6248,7 +6213,7 @@ int screen_ins_lines(int row, int line_count, int end, int col, int width) } LineOffset[j + line_count] = temp; LineWraps[j + line_count] = false; - lineclear(temp, (int)Columns); + lineclear(temp, (int)Columns, false); } } @@ -6283,7 +6248,7 @@ int screen_del_lines(int row, int line_count, int end, int col, int width) linecopy(j - line_count, j, col, width); } j -= line_count; - lineclear(LineOffset[j] + col, width); + lineclear(LineOffset[j] + col, width, false); LineWraps[j] = false; } else { // whole width, moving the line pointers is faster @@ -6295,7 +6260,7 @@ int screen_del_lines(int row, int line_count, int end, int col, int width) } LineOffset[j - line_count] = temp; LineWraps[j - line_count] = false; - lineclear(temp, (int)Columns); + lineclear(temp, (int)Columns, false); } } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index fc7d31edb0..4b00fcf57c 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -94,6 +94,7 @@ typedef struct { bool can_change_scroll_region; bool can_set_lr_margin; bool can_set_left_right_margin; + bool can_erase_chars; bool immediate_wrap_after_last_column; bool bce; bool mouse_enabled; @@ -119,6 +120,7 @@ typedef struct { int set_cursor_style, reset_cursor_style; int enter_undercurl_mode, exit_undercurl_mode, set_underline_color; } unibi_ext; + char *space_buf; } TUIData; static bool volatile got_winch = false; @@ -239,6 +241,7 @@ static void terminfo_start(UI *ui) data->can_set_left_right_margin = !!unibi_get_str(data->ut, unibi_set_left_margin_parm) && !!unibi_get_str(data->ut, unibi_set_right_margin_parm); + data->can_erase_chars = !!unibi_get_str(data->ut, unibi_erase_chars); data->immediate_wrap_after_last_column = terminfo_is_term_family(term, "cygwin") || terminfo_is_term_family(term, "interix"); @@ -401,6 +404,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui) loop_close(&tui_loop, false); kv_destroy(data->invalid_regions); kv_destroy(data->attrs); + xfree(data->space_buf); xfree(data); } @@ -662,7 +666,7 @@ static void cursor_goto(UI *ui, int row, int col) int n = col - grid->col; if (n <= (row == grid->row ? 4 : 2) && cheap_to_print(ui, grid->row, grid->col, n)) { - UGRID_FOREACH_CELL(grid, grid->row, grid->row, grid->col, col - 1, { + UGRID_FOREACH_CELL(grid, grid->row, grid->col, col, { print_cell(ui, cell); }); } @@ -734,50 +738,48 @@ safe_move: } static void clear_region(UI *ui, int top, int bot, int left, int right, - HlAttrs attrs) + int attr_id) { TUIData *data = ui->data; UGrid *grid = &data->grid; - bool cleared = false; + HlAttrs attrs = kv_A(data->attrs, (size_t)attr_id); + update_attrs(ui, attrs); // non-BCE terminals can't clear with non-default background color bool can_clear = data->bce || no_bg(ui, attrs); - if (can_clear && right == ui->width -1) { - // Background is set to the default color and the right edge matches the - // screen end, try to use terminal codes for clearing the requested area. - update_attrs(ui, attrs); - if (left == 0) { - if (bot == ui->height - 1) { - if (top == 0) { - unibi_out(ui, unibi_clear_screen); - ugrid_goto(&data->grid, top, left); - } else { - cursor_goto(ui, top, 0); - unibi_out(ui, unibi_clr_eos); - } - cleared = true; - } + // Background is set to the default color and the right edge matches the + // screen end, try to use terminal codes for clearing the requested area. + if (can_clear && left == 0 && right == ui->width && bot == ui->height) { + if (top == 0) { + unibi_out(ui, unibi_clear_screen); + ugrid_goto(&data->grid, top, left); + } else { + cursor_goto(ui, top, 0); + unibi_out(ui, unibi_clr_eos); } + } else { + int width = right-left; - if (!cleared) { - // iterate through each line and clear with clr_eol - for (int row = top; row <= bot; row++) { - cursor_goto(ui, row, left); + // iterate through each line and clear + for (int row = top; row < bot; row++) { + cursor_goto(ui, row, left); + if (can_clear && right == ui->width) { unibi_out(ui, unibi_clr_eol); + } else if (data->can_erase_chars && can_clear && width >= 5) { + UNIBI_SET_NUM_VAR(data->params[0], width); + unibi_out(ui, unibi_erase_chars); + } else { + out(ui, data->space_buf, (size_t)width); + grid->col += width; + if (data->immediate_wrap_after_last_column) { + // Printing at the right margin immediately advances the cursor. + final_column_wrap(ui); + } } - cleared = true; } } - - if (!cleared) { - // could not clear using faster terminal codes, refresh the whole region - UGRID_FOREACH_CELL(grid, top, bot, left, right, { - cursor_goto(ui, row, col); - print_cell(ui, cell); - }); - } } static void set_scroll_region(UI *ui, int top, int bot, int left, int right) @@ -838,12 +840,16 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height) UGrid *grid = &data->grid; ugrid_resize(grid, (int)width, (int)height); + xfree(data->space_buf); + data->space_buf = xmalloc((size_t)width * sizeof(*data->space_buf)); + memset(data->space_buf, ' ', (size_t)width); + // resize might not always be followed by a clear before flush // so clip the invalid region for (size_t i = 0; i < kv_size(data->invalid_regions); i++) { Rect *r = &kv_A(data->invalid_regions, i); - r->bot = MIN(r->bot, grid->height-1); - r->right = MIN(r->right, grid->width-1); + r->bot = MIN(r->bot, grid->height); + r->right = MIN(r->right, grid->width); } if (!got_winch) { // Try to resize the terminal window. @@ -866,8 +872,7 @@ static void tui_grid_clear(UI *ui, Integer g) UGrid *grid = &data->grid; ugrid_clear(grid); kv_size(data->invalid_regions) = 0; - clear_region(ui, 0, grid->height-1, 0, grid->width-1, - data->clear_attrs); + clear_region(ui, 0, grid->height, 0, grid->width, 0); } static void tui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) @@ -1025,9 +1030,7 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow, data->scroll_region_is_full_screen = fullwidth && top == 0 && bot == ui->height-1; - int clear_top, clear_bot; - ugrid_scroll(grid, top, bot, left, right, (int)rows, - &clear_top, &clear_bot); + ugrid_scroll(grid, top, bot, left, right, (int)rows); bool can_scroll = data->scroll_region_is_full_screen || (data->can_change_scroll_region @@ -1041,8 +1044,6 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow, set_scroll_region(ui, top, bot, left, right); } cursor_goto(ui, top, left); - // also set default color attributes or some terminals can become funny - update_attrs(ui, data->clear_attrs); if (rows > 0) { if (rows == 1) { @@ -1064,16 +1065,14 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow, if (!data->scroll_region_is_full_screen) { reset_scroll_region(ui, fullwidth); } - - if (!(data->bce || no_bg(ui, data->clear_attrs))) { - // Scrolling will leave wrong background in the cleared area on non-BCE - // terminals. Update the cleared area. - clear_region(ui, clear_top, clear_bot, left, right, - data->clear_attrs); - } } else { - // Mark the entire scroll region as invalid for redrawing later - invalidate(ui, top, bot, left, right); + // Mark the moved region as invalid for redrawing later + if (rows > 0) { + endrow = endrow - rows; + } else { + startrow = startrow - rows; + } + invalidate(ui, (int)startrow, (int)endrow, (int)startcol, (int)endcol); } } @@ -1107,7 +1106,7 @@ static void tui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, data->clear_attrs.cterm_bg_color = (int)cterm_bg; data->print_attrs = HLATTRS_INVALID; - invalidate(ui, 0, data->grid.height-1, 0, data->grid.width-1); + invalidate(ui, 0, data->grid.height, 0, data->grid.width); } static void tui_flush(UI *ui) @@ -1129,11 +1128,27 @@ static void tui_flush(UI *ui) while (kv_size(data->invalid_regions)) { Rect r = kv_pop(data->invalid_regions); - assert(r.bot < grid->height && r.right < grid->width); - UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, { - cursor_goto(ui, row, col); - print_cell(ui, cell); - }); + assert(r.bot <= grid->height && r.right <= grid->width); + + for (int row = r.top; row < r.bot; row++) { + int clear_attr = grid->cells[row][r.right-1].attr; + int clear_col; + for (clear_col = r.right; clear_col > 0; clear_col--) { + UCell *cell = &grid->cells[row][clear_col-1]; + if (!(cell->data[0] == ' ' && cell->data[1] == NUL + && cell->attr == clear_attr)) { + break; + } + } + + UGRID_FOREACH_CELL(grid, row, r.left, clear_col, { + cursor_goto(ui, row, col); + print_cell(ui, cell); + }); + if (clear_col < r.right) { + clear_region(ui, row, row+1, clear_col, r.right, clear_attr); + } + } } cursor_goto(ui, data->row, data->col); @@ -1219,7 +1234,7 @@ static void tui_option_set(UI *ui, String name, Object value) ui->rgb = value.data.boolean; data->print_attrs = HLATTRS_INVALID; - invalidate(ui, 0, data->grid.height-1, 0, data->grid.width-1); + invalidate(ui, 0, data->grid.height, 0, data->grid.width); } } @@ -1235,18 +1250,16 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol, assert((size_t)attrs[c-startcol] < kv_size(data->attrs)); grid->cells[linerow][c].attr = attrs[c-startcol]; } - UGRID_FOREACH_CELL(grid, (int)linerow, (int)linerow, (int)startcol, - (int)endcol-1, { - cursor_goto(ui, row, col); + UGRID_FOREACH_CELL(grid, (int)linerow, (int)startcol, (int)endcol, { + cursor_goto(ui, (int)linerow, col); print_cell(ui, cell); }); if (clearcol > endcol) { - HlAttrs cl_attrs = kv_A(data->attrs, (size_t)clearattr); ugrid_clear_chunk(grid, (int)linerow, (int)endcol, (int)clearcol, (sattr_T)clearattr); - clear_region(ui, (int)linerow, (int)linerow, (int)endcol, (int)clearcol-1, - cl_attrs); + clear_region(ui, (int)linerow, (int)linerow+1, (int)endcol, (int)clearcol, + (int)clearattr); } if (wrap && ui->width == grid->width && linerow + 1 < grid->height) { @@ -1269,27 +1282,17 @@ static void invalidate(UI *ui, int top, int bot, int left, int right) { TUIData *data = ui->data; Rect *intersects = NULL; - // Increase dimensions before comparing to ensure adjacent regions are - // treated as intersecting - --top; - ++bot; - --left; - ++right; for (size_t i = 0; i < kv_size(data->invalid_regions); i++) { Rect *r = &kv_A(data->invalid_regions, i); - if (!(top > r->bot || bot < r->top - || left > r->right || right < r->left)) { + // adjacent regions are treated as overlapping + if (!(top > r->bot || bot < r->top) + && !(left > r->right || right < r->left)) { intersects = r; break; } } - ++top; - --bot; - ++left; - --right; - if (intersects) { // If top/bot/left/right intersects with a invalid rect, we replace it // by the union diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c index b741a61d8c..f5bd35a48e 100644 --- a/src/nvim/ugrid.c +++ b/src/nvim/ugrid.c @@ -52,8 +52,7 @@ void ugrid_goto(UGrid *grid, int row, int col) grid->col = col; } -void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, - int count, int *clear_top, int *clear_bot) +void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, int count) { // Compute start/stop/step for the loop below int start, stop, step; @@ -76,26 +75,18 @@ void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, memcpy(target_row, source_row, sizeof(UCell) * (size_t)(right - left + 1)); } - - // clear cells in the emptied region, - if (count > 0) { - *clear_top = stop; - *clear_bot = stop + count - 1; - } else { - *clear_bot = stop; - *clear_top = stop + count + 1; - } - clear_region(grid, *clear_top, *clear_bot, left, right, 0); } static void clear_region(UGrid *grid, int top, int bot, int left, int right, sattr_T attr) { - UGRID_FOREACH_CELL(grid, top, bot, left, right, { - cell->data[0] = ' '; - cell->data[1] = 0; - cell->attr = attr; - }); + for (int row = top; row <= bot; row++) { + UGRID_FOREACH_CELL(grid, row, left, right+1, { + cell->data[0] = ' '; + cell->data[1] = 0; + cell->attr = attr; + }); + } } static void destroy_cells(UGrid *grid) diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h index af78fe91c5..33a706b8c0 100644 --- a/src/nvim/ugrid.h +++ b/src/nvim/ugrid.h @@ -22,15 +22,13 @@ struct ugrid { // -V:UGRID_FOREACH_CELL:625 -#define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \ +#define UGRID_FOREACH_CELL(grid, row, startcol, endcol, code) \ do { \ - for (int row = top; row <= bot; row++) { \ - UCell *row_cells = (grid)->cells[row]; \ - for (int col = left; col <= right; col++) { \ - UCell *cell = row_cells + col; \ - (void)(cell); \ - code; \ - } \ + UCell *row_cells = (grid)->cells[row]; \ + for (int col = startcol; col < endcol; col++) { \ + UCell *cell = row_cells + col; \ + (void)(cell); \ + code; \ } \ } while (0) |