Patch 8.1.0228
Problem:    Dropping files is ignored while Vim is busy.
Solution:   Postpone the effect of dropping files until it's safe.
Files:      src/ex_docmd.c, src/proto/ex_docmd.pro, src/gui.c, src/gui.h,
            src/screen.c, src/main.c, src/gui_mac.c


*** ../vim-8.1.0227/src/ex_docmd.c      2018-07-28 17:07:48.608154066 +0200
--- src/ex_docmd.c      2018-07-29 17:22:20.940320176 +0200
***************
*** 7859,7915 ****
      do_shell(NULL, 0);
  }
  
! #if defined(HAVE_DROP_FILE) \
!       || (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \
!       || defined(FEAT_GUI_MSWIN) \
!       || defined(FEAT_GUI_MAC) \
!       || defined(PROTO)
  
! /*
!  * Handle a file drop. The code is here because a drop is *nearly* like an
!  * :args command, but not quite (we have a list of exact filenames, so we
!  * don't want to (a) parse a command line, or (b) expand wildcards. So the
!  * code is very similar to :args and hence needs access to a lot of the static
!  * functions in this file.
!  *
!  * The list should be allocated using alloc(), as should each item in the
!  * list. This function takes over responsibility for freeing the list.
!  *
!  * XXX The list is made into the argument list. This is freed using
!  * FreeWild(), which does a series of vim_free() calls.
!  */
!     void
! handle_drop(
!     int               filec,          /* the number of files dropped */
!     char_u    **filev,        /* the list of files dropped */
!     int               split)          /* force splitting the window */
  {
      exarg_T   ea;
      int               save_msg_scroll = msg_scroll;
  
!     /* Postpone this while editing the command line. */
!     if (text_locked())
!       return;
!     if (curbuf_locked())
!       return;
! 
!     /* When the screen is being updated we should not change buffers and
!      * windows structures, it may cause freed memory to be used. */
!     if (updating_screen)
!       return;
  
      /* Check whether the current buffer is changed. If so, we will need
       * to split the current window or data could be lost.
       * We don't need to check if the 'hidden' option is set, as in this
       * case the buffer won't be lost.
       */
!     if (!buf_hide(curbuf) && !split)
      {
        ++emsg_off;
!       split = check_changed(curbuf, CCGD_AW);
        --emsg_off;
      }
!     if (split)
      {
        if (win_split(0, 0) == FAIL)
            return;
--- 7859,7895 ----
      do_shell(NULL, 0);
  }
  
! #if defined(HAVE_DROP_FILE) || defined(PROTO)
  
! static int drop_busy = FALSE;
! static int drop_filec;
! static char_u **drop_filev = NULL;
! static int drop_split;
! static void (*drop_callback)(void *);
! static void *drop_cookie;
! 
!     static void
! handle_drop_internal(void)
  {
      exarg_T   ea;
      int               save_msg_scroll = msg_scroll;
  
!     // Setting the argument list may cause screen updates and being called
!     // recursively.  Avoid that by setting drop_busy.
!     drop_busy = TRUE;
  
      /* Check whether the current buffer is changed. If so, we will need
       * to split the current window or data could be lost.
       * We don't need to check if the 'hidden' option is set, as in this
       * case the buffer won't be lost.
       */
!     if (!buf_hide(curbuf) && !drop_split)
      {
        ++emsg_off;
!       drop_split = check_changed(curbuf, CCGD_AW);
        --emsg_off;
      }
!     if (drop_split)
      {
        if (win_split(0, 0) == FAIL)
            return;
***************
*** 7924,7930 ****
      /*
       * Set up the new argument list.
       */
!     alist_set(ALIST(curwin), filec, filev, FALSE, NULL, 0);
  
      /*
       * Move to the first file.
--- 7904,7910 ----
      /*
       * Set up the new argument list.
       */
!     alist_set(ALIST(curwin), drop_filec, drop_filev, FALSE, NULL, 0);
  
      /*
       * Move to the first file.
***************
*** 7942,7947 ****
--- 7922,7999 ----
       * unexpectedly.  The screen will be redrawn by the caller, thus
       * msg_scroll being set by displaying a message is irrelevant. */
      msg_scroll = save_msg_scroll;
+ 
+     if (drop_callback != NULL)
+       drop_callback(drop_cookie);
+ 
+     drop_filev = NULL;
+     drop_busy = FALSE;
+ }
+ 
+ /*
+  * Handle a file drop. The code is here because a drop is *nearly* like an
+  * :args command, but not quite (we have a list of exact filenames, so we
+  * don't want to (a) parse a command line, or (b) expand wildcards. So the
+  * code is very similar to :args and hence needs access to a lot of the static
+  * functions in this file.
+  *
+  * The "filev" list must have been allocated using alloc(), as should each 
item
+  * in the list. This function takes over responsibility for freeing the 
"filev"
+  * list.
+  */
+     void
+ handle_drop(
+     int               filec,          // the number of files dropped
+     char_u    **filev,        // the list of files dropped
+     int               split,          // force splitting the window
+     void      (*callback)(void *), // to be called after setting the argument
+                                    // list
+     void      *cookie)        // argument for "callback" (allocated)
+ {
+     // Cannot handle recursive drops, finish the pending one.
+     if (drop_busy)
+     {
+       FreeWild(filec, filev);
+       vim_free(cookie);
+       return;
+     }
+ 
+     // When calling handle_drop() more than once in a row we only use the last
+     // one.
+     if (drop_filev != NULL)
+     {
+       FreeWild(drop_filec, drop_filev);
+       vim_free(drop_cookie);
+     }
+ 
+     drop_filec = filec;
+     drop_filev = filev;
+     drop_split = split;
+     drop_callback = callback;
+     drop_cookie = cookie;
+ 
+     // Postpone this when:
+     // - editing the command line
+     // - not possible to change the current buffer
+     // - updating the screen
+     // As it may change buffers and window structures that are in use and 
cause
+     // freed memory to be used.
+     if (text_locked() || curbuf_locked() || updating_screen)
+       return;
+ 
+     handle_drop_internal();
+ }
+ 
+ /*
+  * To be called when text is unlocked, curbuf is unlocked or updating_screen 
is
+  * reset: Handle a postponed drop.
+  */
+     void
+ handle_any_postponed_drop(void)
+ {
+     if (!drop_busy && drop_filev != NULL
+                    && !text_locked() && !curbuf_locked() && !updating_screen)
+       handle_drop_internal();
  }
  #endif
  
*** ../vim-8.1.0227/src/proto/ex_docmd.pro      2018-05-17 13:52:34.000000000 
+0200
--- src/proto/ex_docmd.pro      2018-07-29 16:58:19.612440949 +0200
***************
*** 31,37 ****
  void tabpage_close(int forceit);
  void tabpage_close_other(tabpage_T *tp, int forceit);
  void ex_all(exarg_T *eap);
! void handle_drop(int filec, char_u **filev, int split);
  void alist_clear(alist_T *al);
  void alist_init(alist_T *al);
  void alist_unlink(alist_T *al);
--- 31,38 ----
  void tabpage_close(int forceit);
  void tabpage_close_other(tabpage_T *tp, int forceit);
  void ex_all(exarg_T *eap);
! void handle_drop(int filec, char_u **filev, int split, void (*callback)(void 
*), void *cookie);
! void handle_any_postponed_drop(void);
  void alist_clear(alist_T *al);
  void alist_init(alist_T *al);
  void alist_unlink(alist_T *al);
*** ../vim-8.1.0227/src/gui.c   2018-07-29 16:09:14.636945607 +0200
--- src/gui.c   2018-07-29 16:52:45.218249227 +0200
***************
*** 5383,5392 ****
  
  #endif
  
! #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
!       || defined(FEAT_GUI_MSWIN) \
!       || defined(FEAT_GUI_MAC) \
!       || defined(PROTO)
  
  static void gui_wingoto_xy(int x, int y);
  
--- 5383,5389 ----
  
  #endif
  
! #if defined(HAVE_DROP_FILE) || defined(PROTO)
  
  static void gui_wingoto_xy(int x, int y);
  
***************
*** 5409,5414 ****
--- 5406,5447 ----
  }
  
  /*
+  * Function passed to handle_drop() for the actions to be done after the
+  * argument list has been updated.
+  */
+     static void
+ drop_callback(void *cookie)
+ {
+     char_u    *p = cookie;
+ 
+     /* If Shift held down, change to first file's directory.  If the first
+      * item is a directory, change to that directory (and let the explorer
+      * plugin show the contents). */
+     if (p != NULL)
+     {
+       if (mch_isdir(p))
+       {
+           if (mch_chdir((char *)p) == 0)
+               shorten_fnames(TRUE);
+       }
+       else if (vim_chdirfile(p, "drop") == OK)
+           shorten_fnames(TRUE);
+       vim_free(p);
+     }
+ 
+     /* Update the screen display */
+     update_screen(NOT_VALID);
+ # ifdef FEAT_MENU
+     gui_update_menus(0);
+ # endif
+ #ifdef FEAT_TITLE
+     maketitle();
+ #endif
+     setcursor();
+     out_flush_cursor(FALSE, FALSE);
+ }
+ 
+ /*
   * Process file drop.  Mouse cursor position, key modifiers, name of files
   * and count of files are given.  Argument "fnames[count]" has full pathnames
   * of dropped files, they will be freed in this function, and caller can't use
***************
*** 5488,5520 ****
            vim_free(fnames);
        }
        else
!           handle_drop(count, fnames, (modifiers & MOUSE_CTRL) != 0);
! 
!       /* If Shift held down, change to first file's directory.  If the first
!        * item is a directory, change to that directory (and let the explorer
!        * plugin show the contents). */
!       if (p != NULL)
!       {
!           if (mch_isdir(p))
!           {
!               if (mch_chdir((char *)p) == 0)
!                   shorten_fnames(TRUE);
!           }
!           else if (vim_chdirfile(p, "drop") == OK)
!               shorten_fnames(TRUE);
!           vim_free(p);
!       }
! 
!       /* Update the screen display */
!       update_screen(NOT_VALID);
! # ifdef FEAT_MENU
!       gui_update_menus(0);
! # endif
! #ifdef FEAT_TITLE
!       maketitle();
! #endif
!       setcursor();
!       out_flush_cursor(FALSE, FALSE);
      }
  
      entered = FALSE;
--- 5521,5528 ----
            vim_free(fnames);
        }
        else
!           handle_drop(count, fnames, (modifiers & MOUSE_CTRL) != 0,
!                   drop_callback, (void *)p);
      }
  
      entered = FALSE;
*** ../vim-8.1.0227/src/gui.h   2018-05-05 18:42:37.000000000 +0200
--- src/gui.h   2018-07-29 16:52:19.418385701 +0200
***************
*** 65,72 ****
  /*
   * GUIs that support dropping files on a running Vim.
   */
! #if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) \
!       || defined(FEAT_GUI_GTK)
  # define HAVE_DROP_FILE
  #endif
  
--- 65,73 ----
  /*
   * GUIs that support dropping files on a running Vim.
   */
! #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
!       || defined(FEAT_GUI_MSWIN) \
!       || defined(FEAT_GUI_MAC)
  # define HAVE_DROP_FILE
  #endif
  
*** ../vim-8.1.0227/src/screen.c        2018-07-29 16:09:14.644945560 +0200
--- src/screen.c        2018-07-29 16:51:41.606584708 +0200
***************
*** 526,531 ****
--- 526,537 ----
  #ifdef FEAT_TERMINAL
      term_check_channel_closed_recently();
  #endif
+ 
+ #ifdef HAVE_DROP_FILE
+     // If handle_drop() was called while updating_screen was TRUE need to
+     // handle the drop now.
+     handle_any_postponed_drop();
+ #endif
  }
  
  /*
*** ../vim-8.1.0227/src/main.c  2018-06-23 16:12:15.784258242 +0200
--- src/main.c  2018-07-29 17:02:36.091020303 +0200
***************
*** 911,917 ****
  
      /*
       * Call the main command loop.  This never returns.
!     */
      main_loop(FALSE, FALSE);
  
  #endif /* NO_VIM_MAIN */
--- 911,917 ----
  
      /*
       * Call the main command loop.  This never returns.
!      */
      main_loop(FALSE, FALSE);
  
  #endif /* NO_VIM_MAIN */
***************
*** 1155,1163 ****
        else if (do_redraw || stuff_empty())
        {
  #ifdef FEAT_GUI
!           /* If ui_breakcheck() was used a resize may have been postponed. */
            gui_may_resize_shell();
  #endif
            /* Trigger CursorMoved if the cursor moved. */
            if (!finish_op && (
                        has_cursormoved()
--- 1155,1169 ----
        else if (do_redraw || stuff_empty())
        {
  #ifdef FEAT_GUI
!           // If ui_breakcheck() was used a resize may have been postponed.
            gui_may_resize_shell();
  #endif
+ #ifdef HAVE_DROP_FILE
+           // If files were dropped while text was locked or the curbuf was
+           // locked, this would be a good time to handle the drop.
+           handle_any_postponed_drop();
+ #endif
+ 
            /* Trigger CursorMoved if the cursor moved. */
            if (!finish_op && (
                        has_cursormoved()
*** ../vim-8.1.0227/src/gui_mac.c       2018-03-06 18:53:06.000000000 +0100
--- src/gui_mac.c       2018-07-29 17:33:07.670760672 +0200
***************
*** 1007,1012 ****
--- 1007,1061 ----
      long theDate; // modification date/time
  };
  
+ static long drop_numFiles;
+ static short drop_gotPosition;
+ static SelectionRange drop_thePosition;
+ 
+     static void
+ drop_callback(void *cookie UNUSED)
+ {
+     /* TODO: Handle the goto/select line more cleanly */
+     if ((drop_numFiles == 1) & (drop_gotPosition))
+     {
+       if (drop_thePosition.lineNum >= 0)
+       {
+           lnum = drop_thePosition.lineNum + 1;
+       /*  oap->motion_type = MLINE;
+           setpcmark();*/
+           if (lnum < 1L)
+               lnum = 1L;
+           else if (lnum > curbuf->b_ml.ml_line_count)
+               lnum = curbuf->b_ml.ml_line_count;
+           curwin->w_cursor.lnum = lnum;
+           curwin->w_cursor.col = 0;
+       /*  beginline(BL_SOL | BL_FIX);*/
+       }
+       else
+           goto_byte(drop_thePosition.startRange + 1);
+     }
+ 
+     /* Update the screen display */
+     update_screen(NOT_VALID);
+ 
+     /* Select the text if possible */
+     if (drop_gotPosition)
+     {
+       VIsual_active = TRUE;
+       VIsual_select = FALSE;
+       VIsual = curwin->w_cursor;
+       if (drop_thePosition.lineNum < 0)
+       {
+           VIsual_mode = 'v';
+           goto_byte(drop_thePosition.endRange);
+       }
+       else
+       {
+           VIsual_mode = 'V';
+           VIsual.col = 0;
+       }
+     }
+ }
+ 
  /* The IDE uses the optional keyAEPosition parameter to tell the ed-
     itor the selection range. If lineNum is zero or greater, scroll the text
     to the specified line. If lineNum is less than zero, use the values in
***************
*** 1113,1160 ****
      }
  
      /* Handle the drop, :edit to get to the file */
!     handle_drop(numFiles, fnames, FALSE);
! 
!     /* TODO: Handle the goto/select line more cleanly */
!     if ((numFiles == 1) & (gotPosition))
!     {
!       if (thePosition.lineNum >= 0)
!       {
!           lnum = thePosition.lineNum + 1;
!       /*  oap->motion_type = MLINE;
!           setpcmark();*/
!           if (lnum < 1L)
!               lnum = 1L;
!           else if (lnum > curbuf->b_ml.ml_line_count)
!               lnum = curbuf->b_ml.ml_line_count;
!           curwin->w_cursor.lnum = lnum;
!           curwin->w_cursor.col = 0;
!       /*  beginline(BL_SOL | BL_FIX);*/
!       }
!       else
!           goto_byte(thePosition.startRange + 1);
!     }
! 
!     /* Update the screen display */
!     update_screen(NOT_VALID);
! 
!     /* Select the text if possible */
!     if (gotPosition)
!     {
!       VIsual_active = TRUE;
!       VIsual_select = FALSE;
!       VIsual = curwin->w_cursor;
!       if (thePosition.lineNum < 0)
!       {
!           VIsual_mode = 'v';
!           goto_byte(thePosition.endRange);
!       }
!       else
!       {
!           VIsual_mode = 'V';
!           VIsual.col = 0;
!       }
!     }
  
      setcursor();
      out_flush();
--- 1162,1171 ----
      }
  
      /* Handle the drop, :edit to get to the file */
!     drop_numFiles = numFiles;
!     drop_gotPosition = gotPosition;
!     drop_thePosition = thePosition;
!     handle_drop(numFiles, fnames, FALSE, drop_callback, NULL);
  
      setcursor();
      out_flush();
*** ../vim-8.1.0227/src/version.c       2018-07-29 16:13:13.431551849 +0200
--- src/version.c       2018-07-29 16:44:55.344870301 +0200
***************
*** 796,797 ****
--- 796,799 ----
  {   /* Add new patch number below this line */
+ /**/
+     228,
  /**/


-- 
We do not stumble over mountains, but over molehills.
                                Confucius

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui