To: vim_dev@googlegroups.com
Subject: Patch 7.3.509
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.3.509
Problem:    ":vimgrep" fails when 'autochdir' is set.
Solution:   A more generic solution for changing directory. (Ben Fritz)
Files:	    src/quickfix.c


*** ../vim-7.3.508/src/quickfix.c	2012-03-07 20:13:44.000000000 +0100
--- src/quickfix.c	2012-04-25 18:52:24.000000000 +0200
***************
*** 130,138 ****
  static void	qf_fill_buffer __ARGS((qf_info_T *qi));
  #endif
  static char_u	*get_mef_name __ARGS((void));
! static buf_T	*load_dummy_buffer __ARGS((char_u *fname));
! static void	wipe_dummy_buffer __ARGS((buf_T *buf));
! static void	unload_dummy_buffer __ARGS((buf_T *buf));
  static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *));
  
  /* Quickfix window check helper macro */
--- 130,139 ----
  static void	qf_fill_buffer __ARGS((qf_info_T *qi));
  #endif
  static char_u	*get_mef_name __ARGS((void));
! static void	restore_start_dir __ARGS((char_u *dirname_start));
! static buf_T	*load_dummy_buffer __ARGS((char_u *fname, char_u *dirname_start, char_u *resulting_dir));
! static void	wipe_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start));
! static void	unload_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start));
  static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *));
  
  /* Quickfix window check helper macro */
***************
*** 3237,3255 ****
  
  	    /* Load file into a buffer, so that 'fileencoding' is detected,
  	     * autocommands applied, etc. */
! 	    buf = load_dummy_buffer(fname);
! 
! 	    /* When autocommands changed directory: go back.  We assume it was
! 	     * ":lcd %:p:h". */
! 	    mch_dirname(dirname_now, MAXPATHL);
! 	    if (STRCMP(dirname_start, dirname_now) != 0)
! 	    {
! 		exarg_T ea;
! 
! 		ea.arg = dirname_start;
! 		ea.cmdidx = CMD_lcd;
! 		ex_cd(&ea);
! 	    }
  
  	    p_mls = save_mls;
  #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
--- 3238,3244 ----
  
  	    /* Load file into a buffer, so that 'fileencoding' is detected,
  	     * autocommands applied, etc. */
! 	    buf = load_dummy_buffer(fname, dirname_start, dirname_now);
  
  	    p_mls = save_mls;
  #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
***************
*** 3320,3326 ****
  		{
  		    /* Never keep a dummy buffer if there is another buffer
  		     * with the same name. */
! 		    wipe_dummy_buffer(buf);
  		    buf = NULL;
  		}
  		else if (!cmdmod.hide
--- 3309,3315 ----
  		{
  		    /* Never keep a dummy buffer if there is another buffer
  		     * with the same name. */
! 		    wipe_dummy_buffer(buf, dirname_start);
  		    buf = NULL;
  		}
  		else if (!cmdmod.hide
***************
*** 3336,3347 ****
  		     * many swap files. */
  		    if (!found_match)
  		    {
! 			wipe_dummy_buffer(buf);
  			buf = NULL;
  		    }
  		    else if (buf != first_match_buf || (flags & VGR_NOJUMP))
  		    {
! 			unload_dummy_buffer(buf);
  			buf = NULL;
  		    }
  		}
--- 3325,3336 ----
  		     * many swap files. */
  		    if (!found_match)
  		    {
! 			wipe_dummy_buffer(buf, dirname_start);
  			buf = NULL;
  		    }
  		    else if (buf != first_match_buf || (flags & VGR_NOJUMP))
  		    {
! 			unload_dummy_buffer(buf, dirname_start);
  			buf = NULL;
  		    }
  		}
***************
*** 3487,3499 ****
  }
  
  /*
!  * Load file "fname" into a dummy buffer and return the buffer pointer.
   * Returns NULL if it fails.
-  * Must call unload_dummy_buffer() or wipe_dummy_buffer() later!
   */
      static buf_T *
! load_dummy_buffer(fname)
      char_u	*fname;
  {
      buf_T	*newbuf;
      buf_T	*newbuf_to_wipe = NULL;
--- 3476,3523 ----
  }
  
  /*
!  * Restore current working directory to "dirname_start" if they differ, taking
!  * into account whether it is set locally or globally.
!  */
!     static void
! restore_start_dir(dirname_start)
!     char_u	*dirname_start;
! {
!     char_u *dirname_now = alloc(MAXPATHL);
! 
!     if (NULL != dirname_now)
!     {
! 	mch_dirname(dirname_now, MAXPATHL);
! 	if (STRCMP(dirname_start, dirname_now) != 0)
! 	{
! 	    /* If the directory has changed, change it back by building up an
! 	     * appropriate ex command and executing it. */
! 	    exarg_T ea;
! 
! 	    ea.arg = dirname_start;
! 	    ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd;
! 	    ex_cd(&ea);
! 	}
!     }
! }
! 
! /*
!  * Load file "fname" into a dummy buffer and return the buffer pointer,
!  * placing the directory resulting from the buffer load into the
!  * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller
!  * prior to calling this function. Restores directory to "dirname_start" prior
!  * to returning, if autocmds or the 'autochdir' option have changed it.
!  *
!  * If creating the dummy buffer does not fail, must call unload_dummy_buffer()
!  * or wipe_dummy_buffer() later!
!  *
   * Returns NULL if it fails.
   */
      static buf_T *
! load_dummy_buffer(fname, dirname_start, resulting_dir)
      char_u	*fname;
+     char_u	*dirname_start;  /* in: old directory */
+     char_u	*resulting_dir;  /* out: new directory */
  {
      buf_T	*newbuf;
      buf_T	*newbuf_to_wipe = NULL;
***************
*** 3548,3569 ****
  	    wipe_buffer(newbuf_to_wipe, FALSE);
      }
  
      if (!buf_valid(newbuf))
  	return NULL;
      if (failed)
      {
! 	wipe_dummy_buffer(newbuf);
  	return NULL;
      }
      return newbuf;
  }
  
  /*
!  * Wipe out the dummy buffer that load_dummy_buffer() created.
   */
      static void
! wipe_dummy_buffer(buf)
      buf_T	*buf;
  {
      if (curbuf != buf)		/* safety check */
      {
--- 3572,3604 ----
  	    wipe_buffer(newbuf_to_wipe, FALSE);
      }
  
+     /*
+      * When autocommands/'autochdir' option changed directory: go back.
+      * Let the caller know what the resulting dir was first, in case it is
+      * important.
+      */
+     mch_dirname(resulting_dir, MAXPATHL);
+     restore_start_dir(dirname_start);
+ 
      if (!buf_valid(newbuf))
  	return NULL;
      if (failed)
      {
! 	wipe_dummy_buffer(newbuf, dirname_start);
  	return NULL;
      }
      return newbuf;
  }
  
  /*
!  * Wipe out the dummy buffer that load_dummy_buffer() created. Restores
!  * directory to "dirname_start" prior to returning, if autocmds or the
!  * 'autochdir' option have changed it.
   */
      static void
! wipe_dummy_buffer(buf, dirname_start)
      buf_T	*buf;
+     char_u	*dirname_start;
  {
      if (curbuf != buf)		/* safety check */
      {
***************
*** 3583,3600 ****
  	 * new aborting error, interrupt, or uncaught exception. */
  	leave_cleanup(&cs);
  #endif
      }
  }
  
  /*
!  * Unload the dummy buffer that load_dummy_buffer() created.
   */
      static void
! unload_dummy_buffer(buf)
      buf_T	*buf;
  {
      if (curbuf != buf)		/* safety check */
  	close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE);
  }
  
  #if defined(FEAT_EVAL) || defined(PROTO)
--- 3618,3645 ----
  	 * new aborting error, interrupt, or uncaught exception. */
  	leave_cleanup(&cs);
  #endif
+ 	/* When autocommands/'autochdir' option changed directory: go back. */
+ 	restore_start_dir(dirname_start);
      }
  }
  
  /*
!  * Unload the dummy buffer that load_dummy_buffer() created. Restores
!  * directory to "dirname_start" prior to returning, if autocmds or the
!  * 'autochdir' option have changed it.
   */
      static void
! unload_dummy_buffer(buf, dirname_start)
      buf_T	*buf;
+     char_u	*dirname_start;
  {
      if (curbuf != buf)		/* safety check */
+     {
  	close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE);
+ 
+ 	/* When autocommands/'autochdir' option changed directory: go back. */
+ 	restore_start_dir(dirname_start);
+     }
  }
  
  #if defined(FEAT_EVAL) || defined(PROTO)
*** ../vim-7.3.508/src/version.c	2012-04-25 18:24:24.000000000 +0200
--- src/version.c	2012-04-25 18:43:10.000000000 +0200
***************
*** 716,717 ****
--- 716,719 ----
  {   /* Add new patch number below this line */
+ /**/
+     509,
  /**/

-- 
   Arthur pulls Pin out.  The MONK blesses the grenade as ...
ARTHUR:  (quietly) One, two, five ...
GALAHAD: Three, sir!
ARTHUR:  Three.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
