ediff-util.el 151 KB
Newer Older
Karl Heuer's avatar
Karl Heuer committed
1
;;; ediff-util.el --- the core commands and utilities of ediff
Erik Naggum's avatar
Erik Naggum committed
2

3
;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
Glenn Morris's avatar
Glenn Morris committed
4
;;   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Karl Heuer's avatar
Karl Heuer committed
5

6
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
Karl Heuer's avatar
Karl Heuer committed
7 8 9

;; This file is part of GNU Emacs.

10
;; GNU Emacs is free software: you can redistribute it and/or modify
Karl Heuer's avatar
Karl Heuer committed
11
;; it under the terms of the GNU General Public License as published by
12 13
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Karl Heuer's avatar
Karl Heuer committed
14 15 16 17 18 19 20

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
21
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Karl Heuer's avatar
Karl Heuer committed
22

23 24
;;; Commentary:

Karl Heuer's avatar
Karl Heuer committed
25
;;; Code:
26

Karl Heuer's avatar
Karl Heuer committed
27

28 29
(provide 'ediff-util)

Michael Kifer's avatar
Michael Kifer committed
30
;; Compiler pacifier
Michael Kifer's avatar
Michael Kifer committed
31 32
(defvar ediff-use-toolbar-p)
(defvar ediff-toolbar-height)
Michael Kifer's avatar
Michael Kifer committed
33 34 35 36 37 38 39
(defvar ediff-toolbar)
(defvar ediff-toolbar-3way)
(defvar bottom-toolbar)
(defvar bottom-toolbar-visible-p)
(defvar bottom-toolbar-height)
(defvar mark-active)

40 41
(defvar ediff-after-quit-hook-internal nil)

42 43 44
(eval-and-compile
  (unless (fboundp 'declare-function) (defmacro declare-function (&rest  r))))

Michael Kifer's avatar
Michael Kifer committed
45
(eval-when-compile
46 47
  (require 'ediff))

Michael Kifer's avatar
Michael Kifer committed
48 49
;; end pacifier

Michael Kifer's avatar
Michael Kifer committed
50

Michael Kifer's avatar
Michael Kifer committed
51 52 53
(require 'ediff-init)
(require 'ediff-help)
(require 'ediff-mult)
Michael Kifer's avatar
Michael Kifer committed
54 55 56
(require 'ediff-wind)
(require 'ediff-diff)
(require 'ediff-merg)
57
;; for compatibility with current stable version of xemacs
58
(if (featurep 'xemacs)
Michael Kifer's avatar
Michael Kifer committed
59
    (require 'ediff-tbar))
Michael Kifer's avatar
Michael Kifer committed
60

Karl Heuer's avatar
Karl Heuer committed
61 62 63 64

;;; Functions

(defun ediff-mode ()
65 66
  "Ediff mode controls all operations in a single Ediff session.
This mode is entered through one of the following commands:
Karl Heuer's avatar
Karl Heuer committed
67 68 69
	`ediff'
	`ediff-files'
	`ediff-buffers'
Michael Kifer's avatar
Michael Kifer committed
70
	`ebuffers'
Karl Heuer's avatar
Karl Heuer committed
71 72 73
	`ediff3'
	`ediff-files3'
	`ediff-buffers3'
Michael Kifer's avatar
Michael Kifer committed
74
	`ebuffers3'
Karl Heuer's avatar
Karl Heuer committed
75 76 77 78 79 80 81
	`ediff-merge'
	`ediff-merge-files'
	`ediff-merge-files-with-ancestor'
	`ediff-merge-buffers'
	`ediff-merge-buffers-with-ancestor'
	`ediff-merge-revisions'
	`ediff-merge-revisions-with-ancestor'
82 83 84 85
	`ediff-windows-wordwise'
	`ediff-windows-linewise'
	`ediff-regions-wordwise'
	`ediff-regions-linewise'
Karl Heuer's avatar
Karl Heuer committed
86 87 88 89
	`epatch'
	`ediff-patch-file'
	`ediff-patch-buffer'
	`epatch-buffer'
Michael Kifer's avatar
Michael Kifer committed
90
        `erevision'
Karl Heuer's avatar
Karl Heuer committed
91 92 93 94 95 96 97
	`ediff-revision'

Commands:
\\{ediff-mode-map}"
  (kill-all-local-variables)
  (setq major-mode 'ediff-mode)
  (setq mode-name "Ediff")
98 99 100 101 102
  ;; We use run-hooks instead of run-mode-hooks for two reasons.
  ;; The ediff control buffer is read-only and it is not supposed to be
  ;; modified by minor modes and such. So, run-mode-hooks doesn't do anything
  ;; useful here on top of what run-hooks does.
  ;; Second, changing run-hooks to run-mode-hooks would require an
103
  ;; if-statement, since XEmacs doesn't have this.
104
  (run-hooks 'ediff-mode-hook))
Karl Heuer's avatar
Karl Heuer committed
105

106

Karl Heuer's avatar
Karl Heuer committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120

;;; Build keymaps

(ediff-defvar-local ediff-mode-map nil
  "Local keymap used in Ediff mode.
This is local to each Ediff Control Panel, so they may vary from invocation
to invocation.")

;; Set up the keymap in the control buffer
(defun ediff-set-keys ()
  "Set up Ediff keymap, if necessary."
  (if (null ediff-mode-map)
      (ediff-setup-keymap))
  (use-local-map ediff-mode-map))
121

Karl Heuer's avatar
Karl Heuer committed
122 123 124 125 126
;; Reload Ediff keymap.  For debugging only.
(defun ediff-reload-keymap ()
  (interactive)
  (setq ediff-mode-map nil)
  (ediff-set-keys))
127

Karl Heuer's avatar
Karl Heuer committed
128 129 130 131 132

(defun ediff-setup-keymap ()
  "Set up the keymap used in the control buffer of Ediff."
  (setq ediff-mode-map (make-sparse-keymap))
  (suppress-keymap ediff-mode-map)
133

Michael Kifer's avatar
Michael Kifer committed
134
  (define-key ediff-mode-map
135
    (if (featurep 'emacs) [mouse-2] [button2]) 'ediff-help-for-quick-help)
Michael Kifer's avatar
Michael Kifer committed
136 137
  (define-key ediff-mode-map "\C-m"  'ediff-help-for-quick-help)

Karl Heuer's avatar
Karl Heuer committed
138 139 140 141 142
  (define-key ediff-mode-map "p" 'ediff-previous-difference)
  (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
  (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))
Michael Kifer's avatar
Michael Kifer committed
143 144
  ;; must come after C-h, or else C-h wipes out backspace's binding in XEmacs
  (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
Karl Heuer's avatar
Karl Heuer committed
145 146 147 148 149 150 151
  (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)
  (define-key ediff-mode-map "g"  nil)
  (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)
152
  (define-key ediff-mode-map "D" 'ediff-show-diff-output)
Karl Heuer's avatar
Karl Heuer committed
153 154 155 156 157 158
  (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)
  (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
  (or ediff-word-mode
      (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
159
  (if ediff-narrow-job
Karl Heuer's avatar
Karl Heuer committed
160 161 162 163 164 165 166 167 168 169
      (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
  (define-key ediff-mode-map "~" 'ediff-swap-buffers)
  (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
  (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
  (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
  (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
  (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
  (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)
170
  (define-key ediff-mode-map "E" 'ediff-documentation)
Karl Heuer's avatar
Karl Heuer committed
171 172
  (define-key ediff-mode-map "?" 'ediff-toggle-help)
  (define-key ediff-mode-map "!" 'ediff-update-diffs)
Michael Kifer's avatar
Michael Kifer committed
173
  (define-key ediff-mode-map "M" 'ediff-show-current-session-meta-buffer)
174
  (define-key ediff-mode-map "R" 'ediff-show-registry)
Karl Heuer's avatar
Karl Heuer committed
175 176 177 178 179 180
  (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
181 182
	 ;; Will barf if no ancestor
	 (define-key ediff-mode-map "/" 'ediff-show-ancestor)
Karl Heuer's avatar
Karl Heuer committed
183
	 ;; In merging, we allow only A->C and B->C copying.
Michael Kifer's avatar
Michael Kifer committed
184 185 186
	 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
	 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
	 (define-key ediff-mode-map "r" 'ediff-restore-diff-in-merge-buffer)
Karl Heuer's avatar
Karl Heuer committed
187 188
	 (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
	 (define-key ediff-mode-map "+" 'ediff-combine-diffs)
Michael Kifer's avatar
Michael Kifer committed
189 190 191
	 (define-key ediff-mode-map "$"  nil)
	 (define-key ediff-mode-map "$$" 'ediff-toggle-show-clashes-only)
	 (define-key ediff-mode-map "$*" 'ediff-toggle-skip-changed-regions)
Karl Heuer's avatar
Karl Heuer committed
192 193
	 (define-key ediff-mode-map "&" 'ediff-re-merge))
	(ediff-3way-comparison-job
Michael Kifer's avatar
Michael Kifer committed
194 195 196 197
	 (define-key ediff-mode-map "ab" 'ediff-copy-A-to-B)
	 (define-key ediff-mode-map "ba" 'ediff-copy-B-to-A)
	 (define-key ediff-mode-map "ac" 'ediff-copy-A-to-C)
	 (define-key ediff-mode-map "bc" 'ediff-copy-B-to-C)
Karl Heuer's avatar
Karl Heuer committed
198
	 (define-key ediff-mode-map "c" nil)
Michael Kifer's avatar
Michael Kifer committed
199 200
	 (define-key ediff-mode-map "ca" 'ediff-copy-C-to-A)
	 (define-key ediff-mode-map "cb" 'ediff-copy-C-to-B)
Karl Heuer's avatar
Karl Heuer committed
201 202 203 204 205
	 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
	 (define-key ediff-mode-map "rb" 'ediff-restore-diff)
	 (define-key ediff-mode-map "rc" 'ediff-restore-diff)
	 (define-key ediff-mode-map "C"  'ediff-toggle-read-only))
	(t ; 2-way comparison
Michael Kifer's avatar
Michael Kifer committed
206 207
	 (define-key ediff-mode-map "a"  'ediff-copy-A-to-B)
	 (define-key ediff-mode-map "b"  'ediff-copy-B-to-A)
Karl Heuer's avatar
Karl Heuer committed
208 209 210 211 212 213 214
	 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
	 (define-key ediff-mode-map "rb" 'ediff-restore-diff))
	) ; cond
  (define-key ediff-mode-map "G" 'ediff-submit-report)
  (define-key ediff-mode-map "#"  nil)
  (define-key ediff-mode-map "#h"  'ediff-toggle-regexp-match)
  (define-key ediff-mode-map "#f"  'ediff-toggle-regexp-match)
215
  (define-key ediff-mode-map "#c"  'ediff-toggle-ignore-case)
Karl Heuer's avatar
Karl Heuer committed
216 217 218 219 220 221 222 223 224
  (or ediff-word-mode
      (define-key ediff-mode-map "##"  'ediff-toggle-skip-similar))
  (define-key ediff-mode-map "o"   nil)
  (define-key ediff-mode-map "A"  'ediff-toggle-read-only)
  (define-key ediff-mode-map "B"  'ediff-toggle-read-only)
  (define-key ediff-mode-map "w"   nil)
  (define-key ediff-mode-map "wa"  'ediff-save-buffer)
  (define-key ediff-mode-map "wb"  'ediff-save-buffer)
  (define-key ediff-mode-map "wd"  'ediff-save-buffer)
Michael Kifer's avatar
Michael Kifer committed
225
  (define-key ediff-mode-map "="   'ediff-inferior-compare-regions)
226
  (if (and (fboundp 'ediff-show-patch-diagnostics) (ediff-patch-job))
Michael Kifer's avatar
Michael Kifer committed
227
      (define-key ediff-mode-map "P"  'ediff-show-patch-diagnostics))
Karl Heuer's avatar
Karl Heuer committed
228 229 230 231 232 233 234
  (if ediff-3way-job
      (progn
	(define-key ediff-mode-map "wc" 'ediff-save-buffer)
	(define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
	))

  (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
235

Karl Heuer's avatar
Karl Heuer committed
236 237
  ;; Allow ediff-mode-map to be referenced indirectly
  (fset 'ediff-mode-map ediff-mode-map)
238
  (run-hooks 'ediff-keymap-setup-hook))
Karl Heuer's avatar
Karl Heuer committed
239 240 241 242


;;; Setup functions

Michael Kifer's avatar
Michael Kifer committed
243 244 245 246 247
;; Common startup entry for all Ediff functions It now returns control buffer
;; so other functions can do post-processing SETUP-PARAMETERS is a list of the
;; form ((param .val) (param . val)...)  This serves a similar purpose to
;; STARTUP-HOOKS, but these parameters are set in the new control buffer right
;; after this buf is created and before any windows are set and such.
Karl Heuer's avatar
Karl Heuer committed
248
(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
Michael Kifer's avatar
Michael Kifer committed
249 250
			     startup-hooks setup-parameters
			     &optional merge-buffer-file)
251
  (run-hooks 'ediff-before-setup-hook)
Michael Kifer's avatar
Michael Kifer committed
252 253 254 255
  ;; ediff-convert-standard-filename puts file names in the form appropriate
  ;; for the OS at hand.
  (setq file-A (ediff-convert-standard-filename (expand-file-name file-A)))
  (setq file-B (ediff-convert-standard-filename (expand-file-name file-B)))
Karl Heuer's avatar
Karl Heuer committed
256
  (if (stringp file-C)
Michael Kifer's avatar
Michael Kifer committed
257 258
      (setq file-C
	    (ediff-convert-standard-filename (expand-file-name file-C))))
Michael Kifer's avatar
Michael Kifer committed
259 260
  (if (stringp merge-buffer-file)
      (progn
261
	(setq merge-buffer-file
Michael Kifer's avatar
Michael Kifer committed
262 263 264 265
	      (ediff-convert-standard-filename
	       (expand-file-name merge-buffer-file)))
	;; check the directory exists
	(or (file-exists-p (file-name-directory merge-buffer-file))
266
	    (error "Directory %s given as place to save the merge doesn't exist"
267
		   (abbreviate-file-name
Michael Kifer's avatar
Michael Kifer committed
268 269 270 271 272 273
		    (file-name-directory merge-buffer-file))))
	(if (and (file-exists-p merge-buffer-file)
		 (file-directory-p merge-buffer-file))
	    (error "The merge buffer file %s must not be a directory"
		   (abbreviate-file-name merge-buffer-file)))
	))
274
  (let* ((control-buffer-name
Karl Heuer's avatar
Karl Heuer committed
275
	  (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
Michael Kifer's avatar
Michael Kifer committed
276
	 (control-buffer (ediff-with-current-buffer buffer-A
Karl Heuer's avatar
Karl Heuer committed
277
			   (get-buffer-create control-buffer-name))))
Michael Kifer's avatar
Michael Kifer committed
278
    (ediff-with-current-buffer control-buffer
279 280
      (ediff-mode)

Michael Kifer's avatar
Michael Kifer committed
281 282 283 284 285 286 287
      (make-local-variable 'ediff-use-long-help-message)
      (make-local-variable 'ediff-prefer-iconified-control-frame)
      (make-local-variable 'ediff-split-window-function)
      (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)
Michael Kifer's avatar
Michael Kifer committed
288

289 290 291
      (make-local-variable 'window-min-height)
      (setq window-min-height 2)

292 293
      (if (featurep 'xemacs)
	  (make-local-hook 'ediff-after-quit-hook-internal))
294

Karl Heuer's avatar
Karl Heuer committed
295 296 297 298
      ;; unwrap set up parameters passed as argument
      (while setup-parameters
	(set (car (car setup-parameters)) (cdr (car setup-parameters)))
	(setq setup-parameters (cdr setup-parameters)))
299

Karl Heuer's avatar
Karl Heuer committed
300
      ;; set variables classifying the current ediff job
Michael Kifer's avatar
Michael Kifer committed
301
      ;; must come AFTER setup-parameters
Karl Heuer's avatar
Karl Heuer committed
302 303 304 305 306
      (setq 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-3way-job (ediff-3way-job)
	    ediff-diff3-job (ediff-diff3-job)
307 308
	    ediff-narrow-job (ediff-narrow-job)
	    ediff-windows-job (ediff-windows-job)
Karl Heuer's avatar
Karl Heuer committed
309
	    ediff-word-mode-job (ediff-word-mode-job))
310 311

      ;; Don't delete variants in case of ediff-buffer-* jobs without asking.
312
      ;; This is because one may loose work---dangerous.
313 314 315
      (if (string-match "buffer" (symbol-name ediff-job-name))
	  (setq ediff-keep-variants t))

316 317
      (if (featurep 'xemacs)
	  (make-local-hook 'pre-command-hook))
318

Michael Kifer's avatar
Michael Kifer committed
319
      (if (ediff-window-display-p)
320
	  (add-hook 'pre-command-hook 'ediff-spy-after-mouse nil 'local))
321
      (setq ediff-mouse-pixel-position (mouse-pixel-position))
322

Karl Heuer's avatar
Karl Heuer committed
323 324 325
      ;; adjust for merge jobs
      (if ediff-merge-job
	  (let ((buf
326
		 ;; If default variant is `combined', the right stuff is
Karl Heuer's avatar
Karl Heuer committed
327
		 ;; inserted by ediff-do-merge
328
		 ;; Note: at some point, we tried to put ancestor buffer here
Michael Kifer's avatar
Michael Kifer committed
329
		 ;; (which is currently buffer C.  This didn't work right
330 331 332 333 334 335
		 ;; 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))))
336

Karl Heuer's avatar
Karl Heuer committed
337
	    (setq ediff-split-window-function
338 339
		  ediff-merge-split-window-function)

Karl Heuer's avatar
Karl Heuer committed
340 341
	    ;; remember the ancestor buffer, if any
	    (setq ediff-ancestor-buffer buffer-C)
342

Karl Heuer's avatar
Karl Heuer committed
343 344 345
	    (setq buffer-C
		  (get-buffer-create
		   (ediff-unique-buffer-name "*ediff-merge" "*")))
346
	    (with-current-buffer buffer-C
347
	      (insert-buffer-substring buf)
348
	      (goto-char (point-min))
Michael Kifer's avatar
Michael Kifer committed
349
	      (funcall (ediff-with-current-buffer buf major-mode))
350
	      (widen) ; merge buffer is always widened
Michael Kifer's avatar
Michael Kifer committed
351
	      (add-hook 'local-write-file-hooks 'ediff-set-merge-mode nil t)
352
	      )))
353
      (setq buffer-read-only nil
Karl Heuer's avatar
Karl Heuer committed
354 355 356 357
	    ediff-buffer-A buffer-A
	    ediff-buffer-B buffer-B
	    ediff-buffer-C buffer-C
	    ediff-control-buffer control-buffer)
358 359

      (ediff-choose-syntax-table)
360

Karl Heuer's avatar
Karl Heuer committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
      (setq ediff-control-buffer-suffix
	    (if (string-match "<[0-9]*>" control-buffer-name)
		(substring control-buffer-name
			   (match-beginning 0) (match-end 0))
	      "")
	    ediff-control-buffer-number
	    (max
	     0
	     (1-
	      (string-to-number
	       (substring
		ediff-control-buffer-suffix
		(or
		 (string-match "[0-9]+" ediff-control-buffer-suffix)
		 0))))))
376

377 378
      (setq ediff-error-buffer
	    (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
379

380 381 382
      (with-current-buffer ediff-error-buffer
	(setq buffer-undo-list t))

Michael Kifer's avatar
Michael Kifer committed
383 384
      (ediff-with-current-buffer buffer-A (ediff-strip-mode-line-format))
      (ediff-with-current-buffer buffer-B (ediff-strip-mode-line-format))
Karl Heuer's avatar
Karl Heuer committed
385
      (if ediff-3way-job
Michael Kifer's avatar
Michael Kifer committed
386
	  (ediff-with-current-buffer buffer-C (ediff-strip-mode-line-format)))
387
      (if (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
388
	  (ediff-with-current-buffer ediff-ancestor-buffer
389
	    (ediff-strip-mode-line-format)))
390

Karl Heuer's avatar
Karl Heuer committed
391
      (ediff-save-protected-variables) ; save variables to be restored on exit
392

Karl Heuer's avatar
Karl Heuer committed
393 394 395 396 397 398
      ;; ediff-setup-diff-regions-function must be set after setup
      ;; parameters are processed.
      (setq ediff-setup-diff-regions-function
	    (if ediff-diff3-job
		'ediff-setup-diff-regions3
	      'ediff-setup-diff-regions))
399

Karl Heuer's avatar
Karl Heuer committed
400 401 402 403 404 405 406
      (setq ediff-wide-bounds
	    (list (ediff-make-bullet-proof-overlay
		   '(point-min) '(point-max) ediff-buffer-A)
		  (ediff-make-bullet-proof-overlay
		   '(point-min) '(point-max) ediff-buffer-B)
		  (ediff-make-bullet-proof-overlay
		   '(point-min) '(point-max) ediff-buffer-C)))
407

Karl Heuer's avatar
Karl Heuer committed
408 409 410 411 412 413
      ;; This has effect only on ediff-windows/regions
      ;; In all other cases, ediff-visible-region sets visibility bounds to
      ;; ediff-wide-bounds, and ediff-narrow-bounds are ignored.
      (if ediff-start-narrowed
	  (setq ediff-visible-bounds ediff-narrow-bounds)
	(setq ediff-visible-bounds ediff-wide-bounds))
414

Karl Heuer's avatar
Karl Heuer committed
415
      (ediff-set-keys) ; comes after parameter setup
416

Karl Heuer's avatar
Karl Heuer committed
417 418 419
      ;; set up ediff-narrow-bounds, if not set
      (or ediff-narrow-bounds
	  (setq ediff-narrow-bounds ediff-wide-bounds))
420

Michael Kifer's avatar
Michael Kifer committed
421
      ;; All these must be inside ediff-with-current-buffer control-buffer,
Karl Heuer's avatar
Karl Heuer committed
422 423
      ;; since these vars are local to control-buffer
      ;; These won't run if there are errors in diff
Michael Kifer's avatar
Michael Kifer committed
424
      (ediff-with-current-buffer ediff-buffer-A
Karl Heuer's avatar
Karl Heuer committed
425
	(ediff-nuke-selective-display)
426
	(run-hooks 'ediff-prepare-buffer-hook)
Michael Kifer's avatar
Michael Kifer committed
427
	(if (ediff-with-current-buffer control-buffer ediff-merge-job)
Karl Heuer's avatar
Karl Heuer committed
428
	    (setq buffer-read-only t))
429 430
	;; add control-buffer to the list of sessions--no longer used, but may
	;; be used again in the future
431 432 433
	(or (memq control-buffer ediff-this-buffer-ediff-sessions)
	    (setq ediff-this-buffer-ediff-sessions
		  (cons control-buffer ediff-this-buffer-ediff-sessions)))
Michael Kifer's avatar
Michael Kifer committed
434 435
	(if ediff-make-buffers-readonly-at-startup
	    (setq buffer-read-only t))
Karl Heuer's avatar
Karl Heuer committed
436
	)
Michael Kifer's avatar
Michael Kifer committed
437

Michael Kifer's avatar
Michael Kifer committed
438
      (ediff-with-current-buffer ediff-buffer-B
Karl Heuer's avatar
Karl Heuer committed
439
	(ediff-nuke-selective-display)
440
	(run-hooks 'ediff-prepare-buffer-hook)
Michael Kifer's avatar
Michael Kifer committed
441
	(if (ediff-with-current-buffer control-buffer ediff-merge-job)
Karl Heuer's avatar
Karl Heuer committed
442 443
	    (setq buffer-read-only t))
	;; add control-buffer to the list of sessions
444 445 446
	(or (memq control-buffer ediff-this-buffer-ediff-sessions)
	    (setq ediff-this-buffer-ediff-sessions
		  (cons control-buffer ediff-this-buffer-ediff-sessions)))
Michael Kifer's avatar
Michael Kifer committed
447 448
	(if ediff-make-buffers-readonly-at-startup
	    (setq buffer-read-only t))
Karl Heuer's avatar
Karl Heuer committed
449
	)
Michael Kifer's avatar
Michael Kifer committed
450

Karl Heuer's avatar
Karl Heuer committed
451
      (if ediff-3way-job
Michael Kifer's avatar
Michael Kifer committed
452
	  (ediff-with-current-buffer ediff-buffer-C
Karl Heuer's avatar
Karl Heuer committed
453
	    (ediff-nuke-selective-display)
454 455 456 457
	    ;; 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))
458
	    (run-hooks 'ediff-prepare-buffer-hook)
Karl Heuer's avatar
Karl Heuer committed
459
	    ;; add control-buffer to the list of sessions
460 461
	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
		(setq ediff-this-buffer-ediff-sessions
Karl Heuer's avatar
Karl Heuer committed
462
		      (cons control-buffer
463
			    ediff-this-buffer-ediff-sessions)))
Michael Kifer's avatar
Michael Kifer committed
464
	    (if ediff-make-buffers-readonly-at-startup
465 466
		(setq buffer-read-only t)
	      (setq buffer-read-only nil))
467 468 469
	    ))

      (if (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
470
	  (ediff-with-current-buffer ediff-ancestor-buffer
471 472 473 474 475 476 477
	    (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)))
Karl Heuer's avatar
Karl Heuer committed
478
	    ))
479

480
      ;; the following must be after setting up  ediff-narrow-bounds AND after
Karl Heuer's avatar
Karl Heuer committed
481 482 483 484
      ;; 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))
      (setq ediff-current-difference -1)
485

Karl Heuer's avatar
Karl Heuer committed
486 487 488 489
      (ediff-make-current-diff-overlay 'A)
      (ediff-make-current-diff-overlay 'B)
      (if ediff-3way-job
	  (ediff-make-current-diff-overlay 'C))
490 491
      (if ediff-merge-with-ancestor-job
	  (ediff-make-current-diff-overlay 'Ancestor))
492

Karl Heuer's avatar
Karl Heuer committed
493
      (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
494

Karl Heuer's avatar
Karl Heuer committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
      (let ((shift-A (ediff-overlay-start
		      (ediff-get-value-according-to-buffer-type
		       'A ediff-narrow-bounds)))
	    (shift-B (ediff-overlay-start
		      (ediff-get-value-according-to-buffer-type
		       'B ediff-narrow-bounds)))
	    (shift-C (ediff-overlay-start
		      (ediff-get-value-according-to-buffer-type
		       'C ediff-narrow-bounds))))
	;; position point in buf A
	(save-excursion
	  (select-window ediff-window-A)
	  (goto-char shift-A))
	;; position point in buf B
	(save-excursion
	  (select-window ediff-window-B)
	  (goto-char shift-B))
	(if ediff-3way-job
	    (save-excursion
	      (select-window ediff-window-C)
	      (goto-char shift-C)))
	)
517

Karl Heuer's avatar
Karl Heuer committed
518 519
      (select-window ediff-control-window)
      (ediff-visible-region)
520

521
      (run-hooks 'startup-hooks)
Michael Kifer's avatar
Michael Kifer committed
522
      (ediff-arrange-autosave-in-merge-jobs merge-buffer-file)
Michael Kifer's avatar
Michael Kifer committed
523

Karl Heuer's avatar
Karl Heuer committed
524
      (ediff-refresh-mode-lines)
525 526 527 528 529
      (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)
Michael Kifer's avatar
Michael Kifer committed
530 531
	  (ediff-update-meta-buffer
	   ediff-meta-buffer nil ediff-meta-session-number))
532 533
      (run-hooks 'ediff-startup-hook)
      ) ; eval in control-buffer
534
    control-buffer))
535 536


Karl Heuer's avatar
Karl Heuer committed
537
;; This function assumes that we are in the window where control buffer is
538
;; to reside.
Karl Heuer's avatar
Karl Heuer committed
539 540 541 542 543
(defun ediff-setup-control-buffer (ctl-buf)
  "Set up window for control buffer."
  (if (window-dedicated-p (selected-window))
      (set-buffer ctl-buf) ; we are in control frame but just in case
    (switch-to-buffer ctl-buf))
544
  (let ((window-min-height 2))
Karl Heuer's avatar
Karl Heuer committed
545 546 547 548
    (erase-buffer)
    (ediff-set-help-message)
    (insert ediff-help-message)
    (shrink-window-if-larger-than-buffer)
549
    (or (ediff-multiframe-setup-p)
Karl Heuer's avatar
Karl Heuer committed
550
	(ediff-indent-help-message))
Michael Kifer's avatar
Michael Kifer committed
551 552
    (ediff-set-help-overlays)

Karl Heuer's avatar
Karl Heuer committed
553 554 555 556
    (set-buffer-modified-p nil)
    (ediff-refresh-mode-lines)
    (setq ediff-control-window (selected-window))
    (setq ediff-window-config-saved
557
	  (format "%S%S%S%S%S%S%S"
Karl Heuer's avatar
Karl Heuer committed
558 559 560 561
		  ediff-control-window
		  ediff-window-A
		  ediff-window-B
		  ediff-window-C
562 563 564
		  ediff-split-window-function
		  (ediff-multiframe-setup-p)
		  ediff-wide-display-p))
Michael Kifer's avatar
Michael Kifer committed
565

566
    (set-window-dedicated-p (selected-window) t)
Michael Kifer's avatar
Michael Kifer committed
567
    ;; In multiframe, toolbar is set in ediff-setup-control-frame
Michael Kifer's avatar
Michael Kifer committed
568
    (if (not (ediff-multiframe-setup-p))
Michael Kifer's avatar
Michael Kifer committed
569
	(ediff-make-bottom-toolbar)) ; this checks if toolbar is requested
Karl Heuer's avatar
Karl Heuer committed
570 571
    (goto-char (point-min))
    (skip-chars-forward ediff-whitespace)))
572

Michael Kifer's avatar
Michael Kifer committed
573 574
;; This executes in control buffer and sets auto-save, visited file name, etc,
;; in the merge buffer
Michael Kifer's avatar
Michael Kifer committed
575
(defun ediff-arrange-autosave-in-merge-jobs (merge-buffer-file)
Michael Kifer's avatar
Michael Kifer committed
576 577 578 579 580 581 582 583
  (if (not ediff-merge-job)
      ()
    (if (stringp merge-buffer-file)
	(setq ediff-autostore-merges t
	      ediff-merge-store-file merge-buffer-file))
    (if (stringp ediff-merge-store-file)
	(progn
	  ;; save before leaving ctl buffer
584
	  (ediff-verify-file-merge-buffer ediff-merge-store-file)
585
	  (setq merge-buffer-file ediff-merge-store-file)
Michael Kifer's avatar
Michael Kifer committed
586 587 588 589 590 591 592
	  (ediff-with-current-buffer ediff-buffer-C
	    (set-visited-file-name merge-buffer-file))))
    (ediff-with-current-buffer ediff-buffer-C
      (setq buffer-offer-save t) ; ask before killing buffer
      ;; make sure the contents is auto-saved
      (auto-save-mode 1))
    ))
Karl Heuer's avatar
Karl Heuer committed
593 594 595


;;; Commands for working with Ediff
596

Karl Heuer's avatar
Karl Heuer committed
597 598 599 600 601 602
(defun ediff-update-diffs ()
  "Recompute difference regions in buffers A, B, and C.
Buffers are not synchronized with their respective files, so changes done
to these buffers are not saved at this point---the user can do this later,
if necessary."
  (interactive)
603 604
  (ediff-barf-if-not-control-buffer)
  (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
605 606
	   (not
	    (y-or-n-p
Michael Kifer's avatar
Michael Kifer committed
607
	     "Ancestor buffer will not be used.  Recompute diffs anyway? ")))
Michael Kifer's avatar
Michael Kifer committed
608
      (error "Recomputation of differences canceled"))
609

Michael Kifer's avatar
Michael Kifer committed
610 611
  (let ((point-A (ediff-with-current-buffer ediff-buffer-A (point)))
	;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
Karl Heuer's avatar
Karl Heuer committed
612
	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
Michael Kifer's avatar
Michael Kifer committed
613 614 615 616 617
	(buf-A-file-name (buffer-file-name ediff-buffer-A))
	(buf-B-file-name (buffer-file-name ediff-buffer-B))
	;; (null ediff-buffer-C) is no problem, as we later check if
	;; ediff-buffer-C is alive
	(buf-C-file-name (buffer-file-name ediff-buffer-C))
Karl Heuer's avatar
Karl Heuer committed
618 619 620 621 622 623 624 625
	(overl-A (ediff-get-value-according-to-buffer-type
		  'A ediff-narrow-bounds))
	(overl-B (ediff-get-value-according-to-buffer-type
		  'B ediff-narrow-bounds))
	(overl-C (ediff-get-value-according-to-buffer-type
		  'C ediff-narrow-bounds))
	beg-A end-A beg-B end-B beg-C end-C
	file-A file-B file-C)
Michael Kifer's avatar
Michael Kifer committed
626 627 628 629 630 631 632 633

    (if (stringp buf-A-file-name)
	(setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
    (if (stringp buf-B-file-name)
	(setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
    (if (stringp buf-C-file-name)
	(setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))

Karl Heuer's avatar
Karl Heuer committed
634
    (ediff-unselect-and-select-difference -1)
635

Karl Heuer's avatar
Karl Heuer committed
636 637 638 639 640 641
    (setq beg-A (ediff-overlay-start overl-A)
	  beg-B (ediff-overlay-start overl-B)
	  beg-C (ediff-overlay-start overl-C)
	  end-A (ediff-overlay-end overl-A)
	  end-B (ediff-overlay-end overl-B)
	  end-C (ediff-overlay-end overl-C))
642

Karl Heuer's avatar
Karl Heuer committed
643 644 645
    (if ediff-word-mode
	(progn
	  (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
646
	  (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
Karl Heuer's avatar
Karl Heuer committed
647
	  (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
648
	  (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
Karl Heuer's avatar
Karl Heuer committed
649 650 651
	  (if ediff-3way-job
	      (progn
		(ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
652
		(setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
Karl Heuer's avatar
Karl Heuer committed
653 654
	  )
      ;; not word-mode
655 656
      (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))
Karl Heuer's avatar
Karl Heuer committed
657
      (if ediff-3way-job
658
	  (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
Karl Heuer's avatar
Karl Heuer committed
659
      )
660

Karl Heuer's avatar
Karl Heuer committed
661 662 663
    (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)
664 665
    (ediff-clear-diff-vector
     'ediff-difference-vector-Ancestor 'fine-diffs-also)
Michael Kifer's avatar
Michael Kifer committed
666
    ;; let them garbage collect.  we can't use the ancestor after recomputing
667 668 669 670 671
    ;; the diffs.
    (setq ediff-difference-vector-Ancestor nil
	  ediff-ancestor-buffer nil
	  ediff-state-of-merge nil)

Karl Heuer's avatar
Karl Heuer committed
672
    (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
673

674
    ;; In case of merge job, fool it into thinking that it is just doing
Karl Heuer's avatar
Karl Heuer committed
675 676
    ;; comparison
    (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
677 678 679
	  (ediff-3way-comparison-job ediff-3way-comparison-job)
	  (ediff-merge-job ediff-merge-job)
	  (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
Karl Heuer's avatar
Karl Heuer committed
680 681 682
	  (ediff-job-name ediff-job-name))
      (if ediff-merge-job
	  (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
683 684 685
		ediff-3way-comparison-job t
		ediff-merge-job nil
		ediff-merge-with-ancestor-job nil
Karl Heuer's avatar
Karl Heuer committed
686 687
		ediff-job-name 'ediff-files3))
      (funcall ediff-setup-diff-regions-function file-A file-B file-C))
688

Karl Heuer's avatar
Karl Heuer committed
689 690 691 692 693
    (setq ediff-number-of-differences (length ediff-difference-vector-A))
    (delete-file file-A)
    (delete-file file-B)
    (if file-C
	(delete-file file-C))
694

Karl Heuer's avatar
Karl Heuer committed
695 696
    (if ediff-3way-job
	(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
697

Karl Heuer's avatar
Karl Heuer committed
698 699 700
    (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
    (message "")
    ))
701

Michael Kifer's avatar
Michael Kifer committed
702
;; Not bound to any key---to dangerous.  A user can do it if necessary.
Karl Heuer's avatar
Karl Heuer committed
703
(defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
Michael Kifer's avatar
Michael Kifer committed
704
  "Revert buffers A, B and C.  Then rerun Ediff on file A and file B."
Karl Heuer's avatar
Karl Heuer committed
705
  (interactive "P")
706
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
707 708 709 710
  (let ((bufA ediff-buffer-A)
	(bufB ediff-buffer-B)
	(bufC ediff-buffer-C)
	(ctl-buf ediff-control-buffer)
711
	(keep-variants ediff-keep-variants)
Karl Heuer's avatar
Karl Heuer committed
712 713 714 715
	(ancestor-buf ediff-ancestor-buffer)
	(ancestor-job ediff-merge-with-ancestor-job)
	(merge ediff-merge-job)
	(comparison ediff-3way-comparison-job))
Michael Kifer's avatar
Michael Kifer committed
716
    (ediff-with-current-buffer bufA
Karl Heuer's avatar
Karl Heuer committed
717
      (revert-buffer t noconfirm))
Michael Kifer's avatar
Michael Kifer committed
718
    (ediff-with-current-buffer bufB
Karl Heuer's avatar
Karl Heuer committed
719 720 721
      (revert-buffer t noconfirm))
    ;; this should only be executed in a 3way comparison, not in merge
    (if comparison
Michael Kifer's avatar
Michael Kifer committed
722
	(ediff-with-current-buffer bufC
Karl Heuer's avatar
Karl Heuer committed
723 724 725 726
	  (revert-buffer t noconfirm)))
    (if merge
	(progn
	  (set-buffer ctl-buf)
727 728 729 730
	  ;; 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))
Karl Heuer's avatar
Karl Heuer committed
731 732 733 734 735 736 737
	  (kill-buffer bufC)
	  (if ancestor-job
	      (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
	    (ediff-merge-buffers bufA bufB)))
      (ediff-update-diffs))))


738
;; optional NO-REHIGHLIGHT says to not rehighlight buffers
Karl Heuer's avatar
Karl Heuer committed
739 740 741 742
(defun ediff-recenter (&optional no-rehighlight)
  "Bring the highlighted region of all buffers being compared into view.
Reestablish the default three-window display."
  (interactive)
743
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
744 745 746 747
  (let (buffer-read-only)
    (if (and (ediff-buffer-live-p ediff-buffer-A)
	     (ediff-buffer-live-p ediff-buffer-B)
	     (or (not ediff-3way-job)
748
		 (ediff-buffer-live-p ediff-buffer-C)))
Karl Heuer's avatar
Karl Heuer committed
749 750 751
	(ediff-setup-windows
	 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
      (or (eq this-command 'ediff-quit)
Michael Kifer's avatar
Michael Kifer committed
752 753
	  (message ediff-KILLED-VITAL-BUFFER
		   (beep 1)))
Karl Heuer's avatar
Karl Heuer committed
754
      ))
755

Karl Heuer's avatar
Karl Heuer committed
756 757 758
  ;; set visibility range appropriate to this invocation of Ediff.
  (ediff-visible-region)
  ;; raise
759
  (if (and (ediff-window-display-p)
Karl Heuer's avatar
Karl Heuer committed
760 761 762 763 764
	   (symbolp this-command)
	   (symbolp last-command)
	   ;; Either one of the display-changing commands
	   (or (memq this-command
		     '(ediff-recenter
765 766
		       ediff-dir-action ediff-registry-action
		       ediff-patch-action
Karl Heuer's avatar
Karl Heuer committed
767 768
		       ediff-toggle-wide-display ediff-toggle-multiframe))
	       ;; Or one of the movement cmds and prev cmd was an Ediff cmd
Karl Heuer's avatar
Karl Heuer committed
769
	       ;; This avoids raising frames unnecessarily.
Karl Heuer's avatar
Karl Heuer committed
770 771 772 773 774 775 776 777 778
	       (and (memq this-command
			  '(ediff-next-difference
			    ediff-previous-difference
			    ediff-jump-to-difference
			    ediff-jump-to-difference-at-point))
		    (not (string-match "^ediff-" (symbol-name last-command)))
		    )))
      (progn
	(if (window-live-p ediff-window-A)
779
	    (raise-frame (window-frame ediff-window-A)))
Karl Heuer's avatar
Karl Heuer committed
780
	(if (window-live-p ediff-window-B)
781
	    (raise-frame (window-frame ediff-window-B)))
Karl Heuer's avatar
Karl Heuer committed
782
	(if (window-live-p ediff-window-C)
783 784 785
	    (raise-frame (window-frame ediff-window-C)))))
  (if (and (ediff-window-display-p)
	   (frame-live-p ediff-control-frame)
Michael Kifer's avatar
Michael Kifer committed
786
	   (not ediff-use-long-help-message)
Karl Heuer's avatar
Karl Heuer committed
787
	   (not (ediff-frame-iconified-p ediff-control-frame)))
788
      (raise-frame ediff-control-frame))
789

Karl Heuer's avatar
Karl Heuer committed
790
  ;; Redisplay whatever buffers are showing, if there is a selected difference
791 792
  (let ((control-frame ediff-control-frame)
	(control-buf ediff-control-buffer))
Karl Heuer's avatar
Karl Heuer committed
793 794 795
    (if (and (ediff-buffer-live-p ediff-buffer-A)
	     (ediff-buffer-live-p ediff-buffer-B)
	     (or (not ediff-3way-job)
Michael Kifer's avatar
Michael Kifer committed
796
		 (ediff-buffer-live-p ediff-buffer-C)))
Karl Heuer's avatar
Karl Heuer committed
797 798
	(progn
	  (or no-rehighlight
799
	      (ediff-select-difference ediff-current-difference))
800

Karl Heuer's avatar
Karl Heuer committed
801 802 803 804
	  (ediff-recenter-one-window 'A)
	  (ediff-recenter-one-window 'B)
	  (if ediff-3way-job
	      (ediff-recenter-one-window 'C))
805

Michael Kifer's avatar
Michael Kifer committed
806
	  (ediff-with-current-buffer control-buf
Michael Kifer's avatar
Michael Kifer committed
807
	    (ediff-recenter-ancestor) ; check if ancestor is alive
808

809
	    (if (and (ediff-multiframe-setup-p)
Michael Kifer's avatar
Michael Kifer committed
810
		     (not ediff-use-long-help-message)
811 812 813 814 815
		     (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))))
Karl Heuer's avatar
Karl Heuer committed
816
	  ))
Michael Kifer's avatar
Michael Kifer committed
817

818 819
    (or no-rehighlight
	(ediff-restore-highlighting))
Michael Kifer's avatar
Michael Kifer committed
820
    (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines))
Karl Heuer's avatar
Karl Heuer committed
821
    ))
822

Karl Heuer's avatar
Karl Heuer committed
823 824 825
;; this function returns to the window it was called from
;; (which was the control window)
(defun ediff-recenter-one-window (buf-type)
826 827 828 829
  (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
830
		     (ediff-get-value-according-to-buffer-type
831 832 833
		      buf-type ediff-narrow-bounds)))
	     (job-name ediff-job-name)
	     (control-buf ediff-control-buffer)
Michael Kifer's avatar
Michael Kifer committed
834 835
	     (window-name (ediff-get-symbol-from-alist
			   buf-type ediff-window-alist))
836 837
	     (window (if (window-live-p (symbol-value window-name))
			 (symbol-value window-name))))
838

839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
	(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))
Michael Kifer's avatar
Michael Kifer committed
863
	(ediff-with-current-buffer ediff-ancestor-buffer
864 865 866 867 868 869 870 871 872 873 874
	  (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)
	)))
Karl Heuer's avatar
Karl Heuer committed
875

876

Karl Heuer's avatar
Karl Heuer committed
877 878
;; This will have to be refined for 3way jobs
(defun ediff-toggle-split ()
879
  "Toggle vertical/horizontal window split.
Karl Heuer's avatar
Karl Heuer committed
880 881
Does nothing if file-A and file-B are in different frames."
  (interactive)
882
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
883 884 885
  (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))
886 887 888
	 (frame-A (if wind-A (window-frame wind-A)))
	 (frame-B (if wind-B (window-frame wind-B)))
	 (frame-C (if wind-C (window-frame wind-C))))
Karl Heuer's avatar
Karl Heuer committed
889
    (if (or (eq frame-A frame-B)
890 891
	    (not (frame-live-p frame-A))
	    (not (frame-live-p frame-B))
Karl Heuer's avatar
Karl Heuer committed
892
	    (if ediff-3way-comparison-job
893
		(or (not (frame-live-p frame-C))
Karl Heuer's avatar
Karl Heuer committed
894 895 896 897