+ (ediff-barf-if-not-control-buffer)
+ (ediff-compute-custom-diffs-maybe)
+ (ediff-with-current-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) ; 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)))
+
+
+;; idea suggested by Hannu Koivisto <azure@iki.fi>
+(defun ediff-clone-buffer-for-region-comparison (buff region-name)
+ (let ((cloned-buff (ediff-make-cloned-buffer buff region-name))
+ (pop-up-windows t)
+ wind
+ other-wind
+ msg-buf)
+ (ediff-with-current-buffer cloned-buff
+ (setq ediff-temp-indirect-buffer t))
+ (pop-to-buffer cloned-buff)
+ (setq wind (ediff-get-visible-buffer-window cloned-buff))
+ (select-window wind)
+ (delete-other-windows)
+ (split-window-vertically)
+ (ediff-select-lowest-window)
+ (setq other-wind (selected-window))
+ (with-temp-buffer
+ (erase-buffer)
+ (insert
+ (format "\n ******* Mark a region in buffer %s *******\n"
+ (buffer-name cloned-buff)))
+ (insert
+ (ediff-with-current-buffer buff
+ (format "\n\t When done, type %s Use %s to abort\n "
+ (ediff-format-bindings-of 'exit-recursive-edit)
+ (ediff-format-bindings-of 'abort-recursive-edit))))
+ (goto-char (point-min))
+ (setq msg-buf (current-buffer))
+ (set-window-buffer other-wind msg-buf)
+ (shrink-window-if-larger-than-buffer)
+ (if (window-live-p wind)
+ (select-window wind))
+ (condition-case nil
+ (recursive-edit)
+ (quit
+ (ediff-kill-buffer-carefully cloned-buff)))
+ )
+ cloned-buff))
+
+
+(defun ediff-clone-buffer-for-window-comparison (buff wind region-name)
+ (let ((cloned-buff (ediff-make-cloned-buffer buff region-name)))
+ (ediff-with-current-buffer cloned-buff
+ (setq ediff-temp-indirect-buffer t))
+ (set-window-buffer wind cloned-buff)
+ cloned-buff))
+
+(defun ediff-clone-buffer-for-current-diff-comparison (buff buf-type reg-name)
+ (let ((cloned-buff (ediff-make-cloned-buffer buff reg-name))
+ (reg-start (ediff-get-diff-posn buf-type 'beg))
+ (reg-end (ediff-get-diff-posn buf-type 'end)))
+ (ediff-with-current-buffer cloned-buff
+ ;; set region to be the current diff region
+ (goto-char reg-start)
+ (set-mark reg-end)
+ (setq ediff-temp-indirect-buffer t))
+ cloned-buff))
+
+
+
+(defun ediff-make-cloned-buffer (buff region-name)
+ (ediff-make-indirect-buffer
+ buff (generate-new-buffer-name
+ (concat (if (stringp buff) buff (buffer-name buff)) region-name))
+ ))
+
+
+(defun ediff-make-indirect-buffer (base-buf indirect-buf-name)
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (make-indirect-buffer base-buf indirect-buf-name) ; xemacs
+ (make-indirect-buffer base-buf indirect-buf-name 'clone) ; emacs
+ ))
+
+
+;; This function operates only from an ediff control buffer
+(defun ediff-compute-custom-diffs-maybe ()
+ (let ((buf-A-file-name (buffer-file-name ediff-buffer-A))
+ (buf-B-file-name (buffer-file-name ediff-buffer-B))
+ file-A file-B)
+ (unless (and buf-A-file-name (file-exists-p buf-A-file-name))
+ (setq file-A
+ (ediff-make-temp-file ediff-buffer-A)))
+ (unless (and buf-B-file-name (file-exists-p buf-B-file-name))
+ (setq 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-with-current-buffer ediff-custom-diff-buffer
+ (setq buffer-read-only nil)
+ (erase-buffer))
+ (ediff-exec-process
+ ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
+ ediff-custom-diff-options
+ ;; repetition of buf-A-file-name is needed so it'll return a file
+ (or (and buf-A-file-name (file-exists-p buf-A-file-name) buf-A-file-name)
+ file-A)
+ (or (and buf-B-file-name (file-exists-p buf-B-file-name) buf-B-file-name)
+ file-B))
+ ;; put the diff file in diff-mode, if it is available
+ (if (fboundp 'diff-mode)
+ (with-current-buffer ediff-custom-diff-buffer
+ (diff-mode)))
+ (and file-A (file-exists-p file-A) (delete-file file-A))
+ (and file-B (file-exists-p file-B) (delete-file 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-with-current-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)))
+
+
+(defun ediff-inferior-compare-regions ()
+ "Compare regions in an active Ediff session.
+Like ediff-regions-linewise but is called from under an active Ediff session on
+the files that belong to that session.
+
+After quitting the session invoked via this function, type C-l to the parent
+Ediff Control Panel to restore highlighting."
+ (interactive)
+ (let ((answer "")
+ (possibilities (list ?A ?B ?C))
+ (zmacs-regions t)
+ use-current-diff-p
+ begA begB endA endB bufA bufB)
+
+ (if (ediff-valid-difference-p ediff-current-difference)
+ (progn
+ (ediff-set-fine-diff-properties ediff-current-difference 'default)
+ (ediff-unhighlight-diff)))
+ (ediff-paint-background-regions 'unhighlight)
+
+ (cond ((ediff-merge-job)
+ (setq bufB ediff-buffer-C)
+ ;; ask which buffer to compare to the merge buffer
+ (while (cond ((eq answer ?A)
+ (setq bufA ediff-buffer-A
+ possibilities '(?B))
+ nil)
+ ((eq answer ?B)
+ (setq bufA ediff-buffer-B
+ possibilities '(?A))
+ nil)
+ ((equal answer ""))
+ (t (beep 1)
+ (message "Valid values are A or B")
+ (sit-for 2)
+ t))
+ (let ((cursor-in-echo-area t))
+ (message
+ "Which buffer to compare to the merge buffer (A or B)? ")
+ (setq answer (capitalize (read-char-exclusive))))))
+
+ ((ediff-3way-comparison-job)
+ ;; ask which two buffers to compare
+ (while (cond ((memq answer possibilities)
+ (setq possibilities (delq answer possibilities))
+ (setq bufA
+ (eval
+ (ediff-get-symbol-from-alist
+ answer ediff-buffer-alist)))
+ nil)
+ ((equal answer ""))
+ (t (beep 1)
+ (message
+ "Valid values are %s"
+ (mapconcat 'char-to-string possibilities " or "))
+ (sit-for 2)
+ t))
+ (let ((cursor-in-echo-area t))
+ (message "Enter the 1st buffer you want to compare (%s): "
+ (mapconcat 'char-to-string possibilities " or "))
+ (setq answer (capitalize (read-char-exclusive)))))
+ (setq answer "") ; silence error msg
+ (while (cond ((memq answer possibilities)
+ (setq possibilities (delq answer possibilities))
+ (setq bufB
+ (eval
+ (ediff-get-symbol-from-alist
+ answer ediff-buffer-alist)))
+ nil)
+ ((equal answer ""))
+ (t (beep 1)
+ (message
+ "Valid values are %s"
+ (mapconcat 'char-to-string possibilities " or "))
+ (sit-for 2)
+ t))
+ (let ((cursor-in-echo-area t))
+ (message "Enter the 2nd buffer you want to compare (%s): "
+ (mapconcat 'char-to-string possibilities "/"))
+ (setq answer (capitalize (read-char-exclusive))))))
+ (t ; 2way comparison
+ (setq bufA ediff-buffer-A
+ bufB ediff-buffer-B
+ possibilities nil)))
+
+ (if (and (ediff-valid-difference-p ediff-current-difference)
+ (y-or-n-p "Compare currently highlighted difference regions? "))
+ (setq use-current-diff-p t))
+
+ (setq bufA (if use-current-diff-p
+ (ediff-clone-buffer-for-current-diff-comparison
+ bufA 'A "-Region.A-")
+ (ediff-clone-buffer-for-region-comparison bufA "-Region.A-")))
+ (ediff-with-current-buffer bufA
+ (setq begA (region-beginning)
+ endA (region-end))
+ (goto-char begA)
+ (beginning-of-line)
+ (setq begA (point))
+ (goto-char endA)
+ (end-of-line)
+ (or (eobp) (forward-char)) ; include the newline char
+ (setq endA (point)))
+
+ (setq bufB (if use-current-diff-p
+ (ediff-clone-buffer-for-current-diff-comparison
+ bufB 'B "-Region.B-")
+ (ediff-clone-buffer-for-region-comparison bufB "-Region.B-")))
+ (ediff-with-current-buffer bufB
+ (setq begB (region-beginning)
+ endB (region-end))
+ (goto-char begB)
+ (beginning-of-line)
+ (setq begB (point))
+ (goto-char endB)
+ (end-of-line)
+ (or (eobp) (forward-char)) ; include the newline char
+ (setq endB (point)))
+
+
+ (ediff-regions-internal
+ bufA begA endA bufB begB endB
+ nil ; setup-hook
+ (if use-current-diff-p ; job name
+ 'ediff-regions-wordwise
+ 'ediff-regions-linewise)
+ (if use-current-diff-p ; word mode, if diffing current diff
+ t nil)
+ ;; setup param to pass to ediff-setup
+ (list (cons 'ediff-split-window-function ediff-split-window-function)))
+ ))
+
+
+
+(defun ediff-remove-flags-from-buffer (buffer overlay)
+ (ediff-with-current-buffer buffer
+ (let ((inhibit-read-only t))