summaryrefslogtreecommitdiffstats
path: root/src/drawline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drawline.c')
-rw-r--r--src/drawline.c277
1 files changed, 187 insertions, 90 deletions
diff --git a/src/drawline.c b/src/drawline.c
index 7bbe86d..a8de449 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -589,7 +589,7 @@ handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv)
// Correct end of highlighted area for 'showbreak',
// required when 'linebreak' is also set.
if (wlv->tocol == wlv->vcol)
- wlv->tocol += wlv->n_extra;
+ wlv->tocol = wlv->vcol_sbr;
// combine 'showbreak' with 'wincolor'
wlv->char_attr = hl_combine_attr(wlv->win_attr, HL_ATTR(HLF_AT));
# ifdef FEAT_SYN_HL
@@ -812,12 +812,12 @@ text_prop_position(
*p_extra = l;
*n_extra = n_used + before + after + padding;
*n_attr = mb_charlen(*p_extra);
- if (above)
- *n_attr -= padding + after;
-
// n_attr_skip will not be decremented before draw_state is
// WL_LINE
*n_attr_skip = before + (padding > 0 ? padding : 0);
+ *n_attr -= *n_attr_skip;
+ if (above)
+ *n_attr -= after;
}
}
}
@@ -832,9 +832,10 @@ text_prop_position(
* Call screen_line() using values from "wlv".
* Also takes care of putting "<<<" on the first line for 'smoothscroll'
* when 'showbreak' is not set.
+ * When "clear_end" is TRUE clear until the end of the screen line.
*/
static void
-wlv_screen_line(win_T *wp, winlinevars_T *wlv, int negative_width)
+wlv_screen_line(win_T *wp, winlinevars_T *wlv, int clear_end)
{
if (wlv->row == 0 && wp->w_skipcol > 0
#if defined(FEAT_LINEBREAK)
@@ -872,8 +873,8 @@ wlv_screen_line(win_T *wp, winlinevars_T *wlv, int negative_width)
}
screen_line(wp, wlv->screen_row, wp->w_wincol, wlv->col,
- negative_width ? -wp->w_width : wp->w_width,
- wlv->screen_line_flags);
+ clear_end ? wp->w_width : -wp->w_width,
+ wlv->vcol - 1, wlv->screen_line_flags);
}
/*
@@ -885,6 +886,7 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
{
#ifdef FEAT_SYN_HL
long v;
+ int wcol;
// Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
if (wp->w_p_wrap)
@@ -892,9 +894,14 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
else
v = wp->w_leftcol;
+ wcol =
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? wp->w_width - wlv->col - 1 :
+# endif
+ wlv->col;
// check if line ends before left margin
- if (wlv->vcol < v + wlv->col - win_col_off(wp))
- wlv->vcol = v + wlv->col - win_col_off(wp);
+ if (wlv->vcol < v + wcol - win_col_off(wp))
+ wlv->vcol = v + wcol - win_col_off(wp);
# ifdef FEAT_CONCEAL
// Get rid of the boguscols now, we want to draw until the right
// edge for 'cursorcolumn'.
@@ -917,11 +924,7 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
# ifdef LINE_ATTR
|| wlv->line_attr != 0
# endif
- || wlv->win_attr != 0)
-# ifdef FEAT_RIGHTLEFT
- && !wp->w_p_rl
-# endif
- )
+ || wlv->win_attr != 0))
{
int rightmost_vcol = 0;
int i;
@@ -934,41 +937,61 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
if (rightmost_vcol < wlv->color_cols[i])
rightmost_vcol = wlv->color_cols[i];
- while (wlv->col < wp->w_width)
+ while (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (wlv->col >= 0) :
+# endif
+ (wlv->col < wp->w_width))
{
ScreenLines[wlv->off] = ' ';
if (enc_utf8)
ScreenLinesUC[wlv->off] = 0;
- ScreenCols[wlv->off] = MAXCOL;
- ++wlv->col;
+
if (wlv->draw_color_col)
wlv->draw_color_col = advance_color_col(
VCOL_HLC, &wlv->color_cols);
int attr = wlv->win_attr;
- if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
- attr = HL_ATTR(HLF_CUC);
- else if (wlv->draw_color_col && VCOL_HLC == *wlv->color_cols)
- attr = HL_ATTR(HLF_MC);
# ifdef LINE_ATTR
- else if (wlv->line_attr != 0)
- attr = wlv->line_attr;
+ if (wlv->line_attr != 0)
+ attr = hl_combine_attr(attr, wlv->line_attr);
# endif
- ScreenAttrs[wlv->off++] = attr;
+ if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
+ && wlv->lnum != wp->w_cursor.lnum)
+ attr = hl_combine_attr(attr, HL_ATTR(HLF_CUC));
+ else if (wlv->draw_color_col && VCOL_HLC == *wlv->color_cols)
+ attr = hl_combine_attr(attr, HL_ATTR(HLF_MC));
+ ScreenAttrs[wlv->off] = attr;
+ ScreenCols[wlv->off] = wlv->vcol;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ --wlv->off;
+ --wlv->col;
+ }
+ else
+# endif
+ {
+ ++wlv->off;
+ ++wlv->col;
+ }
+ ++wlv->vcol;
- if (VCOL_HLC >= rightmost_vcol
+ if (VCOL_HLC > rightmost_vcol
# ifdef LINE_ATTR
&& wlv->line_attr == 0
# endif
&& wlv->win_attr == 0)
break;
-
- ++wlv->vcol;
}
}
#endif
- wlv_screen_line(wp, wlv, FALSE);
+ // Set increasing virtual columns in ScreenCols[] to set correct curswant
+ // (or "coladd" for 'virtualedit') when clicking after end of line.
+ wlv->screen_line_flags |= SLF_INC_VCOL;
+ wlv_screen_line(wp, wlv, TRUE);
+ wlv->screen_line_flags &= ~SLF_INC_VCOL;
++wlv->row;
++wlv->screen_row;
}
@@ -1091,7 +1114,8 @@ apply_cursorline_highlight(
/*
* Display line "lnum" of window "wp" on the screen.
* Start at row "startrow", stop when "endrow" is reached.
- * When "number_only" is TRUE only update the number column.
+ * When only updating the number column, "number_only" is set to the height of
+ * the line, otherwise it is set to 0.
* "spv" is used to store information for spell checking, kept between
* sequential calls for the same window.
* wp->w_virtcol needs to be valid.
@@ -1120,8 +1144,6 @@ win_line(
#if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
int in_linebreak = FALSE; // n_extra set for showing linebreak
#endif
- static char_u *at_end_str = (char_u *)""; // used for p_extra when
- // displaying eol at end-of-line
int lcs_eol_one = wp->w_lcs_chars.eol; // eol until it's been used
int lcs_prec_todo = wp->w_lcs_chars.prec;
// prec until it's been used
@@ -1273,7 +1295,7 @@ win_line(
wlv.vcol_sbr = -1;
#endif
- if (!number_only)
+ if (number_only == 0)
{
// To speed up the loop below, set extra_check when there is linebreak,
// trailing white space and/or syntax processing to be done.
@@ -1486,7 +1508,7 @@ win_line(
#endif
#ifdef FEAT_SPELL
- if (spv->spv_has_spell && !number_only)
+ if (spv->spv_has_spell && number_only == 0)
{
// Prepare for spell checking.
extra_check = TRUE;
@@ -1534,7 +1556,7 @@ win_line(
}
else
{
- v = (long)STRLEN(line);
+ v = ml_get_buf_len(wp->w_buffer, lnum);
if (v < SPWORDLEN)
{
// Short line, use it completely and append the start of the
@@ -1571,7 +1593,7 @@ win_line(
// find start of trailing whitespace
if (wp->w_lcs_chars.trail)
{
- trailcol = (colnr_T)STRLEN(ptr);
+ trailcol = ml_get_buf_len(wp->w_buffer, lnum);
while (trailcol > (colnr_T)0 && VIM_ISWHITE(ptr[trailcol - 1]))
--trailcol;
trailcol += (colnr_T)(ptr - line);
@@ -1632,16 +1654,6 @@ win_line(
if (text_props[i].tp_id < 0)
last_textprop_text_idx = i;
- // When skipping virtual text the props need to be sorted. The
- // order is reversed!
- if (lnum == wp->w_topline && wp->w_skipcol > 0)
- {
- for (int i = 0; i < text_prop_count; ++i)
- text_prop_idxs[i] = i;
- sort_text_props(wp->w_buffer, text_props,
- text_prop_idxs, text_prop_count);
- }
-
// Text props "above" move the line number down to where the text
// is. Only count the ones that are visible, not those that are
// skipped because of w_skipcol.
@@ -1667,19 +1679,23 @@ win_line(
}
}
- if (number_only)
+ if (number_only > 0)
{
// skip over rows only used for virtual text above
wlv.row += wlv.text_prop_above_count;
- if (wlv.row > endrow)
+ if (wlv.row >= endrow)
+ {
+ vim_free(text_props);
+ vim_free(text_prop_idxs);
return wlv.row;
+ }
wlv.screen_row += wlv.text_prop_above_count;
}
#endif
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
colnr_T vcol_first_char = 0;
- if (wp->w_p_lbr && !number_only)
+ if (wp->w_p_lbr && number_only == 0)
{
chartabsize_T cts;
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
@@ -1695,7 +1711,7 @@ win_line(
v = startrow == 0 ? wp->w_skipcol - skipcol_in_text_prop_above : 0;
else
v = wp->w_leftcol;
- if (v > 0 && !number_only)
+ if (v > 0 && number_only == 0)
{
char_u *prev_ptr = ptr;
chartabsize_T cts;
@@ -1840,7 +1856,7 @@ win_line(
}
#ifdef FEAT_SEARCH_EXTRA
- if (!number_only)
+ if (number_only == 0)
{
v = (long)(ptr - line);
area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v,
@@ -1901,7 +1917,7 @@ win_line(
if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0)
{
wlv.draw_state = WL_CMDLINE;
- if (cmdwin_type != 0 && wp == curwin)
+ if (wp == cmdwin_win)
{
// Draw the cmdline character.
wlv.n_extra = 1;
@@ -1933,6 +1949,38 @@ win_line(
wlv.draw_state = WL_NR;
handle_lnum_col(wp, &wlv, sign_present, num_attr);
}
+
+ // When only displaying the (relative) line number and that's done,
+ // stop here.
+ if (number_only > 0 && wlv.draw_state == WL_NR && wlv.n_extra == 0)
+ {
+ wlv_screen_line(wp, &wlv, FALSE);
+ // Need to update more screen lines if:
+ // - LineNrAbove or LineNrBelow is used, or
+ // - still drawing filler lines.
+ if ((wlv.row + 1 - wlv.startrow < number_only
+ && (HL_ATTR(HLF_LNA) != 0 || HL_ATTR(HLF_LNB) != 0))
+#ifdef FEAT_DIFF
+ || wlv.filler_todo > 0
+#endif
+ )
+ {
+ ++wlv.row;
+ ++wlv.screen_row;
+ if (wlv.row == endrow)
+ break;
+#ifdef FEAT_DIFF
+ --wlv.filler_todo;
+ if (wlv.filler_todo == 0 && wp->w_botfill)
+ break;
+#endif
+ win_line_start(wp, &wlv, TRUE);
+ continue;
+ }
+ else
+ break;
+ }
+
#ifdef FEAT_LINEBREAK
// Check if 'breakindent' applies and show it.
// May change wlv.draw_state to WL_BRI or WL_BRI - 1.
@@ -1957,24 +2005,15 @@ win_line(
if (wlv.cul_screenline && wlv.draw_state == WL_LINE
&& wlv.vcol >= left_curline_col
&& wlv.vcol < right_curline_col)
- {
apply_cursorline_highlight(&wlv, sign_present);
- }
#endif
// When still displaying '$' of change command, stop at cursor.
- // When only displaying the (relative) line number and that's done,
- // stop here.
- if (((dollar_vcol >= 0 && wp == curwin
- && lnum == wp->w_cursor.lnum
- && wlv.vcol >= (long)wp->w_virtcol)
- || (number_only && wlv.draw_state > WL_NR))
-#ifdef FEAT_DIFF
- && wlv.filler_todo <= 0
-#endif
- )
+ if (dollar_vcol >= 0 && wp == curwin
+ && lnum == wp->w_cursor.lnum
+ && wlv.vcol >= (long)wp->w_virtcol)
{
- wlv_screen_line(wp, &wlv, TRUE);
+ wlv_screen_line(wp, &wlv, FALSE);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
#ifdef FEAT_SYN_HL
@@ -2274,7 +2313,7 @@ win_line(
// If another text prop follows the condition below at
// the last window column must know.
- // If this is an "above" text prop and 'nowrap' the we
+ // If this is an "above" text prop and 'nowrap' then we
// must wrap anyway.
text_prop_above = above;
text_prop_follows |= other_tpi != -1
@@ -3212,7 +3251,7 @@ win_line(
// Make sure, the highlighting for the tab char will be
// correctly set further below (effectively reverts the
- // FIX_FOR_BOGSUCOLS macro).
+ // FIX_FOR_BOGUSCOLS macro).
if (wlv.n_extra == tab_len + vc_saved && wp->w_p_list
&& wp->w_lcs_chars.tab1)
tab_len += vc_saved;
@@ -3290,7 +3329,7 @@ win_line(
if (!(area_highlighting && virtual_active()
&& wlv.tocol != MAXCOL
&& wlv.vcol < wlv.tocol))
- wlv.p_extra = at_end_str;
+ wlv.p_extra = (char_u *)"";
wlv.n_extra = 0;
}
if (wp->w_p_list && wp->w_lcs_chars.eol > 0)
@@ -3481,6 +3520,21 @@ win_line(
else
c = ' ';
+ if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+ // When the first char to be concealed is double-width,
+ // need to advance one more virtual column.
+ wlv.n_extra++;
+
+ mb_c = c;
+ if (enc_utf8 && utf_char2len(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8cc[0] = 0;
+ c = 0xc0;
+ }
+ else
+ mb_utf8 = FALSE; // don't draw as UTF-8
+
prev_syntax_id = syntax_seqnr;
if (wlv.n_extra > 0)
@@ -3509,15 +3563,6 @@ win_line(
is_concealing = TRUE;
skip_cells = 1;
}
- mb_c = c;
- if (enc_utf8 && utf_char2len(c) > 1)
- {
- mb_utf8 = TRUE;
- u8cc[0] = 0;
- c = 0xc0;
- }
- else
- mb_utf8 = FALSE; // don't draw as UTF-8
}
else
{
@@ -3535,10 +3580,12 @@ win_line(
#ifdef FEAT_CONCEAL
// In the cursor line and we may be concealing characters: correct
// the cursor column when we reach its position.
+ // 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.draw_state == WL_LINE
&& wp == curwin && lnum == wp->w_cursor.lnum
&& conceal_cursor_line(wp)
- && (int)wp->w_virtcol <= wlv.vcol + skip_cells)
+ && (wlv.vcol + skip_cells >= wp->w_virtcol || c == NUL))
{
# ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
@@ -3546,6 +3593,9 @@ win_line(
else
# endif
wp->w_wcol = wlv.col - wlv.boguscols;
+ if (wlv.vcol + skip_cells < wp->w_virtcol)
+ // Cursor beyond end of the line with 'virtualedit'.
+ wp->w_wcol += wp->w_virtcol - wlv.vcol - skip_cells;
wp->w_wrow = wlv.row;
did_wcol = TRUE;
curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
@@ -3740,7 +3790,7 @@ win_line(
}
#endif
ScreenAttrs[wlv.off] = wlv.char_attr;
- ScreenCols[wlv.off] = MAXCOL;
+ ScreenCols[wlv.off] = wlv.vcol;
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
@@ -3972,10 +4022,21 @@ win_line(
#ifdef FEAT_CONCEAL
else if (wp->w_p_cole > 0 && is_concealing)
{
+ int concealed_wide = has_mbyte && (*mb_char2cells)(mb_c) > 1;
+
--skip_cells;
++wlv.vcol_off_co;
+ if (concealed_wide)
+ {
+ // When a double-width char is concealed,
+ // need to advance one more virtual column.
+ ++wlv.vcol;
+ ++wlv.vcol_off_co;
+ }
+
if (wlv.n_extra > 0)
wlv.vcol_off_co += wlv.n_extra;
+
if (wp->w_p_wrap)
{
// Special voodoo required if 'wrap' is on.
@@ -4008,8 +4069,7 @@ win_line(
n_attr = 0;
}
-
- if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+ if (concealed_wide)
{
// Need to fill two screen columns.
# ifdef FEAT_RIGHTLEFT
@@ -4102,35 +4162,72 @@ win_line(
|| text_prop_next <= last_textprop_text_idx
#endif
|| (wp->w_p_list && wp->w_lcs_chars.eol != NUL
- && wlv.p_extra != at_end_str)
+ && lcs_eol_one != -1)
|| (wlv.n_extra != 0 && (wlv.c_extra != NUL
|| *wlv.p_extra != NUL)))
)
{
#ifdef FEAT_CONCEAL
wlv.col -= wlv.boguscols;
- wlv_screen_line(wp, &wlv, FALSE);
+ // Apply 'cursorline' and 'wincolor' highlight.
+ if (wlv.boguscols != 0 && (
+# ifdef LINE_ATTR
+ wlv.line_attr != 0 ||
+# endif
+ wlv.win_attr != 0
+ )
+ )
+ {
+ int attr = wlv.win_attr;
+# ifdef LINE_ATTR
+ if (wlv.line_attr != 0)
+ attr = hl_combine_attr(attr, wlv.line_attr);
+# endif
+ while ((
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? wlv.col >= 0 :
+# endif
+ wlv.col < wp->w_width))
+ {
+ ScreenLines[wlv.off] = ' ';
+ if (enc_utf8)
+ ScreenLinesUC[wlv.off] = 0;
+ ScreenAttrs[wlv.off] = attr;
+ ScreenCols[wlv.off] = wlv.vcol - 1;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ wlv.off--;
+ wlv.col--;
+ wlv.boguscols++;
+ }
+ else
+# endif
+ {
+ wlv.off++;
+ wlv.col++;
+ wlv.boguscols--;
+ }
+ }
+ }
+ wlv_screen_line(wp, &wlv, TRUE);
wlv.col += wlv.boguscols;
wlv.boguscols = 0;
wlv.vcol_off_co = 0;
#else
- wlv_screen_line(wp, &wlv, FALSE);
+ wlv_screen_line(wp, &wlv, TRUE);
#endif
++wlv.row;
++wlv.screen_row;
- // When not wrapping and finished diff lines, or when displayed
- // '$' and highlighting until last column, break here.
- if (((!wp->w_p_wrap
+ // When not wrapping and finished diff lines, break here.
+ if (!wp->w_p_wrap
#ifdef FEAT_DIFF
&& wlv.filler_todo <= 0
#endif
#ifdef FEAT_PROP_POPUP
&& !text_prop_above
-#endif
- ) || lcs_eol_one == -1)
-#ifdef FEAT_PROP_POPUP
- && !text_prop_follows
+ && !text_prop_follows
#endif
)
break;