# HG changeset patch # User Bram Moolenaar # Date 1647688504 -3600 # Node ID 373f1afadfa38906707ae3401256c813e08d8cdd # Parent a4c48c2beb9f2d213ddfa3f942fd30d3992204fe patch 8.2.4591: cursor line not updated when a callback moves the cursor Commit: https://github.com/vim/vim/commit/e7a74d53754765f22ef8ce71c915bb669d5f7f3f Author: Bram Moolenaar Date: Sat Mar 19 11:10:15 2022 +0000 patch 8.2.4591: cursor line not updated when a callback moves the cursor Problem: Cursor line not updated when a callback moves the cursor. Solution: Check if the cursor moved. (closes https://github.com/vim/vim/issues/9970) diff --git a/src/drawscreen.c b/src/drawscreen.c --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -1463,11 +1463,14 @@ win_update(win_T *wp) #ifdef FEAT_SYN_HL // remember what happened to the previous line, to know if // check_visual_highlight() can be used -#define DID_NONE 1 // didn't update a line -#define DID_LINE 2 // updated a normal line -#define DID_FOLD 3 // updated a folded line +# define DID_NONE 1 // didn't update a line +# define DID_LINE 2 // updated a normal line +# define DID_FOLD 3 // updated a folded line int did_update = DID_NONE; linenr_T syntax_last_parsed = 0; // last parsed text line + // remember the current w_last_cursorline, it changes when drawing the new + // cursor line + linenr_T last_cursorline = wp->w_last_cursorline; #endif linenr_T mod_top = 0; linenr_T mod_bot = 0; @@ -2244,7 +2247,7 @@ win_update(win_T *wp) )))) #ifdef FEAT_SYN_HL || (wp->w_p_cul && (lnum == wp->w_cursor.lnum - || lnum == wp->w_last_cursorline)) + || lnum == last_cursorline)) #endif ) { @@ -3027,6 +3030,23 @@ redraw_asap(int type) } #endif +#if defined(FEAT_SYN_HL) || defined(PROTO) +/* + * Check if the cursor moved and 'cursorline' is set. Mark for a VALID redraw + * if needed. + */ + void +check_redraw_cursorline(void) +{ + // When 'cursorlineopt' is "screenline" need to redraw always. + if (curwin->w_p_cul + && (curwin->w_last_cursorline != curwin->w_cursor.lnum + || (curwin->w_p_culopt_flags & CULOPT_SCRLINE)) + && !char_avail()) + redraw_later(VALID); +} +#endif + /* * Invoked after an asynchronous callback is called. * If an echo command was used the cursor needs to be put back where @@ -3071,6 +3091,10 @@ redraw_after_callback(int call_update_sc } else if (State & (NORMAL | INSERT | TERMINAL)) { +#ifdef FEAT_SYN_HL + // might need to update for 'cursorline' + check_redraw_cursorline(); +#endif // keep the command line if possible update_screen(VALID_NO_UPDATE); setcursor(); diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -1386,12 +1386,7 @@ main_loop( #ifdef FEAT_SYN_HL // Might need to update for 'cursorline'. - // When 'cursorlineopt' is "screenline" need to redraw always. - if (curwin->w_p_cul - && (curwin->w_last_cursorline != curwin->w_cursor.lnum - || (curwin->w_p_culopt_flags & CULOPT_SCRLINE)) - && !char_avail()) - redraw_later(VALID); + check_redraw_cursorline(); #endif if (VIsual_active) update_curbuf(INVERTED); // update inverted part diff --git a/src/proto/drawscreen.pro b/src/proto/drawscreen.pro --- a/src/proto/drawscreen.pro +++ b/src/proto/drawscreen.pro @@ -8,6 +8,7 @@ void update_curbuf(int type); void update_debug_sign(buf_T *buf, linenr_T lnum); void updateWindow(win_T *wp); int redraw_asap(int type); +void check_redraw_cursorline(void); void redraw_after_callback(int call_update_screen, int do_message); void redraw_later(int type); void redraw_win_later(win_T *wp, int type); diff --git a/src/testdir/dumps/Test_cursorline_callback_1.dump b/src/testdir/dumps/Test_cursorline_callback_1.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_cursorline_callback_1.dump @@ -0,0 +1,8 @@ +|a+0&#ffffff0@4| @69 +>b+8&&@4| @69 +|c+0&&@4| @69 +|d@4| @69 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|4|,|1| @10|A|l@1| diff --git a/src/testdir/test_cursorline.vim b/src/testdir/test_cursorline.vim --- a/src/testdir/test_cursorline.vim +++ b/src/testdir/test_cursorline.vim @@ -247,4 +247,30 @@ END call delete('Xtextfile') endfunc +func Test_cursorline_callback() + CheckScreendump + CheckFeature timers + + let lines =<< trim END + call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) + set cursorline + call cursor(4, 1) + + func Func(timer) + call cursor(2, 1) + endfunc + + call timer_start(300, 'Func') + END + call writefile(lines, 'Xcul_timer') + + let buf = RunVimInTerminal('-S Xcul_timer', #{rows: 8}) + call TermWait(buf, 310) + call VerifyScreenDump(buf, 'Test_cursorline_callback_1', {}) + + call StopVimInTerminal(buf) + call delete('Xcul_timer') +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4591, +/**/ 4590, /**/ 4589,