]> granicus.if.org Git - vim/commitdiff
patch 8.1.2294: cursor pos wrong with concealing and search causes a scroll v8.1.2294
authorBram Moolenaar <Bram@vim.org>
Tue, 12 Nov 2019 19:49:15 +0000 (20:49 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 12 Nov 2019 19:49:15 +0000 (20:49 +0100)
Problem:    Cursor position wrong when characters are concealed and asearch
            causes a scroll.
Solution:   Fix the cursor column in a concealed line after window scroll.
            (closes #5215, closes #5012)

src/drawscreen.c
src/testdir/test_matchadd_conceal.vim
src/version.c

index 275925727b3ef8b5dea1cee2a0e38191825d26f2..de0fc6b974583edb63250cbbdfb9863e01569d48 100644 (file)
@@ -1398,7 +1398,11 @@ win_update(win_T *wp)
     int                i;
     long       j;
     static int recursive = FALSE;      // being called recursively
-    int                old_botline = wp->w_botline;
+    linenr_T   old_botline = wp->w_botline;
+#ifdef FEAT_CONCEAL
+    int                old_wrow = wp->w_wrow;
+    int                old_wcol = wp->w_wcol;
+#endif
 #ifdef FEAT_FOLDING
     long       fold_count;
 #endif
@@ -2567,18 +2571,52 @@ win_update(win_T *wp)
        wp->w_valid |= VALID_BOTLINE;
        if (wp == curwin && wp->w_botline != old_botline && !recursive)
        {
+           win_T       *wwp;
+#if defined(FEAT_CONCEAL)
+           linenr_T    old_topline = wp->w_topline;
+           int         new_wcol = wp->w_wcol;
+#endif
            recursive = TRUE;
            curwin->w_valid &= ~VALID_TOPLINE;
            update_topline();   // may invalidate w_botline again
-           if (must_redraw != 0)
+
+#if defined(FEAT_CONCEAL)
+           if (old_wcol != new_wcol && (wp->w_valid & (VALID_WCOL|VALID_WROW))
+                                                   != (VALID_WCOL|VALID_WROW))
+           {
+               // A win_line() call applied a fix to screen cursor column to
+               // accomodate concealment of cursor line, but in this call to
+               // update_topline() the cursor's row or column got invalidated.
+               // If they are left invalid, setcursor() will recompute them
+               // but there won't be any further win_line() call to re-fix the
+               // column and the cursor will end up misplaced.  So we call
+               // cursor validation now and reapply the fix again (or call
+               // win_line() to do it for us).
+               validate_cursor();
+               if (wp->w_wcol == old_wcol && wp->w_wrow == old_wrow
+                                              && old_topline == wp->w_topline)
+                   wp->w_wcol = new_wcol;
+               else
+                   redrawWinline(wp, wp->w_cursor.lnum);
+           }
+#endif
+           // New redraw either due to updated topline or due to wcol fix.
+           if (wp->w_redr_type != 0)
            {
                // Don't update for changes in buffer again.
                i = curbuf->b_mod_set;
                curbuf->b_mod_set = FALSE;
+               j = curbuf->b_mod_xlines;
+               curbuf->b_mod_xlines = 0;
                win_update(curwin);
-               must_redraw = 0;
                curbuf->b_mod_set = i;
+               curbuf->b_mod_xlines = j;
            }
+           // Other windows might have w_redr_type raised in update_topline().
+           must_redraw = 0;
+           FOR_ALL_WINDOWS(wwp)
+               if (wwp->w_redr_type > must_redraw)
+                   must_redraw = wwp->w_redr_type;
            recursive = FALSE;
        }
     }
index 6684378f665e18d82b476d56e151ba992520c887..83eadce5a5a91c61f36ae3b01419ca0a24cf4f8d 100644 (file)
@@ -8,6 +8,8 @@ if !has('gui_running') && has('unix')
 endif
 
 source shared.vim
+source term_util.vim
+source view_util.vim
 
 func Test_simple_matchadd()
   new
@@ -277,3 +279,40 @@ func Test_matchadd_and_syn_conceal()
   call assert_notequal(screenattr(1, 11) , screenattr(1, 12))
   call assert_equal(screenattr(1, 11) , screenattr(1, 32))
 endfunc
+
+func Test_cursor_column_in_concealed_line_after_window_scroll()
+  CheckRunVimInTerminal
+
+  " Test for issue #5012 fix.
+  " For a concealed line with cursor, there should be no window's cursor
+  " position invalidation during win_update() after scrolling attempt that is
+  " not successful and no real topline change happens. The invalidation would
+  " cause a window's cursor position recalc outside of win_line() where it's
+  " not possible to take conceal into account.
+  let lines =<< trim END
+    3split
+    let m = matchadd('Conceal', '=')
+    setl conceallevel=2 concealcursor=nc
+    normal gg
+    "==expr==
+  END
+  call writefile(lines, 'Xcolesearch')
+  let buf = RunVimInTerminal('Xcolesearch', {})
+
+  " Jump to something that is beyond the bottom of the window,
+  " so there's a scroll down.
+  call term_sendkeys(buf, ":so %\<CR>")
+  call term_sendkeys(buf, "/expr\<CR>")
+  call term_wait(buf)
+
+  " Are the concealed parts of the current line really hidden?
+  let cursor_row = term_scrape(buf, '.')->map({_, e -> e.chars})->join('')
+  call assert_equal('"expr', cursor_row)
+
+  " BugFix check: Is the window's cursor column properly updated for hidden
+  " parts of the current line?
+  call assert_equal(2, term_getcursor(buf)[1])
+
+  call StopVimInTerminal(buf)
+  call delete('Xcolesearch')
+endfunc
index 31133c53ee95d47dc4b6c9fad1893cab49bad5a5..e147ac30122c469aaecb9839b5088a13c2fcd57c 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2294,
 /**/
     2293,
 /**/