# HG changeset patch # User Bram Moolenaar # Date 1564168506 -7200 # Node ID 74b6674b99fdda889a94ce1bcaf5cbe96251d707 # Parent a76219d230b3b966ae263336bc91bc4d6d0b1c87 patch 8.1.1751: when redrawing popups plines_win() may be called often commit https://github.com/vim/vim/commit/9d5ffceb3fea247a88d4d3936e97b7f488aab6ff Author: Bram Moolenaar Date: Fri Jul 26 21:01:29 2019 +0200 patch 8.1.1751: when redrawing popups plines_win() may be called often Problem: When redrawing popups plines_win() may be called often. Solution: Pass a cache to mouse_comp_pos(). diff --git a/src/beval.c b/src/beval.c --- a/src/beval.c +++ b/src/beval.c @@ -43,7 +43,7 @@ find_word_under_cursor( { // Found a window and the cursor is in the text. Now find the line // number. - if (!mouse_comp_pos(wp, &row, &col, &lnum)) + if (!mouse_comp_pos(wp, &row, &col, &lnum, NULL)) { // Not past end of the file. lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE); diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -4738,7 +4738,7 @@ f_getchar(typval_T *argvars, typval_T *r win = mouse_find_win(&row, &col, FIND_POPUP); if (win == NULL) return; - (void)mouse_comp_pos(win, &row, &col, &lnum); + (void)mouse_comp_pos(win, &row, &col, &lnum, NULL); # ifdef FEAT_TEXT_PROP if (WIN_IS_POPUP(win)) winnr = 0; diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -2593,6 +2593,10 @@ may_update_popup_mask(int type) // Only check which lines are to be updated if not already // updating all lines. if (mask == popup_mask_next) + { + int *plines_cache = ALLOC_CLEAR_MULT(int, Rows); + win_T *prev_wp = NULL; + for (line = 0; line < screen_Rows; ++line) { int col_done = 0; @@ -2625,13 +2629,19 @@ may_update_popup_mask(int type) wp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP); if (wp != NULL) { + if (wp != prev_wp) + { + vim_memset(plines_cache, 0, sizeof(int) * Rows); + prev_wp = wp; + } + if (line_cp >= wp->w_height) // In (or below) status line wp->w_redr_status = TRUE; // compute the position in the buffer line from the // position on the screen else if (mouse_comp_pos(wp, &line_cp, &col_cp, - &lnum)) + &lnum, plines_cache)) // past bottom wp->w_redr_status = TRUE; else @@ -2645,6 +2655,9 @@ may_update_popup_mask(int type) } } } + + vim_free(plines_cache); + } } /* diff --git a/src/proto/ui.pro b/src/proto/ui.pro --- a/src/proto/ui.pro +++ b/src/proto/ui.pro @@ -64,7 +64,7 @@ void clip_x11_set_selection(Clipboard_T int clip_x11_owner_exists(Clipboard_T *cbd); void yank_cut_buffer0(Display *dpy, Clipboard_T *cbd); int jump_to_mouse(int flags, int *inclusive, int which_button); -int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump); +int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int *plines_cache); win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup); int get_fpos_of_mouse(pos_T *mpos); int vcol2col(win_T *wp, linenr_T lnum, int vcol); diff --git a/src/ui.c b/src/ui.c --- a/src/ui.c +++ b/src/ui.c @@ -3381,7 +3381,7 @@ retnomove: #endif /* compute the position in the buffer line from the posn on the screen */ - if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) + if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum, NULL)) mouse_past_bottom = TRUE; /* Start Visual mode before coladvance(), for when 'sel' != "old" */ @@ -3429,8 +3429,12 @@ retnomove: #if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO) /* - * Compute the position in the buffer line from the posn on the screen in + * Compute the buffer line position from the screen position "rowp" / "colp" in * window "win". + * "plines_cache" can be NULL (no cache) or an array with "win->w_height" + * entries that caches the plines_win() result from a previous call. Entry is + * zero if not computed yet. There must be no text or setting changes since + * the entry is put in the cache. * Returns TRUE if the position is below the last line. */ int @@ -3438,7 +3442,8 @@ mouse_comp_pos( win_T *win, int *rowp, int *colp, - linenr_T *lnump) + linenr_T *lnump, + int *plines_cache) { int col = *colp; int row = *rowp; @@ -3456,23 +3461,32 @@ mouse_comp_pos( while (row > 0) { -#ifdef FEAT_DIFF - /* Don't include filler lines in "count" */ - if (win->w_p_diff -# ifdef FEAT_FOLDING - && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL) -# endif - ) + int cache_idx = lnum - win->w_topline; + + if (plines_cache != NULL && plines_cache[cache_idx] > 0) + count = plines_cache[cache_idx]; + else { - if (lnum == win->w_topline) - row -= win->w_topfill; +#ifdef FEAT_DIFF + /* Don't include filler lines in "count" */ + if (win->w_p_diff +# ifdef FEAT_FOLDING + && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL) +# endif + ) + { + if (lnum == win->w_topline) + row -= win->w_topfill; + else + row -= diff_check_fill(win, lnum); + count = plines_win_nofill(win, lnum, TRUE); + } else - row -= diff_check_fill(win, lnum); - count = plines_win_nofill(win, lnum, TRUE); +#endif + count = plines_win(win, lnum, TRUE); + if (plines_cache != NULL) + plines_cache[cache_idx] = count; } - else -#endif - count = plines_win(win, lnum, TRUE); if (count > row) break; /* Position is in this buffer line. */ #ifdef FEAT_FOLDING @@ -3626,7 +3640,7 @@ get_fpos_of_mouse(pos_T *mpos) return IN_UNKNOWN; /* compute the position in the buffer line from the posn on the screen */ - if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum)) + if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum, NULL)) return IN_STATUS_LINE; /* past bottom */ mpos->col = vcol2col(wp, mpos->lnum, col); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1751, +/**/ 1750, /**/ 1749,