]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1585: weird use of static variables for spell checking v9.0.1585
authorLuuk van Baal <luukvbaal@gmail.com>
Sat, 27 May 2023 21:22:10 +0000 (22:22 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 27 May 2023 21:22:10 +0000 (22:22 +0100)
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)

src/drawline.c
src/drawscreen.c
src/proto/drawline.pro
src/structs.h
src/version.c

index 3791ece432c35e353f8ec22a15658135a7eb4df1..3811060df15587936292cb2fe59f0fe25eac8dff 100644 (file)
@@ -1050,8 +1050,11 @@ apply_cursorline_highlight(
 #endif
 
 /*
- * Display line "lnum" of window 'wp' on the screen.
+ * 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,8 +1065,8 @@ win_line(
     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
+    int                number_only,
+    spellvars_T        *spv UNUSED)
 {
     winlinevars_T      wlv;            // variables passed between functions
 
@@ -1139,7 +1142,6 @@ win_line(
     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
@@ -1148,11 +1150,6 @@ win_line(
                                        // 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
@@ -1289,47 +1286,6 @@ win_line(
        }
 #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)
        {
@@ -1497,15 +1453,38 @@ win_line(
     ptr = line;
 
 #ifdef FEAT_SPELL
-    if (has_spell && !number_only)
+    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 (cap_col == 0)
-           cap_col = getwhitecols(line);
+       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;
+       }
+
 
-       // 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].
+       // 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,7 +1702,7 @@ win_line(
 #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)
+       if (spv->spv_has_spell)
        {
            int         len;
            colnr_T     linecol = (colnr_T)(ptr - line);
@@ -2327,9 +2306,9 @@ win_line(
 # endif
                        syntax_attr = get_syntax_attr((colnr_T)v,
 # ifdef FEAT_SPELL
-                                               has_spell ? &can_spell :
+                                           spv->spv_has_spell ? &can_spell :
 # endif
-                                               NULL, FALSE);
+                                           NULL, FALSE);
                        prev_syntax_col = v;
                        prev_syntax_attr = syntax_attr;
                    }
@@ -2768,7 +2747,7 @@ win_line(
                // @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)
+               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,9 +2771,9 @@ win_line(
                            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);
+                       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,29 +2794,30 @@ win_line(
                        {
                            // 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 = (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 (spv->spv_cap_col > 0)
                        {
                            if (p != prev_ptr
-                                  && (p - nextline) + cap_col >= nextline_idx)
+                                   && (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 = ((p - nextline)
+                                           + spv->spv_cap_col - nextline_idx);
                            }
                            else
                                // Compute the actual column.
-                               cap_col += (int)(prev_ptr - line);
+                               spv->spv_cap_col += (prev_ptr - line);
                        }
                    }
                }
@@ -4119,15 +4099,6 @@ win_line(
        }
 
     }  // 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);
index 0912d7a1569d2a292aca62c8711fd3bbd0d34146..9676f1b0f0f375d5323743c55559b34ee9dee176 100644 (file)
@@ -2191,11 +2191,25 @@ win_update(win_T *wp)
        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;
-    lnum = wp->w_topline;      // first line shown in window
     for (;;)
     {
        // stop updating when reached the end of the window (check for _past_
@@ -2450,10 +2464,19 @@ win_update(win_T *wp)
                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 = lnum + fold_count;
+               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
@@ -2487,7 +2510,7 @@ win_update(win_T *wp)
 #endif
 
                // Display one line.
-               row = win_line(wp, lnum, srow, wp->w_height, mod_top, FALSE);
+               row = win_line(wp, lnum, srow, wp->w_height, FALSE, &spv);
 
 #ifdef FEAT_FOLDING
                wp->w_lines[idx].wl_folded = FALSE;
@@ -2534,7 +2557,7 @@ win_update(win_T *wp)
                    fold_line(wp, fold_count, &win_foldinfo, lnum, row);
                else
 #endif
-                   (void)win_line(wp, lnum, srow, wp->w_height, mod_top, TRUE);
+                   (void)win_line(wp, lnum, srow, wp->w_height, TRUE, &spv);
            }
 
            // This line does not need to be drawn, advance to the next one.
index fc6fb884176ab4e1d75ab4074d22b55abf10dc3c..141ca1b9c21dbef9883ff2b5336059d7e9870935 100644 (file)
@@ -1,4 +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);
+int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int number_only, spellvars_T *spv);
 /* vim: set ft=c : */
index 5df8f841a03f1fe2f570cc82d941c5feeb1d6b5a..3a32bc595d844f8cf70a00fd22cfe8db502fbeaf 100644 (file)
@@ -4870,3 +4870,18 @@ typedef struct
     // 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;
index b23d0667cbff9807d433ddb470a3dc2af4366e0c..27e558a52b906b06fab1738a53f5199dfb854993 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1585,
 /**/
     1584,
 /**/