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,
4 5
;;   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
;;   Free Software Foundation, Inc.
Karl Heuer's avatar
Karl Heuer committed
6

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

;; This file is part of GNU Emacs.

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

;; 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
23
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Karl Heuer's avatar
Karl Heuer committed
24

25 26
;;; Commentary:

Karl Heuer's avatar
Karl Heuer committed
27
;;; Code:
28

Karl Heuer's avatar
Karl Heuer committed
29

30 31
(provide 'ediff-util)

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

42 43
(defvar ediff-after-quit-hook-internal nil)

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

Michael Kifer's avatar
Michael Kifer committed
47
(eval-when-compile
48 49
  (require 'ediff))

Michael Kifer's avatar
Michael Kifer committed
50 51
;; end pacifier

Michael Kifer's avatar
Michael Kifer committed
52

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

Karl Heuer's avatar
Karl Heuer committed
63 64 65 66

;;; Functions

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

Commands:
\\{ediff-mode-map}"
  (kill-all-local-variables)
  (setq major-mode 'ediff-mode)
  (setq mode-name "Ediff")
100 101 102 103 104
  ;; 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
105
  ;; if-statement, since XEmacs doesn't have this.
106
  (run-hooks 'ediff-mode-hook))
Karl Heuer's avatar
Karl Heuer committed
107

108

Karl Heuer's avatar
Karl Heuer committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122

;;; 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))
123

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

Karl Heuer's avatar
Karl Heuer committed
130 131 132 133 134

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

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

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

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


;;; Setup functions

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

Michael Kifer's avatar
Michael Kifer committed
283 284 285 286 287 288 289
      (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
290

291 292 293
      (make-local-variable 'window-min-height)
      (setq window-min-height 2)

294 295
      (if (featurep 'xemacs)
	  (make-local-hook 'ediff-after-quit-hook-internal))
296

Karl Heuer's avatar
Karl Heuer committed
297 298 299 300
      ;; 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)))
301

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

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

318 319
      (if (featurep 'xemacs)
	  (make-local-hook 'pre-command-hook))
320

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

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

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

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

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

      (ediff-choose-syntax-table)
362

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

379 380
      (setq ediff-error-buffer
	    (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
381

382 383 384
      (with-current-buffer ediff-error-buffer
	(setq buffer-undo-list t))

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

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

Karl Heuer's avatar
Karl Heuer committed
395 396 397 398 399 400
      ;; 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))
401

Karl Heuer's avatar
Karl Heuer committed
402 403 404 405 406 407 408
      (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)))
409

Karl Heuer's avatar
Karl Heuer committed
410 411 412 413 414 415
      ;; 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))
416

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

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

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

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

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

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

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

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

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

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

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

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

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


Karl Heuer's avatar
Karl Heuer committed
539
;; This function assumes that we are in the window where control buffer is
540
;; to reside.
Karl Heuer's avatar
Karl Heuer committed
541 542 543 544 545
(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))
546
  (let ((window-min-height 2))
Karl Heuer's avatar
Karl Heuer committed
547 548 549 550
    (erase-buffer)
    (ediff-set-help-message)
    (insert ediff-help-message)
    (shrink-window-if-larger-than-buffer)
551
    (or (ediff-multiframe-setup-p)
Karl Heuer's avatar
Karl Heuer committed
552
	(ediff-indent-help-message))
Michael Kifer's avatar
Michael Kifer committed
553 554
    (ediff-set-help-overlays)

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

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

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


;;; Commands for working with Ediff
598

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

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

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

Karl Heuer's avatar
Karl Heuer committed
638 639 640 641 642 643
    (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))
644

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

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

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

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

Karl Heuer's avatar
Karl Heuer committed
691 692 693 694 695
    (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))
696

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

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

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


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

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

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

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

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

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

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

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

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

878

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