aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/drawline.c26
-rw-r--r--src/nvim/mbyte.c18
-rw-r--r--test/functional/ui/decorations_spec.lua25
3 files changed, 63 insertions, 6 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 0ad03f940a..fddf1362a3 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -969,8 +969,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int n_skip = 0; // nr of chars to skip for 'nowrap' or
// concealing
int skip_cells = 0; // nr of cells to skip for virtual text
- // after the line, when w_skipcol is
- // larger than the text length
+ int skipped_cells = 0; // nr of skipped virtual text cells
int fromcol_prev = -2; // start of inverting after cursor
bool noinvcur = false; // don't invert the cursor
@@ -1786,14 +1785,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// If the text didn't reach until the first window
// column we need to skip cells.
if (skip_cells > 0) {
- if (wlv.n_extra > skip_cells) {
- wlv.n_extra -= skip_cells;
- wlv.p_extra += skip_cells;
+ int virt_text_len = n_attr;
+ if (virt_text_len > skip_cells) {
+ int len = mb_charlen2bytelen(wlv.p_extra, skip_cells);
+ wlv.n_extra -= len;
+ wlv.p_extra += len;
+ n_attr -= skip_cells;
+ // Skipped cells needed to be accounted for in vcol.
+ skipped_cells += skip_cells;
skip_cells = 0;
} else {
// the whole text is left of the window, drop
// it and advance to the next one
- skip_cells -= wlv.n_extra;
+ skip_cells -= virt_text_len;
+ // Skipped cells needed to be accounted for in vcol.
+ skipped_cells += virt_text_len;
+ n_attr = 0;
wlv.n_extra = 0;
}
}
@@ -2969,6 +2976,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
n_skip--;
}
+ // The skipped cells need to be accounted for in vcol.
+ if (wlv.draw_state > WL_STC
+ && skipped_cells > 0) {
+ wlv.vcol += skipped_cells;
+ skipped_cells = 0;
+ }
+
// Only advance the "wlv.vcol" when after the 'number' or
// 'relativenumber' column.
if (wlv.draw_state > WL_STC
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 7d61b918d2..66c26275f1 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -2024,6 +2024,24 @@ int mb_charlen(const char *str)
return count;
}
+int mb_charlen2bytelen(const char *str, int charlen)
+{
+ const char *p = str;
+ int count = 0;
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ for (int i = 0; *p != NUL && i < charlen; i++) {
+ int b = utfc_ptr2len(p);
+ p += b;
+ count += b;
+ }
+
+ return count;
+}
+
/// Like mb_charlen() but for a string with specified length.
int mb_charlen_len(const char *str, int len)
{
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index ba3f73c229..9be8c23ba4 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -1793,6 +1793,31 @@ bbbbbbb]])
|
]]}
end)
+
+ it('tabs are the correct length with no wrap following virtual text', function()
+ command('set nowrap')
+ feed('itest<TAB>a<ESC>')
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
+ feed('gg$')
+ screen:expect { grid = [[
+ {28:aaaaaaaaaaaaaaaaaaaaaaaaa}test ^a |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
end)
describe('decorations: virtual lines', function()