Patch 9.0.1585
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 #12448)
Files: src/drawline.c, src/proto/drawline.pro, src/drawscreen.c,
src/structs.h
*** ../vim-9.0.1584/src/drawline.c 2023-05-25 17:14:18.219481255 +0100
--- src/drawline.c 2023-05-27 21:40:36.834631232 +0100
***************
*** 1050,1057 ****
#endif
/*
! * Display line "lnum" of window 'wp' on the screen.
* Start at row "startrow", stop when "endrow" is reached.
* wp->w_virtcol needs to be valid.
*
* Return the number of last row the line occupies.
--- 1050,1060 ----
#endif
/*
! * 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.
+ * "spv" is used to store information for spell checking, kept between
+ * sequential calls for the same window.
* wp->w_virtcol needs to be valid.
*
* Return the number of last row the line occupies.
***************
*** 1062,1069 ****
linenr_T lnum,
int startrow,
int endrow,
! int mod_top UNUSED, // top line updated for changed
text
! int number_only) // only update the number column
{
winlinevars_T wlv; // variables passed between functions
--- 1065,1072 ----
linenr_T lnum,
int startrow,
int endrow,
! int number_only,
! spellvars_T *spv UNUSED)
{
winlinevars_T wlv; // variables passed between functions
***************
*** 1139,1145 ****
int reset_extra_attr = FALSE;
#endif
#ifdef FEAT_SPELL
- int has_spell = FALSE; // this buffer has spell
checking
int can_spell = FALSE;
# define SPWORDLEN 150
char_u nextline[SPWORDLEN * 2];// text with start of the next line
--- 1142,1147 ----
***************
*** 1148,1158 ****
// 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" used
int cur_checked_col = 0; // checked column for current
line
#endif
int extra_check = 0; // has extra highlighting
--- 1150,1155 ----
***************
*** 1289,1335 ****
}
#endif
- #ifdef FEAT_SPELL
- if (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
- #ifdef FEAT_FOLDING
- || hasFoldingWin(wp, lnum - 1, NULL, NULL, TRUE, NULL)
- #endif
- ) && check_need_cap(wp, lnum, 0)))
- cap_col = 0;
- else if (lnum != capcol_lnum)
- cap_col = -1;
- capcol_lnum = 0;
- }
- #endif
-
// handle Visual active in this window
if (VIsual_active && wp->w_buffer == curwin->w_buffer)
{
--- 1286,1291 ----
***************
*** 1497,1511 ****
ptr = line;
#ifdef FEAT_SPELL
! if (has_spell && !number_only)
{
// For checking first word with a capital skip white space.
! if (cap_col == 0)
! cap_col = getwhitecols(line);
! // 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].
if (nextline[SPWORDLEN] == NUL)
{
// No next line or it is empty.
--- 1453,1490 ----
ptr = line;
#ifdef FEAT_SPELL
! 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;
+
// For checking first word with a capital skip white space.
! if (spv->spv_cap_col == 0)
! spv->spv_cap_col = getwhitecols(line);
! // If current line is empty, check first word in next line for capital.
! else if (*skipwhite(line) == NUL)
! {
! 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.
***************
*** 1723,1729 ****
#ifdef FEAT_SPELL
// 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)
{
int len;
colnr_T linecol = (colnr_T)(ptr - line);
--- 1702,1708 ----
#ifdef FEAT_SPELL
// When spell checking a word we need to figure out the start of the
// word and if it's badly spelled or not.
! if (spv->spv_has_spell)
{
int len;
colnr_T linecol = (colnr_T)(ptr - line);
***************
*** 2327,2335 ****
# endif
syntax_attr = get_syntax_attr((colnr_T)v,
# ifdef FEAT_SPELL
! has_spell ? &can_spell :
# endif
! NULL, FALSE);
prev_syntax_col = v;
prev_syntax_attr = syntax_attr;
}
--- 2306,2314 ----
# endif
syntax_attr = get_syntax_attr((colnr_T)v,
# ifdef FEAT_SPELL
! spv->spv_has_spell ? &can_spell :
# endif
! NULL, FALSE);
prev_syntax_col = v;
prev_syntax_attr = syntax_attr;
}
***************
*** 2768,2774 ****
// @Spell cluster is not used or the current syntax item
// contains the @Spell cluster.
v = (long)(ptr - line);
! if (has_spell && v >= word_end && v > cur_checked_col)
{
spell_attr = 0;
// do not calculate cap_col at the end of the line or when
--- 2747,2753 ----
// @Spell cluster is not used or the current syntax item
// contains the @Spell cluster.
v = (long)(ptr - line);
! if (spv->spv_has_spell && v >= word_end && v > cur_checked_col)
{
spell_attr = 0;
// do not calculate cap_col at the end of the line or when
***************
*** 2792,2800 ****
p = nextline + (prev_ptr - line) - nextlinecol;
else
p = prev_ptr;
! cap_col -= (int)(prev_ptr - line);
! len = spell_check(wp, p, &spell_hlf, &cap_col,
! mod_top == 0);
word_end = v + len;
// In Insert mode only highlight a word that
--- 2771,2779 ----
p = nextline + (prev_ptr - line) - nextlinecol;
else
p = prev_ptr;
! spv->spv_cap_col -= (int)(prev_ptr - line);
! len = spell_check(wp, p, &spell_hlf, &spv->spv_cap_col,
! spv->spv_unchanged);
word_end = v + len;
// In Insert mode only highlight a word that
***************
*** 2815,2843 ****
{
// 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);
}
// Turn index into actual attributes.
if (spell_hlf != HLF_COUNT)
spell_attr = highlight_attr[spell_hlf];
! if (cap_col > 0)
{
if (p != prev_ptr
! && (p - nextline) + 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);
}
else
// Compute the actual column.
! cap_col += (int)(prev_ptr - line);
}
}
}
--- 2794,2823 ----
{
// Remember that the good word continues at the
// start of the next line.
! spv->spv_checked_lnum = lnum + 1;
! spv->spv_checked_col = (p - nextline) + len
! - nextline_idx;
}
// Turn index into actual attributes.
if (spell_hlf != HLF_COUNT)
spell_attr = highlight_attr[spell_hlf];
! 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.
! spv->spv_capcol_lnum = lnum + 1;
! spv->spv_cap_col = ((p - nextline)
! + spv->spv_cap_col - nextline_idx);
}
else
// Compute the actual column.
! spv->spv_cap_col += (prev_ptr - line);
}
}
}
***************
*** 4119,4133 ****
}
} // for every character in the line
-
- #ifdef FEAT_SPELL
- // After an empty line check first word for capital.
- if (*skipwhite(line) == NUL)
- {
- capcol_lnum = lnum + 1;
- cap_col = 0;
- }
- #endif
#ifdef FEAT_PROP_POPUP
vim_free(text_props);
vim_free(text_prop_idxs);
--- 4099,4104 ----
*** ../vim-9.0.1584/src/proto/drawline.pro 2022-12-06 14:17:32.178527467
+0000
--- src/proto/drawline.pro 2023-05-27 21:26:47.825527350 +0100
***************
*** 1,4 ****
/* drawline.c */
int text_prop_position(win_T *wp, textprop_T *tp, int vcol, int scr_col, int
*n_extra, char_u **p_extra, int *n_attr, int *n_attr_skip, int do_skip);
! int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int
nochange, int number_only);
/* vim: set ft=c : */
--- 1,4 ----
/* drawline.c */
int text_prop_position(win_T *wp, textprop_T *tp, int vcol, int scr_col, int
*n_extra, char_u **p_extra, int *n_attr, int *n_attr_skip, int do_skip);
! int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int
number_only, spellvars_T *spv);
/* vim: set ft=c : */
*** ../vim-9.0.1584/src/drawscreen.c 2023-05-25 17:14:18.219481255 +0100
--- src/drawscreen.c 2023-05-27 22:16:56.662425321 +0100
***************
*** 2191,2201 ****
redraw_win_toolbar(wp);
#endif
// Update all the window rows.
idx = 0; // first entry in w_lines[].wl_size
row = 0;
srow = 0;
- lnum = wp->w_topline; // first line shown in window
for (;;)
{
// stop updating when reached the end of the window (check for _past_
--- 2191,2215 ----
redraw_win_toolbar(wp);
#endif
+ lnum = wp->w_topline; // first line shown in window
+
+ spellvars_T spv;
+ #ifdef FEAT_SPELL
+ // Initialize spell related variables for the first drawn line.
+ CLEAR_FIELD(spv);
+ 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;
+ }
+ #endif
+
// Update all the window rows.
idx = 0; // first entry in w_lines[].wl_size
row = 0;
srow = 0;
for (;;)
{
// stop updating when reached the end of the window (check for _past_
***************
*** 2450,2460 ****
fold_line(wp, fold_count, &win_foldinfo, lnum, row);
++row;
--fold_count;
wp->w_lines[idx].wl_folded = TRUE;
! wp->w_lines[idx].wl_lastlnum = lnum + fold_count;
# ifdef FEAT_SYN_HL
did_update = DID_FOLD;
# endif
}
else
#endif
--- 2464,2483 ----
fold_line(wp, fold_count, &win_foldinfo, lnum, row);
++row;
--fold_count;
+ linenr_T lnume = lnum + fold_count;
wp->w_lines[idx].wl_folded = TRUE;
! wp->w_lines[idx].wl_lastlnum = lnume;
# ifdef FEAT_SYN_HL
did_update = DID_FOLD;
# endif
+ # ifdef FEAT_SPELL
+ // 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;
+ }
+ # endif
}
else
#endif
***************
*** 2487,2493 ****
#endif
// Display one line.
! row = win_line(wp, lnum, srow, wp->w_height, mod_top, FALSE);
#ifdef FEAT_FOLDING
wp->w_lines[idx].wl_folded = FALSE;
--- 2510,2516 ----
#endif
// Display one line.
! row = win_line(wp, lnum, srow, wp->w_height, FALSE, &spv);
#ifdef FEAT_FOLDING
wp->w_lines[idx].wl_folded = FALSE;
***************
*** 2534,2540 ****
fold_line(wp, fold_count, &win_foldinfo, lnum, row);
else
#endif
! (void)win_line(wp, lnum, srow, wp->w_height, mod_top, TRUE);
}
// This line does not need to be drawn, advance to the next one.
--- 2557,2563 ----
fold_line(wp, fold_count, &win_foldinfo, lnum, row);
else
#endif
! (void)win_line(wp, lnum, srow, wp->w_height, TRUE, &spv);
}
// This line does not need to be drawn, advance to the next one.
*** ../vim-9.0.1584/src/structs.h 2023-05-27 18:02:50.188062442 +0100
--- src/structs.h 2023-05-27 21:20:27.502104826 +0100
***************
*** 4870,4872 ****
--- 4870,4887 ----
// message (when it is not NULL).
char *os_errbuf;
} optset_T;
+
+ /*
+ * Spell checking variables passed from win_update() to win_line().
+ */
+ typedef struct {
+ int spv_has_spell; // drawn window has spell checking
+ #ifdef FEAT_SPELL
+ int 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"
+ #endif
+ } spellvars_T;
*** ../vim-9.0.1584/src/version.c 2023-05-27 19:01:48.395230967 +0100
--- src/version.c 2023-05-27 21:21:56.521970607 +0100
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1585,
/**/
--
>From "know your smileys":
:-H Is missing teeth
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20230527212235.DF6FE1C140E%40moolenaar.net.