To: vim_dev@googlegroups.com Subject: Patch 9.0.1578 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1578 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) Files: src/drawline.c, src/drawscreen.c, src/spell.c, src/proto/spell.pro, src/spellsuggest.c, src/testdir/test_spell.vim, src/testdir/dumps/Test_spell_6.dump, src/testdir/dumps/Test_spell_7.dump, src/testdir/dumps/Test_spell_8.dump *** ../vim-9.0.1577/src/drawline.c 2023-05-02 20:52:32.047787527 +0100 --- src/drawline.c 2023-05-25 17:08:43.287047551 +0100 *************** *** 1062,1068 **** linenr_T lnum, int startrow, int endrow, ! int nochange UNUSED, // not updating for changed text int number_only) // only update the number column { winlinevars_T wlv; // variables passed between functions --- 1062,1068 ---- 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 *************** *** 1314,1324 **** // 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) cap_col = 0; capcol_lnum = 0; } #endif --- 1314,1331 ---- // 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 *************** *** 2787,2793 **** p = prev_ptr; cap_col -= (int)(prev_ptr - line); len = spell_check(wp, p, &spell_hlf, &cap_col, ! nochange); word_end = v + len; // In Insert mode only highlight a word that --- 2794,2800 ---- 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 *** ../vim-9.0.1577/src/drawscreen.c 2023-05-06 12:39:58.736971487 +0100 --- src/drawscreen.c 2023-05-25 17:08:43.287047551 +0100 *************** *** 2487,2494 **** #endif // Display one line. ! row = win_line(wp, lnum, srow, wp->w_height, ! mod_top == 0, FALSE); #ifdef FEAT_FOLDING wp->w_lines[idx].wl_folded = FALSE; --- 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; *************** *** 2535,2541 **** fold_line(wp, fold_count, &win_foldinfo, lnum, row); else #endif ! (void)win_line(wp, lnum, srow, wp->w_height, TRUE, TRUE); } // This line does not need to be drawn, advance to the next one. --- 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. *** ../vim-9.0.1577/src/spell.c 2023-02-20 12:16:33.336269408 +0000 --- src/spell.c 2023-05-25 17:08:43.291047554 +0100 *************** *** 1342,1348 **** { // For spellbadword(): check if first word needs a capital. col = getwhitecols(line); ! if (check_need_cap(lnum, col)) capcol = col; // Need to get the line again, may have looked at the previous --- 1342,1348 ---- { // For spellbadword(): check if first word needs a capital. col = getwhitecols(line); ! if (check_need_cap(curwin, lnum, col)) capcol = col; // Need to get the line again, may have looked at the previous *************** *** 2815,2838 **** /* * Check if the word at line "lnum" column "col" is required to start with a ! * capital. This uses 'spellcapcheck' of the current buffer. */ int ! check_need_cap(linenr_T lnum, colnr_T col) { int need_cap = FALSE; ! char_u *line; char_u *line_copy = NULL; ! char_u *p; ! colnr_T endcol; ! regmatch_T regmatch; ! if (curwin->w_s->b_cap_prog == NULL) ! return FALSE; ! ! line = ml_get_curline(); ! endcol = 0; ! if (getwhitecols(line) >= (int)col) { // At start of line, check if previous line is empty or sentence // ends there. --- 2815,2834 ---- /* * Check if the word at line "lnum" column "col" is required to start with a ! * capital. This uses 'spellcapcheck' of the buffer in window "wp". */ int ! 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 = col ? ml_get_buf(wp->w_buffer, lnum, FALSE) : NULL; char_u *line_copy = NULL; ! colnr_T endcol = 0; ! if (col == 0 || getwhitecols(line) >= col) { // At start of line, check if previous line is empty or sentence // ends there. *************** *** 2840,2852 **** need_cap = TRUE; else { ! line = ml_get(lnum - 1); if (*skipwhite(line) == NUL) need_cap = TRUE; else { // Append a space in place of the line break. line_copy = concat_str(line, (char_u *)" "); line = line_copy; endcol = (colnr_T)STRLEN(line); } --- 2836,2851 ---- need_cap = TRUE; else { ! 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,2870 **** if (endcol > 0) { // Check if sentence ends before the bad word. ! regmatch.regprog = curwin->w_s->b_cap_prog; regmatch.rm_ic = FALSE; ! p = line + endcol; for (;;) { MB_PTR_BACK(line, p); ! if (p == line || spell_iswordp_nmw(p, curwin)) break; if (vim_regexec(®match, p, 0) && regmatch.endp[0] == line + endcol) --- 2857,2870 ---- if (endcol > 0) { // Check if sentence ends before the bad word. ! regmatch_T regmatch; ! regmatch.regprog = wp->w_s->b_cap_prog; regmatch.rm_ic = FALSE; ! char_u *p = line + endcol; for (;;) { MB_PTR_BACK(line, p); ! if (p == line || spell_iswordp_nmw(p, wp)) break; if (vim_regexec(®match, p, 0) && regmatch.endp[0] == line + endcol) *************** *** 2873,2879 **** break; } } ! curwin->w_s->b_cap_prog = regmatch.regprog; } vim_free(line_copy); --- 2873,2879 ---- break; } } ! wp->w_s->b_cap_prog = regmatch.regprog; } vim_free(line_copy); *************** *** 4340,4346 **** void spell_expand_check_cap(colnr_T col) { ! spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col); } /* --- 4340,4346 ---- void spell_expand_check_cap(colnr_T col) { ! spell_expand_need_cap = check_need_cap(curwin, curwin->w_cursor.lnum, col); } /* *** ../vim-9.0.1577/src/proto/spell.pro 2023-02-20 12:16:33.336269408 +0000 --- src/proto/spell.pro 2023-05-25 17:11:52.183303177 +0100 *************** *** 28,34 **** 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); 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); --- 28,34 ---- 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(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); *** ../vim-9.0.1577/src/spellsuggest.c 2023-03-07 17:13:47.313107772 +0000 --- src/spellsuggest.c 2023-05-25 17:08:43.291047554 +0100 *************** *** 538,544 **** // 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); // Make a copy of current line since autocommands may free the line. line = vim_strsave(ml_get_curline()); --- 538,545 ---- // Get the word and its length. // Figure out if the word should be capitalised. ! 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()); *** ../vim-9.0.1577/src/testdir/test_spell.vim 2022-11-14 20:52:11.277268383 +0000 --- src/testdir/test_spell.vim 2023-05-25 17:08:43.291047554 +0100 *************** *** 999,1011 **** call VerifyScreenDump(buf, 'Test_spell_3', {}) " Deleting a full stop removes missing Cap in next line ! call term_sendkeys(buf, "5Gddk$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:\") call VerifyScreenDump(buf, 'Test_spell_5', {}) " clean up call StopVimInTerminal(buf) endfunc --- 999,1024 ---- call VerifyScreenDump(buf, 'Test_spell_3', {}) " Deleting a full stop removes missing Cap in next line ! call term_sendkeys(buf, "5Gdd\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:\") call VerifyScreenDump(buf, 'Test_spell_5', {}) + " Folding an empty line does not remove Cap in next line + call term_sendkeys(buf, "uzfk:\") + 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, "\\") + call VerifyScreenDump(buf, 'Test_spell_8', {}) + " clean up call StopVimInTerminal(buf) endfunc *** ../vim-9.0.1577/src/testdir/dumps/Test_spell_6.dump 2023-05-25 17:14:07.015468776 +0100 --- src/testdir/dumps/Test_spell_6.dump 2023-05-25 17:08:43.291047554 +0100 *************** *** 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+0fd7ff255|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+0fd7ff255|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| *** ../vim-9.0.1577/src/testdir/dumps/Test_spell_7.dump 2023-05-25 17:14:07.019468782 +0100 --- src/testdir/dumps/Test_spell_7.dump 2023-05-25 17:08:43.291047554 +0100 *************** *** 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+0fd7ff255|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+0fd7ff255|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| *** ../vim-9.0.1577/src/testdir/dumps/Test_spell_8.dump 2023-05-25 17:14:07.023468785 +0100 --- src/testdir/dumps/Test_spell_8.dump 2023-05-25 17:08:43.291047554 +0100 *************** *** 0 **** --- 1,8 ---- + |a+0fd7ff255|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| *** ../vim-9.0.1577/src/version.c 2023-05-25 16:43:23.758752677 +0100 --- src/version.c 2023-05-25 17:11:13.279249455 +0100 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1578, /**/ -- hundred-and-one symptoms of being an internet addict: 78. You find yourself dialing IP numbers on the phone. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///