From 8516c2dc1f301c439695629fff771227dbe00d30 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 23 Nov 2024 14:22:06 +0600 Subject: refactor(options): autogenerate valid values and flag enums for options (#31089) Problem: Option metadata like list of valid values for an option and option flags are not listed in the `options.lua` file and are instead manually defined in C, which means option metadata is split between several places. Solution: Put metadata such as list of valid values for an option and option flags in `options.lua`, and autogenerate the corresponding C variables and enums. Supersedes #28659 Co-authored-by: glepnir --- src/nvim/drawline.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 79f3298eb4..10811d40f8 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -395,7 +395,7 @@ static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum) { return wp->w_p_cul && lnum == wp->w_cursorline - && (wp->w_p_culopt_flags & CULOPT_NBR); + && (wp->w_p_culopt_flags & kOptCuloptFlagNumber); } /// Setup for drawing the 'foldcolumn', if there is one. @@ -507,10 +507,10 @@ static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv) { return wp->w_p_cul && wlv->lnum == wp->w_cursorline - && (wp->w_p_culopt_flags & CULOPT_NBR) + && (wp->w_p_culopt_flags & kOptCuloptFlagNumber) && (wlv->row == wlv->startrow + wlv->filler_lines || (wlv->row > wlv->startrow + wlv->filler_lines - && (wp->w_p_culopt_flags & CULOPT_LINE))); + && (wp->w_p_culopt_flags & kOptCuloptFlagLine))); } static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) @@ -1165,11 +1165,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s wlv.filler_todo = wlv.filler_lines; // Cursor line highlighting for 'cursorline' in the current window. - if (wp->w_p_cul && wp->w_p_culopt_flags != CULOPT_NBR && lnum == wp->w_cursorline + if (wp->w_p_cul && wp->w_p_culopt_flags != kOptCuloptFlagNumber && lnum == wp->w_cursorline // Do not show the cursor line in the text when Visual mode is active, // because it's not clear what is selected then. && !(wp == curwin && VIsual_active)) { - cul_screenline = (is_wrapped && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); + cul_screenline = (is_wrapped && (wp->w_p_culopt_flags & kOptCuloptFlagScreenline)); if (!cul_screenline) { apply_cursorline_highlight(wp, &wlv); } else { @@ -1949,7 +1949,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s decor_attr = 0; if (extra_check) { - const bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0; + const bool no_plain_buffer = (wp->w_s->b_p_spo_flags & kOptSpoFlagNoplainbuffer) != 0; bool can_spell = !no_plain_buffer; // Get extmark and syntax attributes, unless still at the start of the line @@ -2324,7 +2324,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s if (wlv.n_extra == 0) { wlv.n_extra = byte2cells(mb_c) - 1; } - if ((dy_flags & DY_UHEX) && wp->w_p_rl) { + if ((dy_flags & kOptDyFlagUhex) && wp->w_p_rl) { rl_mirror_ascii(wlv.p_extra, NULL); // reverse "<12>" } wlv.sc_extra = NUL; -- cgit From 3abd7ed4a4cdc5128c5e7e0d02c313585bd71745 Mon Sep 17 00:00:00 2001 From: vanaigr Date: Sat, 19 Oct 2024 16:28:47 -0500 Subject: perf: consider only active decorations when drawing lines --- src/nvim/drawline.c | 56 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 10811d40f8..93b66a9ba3 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -251,12 +251,17 @@ static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int win_row) { - DecorState *state = &decor_state; - const int max_col = wp->w_grid.cols; + DecorState *const state = &decor_state; + int const max_col = wp->w_grid.cols; int right_pos = max_col; - bool do_eol = state->eol_col > -1; - for (size_t i = 0; i < kv_size(state->active); i++) { - DecorRange *item = &kv_A(state->active, i); + bool const do_eol = state->eol_col > -1; + + int const count = state->current_end; + int *const indices = state->ranges_i.items; + DecorRangeSlot *const slots = state->slots.items; + + for (int i = 0; i < count; i++) { + DecorRange *item = &slots[indices[i]].range; if (!(item->start_row == state->row && decor_virt_pos(item))) { continue; } @@ -756,17 +761,28 @@ static bool has_more_inline_virt(winlinevars_T *wlv, ptrdiff_t v) if (wlv->virt_inline_i < kv_size(wlv->virt_inline)) { return true; } - DecorState *state = &decor_state; - for (size_t i = 0; i < kv_size(state->active); i++) { - DecorRange *item = &kv_A(state->active, i); - if (item->start_row != state->row - || item->kind != kDecorKindVirtText - || item->data.vt->pos != kVPosInline - || item->data.vt->width == 0) { - continue; - } - if (item->draw_col >= -1 && item->start_col >= v) { - return true; + + int const count = (int)kv_size(decor_state.ranges_i); + int const cur_end = decor_state.current_end; + int const fut_beg = decor_state.future_begin; + int *const indices = decor_state.ranges_i.items; + DecorRangeSlot *const slots = decor_state.slots.items; + + int const beg_pos[] = { 0, fut_beg }; + int const end_pos[] = { cur_end, count }; + + for (int pos_i = 0; pos_i < 2; pos_i++) { + for (int i = beg_pos[pos_i]; i < end_pos[pos_i]; i++) { + DecorRange *item = &slots[indices[i]].range; + if (item->start_row != decor_state.row + || item->kind != kDecorKindVirtText + || item->data.vt->pos != kVPosInline + || item->data.vt->width == 0) { + continue; + } + if (item->draw_col >= -1 && item->start_col >= v) { + return true; + } } } return false; @@ -780,8 +796,12 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t wlv->virt_inline = VIRTTEXT_EMPTY; wlv->virt_inline_i = 0; DecorState *state = &decor_state; - for (size_t i = 0; i < kv_size(state->active); i++) { - DecorRange *item = &kv_A(state->active, i); + int const count = state->current_end; + int *const indices = state->ranges_i.items; + DecorRangeSlot *const slots = state->slots.items; + + for (int i = 0; i < count; i++) { + DecorRange *item = &slots[indices[i]].range; if (item->draw_col == -3) { // No more inline virtual text before this non-inline virtual text item, // so its position can be decided now. -- cgit From fccef5ec35f8cd57d2587e777833068bdf27bafe Mon Sep 17 00:00:00 2001 From: vanaigr Date: Thu, 28 Nov 2024 22:30:38 -0600 Subject: refactor: comments, variable names --- src/nvim/drawline.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 93b66a9ba3..bf14ce1d4a 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -256,11 +256,11 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int right_pos = max_col; bool const do_eol = state->eol_col > -1; - int const count = state->current_end; + int const end = state->current_end; int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; - for (int i = 0; i < count; i++) { + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (!(item->start_row == state->row && decor_virt_pos(item))) { continue; @@ -796,11 +796,11 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t wlv->virt_inline = VIRTTEXT_EMPTY; wlv->virt_inline_i = 0; DecorState *state = &decor_state; - int const count = state->current_end; + int const end = state->current_end; int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; - for (int i = 0; i < count; i++) { + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (item->draw_col == -3) { // No more inline virtual text before this non-inline virtual text item, -- cgit From 433b342baa04b35fb1ab24d4ef38f126d12ea714 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sat, 14 Dec 2024 19:21:50 +0100 Subject: feat(ui): sign/statuscolumn can combine highlight attrs #31575 Problem: Since e049c6e4c08a, most statusline-like UI elements can combine highlight attrs, except for sign/statuscolumn. Solution: Implement for sign/statuscolumn. --- src/nvim/drawline.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index bf14ce1d4a..b8f21d7454 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -462,10 +462,12 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, int sign_cul_attr) { SignTextAttrs sattr = wlv->sattrs[sign_idx]; + int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); if (sattr.text[0] && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { int attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr) ? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0; + attr = hl_combine_attr(scl_attr, attr); int fill = nrcol ? number_width(wp) + 1 : SIGN_WIDTH; draw_col_fill(wlv, schar_from_ascii(' '), fill, attr); int sign_pos = wlv->off - SIGN_WIDTH - (int)nrcol; @@ -474,8 +476,7 @@ static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, i linebuf_char[sign_pos + 1] = sattr.text[1]; } else { assert(!nrcol); // handled in draw_lnum_col() - int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); - draw_col_fill(wlv, schar_from_ascii(' '), SIGN_WIDTH, attr); + draw_col_fill(wlv, schar_from_ascii(' '), SIGN_WIDTH, scl_attr); } } @@ -559,8 +560,8 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int } else { // Draw the line number (empty space after wrapping). int width = number_width(wp) + 1; - int attr = (sign_num_attr > 0 && wlv->filler_todo <= 0) - ? sign_num_attr : get_line_number_attr(wp, wlv); + int attr = hl_combine_attr(get_line_number_attr(wp, wlv), + wlv->filler_todo <= 0 ? sign_num_attr : 0); if (wlv->row == wlv->startrow + wlv->filler_lines && (wp->w_skipcol == 0 || wlv->row > 0 || (wp->w_p_nu && wp->w_p_rnu))) { char buf[32]; @@ -640,7 +641,7 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir draw_col_buf(wp, wlv, transbuf, translen, attr, false); p = sp->start; int hl = sp->userhl; - attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr; + attr = hl < 0 ? hl_combine_attr(stcp->num_attr, syn_id2attr(-hl)) : stcp->num_attr; } size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true); draw_col_buf(wp, wlv, transbuf, translen, attr, false); -- cgit From c830901e8cde49467d1c99c2d656a13e51979790 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 17 Dec 2024 12:40:30 +0800 Subject: vim-patch:9.1.0936: cannot highlight completed text Problem: cannot highlight completed text Solution: (optionally) highlight auto-completed text using the ComplMatchIns highlight group (glepnir) closes: vim/vim#16173 https://github.com/vim/vim/commit/6a38aff218f5b99a1aed7edaa357df24b9092734 Co-authored-by: glepnir --- src/nvim/drawline.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index b8f21d7454..e15296572b 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -31,6 +31,7 @@ #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/indent.h" +#include "nvim/insexpand.h" #include "nvim/mark_defs.h" #include "nvim/marktree_defs.h" #include "nvim/match.h" @@ -934,6 +935,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s colnr_T vcol_prev = -1; // "wlv.vcol" of previous character ScreenGrid *grid = &wp->w_grid; // grid specific to the window + const bool in_curline = wp == curwin && lnum == curwin->w_cursor.lnum; const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL; @@ -954,6 +956,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s int vi_attr = 0; // attributes for Visual and incsearch highlighting int area_attr = 0; // attributes desired by highlighting int search_attr = 0; // attributes desired by 'hlsearch' + int ins_match_attr = 0; // attributes desired by PmenuMatch int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int decor_attr = 0; // attributes desired by syntax and extmarks bool has_syntax = false; // this buffer has syntax highl. @@ -1117,7 +1120,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } // Check if the char under the cursor should be inverted (highlighted). - if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin + if (!highlight_match && in_curline && cursor_is_block_during_visual(*p_sel == 'e')) { noinvcur = true; } @@ -2704,6 +2707,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s vcol_prev = wlv.vcol; } + if (wlv.filler_todo <= 0 + && (State & MODE_INSERT) && in_curline && ins_compl_active()) { + ins_match_attr = ins_compl_col_range_attr(wlv.col); + if (ins_match_attr > 0) { + wlv.char_attr = hl_combine_attr(wlv.char_attr, ins_match_attr); + } + } + // Store character to be displayed. // Skip characters that are left of the screen for 'nowrap'. if (wlv.filler_todo > 0) { -- cgit From 2f7b385f2ef61626bc034bd6f3a25f5ec9f3a1f3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 18 Dec 2024 07:34:52 +0800 Subject: vim-patch:9.1.0941: ComplMatchIns doesn't work after multibyte chars Problem: ComplMatchIns doesn't work after multibyte chars (after v9.1.0936) Solution: Use (ptr - line) instead of wlv.col (zeertzjq). closes: vim/vim#16233 https://github.com/vim/vim/commit/f4ccada5c372b2c14cc32490860c6995cd00268c --- src/nvim/drawline.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e15296572b..a1d03486ff 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -956,7 +956,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s int vi_attr = 0; // attributes for Visual and incsearch highlighting int area_attr = 0; // attributes desired by highlighting int search_attr = 0; // attributes desired by 'hlsearch' - int ins_match_attr = 0; // attributes desired by PmenuMatch int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int decor_attr = 0; // attributes desired by syntax and extmarks bool has_syntax = false; // this buffer has syntax highl. @@ -1632,8 +1631,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } // When still displaying '$' of change command, stop at cursor. - if (dollar_vcol >= 0 && wp == curwin - && lnum == wp->w_cursor.lnum && wlv.vcol >= wp->w_virtcol) { + if (dollar_vcol >= 0 && in_curline && wlv.vcol >= wp->w_virtcol) { draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row); // don't clear anything after wlv.col wlv_put_linebuf(wp, &wlv, wlv.col, false, bg_attr, 0); @@ -1789,6 +1787,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri); } + // Apply ComplMatchIns highlight if needed. + if (wlv.filler_todo <= 0 + && (State & MODE_INSERT) && in_curline && ins_compl_active()) { + int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line)); + if (ins_match_attr > 0) { + char_attr_pri = hl_combine_attr(char_attr_pri, ins_match_attr); + wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri); + } + } + if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) { const int v = (int)(ptr - line); linenr_T lnume = lnum + foldinfo.fi_lines - 1; @@ -2449,8 +2457,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // With 'virtualedit' we may never reach cursor position, but we still // need to correct the cursor column, so do that at end of line. if (!did_wcol && wlv.filler_todo <= 0 - && wp == curwin && lnum == wp->w_cursor.lnum - && conceal_cursor_line(wp) + && in_curline && conceal_cursor_line(wp) && (wlv.vcol + wlv.skip_cells >= wp->w_virtcol || mb_schar == NUL)) { wp->w_wcol = wlv.col - wlv.boguscols; if (wlv.vcol + wlv.skip_cells < wp->w_virtcol) { @@ -2643,7 +2650,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // Update w_cline_height and w_cline_folded if the cursor line was // updated (saves a call to plines_win() later). - if (wp == curwin && lnum == curwin->w_cursor.lnum) { + if (in_curline) { curwin->w_cline_row = startrow; curwin->w_cline_height = wlv.row - startrow; curwin->w_cline_folded = has_fold; @@ -2707,14 +2714,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s vcol_prev = wlv.vcol; } - if (wlv.filler_todo <= 0 - && (State & MODE_INSERT) && in_curline && ins_compl_active()) { - ins_match_attr = ins_compl_col_range_attr(wlv.col); - if (ins_match_attr > 0) { - wlv.char_attr = hl_combine_attr(wlv.char_attr, ins_match_attr); - } - } - // Store character to be displayed. // Skip characters that are left of the screen for 'nowrap'. if (wlv.filler_todo > 0) { -- cgit From 02bc40c19401ea9f7529cbc81bd18bd01c39bb3c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 19 Dec 2024 07:59:03 +0800 Subject: vim-patch:9.1.0945: ComplMatchIns highlight doesn't end after inserted text (#31628) Problem: ComplMatchIns highlight doesn't end after inserted text. Solution: Handle ComplMatchIns highlight more like search highlight. Fix off-by-one error. Handle deleting text properly. (zeertzjq) closes: vim/vim#16244 https://github.com/vim/vim/commit/f25d8f9312a24da2727671560a865888812ab8d9 --- src/nvim/drawline.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index a1d03486ff..35a41f840d 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -955,7 +955,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s bool area_highlighting = false; // Visual or incsearch highlighting in this line int vi_attr = 0; // attributes for Visual and incsearch highlighting int area_attr = 0; // attributes desired by highlighting - int search_attr = 0; // attributes desired by 'hlsearch' + int search_attr = 0; // attributes desired by 'hlsearch' or ComplMatchIns int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int decor_attr = 0; // attributes desired by syntax and extmarks bool has_syntax = false; // this buffer has syntax highl. @@ -969,7 +969,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s int spell_attr = 0; // attributes desired by spelling int word_end = 0; // last byte with same spell_attr int cur_checked_col = 0; // checked column for current line - bool extra_check = 0; // has syntax or linebreak + bool extra_check = false; // has extra highlighting int multi_attr = 0; // attributes desired by multibyte int mb_l = 1; // multi-byte byte length int mb_c = 0; // decoded multi-byte character @@ -1495,6 +1495,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s ptr = line + v; // "line" may have been updated } + if ((State & MODE_INSERT) && in_curline && ins_compl_active()) { + area_highlighting = true; + } + win_line_start(wp, &wlv); bool draw_cols = true; int leftcols_width = 0; @@ -1740,6 +1744,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s if (*ptr == NUL) { has_match_conc = 0; } + + // Check if ComplMatchIns highlight is needed. + if ((State & MODE_INSERT) && in_curline && ins_compl_active()) { + int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line)); + if (ins_match_attr > 0) { + search_attr = hl_combine_attr(search_attr, ins_match_attr); + } + } } if (wlv.diff_hlf != (hlf_T)0) { @@ -1787,16 +1799,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri); } - // Apply ComplMatchIns highlight if needed. - if (wlv.filler_todo <= 0 - && (State & MODE_INSERT) && in_curline && ins_compl_active()) { - int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line)); - if (ins_match_attr > 0) { - char_attr_pri = hl_combine_attr(char_attr_pri, ins_match_attr); - wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri); - } - } - if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) { const int v = (int)(ptr - line); linenr_T lnume = lnum + foldinfo.fi_lines - 1; -- cgit From 05eca4c04d4d2cc6ad3a2af69d76085135e9b16c Mon Sep 17 00:00:00 2001 From: glepnir Date: Tue, 24 Dec 2024 18:12:50 +0800 Subject: vim-patch:9.1.0956: completion may crash, completion highlight wrong with preview window Problem: completion may crash, completion highlight wrong with preview window (after v9.1.0954) Solution: correctly calculate scroll offset, check for preview window when adding extra highlighting (glepnir) when there have a preview window prepare_tagpreview will change curwin to preview window and this may cause ComplMatchIns check condition not correct. check wp is curwin and also the type of wp is not a preview or poup info fixes: https://github.com/vim/vim/issues/16284 closes: https://github.com/vim/vim/pull/16283 https://github.com/vim/vim/commit/8d0bb6dc9f2e5d94ebb59671d592c1b7fa325ca6 --- src/nvim/drawline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 35a41f840d..3062b0f2a3 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1495,7 +1495,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s ptr = line + v; // "line" may have been updated } - if ((State & MODE_INSERT) && in_curline && ins_compl_active()) { + if ((State & MODE_INSERT) && in_curline && ins_compl_win_active(wp)) { area_highlighting = true; } @@ -1746,7 +1746,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } // Check if ComplMatchIns highlight is needed. - if ((State & MODE_INSERT) && in_curline && ins_compl_active()) { + if ((State & MODE_INSERT) && in_curline && ins_compl_win_active(wp)) { int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line)); if (ins_match_attr > 0) { search_attr = hl_combine_attr(search_attr, ins_match_attr); -- cgit From 33ff546b50f759bd49d9518a94f8c2416848bdd7 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 3 Jan 2025 12:36:36 +0100 Subject: fix(decoration): fix crash when on_lines decor provider modifies marktree If a "on_lines" callback changes the structure of the marktree, the iterator (which is used for an entire window viewport) might now point to invalid memory. Restore the iterator to the beginning of the line in this case. fixes #29484 --- src/nvim/drawline.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 3062b0f2a3..d5273ff3d1 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1051,12 +1051,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } } - has_decor = decor_redraw_line(wp, lnum - 1, &decor_state); - if (!end_fill) { - decor_providers_invoke_line(wp, lnum - 1, &has_decor); + decor_providers_invoke_line(wp, lnum - 1); } + has_decor = decor_redraw_line(wp, lnum - 1, &decor_state); + if (has_decor) { extra_check = true; } -- cgit From 34d808b73cbcb0a43636d826282193ab1ca8c148 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Thu, 16 Jan 2025 18:10:22 +0100 Subject: feat(api): combined highlights in nvim_eval_statusline() Problem: Combined highlighting was not applied to nvim_eval_statusline(), and 'statuscolumn' sign segment/numhl highlights. Solution: Add an additional `groups` element to the return value of `nvim_eval_statusline()->highlights`. This is an array of stacked highlight groups (highest priority last). Also resolve combined highlights for the 'statuscolumn' sign segment/numhl highlights. Expose/synchronize some drawline.c logic that is now mimicked in three different places. --- src/nvim/drawline.c | 66 +++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 35 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index d5273ff3d1..74a766bd0c 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -81,6 +81,8 @@ typedef struct { int cul_attr; ///< set when 'cursorline' active int line_attr; ///< attribute for the whole line int line_attr_lowprio; ///< low-priority attribute for the line + int sign_num_attr; ///< line number attribute (sign numhl) + int sign_cul_attr; ///< cursorline sign attribute (sign culhl) int fromcol; ///< start of inverting int tocol; ///< end of inverting @@ -397,7 +399,7 @@ static void draw_col_fill(winlinevars_T *wlv, schar_T fillchar, int width, int a } /// Return true if CursorLineSign highlight is to be used. -static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum) +bool use_cursor_line_highlight(win_T *wp, linenr_T lnum) { return wp->w_p_cul && lnum == wp->w_cursorline @@ -460,16 +462,15 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in /// If "nrcol" is true, the sign is going to be displayed in the number column. /// Otherwise the sign is going to be displayed in the sign column. If there is no /// sign, draw blank cells instead. -static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, int sign_cul_attr) +static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx) { SignTextAttrs sattr = wlv->sattrs[sign_idx]; int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); if (sattr.text[0] && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { - int attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr) - ? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0; - attr = hl_combine_attr(scl_attr, attr); int fill = nrcol ? number_width(wp) + 1 : SIGN_WIDTH; + int attr = wlv->sign_cul_attr ? wlv->sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0; + attr = hl_combine_attr(scl_attr, attr); draw_col_fill(wlv, schar_from_ascii(' '), fill, attr); int sign_pos = wlv->off - SIGN_WIDTH - (int)nrcol; assert(sign_pos >= 0); @@ -544,7 +545,7 @@ static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) /// Display the absolute or relative line number. After the first row fill with /// blanks when the 'n' flag isn't in 'cpo'. -static void draw_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int sign_cul_attr) +static void draw_lnum_col(win_T *wp, winlinevars_T *wlv) { bool has_cpo_n = vim_strchr(p_cpo, CPO_NUMCOL) != NULL; @@ -557,12 +558,12 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int // then display the sign instead of the line number. if (wp->w_minscwidth == SCL_NUM && wlv->sattrs[0].text[0] && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { - draw_sign(true, wp, wlv, 0, sign_cul_attr); + draw_sign(true, wp, wlv, 0); } else { // Draw the line number (empty space after wrapping). int width = number_width(wp) + 1; int attr = hl_combine_attr(get_line_number_attr(wp, wlv), - wlv->filler_todo <= 0 ? sign_num_attr : 0); + wlv->filler_todo <= 0 ? wlv->sign_num_attr : 0); if (wlv->row == wlv->startrow + wlv->filler_lines && (wp->w_skipcol == 0 || wlv->row > 0 || (wp->w_p_nu && wp->w_p_rnu))) { char buf[32]; @@ -631,22 +632,25 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir char *p = buf; char transbuf[MAXPATHL]; - int attr = stcp->num_attr; size_t len = strlen(buf); + int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); + int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv), + wlv->filler_todo <= 0 ? wlv->sign_num_attr : 0); + int cur_attr = num_attr; // Draw each segment with the specified highlighting. for (stl_hlrec_t *sp = stcp->hlrec; sp->start != NULL; sp++) { ptrdiff_t textlen = sp->start - p; // Make all characters printable. size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, attr, false); + draw_col_buf(wp, wlv, transbuf, translen, cur_attr, false); + int attr = sp->item == STL_SIGNCOL ? scl_attr : sp->item == STL_FOLDCOL ? 0 : num_attr; + cur_attr = hl_combine_attr(attr, sp->userhl < 0 ? syn_id2attr(-sp->userhl) : 0); p = sp->start; - int hl = sp->userhl; - attr = hl < 0 ? hl_combine_attr(stcp->num_attr, syn_id2attr(-hl)) : stcp->num_attr; } size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, attr, false); - draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, stcp->num_attr); + draw_col_buf(wp, wlv, transbuf, translen, num_attr, false); + draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr); } static void handle_breakindent(win_T *wp, winlinevars_T *wlv) @@ -1201,11 +1205,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s area_highlighting = true; } - int line_attr = 0; - int sign_cul_attr = 0; - int sign_num_attr = 0; + int sign_line_attr = 0; // TODO(bfredl, vigoux): line_attr should not take priority over decoration! - decor_redraw_signs(wp, buf, wlv.lnum - 1, wlv.sattrs, &line_attr, &sign_cul_attr, &sign_num_attr); + decor_redraw_signs(wp, buf, wlv.lnum - 1, wlv.sattrs, + &sign_line_attr, &wlv.sign_cul_attr, &wlv.sign_num_attr); statuscol_T statuscol = { 0 }; if (*wp->w_p_stc != NUL) { @@ -1214,19 +1217,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s statuscol.sattrs = wlv.sattrs; statuscol.foldinfo = foldinfo; statuscol.width = win_col_off(wp) - (wp == cmdwin_win); - statuscol.use_cul = use_cursor_line_highlight(wp, lnum); - statuscol.sign_cul_id = statuscol.use_cul ? sign_cul_attr : 0; - statuscol.num_attr = sign_num_attr > 0 ? syn_id2attr(sign_num_attr) : 0; - } else { - if (sign_cul_attr > 0) { - sign_cul_attr = syn_id2attr(sign_cul_attr); - } - if (sign_num_attr > 0) { - sign_num_attr = syn_id2attr(sign_num_attr); - } + statuscol.sign_cul_id = use_cursor_line_highlight(wp, lnum) ? wlv.sign_cul_attr : 0; + } else if (wlv.sign_cul_attr > 0) { + wlv.sign_cul_attr = use_cursor_line_highlight(wp, lnum) ? syn_id2attr(wlv.sign_cul_attr) : 0; } - if (line_attr > 0) { - wlv.line_attr = syn_id2attr(line_attr); + if (wlv.sign_num_attr > 0) { + wlv.sign_num_attr = syn_id2attr(wlv.sign_num_attr); + } + if (sign_line_attr > 0) { + wlv.line_attr = syn_id2attr(sign_line_attr); } // Highlight the current line in the quickfix window. @@ -1549,9 +1548,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // skip columns } else if (statuscol.draw) { // Draw 'statuscolumn' if it is set. - if (sign_num_attr == 0) { - statuscol.num_attr = get_line_number_attr(wp, &wlv); - } const int v = (int)(ptr - line); draw_statuscol(wp, &wlv, lnum, wlv.row - startrow - wlv.filler_lines, col_rows, &statuscol); if (wp->w_redr_statuscol) { @@ -1568,10 +1564,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // wp->w_scwidth is zero if signcol=number is used for (int sign_idx = 0; sign_idx < wp->w_scwidth; sign_idx++) { - draw_sign(false, wp, &wlv, sign_idx, sign_cul_attr); + draw_sign(false, wp, &wlv, sign_idx); } - draw_lnum_col(wp, &wlv, sign_num_attr, sign_cul_attr); + draw_lnum_col(wp, &wlv); } win_col_offset = wlv.off; -- cgit From 2cd72258f6be0ea20f0341be9bc0d306c4533535 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Tue, 21 Jan 2025 11:15:31 +0100 Subject: fix(mouse): 'statuscolumn' fold and popopmenu handling Problem: A right-click on the 'statuscolumn' does not open the popupmenu, even if a cell without a clickdef is clicked. Clicking the %C fold item does not open/close the fold. Solution: Open the popupmenu when there is no clickdef like right-clicking the sign/numbercolumn does. Fill "linebuf_vcol" when drawing the 'statuscolumn' to handle foldcolumn item clicks. --- src/nvim/drawline.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 74a766bd0c..5196d5c9f4 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -368,14 +368,14 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, // TODO(bfredl): integrate with grid.c linebuf code? madness? static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t len, int attr, - bool vcol) + const colnr_T *fold_vcol, bool inc_vcol) { const char *ptr = text; while (ptr < text + len && wlv->off < wp->w_grid.cols) { int cells = line_putchar(wp->w_buffer, &ptr, &linebuf_char[wlv->off], wp->w_grid.cols - wlv->off, wlv->off); int myattr = attr; - if (vcol) { + if (inc_vcol) { advance_color_col(wlv, wlv->vcol); if (wlv->color_cols && wlv->vcol == *wlv->color_cols) { myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr); @@ -383,7 +383,7 @@ static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t } for (int c = 0; c < cells; c++) { linebuf_attr[wlv->off] = myattr; - linebuf_vcol[wlv->off] = vcol ? wlv->vcol++ : -1; + linebuf_vcol[wlv->off] = inc_vcol ? wlv->vcol++ : fold_vcol ? *(fold_vcol++) : -1; wlv->off++; } } @@ -412,7 +412,7 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv) int fdc = compute_foldcolumn(wp, 0); if (fdc > 0) { int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLF : HLF_FC); - fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL); + fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL, NULL); } } @@ -421,8 +421,9 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv) /// @param fdc Current width of the foldcolumn /// @param[out] wlv_off Pointer to linebuf offset, incremented for default column /// @param[out] out_buffer Char array to fill, only used for 'statuscolumn' +/// @param[out] out_vcol vcol array to fill, only used for 'statuscolumn' void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, int fdc, int *wlv_off, - schar_T *out_buffer) + colnr_T *out_vcol, schar_T *out_buffer) { bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; int level = foldinfo.fi_level; @@ -448,10 +449,12 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in symbol = schar_from_ascii('>'); } + int vcol = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3; if (out_buffer) { + out_vcol[i] = vcol; out_buffer[i] = symbol; } else { - linebuf_vcol[*wlv_off] = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3; + linebuf_vcol[*wlv_off] = vcol; linebuf_attr[*wlv_off] = attr; linebuf_char[(*wlv_off)++] = symbol; } @@ -577,7 +580,7 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv) char *num = skipwhite(buf); rl_mirror_ascii(num, skiptowhite(num)); } - draw_col_buf(wp, wlv, buf, (size_t)width, attr, false); + draw_col_buf(wp, wlv, buf, (size_t)width, attr, NULL, false); } else { draw_col_fill(wlv, schar_from_ascii(' '), width, attr); } @@ -632,6 +635,7 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir char *p = buf; char transbuf[MAXPATHL]; + colnr_T *fold_vcol = NULL; size_t len = strlen(buf); int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv), @@ -643,13 +647,14 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir ptrdiff_t textlen = sp->start - p; // Make all characters printable. size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, cur_attr, false); + draw_col_buf(wp, wlv, transbuf, translen, cur_attr, fold_vcol, false); int attr = sp->item == STL_SIGNCOL ? scl_attr : sp->item == STL_FOLDCOL ? 0 : num_attr; cur_attr = hl_combine_attr(attr, sp->userhl < 0 ? syn_id2attr(-sp->userhl) : 0); + fold_vcol = sp->item == STL_FOLDCOL ? stcp->fold_vcol : NULL; p = sp->start; } size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, num_attr, false); + draw_col_buf(wp, wlv, transbuf, translen, num_attr, fold_vcol, false); draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr); } @@ -722,7 +727,7 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. int attr = hl_combine_attr(wlv->cul_attr, win_hl_attr(wp, HLF_AT)); colnr_T vcol_before = wlv->vcol; - draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, true); + draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, NULL, true); wlv->vcol_sbr = wlv->vcol; // Correct start of highlighted area for 'showbreak'. -- cgit From 8bc28978b632362ae658f8d4a6327e07a8b371b2 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Fri, 24 Jan 2025 00:42:24 +0100 Subject: fix(column): apply custom highlight to last 'statuscolumn' segment (#32182) --- src/nvim/drawline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 5196d5c9f4..4a7bc9170a 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -654,8 +654,8 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir p = sp->start; } size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, num_attr, fold_vcol, false); - draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr); + draw_col_buf(wp, wlv, transbuf, translen, cur_attr, fold_vcol, false); + draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, cur_attr); } static void handle_breakindent(win_T *wp, winlinevars_T *wlv) -- cgit From 931ee5591fa764a769946318e05062098baf7c21 Mon Sep 17 00:00:00 2001 From: georgev93 <39860568+georgev93@users.noreply.github.com> Date: Fri, 24 Jan 2025 22:57:45 -0500 Subject: feat(extmarks): virtual text can be right-aligned, truncated #31921 Problem: Right aligned virtual text can cover up buffer text if virtual text is too long Solution: An additional option for `virt_text_pos` called `eol_right_align` has been added to truncate virtual text if it would have otherwise covered up buffer text. This ensures the virtual text extends no further left than EOL. --- src/nvim/drawline.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'src/nvim/drawline.c') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 4a7bc9170a..37a42917b0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -263,6 +263,9 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; + /// Total width of all virtual text with "eol_right_align" alignment + int totalWidthOfEolRightAlignedVirtText = 0; + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (!(item->start_row == state->row && decor_virt_pos(item))) { @@ -277,7 +280,44 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int if (decor_virt_pos(item) && item->draw_col == -1) { bool updated = true; VirtTextPos pos = decor_virt_pos_kind(item); - if (pos == kVPosRightAlign) { + + if (do_eol && pos == kVPosEndOfLineRightAlign) { + int eolOffset = 0; + if (totalWidthOfEolRightAlignedVirtText == 0) { + // Look ahead to the remaining decor items + for (int j = i; j < end; j++) { + /// A future decor to be handled in this function's call + DecorRange *lookaheadItem = &slots[indices[j]].range; + + if (lookaheadItem->start_row != state->row + || !decor_virt_pos(lookaheadItem) + || lookaheadItem->draw_col != -1) { + continue; + } + + /// The Virtual Text of the decor item we're looking ahead to + DecorVirtText *lookaheadVt = NULL; + if (item->kind == kDecorKindVirtText) { + assert(item->data.vt); + lookaheadVt = item->data.vt; + } + + if (decor_virt_pos_kind(lookaheadItem) == kVPosEndOfLineRightAlign) { + // An extra space is added for single character spacing in EOL alignment + totalWidthOfEolRightAlignedVirtText += (lookaheadVt->width + 1); + } + } + + // Remove one space from the total width since there's no single space after the last entry + totalWidthOfEolRightAlignedVirtText--; + + if (totalWidthOfEolRightAlignedVirtText <= (right_pos - state->eol_col)) { + eolOffset = right_pos - totalWidthOfEolRightAlignedVirtText - state->eol_col; + } + } + + item->draw_col = state->eol_col + eolOffset; + } else if (pos == kVPosRightAlign) { right_pos -= vt->width; item->draw_col = right_pos; } else if (pos == kVPosEndOfLine && do_eol) { @@ -304,7 +344,7 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int vcol = item->draw_col - col_off; int col = draw_virt_text_item(buf, item->draw_col, vt->data.virt_text, vt->hl_mode, max_col, vcol); - if (vt->pos == kVPosEndOfLine && do_eol) { + if (do_eol && ((vt->pos == kVPosEndOfLine) || (vt->pos == kVPosEndOfLineRightAlign))) { state->eol_col = col + 1; } *end_col = MAX(*end_col, col); -- cgit