#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
int has_lcs_eol = wp->w_p_list && wp->w_lcs_chars.eol != NUL;
+ // Virtual text above the line is on its own screen line, it does not count
+ // for the size of a Tab.
+ colnr_T tab_vcol = vcol;
+
+# ifdef FEAT_PROP_POPUP
+ tab_vcol -= cts->cts_above_width;
+# endif
/*
* First get the normal size, without 'linebreak' or text properties
*/
- size = win_chartabsize(wp, s, vcol);
+ size = win_chartabsize(wp, s, tab_vcol);
# ifdef FEAT_LINEBREAK
if (*s == NUL)
{
{
// tab size changes because of the inserted text
size -= tab_size;
- tab_size = win_chartabsize(wp, s, vcol + size);
+ tab_size = win_chartabsize(wp, s,
+ vcol + size - cts->cts_above_width);
size += tab_size;
}
# endif
*tailp = size - size_before_lbr;
# ifdef FEAT_PROP_POPUP
+ if (cts->cts_first_char > 0)
+ // Remember the width for the size of a Tab later in the line. Use
+ // assignment, this may be called more than once for a character.
+ cts->cts_above_width = cts->cts_first_char;
size += cts->cts_first_char;
# endif
# endif
if (c == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
{
int tab_len = 0;
- long vcol_adjusted = wlv.vcol; // removed showbreak len
+ // Virtual text and 'showbreak' do not count for the size
+ // of a Tab.
+ long vcol_adjusted = wlv.vcol - wlv.vcol_off_tp;
int lcs_tab1 = wp->w_lcs_chars.tab1;
int lcs_tab2 = wp->w_lcs_chars.tab2;
int lcs_tab3 = wp->w_lcs_chars.tab3;
// only adjust the tab_len, when at the first column
// after the showbreak value was drawn
if (*sbr != NUL && wlv.vcol == wlv.vcol_sbr && wp->w_p_wrap)
- vcol_adjusted = wlv.vcol - MB_CHARLEN(sbr);
+ vcol_adjusted -= MB_CHARLEN(sbr);
#endif
// tab amount depends on current column
#ifdef FEAT_VARTABS
int cts_cur_text_width; // width of current inserted text
int cts_prop_lines; // nr of properties above or below
int cts_first_char; // width text props above the line
+ int cts_above_width; // width of text props above the line,
+ // kept for the whole line
int cts_with_trailing; // include size of trailing props with
// last character
int cts_start_incl; // prop has true "start_incl" arg
call prop_type_delete('indented')
endfunc
+" A Tab in the line is not affected by virtual text above it.
+func Test_prop_above_with_tab()
+ " Use a width that is not a multiple of 'tabstop', otherwise counting the
+ " virtual text for the size of a Tab happens to give the right result.
+ call NewWindow(10, 45)
+ setlocal tabstop=8
+ call setline(1, ["\tX"])
+ call prop_type_add('above', #{highlight: 'Search'})
+
+ " Get the column of the "X" without and with the virtual text.
+ redraw
+ let col_without = 0
+ for col in range(1, winwidth(0))
+ if screenstring(1, col) == 'X'
+ let col_without = col
+ break
+ endif
+ endfor
+ call assert_equal(9, col_without)
+
+ call prop_add(1, 0, #{type: 'above', text: 'text above', text_align: 'above'})
+ redraw
+ let col_with = 0
+ for col in range(1, winwidth(0))
+ if screenstring(2, col) == 'X'
+ let col_with = col
+ break
+ endif
+ endfor
+ call assert_equal(col_without, col_with)
+
+ " The cursor is placed on the character, also with a second Tab.
+ call setline(1, ["\t\tX"])
+ redraw
+ normal! 0fX
+ call assert_equal('X', screenstring(winline(), wincol()))
+
+ only!
+ bwipe!
+ call prop_type_delete('above')
+endfunc
+
func Test_prop_above_with_number()
CheckScreendump
CheckRunVimInTerminal
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 896,
/**/
895,
/**/