Patch 9.0.0867
Problem:    Wildmenu redrawing code is spread out.
Solution:   Refactor to move code together. (closes #11528)
Files:      src/cmdexpand.c, src/proto/cmdexpand.pro, src/screen.c,
            src/proto/screen.pro


*** ../vim-9.0.0866/src/cmdexpand.c     2022-09-18 13:06:36.461124371 +0100
--- src/cmdexpand.c     2022-11-12 17:42:15.944860523 +0000
***************
*** 19,24 ****
--- 19,25 ----
                              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,40 ****
  static int compl_startcol;
  static int compl_selected;
  
! #define SHOW_FILE_TEXT(m) (showtail ? sm_gettail(matches[m]) : matches[m])
  
  /*
   * Returns TRUE if fuzzy completion is supported for a given cmdline 
completion
--- 35,41 ----
  static int compl_startcol;
  static int compl_selected;
  
! #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,340 ****
      columns = vim_strsize(xp->xp_pattern);
      if (showtail)
      {
!       columns += vim_strsize(sm_gettail(matches[0]));
        columns -= vim_strsize(matches[0]);
      }
      if (columns >= compl_startcol)
--- 335,341 ----
      columns = vim_strsize(xp->xp_pattern);
      if (showtail)
      {
!       columns += vim_strsize(showmatches_gettail(matches[0]));
        columns -= vim_strsize(matches[0]);
      }
      if (columns >= compl_startcol)
***************
*** 403,408 ****
--- 404,675 ----
  }
  
  /*
+  * 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,989 ****
  }
  
  /*
!  * Private gettail for showmatches() (and win_redr_status_matches()):
!  * Find tail of file name path, but ignore trailing "/".
   */
!     char_u *
! sm_gettail(char_u *s)
  {
      char_u    *p;
      char_u    *t = s;
--- 1246,1256 ----
  }
  
  /*
!  * gettail() version for showmatches() and win_redr_status_matches():
!  * Return the tail of file name path "s", ignoring a trailing "/".
   */
!     static char_u *
! showmatches_gettail(char_u *s)
  {
      char_u    *p;
      char_u    *t = s;
*** ../vim-9.0.0866/src/proto/cmdexpand.pro     2022-06-27 23:14:59.000000000 
+0100
--- src/proto/cmdexpand.pro     2022-11-12 17:37:43.176872002 +0000
***************
*** 10,16 ****
  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);
--- 10,15 ----
*** ../vim-9.0.0866/src/screen.c        2022-11-07 12:16:46.397761740 +0000
--- src/screen.c        2022-11-12 17:36:10.924827342 +0000
***************
*** 916,1189 ****
      }
  }
  
- 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.
--- 916,921 ----
*** ../vim-9.0.0866/src/proto/screen.pro        2022-09-26 15:18:43.782952802 
+0100
--- src/proto/screen.pro        2022-11-12 17:37:37.404869197 +0000
***************
*** 10,16 ****
  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);
--- 10,15 ----
*** ../vim-9.0.0866/src/version.c       2022-11-12 17:30:21.788661869 +0000
--- src/version.c       2022-11-12 17:37:28.828865037 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     867,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
48. You get a tatoo that says "This body best viewed with Netscape 3.1 or
    higher."

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221112174444.AFC771C0473%40moolenaar.net.

Raspunde prin e-mail lui