Major rewrite to behave more like a minor mode.
[bpt/emacs.git] / lisp / ediff.el
index fdd8605..88bc230 100644 (file)
@@ -3,16 +3,11 @@
 
 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
 ;; Created: February 2, 1994
-;; Version: 1.64
+;; Version: 1.65c
 ;; Keywords: comparing, merging, patching, version control.
 
 ;; This file is part of GNU Emacs.
 
-;; LCD Archive Entry:
-;; ediff|Michael Kifer|kifer@cs.sunysb.edu|
-;; Visual interface to diff and patch.|
-;; 28-June-94|1.64|~/packages/ediff.el.Z|
-
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; which regexps are being used, the status command, `i', will supply
 ;; the requisite information.
 ;;
+;; In addition to the ability to ignore regions that match regular
+;; expressions, Ediff can be ordered to start skipping over certain
+;; `inessential' regions. This is controlled by the variable
+;;
+;;      ediff-ignore-similar-regions
+;;
+;; which, if set to t, will cause Ediff to skip over difference regions
+;; that has been found similar, i.e., where the only differences are those
+;; in the white space and newlines.
+;;
+;; Note: In order for this feature to work, auto-refining of difference
+;; regions must be on, since otherwise Ediff won't know if there are no
+;; fine differences between regions. Under X, auto-refining is a default,
+;; but it is nixed on a dumb terminal or in an Xterm window. Therefore, in
+;; a non-windowing environment, the user must explicitly turn
+;; auto-refining on (e.g., by typing `@').
+;;
+;; CAUTION: If many inessential regions appear in a row, Ediff may take a
+;; long time to jump to the next region because it has to compute fine
+;; differences of all intermediate regions.
+;;
 ;;
 ;; Highlighting difference regions
 ;; -------------------------------
 ;; faces: ediff-even/odd-diff-face-A/B.   The odd and the even
 ;; faces are actually identical on monochrome displays, because it is
 ;; rather poor in what you can do on such a display. So, I chose to use
-;; italics to highlight other differences. Any ideas would be welcome. (In
-;; Lucid Emacs, the faces are different because it supports pixmaps.)
+;; italics to highlight other differences. Any ideas would be welcome.
 ;; There are two ways to change the default setting for highlighting faces:
 ;; either change the variables, as in
 ;;
-;; (setq ediff-current-diff-face-A (internal-get-face 'bold-italic))
+;; (setq ediff-current-diff-face-A 'bold-italic)
+;;
+;; or
+;;
+;; (setq ediff-current-diff-face-A
+;;      (copy-face 'bold-italic 'ediff-current-diff-face-A))
 ;;
-;; (`internal-get-face' should be `get-face' if you are using Lucid Emacs)
 ;; or by selectively modifying the defaults:
 ;;
 ;; (add-hook 'ediff-load-hooks
 ;; You may also want to take a look at how the above faces are defined in
 ;; Ediff. 
 ;;
+;; Note: it is not recommended to use `internal-get-face' (or `get-face' in
+;;      Lucid) when defining faces for Ediff, since this may cause
+;;      problems when there are several frames with different font sizes.
+;;       Instead, use copy-face or set/make-face-* as shown above.
+;;
 ;; The last group of variables in this group,
 ;;
 ;;         ediff-want-faces
 ;;
 ;; Refining difference regions
 ;; ---------------------------
-;; There are also variables that control the way fine differences are
-;; highlighted. This feature lets the user highlight the exact words that
+;; Ediff has variables that control the way fine differences are
+;; highlighted. This feature lets the user highlight the exact words that 
 ;; make the difference regions in buffer A and B different. This process
 ;; ignores spaces, tabs, and newlines.
 ;;
 ;; diff to ignore spaces and such. Use the option '-w' for that. Diff
 ;; has several other useful options (type 'man diff' to find out).
 ;;
-;; The output from diff is found in *ediff-diff* buffer.  However, this
-;; makes sense only if you also intend to use Ediff to browse through the
-;; diff'ed files before sending the patch.  This is because diff.el is much
-;; faster in yielding the output of diff  (Ediff is a big gun, if used
-;; for this simple purpose).
+;; The output from diff is found in *ediff-diff* buffer, which you can save.
+;; However, using Ediff for producing a diff output makes sense only if you
+;; also intend to use Ediff to browse through the diff'ed files before
+;; sending the patch.  This is because diff.el, which also comes with
+;; Emacs, is much faster in yielding the output of diff  (Ediff is a big
+;; gun, if used for this simple purpose).
+;;
+;; Mode line
+;; ---------
+;;
+;; When Ediff is running, the mode line of Ediff Control Panel buffer
+;; displays the current difference being displayed and the total number of
+;; difference regions in the two files. 
+;;
+;; The mode line of the buffers being compared displays the type of the
+;; buffer (`A:' or `B:') and (usually) the file name. Ediff is trying to be
+;; intelligent in choosing mode line buffer identification. In particular,
+;; it works well with uniquify.el and mode-line.el packages (which improve
+;; on the default way in which Emacs displays buffer identification).
+;; If you don't like the way Ediff identifies its buffers, there is always
+;; ediff-prepare-buffer-hooks, which can be used to modify the mode line.
 ;;
 ;; Miscellaneous
 ;; -------------
 ;;
 ;; The total number of differences and the current difference number are
 ;; always displayed in the mode line of the control window. 
+;;
+;; If, after making changes to buffers A and B, you decide to save them, it
+;; is recommended to use `ediff-save-buffer', which is bound to `wa' and
+;; `wb' (`wa will save buffer A and `wb' saves buffer B).
+;;
+;; Typing `wf' will also save the diff output in a file. 
 
 ;;; Display Modes
 ;;  -------------
 
 ;; Sat April 16, 1994
 
-;;     Added Ediff to the File menu on the menu bar (version).
+;;     Added Ediff to the File menu on the menu bar (FSF's version).
 
 ;; Mon April 18, 1994
 
 
 ;;     Fixed ediff-patch-files to work with remote and compressed files.
 
+;; Wed July 20, 1994
+
+;;     Changed menu bar items per RMS's suggestion. Changed odd/even faces
+;;     in Lemacs to italic.  Changed ediff-*-face-* variables so that they
+;;     will contain names of faces instead of the face internal
+;;     representation.  (Copy-face works better with face names than with
+;;     face internal representation.  With face internal representation, if
+;;     a face vector mentions a font explicitly, copy-face may attempt to
+;;     copy this font, which would cause an error if the font has a wrong
+;;     size for one of the existing frames.)  Improved the way
+;;     mode-line-buffer-identification is set in ediff-setup so that Ediff
+;;     will accommodate the way buffers are identified in mode-line.el and
+;;     uniquify.el.
+
+;; Fri August 5, 1994
+
+;;     Ediff can now automatically skip over regions that differ only in
+;;     the white space and line breaks. This is controled with the variable
+;;     `ediff-ignore-similar-regions' and can be toggled on/off by typing
+;;     `##'.
+
+;; Mon August 8, 1994
+
+;;     If ediff-save-buffer is invoked with `wf', it'll save the diff
+;;     output in a file.
+
 
 ;;; Acknowledgements:
 
 ;; <maechler@stat.math.ethz.ch>, Richard Mlynarik <mly@adoc.xerox.com>,
 ;; Ray Nickson <nickson@cs.uq.oz.au>, Sandy Rutherford
 ;; <sandy@ibm550.sissa.it>,  Andy Scott <ascott@pcocd2.intel.com>,
-;; Richard Stanton <stanton@haas.berkeley.edu>, Peter Stout 
-;; <Peter_Stout@cs.cmu.edu>  for contributing ideas, patches and bug reports. 
+;; Richard Stallman <rms@gnu.ai.mit.edu>, Richard Stanton 
+;; <stanton@haas.berkeley.edu>, Peter Stout <Peter_Stout@cs.cmu.edu>
+;; for contributing ideas, patches, and bug reports. 
 ;;
 ;; Thanks also to many others who felt obliged to drop a thanks note.
 
 (defmacro ediff-get-difference (n)
   (` (aref ediff-difference-vector (, n))))
   
+;; tell if it has been previously found that the region doesn't
+;; contain diffs other than the white space and newlines
+;; The argument, N, is the diff region number used by Ediff to index the
+;; diff vector. It is 1 less than the number seen by the user.
+(defmacro ediff-no-fine-diffs (n)
+  (` (aref (ediff-get-difference n) 3)))
+  
 (defmacro ediff-get-diff-overlay-from-vector (vec buf-type)
   (` (aref (, vec)
           (cond ((eq (, buf-type) 'A) 0)
       
 (defmacro ediff-set-fine-diff-vector (n fine-vec)
   (` (aset (ediff-get-difference (, n)) 2 (, fine-vec))))
+
+;; if flag is t, puts a mark on diff region saying that 
+;; the differences are in white space only. If flag is nil,
+;; the region is marked as essential (i.e., differences are
+;; not just in the white space and newlines.)
+(defmacro ediff-mark-diff-as-space-only (n flag)
+  (` (aset (ediff-get-difference (, n)) 3 (, flag))))
   
 (defmacro ediff-get-fine-diff-vector (n)
   (` (ediff-get-fine-diff-vector-from-vec (ediff-get-difference (, n)))))
   
+  
 (defmacro ediff-defvar-local (var value doc) 
   "Defines SYMBOL as an advertised local variable.  
 Performs a defvar, then executes `make-variable-buffer-local' on
@@ -996,19 +1084,6 @@ Commands:
   (setq major-mode 'ediff-mode)
   (setq mode-name "Ediff"))
 
-(defvar ediff-version "1.64"
-  "The current version of Ediff.")
-(defvar ediff-date "June 28, 1994"
-  "Date of last update.")  
-
-(defun ediff-version ()
-  "Return string describing the version of Ediff.
-When called interactively, displays the version."
-  (interactive)
-  (if (interactive-p)
-      (message "Ediff version %s" (ediff-version))
-    ediff-version))
-
 
 ;; Hook variables
 
@@ -1038,16 +1113,21 @@ on ediff-quit or ediff-suspend.")
 ;; Help messages
 
 (defconst ediff-help-message-long
-  "p,DEL - prev diff      v/V - scroll up/dn   ab - diff A to B  * - refine diff
-n,SPC - next diff      </> - scroll lt/rt   ba - diff B to A  ! - recomp diffs
-    j - jump to diff     s - toggle split   ra - restore A    i - status info
-ga/gb - goto pt in A/B   h - toggle hilit   rb - restore B    z - suspend Ediff
-    c - recenter         @ - toggle refine                    q - quit Ediff
-                     #f/#h - toggle focus/hide diff regions
-wa/wb - save buf A/B   A/B - toggle read-only in buffers A/B  ? - toggle help")
+  "    Moving around      |     Toggling features     |       Miscellaneous
+=======================|===========================|===========================
+p,DEL -previous diff   |     s -vert/horiz split   | ab/ba -copy diff A->B/B->A
+n,SPC -next diff       |     h -hiliting           | ra/rb -restore diff in A/B
+    j -jump to diff    |     @ -auto-refining      |     * -refine diff
+ga/gb -to point in A/B |---------------------------|     ! -recompute diffs
+    c -recenter        |    ## -skip whitespace    |---------------------------
+  v/V -scroll up/down  | #f/#h -focus/hide regions | wa/wb -save buf A/B
+  </> -scroll lft/rght |   A/B -read-only buf A/B  |    wf -save diff output
+=======================|===========================|===========================
+    i -status info     |     ? -toggle help window |   z/q -suspend/quit Ediff"
+  )
                          
 (defconst ediff-help-message-short
-  "                       ? - toggle help window")                       
+  "                             ? - toggle help window")
 
 (defvar ediff-help-message ediff-help-message-long
   "*The actual help message.")
@@ -1093,17 +1173,21 @@ See `ediff-word-1' for more details.")
 
 ;; Selective browsing
 
-(defconst ediff-skip-diff-region-function 'ediff-show-all-diffs
-  "Function that determines the next/previous diff region to show.")
+(ediff-defvar-local ediff-skip-diff-region-function 'ediff-show-all-diffs
+  "Function that determines the next/previous diff region to show.
+Should return t for regions to be ignored and nil otherwise.
+This function gets a region number as an argument. The region number
+is the one used internally by Ediff. It is 1 less than the number seen
+by the user.")
 
-(defconst ediff-regexp-focus-A ""
+(ediff-defvar-local ediff-regexp-focus-A ""
   "Regexp that determines buf A regions to focus on when skipping to diff.")
-(defconst ediff-regexp-focus-B ""
+(ediff-defvar-local ediff-regexp-focus-B ""
   "Regexp that determines buf B regions to focus on when skipping to diff.")
   
-(defconst ediff-regexp-hide-A ""
+(ediff-defvar-local ediff-regexp-hide-A ""
   "Regexp that determines buf A regions to ignore when skipping to diff.")
-(defconst ediff-regexp-hide-B ""
+(ediff-defvar-local ediff-regexp-hide-B ""
   "Regexp that determines buf B regions to ignore when skipping to diff.")  
   
 
@@ -1210,7 +1294,7 @@ This variable must be set before Ediff is loaded. If you don't like the
 look of the default menus, set this variable to nil and make your own
 menus.")  
 
-(ediff-defvar-local ediff-auto-refine 'on
+(ediff-defvar-local ediff-auto-refine (if window-system 'on 'nix)
   "If `'on', Ediff auto-highlights fine diffs for the current diff region.
 If `off', auto-highlighting is not used. If `'nix', no fine diffs are shown
 at all, unless the user force-refines the region by hitting `*'.
@@ -1218,6 +1302,9 @@ at all, unless the user force-refines the region by hitting `*'.
 This variable can be set either in .emacs or toggled interactively, using
 ediff-toggle-hilit.") 
 
+(ediff-defvar-local ediff-ignore-similar-regions nil
+  "*If t, skip over difference regions that differ only in the white space and line breaks.")
+
 (ediff-defvar-local ediff-auto-refine-limit 700
   "Auto-refine only those regions that are smaller than this number of bytes.")
 
@@ -1280,6 +1367,8 @@ overlay's endpoints coincide. ")
 (ediff-defvar-local ediff-diff-buffer nil
   "Buffer containing the output of diff, which is used by Ediff to step
 through files.")
+(ediff-defvar-local ediff-fine-diff-buffer nil
+  "Buffer used for diff-style fine differences between regions.")
 (ediff-defvar-local ediff-tmp-buffer nil
   "Temporary buffer used for computing fine differences.")
 (ediff-defvar-local ediff-error-buffer nil
@@ -1291,12 +1380,7 @@ through files.")
 (defvar ediff-disturbed-overlays nil
   "List of difference overlays disturbed by working with the current diff.")
   
-(defvar ediff-shaded-overlay-priority 
-  (if (ediff-if-lucid)
-      (1+ mouse-highlight-priority)
-    100)       ;; 100 is a kludge. There is a bug in insert-in-front-hooks
-               ;; in Emacs < 19.23. When this is fixed, I will get rid of
-               ;; this kludge.
+(defvar ediff-shaded-overlay-priority  100
   "Priority of non-selected overlays.")
 
 
@@ -1350,7 +1434,7 @@ through files.")
 (if (not window-system)
     ()
   (defun ediff-set-face (ground face color)
-    "Sets face foreground/background. If color unavailable, guides the user."
+    "Sets face foreground/background."
     (if (ediff-valid-color-p color)
        (if (eq ground 'foreground)
            (set-face-foreground face color)
@@ -1381,7 +1465,8 @@ through files.")
                     (copy-face 'modeline 'ediff-current-diff-face-A)
                   (copy-face 'highlight 'ediff-current-diff-face-A))
                 )))
-      (ediff-get-face 'ediff-current-diff-face-A))
+      'ediff-current-diff-face-A)
+      ;;(ediff-get-face 'ediff-current-diff-face-A))
     "Face for highlighting the selected difference in buffer A.")
 
   (defvar ediff-current-diff-face-B
@@ -1398,7 +1483,8 @@ through files.")
                     (copy-face 'modeline 'ediff-current-diff-face-B)
                   (copy-face 'highlight 'ediff-current-diff-face-B))
                 )))
-      (ediff-get-face 'ediff-current-diff-face-B))
+      'ediff-current-diff-face-B)
+      ;;(ediff-get-face 'ediff-current-diff-face-B))
     "Face for highlighting the selected difference in buffer B.")
 
   (defvar ediff-fine-diff-face-A
@@ -1411,7 +1497,8 @@ through files.")
                 (ediff-set-face 'background 'ediff-fine-diff-face-A
                                 "sky blue"))
                (t (set-face-underline-p 'ediff-fine-diff-face-A t))))
-      (ediff-get-face 'ediff-fine-diff-face-A))
+      'ediff-fine-diff-face-A)
+      ;;(ediff-get-face 'ediff-fine-diff-face-A))
     "Face for highlighting the refinement of the selected diff in buffer A.")
 
   (defvar ediff-fine-diff-face-B
@@ -1422,7 +1509,8 @@ through files.")
                 (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
                 (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
                (t (set-face-underline-p 'ediff-fine-diff-face-B t))))
-      (ediff-get-face 'ediff-fine-diff-face-B))
+      'ediff-fine-diff-face-B)
+      ;;(ediff-get-face 'ediff-fine-diff-face-B))
     "Face for highlighting the refinement of the selected diff in buffer B.")
 
 
@@ -1436,12 +1524,9 @@ through files.")
                 (ediff-set-face
                  'background 'ediff-even-diff-face-A "light grey"))
                (t 
-                (if (ediff-if-lucid)
-                    (progn
-                      (copy-face 'highlight 'ediff-even-diff-face-A)
-                      (invert-face 'ediff-even-diff-face-A))
-                  (copy-face 'italic 'ediff-even-diff-face-A)))))
-      (ediff-get-face 'ediff-even-diff-face-A))
+                (copy-face 'italic 'ediff-even-diff-face-A))))
+      'ediff-even-diff-face-A)
+      ;;(ediff-get-face 'ediff-even-diff-face-A))
     "Face used to highlight even-numbered differences in buffer A.")
       
   (defvar ediff-even-diff-face-B
@@ -1454,10 +1539,9 @@ through files.")
                 (ediff-set-face
                  'background 'ediff-even-diff-face-B "Gray"))
                (t 
-                (if (ediff-if-lucid)
-                    (copy-face 'highlight 'ediff-even-diff-face-B)
-                  (copy-face 'italic 'ediff-even-diff-face-B)))))
-      (ediff-get-face 'ediff-even-diff-face-B))
+                (copy-face 'italic 'ediff-even-diff-face-B))))
+      'ediff-even-diff-face-B)
+      ;;(ediff-get-face 'ediff-even-diff-face-B))
     "Face used to highlight even-numbered differences in buffer B.")
   
   (defvar ediff-odd-diff-face-A
@@ -1470,10 +1554,9 @@ through files.")
                 (ediff-set-face
                  'background 'ediff-odd-diff-face-A "Gray"))
                (t 
-                (if (ediff-if-lucid)
-                    (copy-face 'highlight 'ediff-odd-diff-face-A)
-                  (copy-face 'italic 'ediff-odd-diff-face-A)))))
-      (ediff-get-face 'ediff-odd-diff-face-A))
+                (copy-face 'italic 'ediff-odd-diff-face-A))))
+      'ediff-odd-diff-face-A)
+      ;;(ediff-get-face 'ediff-odd-diff-face-A))
     "Face used to highlight odd-numbered differences in buffer A.")
       
   (defvar ediff-odd-diff-face-B
@@ -1486,12 +1569,9 @@ through files.")
                 (ediff-set-face
                  'background 'ediff-odd-diff-face-B "light grey"))
                (t 
-                (if (ediff-if-lucid)
-                    (progn
-                      (copy-face 'highlight 'ediff-odd-diff-face-B)
-                      (invert-face 'ediff-odd-diff-face-B))
-                  (copy-face 'italic 'ediff-odd-diff-face-B)))))
-      (ediff-get-face 'ediff-odd-diff-face-B))
+                (copy-face 'italic 'ediff-odd-diff-face-B))))
+      'ediff-odd-diff-face-B)
+      ;;(ediff-get-face 'ediff-odd-diff-face-B))
     "Face used to highlight odd-numbered differences in buffer B.")
 
   ;; Create *-var faces. These are the actual faces used to highlight
@@ -1526,9 +1606,9 @@ through files.")
   ;;; Overlays
 
   (ediff-defvar-local ediff-current-diff-overlay-A nil
-    "Overlay in buffer A.")
+    "Overlay specifying the current difference region in buffer A.")
   (ediff-defvar-local ediff-current-diff-overlay-B nil
-    "Overlay in buffer B.")
+    "Overlay specifying the current difference region in buffer B.")
   
   (defun ediff-make-current-diff-overlay (type)
       (let ((overlay (if (eq type 'A)
@@ -1543,12 +1623,12 @@ through files.")
        (ediff-overlay-put (eval overlay) 'ediff ediff-control-buffer)
        ))
        
-  ;; Computes priority of ediff overlay.
+  ;; Compute priority of ediff overlay.
   (defun ediff-highest-priority (start end buffer)
     (let ((pos (max 1 (1- start)))
          ovr-list)
       (if (ediff-if-lucid)
-         (+ 2 mouse-highlight-priority)
+         (1+ ediff-shaded-overlay-priority)
        (ediff-eval-in-buffer
         buffer
         (while (< pos (min (point-max) (1+ end)))
@@ -1644,45 +1724,52 @@ Do not start with `~/' or `~user-name/'.")
 ;;; They only do something in loaddefs.el.
 ;;;###autoload
 (if purify-flag
-  (defvar menu-bar-epatch-menu
-    (make-sparse-keymap "Epatch"))
-  (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
-  (defvar menu-bar-ediff-menu (make-sparse-keymap "Ediff"))
-  (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu)))
+    (progn
+      (defvar menu-bar-epatch-menu (make-sparse-keymap "Epatch"))
+      (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
+      (defvar menu-bar-ediff-menu (make-sparse-keymap "Ediff"))
+      (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))))
 
 
 ;;;###autoload
 (if purify-flag
-  (define-key menu-bar-ediff-menu [rcs-ediff]
-    '("Compare with a version via RCS ..." . rcs-ediff))
-  (define-key menu-bar-ediff-menu [vc-ediff]
-    '("Compare with a version via VC ..." . vc-ediff))
-  (define-key menu-bar-ediff-menu [ediff-buffers]
-    '("Compare buffers ..." . ediff-buffers))
-  (define-key menu-bar-ediff-menu [ediff-files]
-    '("Compare files ..." . ediff-files)))
+    (progn
+      (define-key menu-bar-ediff-menu [rcs-ediff]
+       '("File with a version via RCS ..." . rcs-ediff))
+      (define-key menu-bar-ediff-menu [vc-ediff]
+       '("File with a version via VC ..." . vc-ediff))
+      (define-key menu-bar-ediff-menu [ediff-buffers]
+       '("Buffers ..." . ediff-buffers))
+      (define-key menu-bar-ediff-menu [ediff-files]
+       '("Files ..." . ediff-files))))
 
 ;;;###autoload
 (if purify-flag
-  (define-key menu-bar-epatch-menu [ediff-patch-buffer]
-    '("To a Buffer ..." . ediff-patch-buffer))
-  (define-key menu-bar-epatch-menu [ediff-patch-file]
-    '("To a File ..." . ediff-patch-file)))
+    (progn
+      (define-key menu-bar-epatch-menu [ediff-patch-buffer]
+       '("To a Buffer ..." . ediff-patch-buffer))
+      (define-key menu-bar-epatch-menu [ediff-patch-file]
+       '("To a File ..." . ediff-patch-file))))
+       
+(define-key menu-bar-file-menu [epatch]
+  '("Apply Patch" . menu-bar-epatch-menu))
+(define-key menu-bar-file-menu [ediff]
+  '("Compare" . menu-bar-ediff-menu))
 
 (if (and window-system ediff-want-default-menus (ediff-frame-has-menubar)
         (ediff-if-lucid))
     (progn  ;; Lucid menu bars
       (defvar ediff-menu
        '(""
-         ["Compare files ..."  ediff-files t]
-         ["Compare buffers ..." ediff-buffers t]
-         ["Compare with a version via VC ..."  vc-ediff t]
-         ["Compare with a version via RCS ..."  rcs-ediff t]))
+         ["Files ..."  ediff-files t]
+         ["Buffers ..." ediff-buffers t]
+         ["File with a version via VC ..."  vc-ediff t]
+         ["File with a version via RCS ..."  rcs-ediff t]))
       (defvar epatch-menu
        '(""
          ["To a file ..."  ediff-patch-file t]
          ["To a buffer ..." ediff-patch-buffer t]))
-      (add-menu '("File") "Compare files
+      (add-menu '("File") "Compare" 
                ediff-menu
                "New Screen")
       (add-menu '("File") "Apply Patch" 
@@ -1692,6 +1779,7 @@ Do not start with `~/' or `~user-name/'.")
       (add-menu-item '("File") "---" nil nil "New Screen")))
 
 
+
 (defun ediff-setup-keymap ()
   "Set up the keymap used in the control buffer of Ediff."
   (setq ediff-mode-map (make-sparse-keymap))
@@ -1734,14 +1822,16 @@ Do not start with `~/' or `~user-name/'.")
   (define-key ediff-mode-map "#"  nil)
   (define-key ediff-mode-map "#h"  'ediff-toggle-regexp-match)
   (define-key ediff-mode-map "#f"  'ediff-toggle-regexp-match)
+  (define-key ediff-mode-map "##"  'ediff-toggle-skip-similar)
   (define-key ediff-mode-map "o"   nil)
   (define-key ediff-mode-map "A"  'ediff-toggle-read-only)
   (define-key ediff-mode-map "B"  'ediff-toggle-read-only)
   (define-key ediff-mode-map "w"   nil)
   (define-key ediff-mode-map "wa"  'ediff-save-buffer)
   (define-key ediff-mode-map "wb"  'ediff-save-buffer)
+  (define-key ediff-mode-map "wf"  'ediff-save-buffer)
   (define-key ediff-mode-map "k"   nil)
-  (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ;; for debug
+  (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ;; for debugging
   ;; Allow ediff-mode-map to be referenced indirectly
   (fset 'ediff-mode-map ediff-mode-map))
 
@@ -1780,7 +1870,8 @@ Arguments: (file buffer &optional last-dir hooks)"
            (set hooks-var (cons (` (lambda () (delete-file (, file))))
                                 (eval hooks-var))))
           ;; file processed via auto-mode-alist, a la uncompress.el
-          ((not (equal (expand-file-name file) (buffer-file-name)))
+          ((not (equal (file-truename file)
+                       (file-truename (buffer-file-name))))
            (setq file (ediff-make-temp-file))
            (set hooks-var (cons (` (lambda () (delete-file (, file))))
                                 (eval hooks-var))))
@@ -1855,24 +1946,38 @@ Else, read patch file into a new buffer."
      ;; These won't run if there are errors in diff
      (ediff-eval-in-buffer
       ediff-A-buffer
-      (run-hooks 'ediff-prepare-buffer-hooks)
       (add-hook 'local-write-file-hooks 'ediff-block-write-file)
       (setq before-change-function 'ediff-before-change-guard)
       ;; add control-buffer to the list of sessions
       (or (memq control-buffer ediff-this-buffer-control-sessions)
          (setq ediff-this-buffer-control-sessions
                (cons control-buffer ediff-this-buffer-control-sessions)))
-      (setq mode-line-buffer-identification '("A: %b")))
+      (setq mode-line-buffer-identification
+           (cons "A: "
+                 (if (string-match "\\(^ \\|^[^ \t]*: \\)"
+                                   (car mode-line-buffer-identification))
+                     (cons (substring (car mode-line-buffer-identification)
+                                      (match-end 0))
+                           (cdr mode-line-buffer-identification))
+                   mode-line-buffer-identification)))
+      (run-hooks 'ediff-prepare-buffer-hooks))
      (ediff-eval-in-buffer
       ediff-B-buffer
-      (run-hooks 'ediff-prepare-buffer-hooks)
       (add-hook 'local-write-file-hooks 'ediff-block-write-file)
       (setq before-change-function 'ediff-before-change-guard)
       ;; add control-buffer to the list of sessions
       (or (memq control-buffer ediff-this-buffer-control-sessions)
          (setq ediff-this-buffer-control-sessions
                (cons control-buffer ediff-this-buffer-control-sessions)))
-      (setq mode-line-buffer-identification '("B: %b")))
+      (setq mode-line-buffer-identification
+           (cons "B: "
+                 (if (string-match "\\(^ \\|^[^ \t]*: \\)"
+                                   (car mode-line-buffer-identification))
+                     (cons (substring (car mode-line-buffer-identification)
+                                      (match-end 0))
+                           (cdr mode-line-buffer-identification))
+                   mode-line-buffer-identification)))
+      (run-hooks 'ediff-prepare-buffer-hooks))
 
      (ediff-eval-in-buffer control-buffer
                            (run-hooks 'startup-hooks 'ediff-startup-hooks)
@@ -1892,9 +1997,13 @@ Else, read patch file into a new buffer."
                     
   (or use-old (setq ediff-diff-buffer 
                    (get-buffer-create
-                    (emerge-unique-buffer-name "*ediff-diff" "*"))))
+                    (emerge-unique-buffer-name "*ediff-diff" "*"))
+                   ediff-fine-diff-buffer
+                   (get-buffer-create
+                    (emerge-unique-buffer-name "*ediff-fine-diff" "*"))
+                   ))
   (ediff-eval-in-buffer
-   ediff-diff-buffer
+   (if refine-region ediff-fine-diff-buffer ediff-diff-buffer)
    (erase-buffer)
    ;; shell-command tends to display old shell command buffers even when it
    ;; puts output in another buffer---probably an Emacs bug.
@@ -1910,28 +2019,30 @@ Else, read patch file into a new buffer."
              (ediff-protect-metachars file-B))
       t)
      ))
-  (ediff-prepare-error-list diff-ok-lines-regexp)
-  (if refine-region
-      (message "Refining difference region %d ... Done." (1+ refine-region))
-    (message "Computing differences ... Done.")(sit-for .5))
+  
+   
   (if refine-region
-      (ediff-convert-diffs-to-overlays-refine
-       ediff-A-buffer ediff-B-buffer
-       (ediff-extract-diffs ediff-diff-buffer)
-       refine-region)
+      (progn
+       (ediff-prepare-error-list diff-ok-lines-regexp ediff-fine-diff-buffer)
+       (message "Refining difference region %d ... Done." (1+ refine-region))
+       (ediff-convert-diffs-to-overlays-refine
+        ediff-A-buffer ediff-B-buffer
+        (ediff-extract-diffs ediff-fine-diff-buffer)
+        refine-region))
+    (ediff-prepare-error-list diff-ok-lines-regexp ediff-diff-buffer)
+    (message "Computing differences ... Done.")(sit-for .5)
     (ediff-convert-diffs-to-overlays
      ediff-A-buffer ediff-B-buffer
-     (ediff-extract-diffs ediff-diff-buffer ediff-A-buffer ediff-B-buffer)))
-  )
+     (ediff-extract-diffs ediff-diff-buffer
+                         ediff-A-buffer ediff-B-buffer))))
   
     
-(defun ediff-prepare-error-list (ok-regexp)
-  (let ((diff-buff ediff-diff-buffer))
+(defun ediff-prepare-error-list (ok-regexp diff-buff)
     (ediff-eval-in-buffer
      ediff-error-buffer
      (erase-buffer)
      (insert-buffer diff-buff)
-     (delete-matching-lines ok-regexp))))
+     (delete-matching-lines ok-regexp)))
 
 ;;; Function to start Ediff by patching a file
 
@@ -1974,8 +2085,8 @@ Else, read patch file into a new buffer."
 
     ;; Check if source file name has triggered black magic, such as file name
     ;; handlers or auto mode alist, and make a note of it.
-    (setq file-name-magic-p (not (equal (expand-file-name true-source-filename)
-                                       (expand-file-name source-filename))))
+    (setq file-name-magic-p (not (equal (file-truename true-source-filename)
+                                       (file-truename source-filename))))
     
     (ediff-eval-in-buffer
      ediff-patch-diagnostics
@@ -2138,8 +2249,7 @@ With prefix argument, prompts for a revision name."
         (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
     (message "Working...")
     (setq filename (expand-file-name filename))
-    (with-output-to-temp-buffer
-       buff
+    (with-output-to-temp-buffer buff
       (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
        (delete-windows-on output-buffer)
        (save-excursion
@@ -2520,7 +2630,7 @@ and `auto-save' properties in buffer local variables.  Turns off
            b-begin      (aref list-element 2)
            b-end        (aref list-element 3))
            
-      ;; Put overlays at the appropriate places in the buffers
+      ;; Put overlays at appropriate places in buffers
       (setq a-overlay (ediff-make-overlay a-begin a-end A-buffer))
       ;; Priorities of overlays should be equal in all ediff control
       ;; panels buffers. Otherwise it won't work due to Emacs
@@ -2562,8 +2672,10 @@ and `auto-save' properties in buffer local variables.  Turns off
                         
       ;; record all overlays for this difference
       (setq diff-overlay-list
-           (nconc diff-overlay-list (list (vector a-overlay b-overlay nil)))
-           diff-list (cdr diff-list))
+           (nconc diff-overlay-list
+                  (list (vector a-overlay b-overlay nil nil)))
+           diff-list
+           (cdr diff-list))
       (message "Processing diff region %d of %d"
               current-diff total-diffs)
       ) ;; while
@@ -2697,19 +2809,18 @@ On a dumb terminal, switches between ASCII highlighting and no highlighting."
 (defun ediff-toggle-autorefine ()
   "Toggle auto-refine mode."
   (interactive)
-  (if window-system
-      (cond ((eq ediff-auto-refine 'nix)
-            (setq ediff-auto-refine 'on)
-            (ediff-make-fine-diffs ediff-current-difference 'noforce)
-            (message "Auto-refining is ON."))
-           ((eq ediff-auto-refine 'on)
-            (message "Auto-refining is OFF.")
-            (setq ediff-auto-refine 'off))
-           (t
-            (ediff-set-fine-diff-properties ediff-current-difference 'default)
-            (message "Refinements are HIDDEN.")
-            (setq ediff-auto-refine 'nix))
-           )))
+  (cond ((eq ediff-auto-refine 'nix)
+        (setq ediff-auto-refine 'on)
+        (ediff-make-fine-diffs ediff-current-difference 'noforce)
+        (message "Auto-refining is ON."))
+       ((eq ediff-auto-refine 'on)
+        (message "Auto-refining is OFF.")
+        (setq ediff-auto-refine 'off))
+       (t
+        (ediff-set-fine-diff-properties ediff-current-difference 'default)
+        (message "Refinements are HIDDEN.")
+        (setq ediff-auto-refine 'nix))
+       ))
   
 (defun ediff-toggle-help ()
   "Toggle short/long help message."
@@ -2901,9 +3012,19 @@ With a prefix argument, go back that many differences."
       (let ((n (min ediff-number-of-differences
                    (+ ediff-current-difference (if arg arg 1))))
            (buffer-read-only nil))
-       (while (funcall ediff-skip-diff-region-function n)
+           
+       (while (and (< n ediff-number-of-differences)
+                   (funcall ediff-skip-diff-region-function n))
          (setq n (1+ n)))
-       (ediff-unselect-and-select-difference n))
+       
+       (ediff-unselect-and-select-difference n)
+       ;; possibly skip inessential difference regions
+       (while (and ediff-ignore-similar-regions
+                   (< n ediff-number-of-differences)
+                   (ediff-no-fine-diffs n))
+         (setq n (1+ n))
+         (ediff-unselect-and-select-difference n))
+       ) ;; let
     (error "At end of the difference list.")))
 
 (defun ediff-previous-difference (&optional arg)
@@ -2913,9 +3034,18 @@ With a prefix argument, go back that many differences."
   (if (> ediff-current-difference -1)
       (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
            (buffer-read-only nil))
-       (while (funcall ediff-skip-diff-region-function n)
+           
+       (while (and (funcall ediff-skip-diff-region-function n)
+                   (> n -1))
          (setq n (1- n)))
-       (ediff-unselect-and-select-difference n))
+       (ediff-unselect-and-select-difference n)
+       ;; possibly skip inessential difference regions
+       (while (and ediff-ignore-similar-regions
+                   (> n -1)
+                   (ediff-no-fine-diffs n))
+         (setq n (1- n))
+         (ediff-unselect-and-select-difference n))
+       ) ;; let
     (error "At beginning of the difference list.")))
 
 (defun ediff-jump-to-difference (difference-number)
@@ -3153,7 +3283,7 @@ ARG is a prefix argument.  If ARG is nil, restore current-difference."
   (ediff-recenter 'no-rehighlight))
   
 (defun ediff-toggle-regexp-match ()
-  "Focus on difference regions that match a regexp or hide those diffs."
+  "Toggle focus on difference regions that match a regexp or hide those diffs."
   (interactive)
   (let (regexp-A regexp-B)
     (cond
@@ -3161,7 +3291,7 @@ ARG is a prefix argument.  If ARG is nil, restore current-difference."
               (eq last-command-char ?f))
          (and (eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
               (eq last-command-char ?h)))
-      (message "Show all difference regions.")
+      (message "Selective browsing by regexp turned off.")
       (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
      ((eq last-command-char ?h)
       (setq ediff-skip-diff-region-function 'ediff-hide-regexp-matches
@@ -3193,6 +3323,13 @@ ARG is a prefix argument.  If ARG is nil, restore current-difference."
       (message "Focus on difference regions matching regexp.")
       (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
       (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))))))
+      
+(defun ediff-toggle-skip-similar ()
+  (interactive)
+  (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
+  (if ediff-ignore-similar-regions
+      (message "Skipping over regions that differ only in white space & line breaks.")
+    (message "Skipping over white-space differences turned off.")))
   
 (defun ediff-show-all-diffs (n)
   "Don't skip difference regions."
@@ -3203,22 +3340,27 @@ ARG is a prefix argument.  If ARG is nil, restore current-difference."
 Regions to be ignored according to this function are those where   
 buf A region doesn't match `ediff-regexp-focus-A' and buf B region
 doesn't match `ediff-regexp-focus-B'.
-This function should return nil for regions not to be ignored and t for
-regions to be ignored."
+This function returns nil if the region number N (specified as
+an argument) is not to be ignored and t if region N is to be ignored.
+
+N is a region number used by Ediff internally. It is 1 less
+the number seen by the user."
   (if (and (>= n 0) (< n ediff-number-of-differences))
       (let* ((ctl-buf ediff-control-buffer)
+            (regex-A ediff-regexp-focus-A)
+            (regex-B ediff-regexp-focus-B)
             (reg-A-match (ediff-eval-in-buffer
                           ediff-A-buffer
                           (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
                           (re-search-forward
-                           ediff-regexp-focus-A 
+                           regex-A
                            (ediff-get-diff-posn 'A 'end n ctl-buf)
                            t)))
             (reg-B-match (ediff-eval-in-buffer
                           ediff-B-buffer
                           (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
                           (re-search-forward
-                           ediff-regexp-focus-B 
+                           regex-B
                            (ediff-get-diff-posn 'B 'end n ctl-buf)
                            t))))
        (not (and reg-A-match reg-B-match)))))
@@ -3227,22 +3369,27 @@ regions to be ignored."
   "Hide diffs that match regexp `ediff-regexp-hide-A/B'.
 Regions to be ignored are those where buf A region matches
 `ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
-This function returns nil for regions not to be ignored and t for regions
-to be ignored."
+This function returns nil if the region number N (specified as
+an argument) is not to be ignored and t if region N is to be ignored.
+
+N is a region number used by Ediff internally. It is 1 less
+the number seen by the user."
   (if (and (>= n 0) (< n ediff-number-of-differences))
       (let* ((ctl-buf ediff-control-buffer)
+            (regex-A ediff-regexp-hide-A)
+            (regex-B ediff-regexp-hide-B)
             (reg-A-match (ediff-eval-in-buffer
                           ediff-A-buffer
                           (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
                           (re-search-forward
-                           ediff-regexp-hide-A 
+                           regex-A
                            (ediff-get-diff-posn 'A 'end n ctl-buf)
                            t)))
             (reg-B-match (ediff-eval-in-buffer
                           ediff-B-buffer
                           (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
                           (re-search-forward
-                           ediff-regexp-hide-B 
+                           regex-B
                            (ediff-get-diff-posn 'B 'end n ctl-buf)
                            t))))
        (and reg-A-match reg-B-match))))
@@ -3310,6 +3457,7 @@ flags of the compared file buffers, kills Ediff buffers for this session
   (let ((buff-A ediff-A-buffer)
        (buff-B ediff-B-buffer))
     (ediff-kill-buffer-carefully ediff-diff-buffer)
+    (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
     (ediff-kill-buffer-carefully ediff-tmp-buffer)
     (ediff-kill-buffer-carefully ediff-error-buffer)
     (ediff-kill-buffer-carefully ediff-control-buffer)
@@ -3339,11 +3487,13 @@ flags of the compared file buffers, kills Ediff buffers for this session
        (buf-patch ediff-patch-buf)
        (buf-patch-diag ediff-patch-diagnostics)
        (buf-err  ediff-error-buffer)
-       (buf-diff ediff-diff-buffer))
+       (buf-diff ediff-diff-buffer)
+       (buf-fine-diff ediff-fine-diff-buffer))
     (bury-buffer) ;; ediff-control-buffer
     (delete-other-windows)
     (bury-buffer buf-err)
     (bury-buffer buf-diff)
+    (bury-buffer buf-fine-diff)
     (bury-buffer buf-patch)
     (bury-buffer buf-patch-diag)
     (bury-buffer buf-A)
@@ -3367,8 +3517,6 @@ up an appropriate window config."
 Hit \\[ediff-recenter] to reset the windows afterward."
   (interactive)
   (with-output-to-temp-buffer " *ediff-info*"
-    (princ (format "Ediff version:  %s  of  %s\n\n"
-                  ediff-version ediff-date))
     (ediff-eval-in-buffer ediff-A-buffer
                           (if buffer-file-name
                               (princ
@@ -3389,23 +3537,32 @@ Hit \\[ediff-recenter] to reset the windows afterward."
       (princ (format "\nPoint position in buffer A = %d\n" A-line))
       (princ (format "Point position in buffer B = %d\n" B-line)))
       
-    (princ (format "\nCurrent difference number = %d\n"
-                  (1+ ediff-current-difference)))
-
+    (princ (format "\nCurrent difference number = %S\n"
+                  (cond ((< ediff-current-difference 0) 'start)
+                        ((>= ediff-current-difference
+                             ediff-number-of-differences) 'end)
+                        (t (1+ ediff-current-difference)))))
+
+    (cond (ediff-ignore-similar-regions
+          (princ "\nSkipping over regions that differ only in white space & line breaks."))
+         (t 
+          (princ "\nNo skipping over regions that differ in white space & line breaks.")))
+          
     (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
-          (princ "\nSelective browsing is not in effect.\n"))
+          (princ "\nSelective browsing by regexp is off.\n"))
          ((eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
           (princ
-           "\nSelective browsing is in effect. Ignoring diff regions that:")
+           "\nIgnoring regions that match")
           (princ
-           (format "\n   match `%s' in buffer A  and `%s' in buffer B\n"
+           (format "\n\t regexp `%s' in buffer A  and\n\t regexp `%s' in buffer B\n"
                    ediff-regexp-hide-A ediff-regexp-hide-B)))
          ((eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
           (princ
-           "\nSelective browsing is in effect. Focus on diff regions that:")
+           "\nFocusing on regions that match")
           (princ
-           (format "\n   match `%s' in buffer A  and `%s' in buffer B\n"
-                   ediff-regexp-focus-A ediff-regexp-focus-B))))
+           (format "\n\t regexp `%s' in buffer A  and\n\t regexp `%s' in buffer B\n"
+                   ediff-regexp-focus-A ediff-regexp-focus-B)))
+         (t (princ "\nSelective browsing via a user-defined method.\n")))
     
     (princ "\nBug fixes to:  Michael Kifer <kifer@cs.sunysb.edu>\n")
     (princ   "Gripes to:     /dev/null <dev@null.gov>\n")
@@ -3433,20 +3590,19 @@ Hit \\[ediff-recenter] to reset the windows afterward."
          (ediff-place-flags-in-buffer 'B ediff-B-buffer
                                       ediff-control-buffer n)) 
          
-       (if window-system
-           (cond ((eq ediff-auto-refine 'on)
-                  (if (and
-                       (> ediff-auto-refine-limit
-                          (- (ediff-get-diff-posn 'A 'end n)
-                             (ediff-get-diff-posn 'A 'beg n)))
-                       (> ediff-auto-refine-limit
-                          (- (ediff-get-diff-posn 'B 'end n)
-                             (ediff-get-diff-posn 'B 'beg n))))
-                      (ediff-make-fine-diffs n 'noforce)
-                    (ediff-make-fine-diffs n 'skip)))
-                 
-                 ((eq ediff-auto-refine 'off)       ; highlight iff fine diffs
-                  (ediff-make-fine-diffs n 'skip)))) ; already exist 
+       (cond ((eq ediff-auto-refine 'on)
+              (if (and
+                   (> ediff-auto-refine-limit
+                      (- (ediff-get-diff-posn 'A 'end n)
+                         (ediff-get-diff-posn 'A 'beg n)))
+                   (> ediff-auto-refine-limit
+                      (- (ediff-get-diff-posn 'B 'end n)
+                         (ediff-get-diff-posn 'B 'beg n))))
+                  (ediff-make-fine-diffs n 'noforce)
+                (ediff-make-fine-diffs n 'skip)))
+             
+             ((eq ediff-auto-refine 'off)       ; highlight iff fine diffs
+              (ediff-make-fine-diffs n 'skip))) ; already exist 
      
        (ediff-restore-buffer-characteristics)
        (run-hooks 'ediff-select-hooks))))
@@ -3476,9 +3632,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
        (setq ediff-highlighting-style nil)
        
        ;; unhighlight fine diffs
-       (if window-system
-           (ediff-set-fine-diff-properties
-            ediff-current-difference 'default))
+       (ediff-set-fine-diff-properties ediff-current-difference 'default)
        
        (run-hooks 'ediff-unselect-hooks))))
   
@@ -3573,7 +3727,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
                             (1+ ediff-current-difference)
                             ediff-number-of-differences)))))
   ;; Force mode-line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 
 
@@ -3757,14 +3911,21 @@ them before they disappear."
     (setq ediff-disturbed-overlays nil))
   
 (defun ediff-save-buffer ()
-  "Safe way of saving buffers A and B."
+  "Safe way of saving buffers A, B, and the diff output.
+`wa' saves buffer A, `wb' saves buffer B, and `wf' saves the diff output."
   (interactive)
   (let ((hooks local-write-file-hooks))
     (ediff-unselect-and-select-difference ediff-current-difference
                                          'unselect-only)
     (unwind-protect
        (ediff-eval-in-buffer
-        (if (eq last-command-char ?a) ediff-A-buffer ediff-B-buffer)
+        (cond ((eq last-command-char ?a)
+               ediff-A-buffer)
+              ((eq last-command-char ?b)
+               ediff-B-buffer)
+              ((eq last-command-char ?f)
+               (message "Saving diff output ...")(sit-for 1)
+               ediff-diff-buffer))
         ;; temporarily remove writing block 
         (setq hooks (delq 'ediff-block-write-file hooks))
         (let ((local-write-file-hooks hooks))
@@ -3958,7 +4119,7 @@ buffer."
     (ediff-overlay-put (ediff-get-diff-overlay n 'A) 'face nil)
     (ediff-overlay-put (ediff-get-diff-overlay n 'B) 'face nil)
     
-    (sit-for 0) ;; needs to synch for some reason
+    ;; (sit-for 0) ;; needed synch for some reason in v19.22
     ))
 
 
@@ -4079,98 +4240,107 @@ This is the default for `ediff-forward-word-function'."
 ;; if `flag' is 'skip then don't compute fine diffs for this region.
 (defun ediff-make-fine-diffs (&optional n flag)       
   (interactive)
-  (if (not window-system)
-      (error "Non-window system."))
   (or n  (setq n ediff-current-difference))
   
   (if (< ediff-number-of-differences 1)
       (error "No differences found."))
   
-  (let ((file-A ediff-temp-file-A)
+  (or (< n 0)
+      (>= n ediff-number-of-differences)
+      ;; n is within the range
+      (let ((file-A ediff-temp-file-A)
        (file-B ediff-temp-file-B))
        
-    (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n))
-          nil)
-         ((eq flag 'skip)
-          (or (ediff-get-fine-diff-vector n)
-              (eq ediff-auto-refine 'off)
-              (message "Region %d is larger than auto-refine limit. Hit %S to force-refine."
-                       (1+ n)
-                       (substitute-command-keys "\\[ediff-make-fine-diffs]")
-                       )))
-         (t
-          ;; delete old fine diffs
-          (ediff-clear-diff-vector (ediff-get-fine-diff-vector n))
-          ;; recompute fine diffs
-          (setq ediff-tmp-buffer (get-buffer-create "*ediff-tmp*"))
-      
-          (ediff-wordify
-           (ediff-get-diff-posn 'A 'beg n)
-           (ediff-get-diff-posn 'A 'end n)
-           ediff-A-buffer
-           ediff-tmp-buffer)
-          (ediff-eval-in-buffer
-           ediff-tmp-buffer
-           (setq file-A (ediff-make-temp-file ".fine-diffs-A" file-A)))
-    
-          (ediff-wordify
-           (ediff-get-diff-posn 'B 'beg n)
-           (ediff-get-diff-posn 'B 'end n)
-           ediff-B-buffer
-           ediff-tmp-buffer)
-          (ediff-eval-in-buffer
-           ediff-tmp-buffer
-           (setq file-B (ediff-make-temp-file ".fine-diffs-B" file-B)))
-   
-          ;; save temp file names.
-          (setq ediff-temp-file-A file-A
-                ediff-temp-file-B file-B)
-          
-          ;; set the new vector of fine diffs, if none exists
-          (ediff-set-fine-diff-vector
-                n
-                (ediff-setup-diff-regions file-A file-B 'use-old-diff-buf n
-                                          ediff-fine-diff-program
-                                          ediff-fine-diff-options
-                                          ediff-fine-diff-ok-lines-regexp))
-          (if (eq (length (ediff-get-fine-diff-vector n)) 0)
-              (message "No differences found in region %d, except for white space and line breaks."
-                       (1+ n))))
-         ) ;; end cond
-    (ediff-set-fine-diff-properties n)
-    ))
+       (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n))
+              nil)
+             ((eq flag 'skip)
+              (or (ediff-get-fine-diff-vector n)
+                  (eq ediff-auto-refine 'off)
+                  (message "Region %d is larger than auto-refine limit. Hit %S to force-refine."
+                           (1+ n)
+                           (substitute-command-keys
+                            "\\[ediff-make-fine-diffs]")
+                           )))
+             (t
+              ;; delete old fine diffs
+              (ediff-clear-diff-vector (ediff-get-fine-diff-vector n))
+              ;; recompute fine diffs
+              (setq ediff-tmp-buffer (get-buffer-create "*ediff-tmp*"))
+              
+              (ediff-wordify
+               (ediff-get-diff-posn 'A 'beg n)
+               (ediff-get-diff-posn 'A 'end n)
+               ediff-A-buffer
+               ediff-tmp-buffer)
+              (ediff-eval-in-buffer
+               ediff-tmp-buffer
+               (setq file-A (ediff-make-temp-file ".fine-diffs-A" file-A)))
+              
+              (ediff-wordify
+               (ediff-get-diff-posn 'B 'beg n)
+               (ediff-get-diff-posn 'B 'end n)
+               ediff-B-buffer
+               ediff-tmp-buffer)
+              (ediff-eval-in-buffer
+               ediff-tmp-buffer
+               (setq file-B (ediff-make-temp-file ".fine-diffs-B" file-B)))
+              
+              ;; save temp file names.
+              (setq ediff-temp-file-A file-A
+                    ediff-temp-file-B file-B)
+              
+              ;; set the new vector of fine diffs, if none exists
+              (ediff-set-fine-diff-vector
+               n
+               (ediff-setup-diff-regions file-A file-B 'use-old-diff-buf n
+                                         ediff-fine-diff-program
+                                         ediff-fine-diff-options
+                                         ediff-fine-diff-ok-lines-regexp))
+              (if (eq (length (ediff-get-fine-diff-vector n)) 0)
+                  (progn
+                    (message "No diffs found in region %d, except for white space and line breaks."
+                             (1+ n))
+                    (ediff-mark-diff-as-space-only n t))
+                (ediff-mark-diff-as-space-only n nil)))
+             ) ;; end cond
+       (ediff-set-fine-diff-properties n)
+       )))
     
     
 (defun ediff-set-fine-diff-properties (n &optional default)
-  (let ((fine-diff-vector  (ediff-get-fine-diff-vector n))
-       (face-A (if default 'default (face-name ediff-fine-diff-face-A)))
-       (face-B (if default 'default (face-name ediff-fine-diff-face-B)))
-       (priority-A (if default
-                       0
-                     (1+ (ediff-overlay-get ediff-current-diff-overlay-A
-                                            'priority))))
-       (priority-B (if default
-                       0
-                     (1+ (ediff-overlay-get ediff-current-diff-overlay-B
-                                            'priority)))))
-    (mapcar
-     (function (lambda (vec)
-                (ediff-overlay-put 
-                 (ediff-get-diff-overlay-from-vector vec 'A)
-                 'face face-A)
-                (ediff-overlay-put
-                 (ediff-get-diff-overlay-from-vector vec 'A)
-                 'priority priority-A)
-                
-                (ediff-overlay-put
-                 (ediff-get-diff-overlay-from-vector vec 'B)
-                 'face face-B)
-                (ediff-overlay-put
-                 (ediff-get-diff-overlay-from-vector vec 'B)
-                 'priority priority-B)
-                ))
-     fine-diff-vector)
-    ))
+  (or (not window-system)
+      (< n 0)
+      (>= n ediff-number-of-differences)
+      ;; in a window system, set faces and priorities of fine overlays
+      (let ((fine-diff-vector  (ediff-get-fine-diff-vector n))
+           (face-A (if default 'default (face-name ediff-fine-diff-face-A)))
+           (face-B (if default 'default (face-name ediff-fine-diff-face-B)))
+           (priority-A (if default
+                           0
+                         (1+ (ediff-overlay-get ediff-current-diff-overlay-A
+                                                'priority))))
+           (priority-B (if default
+                           0
+                         (1+ (ediff-overlay-get ediff-current-diff-overlay-B
+                                                'priority)))))
+       (mapcar
+        (function (lambda (vec)
+                    (ediff-overlay-put 
+                     (ediff-get-diff-overlay-from-vector vec 'A)
+                     'face face-A)
+                    (ediff-overlay-put
+                     (ediff-get-diff-overlay-from-vector vec 'A)
+                     'priority priority-A)
+                    
+                    (ediff-overlay-put
+                     (ediff-get-diff-overlay-from-vector vec 'B)
+                     'face face-B)
+                    (ediff-overlay-put
+                     (ediff-get-diff-overlay-from-vector vec 'B)
+                     'priority priority-B)
+                    ))
+        fine-diff-vector)
+       )))
     
 (defun ediff-convert-diffs-to-overlays-refine (A-buffer B-buffer
                                                diff-list refine-region)
@@ -4192,7 +4362,7 @@ This is the default for `ediff-forward-word-function'."
            b-begin      (aref list-element 2)
            b-end        (aref list-element 3))
            
-      ;; place overlays at the appropriate places in the buffers
+      ;; put overlays at appropriate places in buffers
       (setq a-overlay (ediff-make-overlay 
                       (ediff-goto-word (1+ a-begin) A-buffer)
                       (ediff-goto-word a-end A-buffer 'end)
@@ -4292,8 +4462,3 @@ avoid loading cl-*."
 (provide 'ediff)
 
 ;;; ediff.el ends here
-
-
-
-
-