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

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1994-2016 Free Software Foundation, Inc.
Karl Heuer's avatar
Karl Heuer committed
4

5
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
6
;; Package: ediff
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
(eval-and-compile
Daniel Hackney's avatar
Daniel Hackney committed
43
  (unless (fboundp 'declare-function) (defmacro declare-function (&rest  _r))))
44

Michael Kifer's avatar
Michael Kifer committed
45 46
;; end pacifier

Michael Kifer's avatar
Michael Kifer committed
47

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

Karl Heuer's avatar
Karl Heuer committed
58 59 60 61

;;; Functions

(defun ediff-mode ()
62 63
  "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
64 65 66
	`ediff'
	`ediff-files'
	`ediff-buffers'
Michael Kifer's avatar
Michael Kifer committed
67
	`ebuffers'
Karl Heuer's avatar
Karl Heuer committed
68 69 70
	`ediff3'
	`ediff-files3'
	`ediff-buffers3'
Michael Kifer's avatar
Michael Kifer committed
71
	`ebuffers3'
Karl Heuer's avatar
Karl Heuer committed
72 73 74 75 76 77 78
	`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'
79 80 81 82
	`ediff-windows-wordwise'
	`ediff-windows-linewise'
	`ediff-regions-wordwise'
	`ediff-regions-linewise'
Karl Heuer's avatar
Karl Heuer committed
83 84 85 86
	`epatch'
	`ediff-patch-file'
	`ediff-patch-buffer'
	`epatch-buffer'
Michael Kifer's avatar
Michael Kifer committed
87
        `erevision'
Karl Heuer's avatar
Karl Heuer committed
88 89 90 91
	`ediff-revision'

Commands:
\\{ediff-mode-map}"
92
  ;; FIXME: Use define-derived-mode.
Karl Heuer's avatar
Karl Heuer committed
93 94 95
  (kill-all-local-variables)
  (setq major-mode 'ediff-mode)
  (setq mode-name "Ediff")
96 97 98 99 100
  ;; 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
101
  ;; if-statement, since XEmacs doesn't have this.
102
  (run-hooks 'ediff-mode-hook))
Karl Heuer's avatar
Karl Heuer committed
103

104

Karl Heuer's avatar
Karl Heuer committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118

;;; 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))
119

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

Karl Heuer's avatar
Karl Heuer committed
126 127 128 129 130

(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)
131

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

Karl Heuer's avatar
Karl Heuer committed
136 137 138 139 140
  (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
141 142
  ;; 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)
143
  (define-key ediff-mode-map [?\S-\ ] 'ediff-previous-difference)
Karl Heuer's avatar
Karl Heuer committed
144 145 146 147 148 149 150
  (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)
151
  (define-key ediff-mode-map "D" 'ediff-show-diff-output)
Karl Heuer's avatar
Karl Heuer committed
152 153 154 155 156 157
  (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))
158
  (if ediff-narrow-job
Karl Heuer's avatar
Karl Heuer committed
159 160 161 162 163 164 165 166 167 168
      (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)
169
  (define-key ediff-mode-map "E" 'ediff-documentation)
Karl Heuer's avatar
Karl Heuer committed
170 171
  (define-key ediff-mode-map "?" 'ediff-toggle-help)
  (define-key ediff-mode-map "!" 'ediff-update-diffs)
Michael Kifer's avatar
Michael Kifer committed
172
  (define-key ediff-mode-map "M" 'ediff-show-current-session-meta-buffer)
173
  (define-key ediff-mode-map "R" 'ediff-show-registry)
Karl Heuer's avatar
Karl Heuer committed
174 175 176 177 178 179
  (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
180 181
	 ;; Will barf if no ancestor
	 (define-key ediff-mode-map "/" 'ediff-show-ancestor)
Karl Heuer's avatar
Karl Heuer committed
182
	 ;; In merging, we allow only A->C and B->C copying.
Michael Kifer's avatar
Michael Kifer committed
183 184 185
	 (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
186 187
	 (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
188 189 190
	 (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
191 192
	 (define-key ediff-mode-map "&" 'ediff-re-merge))
	(ediff-3way-comparison-job
Michael Kifer's avatar
Michael Kifer committed
193 194 195 196
	 (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
197
	 (define-key ediff-mode-map "c" nil)
Michael Kifer's avatar
Michael Kifer committed
198 199
	 (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
200 201 202 203 204
	 (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
205 206
	 (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
207 208 209 210 211 212 213
	 (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)
214
  (define-key ediff-mode-map "#c"  'ediff-toggle-ignore-case)
Karl Heuer's avatar
Karl Heuer committed
215 216 217 218 219 220 221 222 223
  (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
224
  (define-key ediff-mode-map "="   'ediff-inferior-compare-regions)
225
  (if (and (fboundp 'ediff-show-patch-diagnostics) (ediff-patch-job))
Michael Kifer's avatar
Michael Kifer committed
226
      (define-key ediff-mode-map "P"  'ediff-show-patch-diagnostics))
Karl Heuer's avatar
Karl Heuer committed
227 228 229 230 231 232 233
  (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)
234

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


;;; Setup functions

Michael Kifer's avatar
Michael Kifer committed
242 243 244 245 246
;; 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
247
(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
Michael Kifer's avatar
Michael Kifer committed
248 249
			     startup-hooks setup-parameters
			     &optional merge-buffer-file)
250
  (run-hooks 'ediff-before-setup-hook)
Michael Kifer's avatar
Michael Kifer committed
251 252 253 254
  ;; 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
255
  (if (stringp file-C)
Michael Kifer's avatar
Michael Kifer committed
256 257
      (setq file-C
	    (ediff-convert-standard-filename (expand-file-name file-C))))
Michael Kifer's avatar
Michael Kifer committed
258 259
  (if (stringp merge-buffer-file)
      (progn
260
	(setq merge-buffer-file
Michael Kifer's avatar
Michael Kifer committed
261 262 263 264
	      (ediff-convert-standard-filename
	       (expand-file-name merge-buffer-file)))
	;; check the directory exists
	(or (file-exists-p (file-name-directory merge-buffer-file))
265
	    (error "Directory %s given as place to save the merge doesn't exist"
266
		   (abbreviate-file-name
Michael Kifer's avatar
Michael Kifer committed
267 268 269 270 271 272
		    (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)))
	))
273
  (let* ((control-buffer-name
Karl Heuer's avatar
Karl Heuer committed
274
	  (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
Michael Kifer's avatar
Michael Kifer committed
275
	 (control-buffer (ediff-with-current-buffer buffer-A
Karl Heuer's avatar
Karl Heuer committed
276
			   (get-buffer-create control-buffer-name))))
Michael Kifer's avatar
Michael Kifer committed
277
    (ediff-with-current-buffer control-buffer
278 279
      (ediff-mode)

Michael Kifer's avatar
Michael Kifer committed
280 281 282 283 284 285 286
      (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
287

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

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

Karl Heuer's avatar
Karl Heuer committed
294 295 296 297
      ;; 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)))
298

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

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

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

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

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

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

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

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

      (ediff-choose-syntax-table)
359

Karl Heuer's avatar
Karl Heuer committed
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
      (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))))))
375

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

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

Michael Kifer's avatar
Michael Kifer committed
382 383
      (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
384
      (if ediff-3way-job
Michael Kifer's avatar
Michael Kifer committed
385
	  (ediff-with-current-buffer buffer-C (ediff-strip-mode-line-format)))
386
      (if (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
387
	  (ediff-with-current-buffer ediff-ancestor-buffer
388
	    (ediff-strip-mode-line-format)))
389

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

Karl Heuer's avatar
Karl Heuer committed
392 393 394 395 396 397
      ;; 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))
398

Karl Heuer's avatar
Karl Heuer committed
399 400 401 402 403 404 405
      (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)))
406

Karl Heuer's avatar
Karl Heuer committed
407 408 409 410 411 412
      ;; 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))
413

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

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

Michael Kifer's avatar
Michael Kifer committed
420
      ;; All these must be inside ediff-with-current-buffer control-buffer,
Karl Heuer's avatar
Karl Heuer committed
421 422
      ;; 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
423
      (ediff-with-current-buffer ediff-buffer-A
Karl Heuer's avatar
Karl Heuer committed
424
	(ediff-nuke-selective-display)
425
	(run-hooks 'ediff-prepare-buffer-hook)
Michael Kifer's avatar
Michael Kifer committed
426
	(if (ediff-with-current-buffer control-buffer ediff-merge-job)
Karl Heuer's avatar
Karl Heuer committed
427
	    (setq buffer-read-only t))
428 429
	;; add control-buffer to the list of sessions--no longer used, but may
	;; be used again in the future
430 431 432
	(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
433 434
	(if ediff-make-buffers-readonly-at-startup
	    (setq buffer-read-only t))
Karl Heuer's avatar
Karl Heuer committed
435
	)
Michael Kifer's avatar
Michael Kifer committed
436

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

Karl Heuer's avatar
Karl Heuer committed
450
      (if ediff-3way-job
Michael Kifer's avatar
Michael Kifer committed
451
	  (ediff-with-current-buffer ediff-buffer-C
Karl Heuer's avatar
Karl Heuer committed
452
	    (ediff-nuke-selective-display)
Juanma Barranquero's avatar
Juanma Barranquero committed
453
	    ;; the merge buffer should never be narrowed
454 455 456
	    ;; (it can happen if it is on rmail-mode or similar)
	    (if (ediff-with-current-buffer control-buffer ediff-merge-job)
		(widen))
457
	    (run-hooks 'ediff-prepare-buffer-hook)
Karl Heuer's avatar
Karl Heuer committed
458
	    ;; add control-buffer to the list of sessions
459 460
	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
		(setq ediff-this-buffer-ediff-sessions
Karl Heuer's avatar
Karl Heuer committed
461
		      (cons control-buffer
462
			    ediff-this-buffer-ediff-sessions)))
Michael Kifer's avatar
Michael Kifer committed
463
	    (if ediff-make-buffers-readonly-at-startup
464 465
		(setq buffer-read-only t)
	      (setq buffer-read-only nil))
466 467 468
	    ))

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

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

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

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

Karl Heuer's avatar
Karl Heuer committed
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
      (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)))
	)
516

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

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

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


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

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

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

Michael Kifer's avatar
Michael Kifer committed
572 573
;; This executes in control buffer and sets auto-save, visited file name, etc,
;; in the merge buffer
Michael Kifer's avatar
Michael Kifer committed
574
(defun ediff-arrange-autosave-in-merge-jobs (merge-buffer-file)
Michael Kifer's avatar
Michael Kifer committed
575 576 577 578 579 580 581 582
  (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
583
	  (ediff-verify-file-merge-buffer ediff-merge-store-file)
584
	  (setq merge-buffer-file ediff-merge-store-file)
Michael Kifer's avatar
Michael Kifer committed
585 586 587 588 589 590 591
	  (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
592 593 594


;;; Commands for working with Ediff
595

Karl Heuer's avatar
Karl Heuer committed
596 597 598 599 600 601
(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)
602 603
  (ediff-barf-if-not-control-buffer)
  (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
604 605
	   (not
	    (y-or-n-p
Michael Kifer's avatar
Michael Kifer committed
606
	     "Ancestor buffer will not be used.  Recompute diffs anyway? ")))
Michael Kifer's avatar
Michael Kifer committed
607
      (error "Recomputation of differences canceled"))
608

Michael Kifer's avatar
Michael Kifer committed
609 610
  (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
611
	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
Michael Kifer's avatar
Michael Kifer committed
612 613 614 615 616
	(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
617 618 619 620 621 622 623 624
	(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
625 626 627 628 629 630 631 632

    (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
633
    (ediff-unselect-and-select-difference -1)
634

Karl Heuer's avatar
Karl Heuer committed
635 636 637 638 639 640
    (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))
641

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

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

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

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

Karl Heuer's avatar
Karl Heuer committed
688 689 690 691 692
    (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))
693

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

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

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


737
;; optional NO-REHIGHLIGHT says to not rehighlight buffers
Karl Heuer's avatar
Karl Heuer committed
738 739 740 741
(defun ediff-recenter (&optional no-rehighlight)
  "Bring the highlighted region of all buffers being compared into view.
Reestablish the default three-window display."
  (interactive)
742
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
743 744 745 746
  (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)
747
		 (ediff-buffer-live-p ediff-buffer-C)))
Karl Heuer's avatar
Karl Heuer committed
748 749 750
	(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
751 752
	  (message ediff-KILLED-VITAL-BUFFER
		   (beep 1)))
Karl Heuer's avatar
Karl Heuer committed
753
      ))
754

Karl Heuer's avatar
Karl Heuer committed
755 756 757
  ;; set visibility range appropriate to this invocation of Ediff.
  (ediff-visible-region)
  ;; raise
758
  (if (and (ediff-window-display-p)
Karl Heuer's avatar
Karl Heuer committed
759 760 761 762 763
	   (symbolp this-command)
	   (symbolp last-command)
	   ;; Either one of the display-changing commands
	   (or (memq this-command
		     '(ediff-recenter
764 765
		       ediff-dir-action ediff-registry-action
		       ediff-patch-action
Karl Heuer's avatar
Karl Heuer committed
766 767
		       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
768
	       ;; This avoids raising frames unnecessarily.
Karl Heuer's avatar
Karl Heuer committed
769 770 771 772 773 774 775 776 777
	       (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)
778
	    (raise-frame (window-frame ediff-window-A)))
Karl Heuer's avatar
Karl Heuer committed
779
	(if (window-live-p ediff-window-B)
780
	    (raise-frame (window-frame ediff-window-B)))
Karl Heuer's avatar
Karl Heuer committed
781
	(if (window-live-p ediff-window-C)
782 783 784
	    (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
785
	   (not ediff-use-long-help-message)
Karl Heuer's avatar
Karl Heuer committed
786
	   (not (ediff-frame-iconified-p ediff-control-frame)))
787 788 789 790 791 792
      (if (fboundp 'select-frame-set-input-focus)
	  (select-frame-set-input-focus ediff-control-frame)
	(raise-frame ediff-control-frame)
	(select-frame ediff-control-frame)
	(if (fboundp 'focus-frame)
	    (focus-frame ediff-control-frame))))
793

Karl Heuer's avatar
Karl Heuer committed
794
  ;; Redisplay whatever buffers are showing, if there is a selected difference
795 796
  (let ((control-frame ediff-control-frame)
	(control-buf ediff-control-buffer))
Karl Heuer's avatar
Karl Heuer committed
797 798 799
    (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
800
		 (ediff-buffer-live-p ediff-buffer-C)))
Karl Heuer's avatar
Karl Heuer committed
801 802
	(progn
	  (or no-rehighlight
803
	      (ediff-select-difference ediff-current-difference))
804

Karl Heuer's avatar
Karl Heuer committed
805 806 807 808
	  (ediff-recenter-one-window 'A)
	  (ediff-recenter-one-window 'B)
	  (if ediff-3way-job
	      (ediff-recenter-one-window 'C))
809

Michael Kifer's avatar
Michael Kifer committed
810
	  (ediff-with-current-buffer control-buf
Michael Kifer's avatar
Michael Kifer committed
811
	    (ediff-recenter-ancestor) ; check if ancestor is alive
812

813
	    (if (and (ediff-multiframe-setup-p)
Michael Kifer's avatar
Michael Kifer committed
814
		     (not ediff-use-long-help-message)
815 816 817 818 819
		     (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
820
	  ))
Michael Kifer's avatar
Michael Kifer committed
821

822 823
    (or no-rehighlight
	(ediff-restore-highlighting))
Michael Kifer's avatar
Michael Kifer committed
824
    (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines))
Karl Heuer's avatar
Karl Heuer committed
825
    ))
826

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

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
	(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
867
	(ediff-with-current-buffer ediff-ancestor-buffer
868 869 870 871 872 873 874 875 876 877 878
	  (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
879

880

Karl Heuer's avatar
Karl Heuer committed
881 882
;; This will have to be refined for 3way jobs
(defun ediff-toggle-split ()
883
  "Toggle vertical/horizontal window split.
Karl Heuer's avatar
Karl Heuer committed
884 885
Does nothing if file-A and file-B are in different frames."
  (interactive)
886
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
887 888 889
  (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))
890 891 892
	 (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))))