To: vim-dev@vim.org
Subject: Patch 6.0.030
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
------------

Patch 6.0.030
Problem:    Using ":source! file" doesn't work inside a loop or after
	    ":argdo". (Pavol Juhas)
Solution:   Execute the commands in the file right away, do not let the main
	    loop do it.
Files:	    src/ex_cmds2.c, src/ex_docmd.c, src/getchar.c, src/globals.h,
	    src/proto/ex_docmd.pro, src/proto/getchar.pro


*** ../vim60.29/src/ex_cmds2.c	Tue Sep 25 14:18:04 2001
--- src/ex_cmds2.c	Thu Oct 25 10:08:24 2001
***************
*** 14,20 ****
  #include "vim.h"
  #include "version.h"
  
! static void	cmd_source __ARGS((char_u *fname, int forceit));
  
  #if defined(FEAT_EVAL) || defined(PROTO)
  
--- 14,20 ----
  #include "vim.h"
  #include "version.h"
  
! static void	cmd_source __ARGS((char_u *fname, exarg_T *eap));
  
  #if defined(FEAT_EVAL) || defined(PROTO)
  
***************
*** 1454,1461 ****
--- 1454,1463 ----
  #endif
  
  	    /* execute the command */
+ 	    listcmd_busy = TRUE;
  	    do_cmdline(eap->arg, eap->getline, eap->cookie,
  						DOCMD_VERBOSE + DOCMD_NOWAIT);
+ 	    listcmd_busy = FALSE;
  
  	    if (eap->cmdidx == CMD_bufdo)
  	    {
***************
*** 1693,1699 ****
  ex_options(eap)
      exarg_T	*eap;
  {
!     cmd_source((char_u *)SYS_OPTWIN_FILE, FALSE);
  }
  #endif
  
--- 1695,1701 ----
  ex_options(eap)
      exarg_T	*eap;
  {
!     cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
  }
  #endif
  
***************
*** 1713,1737 ****
  		NULL, NULL, eap->arg, BROWSE_FILTER_MACROS, curbuf);
  	if (fname != NULL)
  	{
! 	    cmd_source(fname, eap->forceit);
  	    vim_free(fname);
  	}
      }
      else
  #endif
! 	cmd_source(eap->arg, eap->forceit);
  }
  
      static void
! cmd_source(fname, forceit)
      char_u	*fname;
!     int		forceit;
  {
      if (*fname == NUL)
  	EMSG(_(e_argreq));
!     else if (forceit)		/* :so! read vi commands */
! 	(void)openscript(fname);
! 				/* :so read ex commands */
      else if (do_source(fname, FALSE, FALSE) == FAIL)
  	EMSG2(_(e_notopen), fname);
  }
--- 1715,1752 ----
  		NULL, NULL, eap->arg, BROWSE_FILTER_MACROS, curbuf);
  	if (fname != NULL)
  	{
! 	    cmd_source(fname, eap);
  	    vim_free(fname);
  	}
      }
      else
  #endif
! 	cmd_source(eap->arg, eap);
  }
  
      static void
! cmd_source(fname, eap)
      char_u	*fname;
!     exarg_T	*eap;
  {
      if (*fname == NUL)
  	EMSG(_(e_argreq));
! 
!     /* ":source!" read vi commands */
!     else if (eap != NULL && eap->forceit)
! 	/* Need to execute the commands directly when:
! 	 * - ":g" command busy
! 	 * - after ":argdo", ":windo" or ":bufdo"
! 	 * - another command follows
! 	 * - inside a loop
! 	 */
! 	openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
! #ifdef FEAT_EVAL
! 						 || eap->cstack->cs_idx >= 0
! #endif
! 						 );
! 
!     /* ":source" read ex commands */
      else if (do_source(fname, FALSE, FALSE) == FAIL)
  	EMSG2(_(e_notopen), fname);
  }
*** ../vim60.29/src/ex_docmd.c	Fri Oct 19 11:18:45 2001
--- src/ex_docmd.c	Sat Oct 20 16:53:27 2001
***************
*** 276,282 ****
  #endif
  #ifdef FEAT_EX_EXTRA
  static void	ex_normal __ARGS((exarg_T *eap));
- static void	update_topline_cursor __ARGS((void));
  static void	ex_startinsert __ARGS((exarg_T *eap));
  #else
  # define ex_normal		ex_ni
--- 276,281 ----
***************
*** 6777,6782 ****
--- 6776,6794 ----
      }
  }
  
+ /*
+  * Update w_topline, w_leftcol and the cursor position.
+  */
+     void
+ update_topline_cursor()
+ {
+     check_cursor();		/* put cursor on valid line */
+     update_topline();
+     if (!curwin->w_p_wrap)
+ 	validate_cursor();
+     update_curswant();
+ }
+ 
  #ifdef FEAT_EX_EXTRA
  /*
   * ":normal[!] {commands}": Execute normal mode commands.
***************
*** 6937,6955 ****
  #ifdef FEAT_MBYTE
      vim_free(arg);
  #endif
- }
- 
- /*
-  * Update w_topline, w_leftcol and the cursor position.
-  */
-     static void
- update_topline_cursor()
- {
-     check_cursor();		/* put cursor on valid line */
-     update_topline();
-     if (!curwin->w_p_wrap)
- 	validate_cursor();
-     update_curswant();
  }
  
  /*
--- 6949,6954 ----
*** ../vim60.29/src/getchar.c	Sun Sep 16 14:38:55 2001
--- src/getchar.c	Sat Oct 20 18:07:04 2001
***************
*** 1224,1244 ****
  }
  
  /*
!  * open new script file for ":so!" command
!  * return OK on success, FAIL on error
   */
!     int
! openscript(name)
!     char_u *name;
  {
-     int		oldcurscript;
-     oparg_T	oa;
-     int		save_State;
- 
      if (curscript + 1 == NSCRIPT)
      {
  	EMSG(_(e_nesting));
! 	return FAIL;
      }
  
      if (scriptin[curscript] != NULL)	/* already reading script */
--- 1224,1240 ----
  }
  
  /*
!  * Open a new script file for the ":source!" command.
   */
!     void
! openscript(name, directly)
!     char_u	*name;
!     int		directly;	/* when TRUE execute directly */
  {
      if (curscript + 1 == NSCRIPT)
      {
  	EMSG(_(e_nesting));
! 	return;
      }
  
      if (scriptin[curscript] != NULL)	/* already reading script */
***************
*** 1250,1281 ****
  	EMSG2(_(e_notopen), name);
  	if (curscript)
  	    --curscript;
! 	return FAIL;
      }
      if (save_typebuf() == FAIL)
! 	return FAIL;
  
      /*
!      * With command ":g/pat/so! file" we have to execute the
!      * commands from the file now.
       */
!     if (global_busy)
      {
! 	clear_oparg(&oa);
! 	save_State = State;
  	State = NORMAL;
  	oldcurscript = curscript;
  	do
  	{
! 	    check_cursor();	/* put cursor on an existing line */
! 	    normal_cmd(&oa, FALSE);
! 	    vpeekc();		/* check for end of file */
  	}
  	while (scriptin[oldcurscript] != NULL);
  	State = save_State;
      }
- 
-     return OK;
  }
  
  /*
--- 1246,1294 ----
  	EMSG2(_(e_notopen), name);
  	if (curscript)
  	    --curscript;
! 	return;
      }
      if (save_typebuf() == FAIL)
! 	return;
  
      /*
!      * Execute the commands from the file right now when using ":source!"
!      * after ":global" or ":argdo" or in a loop.  Also when another command
!      * follows.  This means the display won't be updated.  Don't do this
!      * always, "make test" would fail.
       */
!     if (directly)
      {
! 	oparg_T	oa;
! 	int	oldcurscript;
! 	int	save_State = State;
! 	int	save_restart_edit = restart_edit;
! 	int	save_insertmode = p_im;
! 	int	save_finish_op = finish_op;
! 	int	save_msg_scroll = msg_scroll;
! 
  	State = NORMAL;
+ 	msg_scroll = FALSE;	/* no msg scrolling in Normal mode */
+ 	restart_edit = 0;	/* don't go to Insert mode */
+ 	p_im = FALSE;		/* don't use 'insertmode' */
+ 	clear_oparg(&oa);
+ 	finish_op = FALSE;
+ 
  	oldcurscript = curscript;
  	do
  	{
! 	    update_topline_cursor();	/* update cursor position and topline */
! 	    normal_cmd(&oa, FALSE);	/* execute one command */
! 	    vpeekc();			/* check for end of file */
  	}
  	while (scriptin[oldcurscript] != NULL);
+ 
  	State = save_State;
+ 	msg_scroll = save_msg_scroll;
+ 	restart_edit = save_restart_edit;
+ 	p_im = save_insertmode;
+ 	finish_op = save_finish_op;
      }
  }
  
  /*
*** ../vim60.29/src/globals.h	Fri Sep 28 22:19:57 2001
--- src/globals.h	Sat Oct 20 17:49:38 2001
***************
*** 752,757 ****
--- 752,759 ----
  					    /* set after swap write error msg */
  EXTERN int	undo_off INIT(= FALSE);	    /* undo switched off for now */
  EXTERN int	global_busy INIT(= 0);	    /* set when :global is executing */
+ EXTERN int	listcmd_busy INIT(= FALSE); /* set when :argdo, :windo or
+ 					       :bufdo is executing */
  EXTERN int	need_start_insertmode INIT(= FALSE);
  					    /* start insert mode soon */
  EXTERN char_u	*last_cmdline INIT(= NULL); /* last command line (for ":) */
*** ../vim60.29/src/proto/ex_docmd.pro	Tue Sep 25 21:49:13 2001
--- src/proto/ex_docmd.pro	Sat Oct 20 16:55:04 2001
***************
*** 29,34 ****
--- 29,35 ----
  void do_exedit __ARGS((exarg_T *eap, win_T *old_curwin));
  void do_sleep __ARGS((long msec));
  FILE *open_exfile __ARGS((char_u *fname, int forceit, char *mode));
+ void update_topline_cursor __ARGS((void));
  char_u *eval_vars __ARGS((char_u *src, int *usedlen, linenr_T *lnump, char_u **errormsg, char_u *srcstart));
  char_u *expand_sfile __ARGS((char_u *arg));
  int put_eol __ARGS((FILE *fd));
*** ../vim60.29/src/proto/getchar.pro	Tue Sep 25 21:49:15 2001
--- src/proto/getchar.pro	Sat Oct 20 17:23:58 2001
***************
*** 26,32 ****
  int alloc_typebuf __ARGS((void));
  void free_typebuf __ARGS((void));
  int save_typebuf __ARGS((void));
! int openscript __ARGS((char_u *name));
  int using_script __ARGS((void));
  void updatescript __ARGS((int c));
  int vgetc __ARGS((void));
--- 26,32 ----
  int alloc_typebuf __ARGS((void));
  void free_typebuf __ARGS((void));
  int save_typebuf __ARGS((void));
! void openscript __ARGS((char_u *name, int directly));
  int using_script __ARGS((void));
  void updatescript __ARGS((int c));
  int vgetc __ARGS((void));
*** ../vim60.29/src/version.c	Sun Oct 28 21:15:32 2001
--- src/version.c	Sun Oct 28 21:17:56 2001
***************
*** 608,609 ****
--- 608,611 ----
  {   /* Add new patch number below this line */
+ /**/
+     30,
  /**/

-- 
BLACK KNIGHT:  I move for no man.
ARTHUR:        So be it!
    [hah] [parry thrust]
    [ARTHUR chops the BLACK KNIGHT's left arm off]
ARTHUR:        Now stand aside, worthy adversary.
BLACK KNIGHT:  'Tis but a scratch.
                                  The Quest for the Holy Grail (Monty Python)

 ///  Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net  \\\
(((   Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim   )))
 \\\  Help me helping AIDS orphans in Uganda - http://iccf-holland.org  ///