]> granicus.if.org Git - vim/commitdiff
patch 8.1.1751: when redrawing popups plines_win() may be called often v8.1.1751
authorBram Moolenaar <Bram@vim.org>
Fri, 26 Jul 2019 19:01:29 +0000 (21:01 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 26 Jul 2019 19:01:29 +0000 (21:01 +0200)
Problem:    When redrawing popups plines_win() may be called often.
Solution:   Pass a cache to mouse_comp_pos().

src/beval.c
src/evalfunc.c
src/popupwin.c
src/proto/ui.pro
src/ui.c
src/version.c

index 3dd9b6770c1a28b2aab17c57ff3c62d6518010ce..69e667d63971e78cd4742a99ed527c0eac18f9bd 100644 (file)
@@ -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);
index 73efa79f2cdb93211f35b72f8bbd8661f93dc141..685e2f1e41c7285d9e564ba94f7542492fd661e6 100644 (file)
@@ -4738,7 +4738,7 @@ f_getchar(typval_T *argvars, typval_T *rettv)
                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;
index a303582be61fbd4f6dd2bf13d70b87ff0c374517..d0f6156adf8fcd61d89b8fef15de9cccb7da1bc8 100644 (file)
@@ -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);
+    }
 }
 
 /*
index 7b28a32a2be89078f87bb358240fa2352082cd6a..472da3601bb1005f9b19f9e09af8d87a3fe8f008 100644 (file)
@@ -64,7 +64,7 @@ void clip_x11_set_selection(Clipboard_T *cbd);
 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);
index 1e6c1464a3c1f5f4f7bdcddbf320b907b02f9763..5d04e1b97f3e0d12587616f9229ea1f9cd244ec2 100644 (file)
--- 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)
     {
+       int cache_idx = lnum - win->w_topline;
+
+       if (plines_cache != NULL && plines_cache[cache_idx] > 0)
+           count = plines_cache[cache_idx];
+       else
+       {
 #ifdef FEAT_DIFF
-       /* Don't include filler lines in "count" */
-       if (win->w_p_diff
+           /* Don't include filler lines in "count" */
+           if (win->w_p_diff
 # ifdef FEAT_FOLDING
-               && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
+                   && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
 # endif
-               )
-       {
-           if (lnum == win->w_topline)
-               row -= win->w_topfill;
+                   )
+           {
+               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);
-       }
-       else
 #endif
-           count = plines_win(win, lnum, TRUE);
+               count = plines_win(win, lnum, TRUE);
+           if (plines_cache != NULL)
+               plines_cache[cache_idx] = count;
+       }
        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);
index 5c7507845a02dd38dae9b875e69f9a1576c6e082..5104f6a992b857f2de140098d741e8e13b978781 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1751,
 /**/
     1750,
 /**/