changeset 13131:b0cb28b64a3c

(ediff-toggle-read-only,ediff-read-file-name): replaced abbreviate-file-name with ediff-abbreviate-file-name. (ediff-documentation): bug fix. (ediff-setup,ediff-really-quit): modified to work with Ediff session groups. (ediff-quit,ediff-really-quit): now ask if the user wants to delete buffers.
author Michael Kifer <kifer@cs.stonybrook.edu>
date Fri, 06 Oct 1995 00:59:04 +0000
parents c43bacb1bd0a
children 7ed272c3c177
files lisp/ediff-util.el
diffstat 1 files changed, 608 insertions(+), 324 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ediff-util.el	Fri Oct 06 00:57:20 1995 +0000
+++ b/lisp/ediff-util.el	Fri Oct 06 00:59:04 1995 +0000
@@ -23,13 +23,14 @@
 ;;; Code:
 
 (require 'ediff-init)
+(require 'ediff-meta)
 
 
 ;;; Functions
 
 (defun ediff-mode ()
-  "Ediff mode is used by the Ediff file-difference package.
-It is entered only through one of the following commands:
+  "Ediff mode controls all operations in a single Ediff session.
+This mode is entered through one of the following commands:
 	`ediff'
 	`ediff-files'
 	`ediff-buffers'
@@ -58,7 +59,7 @@
   (kill-all-local-variables)
   (setq major-mode 'ediff-mode)
   (setq mode-name "Ediff")
-  (run-hooks 'ediff-mode-hooks))
+  (run-hooks 'ediff-mode-hook))
 
 (defun ediff-version ()
   "Return string describing the version of Ediff.
@@ -105,10 +106,6 @@
   (define-key ediff-mode-map [delete] 'ediff-previous-difference)
   (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
 					'ediff-previous-difference nil))
-  (define-key ediff-mode-map [f1] (if ediff-no-emacs-help-in-control-buffer
-				      'ediff-previous-difference nil))
-  (define-key ediff-mode-map [help] (if ediff-no-emacs-help-in-control-buffer
-					'ediff-previous-difference nil))
   (define-key ediff-mode-map "n" 'ediff-next-difference)
   (define-key ediff-mode-map " " 'ediff-next-difference)
   (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
@@ -116,6 +113,7 @@
   (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
   (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
   (define-key ediff-mode-map "q" 'ediff-quit)
+  (define-key ediff-mode-map "D" 'ediff-show-diff-output)
   (define-key ediff-mode-map "z" 'ediff-suspend)
   (define-key ediff-mode-map "\C-l" 'ediff-recenter)
   (define-key ediff-mode-map "|" 'ediff-toggle-split)
@@ -133,15 +131,19 @@
   (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
   (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
   (define-key ediff-mode-map "i" 'ediff-status-info)
-  (define-key ediff-mode-map "D" 'ediff-documentation)
+  (define-key ediff-mode-map "E" 'ediff-documentation)
   (define-key ediff-mode-map "?" 'ediff-toggle-help)
   (define-key ediff-mode-map "!" 'ediff-update-diffs)
+  (define-key ediff-mode-map "M" 'ediff-show-meta-buffer)
+  (define-key ediff-mode-map "R" 'ediff-show-registry)
   (or ediff-word-mode
       (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
   (define-key ediff-mode-map "a"  nil)
   (define-key ediff-mode-map "b"  nil)
   (define-key ediff-mode-map "r"  nil)
   (cond (ediff-merge-job
+	 ;; Will barf if no ancestor
+	 (define-key ediff-mode-map "/" 'ediff-show-ancestor)
 	 ;; In merging, we allow only A->C and B->C copying.
 	 (define-key ediff-mode-map "a" (function
 					 (lambda (arg)
@@ -204,18 +206,18 @@
 
   (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
 	
-  (define-key ediff-mode-map "k"   nil)
-  (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)
-  (run-hooks 'ediff-keymap-setup-hooks))
+  (run-hooks 'ediff-keymap-setup-hook))
 
 
 ;;; Setup functions
 
 (require 'ediff-wind)
 
+(or (boundp 'synchronize-minibuffers)
+    (defvar synchronize-minibuffers nil))
+
 ;; Common startup entry for all Ediff functions
 ;; It now returns control buffer so other functions can do post-processing
 (defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
@@ -252,13 +254,35 @@
       (make-local-variable 'ediff-default-variant)
       (make-local-variable 'ediff-merge-window-share)
       (make-local-variable 'ediff-window-setup-function)
+      (make-local-variable 'ediff-keep-variants)
+
+      ;; Don't delete variants in case of ediff-buffer-* jobs without asking.
+      ;; This is because u may loose work---dangerous.
+      (if (string-match "buffer" (symbol-name ediff-job-name))
+	  (setq ediff-keep-variants t))
+
+      ;; XEmacs has local-pre-command-hook
+      (if ediff-emacs-p
+	  (make-local-variable 'pre-command-hook))
+
+      (if ediff-emacs-p
+	  (add-hook 'pre-command-hook 'ediff-spy-after-mouse)
+	(add-hook 'local-pre-command-hook 'ediff-spy-after-mouse))
+      (setq ediff-mouse-pixel-position (mouse-pixel-position))
       
       ;; adjust for merge jobs
       (if ediff-merge-job
 	  (let ((buf
-		 ;; Use buf A even if `combined'. The right stuff is
+		 ;; If default variant is `combined', the right stuff is
 		 ;; inserted by ediff-do-merge
-		 (if (eq ediff-default-variant 'default-B) buffer-B buffer-A)))
+		 ;; Note: at some point, we tried to put ancestor buffer here
+		 ;; (which is currently buffer C. This didn't work right
+		 ;; because the merge buffer will contain lossage: diff regions
+		 ;; in the ancestor, which correspond to revisions that agree
+		 ;; in both buf A and B.
+		 (cond ((eq ediff-default-variant 'default-B)
+			buffer-B)
+		       (t buffer-A))))
 		 
 	    (setq ediff-split-window-function
 		  ediff-merge-split-window-function) 
@@ -298,13 +322,16 @@
 		 (string-match "[0-9]+" ediff-control-buffer-suffix)
 		 0))))))
 	   
-      (setq ediff-error-buffer (get-buffer-create (ediff-unique-buffer-name
-						   "*ediff-errors" "*")))
+      (setq ediff-error-buffer
+	    (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
       
       (ediff-eval-in-buffer buffer-A (ediff-strip-mode-line-format))
       (ediff-eval-in-buffer buffer-B (ediff-strip-mode-line-format))
       (if ediff-3way-job
 	  (ediff-eval-in-buffer buffer-C (ediff-strip-mode-line-format)))
+      (if (ediff-buffer-live-p ediff-ancestor-buffer)
+	  (ediff-eval-in-buffer ediff-ancestor-buffer
+	    (ediff-strip-mode-line-format)))
       
       (ediff-save-protected-variables) ; save variables to be restored on exit
       
@@ -341,34 +368,45 @@
       ;; These won't run if there are errors in diff
       (ediff-eval-in-buffer ediff-buffer-A
 	(ediff-nuke-selective-display)
-	(run-hooks 'ediff-prepare-buffer-hooks)
+	(run-hooks 'ediff-prepare-buffer-hook)
 	(if (ediff-eval-in-buffer control-buffer ediff-merge-job)
 	    (setq buffer-read-only t))
 	;; add control-buffer to the list of sessions--no longer used, but may
 	;; be used again in the future
-	(or (memq control-buffer ediff-this-buffer-control-sessions)
-	    (setq ediff-this-buffer-control-sessions
-		  (cons control-buffer ediff-this-buffer-control-sessions)))
+	(or (memq control-buffer ediff-this-buffer-ediff-sessions)
+	    (setq ediff-this-buffer-ediff-sessions
+		  (cons control-buffer ediff-this-buffer-ediff-sessions)))
 	)
       (ediff-eval-in-buffer ediff-buffer-B
 	(ediff-nuke-selective-display)
-	(run-hooks 'ediff-prepare-buffer-hooks)
+	(run-hooks 'ediff-prepare-buffer-hook)
 	(if (ediff-eval-in-buffer control-buffer ediff-merge-job)
 	    (setq buffer-read-only t))
 	;; 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)))
+	(or (memq control-buffer ediff-this-buffer-ediff-sessions)
+	    (setq ediff-this-buffer-ediff-sessions
+		  (cons control-buffer ediff-this-buffer-ediff-sessions)))
 	)
       (if ediff-3way-job
 	  (ediff-eval-in-buffer ediff-buffer-C
 	    (ediff-nuke-selective-display)
-	    (run-hooks 'ediff-prepare-buffer-hooks)
+	    (run-hooks 'ediff-prepare-buffer-hook)
 	    ;; add control-buffer to the list of sessions
-	    (or (memq control-buffer ediff-this-buffer-control-sessions)
-		(setq ediff-this-buffer-control-sessions
+	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
+		(setq ediff-this-buffer-ediff-sessions
 		      (cons control-buffer
-			    ediff-this-buffer-control-sessions))) 
+			    ediff-this-buffer-ediff-sessions))) 
+	    ))
+
+      (if (ediff-buffer-live-p ediff-ancestor-buffer)
+	  (ediff-eval-in-buffer ediff-ancestor-buffer
+	    (ediff-nuke-selective-display)
+	    (setq buffer-read-only t)
+	    (run-hooks 'ediff-prepare-buffer-hook)
+	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
+		(setq ediff-this-buffer-ediff-sessions
+		      (cons control-buffer
+			    ediff-this-buffer-ediff-sessions)))
 	    ))
       
       ;; must come after setting up  ediff-narrow-bounds AND after
@@ -381,9 +419,8 @@
       (ediff-make-current-diff-overlay 'B)
       (if ediff-3way-job
 	  (ediff-make-current-diff-overlay 'C))
-	  
-      (if (ediff-window-display-p)
-	  (ediff-init-var-faces))
+      (if ediff-merge-with-ancestor-job
+	  (ediff-make-current-diff-overlay 'Ancestor))
 	  
       (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
       
@@ -413,25 +450,16 @@
       (select-window ediff-control-window)
       (ediff-visible-region)
       
-      ;; The following is a hack to placate OS/2
-      ;; The problem is that OS/2 doesn't let us delete files used by other
-      ;; processes. Thus, in ediff-buffers and other functions, we can't
-      ;; delete temp files because they might be used by the asynchronous
-      ;; process that computes custom diffs. So, under OS/1 we have to wait
-      ;; for some time until custom diffs are done.
-      (if (eq system-type 'emx)
-	  (ediff-eval-in-buffer ediff-custom-diff-buffer
-	    (let ((proc (get-buffer-process (current-buffer))))
-	      (while (and (processp proc)
-			  (eq (process-status proc) 'run))
-		(message "Waiting for the diff program to quit")
-		(sleep-for 1))
-	      (message "")
-	      )))
-      
-      (run-hooks 'startup-hooks 'ediff-startup-hooks)
+      (run-hooks 'startup-hooks)
       (ediff-refresh-mode-lines)
-      (setq buffer-read-only t))
+      (setq buffer-read-only t)
+      (setq ediff-session-registry
+	    (cons control-buffer ediff-session-registry))
+      (ediff-update-registry)
+      (if (ediff-buffer-live-p ediff-meta-buffer)
+	  (ediff-update-meta-buffer ediff-meta-buffer))
+      (run-hooks 'ediff-startup-hook)
+      ) ; eval in control-buffer
     control-buffer))
       
       
@@ -490,10 +518,10 @@
 
 (defun ediff-set-help-message ()
   (setq ediff-long-help-message
-	(cond ((and ediff-long-help-message-custom
-		    (or (symbolp ediff-long-help-message-custom)
-			(consp ediff-long-help-message-custom)))
-	       (funcall ediff-long-help-message-custom))
+	(cond ((and ediff-long-help-message-function
+		    (or (symbolp ediff-long-help-message-function)
+			(consp ediff-long-help-message-function)))
+	       (funcall ediff-long-help-message-function))
 	      (ediff-word-mode 
 	       (concat ediff-long-help-message-head
 		       ediff-long-help-message-word-mode
@@ -515,12 +543,12 @@
 		       ediff-long-help-message-compare2
 		       ediff-long-help-message-tail))))
   (setq ediff-brief-help-message 
-	(cond ((and ediff-brief-help-message-custom
-		    (or (symbolp ediff-brief-help-message-custom)
-			(consp ediff-brief-help-message-custom)))
-	       (funcall ediff-brief-help-message-custom))
-	      ((stringp ediff-brief-help-message-custom)
-	       ediff-brief-help-message-custom)
+	(cond ((and ediff-brief-help-message-function
+		    (or (symbolp ediff-brief-help-message-function)
+			(consp ediff-brief-help-message-function)))
+	       (funcall ediff-brief-help-message-function))
+	      ((stringp ediff-brief-help-message-function)
+	       ediff-brief-help-message-function)
 	      ((ediff-multiframe-setup-p) ediff-brief-message-string)
 	      (t ; long brief msg, not multiframe --- put in the middle
 	       ediff-brief-message-string)
@@ -528,9 +556,7 @@
   (setq ediff-help-message (if ediff-prefer-long-help-message
 			       ediff-long-help-message
 			     ediff-brief-help-message))
-  (run-hooks 'ediff-display-help-hooks)
-  )
-
+  (run-hooks 'ediff-display-help-hook))
 
 
 
@@ -542,6 +568,11 @@
 to these buffers are not saved at this point---the user can do this later,
 if necessary."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
+  (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
+	   (not (y-or-n-p "Recompute differences during merge, really? ")))
+      (error "God forbid!"))
+      
   (let ((point-A (ediff-eval-in-buffer ediff-buffer-A (point)))
 	;;(point-B (ediff-eval-in-buffer ediff-buffer-B (point)))
 	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
@@ -580,38 +611,46 @@
     (if ediff-word-mode
 	(progn
 	  (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
-	  (ediff-eval-in-buffer tmp-buffer
-	    (setq file-A (ediff-make-temp-file "regA")))
+	  (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
 	  (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
-	  (ediff-eval-in-buffer tmp-buffer
-	    (setq file-B (ediff-make-temp-file "regB")))
+	  (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
 	  (if ediff-3way-job
 	      (progn
 		(ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
-		(ediff-eval-in-buffer tmp-buffer
-		  (setq file-C (ediff-make-temp-file "regC")))))
+		(setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
 	  )
       ;; not word-mode
-      (ediff-eval-in-buffer ediff-buffer-A
-	(setq file-A (ediff-make-temp-file buf-A-file-name)))
-      (ediff-eval-in-buffer ediff-buffer-B
-	(setq file-B (ediff-make-temp-file buf-B-file-name)))
+      (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
+      (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
       (if ediff-3way-job
-	  (ediff-eval-in-buffer ediff-buffer-C
-	    (setq file-C (ediff-make-temp-file buf-C-file-name))))
+	  (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
       )
 	
     (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
     (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
     (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
+    (ediff-clear-diff-vector
+     'ediff-difference-vector-Ancestor 'fine-diffs-also)
+    ;; let them garbage collect. we can't use the ancestor after recomputing
+    ;; the diffs.
+    (setq ediff-difference-vector-Ancestor nil
+	  ediff-ancestor-buffer nil
+	  ediff-state-of-merge nil)
+
     (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
     
-    ;; In case of merge job, full it into thinking that it is just doing
+    ;; In case of merge job, fool it into thinking that it is just doing
     ;; comparison
     (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
+	  (ediff-3way-comparison-job ediff-3way-comparison-job)
+	  (ediff-merge-job ediff-merge-job)
+	  (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
 	  (ediff-job-name ediff-job-name))
       (if ediff-merge-job
 	  (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
+		ediff-3way-comparison-job t
+		ediff-merge-job nil
+		ediff-merge-with-ancestor-job nil
 		ediff-job-name 'ediff-files3))
       (funcall ediff-setup-diff-regions-function file-A file-B file-C))
 	    
@@ -632,10 +671,12 @@
 (defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
   "Revert buffers A, B and C. Then rerun Ediff on file A and file B."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (let ((bufA ediff-buffer-A)
 	(bufB ediff-buffer-B)
 	(bufC ediff-buffer-C)
 	(ctl-buf ediff-control-buffer)
+	(keep-variants ediff-keep-variants)
 	(ancestor-buf ediff-ancestor-buffer)
 	(ancestor-job ediff-merge-with-ancestor-job)
 	(merge ediff-merge-job)
@@ -651,7 +692,10 @@
     (if merge
 	(progn
 	  (set-buffer ctl-buf)
-	  (ediff-really-quit)
+	  ;; the argument says whether to reverse the meaning of
+	  ;; ediff-keep-variants, i.e., ediff-really-quit runs here with
+	  ;; variants kept.
+	  (ediff-really-quit (not keep-variants))
 	  (kill-buffer bufC)
 	  (if ancestor-job
 	      (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
@@ -664,6 +708,7 @@
   "Bring the highlighted region of all buffers being compared into view.
 Reestablish the default three-window display."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   
   ;; force all minibuffer to display ediff's messages.
   ;; when xemacs implements minibufferless frames, this won't be necessary
@@ -682,10 +727,9 @@
 	   "You've killed an essential Ediff buffer---Please quit Ediff"
 	   (beep 1)))
       ))
-      
+  
   ;; set visibility range appropriate to this invocation of Ediff.
   (ediff-visible-region)
-  
   ;; raise
   (if (and (ediff-window-display-p)
 	   (symbolp this-command)
@@ -693,6 +737,8 @@
 	   ;; Either one of the display-changing commands
 	   (or (memq this-command
 		     '(ediff-recenter
+		       ediff-dir-action ediff-registry-action
+		       ediff-patch-action
 		       ediff-toggle-wide-display ediff-toggle-multiframe))
 	       ;; Or one of the movement cmds and prev cmd was an Ediff cmd
 	       ;; This avoids rasing frames unnecessarily.
@@ -712,35 +758,37 @@
 	    (raise-frame (window-frame ediff-window-C)))))
   (if (and (ediff-window-display-p)
 	   (frame-live-p ediff-control-frame)
+	   (not ediff-prefer-long-help-message)
 	   (not (ediff-frame-iconified-p ediff-control-frame)))
       (raise-frame ediff-control-frame))
   
   ;; Redisplay whatever buffers are showing, if there is a selected difference
-  (let* ((control-frame ediff-control-frame)
-	 (control-buf ediff-control-buffer))
+  (let ((control-frame ediff-control-frame)
+	(control-buf ediff-control-buffer))
     (if (and (ediff-buffer-live-p ediff-buffer-A)
 	     (ediff-buffer-live-p ediff-buffer-B)
 	     (or (not ediff-3way-job)
 		 (ediff-buffer-live-p ediff-buffer-C))
-	     (ediff-valid-difference-p))
+	     )
 	(progn
 	  (or no-rehighlight
 	      (ediff-select-difference ediff-current-difference))
-	    
+	  
 	  (ediff-recenter-one-window 'A)
 	  (ediff-recenter-one-window 'B)
 	  (if ediff-3way-job
 	      (ediff-recenter-one-window 'C))
 	  
-	  (if (and (ediff-multiframe-setup-p)
-		   (not (ediff-frame-iconified-p ediff-control-frame)))
-	      (progn
-		(ediff-reset-mouse control-frame)
-		(or ediff-xemacs-p
-		    (cond ((eq (ediff-device-type) 'ns)
-			   (unfocus-frame (selected-frame)))
-			  (t (unfocus-frame))))
-		))
+	  (ediff-eval-in-buffer control-buf
+	    (ediff-recenter-ancestor) ; it checks if ancestor is alive
+	    
+	    (if (and (ediff-multiframe-setup-p)
+		     (not ediff-prefer-long-help-message)
+		     (not (ediff-frame-iconified-p ediff-control-frame)))
+		;; never grab mouse on quit in this place
+		(ediff-reset-mouse
+		 control-frame
+		 (eq this-command 'ediff-quit))))
 	  ))
     (ediff-eval-in-buffer control-buf
       (ediff-refresh-mode-lines))
@@ -749,31 +797,54 @@
 ;; this function returns to the window it was called from
 ;; (which was the control window)
 (defun ediff-recenter-one-window (buf-type)
-  (let* (;; context must be saved before switching to windows A/B/C
-	 (ctl-wind (selected-window))
-	 (shift (ediff-overlay-start
-		 (ediff-get-value-according-to-buffer-type 
-		  buf-type ediff-narrow-bounds)))
-	 (job-name ediff-job-name)
-	 (control-buf ediff-control-buffer)
-	 (window-name (intern (format "ediff-window-%S" buf-type)))
-	 (window (if (window-live-p (symbol-value window-name))
-		     (symbol-value window-name))))
-	 
-    (if (and window ediff-windows-job)
-	(set-window-start window shift))
-    (if window
-	(progn
-	  (select-window window)
-	  (ediff-deactivate-mark)
-	  (ediff-position-region
-	   (ediff-get-diff-posn buf-type 'beg nil control-buf)
-	   (ediff-get-diff-posn buf-type 'end nil control-buf)
-	   (ediff-get-diff-posn buf-type 'beg nil control-buf)
-	   job-name
-	   )))
-    (select-window ctl-wind)
-    ))
+  (if (ediff-valid-difference-p)
+      ;; context must be saved before switching to windows A/B/C
+      (let* ((ctl-wind (selected-window))
+	     (shift (ediff-overlay-start
+		     (ediff-get-value-according-to-buffer-type 
+		      buf-type ediff-narrow-bounds)))
+	     (job-name ediff-job-name)
+	     (control-buf ediff-control-buffer)
+	     (window-name (intern (format "ediff-window-%S" buf-type)))
+	     (window (if (window-live-p (symbol-value window-name))
+			 (symbol-value window-name))))
+	
+	(if (and window ediff-windows-job)
+	    (set-window-start window shift))
+	(if window
+	    (progn
+	      (select-window window)
+	      (ediff-deactivate-mark)
+	      (ediff-position-region
+	       (ediff-get-diff-posn buf-type 'beg nil control-buf)
+	       (ediff-get-diff-posn buf-type 'end nil control-buf)
+	       (ediff-get-diff-posn buf-type 'beg nil control-buf)
+	       job-name
+	       )))
+	(select-window ctl-wind)
+	)))
+
+(defun ediff-recenter-ancestor ()
+  ;; do half-hearted job by recentering the ancestor buffer, if it is alive and
+  ;; visible.
+  (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
+	   (ediff-valid-difference-p))
+      (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer))
+	    (ctl-wind (selected-window))
+	    (job-name ediff-job-name)
+	    (ctl-buf ediff-control-buffer))
+	(ediff-eval-in-buffer ediff-ancestor-buffer
+	  (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf))
+	  (if window
+	      (progn
+		(select-window window)
+		(ediff-position-region
+		 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
+		 (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf)
+		 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
+		 job-name))))
+	(select-window ctl-wind)
+	)))
 
 	
 ;; This will have to be refined for 3way jobs
@@ -781,6 +852,7 @@
   "Toggle vertical/horizontal window split. 
 Does nothing if file-A and file-B are in different frames."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let* ((wind-A (if (window-live-p ediff-window-A) ediff-window-A))
 	 (wind-B (if (window-live-p ediff-window-B) ediff-window-B))
 	 (wind-C (if (window-live-p ediff-window-C) ediff-window-C))
@@ -804,6 +876,7 @@
   "Switch between highlighting using ASCII flags and highlighting using faces.
 On a dumb terminal, switches between ASCII highlighting and no highlighting." 
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (if (not (ediff-window-display-p))
       (if (eq ediff-highlighting-style 'ascii)
 	  (progn
@@ -828,21 +901,8 @@
 		 ediff-highlight-all-diffs t)))
 		 
     (if (and ediff-use-faces ediff-highlight-all-diffs)
-	(if (not (face-differs-from-default-p 'ediff-odd-diff-face-A-var))
-	    (progn
-	      (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
-	      (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
-	      (copy-face ediff-odd-diff-face-C 'ediff-odd-diff-face-C-var)
-	      (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
-	      (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)
-	      (copy-face ediff-even-diff-face-C 'ediff-even-diff-face-C-var)
-	      ))
-      (copy-face 'default 'ediff-odd-diff-face-A-var)
-      (copy-face 'default 'ediff-odd-diff-face-B-var)
-      (copy-face 'default 'ediff-odd-diff-face-C-var)
-      (copy-face 'default 'ediff-even-diff-face-A-var)
-      (copy-face 'default 'ediff-even-diff-face-B-var)
-      (copy-face 'default 'ediff-even-diff-face-C-var))
+	(ediff-color-background-regions)
+      (ediff-color-background-regions 'unhighlight))
     
     (ediff-unselect-and-select-difference
      ediff-current-difference 'select-only))
@@ -851,6 +911,7 @@
 (defun ediff-toggle-autorefine ()
   "Toggle auto-refine mode."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (if ediff-word-mode
       (error "No fine differences in this mode"))
   (cond ((eq ediff-auto-refine 'nix)
@@ -865,11 +926,25 @@
 	 (message "Refinements are HIDDEN")
 	 (setq ediff-auto-refine 'nix))
 	))
+
+(defun ediff-show-ancestor ()
+  "Show the ancestor buffer in a suitable window."
+  (interactive)
+  (ediff-recenter)
+  (or (ediff-buffer-live-p ediff-ancestor-buffer)
+      (if ediff-merge-with-ancestor-job
+	  (error "Lost connection to ancestor buffer...sorry")
+	(error "Not merging with ancestor")))
+  (let (wind)
+    (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
+	   (raise-frame (window-frame wind)))
+	  (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
 	
 (defun ediff-make-or-kill-fine-diffs (arg)
   "Compute fine diffs. With negative prefix arg, kill fine diffs.
 In both cases, operates on the currrent difference region." 
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (cond ((eq arg '-)
 	 (ediff-clear-fine-differences ediff-current-difference))
 	((and (numberp arg) (< arg 0))
@@ -880,6 +955,7 @@
 (defun ediff-toggle-help ()
   "Toggle short/long help message."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let (buffer-read-only)
     (erase-buffer)
     (setq ediff-prefer-long-help-message (not ediff-prefer-long-help-message))
@@ -901,6 +977,7 @@
 If optional argument BUF is specified, toggle read-only in that buffer instead
 of the current buffer."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let ((ctl-buf (if (null buf) (current-buffer))))
     (or buf (ediff-recenter))
     (or buf
@@ -931,7 +1008,7 @@
 			(y-or-n-p
 			 (format
 			  "File %s is under version control. Check it out? "
-			  (abbreviate-file-name file))))
+			  (ediff-abbreviate-file-name file))))
 		   ;; if we checked the file out, we should also change the
 		   ;; original state of buffer-read-only to nil.  If we don't
 		   ;; do this, the mode line will show %%, since the file was
@@ -946,7 +1023,7 @@
 		   (beep 1) (beep 1)
 		   (message
 		    "Boy, this is risky! Better don't change this file...")
-		   (sit-for 3))))
+		   (sit-for 3)))) ; let the user see the warning
 	(if (and toggle-ro-cmd 
 		 (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
 	    (save-excursion
@@ -961,7 +1038,7 @@
 		 (file-exists-p file)
 		 (not (file-writable-p file)))
 	    (message "Warning: file %s is read-only"
-		     (abbreviate-file-name file) (beep 1)))
+		     (ediff-abbreviate-file-name file) (beep 1)))
 	))))
   
 
@@ -985,6 +1062,7 @@
 (defun ediff-swap-buffers ()
   "Rotate the display of buffers A, B, and C."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (if (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
       (let ((buf ediff-buffer-A)
 	    (values ediff-buffer-values-orig-A)
@@ -1089,6 +1167,7 @@
   "Toggle wide/regular display.
 This is especially useful when comparing buffers side-by-side."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (or (ediff-window-display-p)
       (error "%sEmacs is not running as a window application"
 	     (if ediff-emacs-p "" "X")))
@@ -1099,7 +1178,7 @@
 	(ediff-eval-in-buffer ctl-buf
 	  (modify-frame-parameters
 	   ediff-wide-display-frame ediff-wide-display-orig-parameters)
-	  (sit-for (if ediff-xemacs-p 0.4 0))
+	  ;;(sit-for (if ediff-xemacs-p 0.4 0))
 	  ;; restore control buf, since ctl window may have been deleted
 	  ;; during resizing
 	  (set-buffer ctl-buf)
@@ -1107,7 +1186,7 @@
 		ediff-window-B nil) ; force update of window config
 	  (ediff-recenter 'no-rehighlight))
       (funcall ediff-make-wide-display-function)
-      (sit-for (if ediff-xemacs-p 0.4 0))
+      ;;(sit-for (if ediff-xemacs-p 0.4 0))
       (ediff-eval-in-buffer ctl-buf
 	(setq ediff-window-B nil) ; force update of window config
 	(ediff-recenter 'no-rehighlight)))))
@@ -1116,6 +1195,7 @@
   "Switch from the multiframe display to single-frame display and back.
 This is primarily for debugging, but one can use it for fun, too."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (or (ediff-window-display-p)
       (error "%sEmacs is not running as a window application"
 	     (if ediff-emacs-p "" "X")))
@@ -1131,6 +1211,7 @@
 (defun ediff-toggle-show-clashes-only ()
   "Toggle the mode where only the regions where both buffers differ with the ancestor are shown."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (if (not ediff-merge-with-ancestor-job)
       (error "This command makes sense only when merging with an ancestor"))
   (setq ediff-show-clashes-only (not ediff-show-clashes-only))
@@ -1209,23 +1290,26 @@
 	 (wind-A ediff-window-A)
 	 (wind-B ediff-window-B)
 	 (wind-C ediff-window-C)
-	 (three-way ediff-3way-job))
+	 (coefA (ediff-get-region-size-coefficient 'A operation))
+	 (coefB (ediff-get-region-size-coefficient 'B operation))
+	 (three-way ediff-3way-job)
+	 (coefC (if three-way
+		    (ediff-get-region-size-coefficient 'C operation))))
 	     
     (select-window wind-A)
     (condition-case nil
-	(funcall operation arg)
+	(funcall operation (round (* coefA arg)))
       (error))
     (select-window wind-B)
     (condition-case nil
-	(funcall operation arg)
+	(funcall operation (round (* coefB arg)))
       (error))
     (if three-way
 	(progn
 	  (select-window wind-C)
 	  (condition-case nil
-	      (funcall operation arg)
+	      (funcall operation (round (* coefC arg)))
 	    (error))))
-    
     (select-window wind)))
 
 (defun ediff-scroll-vertically (&optional arg)
@@ -1233,6 +1317,7 @@
 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
 the height of window-A."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   
   ;; make sure windows aren't dead
   (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
@@ -1254,14 +1339,14 @@
        ;; use it
        (prefix-numeric-value arg)
      ;; if not, see if we can determine a default amount (the window height)
-     (let* (default-amount)
+     (let (default-amount)
        (setq default-amount 
-	     (- (min (window-height ediff-window-A)
-		     (window-height ediff-window-B)
-		     (if ediff-3way-job
-			 (window-height ediff-window-C)
-		       123) ; some large number
-		     )
+	     (- (/ (min (window-height ediff-window-A)
+			(window-height ediff-window-B)
+			(if ediff-3way-job
+			    (window-height ediff-window-C)
+			  500)) ; some large number
+		   2)
 		1 next-screen-context-lines))
        ;; window found
        (if arg
@@ -1276,6 +1361,7 @@
 If an argument is given, that is how many columns are scrolled, else nearly
 the width of the A/B/C windows."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   
   ;; make sure windows aren't dead
   (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
@@ -1356,11 +1442,61 @@
     (goto-char pos)
     ))
 
+;; get number of lines from window start to region end
+(defun ediff-get-lines-to-region-end (buf-type &optional n ctl-buf)
+  (or n (setq n ediff-current-difference))
+  (or ctl-buf (setq ctl-buf ediff-control-buffer))
+  (ediff-eval-in-buffer ctl-buf
+    (let* ((buf (ediff-get-buffer buf-type))
+	   (wind (eval (intern (format "ediff-window-%S" buf-type))))
+	   (beg (window-start wind))
+	   (end (ediff-get-diff-posn buf-type 'end))
+	   lines)
+      (ediff-eval-in-buffer buf
+	(if (< beg end)
+	    (setq lines (count-lines beg end))
+	  (setq lines 0))
+	lines
+	))))
+
+;; get number of lines from window end to region start
+(defun ediff-get-lines-to-region-start (buf-type &optional n ctl-buf)
+  (or n (setq n ediff-current-difference))
+  (or ctl-buf (setq ctl-buf ediff-control-buffer))
+  (ediff-eval-in-buffer ctl-buf
+    (let* ((buf (ediff-get-buffer buf-type))
+	   (wind (eval (intern (format "ediff-window-%S" buf-type))))
+	   (end (window-end wind))
+	   (beg (ediff-get-diff-posn buf-type 'beg)))
+      (ediff-eval-in-buffer buf
+	(if (< beg end) (count-lines beg end) 0))
+      )))
+
+
+(defun ediff-get-region-size-coefficient (buf-type op &optional n ctl-buf)
+  (ediff-eval-in-buffer (or ctl-buf ediff-control-buffer)
+    (let* ((func (cond ((eq op 'scroll-down) 'ediff-get-lines-to-region-start)
+		       ((eq op 'scroll-up) 'ediff-get-lines-to-region-end)
+		       (t '(lambda (a b c) 0))))
+	   (max-lines (max (funcall func 'A n ctl-buf)
+			   (funcall func 'B n ctl-buf)
+			   (if (ediff-buffer-live-p ediff-buffer-C)
+			       (funcall func 'C n ctl-buf)
+			     0))))
+      ;; this covers the horizontal coefficient as well:
+      ;; if max-lines = 0 then coef = 1
+      (if (> max-lines 0)
+	  (/ (+ (funcall func buf-type n ctl-buf) 0.0)
+	     (+ max-lines 0.0))
+	1)
+      )))
+
 
 (defun ediff-next-difference (&optional arg)
   "Advance to the next difference. 
 With a prefix argument, go back that many differences."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (if (< ediff-current-difference ediff-number-of-differences)
       (let ((n (min ediff-number-of-differences
 		    (+ ediff-current-difference (if arg arg 1))))
@@ -1397,6 +1533,7 @@
   "Go to the previous difference. 
 With a prefix argument, go back that many differences."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (if (> ediff-current-difference -1)
       (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
 	    regexp-skip)
@@ -1431,6 +1568,7 @@
 (defun ediff-jump-to-difference (difference-number)
   "Go to the difference specified as a prefix argument."
   (interactive "p")
+  (ediff-barf-if-not-control-buffer)
   (setq difference-number (1- difference-number))
   (if (and (>= difference-number -1)
 	   (< difference-number (1+ ediff-number-of-differences)))
@@ -1442,6 +1580,7 @@
 The type of buffer depends on last command character \(a, b, or c\) that
 invoked this command."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let ((buf-type (ediff-char-to-buftype last-command-char)))
     (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
 	
@@ -1489,17 +1628,20 @@
 If the second optional argument, a 2-character string, is given, use it to
 determine the source and the target buffers instead of the command keys."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (or keys (setq keys (this-command-keys)))
   (if arg
       (ediff-jump-to-difference arg))
   (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)))
+	 (char2 (if (and ediff-xemacs-p (eventp key1)) (event-key key2) key2))
+	 ediff-verbose-p)
     (ediff-copy-diff ediff-current-difference
 		     (ediff-char-to-buftype char1)
 		     (ediff-char-to-buftype char2))
-    (ediff-recenter 'no-rehighlight)))
+    ;; recenter with rehighlighting, but no messages
+    (ediff-recenter)))
 
 
 ;; Copy diff N from FROM-BUF-TYPE \(given as A, B or C\) to TO-BUF-TYPE.
@@ -1544,6 +1686,7 @@
 		    ;; these two insert a dummy char to overcome a bug in
 		    ;; XEmacs, which sometimes prevents 0-length extents
 		    ;; from sensing insertion at its end-points.
+		    ;; (need to check if 19.12 still has the bug)
 		    (if ediff-xemacs-p
 			(progn
 			  (goto-char reg-to-delete-end)
@@ -1573,7 +1716,7 @@
 			    (car conds)
 			    (mapconcat 'prin1-to-string (cdr conds) " "))
 		   (beep 1)
-		   (sit-for 2)
+		   (sit-for 2) ; let the user see the error msg
 		   (setq saved-p nil)
 		   )))
       )
@@ -1665,6 +1808,7 @@
 	    ;; these two insert a dummy char to overcome a bug in XEmacs,
 	    ;; which sometimes prevents 0-length extents from sensing
 	    ;; insertion at its end-points.
+	    ;; (need to check if 19.12 still has the bug)
 	    (if ediff-xemacs-p
 		(progn
 		  (goto-char reg-end)
@@ -1720,30 +1864,35 @@
 If the second optional argument, a character, is given, use it to
 determine the target buffer instead of last-command-char"
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (if arg
       (ediff-jump-to-difference arg))
   (ediff-pop-diff ediff-current-difference 
 		  (ediff-char-to-buftype (or key last-command-char)))
-  (ediff-recenter 'no-rehighlight))
+  ;; recenter with rehighlighting, but no messages
+  (let (ediff-verbose-p)
+    (ediff-recenter)))
   
 (defun ediff-toggle-regexp-match ()
   "Toggle between focusing and hiding of difference regions that match
 a regular expression typed in by the user."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let ((regexp-A "")
 	(regexp-B "")
 	(regexp-C "")
 	msg-connective alt-msg-connective alt-connective)
     (cond
      ((or (and (eq ediff-skip-diff-region-function
-		   'ediff-focus-on-regexp-matches)
+		   'ediff-focus-on-regexp-matches-function)
 	       (eq last-command-char ?f))
-	  (and (eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
+	  (and (eq ediff-skip-diff-region-function
+		   ediff-hide-regexp-matches-function)
 	       (eq last-command-char ?h)))
       (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
+      (setq ediff-skip-diff-region-function ediff-hide-regexp-matches-function
 	    regexp-A 
 	    (read-string
 	     (format 
@@ -1769,18 +1918,20 @@
 	      alt-connective 'and))
       (if (y-or-n-p
 	   (format
-	    "Hiding diff regions that match %s regexps. Use %s instead? "
+	    "Ignore regions that match %s regexps, OK? "
 	    msg-connective alt-msg-connective))
-	  (progn
-	    (setq ediff-hide-regexp-connective alt-connective)
-	    (message "Hiding diff regions that match %s regexps"
-		     alt-msg-connective))
-	(message "Hiding diff regions that match %s regexps" msg-connective))
+	  (message "Will ignore regions that match %s regexps" msg-connective)
+	(setq ediff-hide-regexp-connective alt-connective)
+	(message "Will ignore regions that match %s regexps"
+		 alt-msg-connective)) 
+
       (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
       (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
       (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
+
      ((eq last-command-char ?f)
-      (setq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches
+      (setq ediff-skip-diff-region-function
+	    ediff-focus-on-regexp-matches-function
 	    regexp-A 
 	    (read-string
 	     (format 
@@ -1806,20 +1957,21 @@
 	      alt-connective 'and))
       (if (y-or-n-p
 	   (format
-	    "Focusing on diff regions that match %s regexps. Use %s instead? "
+	    "Focus on regions that match %s regexps, OK? "
 	    msg-connective alt-msg-connective))
-	  (progn
-	    (setq ediff-focus-regexp-connective alt-connective)
-	    (message "Focusing on diff regions that match %s regexps" 
-		     alt-msg-connective))
-	(message "Focusing on diff regions that match %s regexps"
-		 msg-connective))
+	  (message "Will focus on regions that match %s regexps"
+		   msg-connective)
+	(setq ediff-focus-regexp-connective alt-connective)
+	(message "Will focus on regions that match %s regexps" 
+		 alt-msg-connective))
+
       (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
       (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))
       (or (string= regexp-C "") (setq ediff-regexp-focus-C regexp-C))))))
       
 (defun ediff-toggle-skip-similar ()
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (if (not (eq ediff-auto-refine 'on))
       (error
        "Can't skip over whitespace regions: first turn auto-refining on"))
@@ -1915,25 +2067,35 @@
 
 ;;; Quitting, suspending, etc.
 
-(defun ediff-quit ()
+(defun ediff-quit (reverse-default-keep-variants)
   "Finish an Ediff session and exit Ediff.
 Unselects the selected difference, if any, restores the read-only and modified
 flags of the compared file buffers, kills Ediff buffers for this session
-\(but not buffers A, B, C\)."
-  (interactive)
+\(but not buffers A, B, C\).
+
+If `ediff-keep-variants' is nil, the user will be asked whether the buffers
+containing the variants should be removed \(if they haven't been modified\). 
+If it is t, they will be preserved unconditionally. A prefix argument, 
+temporarily reverses the meaning of this variable."
+  (interactive "P")
+  (ediff-barf-if-not-control-buffer)
   (if (prog1
-	  (y-or-n-p "Do you really want to exit Ediff? ")
+	  (y-or-n-p
+	   (format "Quit this Ediff session%s? "
+		   (if (ediff-buffer-live-p ediff-meta-buffer)
+		       " & show containing session group" "")))
 	(message ""))
-      (ediff-really-quit)))
+      (ediff-really-quit reverse-default-keep-variants)))
 
 
 ;; Perform the quit operations.
-(defun ediff-really-quit ()
+(defun ediff-really-quit (reverse-default-keep-variants)
   (ediff-unhighlight-diffs-totally)
   (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
   (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
   (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
-  
+  (ediff-clear-diff-vector 'ediff-difference-vector-Ancestor 'fine-diffs-also)
+
   (ediff-delete-temp-files)
 				  
   ;; Restore visibility range. This affects only ediff-*-regions/windows.
@@ -1956,11 +2118,12 @@
 	  ediff-narrow-bounds)
   
   ;; restore buffer mode line id's in buffer-A/B/C
-  (let ((control-buffer ediff-control-buffer))
+  (let ((control-buffer ediff-control-buffer)
+	(meta-buffer ediff-meta-buffer))
     (condition-case nil
 	(ediff-eval-in-buffer ediff-buffer-A
-	  (setq ediff-this-buffer-control-sessions 
-		(delq control-buffer ediff-this-buffer-control-sessions))
+	  (setq ediff-this-buffer-ediff-sessions 
+		(delq control-buffer ediff-this-buffer-ediff-sessions))
 	  (kill-local-variable 'mode-line-buffer-identification)
 	  (kill-local-variable 'mode-line-format)
 	  )
@@ -1968,8 +2131,8 @@
       
     (condition-case nil
 	(ediff-eval-in-buffer ediff-buffer-B
-	  (setq ediff-this-buffer-control-sessions 
-		(delq control-buffer ediff-this-buffer-control-sessions))
+	  (setq ediff-this-buffer-ediff-sessions 
+		(delq control-buffer ediff-this-buffer-ediff-sessions))
 	  (kill-local-variable 'mode-line-buffer-identification)
 	  (kill-local-variable 'mode-line-format)
 	  )
@@ -1977,16 +2140,39 @@
     
     (condition-case nil
 	(ediff-eval-in-buffer ediff-buffer-C
+	  (setq ediff-this-buffer-ediff-sessions 
+		(delq control-buffer ediff-this-buffer-ediff-sessions))
+	  (kill-local-variable 'mode-line-buffer-identification)
+	  (kill-local-variable 'mode-line-format)
+	  )
+      (error))
+
+    (condition-case nil
+	(ediff-eval-in-buffer ediff-ancestor-buffer
+	  (setq ediff-this-buffer-ediff-sessions 
+		(delq control-buffer ediff-this-buffer-ediff-sessions))
 	  (kill-local-variable 'mode-line-buffer-identification)
 	  (kill-local-variable 'mode-line-format)
 	  )
       (error))
-    )
+
+  (setq ediff-session-registry
+	(delq ediff-control-buffer ediff-session-registry))
+  (ediff-update-registry)
   ;; restore state of buffers to what it was before ediff
   (ediff-restore-protected-variables)
   ;; good place to kill buffers A/B/C
-  (run-hooks 'ediff-cleanup-hooks)
-  (run-hooks 'ediff-quit-hooks))
+  (run-hooks 'ediff-cleanup-hook)
+  (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)))
+
+  (run-hooks 'ediff-quit-hook)
+  (ediff-cleanup-meta-buffer meta-buffer)
+  (if (ediff-buffer-live-p meta-buffer)
+      (ediff-show-meta-buffer meta-buffer))
+  ))
   
   
 (defun ediff-delete-temp-files ()
@@ -2049,7 +2235,7 @@
     (message "")
     ))
 
-(defun ediff-janitor ()
+(defun ediff-janitor (&optional ask)
   "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
@@ -2057,21 +2243,32 @@
 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))
   (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))))
 
 ;; The default way of suspending Ediff.
 ;; Buries Ediff buffers, kills all windows.
-(defun ediff-default-suspend-hook ()
+(defun ediff-default-suspend-function ()
   (let* ((buf-A ediff-buffer-A)
 	 (buf-B ediff-buffer-B)
 	 (buf-C ediff-buffer-C)
@@ -2123,16 +2320,19 @@
 buffer and then type \\[ediff-recenter].  Ediff will automatically set
 up an appropriate window config."
   (interactive)
-  (let ((key (substitute-command-keys "\\[ediff-recenter]")))
-  (run-hooks 'ediff-suspend-hooks)
+  (ediff-barf-if-not-control-buffer)
+  (run-hooks 'ediff-suspend-hook)
   (message
-   "To resume, switch to Ediff Control Panel and hit `%s'" key)))
+   "To resume, type M-x eregistry and select the desired Ediff session"))
 
 
 (defun ediff-status-info ()
   "Show the names of the buffers or files being operated on by Ediff.
 Hit \\[ediff-recenter] to reset the windows afterward."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
+  (save-excursion
+    (ediff-skip-unsuitable-frames))
   (with-output-to-temp-buffer " *ediff-info*"
     (princ (ediff-version))
     (princ "\n\n")
@@ -2155,6 +2355,16 @@
 	       (format "File C = %S\n" buffer-file-name))
 	    (princ 
 	     (format "Buffer C = %S\n" (buffer-name))))))
+    (princ (format "Customized diff output %s\n"
+		   (if (ediff-buffer-live-p ediff-custom-diff-buffer)
+		       (concat "\tin buffer "
+			       (buffer-name ediff-custom-diff-buffer))
+		     "is not available")))
+    (princ (format "Plain diff output %s\n"
+		   (if (ediff-buffer-live-p ediff-diff-buffer)
+		       (concat "\tin buffer "
+			       (buffer-name ediff-diff-buffer))
+		     "is not available")))
 			      
     (let* ((A-line (ediff-eval-in-buffer ediff-buffer-A
 		     (1+ (count-lines (point-min) (point)))))
@@ -2182,7 +2392,8 @@
     
     (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
 	   (princ "\nSelective browsing by regexp is off.\n"))
-	  ((eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
+	  ((eq ediff-skip-diff-region-function
+	       ediff-hide-regexp-matches-function)
 	   (princ
 	    "\nIgnoring regions that match")
 	   (princ
@@ -2190,7 +2401,8 @@
 	     "\n\t regexp `%s' in buffer A  %S\n\t regexp `%s' in buffer B\n"
 	     ediff-regexp-hide-A ediff-hide-regexp-connective
 	     ediff-regexp-hide-B)))
-	  ((eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
+	  ((eq ediff-skip-diff-region-function
+	       ediff-focus-on-regexp-matches-function)
 	   (princ
 	    "\nFocusing on regions that match")
 	   (princ
@@ -2203,7 +2415,11 @@
     (princ
      (format "\nBugs/suggestions: type `%s' while in Ediff Control Panel."
 	     (substitute-command-keys "\\[ediff-submit-report]")))
-    ))
+    ) ; with output
+  (if (frame-live-p ediff-control-frame)
+      (ediff-reset-mouse ediff-control-frame))
+  (if (window-live-p ediff-control-window)
+      (select-window ediff-control-window)))
     
 (defun ediff-documentation ()
   "Jump to Ediff's Info file."
@@ -2215,7 +2431,7 @@
     (condition-case nil
 	(progn
 	  (pop-to-buffer (get-buffer-create "*info*"))
-	  (info "ediff")
+	  (info "ediff.info")
 	  (message "Type `i' to search for a specific topic"))
       (error (beep 1)
 	     (with-output-to-temp-buffer " *ediff-info*"
@@ -2228,7 +2444,7 @@
 	     (if (window-live-p ctl-window)
 		 (progn
 		   (select-window ctl-window)
-		   (switch-to-buffer ctl-buf)))))))
+		   (set-window-buffer ctl-window ctl-buf)))))))
     
 
 
@@ -2255,10 +2471,14 @@
 	  (if ediff-3way-job
 	      (ediff-place-flags-in-buffer
 	       'C ediff-buffer-C ediff-control-buffer n))
+	  (if (ediff-buffer-live-p ediff-ancestor-buffer)
+	      (ediff-place-flags-in-buffer
+	       'Ancestor ediff-ancestor-buffer
+	       ediff-control-buffer n))
 	  ) 
 				       
 	(ediff-install-fine-diff-if-necessary n)
-	(run-hooks 'ediff-select-hooks))))
+	(run-hooks 'ediff-select-hook))))
 	
 
 ;; Unselect a difference by removing the ASCII flags in the buffers.
@@ -2279,12 +2499,16 @@
 		   (ediff-remove-flags-from-buffer
 		    ediff-buffer-C
 		    (ediff-get-diff-overlay n 'C)))
+	       (if (ediff-buffer-live-p ediff-ancestor-buffer)
+		   (ediff-remove-flags-from-buffer
+		    ediff-ancestor-buffer
+		    (ediff-get-diff-overlay n 'Ancestor)))
 	       ))
 	(setq ediff-highlighting-style nil)
 	
 	;; unhighlight fine diffs
 	(ediff-set-fine-diff-properties ediff-current-difference 'default)
-	(run-hooks 'ediff-unselect-hooks))))
+	(run-hooks 'ediff-unselect-hook))))
   
 
 ;; Unselects prev diff and selects a new one, if FLAG has value other than
@@ -2293,7 +2517,6 @@
 ;; unselected.  If FLAG is 'unselect-only then the current selection is
 ;; unselected, but the next one is not selected.  If NO-RECENTER is non-nil,
 ;; don't recenter buffers after selecting/unselecting.
-;; 
 (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
   (let ((ediff-current-difference n))
     (or no-recenter
@@ -2326,7 +2549,7 @@
   ;; hack default-dir if it is not set
   (setq default-dir
 	(file-name-as-directory
-	 (abbreviate-file-name
+	 (ediff-abbreviate-file-name
 	  (expand-file-name (or default-dir
 				(and default-file
 				     (file-name-directory default-file))
@@ -2363,11 +2586,11 @@
     f)) 
   
 ;; If `prefix' is given, then it is used as a prefix for the temp file
-;; name. Otherwise, `_buffer-name' is used. If `file' is given, use this
+;; name. Otherwise, `ediff_' is used. If `file' is given, use this
 ;; file and don't create a new one.
 ;; Also, save buffer from START to END in the file.
 ;; START defaults to (point-min), END to (point-max)
-(defun ediff-make-temp-file (&optional prefix given-file start end)
+(defun ediff-make-temp-file (buff &optional prefix given-file start end)
   (let ((f (or given-file
 	       (make-temp-name (concat
 				ediff-temp-file-prefix
@@ -2375,25 +2598,26 @@
 				    (concat prefix "_")
 				    "ediff_"))))))
     ;; create the file
-    (write-region (if start start (point-min))
-		  (if end end (point-max))
-		  f
-		  nil          ; don't append---erase
-		  'no-message) 
-    (set-file-modes f ediff-temp-file-mode)
-    f))
+    (ediff-eval-in-buffer buff
+      (write-region (if start start (point-min))
+		    (if end end (point-max))
+		    f
+		    nil          ; don't append---erase
+		    'no-message) 
+      (set-file-modes f ediff-temp-file-mode)
+      f)))
 
 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
 ;; EMX OS/2
-(defun ediff-protect-metachars (str)
-  (or (memq system-type '(emx vax-vms axp-vms))
-      (let ((limit 0))
-	(while (string-match ediff-metachars str limit)
-	  (setq str (concat (substring str 0 (match-beginning 0))
-			    "\\"
-			    (substring str (match-beginning 0))))
-	  (setq limit (1+ (match-end 0))))))
-  str)
+;;(defun ediff-protect-metachars (str)
+;;  (or (memq system-type '(emx vax-vms axp-vms))
+;;      (let ((limit 0))
+;;	(while (string-match ediff-metachars str limit)
+;;	  (setq str (concat (substring str 0 (match-beginning 0))
+;;			    "\\"
+;;			    (substring str (match-beginning 0))))
+;;	  (setq limit (1+ (match-end 0))))))
+;;  str)
 
 ;; Make sure the current buffer (for a file) has the same contents as the
 ;; file on disk, and attempt to remedy the situation if not.
@@ -2433,15 +2657,6 @@
 
 
 
-(defun ediff-check-for-ascii-flags ()
-  (eval
-   (cons 'or
-	 (mapcar (function (lambda (buf)
-			     (if (ediff-buffer-live-p buf)
-				 (ediff-eval-in-buffer buf
-				   (eq ediff-highlighting-style 'ascii)))))
-		 ediff-this-buffer-control-sessions))))
-
 ;; It would be nice to use these two functions as hooks instead of
 ;; ediff-insert-in-front and ediff-move-disturbed-overlays.
 ;; However, Emacs has a bug that causes BEG and END, below, to be
@@ -2451,14 +2666,14 @@
 ;; the overlay end.
 ;; Either this bug is fixed, or (better) use sticky overlays when they will
 ;; be implemented in Emacs, like they are in XEmacs.
-;;(defun ediff-capture-inserts-in-front (overl beg end)
-;;  (if (ediff-overlay-get overl 'ediff-diff-num)
-;;      (ediff-move-overlay
-;;       overl beg (+ (- end beg) (ediff-overlay-end overl)))
-;;  ))
-;;(defun ediff-capture-inserts-behind (overl beg end)
-;;  (if (ediff-overlay-get overl 'ediff-diff-num)
-;;      (ediff-move-overlay overl (ediff-overlay-start overl) end))
+;;(defun ediff-capture-inserts-in-front (overl flag beg end &optional len)
+;;  (if (and flag (ediff-overlay-get overl 'ediff-diff-num))
+;;      (ediff-move-overlay overl beg (ediff-overlay-end overl))
+;;    ))
+;;
+;;(defun ediff-capture-inserts-behind (overl flag beg end &optional len)
+;;  (if (and flag (ediff-overlay-get overl 'ediff-diff-num))
+;;      (ediff-move-overlay overl (ediff-overlay-start overl) (point))
 ;;  ))
   
 ;; to be deleted in due time
@@ -2487,17 +2702,70 @@
 (defun ediff-save-buffer (arg)
   "Safe way of saving buffers A, B, C, and the diff output.
 `wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C,
-and `wd' saves the diff output."
+and `wd' saves the diff output.
+
+With prefix argument, `wd' saves plain diff output.
+Without an argument, it saves customized diff argument, if available
+\(and plain output, if customized output was not generated\)."
   (interactive "P")
+  (ediff-barf-if-not-control-buffer)
+  (ediff-compute-custom-diffs-maybe)
   (ediff-eval-in-buffer
       (cond ((memq last-command-char '(?a ?b ?c))
 	     (ediff-get-buffer
 	      (ediff-char-to-buftype last-command-char)))
 	    ((eq last-command-char ?d)
-	     (message "Saving diff output ...")(sit-for 1)
-	     (if arg ediff-diff-buffer ediff-custom-diff-buffer)
-	     ))
+	     (message "Saving diff output ...")
+	     (sit-for 1) ; let the user see the message
+	     (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
+		    ediff-diff-buffer)
+		   ((ediff-buffer-live-p ediff-custom-diff-buffer)
+		    ediff-custom-diff-buffer)
+		   ((ediff-buffer-live-p ediff-diff-buffer)
+		    ediff-diff-buffer)
+		   (t (error "Output from `diff' not found"))))
+	    )
     (save-buffer)))
+
+(defun ediff-compute-custom-diffs-maybe ()
+  (or ediff-3way-job
+      (let ((file-A (ediff-make-temp-file ediff-buffer-A))
+	    (file-B (ediff-make-temp-file ediff-buffer-B)))
+	(or (ediff-buffer-live-p ediff-custom-diff-buffer)
+	    (setq ediff-custom-diff-buffer
+		  (get-buffer-create
+		   (ediff-unique-buffer-name "*ediff-custom-diff" "*"))))
+	(ediff-exec-process
+	 ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
+	 ediff-custom-diff-options file-A file-B))))
+
+(defun ediff-show-diff-output (arg)
+  (interactive "P")
+  (ediff-barf-if-not-control-buffer)
+  (ediff-compute-custom-diffs-maybe)
+  (save-excursion
+    (ediff-skip-unsuitable-frames ' ok-unsplittable))
+  (let ((buf (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
+		    ediff-diff-buffer)
+		   ((ediff-buffer-live-p ediff-custom-diff-buffer)
+		    ediff-custom-diff-buffer)
+		   ((ediff-buffer-live-p ediff-diff-buffer)
+		    ediff-diff-buffer)
+		   (t
+		    (beep)
+		    (message "Output from `diff' not found")
+		    nil))))
+    (if buf
+	(progn
+	  (ediff-eval-in-buffer buf
+	    (goto-char (point-min)))
+	  (switch-to-buffer buf)
+	  (raise-frame (selected-frame)))))
+  (if (frame-live-p ediff-control-frame)
+      (ediff-reset-mouse ediff-control-frame))
+  (if (window-live-p ediff-control-window)
+      (select-window ediff-control-window)))
+      
     
 
 ;; will simplify it in due time, when emacs acquires before/after strings
@@ -2585,7 +2853,9 @@
 		     (1+ n) ediff-number-of-differences)
 	    (error "No differences found")))
       (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
-    
+    (if (not (ediff-buffer-live-p (ediff-overlay-buffer diff-overlay)))
+	(error
+	 "You have killed an essential Ediff buffer---Please exit Ediff"))
     (if (eq pos 'beg)
 	(ediff-overlay-start diff-overlay)
       (ediff-overlay-end diff-overlay))
@@ -2604,16 +2874,6 @@
 	     (current-diff-overlay 
 	      (symbol-value
 	       (intern (format "ediff-current-diff-overlay-%S" buf-type))))
-	     (odd-diff-face
-	      (symbol-value
-	       (intern (format "ediff-odd-diff-face-%S" buf-type))))
-	     (even-diff-face
-	      (symbol-value
-	       (intern (format "ediff-even-diff-face-%S" buf-type))))
-	     (odd-diff-face-var
-	      (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
-	     (even-diff-face-var
-	      (intern (format "ediff-even-diff-face-%S-var" buf-type)))
 	     )
 	
 	(if ediff-xemacs-p
@@ -2624,16 +2884,11 @@
 	(ediff-overlay-put current-diff-overlay 'priority  0)
 	(ediff-overlay-put current-diff-overlay 'priority  
 			   (ediff-highest-priority begin end-hilit buff))
+	(ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
 	
-	(or (face-differs-from-default-p odd-diff-face-var)
-	    (not ediff-highlight-all-diffs)
-	    (progn
-	      (copy-face odd-diff-face odd-diff-face-var)
-	      (copy-face even-diff-face even-diff-face-var)))
-	
-	;; unhighlight the background overlay for diff n so they won't
+	;; unhighlight the background overlay for diff n so it won't
 	;; interfere with the current diff overlay
-	(ediff-overlay-put (ediff-get-diff-overlay n buf-type) 'face nil)
+	(ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
 	)))
 
 
@@ -2642,10 +2897,6 @@
       (let ((current-diff-overlay 
 	     (symbol-value
 	      (intern (format "ediff-current-diff-overlay-%S" buf-type))))
-	    (odd-diff-face-var
-	     (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
-	    (even-diff-face-var
-	     (intern (format "ediff-even-diff-face-%S-var" buf-type)))
 	    (overlay
 	     (ediff-get-diff-overlay ediff-current-difference buf-type))
 	    )
@@ -2654,10 +2905,11 @@
 	
 	;; rehighlight the overlay in the background of the
 	;; current difference region
-	(ediff-overlay-put overlay
-			   'face (if (ediff-odd-p ediff-current-difference)
-				     odd-diff-face-var
-				   even-diff-face-var))
+	(ediff-set-overlay-face
+	 overlay
+	 (if (and (ediff-window-display-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)
@@ -2666,15 +2918,8 @@
       (let* ((inhibit-quit t)
 	     (current-diff-overlay-var
 	      (intern (format "ediff-current-diff-overlay-%S" buf-type)))
-	     (current-diff-overlay (symbol-value current-diff-overlay-var))
-	     (odd-diff-face-var
-	      (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
-	     (even-diff-face-var
-	      (intern (format "ediff-even-diff-face-%S-var" buf-type))))
-	(if (face-differs-from-default-p odd-diff-face-var)
-	    (progn
-	      (copy-face 'default odd-diff-face-var)
-	      (copy-face 'default even-diff-face-var)))
+	     (current-diff-overlay (symbol-value current-diff-overlay-var)))
+	(ediff-color-background-regions 'unhighlight)
 	(if (ediff-overlayp current-diff-overlay)
 	    (ediff-delete-overlay current-diff-overlay))
 	(set current-diff-overlay-var nil)
@@ -2696,7 +2941,31 @@
 	      (symbol-value vec-var)))
   ;; allow them to be garbage collected
   (set vec-var nil))
-    
+
+(defun ediff-color-background-regions (&optional unhighlight)
+  (ediff-color-background-regions-in-one-buffer
+   'A unhighlight)
+  (ediff-color-background-regions-in-one-buffer
+   'B unhighlight)
+  (ediff-color-background-regions-in-one-buffer
+   'C unhighlight)
+  (ediff-color-background-regions-in-one-buffer
+   'Ancestor unhighlight))
+
+(defun ediff-color-background-regions-in-one-buffer (buf-type unhighlight)
+  (let ((diff-vector 
+	 (eval (intern (format "ediff-difference-vector-%S" buf-type))))
+	overl diff-num)
+    (mapcar (function
+	     (lambda (rec)
+	       (setq overl (ediff-get-diff-overlay-from-diff-record rec)
+		     diff-num (ediff-overlay-get overl 'ediff-diff-num))
+	       (ediff-set-overlay-face
+		overl
+		(if (not unhighlight)
+		    (ediff-background-face buf-type diff-num))
+		)))
+	    diff-vector)))
        
 
 ;;; Misc
@@ -2746,19 +3015,23 @@
 	  (if ediff-xemacs-p
 	      (progn
 		;; take precautions against detached extents
-		(ediff-overlay-put overl 'detachable nil)
+		(ediff-overlay-put overl 'detachable nil) 
 		;; chars inserted at both ends will be inside extent
 		(ediff-overlay-put overl 'start-open nil)
 		(ediff-overlay-put overl 'end-open nil))
-	    (ediff-overlay-put overl 'ediff-diff-num 0)
+	    (ediff-overlay-put overl 'evaporate nil)  ; don't detach
+	    ;; doesn't work since emacs buggily doesn't call these functions
+	    ;; after the change
 	    ;;(ediff-overlay-put overl 'insert-in-front-hooks
-	    ;;		         (list 'ediff-capture-inserts-in-front))
+	    ;;		         '(ediff-capture-inserts-in-front))
 	    ;;(ediff-overlay-put overl 'insert-behind-hooks
-	    ;;  	         (list 'ediff-capture-inserts-behind))
+	    ;;  	         '(ediff-capture-inserts-behind))
+
 	    ;; These two are not yet implemented in Emacs
-	    ;;(ediff-overlay-put overl 'rear-sticky t)
-	    ;;(ediff-overlay-put overl 'front-sticky t)
+	    (ediff-overlay-put overl 'rear-sticky t)
+	    (ediff-overlay-put overl 'front-sticky t)
 	    )
+	  (ediff-overlay-put overl 'ediff-diff-num 0)
 	  overl))))
 	  
 (defsubst ediff-overlay-start (overl)
@@ -2823,9 +3096,26 @@
       (format "%s<%d>%s" prefix n suffix))))
   
 
+;; splits at a white space, returns a list
+(defun ediff-split-string (string)
+  (let ((start 0)
+        (result '())
+	substr)
+    (while (string-match "[ \t]+" string start)
+      (let ((match (string-match "[ \t]+" string start)))
+	(setq substr (substring string start match))
+	(if (> (length substr) 0)
+	    (setq result (cons substr result)))
+        (setq start (match-end 0))))
+    (setq substr (substring string start nil))
+    (if (> (length substr) 0)
+	(setq result (cons substr result)))
+    (nreverse result)))
+
 (defun ediff-submit-report ()
   "Submit bug report on Ediff."
   (interactive)
+  (ediff-barf-if-not-control-buffer)
   (let ((reporter-prompt-for-summary-p t)
 	(ctl-buf ediff-control-buffer)
 	(ediff-device-type (ediff-device-type))
@@ -2916,24 +3206,6 @@
     ))
 			     
        
-(defun ediff-union (list1 list2)
-  "Combine LIST1 and LIST2 using a set-union operation.
-The result list contains all items that appear in either LIST1 or LIST2.
-This is a non-destructive function; it makes a copy of the data if necessary
-to avoid corrupting the original LIST1 and LIST2.
-This is a slightly simplified version from `cl-seq.el'.  Added here to
-avoid loading cl-*."
-  (cond ((null list1) list2) ((null list2) list1)
-	((equal list1 list2) list1)
-	(t
-	 (or (>= (length list1) (length list2))
-	     (setq list1 (prog1 list2 (setq list2 list1))))
-	 (while list2
-	   (or (memq (car list2) list1)
-	       (setq list1 (cons (car list2) list1)))
-	   (setq list2 (cdr list2)))
-	 list1)))
-	 
 (defun ediff-deactivate-mark ()
   (if ediff-xemacs-p
 	  (zmacs-deactivate-region)
@@ -2974,6 +3246,7 @@
   (while vars
     (set (car vars) (cdr (assoc (car vars) assoc-list)))
     (setq vars (cdr vars))))
+
 (defun ediff-change-saved-variable (var value buf-type)
   (let* ((assoc-list
 	  (symbol-value (intern
@@ -2995,20 +3268,29 @@
   (if ediff-3way-comparison-job
       (setq ediff-buffer-values-orig-C
 	    (ediff-eval-in-buffer ediff-buffer-C
+	      (ediff-save-variables ediff-protected-variables))))
+  (if (ediff-buffer-live-p ediff-ancestor-buffer)
+      (setq ediff-buffer-values-orig-Ancestor
+	    (ediff-eval-in-buffer ediff-ancestor-buffer
 	      (ediff-save-variables ediff-protected-variables)))))
 
 ;; must execute in control buf
 (defun ediff-restore-protected-variables ()
   (let ((values-A ediff-buffer-values-orig-A)
 	(values-B ediff-buffer-values-orig-B)
-	(values-C ediff-buffer-values-orig-C))
-  (ediff-eval-in-buffer ediff-buffer-A
-    (ediff-restore-variables ediff-protected-variables values-A))
-  (ediff-eval-in-buffer ediff-buffer-B
-    (ediff-restore-variables ediff-protected-variables values-B))
-  (if ediff-3way-comparison-job
-      (ediff-eval-in-buffer ediff-buffer-C
-	(ediff-restore-variables ediff-protected-variables values-C)))))
+	(values-C ediff-buffer-values-orig-C)
+	(values-Ancestor ediff-buffer-values-orig-Ancestor))
+    (ediff-eval-in-buffer ediff-buffer-A
+      (ediff-restore-variables ediff-protected-variables values-A))
+    (ediff-eval-in-buffer ediff-buffer-B
+      (ediff-restore-variables ediff-protected-variables values-B))
+    (if ediff-3way-comparison-job
+	(ediff-eval-in-buffer ediff-buffer-C
+	  (ediff-restore-variables ediff-protected-variables values-C)))
+    (if (ediff-buffer-live-p ediff-ancestor-buffer)
+	(ediff-eval-in-buffer ediff-ancestor-buffer
+	  (ediff-restore-variables ediff-protected-variables values-Ancestor)))
+    ))
 
 
 ;;; Debug
@@ -3033,18 +3315,20 @@
 (defun ediff-profile ()
   "Toggle profiling Ediff commands."
   (interactive)
-  (or (ediff-buffer-live-p ediff-control-buffer)
-      (error "This command runs only out of Ediff Control Buffer"))
-  (make-local-hook 'pre-command-hook)
-  (make-local-hook 'post-command-hook)
-  (if (memq 'ediff-save-time pre-command-hook)
-      (progn (remove-hook 'pre-command-hook 'ediff-save-time t)
-	     (remove-hook 'post-command-hook 'ediff-calc-command-time t)
-	     (setq ediff-command-begin-time '(0 0 0))
-	     (message "Ediff profiling disabled"))
-    (add-hook 'pre-command-hook 'ediff-save-time t t)
-    (add-hook 'post-command-hook 'ediff-calc-command-time nil t)
-    (message "Ediff profiling enabled")))
+  (ediff-barf-if-not-control-buffer)
+  (if ediff-emacs-p
+      (make-local-variable 'post-command-hook))
+  (let ((pre-hook (if ediff-emacs-p 'pre-command-hook 'local-pre-command-hook))
+	(post-hook
+	 (if ediff-emacs-p 'post-command-hook 'local-post-command-hook)))
+    (if (not (equal ediff-command-begin-time '(0 0 0)))
+	(progn (remove-hook pre-hook 'ediff-save-time)
+	       (remove-hook post-hook 'ediff-calc-command-time)
+	       (setq ediff-command-begin-time '(0 0 0))
+	       (message "Ediff profiling disabled"))
+      (add-hook pre-hook 'ediff-save-time t)
+      (add-hook post-hook 'ediff-calc-command-time)
+      (message "Ediff profiling enabled"))))
     
 (defun ediff-print-diff-vector (diff-vector-var)
   (princ (format "\n*** %S ***\n" diff-vector-var))
@@ -3075,19 +3359,19 @@
 
 (defun ediff-debug-info ()
   (interactive)
-  (or (ediff-buffer-live-p ediff-control-buffer)
-      (error "This command runs only out of Ediff Control Buffer"))
+  (ediff-barf-if-not-control-buffer)
   (with-output-to-temp-buffer ediff-debug-buffer
     (princ (format "\nCtl buffer: %S\n" ediff-control-buffer))
-    (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "A")))
-    (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "B")))
-    (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "C")))
+    (ediff-print-diff-vector (intern "ediff-difference-vector-A"))
+    (ediff-print-diff-vector (intern "ediff-difference-vector-B"))
+    (ediff-print-diff-vector (intern "ediff-difference-vector-C"))
+    (ediff-print-diff-vector (intern "ediff-difference-vector-Ancestor"))
     ))
 
 ;; don't report error if version control package wasn't found
 ;;(ediff-load-version-control 'silent)
 
-(run-hooks 'ediff-load-hooks)
+(run-hooks 'ediff-load-hook)
     
 
 ;;; Local Variables: