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)

42
(eval-and-compile
Daniel Hackney's avatar
Daniel Hackney committed
43
  (unless (fboundp 'declare-function) (defmacro declare-function (&rest  _r))))
44

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

Michael Kifer's avatar
Michael Kifer committed
47

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

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

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

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

104

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

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

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

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

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

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

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

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

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

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


;;; Setup functions

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

Michael Kifer's avatar
Michael Kifer committed
280 281 282 283 284 285 286
      (make-local-variable 'ediff-use-long-help-message)
      (make-local-variable 'ediff-prefer-iconified-control-frame)
      (make-local-variable 'ediff-split-window-function)
      (make-local-variable 'ediff-default-variant)
      (make-local-variable 'ediff-merge-window-share)
      (make-local-variable 'ediff-window-setup-function)
      (make-local-variable 'ediff-keep-variants)
Michael Kifer's avatar
Michael Kifer committed
287

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

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

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

Karl Heuer's avatar
Karl Heuer committed
299
      ;; set variables classifying the current ediff job
Michael Kifer's avatar
Michael Kifer committed
300
      ;; must come AFTER setup-parameters
Karl Heuer's avatar
Karl Heuer committed
301 302 303 304 305
      (setq ediff-3way-comparison-job (ediff-3way-comparison-job)
	    ediff-merge-job (ediff-merge-job)
	    ediff-merge-with-ancestor-job (ediff-merge-with-ancestor-job)
	    ediff-3way-job (ediff-3way-job)
	    ediff-diff3-job (ediff-diff3-job)
306 307
	    ediff-narrow-job (ediff-narrow-job)
	    ediff-windows-job (ediff-windows-job)
Karl Heuer's avatar
Karl Heuer committed
308
	    ediff-word-mode-job (ediff-word-mode-job))
309 310

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

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

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

Karl Heuer's avatar
Karl Heuer committed
322 323 324
      ;; adjust for merge jobs
      (if ediff-merge-job
	  (let ((buf
325
		 ;; If default variant is `combined', the right stuff is
Karl Heuer's avatar
Karl Heuer committed
326
		 ;; inserted by ediff-do-merge
327
		 ;; Note: at some point, we tried to put ancestor buffer here
Michael Kifer's avatar
Michael Kifer committed
328
		 ;; (which is currently buffer C.  This didn't work right
329 330 331 332 333 334
		 ;; because the merge buffer will contain lossage: diff regions
		 ;; in the ancestor, which correspond to revisions that agree
		 ;; in both buf A and B.
		 (cond ((eq ediff-default-variant 'default-B)
			buffer-B)
		       (t buffer-A))))
335

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

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

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

      (ediff-choose-syntax-table)
359

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

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

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

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

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

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

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

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

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

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

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

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

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

      (if (ediff-buffer-live-p ediff-ancestor-buffer)
Michael Kifer's avatar
Michael Kifer committed
469
	  (ediff-with-current-buffer ediff-ancestor-buffer
470 471 472 473 474 475 476
	    (ediff-nuke-selective-display)
	    (setq buffer-read-only t)
	    (run-hooks 'ediff-prepare-buffer-hook)
	    (or (memq control-buffer ediff-this-buffer-ediff-sessions)
		(setq ediff-this-buffer-ediff-sessions
		      (cons control-buffer
			    ediff-this-buffer-ediff-sessions)))
Karl Heuer's avatar
Karl Heuer committed
477
	    ))
478

479
      ;; the following must be after setting up  ediff-narrow-bounds AND after
Karl Heuer's avatar
Karl Heuer committed
480 481 482 483
      ;; nuking selective display
      (funcall ediff-setup-diff-regions-function file-A file-B file-C)
      (setq ediff-number-of-differences (length ediff-difference-vector-A))
      (setq ediff-current-difference -1)
484

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

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

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

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

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

Karl Heuer's avatar
Karl Heuer committed
523
      (ediff-refresh-mode-lines)
524 525 526 527 528
      (setq buffer-read-only t)
      (setq ediff-session-registry
	    (cons control-buffer ediff-session-registry))
      (ediff-update-registry)
      (if (ediff-buffer-live-p ediff-meta-buffer)
Michael Kifer's avatar
Michael Kifer committed
529 530
	  (ediff-update-meta-buffer
	   ediff-meta-buffer nil ediff-meta-session-number))
531 532
      (run-hooks 'ediff-startup-hook)
      ) ; eval in control-buffer
533
    control-buffer))
534 535


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

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

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

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


;;; Commands for working with Ediff
596

Karl Heuer's avatar
Karl Heuer committed
597 598 599 600 601 602
(defun ediff-update-diffs ()
  "Recompute difference regions in buffers A, B, and C.
Buffers are not synchronized with their respective files, so changes done
to these buffers are not saved at this point---the user can do this later,
if necessary."
  (interactive)
603
  (ediff-barf-if-not-control-buffer)
Michael Kifer's avatar
Michael Kifer committed
604 605
  (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
606
	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
Michael Kifer's avatar
Michael Kifer committed
607 608 609 610 611
	(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))
612
	(buf-ancestor-file-name (buffer-file-name ediff-ancestor-buffer))
Karl Heuer's avatar
Karl Heuer committed
613 614 615 616 617 618
	(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))
619 620 621 622
        (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
623 624 625 626 627 628 629

    (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)))
630 631
    (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
632

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

Karl Heuer's avatar
Karl Heuer committed
635 636 637
    (setq beg-A (ediff-overlay-start overl-A)
	  beg-B (ediff-overlay-start overl-B)
	  beg-C (ediff-overlay-start overl-C)
638
	  beg-Ancestor (ediff-overlay-start overl-Ancestor)
Karl Heuer's avatar
Karl Heuer committed
639 640
	  end-A (ediff-overlay-end overl-A)
	  end-B (ediff-overlay-end overl-B)
641 642
	  end-C (ediff-overlay-end overl-C)
          end-Ancestor (ediff-overlay-end overl-Ancestor))
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"))
650 651 652 653 654 655
	  (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
656 657
	  )
      ;; not word-mode
658 659
      (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
660
      (if ediff-3way-job
661
	  (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
662 663 664 665 666
      (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
667 668 669 670
      )
    (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)
671 672
    (ediff-clear-diff-vector
     'ediff-difference-vector-Ancestor 'fine-diffs-also)
Karl Heuer's avatar
Karl Heuer committed
673
    (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
674 675
    (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
676 677 678
    (setq ediff-number-of-differences (length ediff-difference-vector-A))
    (delete-file file-A)
    (delete-file file-B)
679 680
    (and file-C (delete-file file-C))
    (and file-Ancestor (delete-file file-Ancestor))
681

Karl Heuer's avatar
Karl Heuer committed
682 683
    (if ediff-3way-job
	(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
684

Karl Heuer's avatar
Karl Heuer committed
685 686 687
    (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
    (message "")
    ))
688

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


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

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

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

Karl Heuer's avatar
Karl Heuer committed
795 796 797 798
	  (ediff-recenter-one-window 'A)
	  (ediff-recenter-one-window 'B)
	  (if ediff-3way-job
	      (ediff-recenter-one-window 'C))
799

Michael Kifer's avatar
Michael Kifer committed
800
	  (ediff-with-current-buffer control-buf
Michael Kifer's avatar
Michael Kifer committed
801
	    (ediff-recenter-ancestor) ; check if ancestor is alive
802

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

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

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

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

870

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