changeset 41:f529edb9bab3 v7.0025

updated for version 7.0025
author vimboss
date Mon, 27 Dec 2004 21:59:20 +0000
parents f1d2a58883b9
children c75153d791d0
files runtime/doc/change.txt runtime/doc/index.txt runtime/doc/options.txt runtime/doc/quickfix.txt runtime/doc/tags runtime/doc/todo.txt runtime/doc/version7.txt runtime/optwin.vim src/buffer.c src/charset.c src/digraph.c src/edit.c src/eval.c src/ex_cmds.c src/ex_cmds.h src/ex_cmds2.c src/ex_docmd.c src/ex_getln.c src/fileio.c src/fold.c src/gui_gtk.c src/if_xcmdsrv.c src/main.c src/mbyte.c src/menu.c src/message.c src/misc1.c src/misc2.c src/option.c src/os_mswin.c src/os_win32.c src/proto/buffer.pro src/proto/ex_cmds2.pro src/proto/ex_docmd.pro src/proto/quickfix.pro src/quickfix.c src/regexp.c src/structs.h src/syntax.c src/tag.c src/term.c
diffstat 41 files changed, 537 insertions(+), 219 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt*    For Vim version 7.0aa.  Last change: 2004 Dec 17
+*change.txt*    For Vim version 7.0aa.  Last change: 2004 Dec 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1332,10 +1332,12 @@ a	Automatic formatting of paragraphs.  E
 	deleted the paragraph will be reformatted.  See |auto-format|.
 	When the 'c' flag is present this only happens for recognized
 	comments.
-n	When formatting text, recognize numbered lists.  The indent of the
-	text after the number is used for the next line.  The number may
-	optionally be followed by '.', ':', ')', ']' or '}'.  Note that
-	'autoindent' must be set too.  Doesn't work well together with "2".
+n	When formatting text, recognize numbered lists.  This actually uses
+	the 'formatlistpat' option, thus any kind of list can be used.  The
+	indent of the text after the number is used for the next line.  The
+	default is to find a number, optionally be followed by '.', ':', ')',
+	']' or '}'.  Note that 'autoindent' must be set too.  Doesn't work
+	well together with "2".
 	Example: >
 		1. the first item
 		   wraps
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1,4 +1,4 @@
-*index.txt*     For Vim version 7.0aa.  Last change: 2004 Dec 23
+*index.txt*     For Vim version 7.0aa.  Last change: 2004 Dec 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1059,6 +1059,7 @@ The commands are sorted on the non-optio
 |:cabclear|	:cabc[lear]	clear all abbreviations for Command-line mode
 |:call|		:cal[l]		call a function
 |:catch|	:cat[ch]	part of a :try command
+|:cbuffer|	:cb[uffer]	parse error messages and jump to first error
 |:cc|		:cc		go to specific error
 |:cclose|	:ccl[ose]	close quickfix window
 |:cd|		:cd		change directory
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.0aa.  Last change: 2004 Dec 21
+*options.txt*	For Vim version 7.0aa.  Last change: 2004 Dec 24
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2728,6 +2728,20 @@ A jump table for the options with a shor
 	NOTE: This option is set to the Vi default value when 'compatible' is
 	set and to the Vim default value when 'compatible' is reset.
 
+					*'formatlistpat'* *'flp'*
+'formatlistpat' 'flp'	string (default: "^\s*\d\+[\]:.)}\t ]\s*")
+			local to buffer
+			{not in Vi}
+	A pattern that is used to recognize a list header.  This is used for
+	the "n" flag in 'formatoptions'.
+	The pattern must match exactly the text that will be the indent for
+	the line below it.  You can use |\ze| to mark the end of the match
+	while still checking more characters.  There must be a character
+	following the pattern, when it matches the whole line it is handled
+	like there is no match.
+	The default recognizes a number, followed by an optional punctuation
+	character and white space.
+
 						*'formatprg'* *'fp'*
 'formatprg' 'fp'	string (default "")
 			global
@@ -2795,7 +2809,9 @@ A jump table for the options with a shor
 	When your "grep" accepts the "-H" argument, use this to make ":grep"
 	also work well with a single file: >
 		:set grepprg=grep\ -nH
-<	See also the section |:make_makeprg|, since most of the comments there
+<	Special value: When 'grepprg' is set to "internal" the ":grep" works
+	like ":vimgrep".
+	See also the section |:make_makeprg|, since most of the comments there
 	apply equally to 'grepprg'.
 	For Win32, the default is "findstr /n" if "findstr.exe" can be found,
 	otherwise it's "grep -n".
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1,4 +1,4 @@
-*quickfix.txt*  For Vim version 7.0aa.  Last change: 2004 Jun 16
+*quickfix.txt*  For Vim version 7.0aa.  Last change: 2004 Dec 27
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -105,6 +105,14 @@ The following quickfix commands can be u
 			Read the error file.  Just like ":cfile" but don't
 			jump to the first error.
 
+						*:cb* *:cbuffer* *E681*
+:cb[uffer] [bufnr]	Read the error list from the current buffer.
+			When [bufnr] is given it must be the number of a
+			loaded buffer.  That buffer will then be used instead
+			of the current buffer.
+			A range can be specified for the lines to be used.
+			Otherwise all lines in the buffer are used.
+
 							*:cl* *:clist*
 :cl[ist] [from] [, [to]]
 			List all errors that are valid |quickfix-valid|.
@@ -266,7 +274,37 @@ If 'shellpipe' is empty, the {errorfile}
 for compilers that write to an errorfile themselves (e.g., Manx's Amiga C).
 
 ==============================================================================
-5. Using :grep						*grep* *lid*
+5. Using :vimgrep and :grep				*grep* *lid*
+
+Vim has two ways to find matches for a pattern: Internal and external.  The
+advantage of the internal grep is that it works on all systems and uses the
+powerful Vim search patterns.  An external grep program can be used when the
+Vim grep does not do what you want.
+
+The internal method may be a bit slower, because files are read into memory.
+The advantage is that line separators and encoding are automatically
+recognized, as if a file is being edited.  And multi-line patterns can be
+used.
+
+
+5.1 using Vim's internal grep
+
+							*:vim* *:vimgrep*
+:vim[grep][!] /{pattern}/ {file} ...
+			Search for {pattern} in the files {file} ... and set
+			the error list to the matches.
+			{pattern} if a Vim search pattern.  Instead of
+			enclosing it in / any character can be used, so long
+			as it does not appear in {pattern}.
+
+						*:vimgrepa* *:vimgrepadd*
+:vimgrepa[dd][!] /{pattern}/ {file} ...
+			Just like ":vimgrep", but instead of making a new list
+			of errors the matches are appended to the current
+			list.
+
+
+5.2 External grep
 
 Vim can interface with "grep" and grep-like programs (such as the GNU
 id-utils) in a similar way to its compiler integration (see |:make| above).
@@ -277,6 +315,9 @@ id-utils) in a similar way to its compil
 							    *:gr* *:grep*
 :gr[ep][!] [arguments]	Just like ":make", but use 'grepprg' instead of
 			'makeprg' and 'grepformat' instead of 'errorformat'.
+			When 'grepprg' is "internal" this works like
+			|:vimgrep|.  Note that the pattern needs to be
+			enclosed in separator characters then.
 							*:grepa* *:grepadd*
 :grepa[dd][!] [arguments]
 			Just like ":grep", but instead of making a new list of
@@ -290,7 +331,7 @@ id-utils) in a similar way to its compil
 			":grepadd" jumps to the first error, which is not
 			allowed with |:bufdo|.
 
-5.1 Setting up grep
+5.3 Setting up external grep
 
 If you have a standard "grep" program installed, the :grep command may work
 well with the defaults. The syntax is very similar to the standard command: >
@@ -322,7 +363,7 @@ error in |quickfix| mode.  You can then 
 commands to see the other matches.
 
 
-5.2 Using :grep with id-utils
+5.4 Using :grep with id-utils
 
 You can set up :grep to work with the GNU id-utils like this: >
 
@@ -336,31 +377,31 @@ works just as you'd expect.
 (provided you remembered to mkid first :)
 
 
-5.3 Browsing source code with :grep
+5.5 Browsing source code with :vimgrep or :grep
 
 Using the stack of error lists that Vim keeps, you can browse your files to
 look for functions and the functions they call.  For example, suppose that you
 have to add an argument to the read_file() function.  You enter this command: >
 
-	:grep read_file *.c
+	:vimgrep /\<read_file\>/ *.c
 
 You use ":cn" to go along the list of matches and add the argument.  At one
 place you have to get the new argument from a higher level function msg(), and
 need to change that one too.  Thus you use: >
 
-	:grep msg *.c
+	:vimgrep /\<msg\>/ *.c
 
 While changing the msg() functions, you find another function that needs to
-get the argument from a higher level.  You can again use ":grep" to find these
-functions.  Once you are finished with one function, you can use >
+get the argument from a higher level.  You can again use ":vimgrep" to find
+these functions.  Once you are finished with one function, you can use >
 
 	:colder
 
 to go back to the previous one.
 
-This works like browsing a tree: ":grep" goes one level deeper, creating a
+This works like browsing a tree: ":vimgrep" goes one level deeper, creating a
 list of branches.  ":colder" goes back to the previous level.  You can mix
-this use of ":grep" and "colder" to browse all the locations in a tree-like
+this use of ":vimgrep" and "colder" to browse all the locations in a tree-like
 way.  If you do this consistently, you will find all locations without the
 need to write down a "todo" list.
 
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -210,6 +210,7 @@
 'fkmap'	options.txt	/*'fkmap'*
 'fl'	vi_diff.txt	/*'fl'*
 'flash'	vi_diff.txt	/*'flash'*
+'flp'	options.txt	/*'flp'*
 'fml'	options.txt	/*'fml'*
 'fmr'	options.txt	/*'fmr'*
 'fo'	options.txt	/*'fo'*
@@ -226,6 +227,7 @@
 'foldnestmax'	options.txt	/*'foldnestmax'*
 'foldopen'	options.txt	/*'foldopen'*
 'foldtext'	options.txt	/*'foldtext'*
+'formatlistpat'	options.txt	/*'formatlistpat'*
 'formatoptions'	options.txt	/*'formatoptions'*
 'formatprg'	options.txt	/*'formatprg'*
 'fp'	options.txt	/*'fp'*
@@ -1723,6 +1725,8 @@ 90.5	usr_90.txt	/*90.5*
 :call	eval.txt	/*:call*
 :cat	eval.txt	/*:cat*
 :catch	eval.txt	/*:catch*
+:cb	quickfix.txt	/*:cb*
+:cbuffer	quickfix.txt	/*:cbuffer*
 :cc	quickfix.txt	/*:cc*
 :ccl	quickfix.txt	/*:ccl*
 :cclose	quickfix.txt	/*:cclose*
@@ -3559,6 +3563,7 @@ E678	pattern.txt	/*E678*
 E679	syntax.txt	/*E679*
 E68	pattern.txt	/*E68*
 E680	autocmd.txt	/*E680*
+E681	quickfix.txt	/*E681*
 E69	pattern.txt	/*E69*
 E70	pattern.txt	/*E70*
 E71	pattern.txt	/*E71*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2004 Dec 24
+*todo.txt*      For Vim version 7.0aa.  Last change: 2004 Dec 27
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,6 +30,16 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
+Python 2.4 breaks uploading with rsync, 2.3 is OK.
+
+-   Use a builtin grep command for ":grep"?  Makes it possible to add the
+    column number.
+    Patch from Yegappan Lakshmanan, Nov 4.
+Don't expand wildcards in pattern (first arg)
+completion for all files after first arg.
+Use a buffer to load the file, so that gzip files can be searched and long
+lines work.
+
 Patch for mch_FullName() also in Vim 6.3?  os_mswin.c
 
 Win32: "gvim -V100" should use dialog with scrollbar.  Using
@@ -50,25 +60,6 @@ Included NetBeans patches (Gordon Prieur
 
 PLANNED FOR VERSION 7.0:
 
--   Include many PATCHES:
-    -	VimResized	    - When the Vim window has been resized (SIGWINCH)
-	  patch from Yakov Lerner, 2003 July 24.
-    -	Patch for specifying an expression for numbered lists. (Hugo Haas,
-	2004 Aug 7)
-    -	Add the ":cbuffer" command: read list of errors from a buffer instead
-	of from a file. (Yegappan Lakshmanan, Oct 31, but avoid the temp file)
-	Perhaps ":cexpr" could read from a list?
-	Add %b to 'errorformat': buffer number. (Yegappan Lakshmanan / Suresh
-	Govindachar)
--   Use a builtin grep command for ":grep"?  Makes it possible to add the
-    column number.  Can use the code of ":helpgrep".
-    Patch from Yegappan Lakshmanan, Nov 4.  Or use ":grep" and set 'grepprg'
-    to something special?  Could also do both.
-    Also support using "**" in filename, so that a directory tree can be
-    searched.
-    Also see the "minigrep.vim" script on www.vim.org.
-
-
 -   Drop the kvim support?  There is no maintenance and "yzis" is supposed to
     replace it.
 -   In the kvim/KDE source files fix the formatting.
@@ -77,8 +68,6 @@ PLANNED FOR VERSION 7.0:
 -   KDE GUI Input method patch. (Yasuhiro Matsumoto) (upd. Oct 25 2004)
 
 After including patches:
--   Change ga_room into ga_maxlen, so that it doesn't need to be
-    incremented/decremented each time.
 -   For string variables, use length instead of NUL termination?
 	+ can include NUL characters
 	- setline() will have problems with NL vs NUL.
@@ -105,6 +94,8 @@ After including patches:
 -   Improve the interface between the generic GUI code and the system-specific
     code.  Generic code handles text window with scrollbars, system-specific
     code menu, toolbar, etc.
+-   Support using "**" in filename for ":next", ":vimgrep", etc., so that a
+    directory tree can be searched.
 -   Store messages to allow SCROLLING BACK for all commands.  And other "less"
     like commands.
 -   "INTELLISENSE".  First cleanup the Insert-mode completion.
@@ -180,6 +171,11 @@ 8   Support four composing/combining cha
     "foldcolumn". (Benji Fisher, 2004 Jun 21)
 -   FileChangedShellPost autocommand event: after (not) reloading a changed
     file.  Can be used to update statusline oslt.
+-   VimResized autocmd event: When the Vim window has been resized (SIGWINCH)
+    patch from Yakov Lerner, 2003 July 24.
+	It's not clear that this doesn't cause problems when the executed
+	commands do something like changing 'lines'.  Esp. because the 
+	screen has not yet been allocated with the new size.
 -   Running a shell command from the GUI still has limitations.  Look into how
     the Vim shell project can help: http://vimshell.wana.at
 8   When a file is change outside of Vim and unmodified in Vim there is no
@@ -3067,6 +3063,9 @@ 7   Make the debug mode history availabl
 Various improvements:
 8   Add ":rename" command: rename the file of the current buffer and rename
     the buffer.  Buffer may be modified.
+-   Perhaps ":cexpr" could read errors from a list?
+    Add %b to 'errorformat': buffer number. (Yegappan Lakshmanan / Suresh
+    Govindachar)
 6   In the quickfix window statusline add the command used to get the list of
     errors, e.g. ":make foo", ":grep something *.c".
 7   Add a ":cstring" command.  Works like ":cfile" but reads from a string
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -158,6 +158,9 @@ Options: ~
 'wildoptions'		"tagfile" value enables listing the file name of
 			matching tags for CTRL-D command line completion.
 			(based on an idea from Yegappan Lakshmanan)
+'formatlistpat'		pattern to recognize a numbered list for formatting.
+			(idea by Hugo Haas)
+
 
 Ex commands: ~
 
@@ -180,6 +183,8 @@ Win32: The ":winpos" command now also wo
 
 |:viusage|		Help for Vi commands (Nvi command).
 
+|:cbuffer|		Read error lines from a buffer. (partly by Yegappan
+			Lakshmanan)
 
 New functions: ~
 
@@ -354,6 +359,9 @@ in a Vim server to "utf-8", and using "v
 "fname" is converted from the console encoding to utf-8.  Also allows Vims
 with different 'encoding' settings to exchange messages.
 
+Internal: Changed ga_room into ga_maxlen, so that it doesn't need to be
+incremented/decremented each time.
+
 ==============================================================================
 COMPILE TIME CHANGES					*compile-changes-7*
 
@@ -582,4 +590,7 @@ message for the next buffer.  Temporaril
 Win32: Cannot edit a file starting with # with --remote.  Do escape % and #
 when building the ":drop" command.
 
+A comment or | just after a expresion-backtick argument was not recognized.
+E.g. in :e `="foo"`"comment.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -1,7 +1,7 @@
 " These commands create the option window.
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2004 Dec 20
+" Last Change:	2004 Dec 24
 
 " If there already is an option window, jump to that one.
 if bufwinnr("option-window") > 0
@@ -667,6 +667,9 @@ call <SID>OptionL("com")
 call append("$", "formatoptions\tlist of flags that tell how automatic formatting works")
 call append("$", "\t(local to buffer)")
 call <SID>OptionL("fo")
+call append("$", "formatlistpat\tpattern to recognize a numbered list")
+call append("$", "\t(local to buffer)")
+call <SID>OptionL("flp")
 if has("insert_expand")
   call append("$", "complete\tspecifies how Insert mode completion works")
   call append("$", "\t(local to buffer)")
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1699,6 +1699,7 @@ free_buf_options(buf, free_p_ff)
     clear_string_option(&buf->b_p_kp);
     clear_string_option(&buf->b_p_mps);
     clear_string_option(&buf->b_p_fo);
+    clear_string_option(&buf->b_p_flp);
     clear_string_option(&buf->b_p_isk);
 #ifdef FEAT_KEYMAP
     clear_string_option(&buf->b_p_keymap);
@@ -2541,6 +2542,28 @@ setfname(buf, ffname, sfname, message)
 }
 
 /*
+ * Crude way of changing the name of a buffer.  Use with care!
+ * The name should be relative to the current directory.
+ */
+    void
+buf_set_name(fnum, name)
+    int		fnum;
+    char_u	*name;
+{
+    buf_T	*buf;
+
+    buf = buflist_findnr(fnum);
+    if (buf != NULL)
+    {
+	vim_free(buf->b_sfname);
+	vim_free(buf->b_ffname);
+	buf->b_sfname = vim_strsave(name);
+	buf->b_ffname = FullName_save(buf->b_sfname, FALSE);
+	buf->b_fname = buf->b_sfname;
+    }
+}
+
+/*
  * Take care of what needs to be done when the name of buffer "buf" has
  * changed.
  */
--- a/src/charset.c
+++ b/src/charset.c
@@ -415,7 +415,6 @@ str_foldcase(str, len)
     mch_memmove(ga.ga_data, str, (size_t)len);
     GA_CHAR(len) = NUL;
     ga.ga_len = len;
-    ga.ga_room -= len;
 
     /* Make each character lower case. */
     i = 0;
@@ -451,7 +450,6 @@ str_foldcase(str, len)
 			    mch_memmove(GA_PTR(i) + nl, GA_PTR(i) + ol,
 						  STRLEN(GA_PTR(i) + ol) + 1);
 			    ga.ga_len += nl - ol;
-			    ga.ga_room -= nl - ol;
 			}
 		    }
 		    (void)utf_char2bytes(lc, GA_PTR(i));
--- a/src/digraph.c
+++ b/src/digraph.c
@@ -2230,7 +2230,6 @@ putdigraph(str)
 		dp->char2 = char2;
 		dp->result = n;
 		++user_digraphs.ga_len;
-		--user_digraphs.ga_room;
 	    }
 	}
     }
@@ -2450,10 +2449,7 @@ ex_loadkeymap(eap)
 		vim_free(kp->to);
 	    }
 	    else
-	    {
 		++curbuf->b_kmap_ga.ga_len;
-		--curbuf->b_kmap_ga.ga_room;
-	    }
 	}
 	vim_free(line);
     }
--- a/src/edit.c
+++ b/src/edit.c
@@ -2707,7 +2707,6 @@ expand_by_function(lnum, col, base, matc
 		    break;
 		((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(p, len);
 		++ga.ga_len;
-		--ga.ga_room;
 	    }
 	    if (*pnext != NUL)
 		++pnext;
--- a/src/eval.c
+++ b/src/eval.c
@@ -5972,7 +5972,6 @@ f_inputrestore(argvars, retvar)
     if (ga_userinput.ga_len > 0)
     {
 	--ga_userinput.ga_len;
-	++ga_userinput.ga_room;
 	restore_typeahead((tasave_T *)(ga_userinput.ga_data)
 						       + ga_userinput.ga_len);
 	retvar->var_val.var_number = 0; /* OK */
@@ -5999,7 +5998,6 @@ f_inputsave(argvars, retvar)
 	save_typeahead((tasave_T *)(ga_userinput.ga_data)
 						       + ga_userinput.ga_len);
 	++ga_userinput.ga_len;
-	--ga_userinput.ga_room;
 	retvar->var_val.var_number = 0; /* OK */
     }
     else
@@ -8092,7 +8090,6 @@ error:
 	    ga_grow(&ga, cplen);
 	    mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
 	    ga.ga_len += cplen;
-	    ga.ga_room -= cplen;
 
 	    instr += inlen;
 	}
@@ -9109,7 +9106,6 @@ new_script_vars(id)
 	{
 	    var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
 	    ++ga_scripts.ga_len;
-	    --ga_scripts.ga_room;
 	}
     }
 }
@@ -9269,10 +9265,7 @@ set_var(name, varp)
 	if ((v->var_name = vim_strsave(varname)) == NULL)
 	    return;
 	if (i == gap->ga_len)
-	{
 	    ++gap->ga_len;
-	    --gap->ga_room;
-	}
     }
     copy_var(varp, v);
 }
@@ -9441,12 +9434,8 @@ ex_execute(eap)
 		break;
 	    }
 	    if (ga.ga_len)
-	    {
 		((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
-		--ga.ga_room;
-	    }
 	    STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
-	    ga.ga_room -= len;
 	    ga.ga_len += len;
 	}
 
@@ -9675,7 +9664,6 @@ ex_function(eap)
 	    ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
 	    *p = c;
 	    newargs.ga_len++;
-	    newargs.ga_room--;
 	    if (*p == ',')
 		++p;
 	    else
@@ -9829,7 +9817,6 @@ ex_function(eap)
 	    goto erret;
 	((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
 	newlines.ga_len++;
-	newlines.ga_room--;
     }
 
     /* Don't define the function when skipping commands or when an error was
@@ -11398,7 +11385,6 @@ do_string_sub(str, pat, sub, flags)
 	    (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
 					  + ga.ga_len + i, TRUE, TRUE, FALSE);
 	    ga.ga_len += i + sublen - 1;
-	    ga.ga_room -= i + sublen - 1;
 	    /* avoid getting stuck on a match with an empty string */
 	    if (tail == regmatch.endp[0])
 	    {
@@ -11406,7 +11392,6 @@ do_string_sub(str, pat, sub, flags)
 		    break;
 		*((char_u *)ga.ga_data + ga.ga_len) = *tail++;
 		++ga.ga_len;
-		--ga.ga_room;
 	    }
 	    else
 	    {
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -5315,7 +5315,6 @@ ex_helptags(eap)
 		    break;
 		((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
 		((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
-		ga.ga_room -= 2;
 	    }
 	}
     }
@@ -5425,7 +5424,6 @@ helptags_one(dir, ext, tagfname)
 		sprintf((char *)s, "help-tags\t%s\t1\n", tagfname);
 		((char_u **)ga.ga_data)[ga.ga_len] = s;
 		++ga.ga_len;
-		--ga.ga_room;
 	    }
 	}
     }
@@ -5516,7 +5514,6 @@ helptags_one(dir, ext, tagfname)
 			}
 			((char_u **)ga.ga_data)[ga.ga_len] = s;
 			++ga.ga_len;
-			--ga.ga_room;
 			sprintf((char *)s, "%s\t%s", p1, fname);
 
 			/* find next '*' */
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -190,6 +190,8 @@ EX(CMD_call,		"call",		ex_call,
 			RANGE|NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
 EX(CMD_catch,		"catch",	ex_catch,
 			EXTRA|SBOXOK|CMDWIN),
+EX(CMD_cbuffer,		"cbuffer",	ex_cbuffer,
+			RANGE|NOTADR|WORD1|TRLBAR),
 EX(CMD_cc,		"cc",		ex_cc,
 			RANGE|NOTADR|COUNT|TRLBAR|BANG),
 EX(CMD_cclose,		"cclose",	ex_cclose,
@@ -838,6 +840,10 @@ EX(CMD_visual,		"visual",	ex_edit,
 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_view,		"view",		ex_edit,
 			BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_vimgrep,		"vimgrep",	ex_vimgrep,
+			EXTRA|TRLBAR|NEEDARG),
+EX(CMD_vimgrepadd,	"vimgrepadd",	ex_vimgrep,
+			EXTRA|TRLBAR|NEEDARG),
 EX(CMD_viusage,		"viusage",	ex_viusage,
 			TRLBAR),
 EX(CMD_vmap,		"vmap",		ex_map,
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -491,7 +491,6 @@ ex_breakadd(eap)
 	    if (bp->dbg_lnum == 0)	/* default line number is 1 */
 		bp->dbg_lnum = 1;
 	    BREAKP(dbg_breakp.ga_len++).dbg_nr = ++last_breakp;
-	    --dbg_breakp.ga_room;
 	    ++debug_tick;
 	}
     }
@@ -564,7 +563,6 @@ ex_breakdel(eap)
 	vim_free(BREAKP(todel).dbg_name);
 	vim_free(BREAKP(todel).dbg_prog);
 	--dbg_breakp.ga_len;
-	++dbg_breakp.ga_room;
 	if (todel < dbg_breakp.ga_len)
 	    mch_memmove(&BREAKP(todel), &BREAKP(todel + 1),
 		    (dbg_breakp.ga_len - todel) * sizeof(struct debuggy));
@@ -1063,6 +1061,31 @@ do_one_arg(str)
     return str;
 }
 
+/*
+ * Separate the arguments in "str" and return a list of pointers in the
+ * growarray "gap".
+ */
+    int
+get_arglist(gap, str)
+    garray_T	*gap;
+    char_u	*str;
+{
+    ga_init2(gap, (int)sizeof(char_u *), 20);
+    while (*str != NUL)
+    {
+	if (ga_grow(gap, 1) == FAIL)
+	{
+	    ga_clear(gap);
+	    return FAIL;
+	}
+	((char_u **)gap->ga_data)[gap->ga_len++] = str;
+
+	/* Isolate one argument, change it in-place, put a NUL after it. */
+	str = do_one_arg(str);
+    }
+    return OK;
+}
+
 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
 /*
  * Redefine the argument list.
@@ -1101,20 +1124,8 @@ do_arglist(str, what, after)
     /*
      * Collect all file name arguments in "new_ga".
      */
-    ga_init2(&new_ga, (int)sizeof(char_u *), 20);
-    while (*str)
-    {
-	if (ga_grow(&new_ga, 1) == FAIL)
-	{
-	    ga_clear(&new_ga);
-	    return FAIL;
-	}
-	((char_u **)new_ga.ga_data)[new_ga.ga_len++] = str;
-	--new_ga.ga_room;
-
-	/* Isolate one argument, change it in-place, put a NUL after it. */
-	str = do_one_arg(str);
-    }
+    if (get_arglist(&new_ga, str) == FAIL)
+	return FAIL;
 
 #ifdef FEAT_LISTCMDS
     if (what == AL_DEL)
@@ -1154,7 +1165,6 @@ do_arglist(str, what, after)
 		    mch_memmove(ARGLIST + match, ARGLIST + match + 1,
 			    (ARGCOUNT - match - 1) * sizeof(aentry_T));
 		    --ALIST(curwin)->al_ga.ga_len;
-		    ++ALIST(curwin)->al_ga.ga_room;
 		    if (curwin->w_arg_idx > match)
 			--curwin->w_arg_idx;
 		    --match;
@@ -1189,7 +1199,7 @@ do_arglist(str, what, after)
 	}
 	else /* what == AL_SET */
 #endif
-	    alist_set(ALIST(curwin), exp_count, exp_files, FALSE);
+	    alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
     }
 
     alist_check_arg_idx();
@@ -1342,7 +1352,6 @@ ex_args(eap)
 		    AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
 							  GARGLIST[i].ae_fnum;
 		    ++gap->ga_len;
-		    --gap->ga_room;
 		}
     }
 #endif
@@ -1579,7 +1588,6 @@ ex_argdelete(eap)
 	    mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
 			(size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
 	    ALIST(curwin)->al_ga.ga_len -= n;
-	    ALIST(curwin)->al_ga.ga_room += n;
 	    if (curwin->w_arg_idx >= eap->line2)
 		curwin->w_arg_idx -= n;
 	    else if (curwin->w_arg_idx > eap->line1)
@@ -1786,7 +1794,6 @@ alist_add_list(count, files, after)
 	    ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
 	}
 	ALIST(curwin)->al_ga.ga_len += count;
-	ALIST(curwin)->al_ga.ga_room -= count;
 	if (curwin->w_arg_idx >= after)
 	    ++curwin->w_arg_idx;
 	return after;
@@ -2365,7 +2372,6 @@ do_source(fname, check_other, is_vimrc)
 	    {
 		SCRIPT_NAME(script_names.ga_len + 1) = NULL;
 		++script_names.ga_len;
-		--script_names.ga_room;
 	    }
 	    SCRIPT_NAME(current_SID) = fname_exp;
 # ifdef UNIX
@@ -2674,12 +2680,14 @@ get_one_sourceline(sp)
 #ifdef USE_CR
 	if (sp->fileformat == EOL_MAC)
 	{
-	    if (fgets_cr((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL)
+	    if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
+							      sp->fp) == NULL)
 		break;
 	}
 	else
 #endif
-	    if (fgets((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL)
+	    if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
+							      sp->fp) == NULL)
 		break;
 	len = (int)STRLEN(buf);
 #ifdef USE_CRNL
@@ -2723,11 +2731,10 @@ get_one_sourceline(sp)
 #endif
 
 	have_read = TRUE;
-	ga.ga_room -= len - ga.ga_len;
 	ga.ga_len = len;
 
 	/* If the line was longer than the buffer, read more. */
-	if (ga.ga_room == 1 && buf[len - 1] != '\n')
+	if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
 	    continue;
 
 	if (len >= 1 && buf[len - 1] == '\n')	/* remove trailing NL */
@@ -2749,7 +2756,6 @@ get_one_sourceline(sp)
 		    buf[len - 2] = '\n';
 		    --len;
 		    --ga.ga_len;
-		    ++ga.ga_room;
 		}
 		else	    /* lines like ":map xx yy^M" will have failed */
 		{
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -112,12 +112,14 @@ static char_u	*skip_cmd_arg __ARGS((char
 static int	getargopt __ARGS((exarg_T *eap));
 #ifndef FEAT_QUICKFIX
 # define ex_make		ex_ni
+# define ex_cbuffer		ex_ni
 # define ex_cc			ex_ni
 # define ex_cnext		ex_ni
 # define ex_cfile		ex_ni
 # define qf_list		ex_ni
 # define qf_age			ex_ni
 # define ex_helpgrep		ex_ni
+# define ex_vimgrep		ex_ni
 #endif
 #if !defined(FEAT_QUICKFIX) || !defined(FEAT_WINDOWS)
 # define ex_cclose		ex_ni
@@ -1469,7 +1471,6 @@ store_while_line(gap, line)
     ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line);
     ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum;
     ++gap->ga_len;
-    --gap->ga_room;
     return OK;
 }
 
@@ -1484,7 +1485,6 @@ free_cmdlines(gap)
     {
 	vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
 	--gap->ga_len;
-	++gap->ga_room;
     }
 }
 #endif
@@ -2108,11 +2108,13 @@ do_one_cmd(cmdlinep, sourcing,
 
 #ifdef FEAT_QUICKFIX
     /*
-     * For the :make and :grep commands we insert the 'makeprg'/'grepprg'
+     * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
      * option here, so things like % get expanded.
+     * Don't do it when ":vimgrep" is used for ":grep".
      */
-    if (ea.cmdidx == CMD_make || ea.cmdidx == CMD_grep
-						  || ea.cmdidx == CMD_grepadd)
+    if ((ea.cmdidx == CMD_make
+			 || ea.cmdidx == CMD_grep || ea.cmdidx == CMD_grepadd)
+	    && !grep_internal(&ea))
     {
 	char_u		*new_cmdline;
 	char_u		*program;
@@ -4200,7 +4202,20 @@ separate_nextcmd(eap)
 {
     char_u	*p;
 
-    for (p = eap->arg; *p; ++p)
+    p = eap->arg;
+#ifdef FEAT_QUICKFIX
+    if (eap->cmdidx == CMD_vimgrep
+	    || eap->cmdidx == CMD_vimgrepadd
+	    || grep_internal(eap))
+    {
+	/* Skip over the pattern. */
+	p = skip_regexp(p + 1, *p, TRUE, NULL);
+	if (*p == *eap->arg)
+	    ++p;
+    }
+#endif
+
+    for ( ; *p; mb_ptr_adv(p))
     {
 	if (*p == Ctrl_V)
 	{
@@ -4218,8 +4233,6 @@ separate_nextcmd(eap)
 	{
 	    p += 2;
 	    (void)skip_expr(&p);
-	    if (*p == '`')
-		++p;
 	}
 #endif
 
@@ -4250,11 +4263,8 @@ separate_nextcmd(eap)
 		break;
 	    }
 	}
-#ifdef FEAT_MBYTE
-	else if (has_mbyte)
-	    p += (*mb_ptr2len_check)(p) - 1; /* skip bytes of multi-byte char */
-#endif
-    }
+    }
+
     if (!(eap->argt & NOTRLCOM))	/* remove trailing spaces */
 	del_trailing_spaces(eap->arg);
 }
@@ -4780,7 +4790,6 @@ uc_add_command(name, name_len, rep, argt
 	mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
 
 	++gap->ga_len;
-	--gap->ga_room;
 
 	cmd->uc_name = p;
     }
@@ -5292,7 +5301,6 @@ ex_delcommand(eap)
 # endif
 
     --gap->ga_len;
-    ++gap->ga_room;
 
     if (i < gap->ga_len)
 	mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
@@ -6171,7 +6179,7 @@ handle_drop(filec, filev, split)
     /*
      * Set up the new argument list.
      */
-    alist_set(ALIST(curwin), filec, filev, FALSE);
+    alist_set(ALIST(curwin), filec, filev, FALSE, NULL, 0);
 
     /*
      * Move to the first file.
@@ -6257,11 +6265,16 @@ alist_new()
 #if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) || defined(PROTO)
 /*
  * Expand the file names in the global argument list.
+ * If "fnum_list" is not NULL, use "fnum_list[fnum_len]" as a list of buffer
+ * numbers to be re-used.
  */
     void
-alist_expand()
+alist_expand(fnum_list, fnum_len)
+    int		*fnum_list;
+    int		fnum_len;
 {
     char_u	**old_arg_files;
+    int		old_arg_count;
     char_u	**new_arg_files;
     int		new_arg_file_count;
     char_u	*save_p_su = p_su;
@@ -6275,14 +6288,16 @@ alist_expand()
     if (old_arg_files != NULL)
     {
 	for (i = 0; i < GARGCOUNT; ++i)
-	    old_arg_files[i] = GARGLIST[i].ae_fname;
-	if (expand_wildcards(GARGCOUNT, old_arg_files,
+	    old_arg_files[i] = vim_strsave(GARGLIST[i].ae_fname);
+	old_arg_count = GARGCOUNT;
+	if (expand_wildcards(old_arg_count, old_arg_files,
 		    &new_arg_file_count, &new_arg_files,
 		    EW_FILE|EW_NOTFOUND|EW_ADDSLASH) == OK
 		&& new_arg_file_count > 0)
 	{
-	    alist_set(&global_alist, new_arg_file_count, new_arg_files, TRUE);
-	    vim_free(old_arg_files);
+	    alist_set(&global_alist, new_arg_file_count, new_arg_files,
+						   TRUE, fnum_list, fnum_len);
+	    FreeWild(old_arg_count, old_arg_files);
 	}
     }
     p_su = save_p_su;
@@ -6294,11 +6309,13 @@ alist_expand()
  * Takes over the allocated files[] and the allocated fnames in it.
  */
     void
-alist_set(al, count, files, use_curbuf)
+alist_set(al, count, files, use_curbuf, fnum_list, fnum_len)
     alist_T	*al;
     int		count;
     char_u	**files;
     int		use_curbuf;
+    int		*fnum_list;
+    int		fnum_len;
 {
     int		i;
 
@@ -6315,6 +6332,12 @@ alist_set(al, count, files, use_curbuf)
 		    vim_free(files[i++]);
 		break;
 	    }
+
+	    /* May set buffer name of a buffer previously used for the
+	     * argument list, so that it's re-used by alist_add. */
+	    if (fnum_list != NULL && i < fnum_len)
+		buf_set_name(fnum_list[i], files[i]);
+
 	    alist_add(al, files[i], use_curbuf ? 2 : 1);
 	    ui_breakcheck();
 	}
@@ -6348,7 +6371,6 @@ alist_add(al, fname, set_fnum)
 	AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
 	    buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0));
     ++al->al_ga.ga_len;
-    --al->al_ga.ga_room;
 }
 
 #if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1964,7 +1964,6 @@ getexmodeline(c, dummy, indent)
 			    char_u	*q;
 
 			    --line_ga.ga_len;
-			    ++line_ga.ga_room;
 			    /* compute column that cursor should be in */
 			    v = 0;
 			    q = ((char_u *)line_ga.ga_data);
@@ -1992,7 +1991,6 @@ getexmodeline(c, dummy, indent)
 		    {
 			msg_col = startcol;
 			msg_clr_eos();
-			line_ga.ga_room += line_ga.ga_len;
 			line_ga.ga_len = 0;
 			continue;
 		    }
@@ -2024,7 +2022,6 @@ getexmodeline(c, dummy, indent)
 		    vcol += char2cells(c1);
 		}
 		++line_ga.ga_len;
-		--line_ga.ga_room;
 		escaped = FALSE;
 	    }
 	    windgoto(msg_row, msg_col);
@@ -2036,7 +2033,6 @@ getexmodeline(c, dummy, indent)
 #ifndef NO_COOKED_INPUT
 	{
 	    line_ga.ga_len += len;
-	    line_ga.ga_room -= len;
 	}
 #endif
 	p = (char_u *)(line_ga.ga_data) + line_ga.ga_len;
@@ -4122,7 +4118,6 @@ ExpandUserDefined(xp, regmatch, num_file
 
 	((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, (int)(e - s));
 	++ga.ga_len;
-	--ga.ga_room;
 
 	*e = keep;
 	if (*e != NUL)
@@ -4179,7 +4174,6 @@ ExpandRTDir(pat, num_file, file, dirname
 	    ((char_u **)ga.ga_data)[ga.ga_len] =
 					    vim_strnsave(s, (int)(e - s - 4));
 	    ++ga.ga_len;
-	    --ga.ga_room;
 	}
 	if (*e != NUL)
 	    ++e;
@@ -4247,7 +4241,6 @@ globpath(path, file)
 			*cur++ = '\n';
 		    }
 		    ga.ga_len += len;
-		    ga.ga_room -= len;
 		}
 		FreeWild(num_p, p);
 	    }
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6933,10 +6933,7 @@ au_new_group(name)
 	if (AUGROUP_NAME(i) == NULL)
 	    return AUGROUP_ERROR;
 	if (i == augroups.ga_len)
-	{
 	    ++augroups.ga_len;
-	    --augroups.ga_room;
-	}
     }
 
     return i;
--- a/src/fold.c
+++ b/src/fold.c
@@ -689,7 +689,6 @@ foldCreate(start, end)
 	    /* Move contained folds to inside new fold. */
 	    mch_memmove(fold_ga.ga_data, fp, sizeof(fold_T) * cont);
 	    fold_ga.ga_len += cont;
-	    fold_ga.ga_room -= cont;
 	    i += cont;
 
 	    /* Adjust line numbers in contained folds to be relative to the
@@ -702,7 +701,6 @@ foldCreate(start, end)
 	    mch_memmove(fp + 1, (fold_T *)gap->ga_data + i,
 				     sizeof(fold_T) * (gap->ga_len - i));
 	gap->ga_len = gap->ga_len + 1 - cont;
-	gap->ga_room = gap->ga_room - 1 + cont;
 
 	/* insert new fold */
 	fp->fd_nested = fold_ga;
@@ -1136,7 +1134,6 @@ cloneFoldGrowArray(from, to)
 	to_p->fd_small = from_p->fd_small;
 	cloneFoldGrowArray(&from_p->fd_nested, &to_p->fd_nested);
 	++to->ga_len;
-	--to->ga_room;
 	++from_p;
 	++to_p;
     }
@@ -1455,7 +1452,6 @@ deleteFoldEntry(gap, idx, recursive)
 	/* recursively delete the contained folds */
 	deleteFoldRecurse(&fp->fd_nested);
 	--gap->ga_len;
-	++gap->ga_room;
 	if (idx < gap->ga_len)
 	    mch_memmove(fp, fp + 1, sizeof(fold_T) * (gap->ga_len - idx));
     }
@@ -1485,7 +1481,6 @@ deleteFoldEntry(gap, idx, recursive)
 	    mch_memmove(fp, nfp, (size_t)(sizeof(fold_T) * moved));
 	    vim_free(nfp);
 	    gap->ga_len += moved - 1;
-	    gap->ga_room -= moved - 1;
 	}
     }
 }
@@ -2762,7 +2757,6 @@ foldInsert(gap, i)
     if (i < gap->ga_len)
 	mch_memmove(fp + 1, fp, sizeof(fold_T) * (gap->ga_len - i));
     ++gap->ga_len;
-    --gap->ga_room;
     ga_init2(&fp->fd_nested, (int)sizeof(fold_T), 10);
     return OK;
 }
@@ -2812,9 +2806,7 @@ foldSplit(gap, i, top, bot)
 						 -= fp[1].fd_top - fp->fd_top;
 	}
 	gap2->ga_len = len;
-	gap2->ga_room -= len;
 	gap1->ga_len -= len;
-	gap1->ga_room += len;
     }
     fp->fd_len = top - fp->fd_top;
     fold_changed = TRUE;
@@ -2931,10 +2923,8 @@ foldMerge(fp1, gap, fp2)
 					= ((fold_T *)gap2->ga_data)[idx];
 	    ((fold_T *)gap1->ga_data)[gap1->ga_len].fd_top += fp1->fd_len;
 	    ++gap1->ga_len;
-	    --gap1->ga_room;
 	}
 	gap2->ga_len = 0;
-	/* fp2->fd_nested.ga_room isn't updated, we delete it below */
     }
 
     fp1->fd_len += fp2->fd_len;
--- a/src/gui_gtk.c
+++ b/src/gui_gtk.c
@@ -1348,6 +1348,8 @@ gui_mch_browse(int saving,
     return vim_strsave(p);
 }
 
+#if defined(HAVE_GTK2) || defined(PROTO)
+
 /*
  * Put up a directory selector
  * Returns the selected name in allocated memory, or NULL for Cancel.
@@ -1416,6 +1418,7 @@ gui_mch_browsedir(
     return gui_mch_browse(0, title, NULL, NULL, initdir, NULL);
 # endif
 }
+#endif
 
 #endif	/* FEAT_BROWSE */
 
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -735,7 +735,6 @@ ServerReplyFind(w, op)
 	    ga_init2(&e.strings, 1, 100);
 	    memcpy(p, &e, sizeof(e));
 	    serverReply.ga_len++;
-	    serverReply.ga_room--;
 	}
     }
     else if (p != NULL && op == SROP_Delete)
@@ -743,7 +742,6 @@ ServerReplyFind(w, op)
 	ga_clear(&p->strings);
 	mch_memmove(p, p + 1, (serverReply.ga_len - i - 1) * sizeof(*p));
 	serverReply.ga_len--;
-	serverReply.ga_room++;
     }
 
     return p;
@@ -844,7 +842,6 @@ serverReadReply(dpy, win, str, localLoop
 	{
 	    s = (char_u *) p->strings.ga_data;
 	    mch_memmove(s, s + len, p->strings.ga_len - len);
-	    p->strings.ga_room += len;
 	    p->strings.ga_len -= len;
 	}
 	else
@@ -1276,7 +1273,6 @@ serverEventProc(dpy, eventPtr)
 		sprintf(reply.ga_data, "%cr%c-s %s%c-r ", 0, 0, serial, 0);
 #endif
 		reply.ga_len = 10 + STRLEN(serial);
-		reply.ga_room -= reply.ga_len;
 	    }
 	    res = NULL;
 	    if (serverName != NULL && STRICMP(name, serverName) == 0)
--- a/src/main.c
+++ b/src/main.c
@@ -1137,7 +1137,7 @@ scripterror:
 	     * filename characters but are excluded from 'isfname' to make
 	     * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
 	    do_cmdline_cmd((char_u *)":set isf+=(,)");
-	    alist_expand();
+	    alist_expand(NULL, 0);
 	    do_cmdline_cmd((char_u *)":set isf&");
 	}
 #endif
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -692,11 +692,7 @@ codepage_invalid:
     /* When changing 'encoding' while starting up, then convert the command
      * line arguments from the active codepage to 'encoding'. */
     if (starting != 0)
-    {
-	extern void fix_arg_enc(void);
-
 	fix_arg_enc();
-    }
 #endif
 
 #ifdef FEAT_AUTOCMD
--- a/src/menu.c
+++ b/src/menu.c
@@ -2306,7 +2306,6 @@ ex_menutranslate(eap)
 		    tp[menutrans_ga.ga_len].from_noamp = from_noamp;
 		    tp[menutrans_ga.ga_len].to = to;
 		    ++menutrans_ga.ga_len;
-		    --menutrans_ga.ga_room;
 		}
 		else
 		{
--- a/src/message.c
+++ b/src/message.c
@@ -2275,7 +2275,6 @@ mch_errmsg(str)
 #endif
 	--len;		/* don't count the NUL at the end */
 	error_ga.ga_len += len;
-	error_ga.ga_room -= len;
     }
 }
 
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -382,30 +382,36 @@ copy_indent(size, src)
 /*
  * Return the indent of the current line after a number.  Return -1 if no
  * number was found.  Used for 'n' in 'formatoptions': numbered list.
+ * Since a pattern is used it can actually handle more than numbers.
  */
     int
 get_number_indent(lnum)
     linenr_T	lnum;
 {
-    char_u	*line;
-    char_u	*p;
     colnr_T	col;
     pos_T	pos;
+    regmmatch_T	regmatch;
 
     if (lnum > curbuf->b_ml.ml_line_count)
 	return -1;
-    line = ml_get(lnum);
-    p = skipwhite(line);
-    if (!VIM_ISDIGIT(*p))
+    pos.lnum = 0;
+    regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
+    if (regmatch.regprog != NULL)
+    {
+	regmatch.rmm_ic = FALSE;
+	if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0))
+	{
+	    pos.lnum = regmatch.endpos[0].lnum + lnum;
+	    pos.col = regmatch.endpos[0].col;
+#ifdef FEAT_VIRTUALEDIT
+	    pos.coladd = 0;
+#endif
+	}
+	vim_free(regmatch.regprog);
+    }
+
+    if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
 	return -1;
-    p = skipdigits(p);
-    if (vim_strchr((char_u *)":.)]}\t ", *p) == NULL)
-	return -1;
-    p = skipwhite(p + 1);
-    if (*p == NUL)
-	return -1;
-    pos.lnum = lnum;
-    pos.col = (colnr_T)(p - line);
     getvcol(curwin, &pos, &col, NULL, NULL);
     return (int)col;
 }
@@ -3804,9 +3810,9 @@ remove_tail_with_ext(p, pend, ext)
     char_u	*newend = pend - len;
 
     if (newend >= p && fnamencmp(newend, ext, len - 1) == 0)
-	while (newend != p && !after_pathsep(newend))
-	    mb_ptr_back(newend);
-    if (newend == p || after_pathsep(newend))
+	while (newend > p && !after_pathsep(p, newend))
+	    mb_ptr_back(p, newend);
+    if (newend == p || after_pathsep(p, newend))
 	return newend;
     return pend;
 }
@@ -8447,7 +8453,6 @@ addfile(gap, f, flags)
 	add_pathsep(p);
 #endif
     ((char_u **)gap->ga_data)[gap->ga_len++] = p;
-    --gap->ga_room;
 }
 #endif /* !NO_EXPANDPATH */
 
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1525,7 +1525,7 @@ ga_init(gap)
     garray_T *gap;
 {
     gap->ga_data = NULL;
-    gap->ga_room = 0;
+    gap->ga_maxlen = 0;
     gap->ga_len = 0;
 }
 
@@ -1552,7 +1552,7 @@ ga_grow(gap, n)
     size_t	len;
     char_u	*pp;
 
-    if (gap->ga_room < n)
+    if (gap->ga_maxlen - gap->ga_len < n)
     {
 	if (n < gap->ga_growsize)
 	    n = gap->ga_growsize;
@@ -1560,7 +1560,7 @@ ga_grow(gap, n)
 	pp = alloc_clear((unsigned)len);
 	if (pp == NULL)
 	    return FAIL;
-	gap->ga_room = n;
+	gap->ga_maxlen = gap->ga_len + n;
 	if (gap->ga_data != NULL)
 	{
 	    mch_memmove(pp, gap->ga_data,
@@ -1587,7 +1587,6 @@ ga_concat(gap, s)
     {
 	mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
 	gap->ga_len += len;
-	gap->ga_room -= len;
     }
 }
 
@@ -1603,7 +1602,6 @@ ga_append(gap, c)
     {
 	*((char *)gap->ga_data + gap->ga_len) = c;
 	++gap->ga_len;
-	--gap->ga_room;
     }
 }
 
@@ -5224,7 +5222,7 @@ pathcmp(p, q, maxlen)
     int maxlen;
 {
     int		i;
-    const char	*s;
+    const char	*s = NULL;
 
     for (i = 0; maxlen < 0 || i < maxlen; ++i)
     {
@@ -5264,18 +5262,19 @@ pathcmp(p, q, maxlen)
 	    return ((char_u *)p)[i] - ((char_u *)q)[i];	    /* no match */
 	}
     }
+    if (s == NULL)	/* "i" ran into "maxlen" */
+	return 0;
 
     /* ignore a trailing slash, but not "//" or ":/" */
-    if (i >= maxlen
-	    || (s[i + 1] == NUL
-		&& i > 0
-		&& !after_pathsep((char_u *)s, (char_u *)s + i)
+    if (s[i + 1] == NUL
+	    && i > 0
+	    && !after_pathsep((char_u *)s, (char_u *)s + i)
 #ifdef BACKSLASH_IN_FILENAME
-		&& (s[i] == '/' || s[i] == '\\')
+	    && (s[i] == '/' || s[i] == '\\')
 #else
-		&& s[i] == '/'
+	    && s[i] == '/'
 #endif
-	       ))
+       )
 	return 0;   /* match with trailing slash */
     if (s == q)
 	return -1;	    /* no match */
--- a/src/option.c
+++ b/src/option.c
@@ -82,6 +82,7 @@ typedef enum
     , PV_FF
     , PV_FML
     , PV_FMR
+    , PV_FLP
     , PV_FO
     , PV_FT
     , PV_GP
@@ -183,6 +184,7 @@ static char_u	*p_fenc;
 #endif
 static char_u	*p_ff;
 static char_u	*p_fo;
+static char_u	*p_flp;
 #ifdef FEAT_AUTOCMD
 static char_u	*p_ft;
 #endif
@@ -952,6 +954,9 @@ static struct vimoption
     {"formatoptions","fo",  P_STRING|P_ALLOCED|P_VIM|P_FLAGLIST,
 			    (char_u *)&p_fo, PV_FO,
 			    {(char_u *)DFLT_FO_VI, (char_u *)DFLT_FO_VIM}},
+    {"formatlistpat","flp", P_STRING|P_ALLOCED|P_VI_DEF,
+			    (char_u *)&p_flp, PV_FLP,
+			    {(char_u *)"^\\s*\\d\\+[\\]:.)}\\t ]\\s*", (char_u *)0L}},
     {"formatprg",   "fp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 			    (char_u *)&p_fp, PV_NONE,
 			    {(char_u *)"", (char_u *)0L}},
@@ -2636,7 +2641,6 @@ set_init_1()
 		    STRCAT(ga.ga_data, p);
 		    add_pathsep(ga.ga_data);
 		    STRCAT(ga.ga_data, "*");
-		    ga.ga_room -= len;
 		    ga.ga_len += len;
 		}
 	    }
@@ -4487,6 +4491,7 @@ check_buf_options(buf)
     check_string_option(&buf->b_p_kp);
     check_string_option(&buf->b_p_mps);
     check_string_option(&buf->b_p_fo);
+    check_string_option(&buf->b_p_flp);
     check_string_option(&buf->b_p_isk);
 #ifdef FEAT_COMMENTS
     check_string_option(&buf->b_p_com);
@@ -8082,6 +8087,7 @@ get_varp(p)
 	case PV_FT:	return (char_u *)&(curbuf->b_p_ft);
 #endif
 	case PV_FO:	return (char_u *)&(curbuf->b_p_fo);
+	case PV_FLP:	return (char_u *)&(curbuf->b_p_flp);
 	case PV_IMI:	return (char_u *)&(curbuf->b_p_iminsert);
 	case PV_IMS:	return (char_u *)&(curbuf->b_p_imsearch);
 	case PV_INF:	return (char_u *)&(curbuf->b_p_inf);
@@ -8404,6 +8410,7 @@ buf_copy_options(buf, flags)
 	    buf->b_p_cms = vim_strsave(p_cms);
 #endif
 	    buf->b_p_fo = vim_strsave(p_fo);
+	    buf->b_p_flp = vim_strsave(p_flp);
 	    buf->b_p_nf = vim_strsave(p_nf);
 	    buf->b_p_mps = vim_strsave(p_mps);
 #ifdef FEAT_SMARTINDENT
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -2908,7 +2908,6 @@ static garray_T reply_list = {0, 0, size
 
 #define REPLY_ITEM(i) ((reply_T *)(reply_list.ga_data) + (i))
 #define REPLY_COUNT (reply_list.ga_len)
-#define REPLY_ROOM (reply_list.ga_room)
 
 /* Flag which is used to wait for a reply */
 static int reply_received = 0;
@@ -2932,7 +2931,6 @@ save_reply(HWND server, char_u *reply, i
 	return FAIL;
 
     ++REPLY_COUNT;
-    --REPLY_ROOM;
     reply_received = 1;
     return OK;
 }
@@ -2976,7 +2974,6 @@ serverGetReply(HWND server, int *expr_re
 		    mch_memmove(rep, rep + 1,
 				     (REPLY_COUNT - i - 1) * sizeof(reply_T));
 		    --REPLY_COUNT;
-		    ++REPLY_ROOM;
 		}
 
 		/* Return the reply to the caller, who takes on responsibility
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -4988,6 +4988,7 @@ fix_arg_enc(void)
     int		i;
     int		idx;
     char_u	*str;
+    int		*fnum_list;
 
     /* Safety checks:
      * - if argument count differs between the wide and non-wide argument
@@ -5002,17 +5003,31 @@ fix_arg_enc(void)
 	    || used_alist_count != GARGCOUNT)
 	return;
 
+    /* Remember the buffer numbers for the arguments. */
+    fnum_list = (int *)alloc((int)sizeof(int) * GARGCOUNT);
+    if (fnum_list == NULL)
+	return;		/* out of memory */
+    for (i = 0; i < GARGCOUNT; ++i)
+	fnum_list[i] = GARGLIST[i].ae_fnum;
+
     /* Clear the argument list.  Make room for the new arguments. */
     alist_clear(&global_alist);
     if (ga_grow(&global_alist.al_ga, used_file_count) == FAIL)
-	return;	    /* out of memory */
+	return;		/* out of memory */
 
     for (i = 0; i < used_file_count; ++i)
     {
 	idx = used_file_indexes[i];
 	str = ucs2_to_enc(ArglistW[idx], NULL);
 	if (str != NULL)
+	{
+	    /* Re-use the old buffer by renaming it.  When not using literal
+	     * names it's done by alist_expand() below. */
+	    if (used_file_literal)
+		buf_set_name(fnum_list[i], str);
+
 	    alist_add(&global_alist, str, used_file_literal ? 2 : 0);
+	}
     }
 
     if (!used_file_literal)
@@ -5022,7 +5037,7 @@ fix_arg_enc(void)
 	 * filename characters but are excluded from 'isfname' to make
 	 * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
 	do_cmdline_cmd((char_u *)":let SaVe_ISF = &isf|set isf+=(,)");
-	alist_expand();
+	alist_expand(fnum_list, used_alist_count);
 	do_cmdline_cmd((char_u *)":let &isf = SaVe_ISF|unlet SaVe_ISF");
     }
 
@@ -5034,5 +5049,7 @@ fix_arg_enc(void)
 	if (GARGCOUNT == 1 && used_file_full_path)
 	    (void)vim_chdirfile(alist_name(&GARGLIST[0]));
     }
+
+    set_alist_count();
 }
 #endif
--- a/src/proto/buffer.pro
+++ b/src/proto/buffer.pro
@@ -25,6 +25,7 @@ linenr_T buflist_findlnum __ARGS((buf_T 
 void buflist_list __ARGS((exarg_T *eap));
 int buflist_name_nr __ARGS((int fnum, char_u **fname, linenr_T *lnum));
 int setfname __ARGS((buf_T *buf, char_u *ffname, char_u *sfname, int message));
+void buf_set_name __ARGS((int fnum, char_u *name));
 void buf_name_changed __ARGS((buf_T *buf));
 buf_T *setaltfname __ARGS((char_u *ffname, char_u *sfname, linenr_T lnum));
 char_u *getaltfname __ARGS((int errmsg));
--- a/src/proto/ex_cmds2.pro
+++ b/src/proto/ex_cmds2.pro
@@ -18,6 +18,7 @@ int can_abandon __ARGS((buf_T *buf, int 
 int check_changed_any __ARGS((int hidden));
 int check_fname __ARGS((void));
 int buf_write_all __ARGS((buf_T *buf, int forceit));
+int get_arglist __ARGS((garray_T *gap, char_u *str));
 void set_arglist __ARGS((char_u *str));
 void check_arg_idx __ARGS((win_T *win));
 void ex_args __ARGS((exarg_T *eap));
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -25,8 +25,8 @@ void alist_clear __ARGS((alist_T *al));
 void alist_init __ARGS((alist_T *al));
 void alist_unlink __ARGS((alist_T *al));
 void alist_new __ARGS((void));
-void alist_expand __ARGS((void));
-void alist_set __ARGS((alist_T *al, int count, char_u **files, int use_curbuf));
+void alist_expand __ARGS((int *fnum_list, int fnum_len));
+void alist_set __ARGS((alist_T *al, int count, char_u **files, int use_curbuf, int *fnum_list, int fnum_len));
 void alist_add __ARGS((alist_T *al, char_u *fname, int set_fnum));
 void alist_slash_adjust __ARGS((void));
 void ex_splitview __ARGS((exarg_T *eap));
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -13,9 +13,12 @@ int bt_nofile __ARGS((buf_T *buf));
 int bt_dontwrite __ARGS((buf_T *buf));
 int bt_dontwrite_msg __ARGS((buf_T *buf));
 int buf_hide __ARGS((buf_T *buf));
+int grep_internal __ARGS((exarg_T *eap));
 void ex_make __ARGS((exarg_T *eap));
 void ex_cc __ARGS((exarg_T *eap));
 void ex_cnext __ARGS((exarg_T *eap));
 void ex_cfile __ARGS((exarg_T *eap));
+void ex_vimgrep __ARGS((exarg_T *eap));
+void ex_cbuffer __ARGS((exarg_T *eap));
 void ex_helpgrep __ARGS((exarg_T *eap));
 /* vim: set ft=c : */
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -86,6 +86,7 @@ struct eformat
 				/*   '-' do not include this line */
 };
 
+static int qf_init_ext __ARGS((char_u *efile, buf_T *buf, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast));
 static void	qf_new_list __ARGS((void));
 static int	qf_add_entry __ARGS((struct qf_line **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int virt_col, int nr, int type, int valid));
 static void	qf_msg __ARGS((void));
@@ -106,7 +107,8 @@ static void	qf_fill_buffer __ARGS((void)
 static char_u	*get_mef_name __ARGS((void));
 
 /*
- * Read the errorfile into memory, line by line, building the error list.
+ * Read the errorfile "efile" into memory, line by line, building the error
+ * list.
  * Return -1 for error, number of errors for success.
  */
     int
@@ -115,6 +117,29 @@ qf_init(efile, errorformat, newlist)
     char_u	    *errorformat;
     int		    newlist;		/* TRUE: start a new error list */
 {
+    if (efile == NULL)
+	return FAIL;
+    return qf_init_ext(efile, curbuf, errorformat, newlist,
+						    (linenr_T)0, (linenr_T)0);
+}
+
+/*
+ * Read the errorfile "efile" into memory, line by line, building the error
+ * list.
+ * Alternative: when "efile" is null read errors from buffer "buf".
+ * Always use 'errorformat' from "buf" if there is a local value.
+ * Then lnumfirst and lnumlast specify the range of lines to use.
+ * Return -1 for error, number of errors for success.
+ */
+    static int
+qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
+    char_u	    *efile;
+    buf_T	    *buf;
+    char_u	    *errorformat;
+    int		    newlist;		/* TRUE: start a new error list */
+    linenr_T	    lnumfirst;		/* first line number to use */
+    linenr_T	    lnumlast;		/* last line number to use */
+{
     char_u	    *namebuf;
     char_u	    *errmsg;
     char_u	    *fmtstr = NULL;
@@ -122,9 +147,10 @@ qf_init(efile, errorformat, newlist)
     char_u	    use_virt_col = FALSE;
     int		    type = 0;
     int		    valid;
+    linenr_T	    buflnum = lnumfirst;
     long	    lnum = 0L;
     int		    enr = 0;
-    FILE	    *fd;
+    FILE	    *fd = NULL;
     struct qf_line  *qfprev = NULL;	/* init to make SASC shut up */
     char_u	    *efmp;
     struct eformat  *fmt_first = NULL;
@@ -163,15 +189,12 @@ qf_init(efile, errorformat, newlist)
 			{'v', "\\d\\+"}
 		    };
 
-    if (efile == NULL)
-	return FAIL;
-
     namebuf = alloc(CMDBUFFSIZE + 1);
     errmsg = alloc(CMDBUFFSIZE + 1);
     if (namebuf == NULL || errmsg == NULL)
 	goto qf_init_end;
 
-    if ((fd = mch_fopen((char *)efile, "r")) == NULL)
+    if (efile != NULL && (fd = mch_fopen((char *)efile, "r")) == NULL)
     {
 	EMSG2(_(e_openerrf), efile);
 	goto qf_init_end;
@@ -191,8 +214,8 @@ qf_init(efile, errorformat, newlist)
  * regex prog.  Only a few % characters are allowed.
  */
     /* Use the local value of 'errorformat' if it's set. */
-    if (errorformat == p_efm && *curbuf->b_p_efm != NUL)
-	efm = curbuf->b_p_efm;
+    if (errorformat == p_efm && *buf->b_p_efm != NUL)
+	efm = buf->b_p_efm;
     else
 	efm = errorformat;
     /*
@@ -405,8 +428,18 @@ qf_init(efile, errorformat, newlist)
      * Read the lines in the error file one by one.
      * Try to recognize one of the error formats in each line.
      */
-    while (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) != NULL && !got_int)
+    while (!got_int)
     {
+	/* Get the next line. */
+	if (fd == NULL)
+	{
+	    if (buflnum > lnumlast)
+		break;
+	    STRNCPY(IObuff, ml_get_buf(buf, buflnum++, FALSE), CMDBUFFSIZE - 2);
+	}
+	else if (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) == NULL)
+	    break;
+
 	IObuff[CMDBUFFSIZE - 2] = NUL;  /* for very long lines */
 	if ((efmp = vim_strrchr(IObuff, '\n')) != NULL)
 	    *efmp = NUL;
@@ -594,7 +627,7 @@ restofline:
 	    goto error2;
 	line_breakcheck();
     }
-    if (!ferror(fd))
+    if (fd == NULL || !ferror(fd))
     {
 	if (qf_lists[qf_curlist].qf_index == 0)	/* no valid entry found */
 	{
@@ -618,7 +651,8 @@ error2:
     if (qf_curlist > 0)
 	--qf_curlist;
 qf_init_ok:
-    fclose(fd);
+    if (fd != NULL)
+	fclose(fd);
     for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_first)
     {
 	fmt_first = fmt_ptr->next;
@@ -2026,6 +2060,18 @@ buf_hide(buf)
 }
 
 /*
+ * Return TRUE when using ":vimgrep" for ":grep".
+ */
+    int
+grep_internal(eap)
+    exarg_T	*eap;
+{
+    return ((eap->cmdidx == CMD_grep || eap->cmdidx == CMD_grepadd)
+	    && STRCMP("internal",
+			*curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0);
+}
+
+/*
  * Used for ":make", ":grep" and ":grepadd".
  */
     void
@@ -2036,6 +2082,13 @@ ex_make(eap)
     char_u	*cmd;
     unsigned	len;
 
+    /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */
+    if (grep_internal(eap))
+    {
+	ex_vimgrep(eap);
+	return;
+    }
+
     autowrite_all();
     name = get_mef_name();
     if (name == NULL)
@@ -2075,7 +2128,7 @@ ex_make(eap)
 #endif
 
     if (qf_init(name, eap->cmdidx != CMD_make ? p_gefm : p_efm,
-					      eap->cmdidx != CMD_grepadd) > 0
+					       eap->cmdidx != CMD_grepadd) > 0
 	    && !eap->forceit)
 	qf_jump(0, 0, FALSE);		/* display first error */
 
@@ -2190,6 +2243,171 @@ ex_cfile(eap)
 }
 
 /*
+ * ":vimgrep {pattern} file(s)"
+ */
+    void
+ex_vimgrep(eap)
+    exarg_T	*eap;
+{
+    regmatch_T	regmatch;
+    char_u	*save_cpo;
+    int         fcount;
+    char_u	**fnames;
+    char_u      *p;
+    int		i;
+    FILE	*fd;
+    int         fi;
+    struct qf_line *prevp = NULL;
+    long	lnum;
+    garray_T	ga;
+
+    /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
+    save_cpo = p_cpo;
+    p_cpo = empty_option;
+
+    /* Get the search pattern */
+    regmatch.regprog = NULL;
+    p = skip_regexp(eap->arg + 1, *eap->arg, TRUE, NULL);
+    if (*p != *eap->arg)
+    {
+	EMSG(_("E682: Invalid search pattern or delimiter"));
+	goto theend;
+    }
+    *p++ = NUL;
+    regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
+    if (regmatch.regprog == NULL)
+	goto theend;
+    regmatch.rm_ic = FALSE;
+
+    p = skipwhite(p);
+    if (*p == NUL)
+    {
+	EMSG(_("E683: File name missing or invalid pattern"));
+	goto theend;
+    }
+
+    if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_vimgrepadd)
+						|| qf_curlist == qf_listcount)
+	/* make place for a new list */
+	qf_new_list();
+    else if (qf_lists[qf_curlist].qf_count > 0)
+	/* Adding to existing list, find last entry. */
+	for (prevp = qf_lists[qf_curlist].qf_start;
+			    prevp->qf_next != prevp; prevp = prevp->qf_next)
+	    ;
+
+    /* parse the list of arguments */
+    if (get_arglist(&ga, p) == FAIL)
+	goto theend;
+    i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
+				       &fcount, &fnames, EW_FILE|EW_NOTFOUND);
+    ga_clear(&ga);
+    if (i == FAIL)
+	goto theend;
+    if (fcount == 0)
+    {
+	EMSG(_(e_nomatch));
+	goto theend;
+    }
+
+    for (fi = 0; fi < fcount && !got_int; ++fi)
+    {
+	fd = fopen((char *)fnames[fi], "r");
+	if (fd == NULL)
+	    smsg((char_u *)_("Cannot open file \"%s\""), fnames[fi]);
+	else
+	{
+	    lnum = 1;
+	    while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
+	    {
+		if (vim_regexec(&regmatch, IObuff, (colnr_T)0))
+		{
+		    int     l = STRLEN(IObuff);
+
+		    /* remove trailing CR, LF, spaces, etc. */
+		    while (l > 0 && IObuff[l - 1] <= ' ')
+			IObuff[--l] = NUL;
+
+		    if (qf_add_entry(&prevp,
+				NULL,       /* dir */
+				fnames[fi],
+				IObuff,
+				lnum,
+				(int)(regmatch.startp[0] - IObuff) + 1,/* col */
+				FALSE,      /* virt_col */
+				0,          /* nr */
+				0,          /* type */
+				TRUE        /* valid */
+				) == FAIL)
+		    {
+			got_int = TRUE;
+			break;
+		    }
+		}
+		++lnum;
+		line_breakcheck();
+	    }
+	    fclose(fd);
+	}
+    }
+
+    FreeWild(fcount, fnames);
+
+    qf_lists[qf_curlist].qf_nonevalid = FALSE;
+    qf_lists[qf_curlist].qf_ptr = qf_lists[qf_curlist].qf_start;
+    qf_lists[qf_curlist].qf_index = 1;
+
+#ifdef FEAT_WINDOWS
+    qf_update_buffer();
+#endif
+
+    /* Jump to first match. */
+    if (qf_lists[qf_curlist].qf_count > 0)
+	qf_jump(0, 0, FALSE);
+
+theend:
+    vim_free(regmatch.regprog);
+
+    /* Only resture 'cpo' when it wasn't set in the mean time. */
+    if (p_cpo == empty_option)
+	p_cpo = save_cpo;
+    else
+	free_string_option(save_cpo);
+}
+
+/*
+ * ":[range]cbuffer [bufnr]" command.
+ */
+    void
+ex_cbuffer(eap)
+    exarg_T   *eap;
+{
+    buf_T	*buf = NULL;
+
+    if (*eap->arg == NUL)
+	buf = curbuf;
+    else if (*skipwhite(skipdigits(eap->arg)) == NUL)
+	buf = buflist_findnr(atoi((char *)eap->arg));
+    if (buf == NULL)
+	EMSG(_(e_invarg));
+    else if (buf->b_ml.ml_mfp == NULL)
+	EMSG(_("E681: Buffer is not loaded"));
+    else
+    {
+	if (eap->addr_count == 0)
+	{
+	    eap->line1 = 1;
+	    eap->line2 = buf->b_ml.ml_line_count;
+	}
+	if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count
+		|| eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count)
+	    EMSG(_(e_invrange));
+	else
+	    qf_init_ext(NULL, buf, p_efm, TRUE, eap->line1, eap->line2);
+    }
+}
+
+/*
  * ":helpgrep {pattern}"
  */
     void
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -726,7 +726,7 @@ re_lookbehind(prog)
 
 /*
  * Skip past regular expression.
- * Stop at end of 'p' of where 'dirc' is found ('/', '?', etc).
+ * Stop at end of 'p' 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
@@ -787,7 +787,8 @@ skip_regexp(startp, dirc, magic, newp)
 }
 
 /*
- * vim_regcomp - compile a regular expression into internal code
+ * vim_regcomp() - compile a regular expression into internal code
+ * Returns the program in allocated space.  Returns NULL for an error.
  *
  * We can't allocate space until we know how big the compiled form will be,
  * but we can't compile it (and thus know how big it is) until we've got a
--- a/src/structs.h
+++ b/src/structs.h
@@ -55,7 +55,7 @@ typedef struct
 typedef struct growarray
 {
     int	    ga_len;		    /* current number of items used */
-    int	    ga_room;		    /* number of unused items at the end */
+    int	    ga_maxlen;		    /* maximum number of items possible */
     int	    ga_itemsize;	    /* sizeof(item) */
     int	    ga_growsize;	    /* number of items to grow each time */
     void    *ga_data;		    /* pointer to the first item */
@@ -1127,6 +1127,7 @@ struct file_buffer
     char_u	*b_p_ft;	/* 'filetype' */
 #endif
     char_u	*b_p_fo;	/* 'formatoptions' */
+    char_u	*b_p_flp;	/* 'formatlistpat' */
     int		b_p_inf;	/* 'infercase' */
     char_u	*b_p_isk;	/* 'iskeyword' */
 #ifdef FEAT_FIND_ID
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1394,10 +1394,7 @@ store_current_state(sp)
 	    if (ga_grow(&sp->sst_union.sst_ga, current_state.ga_len) == FAIL)
 		sp->sst_stacksize = 0;
 	    else
-	    {
 		sp->sst_union.sst_ga.ga_len = current_state.ga_len;
-		sp->sst_union.sst_ga.ga_room -= current_state.ga_len;
-	    }
 	    bp = SYN_STATE_P(&(sp->sst_union.sst_ga));
 	}
 	else
@@ -1454,7 +1451,6 @@ load_current_state(from)
 	    update_si_attr(i);
 	}
 	current_state.ga_len = from->sst_stacksize;
-	current_state.ga_room -= current_state.ga_len;
     }
     current_next_list = from->sst_next_list;
     current_next_flags = from->sst_next_flags;
@@ -2089,7 +2085,6 @@ syn_current_attr(syncing, displaying)
 			{
 			    ((int *)(zero_width_next_ga.ga_data))
 				[zero_width_next_ga.ga_len++] = next_match_idx;
-			    --zero_width_next_ga.ga_room;
 			}
 			next_match_idx = -1;
 		    }
@@ -2579,7 +2574,6 @@ push_current_state(idx)
     vim_memset(&CUR_STATE(current_state.ga_len), 0, sizeof(stateitem_T));
     CUR_STATE(current_state.ga_len).si_idx = idx;
     ++current_state.ga_len;
-    --current_state.ga_room;
     return OK;
 }
 
@@ -2593,7 +2587,6 @@ pop_current_state()
     {
 	unref_extmatch(CUR_STATE(current_state.ga_len - 1).si_extmatch);
 	--current_state.ga_len;
-	++current_state.ga_room;
     }
     /* after the end of a pattern, try matching a keyword or pattern */
     next_match_idx = -1;
@@ -3151,7 +3144,6 @@ syn_remove_pattern(buf, idx)
     mch_memmove(spp, spp + 1,
 		   sizeof(synpat_T) * (buf->b_syn_patterns.ga_len - idx - 1));
     --buf->b_syn_patterns.ga_len;
-    --buf->b_syn_patterns.ga_room;
 }
 
 /*
@@ -4499,7 +4491,6 @@ syn_cmd_match(eap, syncing)
 		curbuf->b_syn_containedin = TRUE;
 	    SYN_ITEMS(curbuf)[idx].sp_next_list = next_list;
 	    ++curbuf->b_syn_patterns.ga_len;
-	    --curbuf->b_syn_patterns.ga_room;
 
 	    /* remember that we found a match for syncing on */
 	    if (flags & (HL_SYNC_HERE|HL_SYNC_THERE))
@@ -4742,7 +4733,6 @@ syn_cmd_region(eap, syncing)
 			SYN_ITEMS(curbuf)[idx].sp_next_list = next_list;
 		    }
 		    ++curbuf->b_syn_patterns.ga_len;
-		    --curbuf->b_syn_patterns.ga_room;
 		    ++idx;
 #ifdef FEAT_FOLDING
 		    if (flags & HL_FOLD)
@@ -5033,7 +5023,6 @@ syn_add_cluster(name)
     SYN_CLSTR(curbuf)[len].scl_name_u = vim_strsave_up(name);
     SYN_CLSTR(curbuf)[len].scl_list = NULL;
     ++curbuf->b_syn_clusters.ga_len;
-    --curbuf->b_syn_clusters.ga_room;
 
     return len + SYNID_CLUSTER;
 }
@@ -7467,7 +7456,6 @@ get_attr_entry(table, aep)
 	gap->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
     }
     ++table->ga_len;
-    --table->ga_room;
     return (table->ga_len - 1 + ATTR_OFF);
 }
 
@@ -7972,7 +7960,6 @@ syn_add_group(name)
     HL_TABLE()[highlight_ga.ga_len].sg_gui_fg = INVALCOLOR;
 #endif
     ++highlight_ga.ga_len;
-    --highlight_ga.ga_room;
 
     return highlight_ga.ga_len;		    /* ID is index plus one */
 }
@@ -7985,7 +7972,6 @@ syn_add_group(name)
 syn_unadd_group()
 {
     --highlight_ga.ga_len;
-    ++highlight_ga.ga_room;
     vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name);
     vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
 }
--- a/src/tag.c
+++ b/src/tag.c
@@ -2174,7 +2174,6 @@ line_read_in:
 			{
 			    ((struct match_found **)(ga_match[mtt].ga_data))
 					       [ga_match[mtt].ga_len++] = mfp;
-			    ga_match[mtt].ga_room--;
 			    ++match_count;
 			}
 			else
@@ -2345,11 +2344,8 @@ found_tagfile_cb(fname)
     char_u	*fname;
 {
     if (ga_grow(&tag_fnames, 1) == OK)
-    {
 	((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] =
 							   vim_strsave(fname);
-	--tag_fnames.ga_room;
-    }
 }
 
 /*
--- a/src/term.c
+++ b/src/term.c
@@ -2978,6 +2978,9 @@ check_shellsize()
 	Rows = min_rows();
 }
 
+/*
+ * Invoked just before the screen structures are going to be (re)allocated.
+ */
     void
 win_new_shellsize()
 {