ediff-util.el 154 KB
Newer Older
1
;;; ediff-util.el --- the core commands and utilities of ediff  -*- lexical-binding:t -*-
Erik Naggum's avatar
Erik Naggum committed
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1994-2018 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 <https://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)

Michael Kifer's avatar
Michael Kifer committed
42 43
;; end pacifier

Michael Kifer's avatar
Michael Kifer committed
44

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

Karl Heuer's avatar
Karl Heuer committed
55 56 57 58

;;; Functions

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

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

101

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

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

Karl Heuer's avatar
Karl Heuer committed
123 124 125 126 127

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

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

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

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


;;; Setup functions

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

Michael Kifer's avatar
Michael Kifer committed
277 278 279 280 281 282 283
      (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
284

285 286 287
      (make-local-variable 'window-min-height)
      (setq window-min-height 2)

288 289
      (if (featurep 'xemacs)
	  (make-local-hook 'ediff-after-quit-hook-internal))
290

Karl Heuer's avatar
Karl Heuer committed
291 292 293 294
      ;; 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)))
295

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

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

312 313
      (if (featurep 'xemacs)
	  (make-local-hook 'pre-command-hook))
314

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

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

Karl Heuer's avatar
Karl Heuer committed
333
	    (setq ediff-split-window-function
334 335
		  ediff-merge-split-window-function)

Karl Heuer's avatar
Karl Heuer committed
336 337
	    ;; remember the ancestor buffer, if any
	    (setq ediff-ancestor-buffer buffer-C)
338

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

      (ediff-choose-syntax-table)
356

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

373 374
      (setq ediff-error-buffer
	    (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
375

376 377 378
      (with-current-buffer ediff-error-buffer
	(setq buffer-undo-list t))

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

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

Karl Heuer's avatar
Karl Heuer committed
389 390 391 392 393 394
      ;; 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))
395

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

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

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

Karl Heuer's avatar
Karl Heuer committed
413 414 415
      ;; set up ediff-narrow-bounds, if not set
      (or ediff-narrow-bounds
	  (setq ediff-narrow-bounds ediff-wide-bounds))
416

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

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

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

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

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

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

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

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

Karl Heuer's avatar
Karl Heuer committed
514 515
      (select-window ediff-control-window)
      (ediff-visible-region)
516

517
      (mapc #'funcall startup-hooks)
Michael Kifer's avatar
Michael Kifer committed
518
      (ediff-arrange-autosave-in-merge-jobs merge-buffer-file)
Michael Kifer's avatar
Michael Kifer committed
519

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


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

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

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

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


;;; Commands for working with Ediff
593

Karl Heuer's avatar
Karl Heuer committed
594 595 596 597 598 599
(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)
600
  (ediff-barf-if-not-control-buffer)
Michael Kifer's avatar
Michael Kifer committed
601 602
  (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
603
	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
Michael Kifer's avatar
Michael Kifer committed
604 605 606 607 608
	(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))
609
	(buf-ancestor-file-name (buffer-file-name ediff-ancestor-buffer))
Karl Heuer's avatar
Karl Heuer committed
610 611 612 613 614 615
	(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))
616 617 618 619
        (overl-Ancestor (ediff-get-value-according-to-buffer-type
                         'Ancestor ediff-narrow-bounds))
	beg-A end-A beg-B end-B beg-C end-C beg-Ancestor end-Ancestor
	file-A file-B file-C file-Ancestor)
Michael Kifer's avatar
Michael Kifer committed
620 621 622 623 624 625 626

    (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)))
627 628
    (if (stringp buf-ancestor-file-name)
        (setq buf-ancestor-file-name (file-name-nondirectory buf-ancestor-file-name)))
Michael Kifer's avatar
Michael Kifer committed
629

Karl Heuer's avatar
Karl Heuer committed
630
    (ediff-unselect-and-select-difference -1)
631

Karl Heuer's avatar
Karl Heuer committed
632 633 634
    (setq beg-A (ediff-overlay-start overl-A)
	  beg-B (ediff-overlay-start overl-B)
	  beg-C (ediff-overlay-start overl-C)
635
	  beg-Ancestor (ediff-overlay-start overl-Ancestor)
Karl Heuer's avatar
Karl Heuer committed
636 637
	  end-A (ediff-overlay-end overl-A)
	  end-B (ediff-overlay-end overl-B)
638 639
	  end-C (ediff-overlay-end overl-C)
          end-Ancestor (ediff-overlay-end overl-Ancestor))
640

Karl Heuer's avatar
Karl Heuer committed
641 642 643
    (if ediff-word-mode
	(progn
	  (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
644
	  (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
Karl Heuer's avatar
Karl Heuer committed
645
	  (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
646
	  (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
647 648 649 650 651 652
	  (when ediff-3way-job
            (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
            (setq file-C (ediff-make-temp-file tmp-buffer "regC")))
          (when ediff-merge-with-ancestor-job
            (ediff-wordify beg-Ancestor end-Ancestor ediff-ancestor-buffer tmp-buffer)
            (setq file-Ancestor (ediff-make-temp-file tmp-buffer "regAncestor")))
Karl Heuer's avatar
Karl Heuer committed
653 654
	  )
      ;; not word-mode
655 656
      (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
      (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
Karl Heuer's avatar
Karl Heuer committed
657
      (if ediff-3way-job
658
	  (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
659 660 661 662 663
      (when ediff-merge-with-ancestor-job
        (setq file-Ancestor
              (ediff-make-temp-file
               ediff-ancestor-buffer
               buf-ancestor-file-name)))
Karl Heuer's avatar
Karl Heuer committed
664 665 666 667
      )
    (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)
668 669
    (ediff-clear-diff-vector
     'ediff-difference-vector-Ancestor 'fine-diffs-also)
Karl Heuer's avatar
Karl Heuer committed
670
    (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
671 672
    (funcall ediff-setup-diff-regions-function file-A file-B
             (if ediff-merge-with-ancestor-job file-Ancestor file-C))
Karl Heuer's avatar
Karl Heuer committed
673 674 675
    (setq ediff-number-of-differences (length ediff-difference-vector-A))
    (delete-file file-A)
    (delete-file file-B)
676 677
    (and file-C (delete-file file-C))
    (and file-Ancestor (delete-file file-Ancestor))
678

Karl Heuer's avatar
Karl Heuer committed
679 680
    (if ediff-3way-job
	(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
681

Karl Heuer's avatar
Karl Heuer committed
682 683 684
    (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
    (message "")
    ))
685

Michael Kifer's avatar
Michael Kifer committed
686
;; Not bound to any key---to dangerous.  A user can do it if necessary.
Karl Heuer's avatar
Karl Heuer committed
687
(defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
Michael Kifer's avatar
Michael Kifer committed
688
  "Revert buffers A, B and C.  Then rerun Ediff on file A and file B."
Karl Heuer's avatar
Karl Heuer committed
689
  (interactive "P")
690
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
691 692 693 694
  (let ((bufA ediff-buffer-A)
	(bufB ediff-buffer-B)
	(bufC ediff-buffer-C)
	(ctl-buf ediff-control-buffer)
695
	(keep-variants ediff-keep-variants)
Karl Heuer's avatar
Karl Heuer committed
696 697 698 699
	(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
700
    (ediff-with-current-buffer bufA
Karl Heuer's avatar
Karl Heuer committed
701
      (revert-buffer t noconfirm))
Michael Kifer's avatar
Michael Kifer committed
702
    (ediff-with-current-buffer bufB
Karl Heuer's avatar
Karl Heuer committed
703 704 705
      (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
706
	(ediff-with-current-buffer bufC
Karl Heuer's avatar
Karl Heuer committed
707 708 709 710
	  (revert-buffer t noconfirm)))
    (if merge
	(progn
	  (set-buffer ctl-buf)
711 712 713 714
	  ;; 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
715 716 717 718 719 720 721
	  (kill-buffer bufC)
	  (if ancestor-job
	      (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
	    (ediff-merge-buffers bufA bufB)))
      (ediff-update-diffs))))


722
;; optional NO-REHIGHLIGHT says to not rehighlight buffers
Karl Heuer's avatar
Karl Heuer committed
723 724
(defun ediff-recenter (&optional no-rehighlight)
  "Bring the highlighted region of all buffers being compared into view.
725
Reestablish the default window display."
Karl Heuer's avatar
Karl Heuer committed
726
  (interactive)
727
  (ediff-barf-if-not-control-buffer)
Karl Heuer's avatar
Karl Heuer committed
728 729 730 731
  (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)
732 733 734
		 (ediff-buffer-live-p ediff-buffer-C))
             (or (not ediff-merge-with-ancestor-job)
		 (ediff-buffer-live-p ediff-ancestor-buffer)))
Karl Heuer's avatar
Karl Heuer committed
735 736 737
	(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
738 739
	  (message ediff-KILLED-VITAL-BUFFER
		   (beep 1)))
Karl Heuer's avatar
Karl Heuer committed
740
      ))
741

Karl Heuer's avatar
Karl Heuer committed
742 743 744
  ;; set visibility range appropriate to this invocation of Ediff.
  (ediff-visible-region)
  ;; raise
745
  (if (and (ediff-window-display-p)
Karl Heuer's avatar
Karl Heuer committed
746 747 748 749 750
	   (symbolp this-command)
	   (symbolp last-command)
	   ;; Either one of the display-changing commands
	   (or (memq this-command
		     '(ediff-recenter
751 752
		       ediff-dir-action ediff-registry-action
		       ediff-patch-action
Karl Heuer's avatar
Karl Heuer committed
753 754
		       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
755
	       ;; This avoids raising frames unnecessarily.
Karl Heuer's avatar
Karl Heuer committed
756 757 758 759 760 761 762 763 764
	       (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)
765
	    (raise-frame (window-frame ediff-window-A)))
Karl Heuer's avatar
Karl Heuer committed
766
	(if (window-live-p ediff-window-B)
767
	    (raise-frame (window-frame ediff-window-B)))
Karl Heuer's avatar
Karl Heuer committed
768
	(if (window-live-p ediff-window-C)
769 770 771
	    (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
772
	   (not ediff-use-long-help-message)
Karl Heuer's avatar
Karl Heuer committed
773
	   (not (ediff-frame-iconified-p ediff-control-frame)))
774 775 776 777
      (if (fboundp 'select-frame-set-input-focus)
	  (select-frame-set-input-focus ediff-control-frame)
	(raise-frame ediff-control-frame)
	(select-frame ediff-control-frame)
778 779
	(and (featurep 'xemacs) (fboundp 'focus-frame)
	     (focus-frame ediff-control-frame))))
780

Karl Heuer's avatar
Karl Heuer committed
781
  ;; Redisplay whatever buffers are showing, if there is a selected difference
782 783
  (let ((control-frame ediff-control-frame)
	(control-buf ediff-control-buffer))
Karl Heuer's avatar
Karl Heuer committed
784 785 786
    (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
787
		 (ediff-buffer-live-p ediff-buffer-C)))
Karl Heuer's avatar
Karl Heuer committed
788 789
	(progn
	  (or no-rehighlight
790
	      (ediff-select-difference ediff-current-difference))
791

Karl Heuer's avatar
Karl Heuer committed
792 793 794 795
	  (ediff-recenter-one-window 'A)
	  (ediff-recenter-one-window 'B)
	  (if ediff-3way-job
	      (ediff-recenter-one-window 'C))
796

Michael Kifer's avatar
Michael Kifer committed
797
	  (ediff-with-current-buffer control-buf
Michael Kifer's avatar
Michael Kifer committed
798
	    (ediff-recenter-ancestor) ; check if ancestor is alive
799

800
	    (if (and (ediff-multiframe-setup-p)
Michael Kifer's avatar
Michael Kifer committed
801
		     (not ediff-use-long-help-message)
802 803 804 805 806
		     (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
807
	  ))
Michael Kifer's avatar
Michael Kifer committed
808

809 810
    (or no-rehighlight
	(ediff-restore-highlighting))
Michael Kifer's avatar
Michael Kifer committed
811
    (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines))
Karl Heuer's avatar
Karl Heuer committed
812
    ))
813

Karl Heuer's avatar
Karl Heuer committed
814 815 816
;; this function returns to the window it was called from
;; (which was the control window)
(defun ediff-recenter-one-window (buf-type)
817 818 819 820
  (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
821
		     (ediff-get-value-according-to-buffer-type
822 823 824
		      buf-type ediff-narrow-bounds)))
	     (job-name ediff-job-name)
	     (control-buf ediff-control-buffer)
Michael Kifer's avatar
Michael Kifer committed
825 826
	     (window-name (ediff-get-symbol-from-alist
			   buf-type ediff-window-alist))
827 828
	     (window (if (window-live-p (symbol-value window-name))
			 (symbol-value window-name))))
829

830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
	(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
854
	(ediff-with-current-buffer ediff-ancestor-buffer
855 856 857 858 859 860 861 862 863 864 865
	  (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
866

867

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