aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/drawline.c')
-rw-r--r--src/nvim/drawline.c143
1 files changed, 77 insertions, 66 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index c228fd905f..c9a27ceedf 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -1028,7 +1028,7 @@ static void win_line_continue(winlinevars_T *wlv)
/// @param lnum line to display
/// @param startrow first row relative to window grid
/// @param endrow last grid row to be redrawn
-/// @param nochange not updating for changed text
+/// @param mod_top top line updated for changed text
/// @param number_only only update the number column
/// @param foldinfo fold info for this line
/// @param[in, out] providers decoration providers active this line
@@ -1036,7 +1036,7 @@ static void win_line_continue(winlinevars_T *wlv)
/// or explicitly return `false`.
///
/// @return the number of last row the line occupies.
-int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool number_only,
+int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bool number_only,
foldinfo_T foldinfo, DecorProviders *providers, char **provider_err)
{
winlinevars_T wlv; // variables passed between functions
@@ -1049,7 +1049,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol
// at end-of-line
- bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
+ const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
int saved_attr2 = 0; // char_attr saved for n_attr
int n_attr3 = 0; // chars with overruling special attr
@@ -1075,6 +1075,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
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.
+ int folded_attr = 0; // attributes for folded line
int save_did_emsg;
int eol_hl_off = 0; // 1 if highlighted char after EOL
bool draw_color_col = false; // highlight colorcolumn
@@ -1159,7 +1160,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.vcol_sbr = -1;
buf_T *buf = wp->w_buffer;
- bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
+ const bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
@@ -1226,12 +1227,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// When there was a sentence end in the previous line may require a
// word starting with capital in this line. In line 1 always check
- // the first word.
- if (lnum != capcol_lnum) {
- cap_col = -1;
- }
- if (lnum == 1) {
+ // the first word. Also check for sentence end in the line above
+ // when updating the first row in a window, the top line with
+ // changed text in a window, or if the previous line is folded.
+ if (lnum == 1
+ || ((startrow == 0 || mod_top == lnum
+ || hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL))
+ && check_need_cap(wp, lnum, 0))) {
cap_col = 0;
+ } else if (lnum != capcol_lnum) {
+ cap_col = -1;
}
capcol_lnum = 0;
}
@@ -1724,7 +1729,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.draw_state = WL_LINE;
if (has_decor && wlv.row == startrow + wlv.filler_lines) {
// hide virt_text on text hidden by 'nowrap'
- decor_redraw_col(wp, wlv.vcol, wlv.off, true, &decor_state);
+ decor_redraw_col(wp, (colnr_T)(ptr - line), wlv.off, true, &decor_state);
}
win_line_continue(&wlv); // use wlv.saved_ values
}
@@ -1760,7 +1765,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& wlv.col == win_col_offset
&& wlv.n_extra == 0
&& wlv.row == startrow + wlv.filler_lines) {
- wlv.char_attr = win_hl_attr(wp, HLF_FL);
+ wlv.char_attr = folded_attr = win_hl_attr(wp, HLF_FL);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
memset(buf_fold, ' ', FOLD_TEXT_LEN);
@@ -1802,7 +1807,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
int extmark_attr = 0;
- if (wlv.draw_state == WL_LINE && !has_fold
+ if (wlv.draw_state == WL_LINE
&& (area_highlighting || has_spell || extra_check)) {
// handle Visual or match highlighting in this line
if (wlv.vcol == wlv.fromcol
@@ -1821,63 +1826,65 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_active = false;
}
- if (has_decor && v >= 0) {
- bool selected = (area_active || (area_highlighting && noinvcur
- && wlv.vcol == wp->w_virtcol));
- extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off,
- selected, &decor_state);
-
- bool do_save = false;
- handle_inline_virtual_text(wp, &wlv, v, &do_save);
- if (do_save) {
- // restore search_attr and area_attr when n_extra is down to zero
- // TODO(bfredl): this is ugly as fuck. look if we can do this some other way.
- saved_search_attr = search_attr;
- saved_area_attr = area_attr;
- saved_search_attr_from_match = search_attr_from_match;
- search_attr_from_match = false;
- search_attr = 0;
- area_attr = 0;
- extmark_attr = 0;
- n_skip = 0;
+ if (!has_fold) {
+ if (has_decor && v >= 0) {
+ bool selected = (area_active || (area_highlighting && noinvcur
+ && wlv.vcol == wp->w_virtcol));
+ extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off,
+ selected, &decor_state);
+
+ bool do_save = false;
+ handle_inline_virtual_text(wp, &wlv, v, &do_save);
+ if (do_save) {
+ // restore search_attr and area_attr when n_extra is down to zero
+ // TODO(bfredl): this is ugly as fuck. look if we can do this some other way.
+ saved_search_attr = search_attr;
+ saved_area_attr = area_attr;
+ saved_search_attr_from_match = search_attr_from_match;
+ search_attr_from_match = false;
+ search_attr = 0;
+ area_attr = 0;
+ extmark_attr = 0;
+ n_skip = 0;
+ }
}
- }
-
- if (wlv.n_extra == 0) {
- // Check for start/end of 'hlsearch' and other matches.
- // After end, check for start/end of next match.
- // When another match, have to check for start again.
- v = (ptr - line);
- search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl,
- &has_match_conc, &match_conc, lcs_eol_one,
- &on_last_col, &search_attr_from_match);
- ptr = line + v; // "line" may have been changed
- // Do not allow a conceal over EOL otherwise EOL will be missed
- // and bad things happen.
- if (*ptr == NUL) {
- has_match_conc = 0;
+ if (wlv.n_extra == 0) {
+ // Check for start/end of 'hlsearch' and other matches.
+ // After end, check for start/end of next match.
+ // When another match, have to check for start again.
+ v = (ptr - line);
+ search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl,
+ &has_match_conc, &match_conc, lcs_eol_one,
+ &on_last_col, &search_attr_from_match);
+ ptr = line + v; // "line" may have been changed
+
+ // Do not allow a conceal over EOL otherwise EOL will be missed
+ // and bad things happen.
+ if (*ptr == NUL) {
+ has_match_conc = 0;
+ }
}
- }
- if (wlv.diff_hlf != (hlf_T)0) {
- // When there is extra text (eg: virtual text) it gets the
- // diff highlighting for the line, but not for changed text.
- if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start
- && wlv.n_extra == 0) {
- wlv.diff_hlf = HLF_TXD; // changed text
- }
- if (wlv.diff_hlf == HLF_TXD && ((ptr - line > change_end && wlv.n_extra == 0)
- || (wlv.n_extra > 0 && wlv.extra_for_extmark))) {
- wlv.diff_hlf = HLF_CHD; // changed line
- }
- wlv.line_attr = win_hl_attr(wp, (int)wlv.diff_hlf);
- // Overlay CursorLine onto diff-mode highlight.
- if (wlv.cul_attr) {
- wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine
- ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr),
- hl_get_underline())
- : hl_combine_attr(wlv.line_attr, wlv.cul_attr);
+ if (wlv.diff_hlf != (hlf_T)0) {
+ // When there is extra text (eg: virtual text) it gets the
+ // diff highlighting for the line, but not for changed text.
+ if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start
+ && wlv.n_extra == 0) {
+ wlv.diff_hlf = HLF_TXD; // changed text
+ }
+ if (wlv.diff_hlf == HLF_TXD && ((ptr - line > change_end && wlv.n_extra == 0)
+ || (wlv.n_extra > 0 && wlv.extra_for_extmark))) {
+ wlv.diff_hlf = HLF_CHD; // changed line
+ }
+ wlv.line_attr = win_hl_attr(wp, (int)wlv.diff_hlf);
+ // Overlay CursorLine onto diff-mode highlight.
+ if (wlv.cul_attr) {
+ wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine
+ ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr),
+ hl_get_underline())
+ : hl_combine_attr(wlv.line_attr, wlv.cul_attr);
+ }
}
}
@@ -1904,6 +1911,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
attr_pri = false;
wlv.char_attr = decor_attr;
}
+
+ if (folded_attr != 0) {
+ wlv.char_attr = hl_combine_attr(folded_attr, wlv.char_attr);
+ }
}
// Get the next character to put on the screen.
@@ -2193,7 +2204,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
p = prev_ptr;
}
cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
+ size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, mod_top == 0);
assert(tmplen <= INT_MAX);
int len = (int)tmplen;
word_end = (int)v + len;