changeset 2163:00d8ddf20102

After recovery check if the text changed. If it did mark the buffer as modified.
author Bram Moolenaar <bram@vim.org>
date Sat, 15 May 2010 17:06:53 +0200
parents 071036945d3c
children 733f0dc510c3
files runtime/doc/todo.txt runtime/doc/usr_11.txt runtime/doc/version7.txt src/memline.c src/misc1.c src/proto/misc1.pro
diffstat 6 files changed, 115 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1148,8 +1148,25 @@ Patch for adding "J" flag to 'cinoptions
 
 
 Vim 7.3:
+Patches to include:
 -   Add patch for 'relativenumber' option?  Markus Heidelberg, 2008 Jun 27.
     Update 2010 May 2.
+-   Add blowfish encryption.  Openssl has an implementation.  Also by Paul
+    Kocher (LGPL), close to original.  Mohsin also has some ideas.
+    Take four bytes and turn them into unsigned to avoid byte-order problems.
+    Need to buffer up to 7 bytes to align on 8 byte boundaries.
+    Patch from Moshin: 2010 May 8, addition May 9.
+-   gettabvar() and settabvar() functions. (Yegappan Lakshmanan, 2010 May 14)
+-   Patch to support netbeans in Unix console Vim. (Xavier de Gaye, 2009 Apr
+    26) Now with Mercurial repository (2010 Jan 2)
+- Patch for Lisp support with ECL (Mikael Jansson, 2008 Oct 25)
+- Gvimext patch to support wide file names. (Szabolcs Horvat 2008 Sep 10)
+- Patch to support netbeans for Mac. (Kazuki Sakamoto, 2009 Jun 25)
+- Patch to support clipboard for Mac terminal. (Jjgod Jiang, 2009 Aug 1)
+- Patch to support :browse for more commands. (Lech Lorens, 2009 Jul 18)
+- Patch to add diff functionality to 2html.vim. (Christian Brabandt, 2009 Dec
+  15)
+Needs some work:
 -   Use NSIS 2.45, it includes Windows 7 support.
 	Include "RequestExecutionLevel highest"
 	Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi
@@ -1169,28 +1186,11 @@ 8   Persistent undo: store undo in a fil
     before some time/date can be flushed. 'undopersist' gives maximum time to
     keep undo: "3h", "1d", "2w", "1y", etc.  For the file use dot and
     extension: ".filename.un~" (like swapfile but "un~" instead of "swp").
--   Add blowfish encryption.  Openssl has an implementation.  Also by Paul
-    Kocher (LGPL), close to original.  Mohsin also has some ideas.
-    Take four bytes and turn them into unsigned to avoid byte-order problems.
-    Need to buffer up to 7 bytes to align on 8 byte boundaries.
-    Patch from Moshin: 2010 May 8, addition May 9.
--   gettabvar() and settabvar() functions. (Yegappan Lakshmanan, 2010 May 14)
--   Patch to support netbeans in Unix console Vim. (Xavier de Gaye, 2009 Apr
-    26) Now with Mercurial repository (2010 Jan 2)
 -   ":{range}source": source the lines from the current file.
 	You can already yank lines and use :@" to execute them.
 	Most of do_source() would not be used, need a new function.
 	It's easy when not doing breakpoints or profiling.
-- Patch for Lisp support with ECL (Mikael Jansson, 2008 Oct 25)
-- Gvimext patch to support wide file names. (Szabolcs Horvat 2008 Sep 10)
-- Patch to support netbeans for Mac. (Kazuki Sakamoto, 2009 Jun 25)
-- Patch to support clipboard for Mac terminal. (Jjgod Jiang, 2009 Aug 1)
-- Patch to support :browse for more commands. (Lech Lorens, 2009 Jul 18)
-- Patch to add diff functionality to 2html.vim. (Christian Brabandt, 2009 Dec
-  15)
-- After using ":recover" or recovering a file in another way, ":x" doesn't
-  save what you see.  Mark the buffer as modified?  Only when the text is
-  actually different from the original file.
+Before (beta) release:
 - Add fixes for 7.2 to version7.txt
 
 
--- a/runtime/doc/usr_11.txt
+++ b/runtime/doc/usr_11.txt
@@ -29,29 +29,45 @@ with the "-r" argument added: >
 	vim -r help.txt
 
 Vim will read the swap file (used to store text you were editing) and may read
-bits and pieces of the original file.  If all is well, you will see these
-messages (with different file names, of course):
+bits and pieces of the original file.  If Vim recovered your changes you will
+see these messages (with different file names, of course):
 
 	Using swap file ".help.txt.swp" ~
 	Original file "~/vim/runtime/doc/help.txt" ~
 	Recovery completed. You should check if everything is OK. ~
 	(You might want to write out this file under another name ~
 	and run diff with the original file to check for changes) ~
-	Delete the .swp file afterwards. ~
+	You may want to delete the .swp file now. ~
 
 To be on the safe side, write this file under another name: >
 
 	:write help.txt.recovered
 
 Compare the file with the original file to check if you ended up with what you
-expected.  Vimdiff is very useful for this |08.7|.  Watch out for the original
-file to contain a more recent version (you saved the file just before the
-computer crashed).  And check that no lines are missing (something went wrong
-that Vim could not recover).
+expected.  Vimdiff is very useful for this |08.7|.  For example: >
+
+	:write help.txt.recovered
+	:edit #
+	:diffsp help.txt
+
+Watch out for the original file to contain a more recent version (you saved
+the file just before the computer crashed).  And check that no lines are
+missing (something went wrong that Vim could not recover).
    If Vim produces warning messages when recovering, read them carefully.
 This is rare though.
 
-It's normal that the last few changes can not be recovered.  Vim flushes the
+If the recovery resulted in text that is exactly the same as the file
+contents, you will get this message:
+
+	Using swap file ".help.txt.swp" ~
+	Original file "~/vim/runtime/doc/help.txt" ~
+	Recovery completed. Buffer contents equals file contents. ~
+	You may want to delete the .swp file now. ~
+
+This usually happens if you already recovered your changes, or you wrote the
+file after making changes.  It is safe to delete the swap file now.
+
+It is normal that the last few changes can not be recovered.  Vim flushes the
 changes to disk when you don't type for about four seconds, or after typing
 about two hundred characters.  This is set with the 'updatetime' and
 'updatecount' options.  Thus when Vim didn't get a chance to save itself when
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -7161,6 +7161,11 @@ Changed							*changed-7.3*
 The extra and language files are no longer distributed separately.
 The files for all systems are included in one distribution.
 
+After using ":recover" or recovering a file in another way, ":x" and "ZZ"
+don't save what you see.  This could result in work being lost.  Now the text
+after recovery is compared to the original file contents.  When they differ
+the buffer is marked as modified.
+
 
 Added							*added-7.3*
 -----
--- a/src/memline.c
+++ b/src/memline.c
@@ -870,6 +870,7 @@ ml_recover()
     int		serious_error = TRUE;
     long	mtime;
     int		attr;
+    int		orig_file_status = NOTDONE;
 
     recoverymode = TRUE;
     called_from_main = (curbuf->b_ml.ml_mfp == NULL);
@@ -1119,12 +1120,8 @@ ml_recover()
      * 'fileencoding', etc.  Ignore errors.  The text itself is not used.
      */
     if (curbuf->b_ffname != NULL)
-    {
-	(void)readfile(curbuf->b_ffname, NULL, (linenr_T)0,
+	orig_file_status = readfile(curbuf->b_ffname, NULL, (linenr_T)0,
 			      (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
-	while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
-	    ml_delete((linenr_T)1, FALSE);
-    }
 
     /* Use the 'fileformat' and 'fileencoding' as stored in the swap file. */
     if (b0_ff != 0)
@@ -1325,10 +1322,46 @@ ml_recover()
     }
 
     /*
-     * The dummy line from the empty buffer will now be after the last line in
-     * the buffer. Delete it.
+     * Compare the buffer contents with the original file.  When they differ
+     * set the 'modified' flag.
+     * Lines 1 - lnum are the new contents.
+     * Lines lnum + 1 to ml_line_count are the original contents.
+     * Line ml_line_count + 1 in the dummy empty line.
      */
-    ml_delete(curbuf->b_ml.ml_line_count, FALSE);
+    if (orig_file_status != OK || curbuf->b_ml.ml_line_count != lnum * 2 + 1)
+    {
+	/* Recovering an empty file results in two lines and the first line is
+	 * empty.  Don't set the modified flag then. */
+	if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL))
+	{
+	    changed_int();
+	    ++curbuf->b_changedtick;
+	}
+    }
+    else
+    {
+	for (idx = 1; idx <= lnum; ++idx)
+	{
+	    /* Need to copy one line, fetching the other one may flush it. */
+	    p = vim_strsave(ml_get(idx));
+	    i = STRCMP(p, ml_get(idx + lnum));
+	    vim_free(p);
+	    if (i != 0)
+	    {
+		changed_int();
+		++curbuf->b_changedtick;
+		break;
+	    }
+	}
+    }
+
+    /*
+     * Delete the lines from the original file and the dummy line from the
+     * empty buffer.  These will now be after the last line in the buffer.
+     */
+    while (curbuf->b_ml.ml_line_count > lnum
+				       && !(curbuf->b_ml.ml_flags & ML_EMPTY))
+	ml_delete(curbuf->b_ml.ml_line_count, FALSE);
     curbuf->b_flags |= BF_RECOVERED;
 
     recoverymode = FALSE;
@@ -1345,10 +1378,15 @@ ml_recover()
     }
     else
     {
-	MSG(_("Recovery completed. You should check if everything is OK."));
-	MSG_PUTS(_("\n(You might want to write out this file under another name\n"));
-	MSG_PUTS(_("and run diff with the original file to check for changes)\n"));
-	MSG_PUTS(_("Delete the .swp file afterwards.\n\n"));
+	if (curbuf->b_changed)
+	{
+	    MSG(_("Recovery completed. You should check if everything is OK."));
+	    MSG_PUTS(_("\n(You might want to write out this file under another name\n"));
+	    MSG_PUTS(_("and run diff with the original file to check for changes)"));
+	}
+	else
+	    MSG(_("Recovery completed. Buffer contents equals file contents."));
+	MSG_PUTS(_("\nYou may want to delete the .swp file now.\n\n"));
 	cmdline_row = msg_row;
     }
     redraw_curbuf_later(NOT_VALID);
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2514,17 +2514,26 @@ changed()
 		msg_scroll = save_msg_scroll;
 	    }
 	}
-	curbuf->b_changed = TRUE;
-	ml_setflags(curbuf);
+	changed_int();
+    }
+    ++curbuf->b_changedtick;
+}
+
+/*
+ * Internal part of changed(), no user interaction.
+ */
+    void
+changed_int()
+{
+    curbuf->b_changed = TRUE;
+    ml_setflags(curbuf);
 #ifdef FEAT_WINDOWS
-	check_status(curbuf);
-	redraw_tabline = TRUE;
+    check_status(curbuf);
+    redraw_tabline = TRUE;
 #endif
 #ifdef FEAT_TITLE
-	need_maketitle = TRUE;	    /* set window title later */
-#endif
-    }
-    ++curbuf->b_changedtick;
+    need_maketitle = TRUE;	    /* set window title later */
+#endif
 }
 
 static void changedOneline __ARGS((buf_T *buf, linenr_T lnum));
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -30,6 +30,7 @@ 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_int __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));