aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2023-05-28 00:12:56 +0200
committerLuuk van Baal <luukvbaal@gmail.com>2023-06-01 14:30:15 +0200
commit316c8770348264f64deea34359cb5bdff6856ed8 (patch)
tree5173ab3a196514408a1cc154333f1cb912bb009a
parentb46f61ac050e6eb530ceb4d4b510b612596427c5 (diff)
downloadrneovim-316c8770348264f64deea34359cb5bdff6856ed8.tar.gz
rneovim-316c8770348264f64deea34359cb5bdff6856ed8.tar.bz2
rneovim-316c8770348264f64deea34359cb5bdff6856ed8.zip
vim-patch:9.0.1585: weird use of static variables for spell checking
Problem: Weird use of static variables for spell checking. Solution: Move the variables to a structure and pass them from win_update() to win_line(). (Luuk van Baal, closes vim/vim#12448) https://github.com/vim/vim/commit/30805a1aba0067cf0087f9a0e5c184562433e2e7
-rw-r--r--src/nvim/drawline.c120
-rw-r--r--src/nvim/drawline.h11
-rw-r--r--src/nvim/drawscreen.c27
3 files changed, 79 insertions, 79 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 723c3e1c2b..82ffae6697 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -1021,21 +1021,21 @@ static void win_line_continue(winlinevars_T *wlv)
}
}
-/// Display line "lnum" of window 'wp' on the screen.
+/// Display line "lnum" of window "wp" on the screen.
/// wp->w_virtcol needs to be valid.
///
/// @param lnum line to display
/// @param startrow first row relative to window grid
/// @param endrow last grid row to be redrawn
-/// @param mod_top top line updated for changed text
/// @param number_only only update the number column
+/// @param spv 'spell' related variables kept between calls for "wp"
/// @param foldinfo fold info for this line
/// @param[in, out] providers decoration providers active this line
/// items will be disables if they cause errors
/// 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, int mod_top, bool number_only,
+int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_only, spellvars_T *spv,
foldinfo_T foldinfo, DecorProviders *providers, char **provider_err)
{
winlinevars_T wlv; // variables passed between functions
@@ -1079,7 +1079,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
int eol_hl_off = 0; // 1 if highlighted char after EOL
bool draw_color_col = false; // highlight colorcolumn
int *color_cols = NULL; // pointer to according columns array
- bool has_spell = false; // this buffer has spell checking
#define SPWORDLEN 150
char nextline[SPWORDLEN * 2]; // text with start of the next line
int nextlinecol = 0; // column where nextline[] starts
@@ -1087,11 +1086,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
// starts
int spell_attr = 0; // attributes desired by spelling
int word_end = 0; // last byte with same spell_attr
- static linenr_T checked_lnum = 0; // line number for "checked_col"
- static int checked_col = 0; // column in "checked_lnum" up to which
- // there are no spell errors
- static int cap_col = -1; // column to check for Cap word
- static linenr_T capcol_lnum = 0; // line number where "cap_col"
int cur_checked_col = 0; // checked column for current line
int extra_check = 0; // has syntax or linebreak
int multi_attr = 0; // attributes desired by multibyte
@@ -1203,43 +1197,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
}
- if (!has_fold && !end_fill && spell_check_window(wp)) {
- // Prepare for spell checking.
- has_spell = true;
- extra_check = true;
-
- // Get the start of the next line, so that words that wrap to the next
- // line are found too: "et<line-break>al.".
- // Trick: skip a few chars for C/shell/Vim comments
- nextline[SPWORDLEN] = NUL;
- if (lnum < wp->w_buffer->b_ml.ml_line_count) {
- line = ml_get_buf(wp->w_buffer, lnum + 1, false);
- spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
- }
-
- // When a word wrapped from the previous line the start of the current
- // line is valid.
- if (lnum == checked_lnum) {
- cur_checked_col = checked_col;
- }
- checked_lnum = 0;
-
- // 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. 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;
- }
-
// handle Visual active in this window
if (VIsual_active && wp->w_buffer == curwin->w_buffer) {
pos_T *top, *bot;
@@ -1423,15 +1380,38 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum, false);
ptr = line;
- if (has_spell && !number_only) {
- // For checking first word with a capital skip white space.
- if (cap_col == 0) {
- cap_col = (int)getwhitecols(line);
+ if (spv->spv_has_spell && !number_only) {
+ // Prepare for spell checking.
+ extra_check = true;
+
+ // When a word wrapped from the previous line the start of the
+ // current line is valid.
+ if (lnum == spv->spv_checked_lnum) {
+ cur_checked_col = spv->spv_checked_col;
}
+ if (lnum != spv->spv_capcol_lnum) {
+ spv->spv_cap_col = -1;
+ }
+ spv->spv_checked_lnum = 0;
- // To be able to spell-check over line boundaries copy the end of the
- // current line into nextline[]. Above the start of the next line was
- // copied to nextline[SPWORDLEN].
+ // For checking first word with a capital skip white space.
+ if (spv->spv_cap_col == 0) {
+ spv->spv_cap_col = (int)getwhitecols(line);
+ } else if (*skipwhite(line) == NUL) {
+ // If current line is empty, check first word in next line for capital.
+ spv->spv_cap_col = 0;
+ spv->spv_capcol_lnum = lnum + 1;
+ }
+
+ // Get the start of the next line, so that words that wrap to the
+ // next line are found too: "et<line-break>al.".
+ // Trick: skip a few chars for C/shell/Vim comments
+ nextline[SPWORDLEN] = NUL;
+ if (lnum < wp->w_buffer->b_ml.ml_line_count) {
+ spell_cat_line(nextline + SPWORDLEN,
+ ml_get_buf(wp->w_buffer, lnum + 1, false), SPWORDLEN);
+ }
+ // Copy the end of the current line into nextline[].
if (nextline[SPWORDLEN] == NUL) {
// No next line or it is empty.
nextlinecol = MAXCOL;
@@ -1541,7 +1521,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
}
// When spell checking a word we need to figure out the start of the
// word and if it's badly spelled or not.
- if (has_spell) {
+ if (spv->spv_has_spell) {
size_t len;
colnr_T linecol = (colnr_T)(ptr - line);
hlf_T spell_hlf = HLF_COUNT;
@@ -1807,7 +1787,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
int extmark_attr = 0;
if (wlv.draw_state == WL_LINE
- && (area_highlighting || has_spell || extra_check)) {
+ && (area_highlighting || spv->spv_has_spell || extra_check)) {
// handle Visual or match highlighting in this line
if (wlv.vcol == wlv.fromcol
|| (wlv.vcol + 1 == wlv.fromcol && wlv.n_extra == 0
@@ -2126,7 +2106,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
did_emsg = false;
decor_attr = get_syntax_attr((colnr_T)v - 1,
- has_spell ? &can_spell : NULL, false);
+ spv->spv_has_spell ? &can_spell : NULL, false);
if (did_emsg) { // -V547
wp->w_s->b_syn_error = true;
@@ -2185,7 +2165,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
// @Spell cluster is not used or the current syntax item
// contains the @Spell cluster.
v = (ptr - line);
- if (has_spell && v >= word_end && v > cur_checked_col) {
+ if (spv->spv_has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
char *prev_ptr = ptr - mb_l;
// do not calculate cap_col at the end of the line or when
@@ -2202,8 +2182,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
} else {
p = prev_ptr;
}
- cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, mod_top == 0);
+ spv->spv_cap_col -= (int)(prev_ptr - line);
+ size_t tmplen = spell_check(wp, p, &spell_hlf, &spv->spv_cap_col, spv->spv_unchanged);
assert(tmplen <= INT_MAX);
int len = (int)tmplen;
word_end = (int)v + len;
@@ -2224,8 +2204,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
&& (p - nextline) + len > nextline_idx) {
// Remember that the good word continues at the
// start of the next line.
- checked_lnum = lnum + 1;
- checked_col = (int)((p - nextline) + len - nextline_idx);
+ spv->spv_checked_lnum = lnum + 1;
+ spv->spv_checked_col = (int)((p - nextline) + len - nextline_idx);
}
// Turn index into actual attributes.
@@ -2233,17 +2213,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
spell_attr = highlight_attr[spell_hlf];
}
- if (cap_col > 0) {
- if (p != prev_ptr
- && (p - nextline) + cap_col >= nextline_idx) {
+ if (spv->spv_cap_col > 0) {
+ if (p != prev_ptr && (p - nextline) + spv->spv_cap_col >= nextline_idx) {
// Remember that the word in the next line
// must start with a capital.
- capcol_lnum = lnum + 1;
- cap_col = (int)((p - nextline) + cap_col
- - nextline_idx);
+ spv->spv_capcol_lnum = lnum + 1;
+ spv->spv_cap_col = (int)((p - nextline) + spv->spv_cap_col - nextline_idx);
} else {
// Compute the actual column.
- cap_col += (int)(prev_ptr - line);
+ spv->spv_cap_col += (int)(prev_ptr - line);
}
}
}
@@ -3152,12 +3130,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bo
}
} // for every character in the line
- // After an empty line check first word for capital.
- if (*skipwhite(line) == NUL) {
- capcol_lnum = lnum + 1;
- cap_col = 0;
- }
-
kv_destroy(virt_lines);
xfree(wlv.p_extra_free);
return wlv.row;
diff --git a/src/nvim/drawline.h b/src/nvim/drawline.h
index 91261aba78..9a917df0c5 100644
--- a/src/nvim/drawline.h
+++ b/src/nvim/drawline.h
@@ -23,6 +23,17 @@ EXTERN kvec_t(WinExtmark) win_extmark_arr INIT(= KV_INITIAL_VALUE);
EXTERN bool conceal_cursor_used INIT(= false);
+// Spell checking variables passed from win_update() to win_line().
+typedef struct {
+ bool spv_has_spell; ///< drawn window has spell checking
+ bool spv_unchanged; ///< not updating for changed text
+ int spv_checked_col; ///< column in "checked_lnum" up to
+ ///< which there are no spell errors
+ linenr_T spv_checked_lnum; ///< line number for "checked_col"
+ int spv_cap_col; ///< column to check for Cap word
+ linenr_T spv_capcol_lnum; ///< line number for "cap_col"
+} spellvars_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "drawline.h.generated.h"
#endif
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 4f79ba87af..5e8481cd29 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -95,6 +95,7 @@
#include "nvim/profile.h"
#include "nvim/regexp.h"
#include "nvim/search.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/statusline.h"
#include "nvim/syntax.h"
@@ -1991,11 +1992,20 @@ static void win_update(win_T *wp, DecorProviders *providers)
win_check_ns_hl(wp);
+ spellvars_T spv = { 0 };
+ linenr_T lnum = wp->w_topline; // first line shown in window
+ // Initialize spell related variables for the first drawn line.
+ spv.spv_has_spell = spell_check_window(wp);
+ if (spv.spv_has_spell) {
+ spv.spv_unchanged = mod_top == 0;
+ spv.spv_capcol_lnum = mod_top ? mod_top : lnum;
+ spv.spv_cap_col = check_need_cap(wp, spv.spv_capcol_lnum, 0) ? 0 : -1;
+ }
+
// Update all the window rows.
int idx = 0; // first entry in w_lines[].wl_size
int row = 0; // current window row to display
int srow = 0; // starting row of the current line
- linenr_T lnum = wp->w_topline; // first line shown in window
bool eof = false; // if true, we hit the end of the file
bool didline = false; // if true, we finished the last line
@@ -2223,7 +2233,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Display one line
row = win_line(wp, lnum, srow, foldinfo.fi_lines ? srow : wp->w_grid.rows,
- mod_top, false, foldinfo, &line_providers, &provider_err);
+ false, &spv, foldinfo, &line_providers, &provider_err);
if (foldinfo.fi_lines == 0) {
wp->w_lines[idx].wl_folded = false;
@@ -2232,8 +2242,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
syntax_last_parsed = lnum;
} else {
foldinfo.fi_lines--;
+ linenr_T lnume = lnum + foldinfo.fi_lines;
wp->w_lines[idx].wl_folded = true;
- wp->w_lines[idx].wl_lastlnum = lnum + foldinfo.fi_lines;
+ wp->w_lines[idx].wl_lastlnum = lnume;
+
+ // Check if the line after this fold requires a capital.
+ if (spv.spv_has_spell && check_need_cap(wp, lnume + 1, 0)) {
+ spv.spv_cap_col = 0;
+ spv.spv_capcol_lnum = lnume + 1;
+ }
did_update = DID_FOLD;
}
}
@@ -2260,7 +2277,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// text doesn't need to be drawn, but the number column does.
foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum ?
cursorline_fi : fold_info(wp, lnum);
- (void)win_line(wp, lnum, srow, wp->w_grid.rows, mod_top, true,
+ (void)win_line(wp, lnum, srow, wp->w_grid.rows, true, &spv,
info, &line_providers, &provider_err);
}
@@ -2358,7 +2375,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// for ml_line_count+1 and only draw filler lines
foldinfo_T info = { 0 };
row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
- mod_top, false, info, &line_providers, &provider_err);
+ false, &spv, info, &line_providers, &provider_err);
}
} else if (dollar_vcol == -1) {
wp->w_botline = lnum;