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-2013 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 43 44
(eval-and-compile
  (unless (fboundp 'declare-function) (defmacro declare-function (&rest  r))))

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

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

Michael Kifer's avatar
Michael Kifer committed
50

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

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

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

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

107

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

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

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

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

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

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

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


;;; Setup functions

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

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

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

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

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

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

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

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

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

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

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

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

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

      (ediff-choose-syntax-table)
361

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


;;; Commands for working with Ediff
597

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

877

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