changeset 153:19670b05ee32

updated for version 7.0047
author vimboss
date Wed, 02 Feb 2005 23:04:36 +0000
parents c837baf03d43
children 1a145815483e
files runtime/doc/eval.txt runtime/doc/netbeans.txt runtime/doc/tags runtime/ftplugin/vhdl.vim src/ex_docmd.c src/fileio.c src/globals.h src/gui_w32.c src/gui_w48.c src/os_mswin.c src/proto/fileio.pro src/quickfix.c src/regexp.c src/structs.h src/version.h
diffstat 15 files changed, 302 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.0aa.  Last change: 2005 Jan 31
+*eval.txt*      For Vim version 7.0aa.  Last change: 2005 Feb 02
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -80,8 +80,8 @@ Note that in the command >
 "foo" is converted to 0, which means FALSE.  To test for a non-empty string,
 use strlen(): >
 	:if strlen("foo")
-<						*E728* *E729* *E730* *E731*
-List and Funcref types are not automatically converted.
+<				*E745* *E728* *E703* *E729* *E730* *E731*
+List, Dictionary and Funcref types are not automatically converted.
 
 								*E706*
 You will get an error if you try to change the type of a variable.  You need
@@ -93,7 +93,7 @@ equivalent though.  Consider this sequen
 
 
 1.2 Function references ~
-					*Funcref* *E695* *E703* *E718*
+					*Funcref* *E695* *E718*
 A Funcref variable is obtained with the |function()| function.  It can be used
 in an expression in the place of a function name, before the parenthesis
 around the arguments, to invoke the function it refers to.  Example: >
@@ -1560,11 +1560,11 @@ add({list}, {expr})					*add()*
 
 
 append({lnum}, {expr})					*append()*
-		When {expr} is a List: Append each item of the list as a text
+		When {expr} is a List: Append each item of the List as a text
 		line below line {lnum} in the current buffer.
-		Otherwise append the text line {expr} below line {lnum} in the
-		current buffer.
-		{lnum} can be zero, to insert a line before the first one.
+		Otherwise append {expr} as one text line below line {lnum} in
+		the current buffer.
+		{lnum} can be zero to insert a line before the first one.
 		Returns 1 for failure ({lnum} out of range or out of memory),
 		0 for success.  Example: >
 			:let failed = append(line('$'), "# THE END")
@@ -2683,7 +2683,8 @@ indent({lnum})	The result is a Number, w
 index({list}, {expr} [, {start} [, {ic}]])			*index()*
 		Return the lowest index in List {list} where the item has a
 		value equal to {expr}.
-		If {start} is given then skip items with a lower index.
+		If {start} is given then start looking at the item with index
+		{start} (may be negative for an item relative to the end).
 		When {ic} is given and it is non-zero, ignore case.  Otherwise
 		case must match.
 		-1 is returned when {expr} is not found in {list}.
@@ -3762,15 +3763,17 @@ tr({src}, {fromstr}, {tostr})				*tr()*
 
 							*type()*
 type({expr})	The result is a Number, depending on the type of {expr}:
-			Number:  0
-			String:  1
-			Funcref: 2
-			List:    3
-		To avoid the magic numbers it can be used this way: >
+			Number:	    0
+			String:	    1
+			Funcref:    2
+			List:	    3
+			Dictionary: 4
+		To avoid the magic numbers it should be used this way: >
 			:if type(myvar) == type(0)
 			:if type(myvar) == type("")
 			:if type(myvar) == type(function("tr"))
 			:if type(myvar) == type([])
+			:if type(myvar) == type({})
 
 values({dict})						*values()*
 		Return a List with all the values of {dict}.  The List is in
@@ -4358,7 +4361,7 @@ 7. Commands						*expression-commands*
 			When the selected range of items is partly past the
 			end of the list, items will be added.
 
-						*:let+=* *:let-=* *:let.=*
+					*:let+=* *:let-=* *:let.=* *E734*
 :let {var} += {expr1}	Like ":let {var} = {var} + {expr1}".
 :let {var} -= {expr1}	Like ":let {var} = {var} - {expr1}".
 :let {var} .= {expr1}	Like ":let {var} = {var} . {expr1}".
--- a/runtime/doc/netbeans.txt
+++ b/runtime/doc/netbeans.txt
@@ -560,6 +560,9 @@ stopCaretListen
 stopDocumentListen
 		Mark the buffer to stop reporting changes to the IDE.
 		Opposite of startDocumentListen.
+		NOTE: if "netbeansBuffer" was used to mark this buffer as a
+		NetBeans buffer, then the buffer is deleted in Vim.  This is
+		for compatibility with Sun Studio 10.
 
 unguard off len
 		Opposite of "guard", remove guarding for a text area.
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -3639,6 +3639,7 @@ E730	eval.txt	/*E730*
 E731	eval.txt	/*E731*
 E732	eval.txt	/*E732*
 E733	eval.txt	/*E733*
+E734	eval.txt	/*E734*
 E735	eval.txt	/*E735*
 E736	eval.txt	/*E736*
 E737	eval.txt	/*E737*
@@ -3650,6 +3651,7 @@ E741	eval.txt	/*E741*
 E742	eval.txt	/*E742*
 E743	eval.txt	/*E743*
 E744	netbeans.txt	/*E744*
+E745	eval.txt	/*E745*
 E75	vi_diff.txt	/*E75*
 E76	pattern.txt	/*E76*
 E77	message.txt	/*E77*
new file mode 100644
--- /dev/null
+++ b/runtime/ftplugin/vhdl.vim
@@ -0,0 +1,41 @@
+" Vim filetype plugin file
+" Language: VHDL
+" Maintainer:   R.Shankar (shankar at txc.stpn.soft.net)
+" Last Change:  Tue Oct 8
+
+
+" Only do this when not done yet for this buffer
+if exists("b:did_ftplugin")
+  finish
+endif
+
+" Don't load another plugin for this buffer
+let b:did_ftplugin = 1
+
+" Set 'formatoptions' to break comment lines but not other lines,
+" and insert the comment leader when hitting <CR> or using "o".
+"setlocal fo-=t fo+=croqlm1
+
+" Set 'comments' to format dashed lists in comments.
+"setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
+
+" Format comments to be up to 78 characters long
+setlocal tw=75
+
+set cpo-=C
+
+" Win32 can filter files in the browse dialog
+"if has("gui_win32") && !exists("b:browsefilter")
+"  let b:browsefilter = "Verilog Source Files (*.v)\t*.v\n" .
+"   \ "All Files (*.*)\t*.*\n"
+"endif
+
+" Let the matchit plugin know what items can be matched.
+if ! exists("b:match_words")  &&  exists("loaded_matchit")
+  let b:match_ignorecase=1
+  let s:notend = '\%(\<end\s\+\)\@<!'
+  let b:match_words=
+  \ s:notend . '\<if\>:\<elsif\>:\<else\>:\<end\>\s\+\<if\>,' .
+  \ s:notend . '\<case\>:\<when\>:\<end\>\s\+\<case\>,' .
+  \ s:notend . '\<process\>:\<end\>\s\+\<process\>'
+endif
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3180,13 +3180,7 @@ set_one_cmd_context(xp, buff)
 	p++;
     xp->xp_pattern = p;
 
-    if ((argt & XFILE)
-#ifdef FEAT_QUICKFIX
-	    || cmdidx == CMD_vimgrep
-	    || cmdidx == CMD_vimgrepadd
-	    || grep_internal(cmdidx)
-#endif
-       )
+    if (argt & XFILE)
     {
 	int in_quote = FALSE;
 	char_u *bow = NULL;	/* Beginning of word */
@@ -3919,6 +3913,32 @@ correct_range(eap)
     }
 }
 
+#ifdef FEAT_QUICKFIX
+static char_u	*skip_grep_pat __ARGS((exarg_T *eap));
+
+/*
+ * For a ":vimgrep" or ":vimgrepadd" command return a pointer past the
+ * pattern.  Otherwise return eap->arg.
+ */
+    static char_u *
+skip_grep_pat(eap)
+    exarg_T	*eap;
+{
+    char_u	*p = eap->arg;
+
+    if (*p != NUL && (eap->cmdidx == CMD_vimgrep
+		|| eap->cmdidx == CMD_vimgrepadd || grep_internal(eap->cmdidx)))
+    {
+	p = skip_vimgrep_pat(p, NULL);
+	if (p == NULL)
+	    p = eap->arg;
+	else if (*p != NUL && !vim_iswhite(*p))
+	    ++p;	/* step past ending separator of /pat/ */
+    }
+    return p;
+}
+#endif
+
 /*
  * Expand file name in Ex command argument.
  * Return FAIL for failure, OK otherwise.
@@ -3935,13 +3955,20 @@ expand_filename(eap, cmdlinep, errormsgp
     char_u	*p;
     int		n;
 
+#ifdef FEAT_QUICKFIX
+    /* Skip a regexp pattern for ":vimgrep[add] pat file..." */
+    p = skip_grep_pat(eap);
+#else
+    p = eap->arg;
+#endif
+
     /*
      * Decide to expand wildcards *before* replacing '%', '#', etc.  If
      * the file name contains a wildcard it should not cause expanding.
      * (it will be expanded anyway if there is a wildcard before replacing).
      */
-    has_wildcards = mch_has_wildcard(eap->arg);
-    for (p = eap->arg; *p; )
+    has_wildcards = mch_has_wildcard(p);
+    while (*p != NUL)
     {
 #ifdef FEAT_EVAL
 	/* Skip over `=expr`, wildcards in it are not expanded. */
@@ -4225,22 +4252,10 @@ separate_nextcmd(eap)
 {
     char_u	*p;
 
+#ifdef FEAT_QUICKFIX
+    p = skip_grep_pat(eap);
+#else
     p = eap->arg;
-#ifdef FEAT_QUICKFIX
-    if (*p != NUL && (eap->cmdidx == CMD_vimgrep
-		|| eap->cmdidx == CMD_vimgrepadd
-		|| grep_internal(eap->cmdidx)))
-    {
-	/* Skip over the pattern. */
-	if (vim_isIDc(*p))
-	    p = skiptowhite(p);
-	else
-	{
-	    p = skip_regexp(p + 1, *p, TRUE, NULL);
-	    if (*p == *eap->arg)
-		++p;
-	}
-    }
 #endif
 
     for ( ; *p; mb_ptr_adv(p))
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6585,7 +6585,7 @@ typedef struct AutoPat
     char_u	    *pat;		/* pattern as typed (NULL when pattern
 					   has been removed) */
     int		    patlen;		/* strlen() of pat */
-    char_u	    *reg_pat;		/* pattern converted to regexp */
+    regprog_T	    *reg_prog;		/* compiled regprog for pattern */
     char	    allow_dirs;		/* Pattern may match whole path */
     char	    last;		/* last pattern for apply_autocmds() */
     AutoCmd	    *cmds;		/* list of commands to do */
@@ -6865,7 +6865,7 @@ au_cleanup()
 	    if (ap->pat == NULL)
 	    {
 		*prev_ap = ap->next;
-		vim_free(ap->reg_pat);
+		vim_free(ap->reg_prog);
 		vim_free(ap);
 	    }
 	    else
@@ -7167,8 +7167,6 @@ au_event_restore(old_ei)
     if (old_ei != NULL)
     {
 	set_string_option_direct((char_u *)"ei", -1, old_ei, OPT_FREE);
-	apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
-					       curbuf->b_fname, TRUE, curbuf);
 	vim_free(old_ei);
     }
 }
@@ -7542,15 +7540,20 @@ do_autocmd_event(event, pat, nested, cmd
 		if (is_buflocal)
 		{
 		    ap->buflocal_nr = buflocal_nr;
-		    ap->reg_pat = NULL;
+		    ap->reg_prog = NULL;
 		}
 		else
 		{
+		    char_u	*reg_pat;
+
 		    ap->buflocal_nr = 0;
-		    ap->reg_pat = file_pat_to_reg_pat(pat, endpat,
+		    reg_pat = file_pat_to_reg_pat(pat, endpat,
 							 &ap->allow_dirs, TRUE);
-		    if (ap->reg_pat == NULL)
+		    if (reg_pat != NULL)
+			ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
+		    if (reg_pat == NULL || ap->reg_prog == NULL)
 		    {
+			vim_free(reg_pat);
 			vim_free(ap->pat);
 			vim_free(ap);
 			return FAIL;
@@ -8250,8 +8253,8 @@ auto_next_pat(apc, stop_at_last)
 	{
 	    /* execution-condition */
 	    if (ap->buflocal_nr == 0
-		    ? (match_file_pat(ap->reg_pat, apc->fname, apc->sfname,
-						   apc->tail, ap->allow_dirs))
+		    ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
+				      apc->sfname, apc->tail, ap->allow_dirs))
 		    : ap->buflocal_nr == apc->arg_bufnr)
 	    {
 		name = event_nr2name(apc->event);
@@ -8381,8 +8384,8 @@ has_autocmd(event, sfname, buf)
     for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
 	if (ap->pat != NULL && ap->cmds != NULL
             && (ap->buflocal_nr == 0
-		? match_file_pat(ap->reg_pat, fname, sfname, tail,
-							       ap->allow_dirs)
+		? match_file_pat(NULL, ap->reg_prog,
+					  fname, sfname, tail, ap->allow_dirs)
                 : buf != NULL && ap->buflocal_nr == buf->b_fnum
 	   ))
 	{
@@ -8549,13 +8552,16 @@ au_exists(name, name_end, pattern)
 
 #if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
 /*
- * Try matching a filename with a pattern.
+ * Try matching a filename with a "pattern" ("prog" is NULL), or use the
+ * precompiled regprog "prog" ("pattern" is NULL).  That avoids calling
+ * vim_regcomp() often.
  * Used for autocommands and 'wildignore'.
  * Returns TRUE if there is a match, FALSE otherwise.
  */
     int
-match_file_pat(pattern, fname, sfname, tail, allow_dirs)
+match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
     char_u	*pattern;		/* pattern to match with */
+    regprog_T	*prog;			/* pre-compiled regprog or NULL */
     char_u	*fname;			/* full path of file name */
     char_u	*sfname;		/* short file name or NULL */
     char_u	*tail;			/* tail of path */
@@ -8610,7 +8616,12 @@ match_file_pat(pattern, fname, sfname, t
     }
     else
 #endif
-	regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
+    {
+	if (prog != NULL)
+	    regmatch.regprog = prog;
+	else
+	    regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
+    }
 
     /*
      * Try for a match with the pattern with:
@@ -8633,7 +8644,8 @@ match_file_pat(pattern, fname, sfname, t
 		 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
 	result = TRUE;
 
-    vim_free(regmatch.regprog);
+    if (prog == NULL)
+	vim_free(regmatch.regprog);
     return result;
 }
 #endif
@@ -8667,7 +8679,8 @@ match_file_list(list, sfname, ffname)
 	regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
 	if (regpat == NULL)
 	    break;
-	match = match_file_pat(regpat, ffname, sfname, tail, (int)allow_dirs);
+	match = match_file_pat(regpat, NULL, ffname, sfname,
+						       tail, (int)allow_dirs);
 	vim_free(regpat);
 	if (match)
 	    return TRUE;
--- a/src/globals.h
+++ b/src/globals.h
@@ -1402,6 +1402,10 @@ EXTERN char_u e_nbreadonly[]	INIT(=N_("E
 #if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
 EXTERN char_u e_intern2[]	INIT(=N_("E685: Internal error: %s"));
 #endif
+#if defined(HAVE_SETJMP_H) || defined(HAVE_TRY_EXCEPT)
+EXTERN char_u e_complex[]	INIT(=N_("E361: Crash intercepted; regexp too complex?"));
+#endif
+EXTERN char_u e_outofstack[]	INIT(=N_("E363: pattern caused out-of-stack error"));
 
 
 #ifdef MACOS_X_UNIX
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -991,13 +991,10 @@ gui_mch_init(void)
     ATOM	atom;
 #endif
 
-    /* Display any pending error messages */
-    display_errors();
-
     /* Return here if the window was already opened (happens when
      * gui_mch_dialog() is called early). */
     if (s_hwnd != NULL)
-	return OK;
+	goto theend;
 
     /*
      * Load the tearoff bitmap
@@ -1224,6 +1221,10 @@ gui_mch_init(void)
     s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
 #endif
 
+theend:
+    /* Display any pending error messages */
+    display_errors();
+
     return OK;
 }
 
@@ -2540,6 +2541,8 @@ gui_mch_dialog(
     int		fontHeight;
     int		textWidth, minButtonWidth, messageWidth;
     int		maxDialogWidth;
+    int		maxDialogHeight;
+    int		scroll_flag = 0;
     int		vertical;
     int		dlgPaddingX;
     int		dlgPaddingY;
@@ -2554,9 +2557,14 @@ gui_mch_dialog(
 	return dfltbutton;   /* return default option */
 #endif
 
+#if 0
     /* If there is no window yet, open it. */
     if (s_hwnd == NULL && gui_mch_init() == FAIL)
 	return dfltbutton;
+#else
+    if (s_hwnd == NULL)
+	get_dialog_font_metrics();
+#endif
 
     if ((type < 0) || (type > VIM_LAST_TYPE))
 	type = 0;
@@ -2639,10 +2647,14 @@ gui_mch_dialog(
     if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
 	maxDialogWidth = DLG_MIN_MAX_WIDTH;
 
+    maxDialogHeight = rect.bottom - rect.top - GetSystemMetrics(SM_CXFRAME) * 2;
+    if (maxDialogHeight < DLG_MIN_MAX_HEIGHT)
+	maxDialogHeight = DLG_MIN_MAX_HEIGHT;
+
     /* Set dlgwidth to width of message */
     pstart = message;
     messageWidth = 0;
-    msgheight = 0;
+    msgheight = fontHeight;
     do
     {
 	pend = vim_strchr(pstart, DLG_BUTTON_SEP);
@@ -2650,14 +2662,33 @@ gui_mch_dialog(
 	    pend = pstart + STRLEN(pstart);	/* Last line of message. */
 	msgheight += fontHeight;
 	textWidth = GetTextWidth(hdc, pstart, (int)(pend - pstart));
-	if (textWidth > messageWidth)
+	if (textWidth >= maxDialogWidth)
+	{
+	    /* Line will wrap.  This doesn't work correctly, because the wrap
+	     * happens at a word boundary! */
+	    messageWidth = maxDialogWidth;
+	    while (textWidth >= maxDialogWidth)
+	    {
+		msgheight += fontHeight;
+		textWidth -= maxDialogWidth;
+	    }
+	}
+	else if (textWidth > messageWidth)
 	    messageWidth = textWidth;
 	pstart = pend + 1;
     } while (*pend != NUL);
-    dlgwidth = messageWidth;
+
+    messageWidth += 10;		/* roundoff space */
+
+    /* Restrict the size to a maximum.  Causes a scrollbar to show up. */
+    if (msgheight > maxDialogHeight)
+    {
+	msgheight = maxDialogHeight;
+	scroll_flag = WS_VSCROLL;
+    }
 
     /* Add width of icon to dlgwidth, and some space */
-    dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;
+    dlgwidth = messageWidth + DLG_ICON_WIDTH + 3 * dlgPaddingX;
 
     if (msgheight < DLG_ICON_HEIGHT)
 	msgheight = DLG_ICON_HEIGHT;
@@ -2839,6 +2870,7 @@ gui_mch_dialog(
 	    DLG_NONBUTTON_CONTROL + 0, (WORD)0x0082,
 	    dlg_icons[type]);
 
+#if 0
     /* Dialog message */
     p = add_dialog_element(p, SS_LEFT,
 	    PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
@@ -2846,6 +2878,15 @@ gui_mch_dialog(
 	    (WORD)(PixelToDialogX(messageWidth) + 1),
 	    PixelToDialogY(msgheight),
 	    DLG_NONBUTTON_CONTROL + 1, (WORD)0x0082, message);
+#else
+    /* Dialog message */
+    p = add_dialog_element(p, ES_LEFT|scroll_flag|ES_MULTILINE|ES_READONLY,
+	    PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
+	    PixelToDialogY(dlgPaddingY),
+	    (WORD)(PixelToDialogX(messageWidth) + 1),
+	    PixelToDialogY(msgheight),
+	    DLG_NONBUTTON_CONTROL + 1, (WORD)0x0081, message);
+#endif
 
     /* Edit box */
     if (textfield != NULL)
--- a/src/gui_w48.c
+++ b/src/gui_w48.c
@@ -61,6 +61,7 @@
 #define DLG_FONT_NAME		"MS Sans Serif"
 #define DLG_FONT_POINT_SIZE	8
 #define DLG_MIN_MAX_WIDTH	400
+#define DLG_MIN_MAX_HEIGHT	400
 
 #define DLG_NONBUTTON_CONTROL	5000	/* First ID of non-button controls */
 
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -595,11 +595,16 @@ display_errors()
 #endif
 		    STRCPY(s, _("...(truncated)"));
 		}
+
+		(void)gui_mch_dialog(VIM_ERROR, (char_u *)_("Error"),
+					      p, (char_u *)_("&Ok"), 1, NULL);
+#if 0
 #ifdef WIN3264
 		MessageBox(NULL, p, "Vim", MB_TASKMODAL|MB_SETFOREGROUND);
 #else
 		MessageBox(NULL, p, "Vim", MB_TASKMODAL);
 #endif
+#endif
 		break;
 	    }
 	ga_clear(&error_ga);
--- a/src/proto/fileio.pro
+++ b/src/proto/fileio.pro
@@ -38,7 +38,7 @@ char_u *get_augroup_name __ARGS((expand_
 char_u *set_context_in_autocmd __ARGS((expand_T *xp, char_u *arg, int doautocmd));
 char_u *get_event_name __ARGS((expand_T *xp, int idx));
 int au_exists __ARGS((char_u *name, char_u *name_end, char_u *pattern));
-int match_file_pat __ARGS((char_u *pattern, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs));
+int match_file_pat __ARGS((char_u *pattern, regprog_T *prog, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs));
 int match_file_list __ARGS((char_u *list, char_u *sfname, char_u *ffname));
 char_u *file_pat_to_reg_pat __ARGS((char_u *pat, char_u *pat_end, char *allow_dirs, int no_bslash));
 /* vim: set ft=c : */
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2256,12 +2256,12 @@ ex_vimgrep(eap)
 {
     regmmatch_T	regmatch;
     char_u	*save_cpo;
-    int         fcount;
+    int		fcount;
     char_u	**fnames;
-    char_u      *s;
-    char_u      *p;
+    char_u	*s;
+    char_u	*p;
     int		i;
-    int         fi;
+    int		fi;
     struct qf_line *prevp = NULL;
     long	lnum;
     garray_T	ga;
@@ -2282,20 +2282,11 @@ ex_vimgrep(eap)
 
     /* Get the search pattern: either white-separated or enclosed in // */
     regmatch.regprog = NULL;
-    if (vim_isIDc(*eap->arg))
-    {
-	s = eap->arg;
-	p = skiptowhite(s);
-    }
-    else
+    p = skip_vimgrep_pat(eap->arg, &s);
+    if (p == NULL)
     {
-	s = eap->arg + 1;
-	p = skip_regexp(s, *eap->arg, TRUE, NULL);
-	if (*p != *eap->arg)
-	{
-	    EMSG(_("E682: Invalid search pattern or delimiter"));
-	    goto theend;
-	}
+	EMSG(_("E682: Invalid search pattern or delimiter"));
+	goto theend;
     }
     if (*p != NUL)
 	*p++ = NUL;
@@ -2391,6 +2382,25 @@ ex_vimgrep(eap)
 	else
 	{
 	    found_match = FALSE;
+#ifdef HAVE_SETJMP_H
+	    /*
+	     * Matching with a regexp may cause a very deep recursive call of
+	     * regmatch().  Vim will crash when running out of stack space.
+	     * Catch this here if the system supports it.
+	     * It's a bit slow, thus do it outside of the loop.
+	     */
+	    mch_startjmp();
+	    if (SETJMP(lc_jump_env) != 0)
+	    {
+		mch_didjmp();
+# ifdef SIGHASARG
+		if (lc_signal != SIGINT)
+# endif
+		    EMSG(_(e_complex));
+		got_int = TRUE;
+		goto jumpend;
+	    }
+#endif
 	    for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
 	    {
 		if (vim_regexec_multi(&regmatch, curwin, buf, lnum,
@@ -2419,6 +2429,10 @@ ex_vimgrep(eap)
 		if (got_int)
 		    break;
 	    }
+#ifdef HAVE_SETJMP_H
+jumpend:
+	    mch_endjmp();
+#endif
 
 	    if (using_dummy)
 	    {
@@ -2453,10 +2467,12 @@ ex_vimgrep(eap)
 		if (buf != NULL)
 		{
 		    /* The buffer is still loaded, the Filetype autocommands
-		     * need to be done now, in that buffer. */
+		     * need to be done now, in that buffer.  And then the
+		     * modelines (again). */
 		    aucmd_prepbuf(&aco, buf);
 		    apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
 						     buf->b_fname, TRUE, buf);
+		    do_modelines(FALSE);
 		    aucmd_restbuf(&aco);
 		}
 #endif
@@ -2491,6 +2507,33 @@ theend:
 }
 
 /*
+ * Skip over the pattern argument of ":vimgrep /pat/".
+ * Put the start of the pattern in "*s", unless "s" is NULL.
+ * Return a pointer to the char just past the pattern.
+ */
+    char_u *
+skip_vimgrep_pat(p, s)
+    char_u *p;
+    char_u **s;
+{
+    int		c;
+
+    if (vim_isIDc(*p))
+    {
+	if (s != NULL)
+	    *s = p;
+	return skiptowhite(p);
+    }
+    if (s != NULL)
+	*s = p + 1;
+    c = *p;
+    p = skip_regexp(p + 1, c, TRUE, NULL);
+    if (*p != c)
+	return NULL;
+    return p;
+}
+
+/*
  * 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!
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -726,7 +726,7 @@ re_lookbehind(prog)
 
 /*
  * Skip past regular expression.
- * Stop at end of 'p' or where 'dirc' is found ('/', '?', etc).
+ * Stop at end of "startp" or where "dirc" is found ('/', '?', etc).
  * Take care of characters with a backslash in front of it.
  * Skip strings inside [ and ].
  * When "newp" is not NULL and "dirc" is '?', make an allocated copy of the
@@ -3010,33 +3010,12 @@ vim_regexec_both(line, col)
 #ifdef HAVE_SETJMP_H
     char_u	*line;
     colnr_T	col;
+    int		did_mch_startjmp = FALSE;
 #endif
 
     reg_tofree = NULL;
 
-#ifdef HAVE_TRY_EXCEPT
-    __try
-    {
-#endif
-
 #ifdef HAVE_SETJMP_H
-    /*
-     * Matching with a regexp may cause a very deep recursive call of
-     * regmatch().  Vim will crash when running out of stack space.  Catch
-     * this here if the system supports it.
-     */
-    mch_startjmp();
-    if (SETJMP(lc_jump_env) != 0)
-    {
-	mch_didjmp();
-# ifdef SIGHASARG
-	if (lc_signal != SIGINT)
-# endif
-	    EMSG(_("E361: Crash intercepted; regexp too complex?"));
-	retval = 0L;
-	goto theend;
-    }
-
     /* Trick to avoid "might be clobbered by `longjmp'" warning from gcc. */
     line = line_arg;
     col = col_arg;
@@ -3102,6 +3081,36 @@ vim_regexec_both(line, col)
 	    goto theend;
     }
 
+#ifdef HAVE_TRY_EXCEPT
+    __try
+    {
+#endif
+
+#ifdef HAVE_SETJMP_H
+    /*
+     * Matching with a regexp may cause a very deep recursive call of
+     * regmatch().  Vim will crash when running out of stack space.  Catch
+     * this here if the system supports it.
+     * It's a bit slow, do it after the check for "regmust".
+     * Don't do it if the caller already set it up.
+     */
+    if (!lc_active)
+    {
+	did_mch_startjmp = TRUE;
+	mch_startjmp();
+	if (SETJMP(lc_jump_env) != 0)
+	{
+	    mch_didjmp();
+# ifdef SIGHASARG
+	    if (lc_signal != SIGINT)
+# endif
+		EMSG(_(e_complex));
+	    retval = 0L;
+	    goto inner_end;
+	}
+    }
+#endif
+
     regline = line;
     reglnum = 0;
     out_of_stack = FALSE;
@@ -3168,8 +3177,12 @@ vim_regexec_both(line, col)
     }
 
     if (out_of_stack)
-	EMSG(_("E363: pattern caused out-of-stack error"));
-
+	EMSG(_(e_outofstack));
+
+#ifdef HAVE_SETJMP_H
+inner_end:
+    ;
+#endif
 #ifdef HAVE_TRY_EXCEPT
     }
     __except(EXCEPTION_EXECUTE_HANDLER)
@@ -3177,20 +3190,21 @@ vim_regexec_both(line, col)
 	if (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW)
 	{
 	    RESETSTKOFLW();
-	    EMSG(_("E363: pattern caused out-of-stack error"));
+	    EMSG(_(e_outofstack));
 	}
 	else
-	    EMSG(_("E361: Crash intercepted; regexp too complex?"));
+	    EMSG(_(e_complex));
 	retval = 0L;
     }
 #endif
+#ifdef HAVE_SETJMP_H
+    if (did_mch_startjmp)
+	mch_endjmp();
+#endif
 
 theend:
     /* Didn't find a match. */
     vim_free(reg_tofree);
-#ifdef HAVE_SETJMP_H
-    mch_endjmp();
-#endif
     return retval;
 }
 
--- a/src/structs.h
+++ b/src/structs.h
@@ -1015,9 +1015,12 @@ struct listwatch_S
 struct listvar_S
 {
     int		lv_refcount;	/* reference count */
+    int		lv_len;		/* number of items */
     listitem_T	*lv_first;	/* first item, NULL if none */
     listitem_T	*lv_last;	/* last item, NULL if none */
     listwatch_T	*lv_watch;	/* first watcher, NULL if none */
+    int		lv_idx;		/* cached index of an item */
+    listitem_T	*lv_idx_item;	/* when not NULL item at index "lv_idx" */
     char	lv_lock;	/* zero, VAR_LOCKED, VAR_FIXED */
 };
 
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2005 Jan 31)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2005 Jan 31, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 2)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 2, compiled "