]> granicus.if.org Git - vim/commitdiff
patch 9.0.0867: wildmenu redrawing code is spread out v9.0.0867
authorBram Moolenaar <Bram@vim.org>
Sat, 12 Nov 2022 17:44:13 +0000 (17:44 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 12 Nov 2022 17:44:13 +0000 (17:44 +0000)
Problem:    Wildmenu redrawing code is spread out.
Solution:   Refactor to move code together. (closes #11528)

src/cmdexpand.c
src/proto/cmdexpand.pro
src/proto/screen.pro
src/screen.c
src/version.c

index e0ad1a77f26eeb1cefe283a9ce800d55d60b69f4..2dbde4ef7751684b74c36a56eb124437d2cb98bf 100644 (file)
@@ -19,6 +19,7 @@ static int      ExpandGeneric(char_u *pat, expand_T *xp, regmatch_T *regmatch,
                              char_u ***matches, int *numMatches,
                              char_u *((*func)(expand_T *, int)), int escaped);
 static int     ExpandFromContext(expand_T *xp, char_u *, char_u ***, int *, int);
+static char_u  *showmatches_gettail(char_u *s);
 static int     expand_showtail(expand_T *xp);
 static int     expand_shellcmd(char_u *filepat, char_u ***matches, int *numMatches, int flagsarg);
 #if defined(FEAT_EVAL)
@@ -34,7 +35,7 @@ static int compl_match_arraysize;
 static int compl_startcol;
 static int compl_selected;
 
-#define SHOW_FILE_TEXT(m) (showtail ? sm_gettail(matches[m]) : matches[m])
+#define SHOW_FILE_TEXT(m) (showtail ? showmatches_gettail(matches[m]) : matches[m])
 
 /*
  * Returns TRUE if fuzzy completion is supported for a given cmdline completion
@@ -334,7 +335,7 @@ cmdline_pum_create(
     columns = vim_strsize(xp->xp_pattern);
     if (showtail)
     {
-       columns += vim_strsize(sm_gettail(matches[0]));
+       columns += vim_strsize(showmatches_gettail(matches[0]));
        columns -= vim_strsize(matches[0]);
     }
     if (columns >= compl_startcol)
@@ -402,6 +403,272 @@ int cmdline_compl_startcol(void)
     return compl_startcol;
 }
 
+/*
+ * Return the number of characters that should be skipped in a status match.
+ * These are backslashes used for escaping.  Do show backslashes in help tags.
+ */
+    static int
+skip_status_match_char(expand_T *xp, char_u *s)
+{
+    if ((rem_backslash(s) && xp->xp_context != EXPAND_HELP)
+#ifdef FEAT_MENU
+           || ((xp->xp_context == EXPAND_MENUS
+                   || xp->xp_context == EXPAND_MENUNAMES)
+                         && (s[0] == '\t' || (s[0] == '\\' && s[1] != NUL)))
+#endif
+          )
+    {
+#ifndef BACKSLASH_IN_FILENAME
+       if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!')
+           return 2;
+#endif
+       return 1;
+    }
+    return 0;
+}
+
+/*
+ * Get the length of an item as it will be shown in the status line.
+ */
+    static int
+status_match_len(expand_T *xp, char_u *s)
+{
+    int        len = 0;
+
+#ifdef FEAT_MENU
+    int emenu = xp->xp_context == EXPAND_MENUS
+            || xp->xp_context == EXPAND_MENUNAMES;
+
+    // Check for menu separators - replace with '|'.
+    if (emenu && menu_is_separator(s))
+       return 1;
+#endif
+
+    while (*s != NUL)
+    {
+       s += skip_status_match_char(xp, s);
+       len += ptr2cells(s);
+       MB_PTR_ADV(s);
+    }
+
+    return len;
+}
+
+/*
+ * Show wildchar matches in the status line.
+ * Show at least the "match" item.
+ * We start at item 'first_match' in the list and show all matches that fit.
+ *
+ * If inversion is possible we use it. Else '=' characters are used.
+ */
+    static void
+win_redr_status_matches(
+    expand_T   *xp,
+    int                num_matches,
+    char_u     **matches,      // list of matches
+    int                match,
+    int                showtail)
+{
+#define L_MATCH(m) (showtail ? showmatches_gettail(matches[m]) : matches[m])
+    int                row;
+    char_u     *buf;
+    int                len;
+    int                clen;           // length in screen cells
+    int                fillchar;
+    int                attr;
+    int                i;
+    int                highlight = TRUE;
+    char_u     *selstart = NULL;
+    int                selstart_col = 0;
+    char_u     *selend = NULL;
+    static int first_match = 0;
+    int                add_left = FALSE;
+    char_u     *s;
+#ifdef FEAT_MENU
+    int                emenu;
+#endif
+    int                l;
+
+    if (matches == NULL)       // interrupted completion?
+       return;
+
+    if (has_mbyte)
+       buf = alloc(Columns * MB_MAXBYTES + 1);
+    else
+       buf = alloc(Columns + 1);
+    if (buf == NULL)
+       return;
+
+    if (match == -1)   // don't show match but original text
+    {
+       match = 0;
+       highlight = FALSE;
+    }
+    // count 1 for the ending ">"
+    clen = status_match_len(xp, L_MATCH(match)) + 3;
+    if (match == 0)
+       first_match = 0;
+    else if (match < first_match)
+    {
+       // jumping left, as far as we can go
+       first_match = match;
+       add_left = TRUE;
+    }
+    else
+    {
+       // check if match fits on the screen
+       for (i = first_match; i < match; ++i)
+           clen += status_match_len(xp, L_MATCH(i)) + 2;
+       if (first_match > 0)
+           clen += 2;
+       // jumping right, put match at the left
+       if ((long)clen > Columns)
+       {
+           first_match = match;
+           // if showing the last match, we can add some on the left
+           clen = 2;
+           for (i = match; i < num_matches; ++i)
+           {
+               clen += status_match_len(xp, L_MATCH(i)) + 2;
+               if ((long)clen >= Columns)
+                   break;
+           }
+           if (i == num_matches)
+               add_left = TRUE;
+       }
+    }
+    if (add_left)
+       while (first_match > 0)
+       {
+           clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2;
+           if ((long)clen >= Columns)
+               break;
+           --first_match;
+       }
+
+    fillchar = fillchar_status(&attr, curwin);
+
+    if (first_match == 0)
+    {
+       *buf = NUL;
+       len = 0;
+    }
+    else
+    {
+       STRCPY(buf, "< ");
+       len = 2;
+    }
+    clen = len;
+
+    i = first_match;
+    while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < Columns)
+    {
+       if (i == match)
+       {
+           selstart = buf + len;
+           selstart_col = clen;
+       }
+
+       s = L_MATCH(i);
+       // Check for menu separators - replace with '|'
+#ifdef FEAT_MENU
+       emenu = (xp->xp_context == EXPAND_MENUS
+               || xp->xp_context == EXPAND_MENUNAMES);
+       if (emenu && menu_is_separator(s))
+       {
+           STRCPY(buf + len, transchar('|'));
+           l = (int)STRLEN(buf + len);
+           len += l;
+           clen += l;
+       }
+       else
+#endif
+           for ( ; *s != NUL; ++s)
+       {
+           s += skip_status_match_char(xp, s);
+           clen += ptr2cells(s);
+           if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1)
+           {
+               STRNCPY(buf + len, s, l);
+               s += l - 1;
+               len += l;
+           }
+           else
+           {
+               STRCPY(buf + len, transchar_byte(*s));
+               len += (int)STRLEN(buf + len);
+           }
+       }
+       if (i == match)
+           selend = buf + len;
+
+       *(buf + len++) = ' ';
+       *(buf + len++) = ' ';
+       clen += 2;
+       if (++i == num_matches)
+               break;
+    }
+
+    if (i != num_matches)
+    {
+       *(buf + len++) = '>';
+       ++clen;
+    }
+
+    buf[len] = NUL;
+
+    row = cmdline_row - 1;
+    if (row >= 0)
+    {
+       if (wild_menu_showing == 0)
+       {
+           if (msg_scrolled > 0)
+           {
+               // Put the wildmenu just above the command line.  If there is
+               // no room, scroll the screen one line up.
+               if (cmdline_row == Rows - 1)
+               {
+                   screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL);
+                   ++msg_scrolled;
+               }
+               else
+               {
+                   ++cmdline_row;
+                   ++row;
+               }
+               wild_menu_showing = WM_SCROLLED;
+           }
+           else
+           {
+               // Create status line if needed by setting 'laststatus' to 2.
+               // Set 'winminheight' to zero to avoid that the window is
+               // resized.
+               if (lastwin->w_status_height == 0)
+               {
+                   save_p_ls = p_ls;
+                   save_p_wmh = p_wmh;
+                   p_ls = 2;
+                   p_wmh = 0;
+                   last_status(FALSE);
+               }
+               wild_menu_showing = WM_SHOWN;
+           }
+       }
+
+       screen_puts(buf, row, 0, attr);
+       if (selstart != NULL && highlight)
+       {
+           *selend = NUL;
+           screen_puts(selstart, row, selstart_col, HL_ATTR(HLF_WM));
+       }
+
+       screen_fill(row, row + 1, clen, (int)Columns, fillchar, fillchar, attr);
+    }
+
+    win_redraw_last_status(topframe);
+    vim_free(buf);
+}
+
 /*
  * Get the next or prev cmdline completion match. The index of the match is set
  * in "p_findex"
@@ -979,11 +1246,11 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
 }
 
 /*
- * Private gettail for showmatches() (and win_redr_status_matches()):
- * Find tail of file name path, but ignore trailing "/".
+ * gettail() version for showmatches() and win_redr_status_matches():
+ * Return the tail of file name path "s", ignoring a trailing "/".
  */
-    char_u *
-sm_gettail(char_u *s)
+    static char_u *
+showmatches_gettail(char_u *s)
 {
     char_u     *p;
     char_u     *t = s;
index e42ed6d423d1b6cfba27c76e6bdbbf8d9ba4f26b..2fb543ab43dd58c8747d5ffd72264ee318b004c7 100644 (file)
@@ -10,7 +10,6 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode
 void ExpandInit(expand_T *xp);
 void ExpandCleanup(expand_T *xp);
 int showmatches(expand_T *xp, int wildmenu);
-char_u *sm_gettail(char_u *s);
 char_u *addstar(char_u *fname, int len, int context);
 void set_expand_context(expand_T *xp);
 void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline);
index d53955efc79444c9194d5b0f47248027d65271b7..84f53e9244bf638513f43d419436fa3ddd53f4d1 100644 (file)
@@ -10,7 +10,6 @@ void reset_screen_attr(void);
 void screen_line(win_T *wp, int row, int coloff, int endcol, int clear_width, int flags);
 void rl_mirror(char_u *str);
 void draw_vsep_win(win_T *wp, int row);
-void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, int match, int showtail);
 int stl_connected(win_T *wp);
 int get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len);
 void win_redr_custom(win_T *wp, int draw_ruler);
index 15fbe598b32d4f595b5edfe0c6bedfe773812816..5855b90080049dda60c2a66fb7661b59af111dcd 100644 (file)
@@ -916,274 +916,6 @@ draw_vsep_win(win_T *wp, int row)
     }
 }
 
-static int skip_status_match_char(expand_T *xp, char_u *s);
-
-/*
- * Get the length of an item as it will be shown in the status line.
- */
-    static int
-status_match_len(expand_T *xp, char_u *s)
-{
-    int        len = 0;
-
-#ifdef FEAT_MENU
-    int emenu = (xp->xp_context == EXPAND_MENUS
-           || xp->xp_context == EXPAND_MENUNAMES);
-
-    // Check for menu separators - replace with '|'.
-    if (emenu && menu_is_separator(s))
-       return 1;
-#endif
-
-    while (*s != NUL)
-    {
-       s += skip_status_match_char(xp, s);
-       len += ptr2cells(s);
-       MB_PTR_ADV(s);
-    }
-
-    return len;
-}
-
-/*
- * Return the number of characters that should be skipped in a status match.
- * These are backslashes used for escaping.  Do show backslashes in help tags.
- */
-    static int
-skip_status_match_char(expand_T *xp, char_u *s)
-{
-    if ((rem_backslash(s) && xp->xp_context != EXPAND_HELP)
-#ifdef FEAT_MENU
-           || ((xp->xp_context == EXPAND_MENUS
-                   || xp->xp_context == EXPAND_MENUNAMES)
-                         && (s[0] == '\t' || (s[0] == '\\' && s[1] != NUL)))
-#endif
-          )
-    {
-#ifndef BACKSLASH_IN_FILENAME
-       if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!')
-           return 2;
-#endif
-       return 1;
-    }
-    return 0;
-}
-
-/*
- * Show wildchar matches in the status line.
- * Show at least the "match" item.
- * We start at item 'first_match' in the list and show all matches that fit.
- *
- * If inversion is possible we use it. Else '=' characters are used.
- */
-    void
-win_redr_status_matches(
-    expand_T   *xp,
-    int                num_matches,
-    char_u     **matches,      // list of matches
-    int                match,
-    int                showtail)
-{
-#define L_MATCH(m) (showtail ? sm_gettail(matches[m]) : matches[m])
-    int                row;
-    char_u     *buf;
-    int                len;
-    int                clen;           // length in screen cells
-    int                fillchar;
-    int                attr;
-    int                i;
-    int                highlight = TRUE;
-    char_u     *selstart = NULL;
-    int                selstart_col = 0;
-    char_u     *selend = NULL;
-    static int first_match = 0;
-    int                add_left = FALSE;
-    char_u     *s;
-#ifdef FEAT_MENU
-    int                emenu;
-#endif
-    int                l;
-
-    if (matches == NULL)       // interrupted completion?
-       return;
-
-    if (has_mbyte)
-       buf = alloc(Columns * MB_MAXBYTES + 1);
-    else
-       buf = alloc(Columns + 1);
-    if (buf == NULL)
-       return;
-
-    if (match == -1)   // don't show match but original text
-    {
-       match = 0;
-       highlight = FALSE;
-    }
-    // count 1 for the ending ">"
-    clen = status_match_len(xp, L_MATCH(match)) + 3;
-    if (match == 0)
-       first_match = 0;
-    else if (match < first_match)
-    {
-       // jumping left, as far as we can go
-       first_match = match;
-       add_left = TRUE;
-    }
-    else
-    {
-       // check if match fits on the screen
-       for (i = first_match; i < match; ++i)
-           clen += status_match_len(xp, L_MATCH(i)) + 2;
-       if (first_match > 0)
-           clen += 2;
-       // jumping right, put match at the left
-       if ((long)clen > Columns)
-       {
-           first_match = match;
-           // if showing the last match, we can add some on the left
-           clen = 2;
-           for (i = match; i < num_matches; ++i)
-           {
-               clen += status_match_len(xp, L_MATCH(i)) + 2;
-               if ((long)clen >= Columns)
-                   break;
-           }
-           if (i == num_matches)
-               add_left = TRUE;
-       }
-    }
-    if (add_left)
-       while (first_match > 0)
-       {
-           clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2;
-           if ((long)clen >= Columns)
-               break;
-           --first_match;
-       }
-
-    fillchar = fillchar_status(&attr, curwin);
-
-    if (first_match == 0)
-    {
-       *buf = NUL;
-       len = 0;
-    }
-    else
-    {
-       STRCPY(buf, "< ");
-       len = 2;
-    }
-    clen = len;
-
-    i = first_match;
-    while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < Columns)
-    {
-       if (i == match)
-       {
-           selstart = buf + len;
-           selstart_col = clen;
-       }
-
-       s = L_MATCH(i);
-       // Check for menu separators - replace with '|'
-#ifdef FEAT_MENU
-       emenu = (xp->xp_context == EXPAND_MENUS
-               || xp->xp_context == EXPAND_MENUNAMES);
-       if (emenu && menu_is_separator(s))
-       {
-           STRCPY(buf + len, transchar('|'));
-           l = (int)STRLEN(buf + len);
-           len += l;
-           clen += l;
-       }
-       else
-#endif
-           for ( ; *s != NUL; ++s)
-       {
-           s += skip_status_match_char(xp, s);
-           clen += ptr2cells(s);
-           if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1)
-           {
-               STRNCPY(buf + len, s, l);
-               s += l - 1;
-               len += l;
-           }
-           else
-           {
-               STRCPY(buf + len, transchar_byte(*s));
-               len += (int)STRLEN(buf + len);
-           }
-       }
-       if (i == match)
-           selend = buf + len;
-
-       *(buf + len++) = ' ';
-       *(buf + len++) = ' ';
-       clen += 2;
-       if (++i == num_matches)
-               break;
-    }
-
-    if (i != num_matches)
-    {
-       *(buf + len++) = '>';
-       ++clen;
-    }
-
-    buf[len] = NUL;
-
-    row = cmdline_row - 1;
-    if (row >= 0)
-    {
-       if (wild_menu_showing == 0)
-       {
-           if (msg_scrolled > 0)
-           {
-               // Put the wildmenu just above the command line.  If there is
-               // no room, scroll the screen one line up.
-               if (cmdline_row == Rows - 1)
-               {
-                   screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL);
-                   ++msg_scrolled;
-               }
-               else
-               {
-                   ++cmdline_row;
-                   ++row;
-               }
-               wild_menu_showing = WM_SCROLLED;
-           }
-           else
-           {
-               // Create status line if needed by setting 'laststatus' to 2.
-               // Set 'winminheight' to zero to avoid that the window is
-               // resized.
-               if (lastwin->w_status_height == 0)
-               {
-                   save_p_ls = p_ls;
-                   save_p_wmh = p_wmh;
-                   p_ls = 2;
-                   p_wmh = 0;
-                   last_status(FALSE);
-               }
-               wild_menu_showing = WM_SHOWN;
-           }
-       }
-
-       screen_puts(buf, row, 0, attr);
-       if (selstart != NULL && highlight)
-       {
-           *selend = NUL;
-           screen_puts(selstart, row, selstart_col, HL_ATTR(HLF_WM));
-       }
-
-       screen_fill(row, row + 1, clen, (int)Columns, fillchar, fillchar, attr);
-    }
-
-    win_redraw_last_status(topframe);
-    vim_free(buf);
-}
-
 /*
  * Return TRUE if the status line of window "wp" is connected to the status
  * line of the window right of it.  If not, then it's a vertical separator.
index 02ffdeca2f15cb657bc64f9f83b2aaff4d68d731..a7da3160e166490c8c2fd340fa5f72a7b8242cba 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    867,
 /**/
     866,
 /**/