Commits

Anonymous committed 9245301

2002-01-07 Michael Kifer <kifer@cs.stonybrook.edu>

* ediff-help.el: use ediff-cond-compile-for-xemacs-or-emacs.

* ediff-hook.el: use ediff-cond-compile-for-xemacs-or-emacs.

* ediff-init.el (ediff-cond-compile-for-xemacs-or-emacs): new
macro designed to be used in many places where ediff-emacs-p or
ediff-xemacs-p was previously used. Reduces the number of
warnings.
Use ediff-cond-compile-for-xemacs-or-emacs in many places in lieue
of ediff-xemacs-p.
(ediff-make-current-diff-overlay, ediff-highlight-diff-in-one-buffer,
ediff-convert-fine-diffs-to-overlays, ediff-empty-diff-region-p,
ediff-whitespace-diff-region-p, ediff-get-region-contents):
moved to ediff-util.el.
(ediff-event-key): moved here.

* ediff-merge.el: got rid of unreferenced variables.

* ediff-mult.el: use ediff-cond-compile-for-xemacs-or-emacs.

* ediff-util.el: use ediff-cond-compile-for-xemacs-or-emacs.
(ediff-cleanup-mess): improved the way windows are set up after
quitting ediff.
(ediff-janitor): use ediff-dispose-of-variant-according-to-user.
(ediff-dispose-of-variant-according-to-user): new function
designed to be smarter and also understands indirect buffers.
(ediff-highlight-diff-in-one-buffer,
ediff-unhighlight-diff-in-one-buffer,
ediff-unhighlight-diffs-totally-in-one-buffer,
ediff-highlight-diff, ediff-highlight-diff,
ediff-unhighlight-diff, ediff-unhighlight-diffs-totally,
ediff-empty-diff-region-p, ediff-whitespace-diff-region-p,
ediff-get-region-contents, ediff-make-current-diff-overlay):
moved here.
(ediff-format-bindings-of): new function by Hannu Koivisto
<azure@iki.fi>.
(ediff-setup): make sure the merge buffer is always widened and
modifiable.
(ediff-write-merge-buffer-and-maybe-kill): refuse to write the
result of a merge into a file visited by another buffer.
(ediff-arrange-autosave-in-merge-jobs): check if the merge file
is visited by another buffer and ask to save/delete that buffer.
(ediff-verify-file-merge-buffer): new function to do the above.

* ediff-vers.el: load ediff-init.el at compile time.

* ediff-wind.el: use ediff-cond-compile-for-xemacs-or-emacs.

* ediff.el (ediff-windows, ediff-regions-wordwise,
ediff-regions-linewise): use indirect buffers to improve
robustness and make it possible to compare regions of the same
buffer (even overlapping regions).
(ediff-clone-buffer-for-region-comparison,
ediff-clone-buffer-for-window-comparison): new functions.
(ediff-files-internal): refuse to compare identical files.
(ediff-regions-internal): get rid of the warning about comparing
regions of the same buffer.

* ediff-diff.el (ediff-convert-fine-diffs-to-overlays): moved here.
Plus the following fixes courtesy of Dave Love:
Doc fixes.
(ediff-word-1): Use word class and move - to the
front per regexp documentation.
(ediff-wordify): Bind forward-word-function outside loop.
(ediff-copy-to-buffer): Use insert-buffer-substring rather than
consing buffer contents.
(ediff-goto-word): Move syntax table setting outside loop.

  • Participants
  • Parent commits 1a7ac45

Comments (0)

Files changed (14)

+2002-01-07  Michael Kifer  <kifer@cs.stonybrook.edu>
+	
+	* ediff-help.el: use ediff-cond-compile-for-xemacs-or-emacs.
+	
+	* ediff-hook.el: use ediff-cond-compile-for-xemacs-or-emacs.
+	
+	* ediff-init.el (ediff-cond-compile-for-xemacs-or-emacs): new
+	macro designed to be used in many places where ediff-emacs-p or
+	ediff-xemacs-p was previously used. Reduces the number of
+	warnings.
+	Use ediff-cond-compile-for-xemacs-or-emacs in many places in lieue
+	of ediff-xemacs-p.
+	(ediff-make-current-diff-overlay, ediff-highlight-diff-in-one-buffer,
+	ediff-convert-fine-diffs-to-overlays, ediff-empty-diff-region-p,
+	ediff-whitespace-diff-region-p, ediff-get-region-contents):
+	moved to ediff-util.el.
+	(ediff-event-key): moved here.
+	
+	* ediff-merge.el: got rid of unreferenced variables.
+	
+	* ediff-mult.el: use ediff-cond-compile-for-xemacs-or-emacs.
+	
+	* ediff-util.el: use ediff-cond-compile-for-xemacs-or-emacs.
+	(ediff-cleanup-mess): improved the way windows are set up after
+	quitting ediff.
+	(ediff-janitor): use ediff-dispose-of-variant-according-to-user.
+	(ediff-dispose-of-variant-according-to-user): new function
+	designed to be smarter and also understands indirect buffers.
+	(ediff-highlight-diff-in-one-buffer,
+	ediff-unhighlight-diff-in-one-buffer,
+	ediff-unhighlight-diffs-totally-in-one-buffer,
+	ediff-highlight-diff, ediff-highlight-diff,
+	ediff-unhighlight-diff, ediff-unhighlight-diffs-totally,
+	ediff-empty-diff-region-p, ediff-whitespace-diff-region-p,
+	ediff-get-region-contents, ediff-make-current-diff-overlay):
+	moved here.
+	(ediff-format-bindings-of): new function by Hannu Koivisto
+	<azure@iki.fi>.
+	(ediff-setup): make sure the merge buffer is always widened and
+	modifiable.
+	(ediff-write-merge-buffer-and-maybe-kill): refuse to write the
+	result of a merge into a file visited by another buffer.
+	(ediff-arrange-autosave-in-merge-jobs): check if the merge file
+	is visited by another buffer and ask to save/delete that buffer.
+	(ediff-verify-file-merge-buffer): new function to do the above.
+	
+	* ediff-vers.el: load ediff-init.el at compile time.
+	
+	* ediff-wind.el: use ediff-cond-compile-for-xemacs-or-emacs.
+	
+	* ediff.el (ediff-windows, ediff-regions-wordwise,
+	ediff-regions-linewise): use indirect buffers to improve
+	robustness and make it possible to compare regions of the same
+	buffer (even overlapping regions).
+	(ediff-clone-buffer-for-region-comparison,
+	ediff-clone-buffer-for-window-comparison): new functions.
+	(ediff-files-internal): refuse to compare identical files.
+	(ediff-regions-internal): get rid of the warning about comparing
+	regions of the same buffer.
+	
+	* ediff-diff.el (ediff-convert-fine-diffs-to-overlays): moved here.
+	Plus the following fixes courtesy of Dave Love:
+	Doc fixes.
+	(ediff-word-1): Use word class and move - to the
+	front per regexp documentation.
+	(ediff-wordify): Bind forward-word-function outside loop.
+	(ediff-copy-to-buffer): Use insert-buffer-substring rather than
+	consing buffer contents.
+	(ediff-goto-word): Move syntax table setting outside loop.
+
 2001-12-30  Steve Youngs  <youngs@xemacs.org>
 
 	* package-info.in (provides): Update to include all provides.
-
+	
 2001-12-24  Michael Kifer  <kifer@cs.sunysb.edu>
 	
 	* ediff-mult.el (ediff-meta-mark-equal-files): Added optional
 ;;; ediff-diff.el --- diff-related utilities
 
-;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
 
 ;; compiler pacifier
 (defvar ediff-default-variant)
+(defvar null-device)
 
 (eval-when-compile
   (let ((load-path (cons (expand-file-name ".") load-path)))
 ;; make sure that mandatory options are added even if the user changes
 ;; ediff-diff-options or ediff-diff3-options in the customization widget
 (defun ediff-reset-diff-options (symb val)
-  (let* ((diff-program 
-	  (if (eq symb 'ediff-diff-options) 
+  (let* ((diff-program
+	  (if (eq symb 'ediff-diff-options)
 	      ediff-diff-program
 	    ediff-diff3-program))
 	 (mandatory-option (ediff-diff-mandatory-option diff-program))
 	 (spacer (if (string-equal mandatory-option "") "" " ")))
-    (set symb 
+    (set symb
 	 (if (string-match mandatory-option val)
 	     val
 	   (concat mandatory-option spacer val)))
 	 shell-file-name) ; no standard name on MS-DOS
 	((memq system-type '(vax-vms axp-vms)) "*dcl*") ; VMS
 	(t  "sh")) ; UNIX
-  "*The shell used to run diff and patch.  If user's .profile or
-.cshrc files are set up correctly, any shell will do.  However, some people
-set $prompt or other things incorrectly, which leads to undesirable output
-messages.  These may cause Ediff to fail.  In such a case, set ediff-shell
-to a shell that you are not using or, better, fix your shell's startup file."
+  "*The shell used to run diff and patch.
+If user's .profile or .cshrc files are set up correctly, any shell
+will do.  However, some people set $prompt or other things
+incorrectly, which leads to undesirable output messages.  These may
+cause Ediff to fail.  In such a case, set `ediff-shell' to a shell that
+you are not using or, better, fix your shell's startup file."
   :type 'string
   :group 'ediff-diff)
 
 (defcustom ediff-cmp-options nil
   "*Options to pass to `ediff-cmp-program'.
 If GNU diff is used as `ediff-cmp-program', then the most useful options
-are `-I RE', to ignore changes whose lines all match the regexp RE."
+are `-I REGEXP', to ignore changes whose lines match the REGEXP."
   :type '(repeat string)
   :group 'ediff-diff)
 
 (defcustom ediff-diff-options ""
   "*Options to pass to `ediff-diff-program'. 
-If diff\(1\) is used as `ediff-diff-program', then the most useful options are
+If Unix diff is used as `ediff-diff-program', then the most useful options are
 `-w', to ignore space, and `-i', to ignore case of letters.
 At present, the option `-c' is not allowed."
   :set 'ediff-reset-diff-options
 
 (defvar ediff-match-diff3-line "^====\\(.?\\)\C-m?$"
   "Pattern to match lines produced by diff3 that describe differences.")
-(defcustom ediff-diff3-options ""  
+(defcustom ediff-diff3-options ""
   "*Options to pass to `ediff-diff3-program'."
   :set 'ediff-reset-diff-options
   :type 'string
 (ediff-defvar-local ediff-diff-status "" "")
 
   
-;;; Fine differences 
+;;; Fine differences
 
 (ediff-defvar-local ediff-auto-refine (if (ediff-has-face-support-p) 'on 'nix)
   "If `on', Ediff auto-highlights fine diffs for the current diff region.
   
 ;;; General
 
-(defvar ediff-diff-ok-lines-regexp  
+(defvar ediff-diff-ok-lines-regexp
   (concat
    "^\\("
    "[0-9,]+[acd][0-9,]+\C-m?$"
 	(ediff-skip-unsuitable-frames)
 	(switch-to-buffer error-buf)
 	(ediff-kill-buffer-carefully ctl-buf)
-	(error "Errors in diff output. Diff output is in %S" diff-buff))))
+	(error "Errors in diff output.  Diff output is in %S" diff-buff))))
 
 ;; BOUNDS specifies visibility bounds to use.
 ;; WORD-MODE tells whether we are in the word-mode or not.
 	(setq shift-A
 	      (ediff-overlay-start
 	       (ediff-get-value-according-to-buffer-type 'A bounds))
-	      shift-B 
+	      shift-B
 	      (ediff-overlay-start
 	       (ediff-get-value-according-to-buffer-type 'B bounds))))
     
 	 ;; compute main diff vector
 	 (if word-mode
 	     ;; make diff-list contain word numbers
-	     (setq diff-list 
+	     (setq diff-list
 		   (nconc diff-list
 			  (list
 			   (if (ediff-buffer-live-p C-buffer)
 		 (forward-line (- c-end c-begin))
 		 (setq c-end-pt (point)
 		       c-prev c-end)))
-	   (setq diff-list 
+	   (setq diff-list
 		 (nconc
 		  diff-list
 		  (list
 			     nil nil	; dummy ancestor
 			     nil nil	; dummy state of diff & merge
 			     nil	; dummy state of ancestor
-			     ))) 
+			     )))
 		  )))
 		  
 	 ))) ; end ediff-with-current-buffer
 		 (ediff-get-value-according-to-buffer-type
 		  buf-type ediff-narrow-bounds)))
 	 (limit (ediff-overlay-end
-		 (ediff-get-value-according-to-buffer-type 
+		 (ediff-get-value-according-to-buffer-type
 		  buf-type ediff-narrow-bounds)))
 	 diff-overlay-list list-element total-diffs
 	 begin end pt-saved overlay state-of-diff)
 ;; if `flag' is 'noforce then make fine-diffs only if this region's fine
 ;; diffs have not been computed before.
 ;; if `flag' is 'skip then don't compute fine diffs for this region.
-(defun ediff-make-fine-diffs (&optional n flag)       
+(defun ediff-make-fine-diffs (&optional n flag)
   (or n  (setq n ediff-current-difference))
   
   (if (< ediff-number-of-differences 1)
 	       (if ediff-3way-comparison-job
 		   (ediff-message-if-verbose
 		    "Region %d is empty in all buffers but %S"
-		    (1+ n) 
+		    (1+ n)
 		    (cond ((not empty-A) 'A)
 			  ((not empty-B) 'B)
 			  ((not empty-C) 'C)))
 		 (ediff-message-if-verbose
 		  "Region %d in buffer %S is empty"
-		  (1+ n) 
+		  (1+ n)
 		  (cond (empty-A 'A)
 			(empty-B 'B)
 			(empty-C 'C)))
 					   "in buffers A & C")
 			     (whitespace-C (ediff-mark-diff-as-space-only n 'C)
 					   "in buffers A & B"))))
-		     (t 
+		     (t
 		      (ediff-mark-diff-as-space-only n nil)))
 	       )
 	      ) ; end cond
 (defun ediff-set-fine-diff-properties-in-one-buffer (buf-type
 						     n &optional default)
   (let ((fine-diff-vector  (ediff-get-fine-diff-vector n buf-type))
-	(face (if default 
+	(face (if default
 		  'default
 		(face-name
 		 (ediff-get-symbol-from-alist
 	) ; while
       ;; convert the list of difference information into a vector
       ;; for fast access
-      (ediff-set-fine-diff-vector 
+      (ediff-set-fine-diff-vector
        region-num buf-type (vconcat diff-overlay-list))
       )))
 
 
+(defsubst ediff-convert-fine-diffs-to-overlays (diff-list region-num)
+  (ediff-set-fine-overlays-in-one-buffer 'A diff-list region-num)
+  (ediff-set-fine-overlays-in-one-buffer 'B diff-list region-num)
+  (if ediff-3way-job
+      (ediff-set-fine-overlays-in-one-buffer 'C diff-list region-num)
+    ))
+
+
 ;; Stolen from emerge.el
 (defun ediff-get-diff3-group (file)
   ;; This save-excursion allows ediff-get-diff3-group to be called for the
 	(setq shift-A
 	      (ediff-overlay-start
 	       (ediff-get-value-according-to-buffer-type 'A bounds))
-	      shift-B 
+	      shift-B
 	      (ediff-overlay-start
 	       (ediff-get-value-according-to-buffer-type 'B bounds))
-	      shift-C 
+	      shift-C
 	      (if three-way-comp
 		  (ediff-overlay-start
 		   (ediff-get-value-according-to-buffer-type 'C bounds)))))
 	       ;; compute main diff vector
 	       (if word-mode
 		   ;; make diff-list contain word numbers
-		   (setq diff-list 
+		   (setq diff-list
 			 (nconc diff-list
 				(list (vector
 				       (- a-begin a-prev) (- a-end a-begin)
 		       (forward-line (- c-or-anc-end c-or-anc-begin))
 		       (setq anc-end-pt (point)
 			     anc-prev c-or-anc-end)))
-		 (setq diff-list 
+		 (setq diff-list
 		       (nconc
 			diff-list
 			;; if comparing with ancestor, then there also is a
         (delete-process process))))
 	
 
-;;; Word functions used to refine the current diff	    
+;;; Word functions used to refine the current diff
 
 (defvar ediff-forward-word-function 'ediff-forward-word
   "*Function to call to move to the next word.
   "*Characters constituting white space.
 These characters are ignored when differing regions are split into words.")
 
-(defvar ediff-word-1 "a-zA-Z---_"
+(defvar ediff-word-1
+  (ediff-cond-compile-for-xemacs-or-emacs "a-zA-Z---_" "-[:word:]_")
   "*Characters that constitute words of type 1.
 More precisely, [ediff-word-1] is a regexp that matches type 1 words.
-See `ediff-forward-word' for more details.")  
+See `ediff-forward-word' for more details.")
 
 (defvar ediff-word-2 "0-9.,"
   "*Characters that constitute words of type 2.
   (concat "^" ediff-word-1 ediff-word-2 ediff-word-3 ediff-whitespace)
   "*Characters that constitute words of type 4.
 More precisely, [ediff-word-4] is a regexp that matches type 4 words.
-See `ediff-forward-word' for more details.")  
+See `ediff-forward-word' for more details.")
 
 ;; Split region along word boundaries. Each word will be on its own line.
 ;; Output to buffer out-buffer.
 
 
 (defun ediff-wordify (beg end in-buffer out-buffer &optional control-buf)
-  (let (inbuf-syntax-tbl sv-point diff-string)
+  (let ((forward-word-function
+	 ;; eval in control buf to let user create local versions for
+	 ;; different invocations
+	 (if control-buf
+	     (ediff-with-current-buffer control-buf
+	       ediff-forward-word-function)
+	   ediff-forward-word-function))
+	inbuf-syntax-tbl sv-point diff-string)
     (save-excursion
      (set-buffer in-buffer)
      (setq inbuf-syntax-tbl
      (delete-region (point-min) (point))
      
      (while (not (eobp))
-       ;; eval in control buf to let user create local versions for
-       ;; different invocations
-       (if control-buf
-	   (funcall 
-	    (ediff-with-current-buffer control-buf
-	      ediff-forward-word-function))
-	 (funcall ediff-forward-word-function))
+       (funcall forward-word-function)
        (setq sv-point (point))
        (skip-chars-forward ediff-whitespace)
        (delete-region sv-point (point))
        (insert "\n")))))
        
-;; copy string from BEG END from IN-BUF to OUT-BUF
+;; copy string specified as BEG END from IN-BUF to OUT-BUF
 (defun ediff-copy-to-buffer (beg end in-buffer out-buffer)
-  (let (string)
-    (save-excursion
-      (set-buffer in-buffer)
-     (setq string (buffer-substring beg end))
-
-     (set-buffer out-buffer)
-     (erase-buffer)
-     (insert string)
-     (goto-char (point-min)))))
+  (with-current-buffer out-buffer
+    (erase-buffer)
+    (insert-buffer-substring in-buffer beg end)
+    (goto-char (point-min))))
 
 
 ;; goto word #n starting at current position in buffer `buf'
 	(syntax-tbl ediff-syntax-table))
     (ediff-with-current-buffer buf
       (skip-chars-forward ediff-whitespace)
-      (while (> n 1)
-	(ediff-with-syntax-table syntax-tbl
-	    (funcall fwd-word-fun))
-	(skip-chars-forward ediff-whitespace)
-	(setq n (1- n)))
+      (ediff-with-syntax-table syntax-tbl
+	(while (> n 1)
+	  (funcall fwd-word-fun)
+	  (skip-chars-forward ediff-whitespace)
+	  (setq n (1- n))))
       (if (and flag (> n 0))
 	  (funcall fwd-word-fun))
       (point))))
 
 (defun ediff-same-file-contents (f1 f2)
-  "T if F1 and F2 have identical contents."
-  (let ((res 
+  "Return t if F1 and F2 have identical contents."
+  (let ((res
 	 (apply 'call-process ediff-cmp-program nil nil nil
  		(append ediff-cmp-options (list f1 f2)))))
     (and (numberp res) (eq res 0))))
 ;;; ediff-help.el --- Code related to the contents of Ediff help buffers
 
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
   (let ((pos (ediff-event-point last-command-event))
 	overl cmd)
 
-    (if ediff-xemacs-p
-	(setq overl (extent-at pos (current-buffer) 'ediff-help-info)
-	      cmd   (ediff-overlay-get overl 'ediff-help-info))
-      (setq cmd (car (mapcar (lambda (elt)
-			       (overlay-get elt 'ediff-help-info))
-			     (overlays-at pos)))))
+    (ediff-cond-compile-for-xemacs-or-emacs
+     ;; xemacs
+     (setq overl (extent-at pos (current-buffer) 'ediff-help-info)
+	   cmd   (ediff-overlay-get overl 'ediff-help-info))
+     ;; emacs
+     (setq cmd (car (mapcar (lambda (elt)
+			      (overlay-get elt 'ediff-help-info))
+			    (overlays-at pos))))
+     )
     
     (if (not (stringp cmd))
 	(error "Hmm...  I don't see an Ediff command around here..."))
 ;;; ediff-hook.el --- setup for Ediff's menus and autoloads
 
-;; Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
 ;; allow menus to be set up without ediff-wind.el being loaded
 ;;;###autoload
 (defvar ediff-window-setup-function)
+
+;; This is used to avoid compilation warnings. When emacs/xemacs forms can
+;; generate compile time warnings, we use this macro.
+;; In this case, the macro will expand into the form that is appropriate to the
+;; compiler at hand.
+;; Suggested by rms.
+(defmacro ediff-cond-compile-for-xemacs-or-emacs (xemacs-form emacs-form)
+  (if (string-match "XEmacs" emacs-version)
+      xemacs-form emacs-form))
  
 ;; Note we wrap this in a progn so that we pick up the whole def
 ;; for auto-autoload. That way we do not load ediff-hook.el when defining
 ;; the menus.
 ;;;###autoload
 (progn
-  (defun ediff-xemacs-init-menus ()
-    (if (featurep 'menubar)
-	(progn
-	  (add-submenu
-	   '("Tools") ediff-menu "OO-Browser...")
-	  (add-submenu
-	   '("Tools") ediff-merge-menu "OO-Browser...")
-	  (add-submenu
-	   '("Tools") epatch-menu "OO-Browser...")
-	  (add-submenu
-	   '("Tools") ediff-misc-menu "OO-Browser...")
-	  (add-menu-button
-	   '("Tools") "-------" "OO-Browser...")
-	  ))))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   ;; xemacs form
+   (defun ediff-xemacs-init-menus ()
+     (if (featurep 'menubar)
+	 (progn
+	   (add-submenu
+	    '("Tools") ediff-menu "OO-Browser...")
+	   (add-submenu
+	    '("Tools") ediff-merge-menu "OO-Browser...")
+	   (add-submenu
+	    '("Tools") epatch-menu "OO-Browser...")
+	   (add-submenu
+	    '("Tools") ediff-misc-menu "OO-Browser...")
+	   (add-menu-button
+	    '("Tools") "-------" "OO-Browser...")
+	   )))
+   nil ; emacs form
+   ))
 
 
-;; explicit string-match is needed: ediff-xemacs-p is not defined at build time
 ;;;###autoload
-(cond ((string-match "XEmacs" emacs-version)
-       (defvar ediff-menu
-	 '("Compare"
-	   ["Two Files..."  ediff-files t]
-	   ["Two Buffers..." ediff-buffers t]
-	   ["Three Files..."  ediff-files3 t]
-	   ["Three Buffers..." ediff-buffers3 t]
-	   "---"
-	   ["Two Directories..." ediff-directories t]
-	   ["Three Directories..." ediff-directories3 t]
-	   "---"
-	   ["File with Revision..."  ediff-revision t]
-	   ["Directory Revisions..."  ediff-directory-revisions t]
-	   "---"
-	   ["Windows Word-by-word..." ediff-windows-wordwise t]
-	   ["Windows Line-by-line..." ediff-windows-linewise t]
-	   "---"
-	   ["Regions Word-by-word..." ediff-regions-wordwise t]
-	   ["Regions Line-by-line..." ediff-regions-linewise t]
-	   ))
-       (defvar ediff-merge-menu
-	 '("Merge"
-	   ["Files..."  ediff-merge-files t]
-	   ["Files with Ancestor..." ediff-merge-files-with-ancestor t]
-	   ["Buffers..."  ediff-merge-buffers t]
-	   ["Buffers with Ancestor..."
-	    ediff-merge-buffers-with-ancestor t]
-	   "---"
-	   ["Directories..."  ediff-merge-directories t]
-	   ["Directories with Ancestor..."
-	    ediff-merge-directories-with-ancestor t]
-	   "---"
-	   ["Revisions..."  ediff-merge-revisions t]
-	   ["Revisions with Ancestor..."
-	    ediff-merge-revisions-with-ancestor t]
-	   ["Directory Revisions..." ediff-merge-directory-revisions t]
-	   ["Directory Revisions with Ancestor..."
-	    ediff-merge-directory-revisions-with-ancestor t]
-	   ))
-       (defvar epatch-menu
-	 '("Apply Patch"
-	   ["To a file..."  ediff-patch-file t]
-	   ["To a buffer..." ediff-patch-buffer t]
-	   ))
-       (defvar ediff-misc-menu
-	 '("Ediff Miscellanea"
-	   ["Ediff Manual..." ediff-documentation t]
-	   ["Customize Ediff..." ediff-customize t]
-	   ["List Ediff Sessions..." ediff-show-registry t]
-	   ["Use separate frame for Ediff control buffer..."
-	    ediff-toggle-multiframe
-	    :style toggle
-	    :selected (if (and (featurep 'ediff-util)
-			       (boundp 'ediff-window-setup-function))
-			  (eq ediff-window-setup-function
-			      'ediff-setup-windows-multiframe))]
-	   ["Use a toolbar with Ediff control buffer"
-	    ediff-toggle-use-toolbar
-	    :style toggle
-	    :selected (if (featurep 'ediff-tbar)
-			  (ediff-use-toolbar-p))]
-	   ))
-       
-       ;; put these menus before Object-Oriented-Browser in Tools menu
-;;;      (add-hook 'before-init-hook 'ediff-xemacs-init-menus)
-;;;      (if (not purify-flag)
-;;;	   (ediff-xemacs-init-menus))
-;;;      )       
-       (if (and (featurep 'menubar) (not (featurep 'infodock))
-		(not (featurep 'ediff-hook)))
+(ediff-cond-compile-for-xemacs-or-emacs
+ (progn
+   (defvar ediff-menu
+     '("Compare"
+       ["Two Files..."  ediff-files t]
+       ["Two Buffers..." ediff-buffers t]
+       ["Three Files..."  ediff-files3 t]
+       ["Three Buffers..." ediff-buffers3 t]
+       "---"
+       ["Two Directories..." ediff-directories t]
+       ["Three Directories..." ediff-directories3 t]
+       "---"
+       ["File with Revision..."  ediff-revision t]
+       ["Directory Revisions..."  ediff-directory-revisions t]
+       "---"
+       ["Windows Word-by-word..." ediff-windows-wordwise t]
+       ["Windows Line-by-line..." ediff-windows-linewise t]
+       "---"
+       ["Regions Word-by-word..." ediff-regions-wordwise t]
+       ["Regions Line-by-line..." ediff-regions-linewise t]
+       ))
+   (defvar ediff-merge-menu
+     '("Merge"
+       ["Files..."  ediff-merge-files t]
+       ["Files with Ancestor..." ediff-merge-files-with-ancestor t]
+       ["Buffers..."  ediff-merge-buffers t]
+       ["Buffers with Ancestor..."
+	ediff-merge-buffers-with-ancestor t]
+       "---"
+       ["Directories..."  ediff-merge-directories t]
+       ["Directories with Ancestor..."
+	ediff-merge-directories-with-ancestor t]
+       "---"
+       ["Revisions..."  ediff-merge-revisions t]
+       ["Revisions with Ancestor..."
+	ediff-merge-revisions-with-ancestor t]
+       ["Directory Revisions..." ediff-merge-directory-revisions t]
+       ["Directory Revisions with Ancestor..."
+	ediff-merge-directory-revisions-with-ancestor t]
+       ))
+   (defvar epatch-menu
+     '("Apply Patch"
+       ["To a file..."  ediff-patch-file t]
+       ["To a buffer..." ediff-patch-buffer t]
+       ))
+   (defvar ediff-misc-menu
+     '("Ediff Miscellanea"
+       ["Ediff Manual..." ediff-documentation t]
+       ["Customize Ediff..." ediff-customize t]
+       ["List Ediff Sessions..." ediff-show-registry t]
+       ["Use separate frame for Ediff control buffer..."
+	ediff-toggle-multiframe
+	:style toggle
+	:selected (if (and (featurep 'ediff-util)
+			   (boundp 'ediff-window-setup-function))
+		      (eq ediff-window-setup-function
+			  'ediff-setup-windows-multiframe))]
+       ["Use a toolbar with Ediff control buffer"
+	ediff-toggle-use-toolbar
+	:style toggle
+	:selected (if (featurep 'ediff-tbar)
+		      (ediff-use-toolbar-p))]
+       ))
+   
+   ;; put these menus before Object-Oriented-Browser in Tools menu
+   (if (and (featurep 'menubar) (not (featurep 'infodock))
+	    (not (featurep 'ediff-hook)))
 	   (ediff-xemacs-init-menus)))
-      
-      ;; Emacs--only if menu-bar is loaded
-      ((featurep 'menu-bar)
+ 
+ ;; Emacs--only if menu-bar is loaded
+ (if (featurep 'menu-bar)
+     (progn
        ;; initialize menu bar keymaps
        (defvar menu-bar-ediff-misc-menu
 	 (make-sparse-keymap "Ediff Miscellanea"))
 	 '("Ediff Manual..." . ediff-documentation))
        )
       
-      ) ; cond
+      ) ; emacs case
+ ) ; ediff-cond-compile-for-xemacs-or-emacs
 
 ;; arrange for autoloads
 (if purify-flag
 ;;; ediff-init.el --- Macros, variables, and defsubsts used by Ediff
 
-;; Copyright (C) 1994, 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
 (defvar ediff-whitespace)
 (defvar ediff-multiframe)
 (defvar ediff-use-toolbar-p)
+(defvar mswindowsx-bitmap-file-path)
 
 (and noninteractive
      (eval-when-compile
 ;; Is it Emacs?
 (defconst ediff-emacs-p (not ediff-xemacs-p))
 
+;; This is used to avoid compilation warnings. When emacs/xemacs forms can
+;; generate compile time warnings, we use this macro.
+;; In this case, the macro will expand into the form that is appropriate to the
+;; compiler at hand.
+;; Suggested by rms.
+(defmacro ediff-cond-compile-for-xemacs-or-emacs (xemacs-form emacs-form)
+  (if (string-match "XEmacs" emacs-version)
+      xemacs-form emacs-form))
+
 (defvar ediff-force-faces nil
   "If t, Ediff will think that it is running on a display that supports faces.
 This is provided as a temporary relief for users of face-capable displays
 
 ;; Are we running as a window application or on a TTY?
 (defsubst ediff-device-type ()
-  (if ediff-emacs-p
-      window-system
-    (device-type (selected-device))))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (device-type (selected-device)) ; xemacs form
+   window-system  ; emacs form
+   ))
 
 ;; in XEmacs: device-type is tty on tty and stream in batch.
 (defun ediff-window-display-p ()
 	(ediff-emacs-p (memq (ediff-device-type) '(pc)))
 	(ediff-xemacs-p (memq (ediff-device-type) '(tty pc)))))
 
+;; toolbar support for emacs hasn't been implemented in ediff
 (defun ediff-has-toolbar-support-p ()
-  (and ediff-xemacs-p
-       (featurep 'toolbar)
-       (console-on-window-system-p)))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (and (featurep 'toolbar) (console-on-window-system-p)) ; xemacs form
+   nil ; emacs form
+   ))
 
 (defun ediff-use-toolbar-p ()
   (and (ediff-has-toolbar-support-p)	;Can it do it ?
 ;; The Ediff control buffer
 (ediff-defvar-local ediff-control-buffer nil "")
 
+(ediff-defvar-local ediff-temp-indirect-buffer nil
+  "If t, the buffer is a temporary indirect buffer.
+It needs to be killed when we quit the session.")
+
 
 ;; Association between buff-type and ediff-buffer-*
 (defconst ediff-buffer-alist
   :group 'ediff)
 
 
-(if ediff-xemacs-p
-    (progn
-      (fset 'ediff-read-event (symbol-function 'next-command-event))
-      (fset 'ediff-overlayp (symbol-function 'extentp))
-      (fset 'ediff-make-overlay (symbol-function 'make-extent))
-      (fset 'ediff-delete-overlay (symbol-function 'delete-extent)))
-  (fset 'ediff-read-event (symbol-function 'read-event))
-  (fset 'ediff-overlayp (symbol-function 'overlayp))
-  (fset 'ediff-make-overlay (symbol-function 'make-overlay))
-  (fset 'ediff-delete-overlay (symbol-function 'delete-overlay)))
+(ediff-cond-compile-for-xemacs-or-emacs
+ (progn ; xemacs
+   (fset 'ediff-read-event (symbol-function 'next-command-event))
+   (fset 'ediff-overlayp (symbol-function 'extentp))
+   (fset 'ediff-make-overlay (symbol-function 'make-extent))
+   (fset 'ediff-delete-overlay (symbol-function 'delete-extent)))
+ (progn ; emacs
+   (fset 'ediff-read-event (symbol-function 'read-event))
+   (fset 'ediff-overlayp (symbol-function 'overlayp))
+   (fset 'ediff-make-overlay (symbol-function 'make-overlay))
+   (fset 'ediff-delete-overlay (symbol-function 'delete-overlay)))
+ )
 
 ;; Check the current version against the major and minor version numbers
 ;; using op: cur-vers op major.minor If emacs-major-version or
 
 (defun ediff-color-display-p ()
   (condition-case nil
-      (if ediff-emacs-p
-	  (if (fboundp 'display-color-p)
-	      (display-color-p)
-	    (x-display-color-p))
-	(eq (device-class (selected-device)) 'color))
-    (error
-     nil)))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (eq (device-class (selected-device)) 'color) ; xemacs form
+       (if (fboundp 'display-color-p) ; emacs form
+	   (display-color-p)
+	 (x-display-color-p))
+	)
+    (error nil)))
 
 
 (if (ediff-has-face-support-p)
-    (if ediff-xemacs-p
-	(progn
-	  (fset 'ediff-valid-color-p (symbol-function 'valid-color-name-p))
-	  (fset 'ediff-get-face (symbol-function 'get-face)))
-      (fset 'ediff-valid-color-p (symbol-function
-				  (if (fboundp 'color-defined-p)
-				      'color-defined-p
-				    'x-color-defined-p)))
-      (fset 'ediff-get-face (symbol-function 'internal-get-face))))
+    (ediff-cond-compile-for-xemacs-or-emacs
+     (progn ; xemacs
+       (defalias 'ediff-valid-color-p 'valid-color-name-p)
+       (defalias 'ediff-get-face 'get-face))
+     (progn ; emacs
+       (defalias 'ediff-valid-color-p (if (fboundp 'color-defined-p)
+					  'color-defined-p
+					'x-color-defined-p))
+       (defalias 'ediff-get-face 'internal-get-face))
+     ))
 
 (if (ediff-window-display-p)
-    (if ediff-xemacs-p
-	(progn
-	  (fset 'ediff-display-pixel-width
-		(symbol-function 'device-pixel-width))
-	  (fset 'ediff-display-pixel-height
-		(symbol-function 'device-pixel-height)))
-      (fset 'ediff-display-pixel-width (symbol-function
-					(if (fboundp 'display-pixel-width)
-					    'display-pixel-width
-					  'x-display-pixel-width)))
-      (fset 'ediff-display-pixel-height (symbol-function
-					 (if (fboundp 'display-pixel-height)
-					     'display-pixel-height
-					   'x-display-pixel-height)))))
+    (ediff-cond-compile-for-xemacs-or-emacs
+     (progn   ; xemacs
+       (fset 'ediff-display-pixel-width (symbol-function 'device-pixel-width))
+       (fset 'ediff-display-pixel-height
+	     (symbol-function 'device-pixel-height)))
+     (progn   ; emacs
+       (fset 'ediff-display-pixel-width
+	     (if (fboundp 'display-pixel-width)
+		 (symbol-function 'display-pixel-width)
+	       (symbol-function 'x-display-pixel-width)))
+       (fset 'ediff-display-pixel-height
+	     (if (fboundp 'display-pixel-height)
+		 (symbol-function 'display-pixel-height)
+	       (symbol-function 'x-display-pixel-height))))
+     ))
 
 ;; A-list of current-diff-overlay symbols associated with buf types
 (defconst ediff-current-diff-overlay-alist
     (Ancestor . ediff-current-diff-face-Ancestor)))
 
 
-(defun ediff-make-current-diff-overlay (type)
-  (if (ediff-has-face-support-p)
-      (let ((overlay (ediff-get-symbol-from-alist
-		      type ediff-current-diff-overlay-alist))
-	    (buffer (ediff-get-buffer type))
-	    (face (face-name
-		   (symbol-value
-		    (ediff-get-symbol-from-alist
-		     type ediff-current-diff-face-alist)))))
-	(set overlay
-	     (ediff-make-bullet-proof-overlay (point-max) (point-max) buffer))
-	(ediff-set-overlay-face (symbol-value overlay) face)
-	(ediff-overlay-put (symbol-value overlay) 'ediff ediff-control-buffer))
-    ))
-
 (defun ediff-set-overlay-face (extent face)
   (ediff-overlay-put extent 'face face)
   (ediff-overlay-put extent 'help-echo 'ediff-region-help-echo))
 (defun ediff-highest-priority (start end buffer)
   (let ((pos (max 1 (1- start)))
 	ovr-list)
-    (if ediff-xemacs-p
-	(1+ ediff-shadow-overlay-priority)
-      (ediff-with-current-buffer buffer
-	(while (< pos (min (point-max) (1+ end)))
-	  (setq ovr-list (append (overlays-at pos) ovr-list))
-	  (setq pos (next-overlay-change pos)))
-	(+ 1 ediff-shadow-overlay-priority
-	   (apply 'max
-		  (cons
-		   1
-		   (mapcar
-		    (lambda (ovr)
-		      (if (and ovr
-			       ;; exclude ediff overlays from priority
-			       ;; calculation, or else priority will keep
-			       ;; increasing
-			       (null (ediff-overlay-get ovr 'ediff))
-			       (null (ediff-overlay-get ovr 'ediff-diff-num)))
-			  ;; use the overlay priority or 0
-			  (or (ediff-overlay-get ovr 'priority) 0)
-			0))
-		    ovr-list)
-		   )
-		  ))
-	))))
+    (ediff-cond-compile-for-xemacs-or-emacs
+     (1+ ediff-shadow-overlay-priority)  ; xemacs form
+     ;; emacs form
+     (ediff-with-current-buffer buffer
+       (while (< pos (min (point-max) (1+ end)))
+	 (setq ovr-list (append (overlays-at pos) ovr-list))
+	 (setq pos (next-overlay-change pos)))
+       (+ 1 ediff-shadow-overlay-priority
+	  (apply 'max
+		 (cons
+		  1
+		  (mapcar
+		   (lambda (ovr)
+		     (if (and ovr
+			      ;; exclude ediff overlays from priority
+			      ;; calculation, or else priority will keep
+			      ;; increasing
+			      (null (ediff-overlay-get ovr 'ediff))
+			      (null (ediff-overlay-get ovr 'ediff-diff-num)))
+			 ;; use the overlay priority or 0
+			 (or (ediff-overlay-get ovr 'priority) 0)
+		       0))
+		   ovr-list)
+		  )
+		 )))
+     ) ; ediff-cond-compile-for-xemacs-or-emacs
+    ))
 
 
 (defvar ediff-toggle-read-only-function nil
 (ediff-defvar-local ediff-temp-file-C nil "")
 
 
-;;; In-line functions
-
 ;; If file-remote-p is defined (as in XEmacs, use it. Otherwise, check
 ;; if find-file-name-handler is defined for 'file-local-copy
 (defun ediff-file-remote-p (file-name)
   (ediff-paint-background-regions-in-one-buffer
    'Ancestor unhighlight))
 
-(defun ediff-highlight-diff-in-one-buffer (n buf-type)
-  (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
-      (let* ((buff (ediff-get-buffer buf-type))
-	     (last (ediff-with-current-buffer buff (point-max)))
-	     (begin (ediff-get-diff-posn buf-type 'beg n))
-	     (end (ediff-get-diff-posn buf-type 'end n))
-	     (xtra (if (equal begin end) 1 0))
-	     (end-hilit (min last (+ end xtra)))
-	     (current-diff-overlay
-	      (symbol-value
-	       (ediff-get-symbol-from-alist
-		buf-type ediff-current-diff-overlay-alist))))
-
-	(if ediff-xemacs-p
-	    (ediff-move-overlay current-diff-overlay begin end-hilit)
-	  (ediff-move-overlay current-diff-overlay begin end-hilit buff))
-	(ediff-overlay-put current-diff-overlay 'priority
-			   (ediff-highest-priority begin end-hilit buff))
-	(ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
-
-	;; unhighlight the background overlay for diff n so it won't
-	;; interfere with the current diff overlay
-	(ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
-	)))
-
-
-(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
-  (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
-      (let ((current-diff-overlay
-	     (symbol-value
-	      (ediff-get-symbol-from-alist
-	       buf-type ediff-current-diff-overlay-alist)))
-	    (overlay
-	     (ediff-get-diff-overlay ediff-current-difference buf-type))
-	    )
-
-	(ediff-move-overlay current-diff-overlay 1 1)
-
-	;; rehighlight the overlay in the background of the
-	;; current difference region
-	(ediff-set-overlay-face
-	 overlay
-	 (if (and (ediff-has-face-support-p)
-		  ediff-use-faces ediff-highlight-all-diffs)
-	     (ediff-background-face buf-type ediff-current-difference)))
-	)))
-
-(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
-  (ediff-unselect-and-select-difference -1)
-  (if (and (ediff-has-face-support-p) ediff-use-faces)
-      (let* ((inhibit-quit t)
-	     (current-diff-overlay-var
-	      (ediff-get-symbol-from-alist
-	       buf-type ediff-current-diff-overlay-alist))
-	     (current-diff-overlay (symbol-value current-diff-overlay-var)))
-	(ediff-paint-background-regions 'unhighlight)
-	(if (ediff-overlayp current-diff-overlay)
-	    (ediff-delete-overlay current-diff-overlay))
-	(set current-diff-overlay-var nil)
-	)))
-
-
-(defsubst ediff-highlight-diff (n)
-  "Put face on diff N.  Invoked for X displays only."
-  (ediff-highlight-diff-in-one-buffer n 'A)
-  (ediff-highlight-diff-in-one-buffer n 'B)
-  (ediff-highlight-diff-in-one-buffer n 'C)
-  (ediff-highlight-diff-in-one-buffer n 'Ancestor)
-  )
-
-
-(defsubst ediff-unhighlight-diff ()
-  "Remove overlays from buffers A, B, and C."
-  (ediff-unhighlight-diff-in-one-buffer 'A)
-  (ediff-unhighlight-diff-in-one-buffer 'B)
-  (ediff-unhighlight-diff-in-one-buffer 'C)
-  (ediff-unhighlight-diff-in-one-buffer 'Ancestor)
-  )
-
-;; delete highlighting overlays, restore faces to their original form
-(defsubst ediff-unhighlight-diffs-totally ()
-  (ediff-unhighlight-diffs-totally-in-one-buffer 'A)
-  (ediff-unhighlight-diffs-totally-in-one-buffer 'B)
-  (ediff-unhighlight-diffs-totally-in-one-buffer 'C)
-  (ediff-unhighlight-diffs-totally-in-one-buffer 'Ancestor)
-  )
-
 
 ;; arg is a record for a given diff in a difference vector
 ;; this record is itself a vector
       (ediff-clear-fine-differences-in-one-buffer n 'C)))
 
 
-(defsubst ediff-convert-fine-diffs-to-overlays (diff-list region-num)
-  (ediff-set-fine-overlays-in-one-buffer 'A diff-list region-num)
-  (ediff-set-fine-overlays-in-one-buffer 'B diff-list region-num)
-  (if ediff-3way-job
-      (ediff-set-fine-overlays-in-one-buffer 'C diff-list region-num)
-    ))
-
 (defsubst ediff-mouse-event-p (event)
-  (if ediff-xemacs-p
-      (button-event-p event)
-    (string-match "mouse" (format "%S" (event-basic-type event)))
-    ))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (button-event-p event) ; xemacs form
+   (string-match "mouse" (format "%S" (event-basic-type event))) ; emacs form
+   ))
 
 
 (defsubst ediff-key-press-event-p (event)
-  (if ediff-xemacs-p
-      (key-press-event-p event)
-    (or (char-or-string-p event) (symbolp event))))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (key-press-event-p event) ; xemacs form
+   (or (char-or-string-p event) (symbolp event)) ; emacs form
+   ))
 
 (defun ediff-event-point (event)
   (cond ((ediff-mouse-event-p event)
-	 (if ediff-xemacs-p
-	     (event-point event)
-	   (posn-point (event-start event))))
+	 (ediff-cond-compile-for-xemacs-or-emacs
+	  (event-point event)               ; xemacs form
+	  (posn-point (event-start event))  ; emacs form
+	  )
+	 )
 	((ediff-key-press-event-p event)
 	 (point))
-	(t (error))))
+	(t (error nil))))
 
 (defun ediff-event-buffer (event)
   (cond ((ediff-mouse-event-p event)
-	 (if ediff-xemacs-p
-	     (event-buffer event)
-	   (window-buffer (posn-window (event-start event)))))
+	 (ediff-cond-compile-for-xemacs-or-emacs
+	  (event-buffer event)                              ; xemacs form
+	  (window-buffer (posn-window (event-start event))) ; emacs form
+	  )
+	 )
 	((ediff-key-press-event-p event)
 	 (current-buffer))
-	(t (error))))
+	(t (error nil))))
+
+(defun ediff-event-key (event-or-key)
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (if (eventp event-or-key) (event-key event-or-key) event-or-key) ; xemacs
+   event-or-key   ; emacs form
+   ))
 
 
 (defsubst ediff-frame-iconified-p (frame)
   (if (and (ediff-window-display-p) (frame-live-p frame))
-      (if ediff-xemacs-p
-	  (frame-iconified-p frame)
-	(eq (frame-visible-p frame) 'icon))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (frame-iconified-p frame)          ; xemacs form
+       (eq (frame-visible-p frame) 'icon) ; emacs form
+       )
+    ))
 
 (defsubst ediff-window-visible-p (wind)
   ;; under TTY, window-live-p also means window is visible
 
 
 (defsubst ediff-frame-char-width (frame)
-  (if ediff-xemacs-p
-      (/ (frame-pixel-width frame) (frame-width frame))
-    (frame-char-width frame)))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (/ (frame-pixel-width frame) (frame-width frame)) ; xemacs
+   (frame-char-width frame) ; emacs
+   ))
 
 (defun ediff-reset-mouse (&optional frame do-not-grab-mouse)
   (or frame (setq frame (selected-frame)))
 	    (t nil))))
 
 (defsubst ediff-frame-char-height (frame)
-  (if ediff-xemacs-p
-      (glyph-height ediff-H-glyph (selected-window frame))
-    (frame-char-height frame)))
+  (ediff-cond-compile-for-xemacs-or-emacs 
+   (glyph-height ediff-H-glyph (selected-window frame)) ; xemacs cse
+   (frame-char-height frame) ; emacs case
+   )
+  )
 
 ;; Some overlay functions
 
 (defsubst ediff-overlay-start (overl)
   (if (ediff-overlayp overl)
-      (if ediff-emacs-p
-	  (overlay-start overl)
-	(extent-start-position overl))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (extent-start-position overl) ; xemacs form
+       (overlay-start overl)         ; emacs form
+       )
+    ))
 
 (defsubst ediff-overlay-end  (overl)
   (if (ediff-overlayp overl)
-      (if ediff-emacs-p
-	  (overlay-end overl)
-	(extent-end-position overl))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (extent-end-position overl) ; xemacs form
+       (overlay-end overl) ; emacs form
+       )
+    ))
 
 (defsubst ediff-empty-overlay-p (overl)
   (= (ediff-overlay-start overl) (ediff-overlay-end overl)))
 ;; like overlay-buffer in Emacs.  In XEmacs, returns nil if the extent is
 ;; dead.  Otherwise, works like extent-buffer
 (defun ediff-overlay-buffer (overl)
-  (if ediff-emacs-p
-      (overlay-buffer overl)
-    (and (extent-live-p overl) (extent-object overl))))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (and (extent-live-p overl) (extent-object overl)) ; xemacs form
+   (overlay-buffer overl) ; emacs form
+   ))
 
 ;; like overlay-get in Emacs.  In XEmacs, returns nil if the extent is
 ;; dead.  Otherwise, like extent-property
 (defun ediff-overlay-get (overl property)
-  (if ediff-emacs-p
-      (overlay-get overl property)
-    (and (extent-live-p overl) (extent-property overl property))))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (and (extent-live-p overl) (extent-property overl property)) ; xemacs form
+   (overlay-get overl property) ; emacs form
+   ))
 
 
 ;; These two functions are here because XEmacs refuses to
 Checks if overlay's buffer exists before actually doing the move."
   (let ((buf (and overlay (ediff-overlay-buffer overlay))))
     (if (ediff-buffer-live-p buf)
-	(if ediff-xemacs-p
-	    (set-extent-endpoints overlay beg end)
-	  (move-overlay overlay beg end buffer))
+	(ediff-cond-compile-for-xemacs-or-emacs
+	 (set-extent-endpoints overlay beg end) ; xemacs form
+	 (move-overlay overlay beg end buffer)  ; emacs form
+	 )
       ;; buffer's dead
       (if overlay
 	  (ediff-delete-overlay overlay)))))
   "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
 Checks if overlay's buffer exists."
   (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
-      (if ediff-xemacs-p
-	  (set-extent-property overlay prop value)
-	(overlay-put overlay prop value))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (set-extent-property overlay prop value) ; xemacs form
+       (overlay-put overlay prop value) ; emacs form
+       )
     (ediff-delete-overlay overlay)))
 
-;; Some diff region tests
-
-;; t if diff region is empty.
-;; In case of buffer C, t also if it is not a 3way
-;; comparison job (merging jobs return t as well).
-(defun ediff-empty-diff-region-p (n buf-type)
-  (if (eq buf-type 'C)
-      (or (not ediff-3way-comparison-job)
-	  (= (ediff-get-diff-posn 'C 'beg n)
-	     (ediff-get-diff-posn 'C 'end n)))
-    (= (ediff-get-diff-posn buf-type 'beg n)
-       (ediff-get-diff-posn buf-type 'end n))))
-
-;; Test if diff region is white space only.
-;; If 2-way job and buf-type = C, then returns t.
-(defun ediff-whitespace-diff-region-p (n buf-type)
-  (or (and (eq buf-type 'C) (not ediff-3way-job))
-      (ediff-empty-diff-region-p n buf-type)
-      (let ((beg (ediff-get-diff-posn buf-type 'beg n))
-	    (end (ediff-get-diff-posn buf-type 'end n)))
-	(ediff-with-current-buffer (ediff-get-buffer buf-type)
-	  (save-excursion
-	    (goto-char beg)
-	    (skip-chars-forward ediff-whitespace)
-	    (>= (point) end))))))
-
 ;; temporarily uses DIR to abbreviate file name
 ;; if DIR is nil, use default-directory
 (defun ediff-abbreviate-file-name (file &optional dir)
   (cond ((stringp dir)
 	 (let ((directory-abbrev-alist (list (cons dir ""))))
 	   (abbreviate-file-name file)))
-	(ediff-emacs-p (abbreviate-file-name file))
-	(t ; XEmacs requires addl argument
-	 (abbreviate-file-name file t))))
+	(t
+	 (ediff-cond-compile-for-xemacs-or-emacs
+	  ;; XEmacs requires addl argument
+	  (abbreviate-file-name file t) ; xemacs form
+	  (abbreviate-file-name file))  ; emacs form
+	 )
+	))
 
 ;; Takes a directory and returns the parent directory.
 ;; does nothing to `/'.  If the ARG is a regular file,
 	))
 
 
-(defsubst ediff-get-region-contents (n buf-type ctrl-buf &optional start end)
-  (ediff-with-current-buffer
-      (ediff-with-current-buffer ctrl-buf (ediff-get-buffer buf-type))
-    (buffer-substring
-     (or start (ediff-get-diff-posn buf-type 'beg n ctrl-buf))
-     (or end (ediff-get-diff-posn buf-type 'end n ctrl-buf)))))
-
 ;; If ediff modified mode line, strip the modification
 (defsubst ediff-strip-mode-line-format ()
   (if (member (car mode-line-format) '(" A: " " B: " " C: " " Ancestor: "))
 ;;; ediff-merg.el --- merging utilities
 
-;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
 	(combo-region "")
 	(err-msg
 	 "ediff-combination-pattern: Invalid format. Please consult the documentation")
-	diff-region region-delim region-spec)
+	region-delim region-spec)
 
     (if (< (length pattern-list) 5)
 	(error err-msg))
       (or (and (stringp region-delim) (memq region-spec '(A B Ancestor)))
 	  (error err-msg))
 
-      (condition-case err
+      (condition-case nil
 	  (setq combo-region
 		(concat combo-region
 			region-delim "\n"
       (setq state-of-merge (ediff-get-state-of-merge n))
 
       (if remerging
-	  (let ((reg-A (ediff-get-region-contents n 'A ediff-control-buffer))
-		(reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
-		(reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
+	  ;;(let ((reg-A (ediff-get-region-contents n 'A ediff-control-buffer))
+	  ;;	(reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
+	  ;;	(reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
+	  (let ()
 		
 	    ;; if region was edited since it was first set by default
 	    (if (or (ediff-merge-changed-from-default-p n)
   (interactive "P")
   (setq n (if (numberp n) (1- n) ediff-current-difference))
   
-  (let (regA regB reg-combined)
+  (let (reg-combined)
     ;;(setq regA (ediff-get-region-contents n 'A ediff-control-buffer)
     ;;	  regB (ediff-get-region-contents n 'B ediff-control-buffer))
     ;;(setq reg-combined (ediff-make-combined-diff regA regB))
 ;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff
 
-;; Copyright (C) 1995, 1996, 1997, 2001 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
       (erase-buffer)
       ;; delete phony overlays that used to represent sessions before the buff
       ;; was redrawn
-      (if ediff-emacs-p
-	  (mapcar 'delete-overlay (overlays-in 1 1))
-	(map-extents 'delete-extent))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (map-extents 'delete-extent)   ; xemacs
+       (mapcar 'delete-overlay (overlays-in 1 1))  ; emacs
+       )
       
       (insert (format ediff-meta-buffer-message
 		      (ediff-abbrev-jobname ediff-metajob-name)))
 (defun ediff-update-session-marker-in-dir-meta-buffer (session-num)
   (let (buffer-meta-overlays session-info overl buffer-read-only)
     (setq overl
-	  (if ediff-xemacs-p
-	      (map-extents
-	       (lambda (ext maparg)
-		 (if (and
-		      (ediff-overlay-get ext 'ediff-meta-info)
-		      (eq (ediff-overlay-get ext 'ediff-meta-session-number)
-			  session-num))
-		     ext)))
+	  (ediff-cond-compile-for-xemacs-or-emacs
+	   (map-extents ; xemacs
+	    (lambda (ext maparg)
+	      (if (and
+		   (ediff-overlay-get ext 'ediff-meta-info)
+		   (eq (ediff-overlay-get ext 'ediff-meta-session-number)
+		       session-num))
+		  ext)))
 	    ;; Emacs doesn't have map-extents, so try harder
 	    ;; Splice overlay lists to get all buffer overlays
-	    (setq buffer-meta-overlays (overlay-lists)
-		  buffer-meta-overlays (append (car buffer-meta-overlays)
-					       (cdr buffer-meta-overlays)))
-	    (car
-	     (delq nil
-		   (mapcar
-		    (lambda (overl)
-		      (if (and
-			   (ediff-overlay-get overl 'ediff-meta-info)
-			   (eq (ediff-overlay-get
-				overl 'ediff-meta-session-number)
-			       session-num))
-			  overl))
-		    buffer-meta-overlays)))))
+	   (progn
+	     (setq buffer-meta-overlays (overlay-lists)
+		   buffer-meta-overlays (append (car buffer-meta-overlays)
+						(cdr buffer-meta-overlays)))
+	     (car
+	      (delq nil
+		    (mapcar
+		     (lambda (overl)
+		       (if (and
+			    (ediff-overlay-get overl 'ediff-meta-info)
+			    (eq (ediff-overlay-get
+				 overl 'ediff-meta-session-number)
+				session-num))
+			   overl))
+		     buffer-meta-overlays))))
+	   ))
     (or overl
 	(error
 	 "Bug in ediff-update-session-marker-in-dir-meta-buffer: no overlay with given number %S"
       (erase-buffer)
       ;; delete phony overlays that used to represent sessions before the buff
       ;; was redrawn
-      (if ediff-emacs-p
-	  (mapcar 'delete-overlay (overlays-in 1 1))
-	(map-extents 'delete-extent))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (map-extents 'delete-extent) ; xemacs
+       (mapcar 'delete-overlay (overlays-in 1 1)) ; emacs
+       )
 
       (insert "This is a registry of all active Ediff sessions.
 
 	      
 ;; This function executes in meta buffer.  It knows where event happened.
 (defun ediff-filegroup-action ()
-  "Execute appropriate action for the selected session."
+  "Execute appropriate action for a selected session."
   (interactive)
   (let* ((pos (ediff-event-point last-command-event))
 	 (meta-buf (ediff-event-buffer last-command-event))
 	  (setq frame (window-frame wind))
 	  (raise-frame frame)
 	  (ediff-reset-mouse frame)))
+    (sit-for 0) ; sometimes needed to synch the display and ensure that the
+		; point ends up after the just completed session
     (run-hooks 'ediff-show-session-group-hook)
     ))
 
   (let (result olist tmp)
     (if (and point (ediff-buffer-live-p buf))
 	(ediff-with-current-buffer buf
-	  (if ediff-xemacs-p
-	      (setq result
-		    (if (setq tmp (extent-at point buf 'ediff-meta-info))
-			(ediff-overlay-get tmp 'ediff-meta-info)))
-	    (setq olist (overlays-at point))
-	    (setq olist
-		  (mapcar (lambda (elt)
-			    (unless (overlay-get elt 'invisible)
-			      (overlay-get elt 'ediff-meta-info)))
-			  olist))
-	    (while (and olist (null (car olist)))
-	      (setq olist (cdr olist)))
-	    (setq result (car olist)))))
+	  (ediff-cond-compile-for-xemacs-or-emacs
+	   (setq result  ; xemacs
+		 (if (setq tmp (extent-at point buf 'ediff-meta-info))
+		     (ediff-overlay-get tmp 'ediff-meta-info)))
+	   (progn ; emacs
+	     (setq olist (overlays-at point))
+	     (setq olist
+		   (mapcar (lambda (elt)
+			     (unless (overlay-get elt 'invisible)
+			       (overlay-get elt 'ediff-meta-info)))
+			   olist))
+	     (while (and olist (null (car olist)))
+	       (setq olist (cdr olist)))
+	     (setq result (car olist)))
+	   )
+	  ))
     (if result
 	result
       (if noerror
 
 
 (defun ediff-get-meta-overlay-at-pos (point)
-  (if ediff-xemacs-p
-      (extent-at point (current-buffer) 'ediff-meta-info)
-    (let* ((overl-list (overlays-at point))
-	   (overl (car overl-list)))
-      (while (and overl (null (overlay-get overl 'ediff-meta-info)))
-	(setq overl-list (cdr overl-list)
-	      overl (car overl-list)))
-      overl)))
+  (ediff-cond-compile-for-xemacs-or-emacs
+   (extent-at point (current-buffer) 'ediff-meta-info) ; xemacs
+   ;; emacs
+   (let* ((overl-list (overlays-at point))
+	  (overl (car overl-list)))
+     (while (and overl (null (overlay-get overl 'ediff-meta-info)))
+       (setq overl-list (cdr overl-list)
+	     overl (car overl-list)))
+     overl)
+   )
+  )
 
 (defsubst ediff-get-session-number-at-pos (point &optional meta-buffer)
   (setq meta-buffer (if (ediff-buffer-live-p meta-buffer)
   (if (eobp)
       (goto-char (point-min))
     (let ((overl (ediff-get-meta-overlay-at-pos point)))
-      (if ediff-xemacs-p
-	  (progn
-	    (if overl
-		(setq overl (next-extent overl))
-	      (setq overl (next-extent (current-buffer))))
-	    (if overl
-		(extent-start-position overl)
-	      (point-max)))
-	(if overl
-	    ;; note: end of current overlay is the beginning of the next one
-	    (overlay-end overl)
-	  (next-overlay-change point))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (progn ; xemacs
+	 (if overl
+	     (setq overl (next-extent overl))
+	   (setq overl (next-extent (current-buffer))))
+	 (if overl
+	     (extent-start-position overl)
+	   (point-max)))
+       ;; emacs
+       (if overl
+	   ;; note: end of current overlay is the beginning of the next one
+	   (overlay-end overl)
+	 (next-overlay-change point))
+       )
+      )
     ))
 
 
   (if (bobp)
       (goto-char (point-max))
     (let ((overl (ediff-get-meta-overlay-at-pos point)))
-      (if ediff-xemacs-p
-	  (progn
-	    (if overl
-		(setq overl (previous-extent overl))
-	      (setq overl (previous-extent (current-buffer))))
-	    (if overl
-		(extent-start-position overl)
-	      (point-min)))
-	(if overl (setq point (overlay-start overl)))
-	;; to get to the beginning of prev overlay
-	(if (not (bobp))
-	    ;; trick to overcome an emacs bug--doesn't always find previous
-	    ;; overlay change correctly
-	    (setq point (1- point)))
-	(setq point (previous-overlay-change point))
-	;; If we are not over an overlay after subtracting 1, it means we are
-	;; in the description area preceding session records.  In this case,
-	;; goto the top of the registry buffer.
-	(or (car (overlays-at point))
-	    (setq point (point-min)))
-	point))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (progn
+	 (if overl
+	     (setq overl (previous-extent overl))
+	   (setq overl (previous-extent (current-buffer))))
+	 (if overl
+	     (extent-start-position overl)
+	   (point-min)))
+       (progn
+	 (if overl (setq point (overlay-start overl)))
+	 ;; to get to the beginning of prev overlay
+	 (if (not (bobp))
+	     ;; trick to overcome an emacs bug--doesn't always find previous
+	     ;; overlay change correctly
+	     (setq point (1- point)))
+	 (setq point (previous-overlay-change point))
+	 ;; If we are not over an overlay after subtracting 1, it means we are
+	 ;; in the description area preceding session records.  In this case,
+	 ;; goto the top of the registry buffer.
+	 (or (car (overlays-at point))
+	     (setq point (point-min)))
+	 point)
+       )
+      )))
 
 ;; this is the action invoked when the user selects a patch from the meta
 ;; buffer.
 ;;; ediff-ptch.el --- Ediff's  patch support
 
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
 ;;; ediff-tbar.el --- A toolbar for Ediff control buffer
 
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 97, 2002 Free Software Foundation, Inc.
 
 ;; Author: Marc Paquette <marcpa@cam.org>
 
     (or (featurep 'ediff-util)
 	(load "ediff-util.el" nil nil 'nosuffix))
     ))
+(defvar toolbar-icon-directory)
 ;; end pacifier
 
 (require 'ediff-init)
       '([ediff-toolbar-refine-icon
 	 ediff-toolbar-refine
 	 t
-	 ;;; The toolbar is not automatically refreshed (in 19.14)
-	 ;;; when :activep changes state. 
-	 ;;(ediff-toolbar-refine-needed-p)
 	 "Refine current difference region by computing fine diffs."]
 	[ediff-toolbar-previous-icon
 	 ediff-toolbar-previous-difference
       '([ediff-toolbar-refine-icon
 	 ediff-toolbar-refine
 	 t
-	 ;;; The toolbar is not automatically refreshed (in 19.14)
-	 ;;; when :activep changes state. 
-	 ;;(ediff-toolbar-refine-needed-p)
 	 "Refine current difference region by computing fine diffs."]
 	[ediff-toolbar-previous-icon
 	 ediff-toolbar-previous-difference
 ;;; ediff-util.el --- the core commands and utilities of ediff
 
-;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
+
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
       (make-local-variable 'ediff-window-setup-function)
       (make-local-variable 'ediff-keep-variants)
 
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (make-local-hook 'ediff-after-quit-hook-internal) ; xemacs form
+       nil ; emacs form
+       )
+
       ;; unwrap set up parameters passed as argument
       (while setup-parameters
 	(set (car (car setup-parameters)) (cdr (car setup-parameters)))
       (if (string-match "buffer" (symbol-name ediff-job-name))
 	  (setq ediff-keep-variants t))
 
-      (if ediff-xemacs-p
-	  (make-local-hook 'pre-command-hook))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (make-local-hook 'pre-command-hook) ; xemacs form
+       nil                                 ; emacs form
+       )
 
       (if (ediff-window-display-p)
 	  (add-hook 'pre-command-hook 'ediff-spy-after-mouse nil 'local))
 	      (set-buffer buffer-C)
 	      (insert-buffer buf)
 	      (funcall (ediff-with-current-buffer buf major-mode))
+	      (widen) ; merge buffer is always widened
 	      (add-hook 'local-write-file-hooks 'ediff-set-merge-mode nil t)
 	      )))
       (setq buffer-read-only nil    
       (if ediff-3way-job
 	  (ediff-with-current-buffer ediff-buffer-C
 	    (ediff-nuke-selective-display)
+	    ;; the merge bufer should never be narrowed
+	    ;; (it can happen if it is on rmail-mode or similar)
+	    (if (ediff-with-current-buffer control-buffer ediff-merge-job)
+		(widen))
 	    (run-hooks 'ediff-prepare-buffer-hook)
 	    ;; add control-buffer to the list of sessions
 	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
 		      (cons control-buffer
 			    ediff-this-buffer-ediff-sessions))) 
 	    (if ediff-make-buffers-readonly-at-startup
-		(setq buffer-read-only t))
+		(setq buffer-read-only t)
+	      (setq buffer-read-only nil))
 	    ))
 
       (if (ediff-buffer-live-p ediff-ancestor-buffer)
 			    ediff-this-buffer-ediff-sessions)))
 	    ))
       
-      ;; must come after setting up  ediff-narrow-bounds AND after
+      ;; the following must be after setting up  ediff-narrow-bounds AND after
       ;; nuking selective display
       (funcall ediff-setup-diff-regions-function file-A file-B file-C)
       (setq ediff-number-of-differences (length ediff-difference-vector-A))
     (if (stringp ediff-merge-store-file)
 	(progn
 	  ;; save before leaving ctl buffer
+	  (ediff-verify-file-merge-buffer ediff-merge-store-file)
 	  (setq merge-buffer-file ediff-merge-store-file) 
 	  (ediff-with-current-buffer ediff-buffer-C
 	    (set-visited-file-name merge-buffer-file))))
   ;; will not re-appear after our cleanup here.  Is there a way
   ;; to do "push" and "pop" toolbars ?  --marcpa  
   (if (ediff-use-toolbar-p)
-      (progn
-	(set-specifier bottom-toolbar (list (selected-frame) nil))
-	(set-specifier bottom-toolbar-visible-p (list (selected-frame) nil)))))
+      (ediff-cond-compile-for-xemacs-or-emacs
+       (progn ; xemacs
+	 (set-specifier bottom-toolbar (list (selected-frame) nil))
+	 (set-specifier bottom-toolbar-visible-p (list (selected-frame) nil)))
+       nil  ; emacs
+       )
+    ))
 
 ;; If wants to use toolbar, make it.
 ;; If not, zero the toolbar for XEmacs.
       (progn
 	(setq frame (or frame (selected-frame)))
 	(cond ((ediff-use-toolbar-p) ; this checks for XEmacs
-	       (set-specifier
-		bottom-toolbar
-		(list frame (if (ediff-3way-comparison-job)
-				ediff-toolbar-3way ediff-toolbar)))
-	       (set-specifier bottom-toolbar-visible-p (list frame t)) 
-	       (set-specifier bottom-toolbar-height
-			      (list frame ediff-toolbar-height)))
+	       (ediff-cond-compile-for-xemacs-or-emacs
+		(progn ; xemacs
+		  (set-specifier
+		   bottom-toolbar
+		   (list frame (if (ediff-3way-comparison-job)
+				   ediff-toolbar-3way ediff-toolbar)))
+		  (set-specifier bottom-toolbar-visible-p (list frame t)) 
+		  (set-specifier bottom-toolbar-height
+				 (list frame ediff-toolbar-height)))
+		nil ; emacs
+		)
+	       )
 	      ((ediff-has-toolbar-support-p)
-	       (set-specifier bottom-toolbar-height (list frame 0)))
+	       (ediff-cond-compile-for-xemacs-or-emacs
+		(set-specifier bottom-toolbar-height (list frame 0)) ; xemacs
+		nil                                                  ; emacs
+		)
+	       )
 	      ))
     ))
 	       
 
   (let* ((key1 (aref keys 0))
 	 (key2 (aref keys 1))
-	 (char1 (if (and ediff-xemacs-p (eventp key1)) (event-key key1) key1))
-	 (char2 (if (and ediff-xemacs-p (eventp key1)) (event-key key2) key2))
+	 (char1 (ediff-event-key key1))
+	 (char2 (ediff-event-key key2))
 	 ediff-verbose-p)
     (ediff-copy-diff ediff-current-difference
 		     (ediff-char-to-buftype char1)
 
   (ediff-delete-temp-files)
 				  
-  ;; Restore visibility range.  This affects only ediff-*-regions/windows.
+  ;; Restore the visibility range.  This affects only ediff-*-regions/windows.
   ;; Since for other job names ediff-visible-region sets
   ;; ediff-visible-bounds to ediff-wide-bounds, the settings below are
   ;; ignored for such jobs.
 
   (run-hooks 'ediff-cleanup-hook)
 
-  ;; now kill buffers A/B/C, if requested
-  (let ((ediff-keep-variants ediff-keep-variants))
-    (if reverse-default-keep-variants
-	(setq ediff-keep-variants (not ediff-keep-variants)))
-    (or ediff-keep-variants (ediff-janitor 'ask)))
+  (ediff-janitor
+   'ask
+   ;; reverse-default-keep-variants is t if the user quits with a prefix arg
+   (if reverse-default-keep-variants
+       (not ediff-keep-variants)
+     ediff-keep-variants))
 
   ;; one hook here is ediff-cleanup-mess, which kills the control buffer and
   ;; other auxiliary buffers. we made it into a hook to let the users do their
     (ediff-kill-buffer-carefully ctl-buf)
       
     (if (frame-live-p main-frame)
-	(progn
-	  (select-frame main-frame)
-	  (delete-other-windows)))
+	(select-frame main-frame))
     
     ;; display only if not visible
     (condition-case nil
     (condition-case nil
 	(or (ediff-get-visible-buffer-window buff-A)
 	    (progn
-	      (if (ediff-get-visible-buffer-window buff-B)
+	      (if (and (ediff-get-visible-buffer-window buff-B)
+		       (ediff-buffer-live-p buff-A))
 		  (funcall ediff-split-window-function))
 	      (switch-to-buffer buff-A)))
       (error))
 	(condition-case nil
 	    (or (ediff-get-visible-buffer-window buff-C)
 		(progn
-		  (if (or (ediff-get-visible-buffer-window buff-A)
-			  (ediff-get-visible-buffer-window buff-B))
+		  (if (and (or (ediff-get-visible-buffer-window buff-A)
+			       (ediff-get-visible-buffer-window buff-B))
+			   (ediff-buffer-live-p buff-C))
 		      (funcall ediff-split-window-function))
 		  (switch-to-buffer buff-C)
 		  (balance-windows)))
     (message "")
     ))
 
-(defun ediff-janitor (&optional ask)
+(defun ediff-janitor (ask keep-variants)
   "Kill buffers A, B, and, possibly, C, if these buffers aren't modified.
-In merge jobs, buffer C is never deleted.
-However, the side effect of cleaning up may be that you cannot compare the same
-buffer in two separate Ediff sessions: quitting one of them will delete this
-buffer in another session as well."
-  (or (not (ediff-buffer-live-p ediff-buffer-A))
-      (buffer-modified-p ediff-buffer-A)
-      (and ask
-	   (not (y-or-n-p (format "Kill buffer A [%s]? "
-				  (buffer-name ediff-buffer-A)))))
-      (ediff-kill-buffer-carefully ediff-buffer-A))
-  (or (not (ediff-buffer-live-p ediff-buffer-B))
-      (buffer-modified-p ediff-buffer-B)
-      (and ask
-	   (not (y-or-n-p (format "Kill buffer B [%s]? "
-				  (buffer-name ediff-buffer-B)))))
-      (ediff-kill-buffer-carefully ediff-buffer-B))
+In merge jobs, buffer C is not deleted here, but rather according to
+ediff-quit-merge-hook.
+A side effect of cleaning up may be that you should be careful when comparing
+the same buffer in two separate Ediff sessions: quitting one of them might
+delete this buffer in another session as well."
+  (ediff-dispose-of-variant-according-to-user
+   ediff-buffer-A 'A ask keep-variants)
+  (ediff-dispose-of-variant-according-to-user
+   ediff-buffer-B 'B ask keep-variants)
   (if ediff-merge-job  ; don't del buf C if merging--del ancestor buf instead
-      (or (not (ediff-buffer-live-p ediff-ancestor-buffer))
-	  (buffer-modified-p ediff-ancestor-buffer)
-	  (and ask
-	       (not (y-or-n-p (format "Kill the ancestor buffer [%s]? "
-				      (buffer-name ediff-ancestor-buffer)))))
-	  (ediff-kill-buffer-carefully ediff-ancestor-buffer))
-    (or (not (ediff-buffer-live-p ediff-buffer-C))
-	(buffer-modified-p ediff-buffer-C)
-	(and ask (not (y-or-n-p (format "Kill buffer C [%s]? "
-					(buffer-name ediff-buffer-C)))))
-	(ediff-kill-buffer-carefully ediff-buffer-C))))
+      (ediff-dispose-of-variant-according-to-user
+       ediff-ancestor-buffer 'Ancestor ask keep-variants)
+    (ediff-dispose-of-variant-according-to-user
+     ediff-buffer-C 'C ask keep-variants)
+    ))
+
+;; Kill the variant buffer, according to user directives (ask, kill
+;; unconditionaly, keep)
+;; BUFF is the buffer, BUFF-TYPE is either 'A, or 'B, 'C, 'Ancestor
+(defun ediff-dispose-of-variant-according-to-user (buff bufftype ask keep-variants)
+  ;; if this is indirect buffer, kill it and substitute with direct buf
+  (if (ediff-with-current-buffer buff ediff-temp-indirect-buffer)
+      (let ((wind (ediff-get-visible-buffer-window buff))
+	    (base (buffer-base-buffer buff))
+	    (modified-p (buffer-modified-p buff)))
+	(if (and (window-live-p wind) (ediff-buffer-live-p base))
+	    (set-window-buffer wind base))
+	;; Kill indirect buffer even if it is modified, because the base buffer
+	;; is still there. Note that if the base buffer is dead then so will be
+	;; the indirect buffer
+	(ediff-with-current-buffer buff 
+	  (set-buffer-modified-p nil))
+	(ediff-kill-buffer-carefully buff)
+	(ediff-with-current-buffer base
+	  (set-buffer-modified-p modified-p)))
+    ;; otherwise, ask or use the value of keep-variants
+    (or (not (ediff-buffer-live-p buff))
+	keep-variants
+	(buffer-modified-p buff)
+	(and ask
+	     (not (y-or-n-p (format "Kill buffer %S [%s]? "
+				    bufftype (buffer-name buff)))))
+	(ediff-kill-buffer-carefully buff))
+    ))
 
 (defun ediff-maybe-save-and-delete-merge (&optional save-and-continue)
   "Default hook to run on quitting a merge job.
 	(ediff-autostore-merges ; fake ediff-autostore-merges, if necessary
 	 (if save-and-continue t ediff-autostore-merges)))
     (if ediff-autostore-merges
-	(cond ((stringp ediff-merge-store-file)
+	(cond ((stringp merge-store-file)
 	       ;; store, ask to delete
 	       (ediff-write-merge-buffer-and-maybe-kill
 		ediff-buffer-C merge-store-file 'show-file save-and-continue))
 (defun ediff-write-merge-buffer-and-maybe-kill (buf file
 					       &optional
 					       show-file save-and-continue)
-  (ediff-with-current-buffer buf
-    (if (or (not (file-exists-p file))
-	    (y-or-n-p (format "File %s exists, overwrite? " file)))
-	(progn
-	  (write-region (point-min) (point-max) file)
-	  (if show-file
-	      (progn
-		(message "Merge buffer saved in: %s" file)
-		(set-buffer-modified-p nil)
-		(sit-for 3)))
-	  (if (and
-	       (not save-and-continue)
-	       (y-or-n-p "Merge buffer saved.  Now kill the buffer? "))
-	      (ediff-kill-buffer-carefully buf))))))
+  (if (not (eq (find-buffer-visiting file) buf))
+      (let ((warn-message
+	     (format "Another buffer is visiting file %s. Too dangerous to save the merge buffer"
+		     file)))
+	(beep)
+	(message warn-message)
+	(with-output-to-temp-buffer ediff-msg-buffer
+	  (princ "\n\n")
+	  (princ warn-message)
+	  (princ "\n\n")
+	  )
+	(sit-for 2))
+    (ediff-with-current-buffer buf
+      (if (or (not (file-exists-p file))
+	      (y-or-n-p (format "File %s exists, overwrite? " file)))
+	  (progn
+	    ;;(write-region (point-min) (point-max) file)
+	    (ediff-with-current-buffer buf
+	      (set-visited-file-name file)
+	      (save-buffer))
+	    (if show-file
+		(progn
+		  (message "Merge buffer saved in: %s" file)
+		  (set-buffer-modified-p nil)
+		  (sit-for 3)))
+	    (if (and
+		 (not save-and-continue)
+		 (y-or-n-p "Merge buffer saved.  Now kill the buffer? "))
+		(ediff-kill-buffer-carefully buf)))))
+    ))
 
 ;; The default way of suspending Ediff.
 ;; Buries Ediff buffers, kills all windows.
       )))
 
 
+
+(defun ediff-highlight-diff-in-one-buffer (n buf-type)
+  (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
+      (let* ((buff (ediff-get-buffer buf-type))
+	     (last (ediff-with-current-buffer buff (point-max)))
+	     (begin (ediff-get-diff-posn buf-type 'beg n))
+	     (end (ediff-get-diff-posn buf-type 'end n))
+	     (xtra (if (equal begin end) 1 0))
+	     (end-hilit (min last (+ end xtra)))
+	     (current-diff-overlay
+	      (symbol-value
+	       (ediff-get-symbol-from-alist
+		buf-type ediff-current-diff-overlay-alist))))
+
+	(if ediff-xemacs-p
+	    (ediff-move-overlay current-diff-overlay begin end-hilit)
+	  (ediff-move-overlay current-diff-overlay begin end-hilit buff))
+	(ediff-overlay-put current-diff-overlay 'priority
+			   (ediff-highest-priority begin end-hilit buff))
+	(ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
+
+	;; unhighlight the background overlay for diff n so it won't
+	;; interfere with the current diff overlay
+	(ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
+	)))
+
+
+(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
+  (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
+      (let ((current-diff-overlay
+	     (symbol-value
+	      (ediff-get-symbol-from-alist
+	       buf-type ediff-current-diff-overlay-alist)))
+	    (overlay
+	     (ediff-get-diff-overlay ediff-current-difference buf-type))
+	    )
+
+	(ediff-move-overlay current-diff-overlay 1 1)
+
+	;; rehighlight the overlay in the background of the
+	;; current difference region
+	(ediff-set-overlay-face
+	 overlay
+	 (if (and (ediff-has-face-support-p)
+		  ediff-use-faces ediff-highlight-all-diffs)
+	     (ediff-background-face buf-type ediff-current-difference)))
+	)))
+
+(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
+  (ediff-unselect-and-select-difference -1)
+  (if (and (ediff-has-face-support-p) ediff-use-faces)
+      (let* ((inhibit-quit t)
+	     (current-diff-overlay-var
+	      (ediff-get-symbol-from-alist
+	       buf-type ediff-current-diff-overlay-alist))
+	     (current-diff-overlay (symbol-value current-diff-overlay-var)))
+	(ediff-paint-background-regions 'unhighlight)
+	(if (ediff-overlayp current-diff-overlay)
+	    (ediff-delete-overlay current-diff-overlay))
+	(set current-diff-overlay-var nil)
+	)))
+
+
+(defsubst ediff-highlight-diff (n)
+  "Put face on diff N.  Invoked for X displays only."
+  (ediff-highlight-diff-in-one-buffer n 'A)
+  (ediff-highlight-diff-in-one-buffer n 'B)
+  (ediff-highlight-diff-in-one-buffer n 'C)
+  (ediff-highlight-diff-in-one-buffer n 'Ancestor)
+  )
+
+
+(defsubst ediff-unhighlight-diff ()
+  "Remove overlays from buffers A, B, and C."
+  (ediff-unhighlight-diff-in-one-buffer 'A)
+  (ediff-unhighlight-diff-in-one-buffer 'B)
+  (ediff-unhighlight-diff-in-one-buffer 'C)
+  (ediff-unhighlight-diff-in-one-buffer 'Ancestor)
+  )
+
+;; delete highlighting overlays, restore faces to their original form
+(defsubst ediff-unhighlight-diffs-totally ()
+  (ediff-unhighlight-diffs-totally-in-one-buffer 'A)
+  (ediff-unhighlight-diffs-totally-in-one-buffer 'B)
+  (ediff-unhighlight-diffs-totally-in-one-buffer 'C)
+  (ediff-unhighlight-diffs-totally-in-one-buffer 'Ancestor)
+  )
+
+
 ;; This is adapted from a similar function in `emerge.el'.
 ;; PROMPT should not have a trailing ': ', so that it can be modified
 ;; according to context.
 ;; If DEFAULT-FILE is set, it should be used as the default value.
 ;; If DEFAULT-DIR is non-nil, use it as the default directory.
 ;; Otherwise, use the value of Emacs' variable `default-directory.'
-(defun ediff-read-file-name (prompt default-dir default-file)
+(defun ediff-read-file-name (prompt default-dir default-file &optional no-dirs)
   ;; hack default-dir if it is not set
   (setq default-dir
 	(file-name-as-directory
 	      )
 	     default-dir
 	     ))
-    ;; If user enters a directory name, expand the default file in that
+    ;; If user entered a directory name, expand the default file in that
     ;; directory.  This allows the user to enter a directory name for the
     ;; B-file and diff against the default-file in that directory instead
     ;; of a DIRED listing!
     (if (and (file-directory-p f) default-file)
 	(setq f (expand-file-name
 		 (file-name-nondirectory default-file) f)))
+    (if (and no-dirs (file-directory-p f))
+	(error "File %s is a directory" f))
     f)) 
   
 ;; If PREFIX is given, then it is used as a prefix for the temp file
                (progn
 		 (if (or (file-exists-p file) (not keep-proposed-name))
 		     (setq file (make-temp-name proposed-name)))
-		 (write-region "" nil file nil 'silent nil 'excl)
+		 ;; the with-temp-buffer thing is a workaround for an XEmacs
+		 ;; bug: write-region complains that we are trying to visit a
+		 ;; file in an indirect buffer, failing to notice that the
+		 ;; VISIT flag is unset and that we are actually writing from a
+		 ;; string and not from any buffer.
+		 (with-temp-buffer
+		   (write-region "" nil file nil 'silent nil 'excl))
                  nil)
             (file-already-exists t))
       ;; the file was somehow created by someone else between
       (if (buffer-modified-p)
 	  ;; If buffer is not obsolete and is modified, offer to save
 	  (if (yes-or-no-p 
-	       (format "Buffer out of sync with visited file.  Save file %s? "
+	       (format "Buffer %s has been modified. Save it in file %s? "
+		       (buffer-name)
 		       buffer-file-name))
 	      (condition-case nil
 		  (save-buffer)
 	nil)
     ;; If buffer is obsolete, offer to revert
     (if (yes-or-no-p
-	 (format "Buffer is out of sync with visited file.  REVERT file %s? "
+	 (format "File %s was modified since visited by buffer %s.  REVERT file %s? "
+		 buffer-file-name
+		 (buffer-name)
 		 buffer-file-name))
 	(progn
 	  (if file-magic
 	  (revert-buffer t t))
       (error "Buffer out of sync for file %s" buffer-file-name))))