]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1578: SpellCap highlight not always updated when needed v9.0.1578
authorLuuk van Baal <luukvbaal@gmail.com>
Thu, 25 May 2023 16:14:42 +0000 (17:14 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 25 May 2023 16:14:42 +0000 (17:14 +0100)
Problem:    SpellCap highlight not always updated when needed.
Solution:   Handle updating line below closed fold and other situations where
            only part of the window is redrawn. (Luuk van Baal, closes #12428,
            closes #12420)

src/drawline.c
src/drawscreen.c
src/proto/spell.pro
src/spell.c
src/spellsuggest.c
src/testdir/dumps/Test_spell_6.dump [new file with mode: 0644]
src/testdir/dumps/Test_spell_7.dump [new file with mode: 0644]
src/testdir/dumps/Test_spell_8.dump [new file with mode: 0644]
src/testdir/test_spell.vim
src/version.c

index e5fa15cbeded9020a0f23ccd714efadb08079445..3791ece432c35e353f8ec22a15658135a7eb4df1 100644 (file)
@@ -1062,7 +1062,7 @@ win_line(
     linenr_T   lnum,
     int                startrow,
     int                endrow,
-    int                nochange UNUSED,        // not updating for changed text
+    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
@@ -1314,11 +1314,18 @@ win_line(
 
            // 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
+#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
@@ -2787,7 +2794,7 @@ win_line(
                            p = prev_ptr;
                        cap_col -= (int)(prev_ptr - line);
                        len = spell_check(wp, p, &spell_hlf, &cap_col,
-                                                                   nochange);
+                                                               mod_top == 0);
                        word_end = v + len;
 
                        // In Insert mode only highlight a word that
index a07c176d03407e7ea3a247b0cc7aea716d949c41..0912d7a1569d2a292aca62c8711fd3bbd0d34146 100644 (file)
@@ -2487,8 +2487,7 @@ win_update(win_T *wp)
 #endif
 
                // Display one line.
-               row = win_line(wp, lnum, srow, wp->w_height,
-                                                         mod_top == 0, FALSE);
+               row = win_line(wp, lnum, srow, wp->w_height, mod_top, FALSE);
 
 #ifdef FEAT_FOLDING
                wp->w_lines[idx].wl_folded = FALSE;
@@ -2535,7 +2534,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, TRUE, TRUE);
+                   (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.
index f6bad568ba86457983f4fbebeb2bebccd056b12c..98a1353493f67fa9178de5980a12c3ecc3d25ae1 100644 (file)
@@ -28,7 +28,7 @@ void init_spell_chartab(void);
 int spell_iswordp(char_u *p, win_T *wp);
 int spell_iswordp_nmw(char_u *p, win_T *wp);
 int spell_casefold(win_T *wp, char_u *str, int len, char_u *buf, int buflen);
-int check_need_cap(linenr_T lnum, colnr_T col);
+int check_need_cap(win_T *wp, linenr_T lnum, colnr_T col);
 void ex_spellrepall(exarg_T *eap);
 void onecap_copy(char_u *word, char_u *wcopy, int upper);
 void allcap_copy(char_u *word, char_u *wcopy);
index 071ac9c95bb77078d00c618a536a0b604d356501..db70fcf48a06f454f3a4fe2eadde19cd35202d63 100644 (file)
@@ -1342,7 +1342,7 @@ spell_move_to(
        {
            // For spellbadword(): check if first word needs a capital.
            col = getwhitecols(line);
-           if (check_need_cap(lnum, col))
+           if (check_need_cap(curwin, lnum, col))
                capcol = col;
 
            // Need to get the line again, may have looked at the previous
@@ -2815,24 +2815,20 @@ spell_casefold(
 
 /*
  * Check if the word at line "lnum" column "col" is required to start with a
- * capital.  This uses 'spellcapcheck' of the current buffer.
+ * capital.  This uses 'spellcapcheck' of the buffer in window "wp".
  */
     int
-check_need_cap(linenr_T lnum, colnr_T col)
+check_need_cap(win_T *wp, linenr_T lnum, colnr_T col)
 {
+    if (wp->w_s->b_cap_prog == NULL)
+       return FALSE;
+
     int                need_cap = FALSE;
-    char_u     *line;
+    char_u     *line = col ? ml_get_buf(wp->w_buffer, lnum, FALSE) : NULL;
     char_u     *line_copy = NULL;
-    char_u     *p;
-    colnr_T    endcol;
-    regmatch_T regmatch;
+    colnr_T    endcol = 0;
 
-    if (curwin->w_s->b_cap_prog == NULL)
-       return FALSE;
-
-    line = ml_get_curline();
-    endcol = 0;
-    if (getwhitecols(line) >= (int)col)
+    if (col == 0 || getwhitecols(line) >= col)
     {
        // At start of line, check if previous line is empty or sentence
        // ends there.
@@ -2840,13 +2836,16 @@ check_need_cap(linenr_T lnum, colnr_T col)
            need_cap = TRUE;
        else
        {
-           line = ml_get(lnum - 1);
+           line = ml_get_buf(wp->w_buffer, lnum - 1, FALSE);
            if (*skipwhite(line) == NUL)
                need_cap = TRUE;
            else
            {
                // Append a space in place of the line break.
                line_copy = concat_str(line, (char_u *)" ");
+               if (line_copy == NULL)
+                   return FALSE;
+
                line = line_copy;
                endcol = (colnr_T)STRLEN(line);
            }
@@ -2858,13 +2857,14 @@ check_need_cap(linenr_T lnum, colnr_T col)
     if (endcol > 0)
     {
        // Check if sentence ends before the bad word.
-       regmatch.regprog = curwin->w_s->b_cap_prog;
+       regmatch_T      regmatch;
+       regmatch.regprog = wp->w_s->b_cap_prog;
        regmatch.rm_ic = FALSE;
-       p = line + endcol;
+       char_u *p = line + endcol;
        for (;;)
        {
            MB_PTR_BACK(line, p);
-           if (p == line || spell_iswordp_nmw(p, curwin))
+           if (p == line || spell_iswordp_nmw(p, wp))
                break;
            if (vim_regexec(&regmatch, p, 0)
                                         && regmatch.endp[0] == line + endcol)
@@ -2873,7 +2873,7 @@ check_need_cap(linenr_T lnum, colnr_T col)
                break;
            }
        }
-       curwin->w_s->b_cap_prog = regmatch.regprog;
+       wp->w_s->b_cap_prog = regmatch.regprog;
     }
 
     vim_free(line_copy);
@@ -4340,7 +4340,7 @@ static int spell_expand_need_cap;
     void
 spell_expand_check_cap(colnr_T col)
 {
-    spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col);
+    spell_expand_need_cap = check_need_cap(curwin, curwin->w_cursor.lnum, col);
 }
 
 /*
index 1084230a574582f04894ca0ebb3fa4f43dab04ae..42eb434ad635555430049768c830d678823668bf 100644 (file)
@@ -538,7 +538,8 @@ spell_suggest(int count)
     // Get the word and its length.
 
     // Figure out if the word should be capitalised.
-    need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
+    need_cap = check_need_cap(curwin, curwin->w_cursor.lnum,
+                                                       curwin->w_cursor.col);
 
     // Make a copy of current line since autocommands may free the line.
     line = vim_strsave(ml_get_curline());
diff --git a/src/testdir/dumps/Test_spell_6.dump b/src/testdir/dumps/Test_spell_6.dump
new file mode 100644 (file)
index 0000000..5c000ed
--- /dev/null
@@ -0,0 +1,8 @@
+| +0&#ffffff0@2|T|h|i|s| |l|i|n|e| |h|a|s| |a| |s+0&#ffd7d7255|e|p|l@1| +0&#ffffff0|e|r@1|o|r|.| |a+0&#5fd7ff255|n|d| +0&#ffffff0|m|i|s@1|i|n|g| |c|a|p|s| |a|n|d| |t|r|a|i|l|i|n|g| |s|p|a|c|e|s|.| @5
+|a+0&#5fd7ff255|n|o|t|h|e|r| +0&#ffffff0|m|i|s@1|i|n|g| |c|a|p| |h|e|r|e|.| @49
+|N|o|t| @71
+>++0#0000e05#a8a8a8255|-@1| @1|2| |l|i|n|e|s|:| |a|n|d| |h|e|r|e|.|-@51
+|a+0#0000000#5fd7ff255|n|d| +0&#ffffff0|h|e|r|e|.| @65
+|~+0#4040ff13&| @73
+|~| @73
+| +0#0000000&@56|4|,|4|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_spell_7.dump b/src/testdir/dumps/Test_spell_7.dump
new file mode 100644 (file)
index 0000000..42c52fe
--- /dev/null
@@ -0,0 +1,8 @@
+| +0&#ffffff0@2|T|h|i|s| |l|i|n|e| |h|a|s| |a| |s+0&#ffd7d7255|e|p|l@1| +0&#ffffff0|e|r@1|o|r|.| |a+0&#5fd7ff255|n|d| +0&#ffffff0|m|i|s@1|i|n|g| |c|a|p|s| |a|n|d| |t|r|a|i|l|i|n|g| |s|p|a|c|e|s|.| @5
+|a+0&#5fd7ff255|n|o|t|h|e|r| +0&#ffffff0|m|i|s@1|i|n|g| |c|a|p| |h|e|r>e| @50
+|++0#0000e05#a8a8a8255|-@1| @1|2| |l|i|n|e|s|:| |N|o|t|-@57
+|a+0#0000000#5fd7ff255|n|d| +0&#ffffff0|h|e|r|e|.| @65
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|2|,|2|4| @9|A|l@1| 
diff --git a/src/testdir/dumps/Test_spell_8.dump b/src/testdir/dumps/Test_spell_8.dump
new file mode 100644 (file)
index 0000000..2f34240
--- /dev/null
@@ -0,0 +1,8 @@
+|a+0&#5fd7ff255|n|o|t|h|e|r| +0&#ffffff0|m|i|s@1|i|n|g| |c|a|p| |h|e|r|e| @50
+|++0#0000e05#a8a8a8255|-@1| @1|2| |l|i|n|e|s|:| |N|o|t|-@57
+|a+0#0000000#5fd7ff255|n|d| +0&#ffffff0|h|e|r|e>.| @65
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|5|,|9| @10|B|o|t| 
index bd387f11d22109be2a066ccf3cb87413849cbd39..350077ad2a0734dc54c519eda604399ae3cb1f80 100644 (file)
@@ -999,13 +999,26 @@ func Test_spell_screendump_spellcap()
   call VerifyScreenDump(buf, 'Test_spell_3', {})
 
   " Deleting a full stop removes missing Cap in next line
-  call term_sendkeys(buf, "5Gddk$x")
+  call term_sendkeys(buf, "5Gdd\<C-L>k$x")
   call VerifyScreenDump(buf, 'Test_spell_4', {})
 
   " Undo also updates the next line (go to command line to remove message)
   call term_sendkeys(buf, "u:\<Esc>")
   call VerifyScreenDump(buf, 'Test_spell_5', {})
 
+  " Folding an empty line does not remove Cap in next line
+  call term_sendkeys(buf, "uzfk:\<Esc>")
+  call VerifyScreenDump(buf, 'Test_spell_6', {})
+
+  " Folding the end of a sentence does not remove Cap in next line
+  " and editing a line does not remove Cap in current line
+  call term_sendkeys(buf, "Jzfkk$x")
+  call VerifyScreenDump(buf, 'Test_spell_7', {})
+
+  " Cap is correctly applied in the first row of a window
+  call term_sendkeys(buf, "\<C-E>\<C-L>")
+  call VerifyScreenDump(buf, 'Test_spell_8', {})
+
   " clean up
   call StopVimInTerminal(buf)
 endfunc
index 02be5bf57dc9027f251ecde609eee8b886b85121..2e8244d3f412091f8966e3930937c32c2112a633 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1578,
 /**/
     1577,
 /**/