Patch 9.0.0388
Problem:    The do_arg_all() function is too long.
Solution:   Split the function in smaller parts. (Yegappan Lakshmanan,
            closes #11062)
Files:      src/arglist.c


*** ../vim-9.0.0387/src/arglist.c       2022-09-05 14:33:42.202419990 +0100
--- src/arglist.c       2022-09-05 18:24:52.327375787 +0100
***************
*** 574,594 ****
            alist_new();
      }
  
      if (*eap->arg != NUL)
      {
        if (check_arglist_locked() == FAIL)
            return;
-       // ":args file ..": define new argument list, handle like ":next"
-       // Also for ":argslocal file .." and ":argsglobal file ..".
        ex_next(eap);
      }
!     else if (eap->cmdidx == CMD_args)
      {
        char_u **items;
  
-       // ":args": list arguments.
        if (ARGCOUNT <= 0)
!           return;
  
        items = ALLOC_MULT(char_u *, ARGCOUNT);
        if (items == NULL)
--- 574,596 ----
            alist_new();
      }
  
+     // ":args file ..": define new argument list, handle like ":next"
+     // Also for ":argslocal file .." and ":argsglobal file ..".
      if (*eap->arg != NUL)
      {
        if (check_arglist_locked() == FAIL)
            return;
        ex_next(eap);
+       return;
      }
! 
!     // ":args": list arguments.
!     if (eap->cmdidx == CMD_args)
      {
        char_u **items;
  
        if (ARGCOUNT <= 0)
!           return;             // empty argument list
  
        items = ALLOC_MULT(char_u *, ARGCOUNT);
        if (items == NULL)
***************
*** 602,613 ****
            items[i] = alist_name(&ARGLIST[i]);
        list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
        vim_free(items);
      }
!     else if (eap->cmdidx == CMD_arglocal)
      {
        garray_T        *gap = &curwin->w_alist->al_ga;
  
-       // ":argslocal": make a local copy of the global argument list.
        if (GA_GROW_FAILS(gap, GARGCOUNT))
            return;
  
--- 604,618 ----
            items[i] = alist_name(&ARGLIST[i]);
        list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
        vim_free(items);
+ 
+       return;
      }
! 
!     // ":argslocal": make a local copy of the global argument list.
!     if (eap->cmdidx == CMD_arglocal)
      {
        garray_T        *gap = &curwin->w_alist->al_ga;
  
        if (GA_GROW_FAILS(gap, GARGCOUNT))
            return;
  
***************
*** 919,995 ****
  }
  
  /*
!  * do_arg_all(): Open up to 'count' windows, one for each argument.
   */
!     static void
! do_arg_all(
!     int       count,
!     int       forceit,                // hide buffers in current windows
!     int keep_tabs)            // keep current tabs, for ":tab drop file"
! {
!     int               i;
!     win_T     *wp, *wpnext;
      char_u    *opened;        // Array of weight for which args are open:
                                //  0: not opened
                                //  1: opened in other tab
                                //  2: opened in curtab
                                //  3: opened in curtab and curwin
-                               //
      int               opened_len;     // length of opened[]
!     int               use_firstwin = FALSE;   // use first window for arglist
!     int               tab_drop_empty_window = FALSE;
!     int               split_ret = OK;
!     int               p_ea_save;
!     alist_T   *alist;         // argument list to be used
!     buf_T     *buf;
!     tabpage_T *tpnext;
!     int               had_tab = cmdmod.cmod_tab;
!     win_T     *old_curwin, *last_curwin;
!     tabpage_T *old_curtab, *last_curtab;
!     win_T     *new_curwin = NULL;
!     tabpage_T *new_curtab = NULL;
!     int               prev_arglist_locked = arglist_locked;
  
! #ifdef FEAT_CMDWIN
!     if (cmdwin_type != 0)
!     {
!       emsg(_(e_invalid_in_cmdline_window));
!       return;
!     }
! #endif
!     if (ARGCOUNT <= 0)
!     {
!       // Don't give an error message.  We don't want it when the ":all"
!       // command is in the .vimrc.
!       return;
!     }
!     setpcmark();
! 
!     opened_len = ARGCOUNT;
!     opened = alloc_clear(opened_len);
!     if (opened == NULL)
!       return;
! 
!     // Autocommands may do anything to the argument list.  Make sure it's not
!     // freed while we are working here by "locking" it.  We still have to
!     // watch out for its size to be changed.
!     alist = curwin->w_alist;
!     ++alist->al_refcount;
!     arglist_locked = TRUE;
  
      old_curwin = curwin;
      old_curtab = curtab;
  
! #ifdef FEAT_GUI
!     need_mouse_correct = TRUE;
! #endif
! 
!     // Try closing all windows that are not in the argument list.
!     // Also close windows that are not full width;
!     // When 'hidden' or "forceit" set the buffer becomes hidden.
!     // Windows that have a changed buffer and can't be hidden won't be closed.
!     // When the ":tab" modifier was used do this for all tab pages.
!     if (had_tab > 0)
        goto_tabpage_tp(first_tabpage, TRUE, TRUE);
      for (;;)
      {
--- 924,968 ----
  }
  
  /*
!  * State used by the :all command to open all the files in the argument list 
in
!  * separate windows.
   */
! typedef struct {
!     alist_T   *alist;         // argument list to be used
!     int               had_tab;
!     int               keep_tabs;
!     int               forceit;
! 
!     int               use_firstwin;   // use first window for arglist
      char_u    *opened;        // Array of weight for which args are open:
                                //  0: not opened
                                //  1: opened in other tab
                                //  2: opened in curtab
                                //  3: opened in curtab and curwin
      int               opened_len;     // length of opened[]
!     win_T     *new_curwin;
!     tabpage_T *new_curtab;
! } arg_all_state_T;
  
! /*
!  * Close all the windows containing files which are not in the argument list.
!  * Used by the ":all" command.
!  */
!     static void
! arg_all_close_unused_windows(arg_all_state_T *aall)
! {
!     win_T     *wp;
!     win_T     *wpnext;
!     tabpage_T *tpnext;
!     buf_T     *buf;
!     int               i;
!     win_T     *old_curwin;
!     tabpage_T *old_curtab;
  
      old_curwin = curwin;
      old_curtab = curtab;
  
!     if (aall->had_tab > 0)
        goto_tabpage_tp(first_tabpage, TRUE, TRUE);
      for (;;)
      {
***************
*** 999,1015 ****
            wpnext = wp->w_next;
            buf = wp->w_buffer;
            if (buf->b_ffname == NULL
!                   || (!keep_tabs && (buf->b_nwindows > 1
                            || wp->w_width != Columns)))
!               i = opened_len;
            else
            {
                // check if the buffer in this window is in the arglist
!               for (i = 0; i < opened_len; ++i)
                {
!                   if (i < alist->al_ga.ga_len
!                           && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum
!                               || fullpathcmp(alist_name(&AARGLIST(alist)[i]),
                                        buf->b_ffname, TRUE, TRUE) & FPC_SAME))
                    {
                        int weight = 1;
--- 972,988 ----
            wpnext = wp->w_next;
            buf = wp->w_buffer;
            if (buf->b_ffname == NULL
!                   || (!aall->keep_tabs && (buf->b_nwindows > 1
                            || wp->w_width != Columns)))
!               i = aall->opened_len;
            else
            {
                // check if the buffer in this window is in the arglist
!               for (i = 0; i < aall->opened_len; ++i)
                {
!                   if (i < aall->alist->al_ga.ga_len
!                           && (AARGLIST(aall->alist)[i].ae_fnum == buf->b_fnum
!                               || 
fullpathcmp(alist_name(&AARGLIST(aall->alist)[i]),
                                        buf->b_ffname, TRUE, TRUE) & FPC_SAME))
                    {
                        int weight = 1;
***************
*** 1021,1046 ****
                                ++weight;
                        }
  
!                       if (weight > (int)opened[i])
                        {
!                           opened[i] = (char_u)weight;
                            if (i == 0)
                            {
!                               if (new_curwin != NULL)
!                                   new_curwin->w_arg_idx = opened_len;
!                               new_curwin = wp;
!                               new_curtab = curtab;
                            }
                        }
!                       else if (keep_tabs)
!                           i = opened_len;
  
!                       if (wp->w_alist != alist)
                        {
                            // Use the current argument list for all windows
                            // containing a file from it.
                            alist_unlink(wp->w_alist);
!                           wp->w_alist = alist;
                            ++wp->w_alist->al_refcount;
                        }
                        break;
--- 994,1019 ----
                                ++weight;
                        }
  
!                       if (weight > (int)aall->opened[i])
                        {
!                           aall->opened[i] = (char_u)weight;
                            if (i == 0)
                            {
!                               if (aall->new_curwin != NULL)
!                                   aall->new_curwin->w_arg_idx = 
aall->opened_len;
!                               aall->new_curwin = wp;
!                               aall->new_curtab = curtab;
                            }
                        }
!                       else if (aall->keep_tabs)
!                           i = aall->opened_len;
  
!                       if (wp->w_alist != aall->alist)
                        {
                            // Use the current argument list for all windows
                            // containing a file from it.
                            alist_unlink(wp->w_alist);
!                           wp->w_alist = aall->alist;
                            ++wp->w_alist->al_refcount;
                        }
                        break;
***************
*** 1049,1057 ****
            }
            wp->w_arg_idx = i;
  
!           if (i == opened_len && !keep_tabs)// close this window
            {
!               if (buf_hide(buf) || forceit || buf->b_nwindows > 1
                                                        || !bufIsChanged(buf))
                {
                    // If the buffer was changed, and we would like to hide it,
--- 1022,1030 ----
            }
            wp->w_arg_idx = i;
  
!           if (i == aall->opened_len && !aall->keep_tabs)// close this window
            {
!               if (buf_hide(buf) || aall->forceit || buf->b_nwindows > 1
                                                        || !bufIsChanged(buf))
                {
                    // If the buffer was changed, and we would like to hide it,
***************
*** 1074,1081 ****
                    }
                    // don't close last window
                    if (ONE_WINDOW
!                           && (first_tabpage->tp_next == NULL || !had_tab))
!                       use_firstwin = TRUE;
                    else
                    {
                        win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
--- 1047,1055 ----
                    }
                    // don't close last window
                    if (ONE_WINDOW
!                           && (first_tabpage->tp_next == NULL
!                               || !aall->had_tab))
!                       aall->use_firstwin = TRUE;
                    else
                    {
                        win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
***************
*** 1089,1095 ****
        }
  
        // Without the ":tab" modifier only do the current tab page.
!       if (had_tab == 0 || tpnext == NULL)
            break;
  
        // check if autocommands removed the next tab page
--- 1063,1069 ----
        }
  
        // Without the ":tab" modifier only do the current tab page.
!       if (aall->had_tab == 0 || tpnext == NULL)
            break;
  
        // check if autocommands removed the next tab page
***************
*** 1098,1151 ****
  
        goto_tabpage_tp(tpnext, TRUE, TRUE);
      }
  
!     // Open a window for files in the argument list that don't have one.
!     // ARGCOUNT may change while doing this, because of autocommands.
!     if (count > opened_len || count <= 0)
!       count = opened_len;
  
-     // Don't execute Win/Buf Enter/Leave autocommands here.
-     ++autocmd_no_enter;
-     ++autocmd_no_leave;
-     last_curwin = curwin;
-     last_curtab = curtab;
-     win_enter(lastwin, FALSE);
      // ":tab drop file" should re-use an empty window to avoid "--remote-tab"
      // leaving an empty tab page when executed locally.
!     if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
                            && curbuf->b_ffname == NULL && !curbuf->b_changed)
      {
!       use_firstwin = TRUE;
        tab_drop_empty_window = TRUE;
      }
  
      for (i = 0; i < count && !got_int; ++i)
      {
!       if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
            arg_had_last = TRUE;
!       if (opened[i] > 0)
        {
            // Move the already present window to below the current window
            if (curwin->w_arg_idx != i)
            {
!               FOR_ALL_WINDOWS(wpnext)
                {
!                   if (wpnext->w_arg_idx == i)
                    {
!                       if (keep_tabs)
                        {
!                           new_curwin = wpnext;
!                           new_curtab = curtab;
                        }
!                       else if (wpnext->w_frame->fr_parent
!                                                != curwin->w_frame->fr_parent)
                        {
                            emsg(_(e_window_layout_changed_unexpectedly));
                            i = count;
                            break;
                        }
                        else
!                           win_move_after(wpnext, curwin);
                        break;
                    }
                }
--- 1072,1127 ----
  
        goto_tabpage_tp(tpnext, TRUE, TRUE);
      }
+ }
  
! /*
!  * Open upto "count" windows for the files in the argument list 'aall->alist'.
!  */
!     static void
! arg_all_open_windows(arg_all_state_T *aall, int count)
! {
!     win_T     *wp;
!     int               tab_drop_empty_window = FALSE;
!     int               i;
!     int               split_ret = OK;
!     int               p_ea_save;
  
      // ":tab drop file" should re-use an empty window to avoid "--remote-tab"
      // leaving an empty tab page when executed locally.
!     if (aall->keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
                            && curbuf->b_ffname == NULL && !curbuf->b_changed)
      {
!       aall->use_firstwin = TRUE;
        tab_drop_empty_window = TRUE;
      }
  
      for (i = 0; i < count && !got_int; ++i)
      {
!       if (aall->alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
            arg_had_last = TRUE;
!       if (aall->opened[i] > 0)
        {
            // Move the already present window to below the current window
            if (curwin->w_arg_idx != i)
            {
!               FOR_ALL_WINDOWS(wp)
                {
!                   if (wp->w_arg_idx == i)
                    {
!                       if (aall->keep_tabs)
                        {
!                           aall->new_curwin = wp;
!                           aall->new_curtab = curtab;
                        }
!                       else if (wp->w_frame->fr_parent
!                               != curwin->w_frame->fr_parent)
                        {
                            emsg(_(e_window_layout_changed_unexpectedly));
                            i = count;
                            break;
                        }
                        else
!                           win_move_after(wp, curwin);
                        break;
                    }
                }
***************
*** 1156,1162 ****
            // trigger events for tab drop
            if (tab_drop_empty_window && i == count - 1)
                --autocmd_no_enter;
!           if (!use_firstwin)          // split current window
            {
                p_ea_save = p_ea;
                p_ea = TRUE;            // use space from all windows
--- 1132,1138 ----
            // trigger events for tab drop
            if (tab_drop_empty_window && i == count - 1)
                --autocmd_no_enter;
!           if (!aall->use_firstwin)            // split current window
            {
                p_ea_save = p_ea;
                p_ea = TRUE;            // use space from all windows
***************
*** 1172,1206 ****
            curwin->w_arg_idx = i;
            if (i == 0)
            {
!               new_curwin = curwin;
!               new_curtab = curtab;
            }
!           (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
!                     ECMD_ONE,
!                     ((buf_hide(curwin->w_buffer)
!                          || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
!                                                      + ECMD_OLDBUF, curwin);
            if (tab_drop_empty_window && i == count - 1)
                ++autocmd_no_enter;
!           if (use_firstwin)
                ++autocmd_no_leave;
!           use_firstwin = FALSE;
        }
        ui_breakcheck();
  
        // When ":tab" was used open a new tab for a new window repeatedly.
!       if (had_tab > 0 && tabpage_index(NULL) <= p_tpm)
            cmdmod.cmod_tab = 9999;
      }
  
      // Remove the "lock" on the argument list.
!     alist_unlink(alist);
      arglist_locked = prev_arglist_locked;
  
      --autocmd_no_enter;
  
      // restore last referenced tabpage's curwin
!     if (last_curtab != new_curtab)
      {
        if (valid_tabpage(last_curtab))
            goto_tabpage_tp(last_curtab, TRUE, TRUE);
--- 1148,1258 ----
            curwin->w_arg_idx = i;
            if (i == 0)
            {
!               aall->new_curwin = curwin;
!               aall->new_curtab = curtab;
            }
!           (void)do_ecmd(0, alist_name(&AARGLIST(aall->alist)[i]), NULL, NULL,
!                   ECMD_ONE,
!                   ((buf_hide(curwin->w_buffer)
!                     || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
!                   + ECMD_OLDBUF, curwin);
            if (tab_drop_empty_window && i == count - 1)
                ++autocmd_no_enter;
!           if (aall->use_firstwin)
                ++autocmd_no_leave;
!           aall->use_firstwin = FALSE;
        }
        ui_breakcheck();
  
        // When ":tab" was used open a new tab for a new window repeatedly.
!       if (aall->had_tab > 0 && tabpage_index(NULL) <= p_tpm)
            cmdmod.cmod_tab = 9999;
      }
+ }
+ 
+ /*
+  * do_arg_all(): Open up to "count" windows, one for each argument.
+  */
+     static void
+ do_arg_all(
+     int       count,
+     int       forceit,                // hide buffers in current windows
+     int keep_tabs)            // keep current tabs, for ":tab drop file"
+ {
+     arg_all_state_T   aall;
+     win_T             *last_curwin;
+     tabpage_T         *last_curtab;
+     int                       prev_arglist_locked = arglist_locked;
+ 
+ #ifdef FEAT_CMDWIN
+     if (cmdwin_type != 0)
+     {
+       emsg(_(e_invalid_in_cmdline_window));
+       return;
+     }
+ #endif
+     if (ARGCOUNT <= 0)
+     {
+       // Don't give an error message.  We don't want it when the ":all"
+       // command is in the .vimrc.
+       return;
+     }
+     setpcmark();
+ 
+     aall.use_firstwin = FALSE;
+     aall.had_tab = cmdmod.cmod_tab;
+     aall.new_curwin = NULL;
+     aall.new_curtab = NULL;
+     aall.forceit = forceit;
+     aall.keep_tabs = keep_tabs;
+     aall.opened_len = ARGCOUNT;
+     aall.opened = alloc_clear(aall.opened_len);
+     if (aall.opened == NULL)
+       return;
+ 
+     // Autocommands may do anything to the argument list.  Make sure it's not
+     // freed while we are working here by "locking" it.  We still have to
+     // watch out for its size being changed.
+     aall.alist = curwin->w_alist;
+     ++aall.alist->al_refcount;
+     arglist_locked = TRUE;
+ 
+ #ifdef FEAT_GUI
+     need_mouse_correct = TRUE;
+ #endif
+ 
+     // Try closing all windows that are not in the argument list.
+     // Also close windows that are not full width;
+     // When 'hidden' or "forceit" set the buffer becomes hidden.
+     // Windows that have a changed buffer and can't be hidden won't be closed.
+     // When the ":tab" modifier was used do this for all tab pages.
+     arg_all_close_unused_windows(&aall);
+ 
+     // Open a window for files in the argument list that don't have one.
+     // ARGCOUNT may change while doing this, because of autocommands.
+     if (count > aall.opened_len || count <= 0)
+       count = aall.opened_len;
+ 
+     // Don't execute Win/Buf Enter/Leave autocommands here.
+     ++autocmd_no_enter;
+     ++autocmd_no_leave;
+     last_curwin = curwin;
+     last_curtab = curtab;
+     win_enter(lastwin, FALSE);
+ 
+     /*
+      * Open upto "count" windows.
+      */
+     arg_all_open_windows(&aall, count);
  
      // Remove the "lock" on the argument list.
!     alist_unlink(aall.alist);
      arglist_locked = prev_arglist_locked;
  
      --autocmd_no_enter;
  
      // restore last referenced tabpage's curwin
!     if (last_curtab != aall.new_curtab)
      {
        if (valid_tabpage(last_curtab))
            goto_tabpage_tp(last_curtab, TRUE, TRUE);
***************
*** 1208,1220 ****
            win_enter(last_curwin, FALSE);
      }
      // to window with first arg
!     if (valid_tabpage(new_curtab))
!       goto_tabpage_tp(new_curtab, TRUE, TRUE);
!     if (win_valid(new_curwin))
!       win_enter(new_curwin, FALSE);
  
      --autocmd_no_leave;
!     vim_free(opened);
  }
  
  /*
--- 1260,1272 ----
            win_enter(last_curwin, FALSE);
      }
      // to window with first arg
!     if (valid_tabpage(aall.new_curtab))
!       goto_tabpage_tp(aall.new_curtab, TRUE, TRUE);
!     if (win_valid(aall.new_curwin))
!       win_enter(aall.new_curwin, FALSE);
  
      --autocmd_no_leave;
!     vim_free(aall.opened);
  }
  
  /*
*** ../vim-9.0.0387/src/version.c       2022-09-05 16:53:17.115566769 +0100
--- src/version.c       2022-09-05 18:16:41.403970414 +0100
***************
*** 705,706 ****
--- 705,708 ----
  {   /* Add new patch number below this line */
+ /**/
+     388,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
7. You finally do take that vacation, but only after buying a USB modem
   and a laptop.

 /// 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/20220905172827.205E51C0CE4%40moolenaar.net.

Raspunde prin e-mail lui