diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-07-15 18:35:20 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-15 18:35:20 +0800 |
commit | 594c7f3d77262a1222c9786d86353a0595f2894c (patch) | |
tree | d67b95de5f1c770a49317f8a7a0adaf0fdaa5a82 | |
parent | 04c158fbec9aeeccd7bd1bb16fc8a688edadd353 (diff) | |
download | rneovim-594c7f3d77262a1222c9786d86353a0595f2894c.tar.gz rneovim-594c7f3d77262a1222c9786d86353a0595f2894c.tar.bz2 rneovim-594c7f3d77262a1222c9786d86353a0595f2894c.zip |
fix(ui): avoid ambiguity about last chunk when flushing halfway (#29718)
-rw-r--r-- | src/nvim/api/ui.c | 26 | ||||
-rw-r--r-- | test/functional/terminal/testutil.lua | 2 | ||||
-rw-r--r-- | test/functional/terminal/tui_spec.lua | 41 |
3 files changed, 60 insertions, 9 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index fdf25c75d7..852b8b9b48 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -778,16 +778,26 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco for (size_t i = 0; i < ncells; i++) { repeat++; if (i == ncells - 1 || attrs[i] != attrs[i + 1] || chunk[i] != chunk[i + 1]) { - if (UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + MAX_SCHAR_SIZE + 5 + 5) + 1 + if ( + // Close to overflowing the redraw buffer. Finish this event, flush, + // and start a new "grid_line" event at the current position. + // For simplicity leave place for the final "clear" element as well, + // hence the factor of 2 in the check. + UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + MAX_SCHAR_SIZE + 5 + 5) + 1 + // Also if there is a lot of packed cells, pass them off to the UI to + // let it start processing them. || ui->ncells_pending >= 500) { - // close to overflowing the redraw buffer. finish this event, - // flush, and start a new "grid_line" event at the current position. - // For simplicity leave place for the final "clear" element - // as well, hence the factor of 2 in the check. - // Also if there is a lot of packed cells, pass them of to the UI to - // let it start processing them + // If the last chunk was all spaces, add an empty clearing chunk, + // so it's clear that the last chunk wasn't a clearing chunk. + if (was_space) { + nelem++; + ui->ncells_pending += 1; + mpack_array(buf, 3); + mpack_str_small(buf, S_LEN(" ")); + mpack_uint(buf, (uint32_t)clearattr); + mpack_uint(buf, 0); + } mpack_w2(&lenpos, nelem); - // We only ever set the wrap field on the final "grid_line" event for the line. mpack_bool(buf, false); ui_flush_buf(ui); diff --git a/test/functional/terminal/testutil.lua b/test/functional/terminal/testutil.lua index 45c73b1dc6..7eb4af4940 100644 --- a/test/functional/terminal/testutil.lua +++ b/test/functional/terminal/testutil.lua @@ -169,7 +169,7 @@ local function setup_child_nvim(args, opts) env.VIMRUNTIME = os.getenv('VIMRUNTIME') end - return screen_setup(0, argv, opts.cols, env) + return screen_setup(opts.extra_rows, argv, opts.cols, env) end return { diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 5269af760a..3e0b907ea2 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -2199,6 +2199,47 @@ describe('TUI', function() } end) + it('draws screen lines with leading spaces correctly #29711', function() + local screen = tt.setup_child_nvim({ + '-u', + 'NONE', + '-i', + 'NONE', + '--cmd', + 'set foldcolumn=6 | call setline(1, ["", repeat("aabb", 1000)]) | echo 42', + }, { extra_rows = 10, cols = 66 }) + screen:expect { + grid = [[ + | + aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabb|*12 + aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba@@@| + [No Name] [+] 1,0-1 Top| + 42 | + -- TERMINAL -- | + ]], + attr_ids = {}, + } + feed_data('\12') -- Ctrl-L + -- The first line counts as 3 cells. + -- For the second line, 6 repeated spaces at the start counts as 2 cells, + -- so each screen line of the second line counts as 62 cells. + -- After drawing the first line and 8 screen lines of the second line, + -- 3 + 8 * 62 = 499 cells have been counted. + -- The 6 repeated spaces at the start of the next screen line exceeds the + -- 500-cell limit, so the buffer is flushed after these spaces. + screen:expect { + grid = [[ + | + aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabb|*12 + aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba@@@| + [No Name] [+] 1,0-1 Top| + | + -- TERMINAL -- | + ]], + attr_ids = {}, + } + end) + it('no heap-buffer-overflow when changing &columns', function() -- Set a different bg colour and change $TERM to something dumber so the `print_spaces()` -- codepath in `clear_region()` is hit. |