changeset 594:35cef95a6b76 v7.0168

updated for version 7.0168
author vimboss
date Mon, 12 Dec 2005 22:05:50 +0000
parents d220eb88e4e4
children fea48f63efc8
files runtime/doc/todo.txt runtime/doc/version7.txt src/eval.c src/memline.c src/misc1.c src/proto/misc1.pro
diffstat 6 files changed, 261 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2005 Dec 11
+*todo.txt*      For Vim version 7.0aa.  Last change: 2005 Dec 12
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,24 +30,6 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-When editing a file "a" that is a symbolic link to "b", while another Vim is
-editing "b", there is no warning.  Follow symlink to make swap file name?
-Patch from Stefano Zacchiroli.  Updated by James Vega, Dec 2.
-
-Using pipes for filter commands: provide some way to type a password, keep
-stderr in/out open for this? (Konstanti Rozinov)
-New problem: password is echoed.  Put terminal in cooked mode and don't read
-from terminal?
-
-Allow the user to handle the situation that a swap file already exists.
-Option to define a function to be called?  Function would return the character
-that the dialog provides.  Would make it possible to bring the other Vim to
-the foreground and abort the edit.  Or hard-code this?
-
-To support mapping <F4> to be used as <F4>{motion}: Add operator that
-executes a user defined function. '[ and '] marks are at start and end of
-text.  ":map <F4> :set opfunc=MyOp<CR>gy".
-
 Patch from Yasuhiro Matsumoto: ":e ++enc=xxx" keeps encoding for conversion
 errors and illegal bytes.  Make default to replace bad bytes/characters with
 '?' and allow for two alternatives:
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2005 Dec 11
+*version7.txt*  For Vim version 7.0aa.  Last change: 2005 Dec 12
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -29,6 +29,7 @@ Scroll back in messages			|new-scroll-ba
 POSIX compatibility			|new-posix|
 Debugger support			|new-debug-support|
 Remote file explorer			|new-netrw-explore|
+Define an operator			|new-define-operator|
 Various new items			|new-items-7|
 
 IMPROVEMENTS				|improvements-7|
@@ -167,7 +168,7 @@ The 'spellsuggest' option specifies the 
 
 The |[s| and |]s| commands can be used to move to the next or previous error.
 The |zg| and |zw| commands can be used to add good and wrong words.
-The |z?| command can be used to correct the word.
+The |z=| command can be used to correct the word.
 The |:mkspell| command is used to generate a Vim spell file from word lists.
 
 The "undercurl" highlighting attribute was added to nicely point out spelling
@@ -341,6 +342,18 @@ and a GUI dialog is not possible.
 The netrw plugin is maintained by Charles Campbell.
 
 
+Define an operator					*new-define-operator*
+------------------
+
+Previously it was not possible to define your own operator; a command that is
+followed by a {motion}.  Vim 7 introduces the 'operatorfunc' option and the
+|g@| operator.  This makes it possible to define a mapping that works like an
+operator.  The actual work is then done by a function, which is invoked
+through the |g@| operator.
+
+See |:map-operator| for the explanation and an example.
+
+
 Various new items					*new-items-7*
 -----------------
 
@@ -573,17 +586,19 @@ Mac: GUI font selector. (Peter Cucka)
 
 Mac: support for multi-byte characters. (Da Woon Jung)
 
+Mac: Support the xterm mouse in the non-GUI version.
+
+Mac: better integration with Xcode.  Post a fake mouse-up event after the odoc
+event and the drag receive handler to work around a stall after Vim loads a
+file.  Fixed an off-by-one line number error. (Da Woon Jung)
+
+Added the t_SI and t_EI escape sequences for starting and ending Insert mode.
 GUI font selector for Motif. (Marcin Dalecki)
 
 Nicer toolbar buttons for Motif. (Marcin Dalecki)
 
 Mnemonics for the Motif find/replace dialog. (Marcin Dalecki)
 
-Mac: better integration with Xcode.  Post a fake mouse-up event after the odoc
-event and the drag receive handler to work around a stall after Vim loads a
-file.  Fixed an off-by-one line number error. (Da Woon Jung)
-
-Added the t_SI and t_EI escape sequences for starting and ending Insert mode.
 To be used to set the cursor shape to a bar or a block.  No default values,
 they are not supported by termcap/terminfo.
 
@@ -707,6 +722,10 @@ the swap file to indicate it is in the s
 used path then doesn't matter and the check for editing the same file is much
 more reliable.
 
+Unix: When editing a file through a symlink the swap file would use the name
+of the symlink.  Now use the name of the actual file, so that editing the same
+file twice is detected. (suggestions by Stefano Zacchiroli and James Vega)
+
 Client-server communication now supports 'encoding'.  When setting 'encoding'
 in a Vim server to "utf-8", and using "vim --remote fname" in a console,
 "fname" is converted from the console encoding to utf-8.  Also allows Vims
@@ -869,6 +888,10 @@ file would be used for the current buffe
 actually different from the file content.  Don't set the file name, unless the
 'P' flag is present in 'cpoptions'.
 
+When starting to edit a new file and the directory for the file doesn't exist
+then Vim will report "[New DIRECTORY]" instead of "[New File] to give the user
+a hint that something might be wrong.
+
 ==============================================================================
 COMPILE TIME CHANGES					*compile-changes-7*
 
@@ -1438,4 +1461,8 @@ the buffer to use "fname", the modified 
 When appending to to current file the "not edited" flag would be reset.
 ":w" would overwrite the file accidentally.
 
+Unix: When filtering text with an external command Vim would still read input,
+causing text typed for the command (e.g., a password) to be eaten and echoed.
+Don't read input when the terminal is in cooked mode.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/src/eval.c
+++ b/src/eval.c
@@ -12836,10 +12836,9 @@ f_resolve(argvars, rettv)
 			remain = vim_strsave(q - 1);
 		    else
 		    {
-			cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
+			cpy = concat_str(q - 1, remain);
 			if (cpy != NULL)
 			{
-			    STRCAT(cpy, remain);
 			    vim_free(remain);
 			    remain = cpy;
 			}
--- a/src/memline.c
+++ b/src/memline.c
@@ -3382,6 +3382,87 @@ ml_lineadd(buf, count)
     }
 }
 
+#ifdef HAVE_READLINK
+static int resolve_symlink __ARGS((char_u *fname, char_u *buf));
+
+/*
+ * Resolve a symlink in the last component of a file name.
+ * Note that f_resolve() does it for every part of the path, we don't do that
+ * here.
+ * If it worked returns OK and the resolved link in "buf[MAXPATHL]".
+ * Otherwise returns FAIL.
+ */
+    static int
+resolve_symlink(fname, buf)
+    char_u	*fname;
+    char_u	*buf;
+{
+    char_u	tmp[MAXPATHL];
+    int		ret;
+    int		depth = 0;
+
+    if (fname == NULL)
+	return FAIL;
+
+    /* Put the result so far in tmp[], starting with the original name. */
+    vim_strncpy(tmp, fname, MAXPATHL - 1);
+
+    for (;;)
+    {
+	/* Limit symlink depth to 100, catch recursive loops. */
+	if (++depth == 100)
+	{
+	    EMSG2(_("E773: Symlink loop for \"%s\""), fname);
+	    return FAIL;
+	}
+
+	ret = readlink((char *)tmp, (char *)buf, MAXPATHL - 1);
+	if (ret <= 0)
+	{
+	    if (errno == EINVAL)  /* found non-symlink, stop here */
+	    {
+		/* When at the first level use the unmodifed name, skip the
+		 * call to vim_FullName(). */
+		if (depth == 1)
+		    return FAIL;
+
+		/* Use the resolved name in tmp[]. */
+		break;
+	    }
+
+	    /* There must be some error reading links, use original name. */
+	    return FAIL;
+	}
+	buf[ret] = NUL;
+
+	/*
+	 * Check whether the symlink is relative or absolute.
+	 * If it's relative, build a new path based on the directory
+	 * portion of the filename (if any) and the path the symlink
+	 * points to.
+	 */
+	if (mch_isFullName(buf))
+	    STRCPY(tmp, buf);
+	else
+	{
+	    char_u *tail;
+
+	    tail = gettail(tmp);
+	    if (STRLEN(tail) + STRLEN(buf) >= MAXPATHL)
+		return FAIL;
+	    STRCPY(tail, buf);
+	}
+    }
+
+    /*
+     * Try to resolve the full name of the file so that the swapfile name will
+     * be consistent even when opening a relative symlink from different
+     * working directories.
+     */
+    return vim_FullName(tmp, buf, MAXPATHL, TRUE);
+}
+#endif
+
 /*
  * Make swap file name out of the file name and a directory name.
  * Returns pointer to allocated memory or NULL.
@@ -3395,6 +3476,10 @@ makeswapname(fname, ffname, buf, dir_nam
     char_u	*dir_name;
 {
     char_u	*r, *s;
+#ifdef HAVE_READLINK
+    char_u	fname_buf[MAXPATHL];
+    char_u	*fname_res;
+#endif
 
 #if defined(UNIX) || defined(WIN3264)  /* Need _very_ long file names */
     s = dir_name + STRLEN(dir_name);
@@ -3410,6 +3495,15 @@ makeswapname(fname, ffname, buf, dir_nam
     }
 #endif
 
+#ifdef HAVE_READLINK
+    /* Expand symlink in the file name, so that we put the swap file with the
+     * actual file instead of with the symlink. */
+    if (resolve_symlink(fname, fname_buf) == OK)
+	fname_res = fname_buf;
+    else
+	fname_res = fname;
+#endif
+
     r = buf_modname(
 #ifdef SHORT_FNAME
 	    TRUE,
@@ -3420,7 +3514,11 @@ makeswapname(fname, ffname, buf, dir_nam
 	    /* Avoid problems if fname has special chars, eg <Wimp$Scrap> */
 	    ffname,
 #else
+# ifdef HAVE_READLINK
+	    fname_res,
+# else
 	    fname,
+# endif
 #endif
 	    (char_u *)
 #if defined(VMS) || defined(RISCOS)
@@ -3848,7 +3946,17 @@ findswapname(buf, dirp, old_fname)
 			    if (fnamecmp(gettail(buf->b_ffname),
 						   gettail(b0.b0_fname)) != 0
 				    || !same_directory(fname, buf->b_ffname))
-				differ = TRUE;
+			    {
+#ifdef CHECK_INODE
+				/* Symlinks may point to the same file even
+				 * when the name differs, need to check the
+				 * inode too. */
+				expand_env(b0.b0_fname, NameBuff, MAXPATHL);
+				if (fnamecmp_ino(buf->b_ffname, NameBuff,
+						     char_to_long(b0.b0_ino)))
+#endif
+				    differ = TRUE;
+			    }
 			}
 			else
 			{
@@ -3859,7 +3967,7 @@ findswapname(buf, dirp, old_fname)
 			    expand_env(b0.b0_fname, NameBuff, MAXPATHL);
 #ifdef CHECK_INODE
 			    if (fnamecmp_ino(buf->b_ffname, NameBuff,
-					char_to_long(b0.b0_ino)))
+						     char_to_long(b0.b0_ino)))
 				differ = TRUE;
 #else
 			    if (fnamecmp(NameBuff, buf->b_ffname) != 0)
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -4443,6 +4443,29 @@ vim_ispathlistsep(c)
 }
 #endif
 
+/*
+ * Return TRUE if the directory of "fname" exists, FALSE otherwise.
+ * Also returns TRUE if there is no directory name.
+ * "fname" must be writable!.
+ */
+    int
+dir_of_file_exists(fname)
+    char_u	*fname;
+{
+    char_u	*p;
+    int		c;
+    int		retval;
+
+    p = gettail_sep(fname);
+    if (p == fname)
+	return TRUE;
+    c = *p;
+    *p = NUL;
+    retval = mch_isdir(fname);
+    *p = c;
+    return retval;
+}
+
 #if (defined(CASE_INSENSITIVE_FILENAME) && defined(BACKSLASH_IN_FILENAME)) \
 	|| defined(PROTO)
 /*
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -1,93 +1,94 @@
 /* misc1.c */
-int get_indent __ARGS((void));
-int get_indent_lnum __ARGS((linenr_T lnum));
-int get_indent_buf __ARGS((buf_T *buf, linenr_T lnum));
-int get_indent_str __ARGS((char_u *ptr, int ts));
-int set_indent __ARGS((int size, int flags));
-int get_number_indent __ARGS((linenr_T lnum));
-int open_line __ARGS((int dir, int flags, int old_indent));
-int get_leader_len __ARGS((char_u *line, char_u **flags, int backward));
-int plines __ARGS((linenr_T lnum));
-int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight));
-int plines_nofill __ARGS((linenr_T lnum));
-int plines_win_nofill __ARGS((win_T *wp, linenr_T lnum, int winheight));
-int plines_win_nofold __ARGS((win_T *wp, linenr_T lnum));
-int plines_win_col __ARGS((win_T *wp, linenr_T lnum, long column));
-int plines_m_win __ARGS((win_T *wp, linenr_T first, linenr_T last));
-void ins_bytes __ARGS((char_u *p));
-void ins_bytes_len __ARGS((char_u *p, int len));
-void ins_char __ARGS((int c));
-void ins_char_bytes __ARGS((char_u *buf, int charlen));
-void ins_str __ARGS((char_u *s));
-int del_char __ARGS((int fixpos));
-int del_chars __ARGS((long count, int fixpos));
-int del_bytes __ARGS((long count, int fixpos));
-int truncate_line __ARGS((int fixpos));
-void del_lines __ARGS((long nlines, int undo));
-int gchar_pos __ARGS((pos_T *pos));
-int gchar_cursor __ARGS((void));
-void pchar_cursor __ARGS((int c));
-int inindent __ARGS((int extra));
-char_u *skip_to_option_part __ARGS((char_u *p));
-void changed __ARGS((void));
-void changed_bytes __ARGS((linenr_T lnum, colnr_T col));
-void appended_lines __ARGS((linenr_T lnum, long count));
-void appended_lines_mark __ARGS((linenr_T lnum, long count));
-void deleted_lines __ARGS((linenr_T lnum, long count));
-void deleted_lines_mark __ARGS((linenr_T lnum, long count));
-void changed_lines __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra));
-void unchanged __ARGS((buf_T *buf, int ff));
-void check_status __ARGS((buf_T *buf));
-void change_warning __ARGS((int col));
-int ask_yesno __ARGS((char_u *str, int direct));
-int get_keystroke __ARGS((void));
-int get_number __ARGS((int colon, int *mouse_used));
-int prompt_for_number __ARGS((int *mouse_used));
-void msgmore __ARGS((long n));
-void beep_flush __ARGS((void));
-void vim_beep __ARGS((void));
-void init_homedir __ARGS((void));
-void free_homedir __ARGS((void));
-void expand_env __ARGS((char_u *src, char_u *dst, int dstlen));
-void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr));
-char_u *vim_getenv __ARGS((char_u *name, int *mustfree));
-char_u *expand_env_save __ARGS((char_u *src));
-void vim_setenv __ARGS((char_u *name, char_u *val));
-char_u *get_env_name __ARGS((expand_T *xp, int idx));
-void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one));
-char_u *home_replace_save __ARGS((buf_T *buf, char_u *src));
-int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname));
-char_u *gettail __ARGS((char_u *fname));
-char_u *gettail_sep __ARGS((char_u *fname));
-char_u *getnextcomp __ARGS((char_u *fname));
-char_u *get_past_head __ARGS((char_u *path));
-int vim_ispathsep __ARGS((int c));
-int vim_ispathlistsep __ARGS((int c));
-int vim_fnamecmp __ARGS((char_u *x, char_u *y));
-int vim_fnamencmp __ARGS((char_u *x, char_u *y, size_t len));
-char_u *concat_fnames __ARGS((char_u *fname1, char_u *fname2, int sep));
-char_u *concat_str __ARGS((char_u *str1, char_u *str2));
-void add_pathsep __ARGS((char_u *p));
-char_u *FullName_save __ARGS((char_u *fname, int force));
-pos_T *find_start_comment __ARGS((int ind_maxcomment));
-void do_c_expr_indent __ARGS((void));
-int cin_islabel __ARGS((int ind_maxcomment));
-int cin_iscase __ARGS((char_u *s));
-int cin_isscopedecl __ARGS((char_u *s));
-int get_c_indent __ARGS((void));
-int get_expr_indent __ARGS((void));
-int get_lisp_indent __ARGS((void));
-void prepare_to_exit __ARGS((void));
-void preserve_exit __ARGS((void));
-int vim_fexists __ARGS((char_u *fname));
-void line_breakcheck __ARGS((void));
-void fast_breakcheck __ARGS((void));
-int expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
-int match_suffix __ARGS((char_u *fname));
-int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags, int didstar));
-int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
-void addfile __ARGS((garray_T *gap, char_u *f, int flags));
-char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags));
-void FreeWild __ARGS((int count, char_u **files));
-int goto_im __ARGS((void));
+extern int get_indent __ARGS((void));
+extern int get_indent_lnum __ARGS((linenr_T lnum));
+extern int get_indent_buf __ARGS((buf_T *buf, linenr_T lnum));
+extern int get_indent_str __ARGS((char_u *ptr, int ts));
+extern int set_indent __ARGS((int size, int flags));
+extern int get_number_indent __ARGS((linenr_T lnum));
+extern int open_line __ARGS((int dir, int flags, int old_indent));
+extern int get_leader_len __ARGS((char_u *line, char_u **flags, int backward));
+extern int plines __ARGS((linenr_T lnum));
+extern int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight));
+extern int plines_nofill __ARGS((linenr_T lnum));
+extern int plines_win_nofill __ARGS((win_T *wp, linenr_T lnum, int winheight));
+extern int plines_win_nofold __ARGS((win_T *wp, linenr_T lnum));
+extern int plines_win_col __ARGS((win_T *wp, linenr_T lnum, long column));
+extern int plines_m_win __ARGS((win_T *wp, linenr_T first, linenr_T last));
+extern void ins_bytes __ARGS((char_u *p));
+extern void ins_bytes_len __ARGS((char_u *p, int len));
+extern void ins_char __ARGS((int c));
+extern void ins_char_bytes __ARGS((char_u *buf, int charlen));
+extern void ins_str __ARGS((char_u *s));
+extern int del_char __ARGS((int fixpos));
+extern int del_chars __ARGS((long count, int fixpos));
+extern int del_bytes __ARGS((long count, int fixpos));
+extern int truncate_line __ARGS((int fixpos));
+extern void del_lines __ARGS((long nlines, int undo));
+extern int gchar_pos __ARGS((pos_T *pos));
+extern int gchar_cursor __ARGS((void));
+extern void pchar_cursor __ARGS((int c));
+extern int inindent __ARGS((int extra));
+extern char_u *skip_to_option_part __ARGS((char_u *p));
+extern void changed __ARGS((void));
+extern void changed_bytes __ARGS((linenr_T lnum, colnr_T col));
+extern void appended_lines __ARGS((linenr_T lnum, long count));
+extern void appended_lines_mark __ARGS((linenr_T lnum, long count));
+extern void deleted_lines __ARGS((linenr_T lnum, long count));
+extern void deleted_lines_mark __ARGS((linenr_T lnum, long count));
+extern void changed_lines __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra));
+extern void unchanged __ARGS((buf_T *buf, int ff));
+extern void check_status __ARGS((buf_T *buf));
+extern void change_warning __ARGS((int col));
+extern int ask_yesno __ARGS((char_u *str, int direct));
+extern int get_keystroke __ARGS((void));
+extern int get_number __ARGS((int colon, int *mouse_used));
+extern int prompt_for_number __ARGS((int *mouse_used));
+extern void msgmore __ARGS((long n));
+extern void beep_flush __ARGS((void));
+extern void vim_beep __ARGS((void));
+extern void init_homedir __ARGS((void));
+extern void free_homedir __ARGS((void));
+extern void expand_env __ARGS((char_u *src, char_u *dst, int dstlen));
+extern void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr));
+extern char_u *vim_getenv __ARGS((char_u *name, int *mustfree));
+extern char_u *expand_env_save __ARGS((char_u *src));
+extern void vim_setenv __ARGS((char_u *name, char_u *val));
+extern char_u *get_env_name __ARGS((expand_T *xp, int idx));
+extern void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one));
+extern char_u *home_replace_save __ARGS((buf_T *buf, char_u *src));
+extern int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname));
+extern char_u *gettail __ARGS((char_u *fname));
+extern char_u *gettail_sep __ARGS((char_u *fname));
+extern char_u *getnextcomp __ARGS((char_u *fname));
+extern char_u *get_past_head __ARGS((char_u *path));
+extern int vim_ispathsep __ARGS((int c));
+extern int vim_ispathlistsep __ARGS((int c));
+extern int dir_of_file_exists __ARGS((char_u *fname));
+extern int vim_fnamecmp __ARGS((char_u *x, char_u *y));
+extern int vim_fnamencmp __ARGS((char_u *x, char_u *y, size_t len));
+extern char_u *concat_fnames __ARGS((char_u *fname1, char_u *fname2, int sep));
+extern char_u *concat_str __ARGS((char_u *str1, char_u *str2));
+extern void add_pathsep __ARGS((char_u *p));
+extern char_u *FullName_save __ARGS((char_u *fname, int force));
+extern pos_T *find_start_comment __ARGS((int ind_maxcomment));
+extern void do_c_expr_indent __ARGS((void));
+extern int cin_islabel __ARGS((int ind_maxcomment));
+extern int cin_iscase __ARGS((char_u *s));
+extern int cin_isscopedecl __ARGS((char_u *s));
+extern int get_c_indent __ARGS((void));
+extern int get_expr_indent __ARGS((void));
+extern int get_lisp_indent __ARGS((void));
+extern void prepare_to_exit __ARGS((void));
+extern void preserve_exit __ARGS((void));
+extern int vim_fexists __ARGS((char_u *fname));
+extern void line_breakcheck __ARGS((void));
+extern void fast_breakcheck __ARGS((void));
+extern int expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+extern int match_suffix __ARGS((char_u *fname));
+extern int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags, int didstar));
+extern int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+extern void addfile __ARGS((garray_T *gap, char_u *f, int flags));
+extern char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags));
+extern void FreeWild __ARGS((int count, char_u **files));
+extern int goto_im __ARGS((void));
 /* vim: set ft=c : */