changeset 1733:5a7384b9ca66 v7.2.031

updated for version 7.2-031
author vimboss
date Sun, 09 Nov 2008 12:46:09 +0000
parents f84061aa57e4
children 619b90abfdc9
files runtime/doc/cmdline.txt runtime/doc/eval.txt runtime/doc/starting.txt runtime/doc/usr_21.txt src/eval.c src/ex_cmds.c src/ex_cmds.h src/ex_docmd.c src/feature.h src/fileio.c src/main.c src/mark.c src/misc1.c src/option.c src/proto/eval.pro src/proto/ex_cmds.pro src/proto/mark.pro src/structs.h src/version.c src/vim.h
diffstat 20 files changed, 340 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -1,4 +1,4 @@
-*cmdline.txt*   For Vim version 7.2.  Last change: 2008 Jul 29
+*cmdline.txt*   For Vim version 7.2.  Last change: 2008 Sep 18
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -157,6 +157,11 @@ CTRL-R {0-9a-z"%#:-=.}					*c_CTRL-R* *c
 				(doesn't work at the expression prompt; some
 				things such as changing the buffer or current
 				window are not allowed to avoid side effects)
+				When the result is a |List| the items are used
+				as lines.  They can have line breaks inside
+				too.
+				When the result is a Float it's automatically
+				converted to a String.
 		See |registers| about registers.  {not in Vi}
 		Implementation detail: When using the |expression| register
 		and invoking setcmdpos(), this sets the position before
@@ -730,19 +735,29 @@ to use |fnameescape()|.
 In Ex commands, at places where a file name can be used, the following
 characters have a special meaning.  These can also be used in the expression
 function expand() |expand()|.
-	%	is replaced with the current file name			*:_%*
-	#	is replaced with the alternate file name		*:_#*
+	%	Is replaced with the current file name.		  *:_%* *c_%*
+	#	Is replaced with the alternate file name.	  *:_#* *c_#*
 	#n	(where n is a number) is replaced with the file name of
-		buffer n.  "#0" is the same as "#"
-	##	is replaced with all names in the argument list		*:_##*
+		buffer n.  "#0" is the same as "#".
+	##	Is replaced with all names in the argument list	  *:_##* *c_##*
 		concatenated, separated by spaces.  Each space in a name
 		is preceded with a backslash.
-Note that these give the file name as it was typed.  If an absolute path is
-needed (when using the file name from a different directory), you need to add
-":p".  See |filename-modifiers|.
+	#<n	(where n is a number > 0) is replaced with old	  *:_#<* *c_#<*
+		file name n.  See |:oldfiles| or |v:oldfiles| to get the
+		number.							*E809*
+		{only when compiled with the +eval and +viminfo features}
+
+Note that these, except "#<n", give the file name as it was typed.  If an
+absolute path is needed (when using the file name from a different directory),
+you need to add ":p".  See |filename-modifiers|.
+
+The "#<n" item returns an absolute path, but it will start with "~/" for files
+below your home directory.
+
 Note that backslashes are inserted before spaces, so that the command will
 correctly interpret the file name.  But this doesn't happen for shell
-commands.  For those you probably have to use quotes: >
+commands.  For those you probably have to use quotes (this fails for files
+that contain a quote and wildcards): >
 	:!ls "%"
 	:r !spell "%"
 
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*	For Vim version 7.2.  Last change: 2008 Aug 09
+*eval.txt*	For Vim version 7.2.  Last change: 2008 Nov 02
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1484,6 +1484,17 @@ v:mouse_col	Column number for a mouse cl
 		This is the screen column number, like with |virtcol()|.  The
 		value is zero when there was no mouse button click.
 
+					*v:oldfiles* *oldfiles-variable*
+v:oldfiles	List of file names that is loaded from the |viminfo| file on
+		startup.  These are the files that Vim remembers marks for.
+		The length of the List is limited by the ' argument of the
+		'viminfo' option (default is 100).
+		Also see |:oldfiles| and |c_#<|.
+		The List can be modified, but this has no effect on what is
+		stored in the |viminfo| file later.  If you use values other
+		than String this will cause trouble.
+		{only when compiled with the +viminfo feature}
+
 					*v:operator* *operator-variable*
 v:operator	The last operator given in Normal mode.  This is a single
 		character except for commands starting with <g> or <z>,
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -1,4 +1,4 @@
-*starting.txt*  For Vim version 7.2.  Last change: 2008 Jun 21
+*starting.txt*  For Vim version 7.2.  Last change: 2008 Nov 09
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1337,8 +1337,9 @@ enter Vim and directly start working in 
 							*viminfo-read*
 When Vim is started and the 'viminfo' option is non-empty, the contents of
 the viminfo file are read and the info can be used in the appropriate places.
-The marks are not read in at startup (but file marks are).  See
-|initialization| for how to set the 'viminfo' option upon startup.
+The |v:oldfiles| variable is filled.  The marks are not read in at startup
+(but file marks are).  See |initialization| for how to set the 'viminfo'
+option upon startup.
 
 							*viminfo-write*
 When Vim exits and 'viminfo' is non-empty, the info is stored in the viminfo
@@ -1372,6 +1373,8 @@ cursor position when the file was last e
 that start with any string given with the "r" flag in 'viminfo'.  This can be
 used to avoid saving marks for files on removable media (for MS-DOS you would
 use "ra:,rb:", for Amiga "rdf0:,rdf1:,rdf2:").
+The |v:oldfiles| variable is filled with the file names that the viminfo file
+has marks for.
 
 							*viminfo-file-marks*
 Uppercase marks ('A to 'Z) are stored when writing the viminfo file.  The
@@ -1463,8 +1466,8 @@ most of the information will be restored
 						   *:rv* *:rviminfo* *E195*
 :rv[iminfo][!] [file]	Read from viminfo file [file] (default: see above).
 			If [!] is given, then any information that is
-			already set (registers, marks, etc.) will be
-			overwritten.  {not in Vi}
+			already set (registers, marks, |v:oldfiles|, etc.)
+			will be overwritten   {not in Vi}
 
 					*:wv* *:wviminfo* *E137* *E138* *E574*
 :wv[iminfo][!] [file]	Write to viminfo file [file] (default: see above).
@@ -1479,4 +1482,20 @@ most of the information will be restored
 			the .viminfo file.
 			{not in Vi}
 
+						*:ol* *:oldfiles*
+:ol[dfiles]		List the files that have marks stored in the viminfo
+			file.  This list is read on startup and only changes
+			afterwards with ":rviminfo!".  Also see |v:oldfiles|.
+			The number can be used with |c_#<|.
+			{not in Vi, only when compiled with the +eval feature}
+
+:bro[wse] ol[dfiles][!]
+			List file names as with |:oldfiles|, and then prompt
+			for a number.  When the number is valid that file from
+			the list is edited.
+			If you get the |press-enter| prompt you can press "q"
+			and still get the prompt to enter a file number.
+			Use ! to abondon a modified buffer. |abandon|
+			{not when compiled with tiny or small features}
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/runtime/doc/usr_21.txt
+++ b/runtime/doc/usr_21.txt
@@ -1,4 +1,4 @@
-*usr_21.txt*	For Vim version 7.2.  Last change: 2007 May 01
+*usr_21.txt*	For Vim version 7.2.  Last change: 2008 Nov 09
 
 		     VIM USER MANUAL - by Bram Moolenaar
 
@@ -153,7 +153,7 @@ information.  This may cause information
 to be lost.  Each item can be remembered only once.
 
 
-GETTING BACK TO WHERE YOU WERE
+GETTING BACK TO WHERE YOU STOPPED VIM
 
 You are halfway editing a file and it's time to leave for holidays.  You exit
 Vim and go enjoy yourselves, forgetting all about your work.  After a couple
@@ -168,6 +168,48 @@ Mark '9 is lost.
    The |:marks| command is useful to find out where '0 to '9 will take you.
 
 
+GETTING BACK TO SOME FILE
+
+If you want to go back to a file that you edited recently, but not when
+exiting Vim, there is a slightly more complicated way.  You can see a list of
+files by typing the command: >
+
+	:oldfiles
+<	1: ~/.viminfo ~
+	2: ~/text/resume.txt ~
+	3: /tmp/draft ~
+
+Now you would like to edit the second file, which is in the list preceded by
+"2:".  You type: >
+
+	:e #<2
+
+Instead of ":e" you can use any command that has a file name argument, the
+"#<2" item works in the same place as "%" (current file name) and "#"
+(alternate file name).  So you can also split the window to edit the third
+file: >
+
+	:split #<3
+
+That #<123 thing is a bit complicated when you just want to edit a file.
+Fortunately there is a simpler way: >
+
+	:browse oldfiles
+<	1: ~/.viminfo ~
+	2: ~/text/resume.txt ~
+	3: /tmp/draft ~
+	-- More --
+
+You get the same list of files as with |:oldfiles|.  If you want to edit
+"resume.txt" first press "q" to stop the listing.  You will get a prompt:
+
+	Type number and <Enter> (empty cancels): ~
+
+Type "2" and press <Enter> to edit the second file.
+
+More info at |:oldfiles|, |v:oldfiles| and |c_#<|.
+
+
 MOVE INFO FROM ONE VIM TO ANOTHER
 
 You can use the ":wviminfo" and ":rviminfo" commands to save and restore the
--- a/src/eval.c
+++ b/src/eval.c
@@ -348,6 +348,7 @@ static struct vimvar
     {VV_NAME("mouse_col",	 VAR_NUMBER), 0},
     {VV_NAME("operator",	 VAR_STRING), VV_RO},
     {VV_NAME("searchforward",	 VAR_NUMBER), 0},
+    {VV_NAME("oldfiles",	 VAR_LIST), 0},
 };
 
 /* shorthand */
@@ -355,6 +356,7 @@ static struct vimvar
 #define vv_nr		vv_di.di_tv.vval.v_number
 #define vv_float	vv_di.di_tv.vval.v_float
 #define vv_str		vv_di.di_tv.vval.v_string
+#define vv_list		vv_di.di_tv.vval.v_list
 #define vv_tv		vv_di.di_tv
 
 /*
@@ -426,7 +428,6 @@ static long list_find_nr __ARGS((list_T 
 static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
 static void list_append __ARGS((list_T *l, listitem_T *item));
 static int list_append_tv __ARGS((list_T *l, typval_T *tv));
-static int list_append_string __ARGS((list_T *l, char_u *str, int len));
 static int list_append_number __ARGS((list_T *l, varnumber_T n));
 static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
 static int list_extend __ARGS((list_T	*l1, list_T *l2, listitem_T *bef));
@@ -845,8 +846,13 @@ eval_clear()
 	p = &vimvars[i];
 	if (p->vv_di.di_tv.v_type == VAR_STRING)
 	{
-	    vim_free(p->vv_di.di_tv.vval.v_string);
-	    p->vv_di.di_tv.vval.v_string = NULL;
+	    vim_free(p->vv_string);
+	    p->vv_string = NULL;
+	}
+	else if (p->vv_di.di_tv.v_type == VAR_LIST)
+	{
+	    list_unref(p->vv_list);
+	    p->vv_list = NULL;
 	}
     }
     hash_clear(&vimvarht);
@@ -6057,6 +6063,25 @@ list_find_nr(l, idx, errorp)
 }
 
 /*
+ * Get list item "l[idx - 1]" as a string.  Returns NULL for failure.
+ */
+    char_u *
+list_find_str(l, idx)
+    list_T	*l;
+    long	idx;
+{
+    listitem_T	*li;
+
+    li = list_find(l, idx - 1);
+    if (li == NULL)
+    {
+	EMSGN(_(e_listidx), idx);
+	return NULL;
+    }
+    return get_tv_string(&li->li_tv);
+}
+
+/*
  * Locate "item" list "l" and return its index.
  * Returns -1 when "item" is not in the list.
  */
@@ -6147,7 +6172,7 @@ list_append_dict(list, dict)
  * When "len" >= 0 use "str[len]".
  * Returns FAIL when out of memory.
  */
-    static int
+    int
 list_append_string(l, str, len)
     list_T	*l;
     char_u	*str;
@@ -6507,6 +6532,9 @@ garbage_collect()
 	set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
     }
 
+    /* v: vars */
+    set_ref_in_ht(&vimvarht, copyID);
+
     /*
      * 2. Go through the list of dicts and free items without the copyID.
      */
@@ -6597,7 +6625,7 @@ set_ref_in_item(tv, copyID)
     {
 	case VAR_DICT:
 	    dd = tv->vval.v_dict;
-	    if (dd->dv_copyID != copyID)
+	    if (dd != NULL && dd->dv_copyID != copyID)
 	    {
 		/* Didn't see this dict yet. */
 		dd->dv_copyID = copyID;
@@ -6607,7 +6635,7 @@ set_ref_in_item(tv, copyID)
 
 	case VAR_LIST:
 	    ll = tv->vval.v_list;
-	    if (ll->lv_copyID != copyID)
+	    if (ll != NULL && ll->lv_copyID != copyID)
 	    {
 		/* Didn't see this list yet. */
 		ll->lv_copyID = copyID;
@@ -18106,6 +18134,17 @@ get_vim_var_str(idx)
 }
 
 /*
+ * Get List v: variable value.  Caller must take care of reference count when
+ * needed.
+ */
+    list_T *
+get_vim_var_list(idx)
+    int		idx;
+{
+    return vimvars[idx].vv_list;
+}
+
+/*
  * Set v:count, v:count1 and v:prevcount.
  */
     void
@@ -18141,6 +18180,20 @@ set_vim_var_string(idx, val, len)
 }
 
 /*
+ * Set List v: variable to "val".
+ */
+    void
+set_vim_var_list(idx, val)
+    int		idx;
+    list_T	*val;
+{
+    list_unref(vimvars[idx].vv_list);
+    vimvars[idx].vv_list = val;
+    if (val != NULL)
+	++val->lv_refcount;
+}
+
+/*
  * Set v:register if needed.
  */
     void
@@ -21900,6 +21953,62 @@ last_set_msg(scriptID)
     }
 }
 
+/*
+ * List v:oldfiles in a nice way.
+ */
+/*ARGSUSED*/
+    void
+ex_oldfiles(eap)
+    exarg_T	*eap;
+{
+    list_T	*l = vimvars[VV_OLDFILES].vv_list;
+    listitem_T	*li;
+    int		nr = 0;
+
+    if (l == NULL)
+	msg((char_u *)_("No old files"));
+    else
+    {
+	msg_start();
+	msg_scroll = TRUE;
+	for (li = l->lv_first; li != NULL && !got_int; li = li->li_next)
+	{
+	    msg_outnum((long)++nr);
+	    MSG_PUTS(": ");
+	    msg_outtrans(get_tv_string(&li->li_tv));
+	    msg_putchar('\n');
+	    out_flush();	    /* output one line at a time */
+	    ui_breakcheck();
+	}
+	/* Assume "got_int" was set to truncate the listing. */
+	got_int = FALSE;
+
+#ifdef FEAT_BROWSE_CMD
+	if (cmdmod.browse)
+	{
+	    quit_more = FALSE;
+	    nr = prompt_for_number(FALSE);
+	    msg_starthere();
+	    if (nr > 0)
+	    {
+		char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES),
+								    (long)nr);
+
+		if (p != NULL)
+		{
+		    p = expand_env_save(p);
+		    eap->arg = p;
+		    eap->cmdidx = CMD_edit;
+		    cmdmod.browse = FALSE;
+		    do_exedit(eap, NULL);
+		    vim_free(p);
+		}
+	    }
+	}
+#endif
+    }
+}
+
 #endif /* FEAT_EVAL */
 
 
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -24,7 +24,7 @@ static int linelen __ARGS((int *has_tab)
 static void do_filter __ARGS((linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out));
 #ifdef FEAT_VIMINFO
 static char_u *viminfo_filename __ARGS((char_u	*));
-static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
+static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int flags));
 static int viminfo_encoding __ARGS((vir_T *virp));
 static int read_viminfo_up_to_marks __ARGS((vir_T *virp, int forceit, int writing));
 #endif
@@ -1676,14 +1676,12 @@ viminfo_error(errnum, message, line)
 
 /*
  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
- * set are not over-written unless force is TRUE. -- webb
+ * set are not over-written unless "flags" includes VIF_FORCEIT. -- webb
  */
     int
-read_viminfo(file, want_info, want_marks, forceit)
-    char_u	*file;
-    int		want_info;
-    int		want_marks;
-    int		forceit;
+read_viminfo(file, flags)
+    char_u	*file;	    /* file name or NULL to use default name */
+    int		flags;	    /* VIF_WANT_INFO et al. */
 {
     FILE	*fp;
     char_u	*fname;
@@ -1691,7 +1689,7 @@ read_viminfo(file, want_info, want_marks
     if (no_viminfo())
 	return FAIL;
 
-    fname = viminfo_filename(file);	    /* may set to default if NULL */
+    fname = viminfo_filename(file);	/* get file name in allocated buffer */
     if (fname == NULL)
 	return FAIL;
     fp = mch_fopen((char *)fname, READBIN);
@@ -1701,8 +1699,9 @@ read_viminfo(file, want_info, want_marks
 	verbose_enter();
 	smsg((char_u *)_("Reading viminfo file \"%s\"%s%s%s"),
 		fname,
-		want_info ? _(" info") : "",
-		want_marks ? _(" marks") : "",
+		(flags & VIF_WANT_INFO) ? _(" info") : "",
+		(flags & VIF_WANT_MARKS) ? _(" marks") : "",
+		(flags & VIF_GET_OLDFILES) ? _(" oldfiles") : "",
 		fp == NULL ? _(" FAILED") : "");
 	verbose_leave();
     }
@@ -1712,10 +1711,9 @@ read_viminfo(file, want_info, want_marks
 	return FAIL;
 
     viminfo_errcnt = 0;
-    do_viminfo(fp, NULL, want_info, want_marks, forceit);
+    do_viminfo(fp, NULL, flags);
 
     fclose(fp);
-
     return OK;
 }
 
@@ -1968,7 +1966,7 @@ write_viminfo(file, forceit)
     }
 
     viminfo_errcnt = 0;
-    do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
+    do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS));
 
     fclose(fp_out);	    /* errors are ignored !? */
     if (fp_in != NULL)
@@ -2041,12 +2039,10 @@ viminfo_filename(file)
  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
  */
     static void
-do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
+do_viminfo(fp_in, fp_out, flags)
     FILE	*fp_in;
     FILE	*fp_out;
-    int		want_info;
-    int		want_marks;
-    int		force_read;
+    int		flags;
 {
     int		count = 0;
     int		eof = FALSE;
@@ -2061,8 +2057,9 @@ do_viminfo(fp_in, fp_out, want_info, wan
 
     if (fp_in != NULL)
     {
-	if (want_info)
-	    eof = read_viminfo_up_to_marks(&vir, force_read, fp_out != NULL);
+	if (flags & VIF_WANT_INFO)
+	    eof = read_viminfo_up_to_marks(&vir,
+					 flags & VIF_FORCEIT, fp_out != NULL);
 	else
 	    /* Skip info, find start of marks */
 	    while (!(eof = viminfo_readline(&vir))
@@ -2092,8 +2089,9 @@ do_viminfo(fp_in, fp_out, want_info, wan
 	write_viminfo_bufferlist(fp_out);
 	count = write_viminfo_marks(fp_out);
     }
-    if (fp_in != NULL && want_marks)
-	copy_viminfo_marks(&vir, fp_out, count, eof);
+    if (fp_in != NULL
+	    && (flags & (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT)))
+	copy_viminfo_marks(&vir, fp_out, count, eof, flags);
 
     vim_free(vir.vir_line);
 #ifdef FEAT_MBYTE
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -653,6 +653,8 @@ EX(CMD_nunmenu,		"nunmenu",	ex_menu,
 			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_open,		"open",		ex_open,
 			RANGE|EXTRA),
+EX(CMD_oldfiles,	"oldfiles",	ex_oldfiles,
+			BANG|TRLBAR|SBOXOK|CMDWIN),
 EX(CMD_omap,		"omap",		ex_map,
 			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_omapclear,	"omapclear",	ex_mapclear,
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -364,6 +364,7 @@ static void	ex_tag_cmd __ARGS((exarg_T *
 # define ex_function		ex_ni
 # define ex_delfunction		ex_ni
 # define ex_return		ex_ni
+# define ex_oldfiles		ex_ni
 #endif
 static char_u	*arg_all __ARGS((void));
 #ifdef FEAT_SESSION
@@ -1770,7 +1771,7 @@ do_one_cmd(cmdlinep, sourcing,
 			}
 			if (checkforcmd(&ea.cmd, "browse", 3))
 			{
-#ifdef FEAT_BROWSE
+#ifdef FEAT_BROWSE_CMD
 			    cmdmod.browse = TRUE;
 #endif
 			    continue;
@@ -9508,24 +9509,50 @@ eval_vars(src, srcstart, usedlen, lnump,
 		    break;
 		}
 		s = src + 1;
+		if (*s == '<')		/* "#<99" uses v:oldfiles */
+		    ++s;
 		i = (int)getdigits(&s);
 		*usedlen = (int)(s - src); /* length of what we expand */
 
-		buf = buflist_findnr(i);
-		if (buf == NULL)
+		if (src[1] == '<')
 		{
-		    *errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'");
+		    if (*usedlen < 2)
+		    {
+			/* Should we give an error message for #<text? */
+			*usedlen = 1;
+			return NULL;
+		    }
+#ifdef FEAT_EVAL
+		    result = list_find_str(get_vim_var_list(VV_OLDFILES),
+								     (long)i);
+		    if (result == NULL)
+		    {
+			*errormsg = (char_u *)"";
+			return NULL;
+		    }
+#else
+		    *errormsg = (char_u *)_("E809: #< is not available without the +eval feature");
 		    return NULL;
-		}
-		if (lnump != NULL)
-		    *lnump = ECMD_LAST;
-		if (buf->b_fname == NULL)
-		{
-		    result = (char_u *)"";
-		    valid = 0;	    /* Must have ":p:h" to be valid */
+#endif
 		}
 		else
-		    result = buf->b_fname;
+		{
+		    buf = buflist_findnr(i);
+		    if (buf == NULL)
+		    {
+			*errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'");
+			return NULL;
+		    }
+		    if (lnump != NULL)
+			*lnump = ECMD_LAST;
+		    if (buf->b_fname == NULL)
+		    {
+			result = (char_u *)"";
+			valid = 0;	    /* Must have ":p:h" to be valid */
+		    }
+		    else
+			result = buf->b_fname;
+		}
 		break;
 
 #ifdef FEAT_SEARCHPATH
@@ -10700,7 +10727,8 @@ ex_viminfo(eap)
 	p_viminfo = (char_u *)"'100";
     if (eap->cmdidx == CMD_rviminfo)
     {
-	if (read_viminfo(eap->arg, TRUE, TRUE, eap->forceit) == FAIL)
+	if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS
+				  | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL)
 	    EMSG(_("E195: Cannot open viminfo file for reading"));
     }
     else
--- a/src/feature.h
+++ b/src/feature.h
@@ -767,9 +767,13 @@
 
 /*
  * +browse		":browse" command.
+ *			or just the ":browse" command modifier
  */
-#if defined(FEAT_NORMAL) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
-# define FEAT_BROWSE
+#if defined(FEAT_NORMAL)
+# define FEAT_BROWSE_CMD
+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
+#  define FEAT_BROWSE
+# endif
 #endif
 
 /*
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2711,7 +2711,7 @@ check_marks_read()
 {
     if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
 						  && curbuf->b_ffname != NULL)
-	read_viminfo(NULL, FALSE, TRUE, FALSE);
+	read_viminfo(NULL, VIF_WANT_MARKS);
 
     /* Always set b_marks_read; needed when 'viminfo' is changed to include
      * the ' parameter after opening a buffer. */
@@ -9108,7 +9108,7 @@ static int include_groups = FALSE;
 set_context_in_autocmd(xp, arg, doautocmd)
     expand_T	*xp;
     char_u	*arg;
-    int		doautocmd;	/* TRUE for :doautocmd, FALSE for :autocmd */
+    int		doautocmd;	/* TRUE for :doauto*, FALSE for :autocmd */
 {
     char_u	*p;
     int		group;
--- a/src/main.c
+++ b/src/main.c
@@ -645,11 +645,12 @@ main
 
 #ifdef FEAT_VIMINFO
     /*
-     * Read in registers, history etc, but not marks, from the viminfo file
+     * Read in registers, history etc, but not marks, from the viminfo file.
+     * This is where v:oldfiles gets filled.
      */
     if (*p_viminfo != NUL)
     {
-	read_viminfo(NULL, TRUE, FALSE, FALSE);
+	read_viminfo(NULL, VIF_WANT_INFO | VIF_GET_OLDFILES);
 	TIME_MSG("reading viminfo");
     }
 #endif
--- a/src/mark.c
+++ b/src/mark.c
@@ -1627,15 +1627,17 @@ write_one_mark(fp_out, c, pos)
 
 /*
  * Handle marks in the viminfo file:
- * fp_out == NULL   read marks for current buffer only
- * fp_out != NULL   copy marks for buffers not in buffer list
+ * fp_out != NULL: copy marks for buffers not in buffer list
+ * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
+ * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
  */
     void
-copy_viminfo_marks(virp, fp_out, count, eof)
+copy_viminfo_marks(virp, fp_out, count, eof, flags)
     vir_T	*virp;
     FILE	*fp_out;
     int		count;
     int		eof;
+    int		flags;
 {
     char_u	*line = virp->vir_line;
     buf_T	*buf;
@@ -1647,10 +1649,23 @@ copy_viminfo_marks(virp, fp_out, count, 
     char_u	*p;
     char_u	*name_buf;
     pos_T	pos;
+#ifdef FEAT_EVAL
+    list_T	*list = NULL;
+#endif
 
     if ((name_buf = alloc(LSIZE)) == NULL)
 	return;
     *name_buf = NUL;
+
+#ifdef FEAT_EVAL
+    if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
+    {
+	list = list_alloc();
+	if (list != NULL)
+	    set_vim_var_list(VV_OLDFILES, list);
+    }
+#endif
+
     num_marked_files = get_viminfo_parameter('\'');
     while (!eof && (count < num_marked_files || fp_out == NULL))
     {
@@ -1681,6 +1696,11 @@ copy_viminfo_marks(virp, fp_out, count, 
 	    p++;
 	*p = NUL;
 
+#ifdef FEAT_EVAL
+	if (list != NULL)
+	    list_append_string(list, str, -1);
+#endif
+
 	/*
 	 * If fp_out == NULL, load marks for current buffer.
 	 * If fp_out != NULL, copy marks for buffers not in buflist.
@@ -1688,7 +1708,7 @@ copy_viminfo_marks(virp, fp_out, count, 
 	load_marks = copy_marks_out = FALSE;
 	if (fp_out == NULL)
 	{
-	    if (curbuf->b_ffname != NULL)
+	    if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL)
 	    {
 		if (*name_buf == NUL)	    /* only need to do this once */
 		    home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -3245,9 +3245,9 @@ prompt_for_number(mouse_used)
 
     /* When using ":silent" assume that <CR> was entered. */
     if (mouse_used != NULL)
-	MSG_PUTS(_("Type number or click with mouse (<Enter> cancels): "));
+	MSG_PUTS(_("Type number and <Enter> or click with mouse (empty cancels): "));
     else
-	MSG_PUTS(_("Choice number (<Enter> cancels): "));
+	MSG_PUTS(_("Type number and <Enter> (empty cancels): "));
 
     /* Set the state such that text can be selected/copied/pasted and we still
      * get mouse events. */
--- a/src/option.c
+++ b/src/option.c
@@ -2593,13 +2593,13 @@ static struct vimoption
 #ifdef FEAT_VIMINFO
 			    (char_u *)&p_viminfo, PV_NONE,
 #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
-			    {(char_u *)"", (char_u *)"'20,<50,s10,h,rA:,rB:"}
+			    {(char_u *)"", (char_u *)"'100,<50,s10,h,rA:,rB:"}
 #else
 # ifdef AMIGA
 			    {(char_u *)"",
-				 (char_u *)"'20,<50,s10,h,rdf0:,rdf1:,rdf2:"}
+				 (char_u *)"'100,<50,s10,h,rdf0:,rdf1:,rdf2:"}
 # else
-			    {(char_u *)"", (char_u *)"'20,<50,s10,h"}
+			    {(char_u *)"", (char_u *)"'100,<50,s10,h"}
 # endif
 #endif
 #else
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -17,7 +17,7 @@ void eval_patch __ARGS((char_u *origfile
 int eval_to_bool __ARGS((char_u *arg, int *error, char_u **nextcmd, int skip));
 char_u *eval_to_string_skip __ARGS((char_u *arg, char_u **nextcmd, int skip));
 int skip_expr __ARGS((char_u **pp));
-char_u *eval_to_string __ARGS((char_u *arg, char_u **nextcmd, int dolist));
+char_u *eval_to_string __ARGS((char_u *arg, char_u **nextcmd, int convert));
 char_u *eval_to_string_safe __ARGS((char_u *arg, char_u **nextcmd, int use_sandbox));
 int eval_to_number __ARGS((char_u *expr));
 list_T *eval_spell_expr __ARGS((char_u *badword, char_u *expr));
@@ -46,7 +46,9 @@ list_T *list_alloc __ARGS((void));
 void list_unref __ARGS((list_T *l));
 void list_free __ARGS((list_T *l, int recurse));
 dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
+char_u *list_find_str __ARGS((list_T *l, long idx));
 int list_append_dict __ARGS((list_T *list, dict_T *dict));
+int list_append_string __ARGS((list_T *l, char_u *str, int len));
 int garbage_collect __ARGS((void));
 dict_T *dict_alloc __ARGS((void));
 int dict_add_nr_str __ARGS((dict_T *d, char *key, long nr, char_u *str));
@@ -58,8 +60,10 @@ long do_searchpair __ARGS((char_u *spat,
 void set_vim_var_nr __ARGS((int idx, long val));
 long get_vim_var_nr __ARGS((int idx));
 char_u *get_vim_var_str __ARGS((int idx));
+list_T *get_vim_var_list __ARGS((int idx));
 void set_vcount __ARGS((long count, long count1));
 void set_vim_var_string __ARGS((int idx, char_u *val, int len));
+void set_vim_var_list __ARGS((int idx, list_T *val));
 void set_reg_var __ARGS((int c));
 char_u *v_exception __ARGS((char_u *oldval));
 char_u *v_throwpoint __ARGS((char_u *oldval));
@@ -94,6 +98,7 @@ int read_viminfo_varlist __ARGS((vir_T *
 void write_viminfo_varlist __ARGS((FILE *fp));
 int store_session_globals __ARGS((FILE *fd));
 void last_set_msg __ARGS((scid_T scriptID));
+void ex_oldfiles __ARGS((exarg_T *eap));
 int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
 char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
 /* vim: set ft=c : */
--- a/src/proto/ex_cmds.pro
+++ b/src/proto/ex_cmds.pro
@@ -11,7 +11,7 @@ void do_shell __ARGS((char_u *cmd, int f
 char_u *make_filter_cmd __ARGS((char_u *cmd, char_u *itmp, char_u *otmp));
 void append_redir __ARGS((char_u *buf, char_u *opt, char_u *fname));
 int viminfo_error __ARGS((char *errnum, char *message, char_u *line));
-int read_viminfo __ARGS((char_u *file, int want_info, int want_marks, int forceit));
+int read_viminfo __ARGS((char_u *file, int flags));
 void write_viminfo __ARGS((char_u *file, int forceit));
 int viminfo_readline __ARGS((vir_T *virp));
 char_u *viminfo_readstring __ARGS((vir_T *virp, int off, int convert));
--- a/src/proto/mark.pro
+++ b/src/proto/mark.pro
@@ -26,5 +26,5 @@ int read_viminfo_filemark __ARGS((vir_T 
 void write_viminfo_filemarks __ARGS((FILE *fp));
 int removable __ARGS((char_u *name));
 int write_viminfo_marks __ARGS((FILE *fp_out));
-void copy_viminfo_marks __ARGS((vir_T *virp, FILE *fp_out, int count, int eof));
+void copy_viminfo_marks __ARGS((vir_T *virp, FILE *fp_out, int count, int eof, int flags));
 /* vim: set ft=c : */
--- a/src/structs.h
+++ b/src/structs.h
@@ -459,7 +459,7 @@ typedef struct expand
 typedef struct
 {
     int		hide;			/* TRUE when ":hide" was used */
-# ifdef FEAT_BROWSE
+# ifdef FEAT_BROWSE_CMD
     int		browse;			/* TRUE to invoke file dialog */
 # endif
 # ifdef FEAT_WINDOWS
--- a/src/version.c
+++ b/src/version.c
@@ -677,6 +677,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    31,
+/**/
     30,
 /**/
     29,
--- a/src/vim.h
+++ b/src/vim.h
@@ -1728,7 +1728,8 @@ typedef int proftime_T;	    /* dummy for
 #define VV_MOUSE_COL	51
 #define VV_OP		52
 #define VV_SEARCHFORWARD 53
-#define VV_LEN		54	/* number of v: vars */
+#define VV_OLDFILES	54
+#define VV_LEN		55	/* number of v: vars */
 
 #ifdef FEAT_CLIPBOARD
 
@@ -2054,4 +2055,10 @@ typedef int VimClipboard;	/* This is req
 #define DOSO_VIMRC	1	/* loading vimrc file */
 #define DOSO_GVIMRC	2	/* loading gvimrc file */
 
+/* flags for read_viminfo() and children */
+#define VIF_WANT_INFO		1	/* load non-mark info */
+#define VIF_WANT_MARKS		2	/* load file marks */
+#define VIF_FORCEIT		4	/* overwrite info already read */
+#define VIF_GET_OLDFILES	8	/* load v:oldfiles */
+
 #endif /* VIM__H */