Spelling fixes.
[bpt/emacs.git] / lisp / vc / ediff-util.el
CommitLineData
475f9031 1;;; ediff-util.el --- the core commands and utilities of ediff
b578f267 2
95df8112 3;; Copyright (C) 1994-2011 Free Software Foundation, Inc.
475f9031 4
50a07e18 5;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
bd78fa1d 6;; Package: ediff
475f9031
KH
7
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
475f9031 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
475f9031
KH
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
475f9031 22
3afbc435
PJ
23;;; Commentary:
24
475f9031 25;;; Code:
71296446 26
475f9031 27
2d84cc27
MK
28(provide 'ediff-util)
29
ddc90f39 30;; Compiler pacifier
3af0304a
MK
31(defvar ediff-use-toolbar-p)
32(defvar ediff-toolbar-height)
ddc90f39
MK
33(defvar ediff-toolbar)
34(defvar ediff-toolbar-3way)
35(defvar bottom-toolbar)
36(defvar bottom-toolbar-visible-p)
37(defvar bottom-toolbar-height)
38(defvar mark-active)
39
b9fe4732
MK
40(defvar ediff-after-quit-hook-internal nil)
41
acb93bb2
MK
42(eval-and-compile
43 (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
44
ddc90f39 45(eval-when-compile
8480ec72
GM
46 (require 'ediff))
47
bbe6126c
MK
48;; end pacifier
49
2eb4bdca 50
bf5d92c5
MK
51(require 'ediff-init)
52(require 'ediff-help)
53(require 'ediff-mult)
ddc90f39
MK
54(require 'ediff-wind)
55(require 'ediff-diff)
56(require 'ediff-merg)
a5254f37 57;; for compatibility with current stable version of xemacs
e83d1fe8 58(if (featurep 'xemacs)
2eb4bdca 59 (require 'ediff-tbar))
bf5d92c5 60
475f9031
KH
61\f
62;;; Functions
63
64(defun ediff-mode ()
651342bc
MK
65 "Ediff mode controls all operations in a single Ediff session.
66This mode is entered through one of the following commands:
475f9031
KH
67 `ediff'
68 `ediff-files'
69 `ediff-buffers'
bbe6126c 70 `ebuffers'
475f9031
KH
71 `ediff3'
72 `ediff-files3'
73 `ediff-buffers3'
bbe6126c 74 `ebuffers3'
475f9031
KH
75 `ediff-merge'
76 `ediff-merge-files'
77 `ediff-merge-files-with-ancestor'
78 `ediff-merge-buffers'
79 `ediff-merge-buffers-with-ancestor'
80 `ediff-merge-revisions'
81 `ediff-merge-revisions-with-ancestor'
41d25ad0
KH
82 `ediff-windows-wordwise'
83 `ediff-windows-linewise'
84 `ediff-regions-wordwise'
85 `ediff-regions-linewise'
475f9031
KH
86 `epatch'
87 `ediff-patch-file'
88 `ediff-patch-buffer'
89 `epatch-buffer'
1e70790f 90 `erevision'
475f9031
KH
91 `ediff-revision'
92
93Commands:
94\\{ediff-mode-map}"
4d789d84 95 ;; FIXME: Use define-derived-mode.
475f9031
KH
96 (kill-all-local-variables)
97 (setq major-mode 'ediff-mode)
98 (setq mode-name "Ediff")
8ea74b0e
MK
99 ;; We use run-hooks instead of run-mode-hooks for two reasons.
100 ;; The ediff control buffer is read-only and it is not supposed to be
101 ;; modified by minor modes and such. So, run-mode-hooks doesn't do anything
102 ;; useful here on top of what run-hooks does.
103 ;; Second, changing run-hooks to run-mode-hooks would require an
56eaedfe 104 ;; if-statement, since XEmacs doesn't have this.
8ea74b0e 105 (run-hooks 'ediff-mode-hook))
475f9031 106
71296446 107
475f9031
KH
108\f
109;;; Build keymaps
110
111(ediff-defvar-local ediff-mode-map nil
112 "Local keymap used in Ediff mode.
113This is local to each Ediff Control Panel, so they may vary from invocation
114to invocation.")
115
116;; Set up the keymap in the control buffer
117(defun ediff-set-keys ()
118 "Set up Ediff keymap, if necessary."
119 (if (null ediff-mode-map)
120 (ediff-setup-keymap))
121 (use-local-map ediff-mode-map))
71296446 122
475f9031
KH
123;; Reload Ediff keymap. For debugging only.
124(defun ediff-reload-keymap ()
125 (interactive)
126 (setq ediff-mode-map nil)
127 (ediff-set-keys))
71296446 128
475f9031
KH
129
130(defun ediff-setup-keymap ()
131 "Set up the keymap used in the control buffer of Ediff."
132 (setq ediff-mode-map (make-sparse-keymap))
133 (suppress-keymap ediff-mode-map)
71296446 134
92c51e07 135 (define-key ediff-mode-map
e83d1fe8 136 (if (featurep 'emacs) [mouse-2] [button2]) 'ediff-help-for-quick-help)
92c51e07
MK
137 (define-key ediff-mode-map "\C-m" 'ediff-help-for-quick-help)
138
475f9031
KH
139 (define-key ediff-mode-map "p" 'ediff-previous-difference)
140 (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
475f9031
KH
141 (define-key ediff-mode-map [delete] 'ediff-previous-difference)
142 (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
143 'ediff-previous-difference nil))
bd698e98
MK
144 ;; must come after C-h, or else C-h wipes out backspace's binding in XEmacs
145 (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
475f9031
KH
146 (define-key ediff-mode-map "n" 'ediff-next-difference)
147 (define-key ediff-mode-map " " 'ediff-next-difference)
148 (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
149 (define-key ediff-mode-map "g" nil)
150 (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
151 (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
152 (define-key ediff-mode-map "q" 'ediff-quit)
651342bc 153 (define-key ediff-mode-map "D" 'ediff-show-diff-output)
475f9031
KH
154 (define-key ediff-mode-map "z" 'ediff-suspend)
155 (define-key ediff-mode-map "\C-l" 'ediff-recenter)
156 (define-key ediff-mode-map "|" 'ediff-toggle-split)
157 (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
158 (or ediff-word-mode
159 (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
41d25ad0 160 (if ediff-narrow-job
475f9031
KH
161 (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
162 (define-key ediff-mode-map "~" 'ediff-swap-buffers)
163 (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
164 (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
165 (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
166 (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
167 (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
168 (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
169 (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
170 (define-key ediff-mode-map "i" 'ediff-status-info)
651342bc 171 (define-key ediff-mode-map "E" 'ediff-documentation)
475f9031
KH
172 (define-key ediff-mode-map "?" 'ediff-toggle-help)
173 (define-key ediff-mode-map "!" 'ediff-update-diffs)
328b4b70 174 (define-key ediff-mode-map "M" 'ediff-show-current-session-meta-buffer)
651342bc 175 (define-key ediff-mode-map "R" 'ediff-show-registry)
475f9031
KH
176 (or ediff-word-mode
177 (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
178 (define-key ediff-mode-map "a" nil)
179 (define-key ediff-mode-map "b" nil)
180 (define-key ediff-mode-map "r" nil)
181 (cond (ediff-merge-job
651342bc
MK
182 ;; Will barf if no ancestor
183 (define-key ediff-mode-map "/" 'ediff-show-ancestor)
475f9031 184 ;; In merging, we allow only A->C and B->C copying.
4ae69eac
MK
185 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
186 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
187 (define-key ediff-mode-map "r" 'ediff-restore-diff-in-merge-buffer)
475f9031
KH
188 (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
189 (define-key ediff-mode-map "+" 'ediff-combine-diffs)
3af0304a
MK
190 (define-key ediff-mode-map "$" nil)
191 (define-key ediff-mode-map "$$" 'ediff-toggle-show-clashes-only)
192 (define-key ediff-mode-map "$*" 'ediff-toggle-skip-changed-regions)
475f9031
KH
193 (define-key ediff-mode-map "&" 'ediff-re-merge))
194 (ediff-3way-comparison-job
4ae69eac
MK
195 (define-key ediff-mode-map "ab" 'ediff-copy-A-to-B)
196 (define-key ediff-mode-map "ba" 'ediff-copy-B-to-A)
197 (define-key ediff-mode-map "ac" 'ediff-copy-A-to-C)
198 (define-key ediff-mode-map "bc" 'ediff-copy-B-to-C)
475f9031 199 (define-key ediff-mode-map "c" nil)
4ae69eac
MK
200 (define-key ediff-mode-map "ca" 'ediff-copy-C-to-A)
201 (define-key ediff-mode-map "cb" 'ediff-copy-C-to-B)
475f9031
KH
202 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
203 (define-key ediff-mode-map "rb" 'ediff-restore-diff)
204 (define-key ediff-mode-map "rc" 'ediff-restore-diff)
205 (define-key ediff-mode-map "C" 'ediff-toggle-read-only))
206 (t ; 2-way comparison
4ae69eac
MK
207 (define-key ediff-mode-map "a" 'ediff-copy-A-to-B)
208 (define-key ediff-mode-map "b" 'ediff-copy-B-to-A)
475f9031
KH
209 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
210 (define-key ediff-mode-map "rb" 'ediff-restore-diff))
211 ) ; cond
212 (define-key ediff-mode-map "G" 'ediff-submit-report)
213 (define-key ediff-mode-map "#" nil)
214 (define-key ediff-mode-map "#h" 'ediff-toggle-regexp-match)
215 (define-key ediff-mode-map "#f" 'ediff-toggle-regexp-match)
b6178721 216 (define-key ediff-mode-map "#c" 'ediff-toggle-ignore-case)
475f9031
KH
217 (or ediff-word-mode
218 (define-key ediff-mode-map "##" 'ediff-toggle-skip-similar))
219 (define-key ediff-mode-map "o" nil)
220 (define-key ediff-mode-map "A" 'ediff-toggle-read-only)
221 (define-key ediff-mode-map "B" 'ediff-toggle-read-only)
222 (define-key ediff-mode-map "w" nil)
223 (define-key ediff-mode-map "wa" 'ediff-save-buffer)
224 (define-key ediff-mode-map "wb" 'ediff-save-buffer)
225 (define-key ediff-mode-map "wd" 'ediff-save-buffer)
92c51e07 226 (define-key ediff-mode-map "=" 'ediff-inferior-compare-regions)
743a79af 227 (if (and (fboundp 'ediff-show-patch-diagnostics) (ediff-patch-job))
bbe6126c 228 (define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics))
475f9031
KH
229 (if ediff-3way-job
230 (progn
231 (define-key ediff-mode-map "wc" 'ediff-save-buffer)
232 (define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
233 ))
234
235 (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
71296446 236
475f9031
KH
237 ;; Allow ediff-mode-map to be referenced indirectly
238 (fset 'ediff-mode-map ediff-mode-map)
651342bc 239 (run-hooks 'ediff-keymap-setup-hook))
475f9031
KH
240
241
242;;; Setup functions
243
ddc90f39
MK
244;; Common startup entry for all Ediff functions It now returns control buffer
245;; so other functions can do post-processing SETUP-PARAMETERS is a list of the
246;; form ((param .val) (param . val)...) This serves a similar purpose to
247;; STARTUP-HOOKS, but these parameters are set in the new control buffer right
248;; after this buf is created and before any windows are set and such.
475f9031 249(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
328b4b70
MK
250 startup-hooks setup-parameters
251 &optional merge-buffer-file)
657f9cb8 252 (run-hooks 'ediff-before-setup-hook)
92c51e07
MK
253 ;; ediff-convert-standard-filename puts file names in the form appropriate
254 ;; for the OS at hand.
255 (setq file-A (ediff-convert-standard-filename (expand-file-name file-A)))
256 (setq file-B (ediff-convert-standard-filename (expand-file-name file-B)))
475f9031 257 (if (stringp file-C)
92c51e07
MK
258 (setq file-C
259 (ediff-convert-standard-filename (expand-file-name file-C))))
328b4b70
MK
260 (if (stringp merge-buffer-file)
261 (progn
71296446 262 (setq merge-buffer-file
328b4b70
MK
263 (ediff-convert-standard-filename
264 (expand-file-name merge-buffer-file)))
265 ;; check the directory exists
266 (or (file-exists-p (file-name-directory merge-buffer-file))
3afbc435 267 (error "Directory %s given as place to save the merge doesn't exist"
71296446 268 (abbreviate-file-name
328b4b70
MK
269 (file-name-directory merge-buffer-file))))
270 (if (and (file-exists-p merge-buffer-file)
271 (file-directory-p merge-buffer-file))
272 (error "The merge buffer file %s must not be a directory"
273 (abbreviate-file-name merge-buffer-file)))
274 ))
71296446 275 (let* ((control-buffer-name
475f9031 276 (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
e756eb9f 277 (control-buffer (ediff-with-current-buffer buffer-A
475f9031 278 (get-buffer-create control-buffer-name))))
e756eb9f 279 (ediff-with-current-buffer control-buffer
71296446
JB
280 (ediff-mode)
281
ddc90f39
MK
282 (make-local-variable 'ediff-use-long-help-message)
283 (make-local-variable 'ediff-prefer-iconified-control-frame)
284 (make-local-variable 'ediff-split-window-function)
285 (make-local-variable 'ediff-default-variant)
286 (make-local-variable 'ediff-merge-window-share)
287 (make-local-variable 'ediff-window-setup-function)
288 (make-local-variable 'ediff-keep-variants)
3af0304a 289
2d84cc27
MK
290 (make-local-variable 'window-min-height)
291 (setq window-min-height 2)
292
d2049452
GM
293 (if (featurep 'xemacs)
294 (make-local-hook 'ediff-after-quit-hook-internal))
50a07e18 295
475f9031
KH
296 ;; unwrap set up parameters passed as argument
297 (while setup-parameters
298 (set (car (car setup-parameters)) (cdr (car setup-parameters)))
299 (setq setup-parameters (cdr setup-parameters)))
71296446 300
475f9031 301 ;; set variables classifying the current ediff job
ddc90f39 302 ;; must come AFTER setup-parameters
475f9031
KH
303 (setq ediff-3way-comparison-job (ediff-3way-comparison-job)
304 ediff-merge-job (ediff-merge-job)
305 ediff-merge-with-ancestor-job (ediff-merge-with-ancestor-job)
306 ediff-3way-job (ediff-3way-job)
307 ediff-diff3-job (ediff-diff3-job)
41d25ad0
KH
308 ediff-narrow-job (ediff-narrow-job)
309 ediff-windows-job (ediff-windows-job)
475f9031 310 ediff-word-mode-job (ediff-word-mode-job))
651342bc
MK
311
312 ;; Don't delete variants in case of ediff-buffer-* jobs without asking.
537b04b9 313 ;; This is because one may lose work---dangerous.
651342bc
MK
314 (if (string-match "buffer" (symbol-name ediff-job-name))
315 (setq ediff-keep-variants t))
316
d2049452
GM
317 (if (featurep 'xemacs)
318 (make-local-hook 'pre-command-hook))
b9fe4732 319
4ae69eac 320 (if (ediff-window-display-p)
b9fe4732 321 (add-hook 'pre-command-hook 'ediff-spy-after-mouse nil 'local))
651342bc 322 (setq ediff-mouse-pixel-position (mouse-pixel-position))
71296446 323
475f9031
KH
324 ;; adjust for merge jobs
325 (if ediff-merge-job
326 (let ((buf
651342bc 327 ;; If default variant is `combined', the right stuff is
475f9031 328 ;; inserted by ediff-do-merge
651342bc 329 ;; Note: at some point, we tried to put ancestor buffer here
3af0304a 330 ;; (which is currently buffer C. This didn't work right
651342bc
MK
331 ;; because the merge buffer will contain lossage: diff regions
332 ;; in the ancestor, which correspond to revisions that agree
333 ;; in both buf A and B.
334 (cond ((eq ediff-default-variant 'default-B)
335 buffer-B)
336 (t buffer-A))))
71296446 337
475f9031 338 (setq ediff-split-window-function
71296446
JB
339 ediff-merge-split-window-function)
340
475f9031
KH
341 ;; remember the ancestor buffer, if any
342 (setq ediff-ancestor-buffer buffer-C)
71296446 343
475f9031
KH
344 (setq buffer-C
345 (get-buffer-create
346 (ediff-unique-buffer-name "*ediff-merge" "*")))
7fdbcd83 347 (with-current-buffer buffer-C
15c77b9e 348 (insert-buffer-substring buf)
e2de3a29 349 (goto-char (point-min))
e756eb9f 350 (funcall (ediff-with-current-buffer buf major-mode))
50a07e18 351 (widen) ; merge buffer is always widened
bbe6126c 352 (add-hook 'local-write-file-hooks 'ediff-set-merge-mode nil t)
41d25ad0 353 )))
71296446 354 (setq buffer-read-only nil
475f9031
KH
355 ediff-buffer-A buffer-A
356 ediff-buffer-B buffer-B
357 ediff-buffer-C buffer-C
358 ediff-control-buffer control-buffer)
4986c2c6
MK
359
360 (ediff-choose-syntax-table)
71296446 361
475f9031
KH
362 (setq ediff-control-buffer-suffix
363 (if (string-match "<[0-9]*>" control-buffer-name)
364 (substring control-buffer-name
365 (match-beginning 0) (match-end 0))
366 "")
367 ediff-control-buffer-number
368 (max
369 0
370 (1-
371 (string-to-number
372 (substring
373 ediff-control-buffer-suffix
374 (or
375 (string-match "[0-9]+" ediff-control-buffer-suffix)
376 0))))))
71296446 377
651342bc
MK
378 (setq ediff-error-buffer
379 (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
71296446 380
e392d1cc
DN
381 (with-current-buffer ediff-error-buffer
382 (setq buffer-undo-list t))
383
e756eb9f
MK
384 (ediff-with-current-buffer buffer-A (ediff-strip-mode-line-format))
385 (ediff-with-current-buffer buffer-B (ediff-strip-mode-line-format))
475f9031 386 (if ediff-3way-job
e756eb9f 387 (ediff-with-current-buffer buffer-C (ediff-strip-mode-line-format)))
651342bc 388 (if (ediff-buffer-live-p ediff-ancestor-buffer)
e756eb9f 389 (ediff-with-current-buffer ediff-ancestor-buffer
651342bc 390 (ediff-strip-mode-line-format)))
71296446 391
475f9031 392 (ediff-save-protected-variables) ; save variables to be restored on exit
71296446 393
475f9031
KH
394 ;; ediff-setup-diff-regions-function must be set after setup
395 ;; parameters are processed.
396 (setq ediff-setup-diff-regions-function
397 (if ediff-diff3-job
398 'ediff-setup-diff-regions3
399 'ediff-setup-diff-regions))
71296446 400
475f9031
KH
401 (setq ediff-wide-bounds
402 (list (ediff-make-bullet-proof-overlay
403 '(point-min) '(point-max) ediff-buffer-A)
404 (ediff-make-bullet-proof-overlay
405 '(point-min) '(point-max) ediff-buffer-B)
406 (ediff-make-bullet-proof-overlay
407 '(point-min) '(point-max) ediff-buffer-C)))
71296446 408
475f9031
KH
409 ;; This has effect only on ediff-windows/regions
410 ;; In all other cases, ediff-visible-region sets visibility bounds to
411 ;; ediff-wide-bounds, and ediff-narrow-bounds are ignored.
412 (if ediff-start-narrowed
413 (setq ediff-visible-bounds ediff-narrow-bounds)
414 (setq ediff-visible-bounds ediff-wide-bounds))
71296446 415
475f9031 416 (ediff-set-keys) ; comes after parameter setup
71296446 417
475f9031
KH
418 ;; set up ediff-narrow-bounds, if not set
419 (or ediff-narrow-bounds
420 (setq ediff-narrow-bounds ediff-wide-bounds))
71296446 421
e756eb9f 422 ;; All these must be inside ediff-with-current-buffer control-buffer,
475f9031
KH
423 ;; since these vars are local to control-buffer
424 ;; These won't run if there are errors in diff
e756eb9f 425 (ediff-with-current-buffer ediff-buffer-A
475f9031 426 (ediff-nuke-selective-display)
651342bc 427 (run-hooks 'ediff-prepare-buffer-hook)
e756eb9f 428 (if (ediff-with-current-buffer control-buffer ediff-merge-job)
475f9031 429 (setq buffer-read-only t))
41d25ad0
KH
430 ;; add control-buffer to the list of sessions--no longer used, but may
431 ;; be used again in the future
651342bc
MK
432 (or (memq control-buffer ediff-this-buffer-ediff-sessions)
433 (setq ediff-this-buffer-ediff-sessions
434 (cons control-buffer ediff-this-buffer-ediff-sessions)))
1e70790f
MK
435 (if ediff-make-buffers-readonly-at-startup
436 (setq buffer-read-only t))
475f9031 437 )
1e70790f 438
e756eb9f 439 (ediff-with-current-buffer ediff-buffer-B
475f9031 440 (ediff-nuke-selective-display)
651342bc 441 (run-hooks 'ediff-prepare-buffer-hook)
e756eb9f 442 (if (ediff-with-current-buffer control-buffer ediff-merge-job)
475f9031 443 (setq buffer-read-only t))
475f9031 444 ;; add control-buffer to the list of sessions
651342bc
MK
445 (or (memq control-buffer ediff-this-buffer-ediff-sessions)
446 (setq ediff-this-buffer-ediff-sessions
447 (cons control-buffer ediff-this-buffer-ediff-sessions)))
1e70790f
MK
448 (if ediff-make-buffers-readonly-at-startup
449 (setq buffer-read-only t))
475f9031 450 )
1e70790f 451
475f9031 452 (if ediff-3way-job
e756eb9f 453 (ediff-with-current-buffer ediff-buffer-C
475f9031 454 (ediff-nuke-selective-display)
fe7a3057 455 ;; the merge buffer should never be narrowed
50a07e18
MK
456 ;; (it can happen if it is on rmail-mode or similar)
457 (if (ediff-with-current-buffer control-buffer ediff-merge-job)
458 (widen))
651342bc 459 (run-hooks 'ediff-prepare-buffer-hook)
475f9031 460 ;; add control-buffer to the list of sessions
651342bc
MK
461 (or (memq control-buffer ediff-this-buffer-ediff-sessions)
462 (setq ediff-this-buffer-ediff-sessions
475f9031 463 (cons control-buffer
71296446 464 ediff-this-buffer-ediff-sessions)))
1e70790f 465 (if ediff-make-buffers-readonly-at-startup
50a07e18
MK
466 (setq buffer-read-only t)
467 (setq buffer-read-only nil))
651342bc
MK
468 ))
469
470 (if (ediff-buffer-live-p ediff-ancestor-buffer)
e756eb9f 471 (ediff-with-current-buffer ediff-ancestor-buffer
651342bc
MK
472 (ediff-nuke-selective-display)
473 (setq buffer-read-only t)
474 (run-hooks 'ediff-prepare-buffer-hook)
475 (or (memq control-buffer ediff-this-buffer-ediff-sessions)
476 (setq ediff-this-buffer-ediff-sessions
477 (cons control-buffer
478 ediff-this-buffer-ediff-sessions)))
475f9031 479 ))
71296446 480
50a07e18 481 ;; the following must be after setting up ediff-narrow-bounds AND after
475f9031
KH
482 ;; nuking selective display
483 (funcall ediff-setup-diff-regions-function file-A file-B file-C)
484 (setq ediff-number-of-differences (length ediff-difference-vector-A))
485 (setq ediff-current-difference -1)
71296446 486
475f9031
KH
487 (ediff-make-current-diff-overlay 'A)
488 (ediff-make-current-diff-overlay 'B)
489 (if ediff-3way-job
490 (ediff-make-current-diff-overlay 'C))
651342bc
MK
491 (if ediff-merge-with-ancestor-job
492 (ediff-make-current-diff-overlay 'Ancestor))
71296446 493
475f9031 494 (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
71296446 495
475f9031
KH
496 (let ((shift-A (ediff-overlay-start
497 (ediff-get-value-according-to-buffer-type
498 'A ediff-narrow-bounds)))
499 (shift-B (ediff-overlay-start
500 (ediff-get-value-according-to-buffer-type
501 'B ediff-narrow-bounds)))
502 (shift-C (ediff-overlay-start
503 (ediff-get-value-according-to-buffer-type
504 'C ediff-narrow-bounds))))
505 ;; position point in buf A
506 (save-excursion
507 (select-window ediff-window-A)
508 (goto-char shift-A))
509 ;; position point in buf B
510 (save-excursion
511 (select-window ediff-window-B)
512 (goto-char shift-B))
513 (if ediff-3way-job
514 (save-excursion
515 (select-window ediff-window-C)
516 (goto-char shift-C)))
517 )
71296446 518
475f9031
KH
519 (select-window ediff-control-window)
520 (ediff-visible-region)
71296446 521
651342bc 522 (run-hooks 'startup-hooks)
3af0304a 523 (ediff-arrange-autosave-in-merge-jobs merge-buffer-file)
328b4b70 524
475f9031 525 (ediff-refresh-mode-lines)
651342bc
MK
526 (setq buffer-read-only t)
527 (setq ediff-session-registry
528 (cons control-buffer ediff-session-registry))
529 (ediff-update-registry)
530 (if (ediff-buffer-live-p ediff-meta-buffer)
328b4b70
MK
531 (ediff-update-meta-buffer
532 ediff-meta-buffer nil ediff-meta-session-number))
651342bc
MK
533 (run-hooks 'ediff-startup-hook)
534 ) ; eval in control-buffer
41d25ad0 535 control-buffer))
71296446
JB
536
537
475f9031 538;; This function assumes that we are in the window where control buffer is
71296446 539;; to reside.
475f9031
KH
540(defun ediff-setup-control-buffer (ctl-buf)
541 "Set up window for control buffer."
542 (if (window-dedicated-p (selected-window))
543 (set-buffer ctl-buf) ; we are in control frame but just in case
544 (switch-to-buffer ctl-buf))
41d25ad0 545 (let ((window-min-height 2))
475f9031
KH
546 (erase-buffer)
547 (ediff-set-help-message)
548 (insert ediff-help-message)
549 (shrink-window-if-larger-than-buffer)
41d25ad0 550 (or (ediff-multiframe-setup-p)
475f9031 551 (ediff-indent-help-message))
92c51e07
MK
552 (ediff-set-help-overlays)
553
475f9031
KH
554 (set-buffer-modified-p nil)
555 (ediff-refresh-mode-lines)
556 (setq ediff-control-window (selected-window))
557 (setq ediff-window-config-saved
41d25ad0 558 (format "%S%S%S%S%S%S%S"
475f9031
KH
559 ediff-control-window
560 ediff-window-A
561 ediff-window-B
562 ediff-window-C
41d25ad0
KH
563 ediff-split-window-function
564 (ediff-multiframe-setup-p)
565 ediff-wide-display-p))
ddc90f39 566
2d84cc27 567 (set-window-dedicated-p (selected-window) t)
ddc90f39 568 ;; In multiframe, toolbar is set in ediff-setup-control-frame
bf5d92c5 569 (if (not (ediff-multiframe-setup-p))
ddc90f39 570 (ediff-make-bottom-toolbar)) ; this checks if toolbar is requested
475f9031
KH
571 (goto-char (point-min))
572 (skip-chars-forward ediff-whitespace)))
71296446 573
328b4b70
MK
574;; This executes in control buffer and sets auto-save, visited file name, etc,
575;; in the merge buffer
3af0304a 576(defun ediff-arrange-autosave-in-merge-jobs (merge-buffer-file)
328b4b70
MK
577 (if (not ediff-merge-job)
578 ()
579 (if (stringp merge-buffer-file)
580 (setq ediff-autostore-merges t
581 ediff-merge-store-file merge-buffer-file))
582 (if (stringp ediff-merge-store-file)
583 (progn
584 ;; save before leaving ctl buffer
50a07e18 585 (ediff-verify-file-merge-buffer ediff-merge-store-file)
71296446 586 (setq merge-buffer-file ediff-merge-store-file)
328b4b70
MK
587 (ediff-with-current-buffer ediff-buffer-C
588 (set-visited-file-name merge-buffer-file))))
589 (ediff-with-current-buffer ediff-buffer-C
590 (setq buffer-offer-save t) ; ask before killing buffer
591 ;; make sure the contents is auto-saved
592 (auto-save-mode 1))
593 ))
475f9031
KH
594
595\f
596;;; Commands for working with Ediff
71296446 597
475f9031
KH
598(defun ediff-update-diffs ()
599 "Recompute difference regions in buffers A, B, and C.
600Buffers are not synchronized with their respective files, so changes done
601to these buffers are not saved at this point---the user can do this later,
602if necessary."
603 (interactive)
651342bc
MK
604 (ediff-barf-if-not-control-buffer)
605 (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
e756eb9f
MK
606 (not
607 (y-or-n-p
3af0304a 608 "Ancestor buffer will not be used. Recompute diffs anyway? ")))
e756eb9f 609 (error "Recomputation of differences canceled"))
71296446 610
e756eb9f
MK
611 (let ((point-A (ediff-with-current-buffer ediff-buffer-A (point)))
612 ;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
475f9031 613 (tmp-buffer (get-buffer-create ediff-tmp-buffer))
e756eb9f
MK
614 (buf-A-file-name (buffer-file-name ediff-buffer-A))
615 (buf-B-file-name (buffer-file-name ediff-buffer-B))
616 ;; (null ediff-buffer-C) is no problem, as we later check if
617 ;; ediff-buffer-C is alive
618 (buf-C-file-name (buffer-file-name ediff-buffer-C))
475f9031
KH
619 (overl-A (ediff-get-value-according-to-buffer-type
620 'A ediff-narrow-bounds))
621 (overl-B (ediff-get-value-according-to-buffer-type
622 'B ediff-narrow-bounds))
623 (overl-C (ediff-get-value-according-to-buffer-type
624 'C ediff-narrow-bounds))
625 beg-A end-A beg-B end-B beg-C end-C
626 file-A file-B file-C)
e756eb9f
MK
627
628 (if (stringp buf-A-file-name)
629 (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
630 (if (stringp buf-B-file-name)
631 (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
632 (if (stringp buf-C-file-name)
633 (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
634
475f9031 635 (ediff-unselect-and-select-difference -1)
71296446 636
475f9031
KH
637 (setq beg-A (ediff-overlay-start overl-A)
638 beg-B (ediff-overlay-start overl-B)
639 beg-C (ediff-overlay-start overl-C)
640 end-A (ediff-overlay-end overl-A)
641 end-B (ediff-overlay-end overl-B)
642 end-C (ediff-overlay-end overl-C))
71296446 643
475f9031
KH
644 (if ediff-word-mode
645 (progn
646 (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
651342bc 647 (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
475f9031 648 (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
651342bc 649 (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
475f9031
KH
650 (if ediff-3way-job
651 (progn
652 (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
651342bc 653 (setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
475f9031
KH
654 )
655 ;; not word-mode
651342bc
MK
656 (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
657 (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
475f9031 658 (if ediff-3way-job
651342bc 659 (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
475f9031 660 )
71296446 661
475f9031
KH
662 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
663 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
664 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
651342bc
MK
665 (ediff-clear-diff-vector
666 'ediff-difference-vector-Ancestor 'fine-diffs-also)
3af0304a 667 ;; let them garbage collect. we can't use the ancestor after recomputing
651342bc
MK
668 ;; the diffs.
669 (setq ediff-difference-vector-Ancestor nil
670 ediff-ancestor-buffer nil
671 ediff-state-of-merge nil)
672
475f9031 673 (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
71296446 674
651342bc 675 ;; In case of merge job, fool it into thinking that it is just doing
475f9031
KH
676 ;; comparison
677 (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
651342bc
MK
678 (ediff-3way-comparison-job ediff-3way-comparison-job)
679 (ediff-merge-job ediff-merge-job)
680 (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
475f9031
KH
681 (ediff-job-name ediff-job-name))
682 (if ediff-merge-job
683 (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
651342bc
MK
684 ediff-3way-comparison-job t
685 ediff-merge-job nil
686 ediff-merge-with-ancestor-job nil
475f9031
KH
687 ediff-job-name 'ediff-files3))
688 (funcall ediff-setup-diff-regions-function file-A file-B file-C))
71296446 689
475f9031
KH
690 (setq ediff-number-of-differences (length ediff-difference-vector-A))
691 (delete-file file-A)
692 (delete-file file-B)
693 (if file-C
694 (delete-file file-C))
71296446 695
475f9031
KH
696 (if ediff-3way-job
697 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
71296446 698
475f9031
KH
699 (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
700 (message "")
701 ))
71296446 702
3af0304a 703;; Not bound to any key---to dangerous. A user can do it if necessary.
475f9031 704(defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
3af0304a 705 "Revert buffers A, B and C. Then rerun Ediff on file A and file B."
475f9031 706 (interactive "P")
651342bc 707 (ediff-barf-if-not-control-buffer)
475f9031
KH
708 (let ((bufA ediff-buffer-A)
709 (bufB ediff-buffer-B)
710 (bufC ediff-buffer-C)
711 (ctl-buf ediff-control-buffer)
651342bc 712 (keep-variants ediff-keep-variants)
475f9031
KH
713 (ancestor-buf ediff-ancestor-buffer)
714 (ancestor-job ediff-merge-with-ancestor-job)
715 (merge ediff-merge-job)
716 (comparison ediff-3way-comparison-job))
e756eb9f 717 (ediff-with-current-buffer bufA
475f9031 718 (revert-buffer t noconfirm))
e756eb9f 719 (ediff-with-current-buffer bufB
475f9031
KH
720 (revert-buffer t noconfirm))
721 ;; this should only be executed in a 3way comparison, not in merge
722 (if comparison
e756eb9f 723 (ediff-with-current-buffer bufC
475f9031
KH
724 (revert-buffer t noconfirm)))
725 (if merge
726 (progn
727 (set-buffer ctl-buf)
651342bc
MK
728 ;; the argument says whether to reverse the meaning of
729 ;; ediff-keep-variants, i.e., ediff-really-quit runs here with
730 ;; variants kept.
731 (ediff-really-quit (not keep-variants))
475f9031
KH
732 (kill-buffer bufC)
733 (if ancestor-job
734 (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
735 (ediff-merge-buffers bufA bufB)))
736 (ediff-update-diffs))))
737
738
71296446 739;; optional NO-REHIGHLIGHT says to not rehighlight buffers
475f9031
KH
740(defun ediff-recenter (&optional no-rehighlight)
741 "Bring the highlighted region of all buffers being compared into view.
742Reestablish the default three-window display."
743 (interactive)
651342bc 744 (ediff-barf-if-not-control-buffer)
475f9031
KH
745 (let (buffer-read-only)
746 (if (and (ediff-buffer-live-p ediff-buffer-A)
747 (ediff-buffer-live-p ediff-buffer-B)
748 (or (not ediff-3way-job)
41d25ad0 749 (ediff-buffer-live-p ediff-buffer-C)))
475f9031
KH
750 (ediff-setup-windows
751 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
752 (or (eq this-command 'ediff-quit)
4ae69eac
MK
753 (message ediff-KILLED-VITAL-BUFFER
754 (beep 1)))
475f9031 755 ))
71296446 756
475f9031
KH
757 ;; set visibility range appropriate to this invocation of Ediff.
758 (ediff-visible-region)
475f9031 759 ;; raise
41d25ad0 760 (if (and (ediff-window-display-p)
475f9031
KH
761 (symbolp this-command)
762 (symbolp last-command)
763 ;; Either one of the display-changing commands
764 (or (memq this-command
765 '(ediff-recenter
651342bc
MK
766 ediff-dir-action ediff-registry-action
767 ediff-patch-action
475f9031
KH
768 ediff-toggle-wide-display ediff-toggle-multiframe))
769 ;; Or one of the movement cmds and prev cmd was an Ediff cmd
a7acbbe4 770 ;; This avoids raising frames unnecessarily.
475f9031
KH
771 (and (memq this-command
772 '(ediff-next-difference
773 ediff-previous-difference
774 ediff-jump-to-difference
775 ediff-jump-to-difference-at-point))
776 (not (string-match "^ediff-" (symbol-name last-command)))
777 )))
778 (progn
779 (if (window-live-p ediff-window-A)
41d25ad0 780 (raise-frame (window-frame ediff-window-A)))
475f9031 781 (if (window-live-p ediff-window-B)
41d25ad0 782 (raise-frame (window-frame ediff-window-B)))
475f9031 783 (if (window-live-p ediff-window-C)
41d25ad0
KH
784 (raise-frame (window-frame ediff-window-C)))))
785 (if (and (ediff-window-display-p)
786 (frame-live-p ediff-control-frame)
4ae69eac 787 (not ediff-use-long-help-message)
475f9031 788 (not (ediff-frame-iconified-p ediff-control-frame)))
41d25ad0 789 (raise-frame ediff-control-frame))
71296446 790
475f9031 791 ;; Redisplay whatever buffers are showing, if there is a selected difference
651342bc
MK
792 (let ((control-frame ediff-control-frame)
793 (control-buf ediff-control-buffer))
475f9031
KH
794 (if (and (ediff-buffer-live-p ediff-buffer-A)
795 (ediff-buffer-live-p ediff-buffer-B)
796 (or (not ediff-3way-job)
bbe6126c 797 (ediff-buffer-live-p ediff-buffer-C)))
475f9031
KH
798 (progn
799 (or no-rehighlight
41d25ad0 800 (ediff-select-difference ediff-current-difference))
71296446 801
475f9031
KH
802 (ediff-recenter-one-window 'A)
803 (ediff-recenter-one-window 'B)
804 (if ediff-3way-job
805 (ediff-recenter-one-window 'C))
71296446 806
e756eb9f 807 (ediff-with-current-buffer control-buf
4ae69eac 808 (ediff-recenter-ancestor) ; check if ancestor is alive
71296446 809
651342bc 810 (if (and (ediff-multiframe-setup-p)
4ae69eac 811 (not ediff-use-long-help-message)
651342bc
MK
812 (not (ediff-frame-iconified-p ediff-control-frame)))
813 ;; never grab mouse on quit in this place
814 (ediff-reset-mouse
815 control-frame
816 (eq this-command 'ediff-quit))))
475f9031 817 ))
92c51e07 818
81ef8960
MK
819 (or no-rehighlight
820 (ediff-restore-highlighting))
e756eb9f 821 (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines))
475f9031 822 ))
71296446 823
475f9031
KH
824;; this function returns to the window it was called from
825;; (which was the control window)
826(defun ediff-recenter-one-window (buf-type)
651342bc
MK
827 (if (ediff-valid-difference-p)
828 ;; context must be saved before switching to windows A/B/C
829 (let* ((ctl-wind (selected-window))
830 (shift (ediff-overlay-start
71296446 831 (ediff-get-value-according-to-buffer-type
651342bc
MK
832 buf-type ediff-narrow-bounds)))
833 (job-name ediff-job-name)
834 (control-buf ediff-control-buffer)
e756eb9f
MK
835 (window-name (ediff-get-symbol-from-alist
836 buf-type ediff-window-alist))
651342bc
MK
837 (window (if (window-live-p (symbol-value window-name))
838 (symbol-value window-name))))
71296446 839
651342bc
MK
840 (if (and window ediff-windows-job)
841 (set-window-start window shift))
842 (if window
843 (progn
844 (select-window window)
845 (ediff-deactivate-mark)
846 (ediff-position-region
847 (ediff-get-diff-posn buf-type 'beg nil control-buf)
848 (ediff-get-diff-posn buf-type 'end nil control-buf)
849 (ediff-get-diff-posn buf-type 'beg nil control-buf)
850 job-name
851 )))
852 (select-window ctl-wind)
853 )))
854
855(defun ediff-recenter-ancestor ()
856 ;; do half-hearted job by recentering the ancestor buffer, if it is alive and
857 ;; visible.
858 (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
859 (ediff-valid-difference-p))
860 (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer))
861 (ctl-wind (selected-window))
862 (job-name ediff-job-name)
863 (ctl-buf ediff-control-buffer))
e756eb9f 864 (ediff-with-current-buffer ediff-ancestor-buffer
651342bc
MK
865 (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf))
866 (if window
867 (progn
868 (select-window window)
869 (ediff-position-region
870 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
871 (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf)
872 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
873 job-name))))
874 (select-window ctl-wind)
875 )))
475f9031 876
71296446 877
475f9031
KH
878;; This will have to be refined for 3way jobs
879(defun ediff-toggle-split ()
71296446 880 "Toggle vertical/horizontal window split.
475f9031
KH
881Does nothing if file-A and file-B are in different frames."
882 (interactive)
651342bc 883 (ediff-barf-if-not-control-buffer)
475f9031
KH
884 (let* ((wind-A (if (window-live-p ediff-window-A) ediff-window-A))
885 (wind-B (if (window-live-p ediff-window-B) ediff-window-B))
886 (wind-C (if (window-live-p ediff-window-C) ediff-window-C))
41d25ad0
KH
887 (frame-A (if wind-A (window-frame wind-A)))
888 (frame-B (if wind-B (window-frame wind-B)))
889 (frame-C (if wind-C (window-frame wind-C))))
475f9031 890 (if (or (eq frame-A frame-B)
41d25ad0
KH
891 (not (frame-live-p frame-A))
892 (not (frame-live-p frame-B))
475f9031 893 (if ediff-3way-comparison-job
41d25ad0 894 (or (not (frame-live-p frame-C))
475f9031
KH
895 (eq frame-A frame-C) (eq frame-B frame-C))))
896 (setq ediff-split-window-function
897 (if (eq ediff-split-window-function 'split-window-vertically)
898 'split-window-horizontally
899 'split-window-vertically))
900 (message "Buffers being compared are in different frames"))
901 (ediff-recenter 'no-rehighlight)))
71296446 902
475f9031
KH
903(defun ediff-toggle-hilit ()
904 "Switch between highlighting using ASCII flags and highlighting using faces.
71296446 905On a dumb terminal, switches between ASCII highlighting and no highlighting."
475f9031 906 (interactive)
651342bc 907 (ediff-barf-if-not-control-buffer)
743a79af
MK
908
909 (ediff-unselect-and-select-difference
910 ediff-current-difference 'unselect-only)
911 ;; cycle through highlighting
912 (cond ((and ediff-use-faces
913 (ediff-has-face-support-p)
914 ediff-highlight-all-diffs)
915 (message "Unhighlighting unselected difference regions")
916 (setq ediff-highlight-all-diffs nil
917 ediff-highlighting-style 'face))
918 ((or (and ediff-use-faces (ediff-has-face-support-p)
919 (eq ediff-highlighting-style 'face)) ; has face support
920 (and (not (ediff-has-face-support-p)) ; no face support
921 (eq ediff-highlighting-style 'off)))
922 (message "Highlighting with ASCII flags")
923 (setq ediff-highlighting-style 'ascii
924 ediff-highlight-all-diffs nil
925 ediff-use-faces nil))
926 ((eq ediff-highlighting-style 'ascii)
927 (message "ASCII highlighting flags removed")
928 (setq ediff-highlighting-style 'off
929 ediff-highlight-all-diffs nil))
930 ((ediff-has-face-support-p) ; catch-all for cases with face support
931 (message "Re-highlighting all difference regions")
932 (setq ediff-use-faces t
933 ediff-highlighting-style 'face
934 ediff-highlight-all-diffs t)))
71296446 935
743a79af
MK
936 (if (and ediff-use-faces ediff-highlight-all-diffs)
937 (ediff-paint-background-regions)
938 (ediff-paint-background-regions 'unhighlight))
71296446 939
743a79af
MK
940 (ediff-unselect-and-select-difference
941 ediff-current-difference 'select-only))
92c51e07 942
71296446 943
475f9031
KH
944(defun ediff-toggle-autorefine ()
945 "Toggle auto-refine mode."
946 (interactive)
651342bc 947 (ediff-barf-if-not-control-buffer)
475f9031
KH
948 (if ediff-word-mode
949 (error "No fine differences in this mode"))
950 (cond ((eq ediff-auto-refine 'nix)
951 (setq ediff-auto-refine 'on)
952 (ediff-make-fine-diffs ediff-current-difference 'noforce)
953 (message "Auto-refining is ON"))
954 ((eq ediff-auto-refine 'on)
955 (message "Auto-refining is OFF")
956 (setq ediff-auto-refine 'off))
957 (t ;; nix 'em
958 (ediff-set-fine-diff-properties ediff-current-difference 'default)
959 (message "Refinements are HIDDEN")
960 (setq ediff-auto-refine 'nix))
961 ))
651342bc
MK
962
963(defun ediff-show-ancestor ()
964 "Show the ancestor buffer in a suitable window."
965 (interactive)
966 (ediff-recenter)
967 (or (ediff-buffer-live-p ediff-ancestor-buffer)
968 (if ediff-merge-with-ancestor-job
969 (error "Lost connection to ancestor buffer...sorry")
970 (error "Not merging with ancestor")))
971 (let (wind)
972 (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
973 (raise-frame (window-frame wind)))
974 (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
71296446 975
475f9031 976(defun ediff-make-or-kill-fine-diffs (arg)
3af0304a 977 "Compute fine diffs. With negative prefix arg, kill fine diffs.
71296446 978In both cases, operates on the current difference region."
475f9031 979 (interactive "P")
651342bc 980 (ediff-barf-if-not-control-buffer)
475f9031
KH
981 (cond ((eq arg '-)
982 (ediff-clear-fine-differences ediff-current-difference))
983 ((and (numberp arg) (< arg 0))
984 (ediff-clear-fine-differences ediff-current-difference))
985 (t (ediff-make-fine-diffs))))
71296446
JB
986
987
475f9031
KH
988(defun ediff-toggle-help ()
989 "Toggle short/long help message."
990 (interactive)
651342bc 991 (ediff-barf-if-not-control-buffer)
475f9031
KH
992 (let (buffer-read-only)
993 (erase-buffer)
4ae69eac 994 (setq ediff-use-long-help-message (not ediff-use-long-help-message))
475f9031
KH
995 (ediff-set-help-message))
996 ;; remember the icon status of the control frame when the user requested
997 ;; full control message
4ae69eac 998 (if (and ediff-use-long-help-message (ediff-multiframe-setup-p))
475f9031
KH
999 (setq ediff-prefer-iconified-control-frame
1000 (ediff-frame-iconified-p ediff-control-frame)))
71296446 1001
475f9031
KH
1002 (setq ediff-window-config-saved "") ; force redisplay
1003 (ediff-recenter 'no-rehighlight))
71296446
JB
1004
1005
41d25ad0
KH
1006;; If BUF, this is the buffer to toggle, not current buffer.
1007(defun ediff-toggle-read-only (&optional buf)
1008 "Toggle read-only in current buffer.
1009If buffer is under version control and locked, check it out first.
1010If optional argument BUF is specified, toggle read-only in that buffer instead
1011of the current buffer."
475f9031 1012 (interactive)
651342bc 1013 (ediff-barf-if-not-control-buffer)
4ae69eac 1014 (let ((ctl-buf (if (null buf) (current-buffer)))
433d9ace 1015 (buf-type (ediff-char-to-buftype (ediff-last-command-char))))
41d25ad0
KH
1016 (or buf (ediff-recenter))
1017 (or buf
4ae69eac 1018 (setq buf (ediff-get-buffer buf-type)))
71296446 1019
e756eb9f 1020 (ediff-with-current-buffer buf ; eval in buf A/B/C
41d25ad0
KH
1021 (let* ((file (buffer-file-name buf))
1022 (file-writable (and file
1023 (file-exists-p file)
1024 (file-writable-p file)))
1025 (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
1026 ((ediff-file-checked-out-p file)
1027 'toggle-read-only)
1028 (file-writable 'toggle-read-only)
1029 (t (key-binding "\C-x\C-q")))))
1030 ;; If the file is checked in, make sure we don't make buffer modifiable
3af0304a
MK
1031 ;; without warning the user. The user can fool our checks by making the
1032 ;; buffer non-RO without checking the file out. We regard this as a
41d25ad0
KH
1033 ;; user problem.
1034 (if (and (ediff-file-checked-in-p file)
1035 ;; If ctl-buf is null, this means we called this
1036 ;; non-interactively, in which case don't ask questions
1037 ctl-buf)
1038 (cond ((not buffer-read-only)
1039 (setq toggle-ro-cmd 'toggle-read-only))
1040 ((and (or (beep 1) t) ; always beep
1041 (y-or-n-p
1042 (format
3af0304a 1043 "File %s is under version control. Check it out? "
651342bc 1044 (ediff-abbreviate-file-name file))))
41d25ad0
KH
1045 ;; if we checked the file out, we should also change the
1046 ;; original state of buffer-read-only to nil. If we don't
1047 ;; do this, the mode line will show %%, since the file was
1048 ;; RO before ediff started, so the user will think the file
1049 ;; is checked in.
e756eb9f 1050 (ediff-with-current-buffer ctl-buf
41d25ad0 1051 (ediff-change-saved-variable
4ae69eac 1052 'buffer-read-only nil buf-type)))
41d25ad0
KH
1053 (t
1054 (setq toggle-ro-cmd 'toggle-read-only)
1055 (beep 1) (beep 1)
1056 (message
bf5d92c5 1057 "Boy, this is risky! Don't modify this file...")
651342bc 1058 (sit-for 3)))) ; let the user see the warning
71296446 1059 (if (and toggle-ro-cmd
41d25ad0
KH
1060 (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
1061 (save-excursion
1062 (save-window-excursion
bf5d92c5 1063 (select-window (ediff-get-visible-buffer-window buf))
41d25ad0
KH
1064 (command-execute toggle-ro-cmd)))
1065 (error "Don't know how to toggle read-only in buffer %S" buf))
71296446 1066
41d25ad0
KH
1067 ;; Check if we made the current buffer updatable, but its file is RO.
1068 ;; Signal a warning in this case.
1069 (if (and file (not buffer-read-only)
1070 (eq this-command 'ediff-toggle-read-only)
1071 (file-exists-p file)
1072 (not (file-writable-p file)))
e314af72
AS
1073 (progn
1074 (beep 1)
1075 (message "Warning: file %s is read-only"
1076 (ediff-abbreviate-file-name file))))
41d25ad0 1077 ))))
41d25ad0 1078
bf5d92c5
MK
1079;; checkout if visited file is checked in
1080(defun ediff-maybe-checkout (buf)
2eb4bdca 1081 (let ((file (expand-file-name (buffer-file-name buf)))
bf5d92c5
MK
1082 (checkout-function (key-binding "\C-x\C-q")))
1083 (if (and (ediff-file-checked-in-p file)
1084 (or (beep 1) t)
1085 (y-or-n-p
1086 (format
3af0304a 1087 "File %s is under version control. Check it out? "
bf5d92c5 1088 (ediff-abbreviate-file-name file))))
e756eb9f 1089 (ediff-with-current-buffer buf
bf5d92c5 1090 (command-execute checkout-function)))))
71296446 1091
bf5d92c5
MK
1092
1093;; This is a simple-minded check for whether a file is under version control.
41d25ad0
KH
1094;; If file,v exists but file doesn't, this file is considered to be not checked
1095;; in and not checked out for the purpose of patching (since patch won't be
1096;; able to read such a file anyway).
1097;; FILE is a string representing file name
2eb4bdca
MK
1098;;(defun ediff-file-under-version-control (file)
1099;; (let* ((filedir (file-name-directory file))
1100;; (file-nondir (file-name-nondirectory file))
1101;; (trial (concat file-nondir ",v"))
1102;; (full-trial (concat filedir trial))
1103;; (full-rcs-trial (concat filedir "RCS/" trial)))
1104;; (and (stringp file)
1105;; (file-exists-p file)
1106;; (or
1107;; (and
1108;; (file-exists-p full-trial)
1109;; ;; in FAT FS, `file,v' and `file' may turn out to be the same!
1110;; ;; don't be fooled by this!
1111;; (not (equal (file-attributes file)
1112;; (file-attributes full-trial))))
1113;; ;; check if a version is in RCS/ directory
1114;; (file-exists-p full-rcs-trial)))
1115;; ))
1116
1117
b6178721 1118(defun ediff-file-checked-out-p (file)
2eb4bdca
MK
1119 (or (not (featurep 'vc-hooks))
1120 (and (vc-backend file)
4960e757
MK
1121 (if (fboundp 'vc-state)
1122 (or (memq (vc-state file) '(edited needs-merge))
1123 (stringp (vc-state file)))
1124 ;; XEmacs has no vc-state
8ac56013 1125 (when (featurep 'xemacs) (vc-locking-user file)))
4960e757 1126 )))
71296446 1127
b6178721 1128(defun ediff-file-checked-in-p (file)
2eb4bdca 1129 (and (featurep 'vc-hooks)
a0c6a0fb
JL
1130 ;; Only RCS and SCCS files are considered checked in
1131 (memq (vc-backend file) '(RCS SCCS))
4960e757 1132 (if (fboundp 'vc-state)
2e955a8b
MK
1133 (and
1134 (not (memq (vc-state file) '(edited needs-merge)))
1135 (not (stringp (vc-state file))))
4960e757 1136 ;; XEmacs has no vc-state
8ac56013 1137 (when (featurep 'xemacs) (not (vc-locking-user file))))
4960e757 1138 ))
2eb4bdca
MK
1139
1140(defun ediff-file-compressed-p (file)
1141 (condition-case nil
1142 (require 'jka-compr)
1143 (error))
1144 (if (featurep 'jka-compr)
1145 (string-match (jka-compr-build-file-regexp) file)))
1146
71296446 1147
475f9031
KH
1148(defun ediff-swap-buffers ()
1149 "Rotate the display of buffers A, B, and C."
1150 (interactive)
651342bc 1151 (ediff-barf-if-not-control-buffer)
475f9031
KH
1152 (if (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
1153 (let ((buf ediff-buffer-A)
41d25ad0 1154 (values ediff-buffer-values-orig-A)
475f9031
KH
1155 (diff-vec ediff-difference-vector-A)
1156 (hide-regexp ediff-regexp-hide-A)
1157 (focus-regexp ediff-regexp-focus-A)
1158 (wide-visibility-p (eq ediff-visible-bounds ediff-wide-bounds))
4ae69eac 1159 (overlay (if (ediff-has-face-support-p)
41d25ad0 1160 ediff-current-diff-overlay-A)))
475f9031
KH
1161 (if ediff-3way-comparison-job
1162 (progn
1163 (set-window-buffer ediff-window-A ediff-buffer-C)
1164 (set-window-buffer ediff-window-B ediff-buffer-A)
1165 (set-window-buffer ediff-window-C ediff-buffer-B)
1166 )
1167 (set-window-buffer ediff-window-A ediff-buffer-B)
1168 (set-window-buffer ediff-window-B ediff-buffer-A))
1169 ;; swap diff buffers
1170 (if ediff-3way-comparison-job
1171 (setq ediff-buffer-A ediff-buffer-C
1172 ediff-buffer-C ediff-buffer-B
1173 ediff-buffer-B buf)
1174 (setq ediff-buffer-A ediff-buffer-B
1175 ediff-buffer-B buf))
71296446 1176
475f9031
KH
1177 ;; swap saved buffer characteristics
1178 (if ediff-3way-comparison-job
41d25ad0
KH
1179 (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-C
1180 ediff-buffer-values-orig-C ediff-buffer-values-orig-B
1181 ediff-buffer-values-orig-B values)
1182 (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-B
1183 ediff-buffer-values-orig-B values))
71296446 1184
475f9031
KH
1185 ;; swap diff vectors
1186 (if ediff-3way-comparison-job
1187 (setq ediff-difference-vector-A ediff-difference-vector-C
1188 ediff-difference-vector-C ediff-difference-vector-B
1189 ediff-difference-vector-B diff-vec)
1190 (setq ediff-difference-vector-A ediff-difference-vector-B
1191 ediff-difference-vector-B diff-vec))
71296446 1192
475f9031
KH
1193 ;; swap hide/focus regexp
1194 (if ediff-3way-comparison-job
1195 (setq ediff-regexp-hide-A ediff-regexp-hide-C
1196 ediff-regexp-hide-C ediff-regexp-hide-B
1197 ediff-regexp-hide-B hide-regexp
1198 ediff-regexp-focus-A ediff-regexp-focus-C
1199 ediff-regexp-focus-C ediff-regexp-focus-B
1200 ediff-regexp-focus-B focus-regexp)
1201 (setq ediff-regexp-hide-A ediff-regexp-hide-B
1202 ediff-regexp-hide-B hide-regexp
1203 ediff-regexp-focus-A ediff-regexp-focus-B
1204 ediff-regexp-focus-B focus-regexp))
71296446 1205
475f9031 1206 ;; The following is needed for XEmacs, since there one can't move
3af0304a 1207 ;; overlay to another buffer. In Emacs, this swap is redundant.
4ae69eac 1208 (if (ediff-has-face-support-p)
475f9031
KH
1209 (if ediff-3way-comparison-job
1210 (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-C
1211 ediff-current-diff-overlay-C ediff-current-diff-overlay-B
1212 ediff-current-diff-overlay-B overlay)
1213 (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-B
1214 ediff-current-diff-overlay-B overlay)))
71296446 1215
475f9031
KH
1216 ;; swap wide bounds
1217 (setq ediff-wide-bounds
1218 (cond (ediff-3way-comparison-job
1219 (list (nth 2 ediff-wide-bounds)
1220 (nth 0 ediff-wide-bounds)
1221 (nth 1 ediff-wide-bounds)))
1222 (ediff-3way-job
1223 (list (nth 1 ediff-wide-bounds)
1224 (nth 0 ediff-wide-bounds)
1225 (nth 2 ediff-wide-bounds)))
71296446 1226 (t
475f9031
KH
1227 (list (nth 1 ediff-wide-bounds)
1228 (nth 0 ediff-wide-bounds)))))
1229 ;; swap narrow bounds
1230 (setq ediff-narrow-bounds
1231 (cond (ediff-3way-comparison-job
1232 (list (nth 2 ediff-narrow-bounds)
1233 (nth 0 ediff-narrow-bounds)
1234 (nth 1 ediff-narrow-bounds)))
1235 (ediff-3way-job
1236 (list (nth 1 ediff-narrow-bounds)
1237 (nth 0 ediff-narrow-bounds)
1238 (nth 2 ediff-narrow-bounds)))
71296446 1239 (t
475f9031
KH
1240 (list (nth 1 ediff-narrow-bounds)
1241 (nth 0 ediff-narrow-bounds)))))
1242 (if wide-visibility-p
1243 (setq ediff-visible-bounds ediff-wide-bounds)
1244 (setq ediff-visible-bounds ediff-narrow-bounds))
1245 ))
1246 (if ediff-3way-job
1247 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
1248 (ediff-recenter 'no-rehighlight)
1249 )
71296446 1250
475f9031
KH
1251
1252(defun ediff-toggle-wide-display ()
1253 "Toggle wide/regular display.
1254This is especially useful when comparing buffers side-by-side."
1255 (interactive)
651342bc 1256 (ediff-barf-if-not-control-buffer)
41d25ad0
KH
1257 (or (ediff-window-display-p)
1258 (error "%sEmacs is not running as a window application"
e83d1fe8 1259 (if (featurep 'emacs) "" "X")))
475f9031
KH
1260 (ediff-recenter 'no-rehighlight) ; make sure buffs are displayed in windows
1261 (let ((ctl-buf ediff-control-buffer))
1262 (setq ediff-wide-display-p (not ediff-wide-display-p))
1263 (if (not ediff-wide-display-p)
e756eb9f 1264 (ediff-with-current-buffer ctl-buf
41d25ad0 1265 (modify-frame-parameters
475f9031 1266 ediff-wide-display-frame ediff-wide-display-orig-parameters)
e83d1fe8 1267 ;;(sit-for (if (featurep 'xemacs) 0.4 0))
475f9031
KH
1268 ;; restore control buf, since ctl window may have been deleted
1269 ;; during resizing
1270 (set-buffer ctl-buf)
1271 (setq ediff-wide-display-orig-parameters nil
1272 ediff-window-B nil) ; force update of window config
1273 (ediff-recenter 'no-rehighlight))
1274 (funcall ediff-make-wide-display-function)
e83d1fe8 1275 ;;(sit-for (if (featurep 'xemacs) 0.4 0))
e756eb9f 1276 (ediff-with-current-buffer ctl-buf
475f9031
KH
1277 (setq ediff-window-B nil) ; force update of window config
1278 (ediff-recenter 'no-rehighlight)))))
71296446 1279
bf5d92c5 1280;;;###autoload
475f9031 1281(defun ediff-toggle-multiframe ()
ddc90f39
MK
1282 "Switch from multiframe display to single-frame display and back.
1283To change the default, set the variable `ediff-window-setup-function',
bbe6126c 1284which see."
475f9031 1285 (interactive)
ddc90f39
MK
1286 (let (window-setup-func)
1287 (or (ediff-window-display-p)
1288 (error "%sEmacs is not running as a window application"
e83d1fe8 1289 (if (featurep 'emacs) "" "X")))
bf5d92c5 1290
475f9031 1291 (cond ((eq ediff-window-setup-function 'ediff-setup-windows-multiframe)
2d84cc27 1292 (setq ediff-multiframe nil)
ddc90f39 1293 (setq window-setup-func 'ediff-setup-windows-plain))
475f9031 1294 ((eq ediff-window-setup-function 'ediff-setup-windows-plain)
bf5d92c5
MK
1295 (if (ediff-in-control-buffer-p)
1296 (ediff-kill-bottom-toolbar))
42acc581
MK
1297 (if (and (ediff-buffer-live-p ediff-control-buffer)
1298 (window-live-p ediff-control-window))
2d84cc27
MK
1299 (set-window-dedicated-p ediff-control-window nil))
1300 (setq ediff-multiframe t)
1301 (setq window-setup-func 'ediff-setup-windows-multiframe))
1302 (t
42acc581
MK
1303 (if (and (ediff-buffer-live-p ediff-control-buffer)
1304 (window-live-p ediff-control-window))
2d84cc27
MK
1305 (set-window-dedicated-p ediff-control-window nil))
1306 (setq ediff-multiframe t)
1307 (setq window-setup-func 'ediff-setup-windows-multiframe))
1308 )
ddc90f39
MK
1309
1310 ;; change default
1311 (setq-default ediff-window-setup-function window-setup-func)
1312 ;; change in all active ediff sessions
56eaedfe
JB
1313 (mapc (lambda(buf) (ediff-with-current-buffer buf
1314 (setq ediff-window-setup-function window-setup-func
1315 ediff-window-B nil)))
1316 ediff-session-registry)
bf5d92c5 1317 (if (ediff-in-control-buffer-p)
42acc581
MK
1318 (progn
1319 (set-window-dedicated-p (selected-window) nil)
1320 (ediff-recenter 'no-rehighlight)))))
ddc90f39
MK
1321
1322
1323;;;###autoload
1324(defun ediff-toggle-use-toolbar ()
1325 "Enable or disable Ediff toolbar.
1326Works only in versions of Emacs that support toolbars.
1327To change the default, set the variable `ediff-use-toolbar-p', which see."
1328 (interactive)
1329 (if (featurep 'ediff-tbar)
bf5d92c5 1330 (progn
ddc90f39
MK
1331 (or (ediff-window-display-p)
1332 (error "%sEmacs is not running as a window application"
e83d1fe8 1333 (if (featurep 'emacs) "" "X")))
ddc90f39
MK
1334 (if (ediff-use-toolbar-p)
1335 (ediff-kill-bottom-toolbar))
1336 ;; do this only after killing the toolbar
1337 (setq ediff-use-toolbar-p (not ediff-use-toolbar-p))
71296446 1338
56eaedfe
JB
1339 (mapc (lambda(buf)
1340 (ediff-with-current-buffer buf
1341 ;; force redisplay
1342 (setq ediff-window-config-saved "")
1343 ))
1344 ediff-session-registry)
ddc90f39
MK
1345 (if (ediff-in-control-buffer-p)
1346 (ediff-recenter 'no-rehighlight)))))
1347
bf5d92c5
MK
1348
1349;; if was using toolbar, kill it
1350(defun ediff-kill-bottom-toolbar ()
1351 ;; Using ctl-buffer or ediff-control-window for LOCALE does not
1352 ;; work properly in XEmacs 19.14: we have to use
1353 ;;(selected-frame).
1354 ;; The problem with this is that any previous bottom-toolbar
1355 ;; will not re-appear after our cleanup here. Is there a way
71296446 1356 ;; to do "push" and "pop" toolbars ? --marcpa
d2049452
GM
1357 (if (featurep 'xemacs)
1358 (when (ediff-use-toolbar-p)
1359 (set-specifier bottom-toolbar (list (selected-frame) nil))
1360 (set-specifier bottom-toolbar-visible-p (list (selected-frame) nil)))))
bf5d92c5 1361
ddc90f39
MK
1362;; If wants to use toolbar, make it.
1363;; If not, zero the toolbar for XEmacs.
1364;; Do nothing for Emacs.
1365(defun ediff-make-bottom-toolbar (&optional frame)
d2049452
GM
1366 (when (ediff-window-display-p)
1367 (setq frame (or frame (selected-frame)))
1368 (if (featurep 'xemacs)
ddc90f39 1369 (cond ((ediff-use-toolbar-p) ; this checks for XEmacs
d2049452
GM
1370 (set-specifier
1371 bottom-toolbar
1372 (list frame (if (ediff-3way-comparison-job)
1373 ediff-toolbar-3way ediff-toolbar)))
1374 (set-specifier bottom-toolbar-visible-p (list frame t))
1375 (set-specifier bottom-toolbar-height
1376 (list frame ediff-toolbar-height)))
2eb4bdca 1377 ((ediff-has-toolbar-support-p)
d2049452 1378 (set-specifier bottom-toolbar-height (list frame 0)))))))
71296446 1379
475f9031
KH
1380;; Merging
1381
1382(defun ediff-toggle-show-clashes-only ()
3af0304a 1383 "Toggle the mode that shows only the merge regions where both variants differ from the ancestor."
475f9031 1384 (interactive)
651342bc 1385 (ediff-barf-if-not-control-buffer)
475f9031
KH
1386 (if (not ediff-merge-with-ancestor-job)
1387 (error "This command makes sense only when merging with an ancestor"))
1388 (setq ediff-show-clashes-only (not ediff-show-clashes-only))
1389 (if ediff-show-clashes-only
1390 (message "Focus on regions where both buffers differ from the ancestor")
1391 (message "Canceling focus on regions where changes clash")))
3af0304a
MK
1392
1393(defun ediff-toggle-skip-changed-regions ()
1394 "Toggle the mode that skips the merge regions that differ from the default."
1395 (interactive)
1396 (ediff-barf-if-not-control-buffer)
1397 (setq ediff-skip-merge-regions-that-differ-from-default
1398 (not ediff-skip-merge-regions-that-differ-from-default))
1399 (if ediff-skip-merge-regions-that-differ-from-default
1400 (message "Skipping regions that differ from default setting")
1401 (message "Showing regions that differ from default setting")))
1402
1403
71296446 1404
475f9031
KH
1405;; Widening/narrowing
1406
1407(defun ediff-toggle-narrow-region ()
1408 "Toggle narrowing in buffers A, B, and C.
1409Used in ediff-windows/regions only."
1410 (interactive)
1411 (if (eq ediff-buffer-A ediff-buffer-B)
4ae69eac 1412 (error ediff-NO-DIFFERENCES))
475f9031
KH
1413 (if (eq ediff-visible-bounds ediff-wide-bounds)
1414 (setq ediff-visible-bounds ediff-narrow-bounds)
1415 (setq ediff-visible-bounds ediff-wide-bounds))
1416 (ediff-recenter 'no-rehighlight))
71296446 1417
3af0304a 1418;; Narrow bufs A/B/C to ediff-visible-bounds. If this is currently set to
475f9031 1419;; ediff-wide-bounds, then this actually widens.
41d25ad0 1420;; This function does nothing if job-name is not
71296446 1421;; ediff-regions-wordwise/linewise or ediff-windows-wordwise/linewise.
475f9031
KH
1422;; Does nothing if buffer-A = buffer-B since we can't narrow
1423;; to two different regions in one buffer.
1424(defun ediff-visible-region ()
1425 (if (or (eq ediff-buffer-A ediff-buffer-B)
1426 (eq ediff-buffer-A ediff-buffer-C)
1427 (eq ediff-buffer-C ediff-buffer-B))
1428 ()
1429 ;; If ediff-*-regions/windows, ediff-visible-bounds is already set
1430 ;; Otherwise, always use full range.
41d25ad0 1431 (if (not ediff-narrow-job)
475f9031
KH
1432 (setq ediff-visible-bounds ediff-wide-bounds))
1433 (let ((overl-A (ediff-get-value-according-to-buffer-type
1434 'A ediff-visible-bounds))
1435 (overl-B (ediff-get-value-according-to-buffer-type
1436 'B ediff-visible-bounds))
1437 (overl-C (ediff-get-value-according-to-buffer-type
1438 'C ediff-visible-bounds))
1439 )
e756eb9f 1440 (ediff-with-current-buffer ediff-buffer-A
328b4b70
MK
1441 (if (ediff-overlay-buffer overl-A)
1442 (narrow-to-region
1443 (ediff-overlay-start overl-A) (ediff-overlay-end overl-A))))
e756eb9f 1444 (ediff-with-current-buffer ediff-buffer-B
328b4b70
MK
1445 (if (ediff-overlay-buffer overl-B)
1446 (narrow-to-region
1447 (ediff-overlay-start overl-B) (ediff-overlay-end overl-B))))
71296446 1448
328b4b70 1449 (if (and ediff-3way-job (ediff-overlay-buffer overl-C))
e756eb9f 1450 (ediff-with-current-buffer ediff-buffer-C
475f9031
KH
1451 (narrow-to-region
1452 (ediff-overlay-start overl-C) (ediff-overlay-end overl-C))))
1453 )))
71296446 1454
475f9031
KH
1455
1456;; Window scrolling operations
1457
1458;; Performs some operation on the two file windows (if they are showing).
1459;; Traps all errors on the operation in windows A/B/C.
1460;; Usually, errors come from scrolling off the
1461;; beginning or end of the buffer, and this gives error messages.
1462(defun ediff-operate-on-windows (operation arg)
71296446 1463
475f9031
KH
1464 ;; make sure windows aren't dead
1465 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1466 (ediff-recenter 'no-rehighlight))
1467 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1468 (ediff-buffer-live-p ediff-buffer-B)
1469 (or (not ediff-3way-job) ediff-buffer-C)
1470 ))
4ae69eac 1471 (error ediff-KILLED-VITAL-BUFFER))
71296446 1472
475f9031
KH
1473 (let* ((wind (selected-window))
1474 (wind-A ediff-window-A)
1475 (wind-B ediff-window-B)
1476 (wind-C ediff-window-C)
651342bc
MK
1477 (coefA (ediff-get-region-size-coefficient 'A operation))
1478 (coefB (ediff-get-region-size-coefficient 'B operation))
1479 (three-way ediff-3way-job)
1480 (coefC (if three-way
1481 (ediff-get-region-size-coefficient 'C operation))))
71296446 1482
475f9031
KH
1483 (select-window wind-A)
1484 (condition-case nil
651342bc 1485 (funcall operation (round (* coefA arg)))
475f9031
KH
1486 (error))
1487 (select-window wind-B)
1488 (condition-case nil
651342bc 1489 (funcall operation (round (* coefB arg)))
475f9031
KH
1490 (error))
1491 (if three-way
1492 (progn
1493 (select-window wind-C)
1494 (condition-case nil
651342bc 1495 (funcall operation (round (* coefC arg)))
475f9031 1496 (error))))
475f9031
KH
1497 (select-window wind)))
1498
1499(defun ediff-scroll-vertically (&optional arg)
1500 "Vertically scroll buffers A, B \(and C if appropriate\).
1501With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
4ae69eac 1502the one half of the height of window-A."
475f9031 1503 (interactive "P")
651342bc 1504 (ediff-barf-if-not-control-buffer)
71296446 1505
475f9031
KH
1506 ;; make sure windows aren't dead
1507 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1508 (ediff-recenter 'no-rehighlight))
1509 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1510 (ediff-buffer-live-p ediff-buffer-B)
1511 (or (not ediff-3way-job)
1512 (ediff-buffer-live-p ediff-buffer-C))
1513 ))
4ae69eac 1514 (error ediff-KILLED-VITAL-BUFFER))
71296446 1515
475f9031 1516 (ediff-operate-on-windows
433d9ace 1517 (if (memq (ediff-last-command-char) '(?v ?\C-v))
71296446 1518 'scroll-up
475f9031
KH
1519 'scroll-down)
1520 ;; calculate argument to scroll-up/down
1521 ;; if there is an explicit argument
1522 (if (and arg (not (equal arg '-)))
1523 ;; use it
1524 (prefix-numeric-value arg)
1525 ;; if not, see if we can determine a default amount (the window height)
651342bc 1526 (let (default-amount)
71296446 1527 (setq default-amount
651342bc
MK
1528 (- (/ (min (window-height ediff-window-A)
1529 (window-height ediff-window-B)
1530 (if ediff-3way-job
1531 (window-height ediff-window-C)
1532 500)) ; some large number
1533 2)
475f9031
KH
1534 1 next-screen-context-lines))
1535 ;; window found
1536 (if arg
1537 ;; C-u as argument means half of default amount
1538 (/ default-amount 2)
1539 ;; no argument means default amount
1540 default-amount)))))
1541
1542
1543(defun ediff-scroll-horizontally (&optional arg)
1544 "Horizontally scroll buffers A, B \(and C if appropriate\).
1545If an argument is given, that is how many columns are scrolled, else nearly
1546the width of the A/B/C windows."
1547 (interactive "P")
651342bc 1548 (ediff-barf-if-not-control-buffer)
71296446 1549
475f9031
KH
1550 ;; make sure windows aren't dead
1551 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1552 (ediff-recenter 'no-rehighlight))
1553 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1554 (ediff-buffer-live-p ediff-buffer-B)
1555 (or (not ediff-3way-job)
1556 (ediff-buffer-live-p ediff-buffer-C))
1557 ))
4ae69eac 1558 (error ediff-KILLED-VITAL-BUFFER))
71296446 1559
475f9031 1560 (ediff-operate-on-windows
8a673c10
GM
1561 ;; Arrange for scroll-left and scroll-right being called
1562 ;; interactively so that they set the window's min_hscroll.
1563 ;; Otherwise, automatic hscrolling will undo the effect of
1564 ;; hscrolling.
433d9ace 1565 (if (= (ediff-last-command-char) ?<)
71296446 1566 (lambda (arg)
8a673c10
GM
1567 (let ((prefix-arg arg))
1568 (call-interactively 'scroll-left)))
1569 (lambda (arg)
1570 (let ((prefix-arg arg))
1571 (call-interactively 'scroll-right))))
475f9031
KH
1572 ;; calculate argument to scroll-left/right
1573 ;; if there is an explicit argument
1574 (if (and arg (not (equal arg '-)))
1575 ;; use it
1576 (prefix-numeric-value arg)
1577 ;; if not, see if we can determine a default amount
1578 ;; (half the window width)
1579 (if (null ediff-control-window)
1580 ;; no control window, use nil
1581 nil
1582 (let ((default-amount
1583 (- (/ (min (window-width ediff-window-A)
1584 (window-width ediff-window-B)
1585 (if ediff-3way-comparison-job
1586 (window-width ediff-window-C)
1587 500) ; some large number
1588 )
1589 2)
1590 3)))
1591 ;; window found
1592 (if arg
1593 ;; C-u as argument means half of default amount
1594 (/ default-amount 2)
1595 ;; no argument means default amount
1596 default-amount))))))
1597
1598
1599;;BEG, END show the region to be positioned.
3af0304a 1600;;JOB-NAME holds ediff-job-name. The ediff-windows job positions regions
71296446 1601;;differently.
475f9031
KH
1602(defun ediff-position-region (beg end pos job-name)
1603 (if (> end (point-max))
1604 (setq end (point-max)))
41d25ad0 1605 (if ediff-windows-job
475f9031
KH
1606 (if (pos-visible-in-window-p end)
1607 () ; do nothing, wind is already positioned
1608 ;; at this point, windows are positioned at the beginning of the
1609 ;; file regions (not diff-regions) being compared.
1610 (save-excursion
1611 (move-to-window-line (- (window-height) 2))
1612 (let ((amount (+ 2 (count-lines (point) end))))
1613 (scroll-up amount))))
1614 (set-window-start (selected-window) beg)
1615 (if (pos-visible-in-window-p end)
1616 ;; Determine the number of lines that the region occupies
41d25ad0
KH
1617 (let ((lines 0)
1618 (prev-point 0))
1619 (while ( and (> end (progn
1620 (move-to-window-line lines)
1621 (point)))
1622 ;; `end' may be beyond the window bottom, so check
a7acbbe4 1623 ;; that we are making progress
41d25ad0
KH
1624 (< prev-point (point)))
1625 (setq prev-point (point))
475f9031
KH
1626 (setq lines (1+ lines)))
1627 ;; And position the beginning on the right line
1628 (goto-char beg)
1629 (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
1630 lines)
1631 1)
1632 )
1633 2))))
1634 (goto-char pos)
1635 ))
1636
651342bc
MK
1637;; get number of lines from window start to region end
1638(defun ediff-get-lines-to-region-end (buf-type &optional n ctl-buf)
1639 (or n (setq n ediff-current-difference))
1640 (or ctl-buf (setq ctl-buf ediff-control-buffer))
e756eb9f 1641 (ediff-with-current-buffer ctl-buf
651342bc 1642 (let* ((buf (ediff-get-buffer buf-type))
e756eb9f
MK
1643 (wind (eval (ediff-get-symbol-from-alist
1644 buf-type ediff-window-alist)))
651342bc
MK
1645 (beg (window-start wind))
1646 (end (ediff-get-diff-posn buf-type 'end))
1647 lines)
e756eb9f 1648 (ediff-with-current-buffer buf
651342bc
MK
1649 (if (< beg end)
1650 (setq lines (count-lines beg end))
1651 (setq lines 0))
1652 lines
1653 ))))
1654
2eb4bdca
MK
1655;; Calculate the number of lines from window end to the start of diff region
1656(defun ediff-get-lines-to-region-start (buf-type &optional diff-num ctl-buf)
1657 (or diff-num (setq diff-num ediff-current-difference))
651342bc 1658 (or ctl-buf (setq ctl-buf ediff-control-buffer))
e756eb9f 1659 (ediff-with-current-buffer ctl-buf
651342bc 1660 (let* ((buf (ediff-get-buffer buf-type))
e756eb9f
MK
1661 (wind (eval (ediff-get-symbol-from-alist
1662 buf-type ediff-window-alist)))
2eb4bdca
MK
1663 (end (or (window-end wind) (window-end wind t)))
1664 (beg (ediff-get-diff-posn buf-type 'beg diff-num)))
e756eb9f 1665 (ediff-with-current-buffer buf
2eb4bdca
MK
1666 (if (< beg end)
1667 (count-lines (max beg (point-min)) (min end (point-max))) 0))
651342bc
MK
1668 )))
1669
1670
bbe6126c
MK
1671;; region size coefficient is a coefficient by which to adjust scrolling
1672;; up/down of the window displaying buffer of type BUFTYPE.
1673;; The purpose of this coefficient is to make the windows scroll in sync, so
1674;; that it won't happen that one diff region is scrolled off while the other is
1675;; still seen.
1676;;
1677;; If the difference region is invalid, the coefficient is 1
651342bc 1678(defun ediff-get-region-size-coefficient (buf-type op &optional n ctl-buf)
e756eb9f 1679 (ediff-with-current-buffer (or ctl-buf ediff-control-buffer)
bbe6126c
MK
1680 (if (ediff-valid-difference-p n)
1681 (let* ((func (cond ((eq op 'scroll-down)
1682 'ediff-get-lines-to-region-start)
1683 ((eq op 'scroll-up)
1684 'ediff-get-lines-to-region-end)
4f91a816 1685 (t (lambda (a b c) 0))))
bbe6126c
MK
1686 (max-lines (max (funcall func 'A n ctl-buf)
1687 (funcall func 'B n ctl-buf)
1688 (if (ediff-buffer-live-p ediff-buffer-C)
1689 (funcall func 'C n ctl-buf)
1690 0))))
1691 ;; this covers the horizontal coefficient as well:
1692 ;; if max-lines = 0 then coef = 1
1693 (if (> max-lines 0)
1694 (/ (+ (funcall func buf-type n ctl-buf) 0.0)
1695 (+ max-lines 0.0))
1696 1))
1697 1)))
651342bc 1698
475f9031
KH
1699
1700(defun ediff-next-difference (&optional arg)
71296446 1701 "Advance to the next difference.
bbe6126c
MK
1702With a prefix argument, go forward that many differences."
1703 (interactive "p")
651342bc 1704 (ediff-barf-if-not-control-buffer)
475f9031
KH
1705 (if (< ediff-current-difference ediff-number-of-differences)
1706 (let ((n (min ediff-number-of-differences
138b07c8 1707 (+ ediff-current-difference (or arg 1))))
3af0304a 1708 non-clash-skip skip-changed regexp-skip)
71296446 1709
ddc90f39 1710 (ediff-visible-region)
475f9031
KH
1711 (or (>= n ediff-number-of-differences)
1712 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
8e41a31c 1713 ;; this won't exec if regexp-skip is t
e2de3a29 1714 (setq non-clash-skip (ediff-merge-region-is-non-clash-to-skip n)
71296446 1715 skip-changed
3af0304a 1716 (ediff-skip-merge-region-if-changed-from-default-p n))
475f9031 1717 (ediff-install-fine-diff-if-necessary n))
3af0304a 1718 ;; Skip loop
475f9031
KH
1719 (while (and (< n ediff-number-of-differences)
1720 (or
1721 ;; regexp skip
1722 regexp-skip
1723 ;; skip clashes, if necessary
8e41a31c 1724 non-clash-skip
3af0304a
MK
1725 ;; skip processed regions
1726 skip-changed
475f9031
KH
1727 ;; skip difference regions that differ in white space
1728 (and ediff-ignore-similar-regions
e2de3a29 1729 (ediff-merge-region-is-non-clash n)
3af0304a
MK
1730 (or (eq (ediff-no-fine-diffs-p n) t)
1731 (and (ediff-merge-job)
1732 (eq (ediff-no-fine-diffs-p n) 'C)))
1733 )))
475f9031
KH
1734 (setq n (1+ n))
1735 (if (= 0 (mod n 20))
1736 (message "Skipped over region %d and counting ..." n))
1737 (or (>= n ediff-number-of-differences)
1738 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
8e41a31c 1739 ;; this won't exec if regexp-skip is t
e2de3a29 1740 (setq non-clash-skip (ediff-merge-region-is-non-clash-to-skip n)
3af0304a
MK
1741 skip-changed
1742 (ediff-skip-merge-region-if-changed-from-default-p n))
475f9031
KH
1743 (ediff-install-fine-diff-if-necessary n))
1744 )
41d25ad0 1745 (message "")
475f9031
KH
1746 (ediff-unselect-and-select-difference n)
1747 ) ; let
1748 (ediff-visible-region)
1749 (error "At end of the difference list")))
1750
1751(defun ediff-previous-difference (&optional arg)
71296446 1752 "Go to the previous difference.
475f9031 1753With a prefix argument, go back that many differences."
bbe6126c 1754 (interactive "p")
651342bc 1755 (ediff-barf-if-not-control-buffer)
475f9031 1756 (if (> ediff-current-difference -1)
138b07c8 1757 (let ((n (max -1 (- ediff-current-difference (or arg 1))))
3af0304a 1758 non-clash-skip skip-changed regexp-skip)
71296446 1759
ddc90f39 1760 (ediff-visible-region)
475f9031
KH
1761 (or (< n 0)
1762 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
8e41a31c 1763 ;; this won't exec if regexp-skip is t
e2de3a29 1764 (setq non-clash-skip (ediff-merge-region-is-non-clash-to-skip n)
71296446 1765 skip-changed
3af0304a 1766 (ediff-skip-merge-region-if-changed-from-default-p n))
475f9031
KH
1767 (ediff-install-fine-diff-if-necessary n))
1768 (while (and (> n -1)
1769 (or
1770 ;; regexp skip
1771 regexp-skip
1772 ;; skip clashes, if necessary
8e41a31c 1773 non-clash-skip
3af0304a
MK
1774 ;; skipp changed regions
1775 skip-changed
475f9031
KH
1776 ;; skip difference regions that differ in white space
1777 (and ediff-ignore-similar-regions
39bcfe5f 1778 (ediff-merge-region-is-non-clash n)
3af0304a
MK
1779 (or (eq (ediff-no-fine-diffs-p n) t)
1780 (and (ediff-merge-job)
1781 (eq (ediff-no-fine-diffs-p n) 'C)))
1782 )))
475f9031
KH
1783 (if (= 0 (mod (1+ n) 20))
1784 (message "Skipped over region %d and counting ..." (1+ n)))
1785 (setq n (1- n))
1786 (or (< n 0)
1787 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
8e41a31c 1788 ;; this won't exec if regexp-skip is t
e2de3a29 1789 (setq non-clash-skip (ediff-merge-region-is-non-clash-to-skip n)
3af0304a
MK
1790 skip-changed
1791 (ediff-skip-merge-region-if-changed-from-default-p n))
475f9031
KH
1792 (ediff-install-fine-diff-if-necessary n))
1793 )
41d25ad0 1794 (message "")
475f9031
KH
1795 (ediff-unselect-and-select-difference n)
1796 ) ; let
1797 (ediff-visible-region)
1798 (error "At beginning of the difference list")))
1799
bbe6126c
MK
1800;; The diff number is as perceived by the user (i.e., 1+ the internal
1801;; representation)
475f9031 1802(defun ediff-jump-to-difference (difference-number)
bbe6126c
MK
1803 "Go to the difference specified as a prefix argument.
1804If the prefix is negative, count differences from the end."
475f9031 1805 (interactive "p")
651342bc 1806 (ediff-barf-if-not-control-buffer)
bbe6126c
MK
1807 (setq difference-number
1808 (cond ((< difference-number 0)
1809 (+ ediff-number-of-differences difference-number))
1810 ((> difference-number 0) (1- difference-number))
1811 (t -1)))
1812 ;; -1 is allowed by ediff-unselect-and-select-difference --- it is the
1813 ;; position before the first one.
41d25ad0 1814 (if (and (>= difference-number -1)
bbe6126c 1815 (<= difference-number ediff-number-of-differences))
41d25ad0 1816 (ediff-unselect-and-select-difference difference-number)
bbe6126c
MK
1817 (error ediff-BAD-DIFF-NUMBER
1818 this-command (1+ difference-number) ediff-number-of-differences)))
71296446 1819
bbe6126c 1820(defun ediff-jump-to-difference-at-point (arg)
475f9031 1821 "Go to difference closest to the point in buffer A, B, or C.
bbe6126c 1822The buffer depends on last command character \(a, b, or c\) that invoked this
3af0304a
MK
1823command. For instance, if the command was `ga' then the point value in buffer
1824A is used.
bbe6126c
MK
1825With a prefix argument, synchronize all files around the current point position
1826in the specified buffer."
1827 (interactive "P")
651342bc 1828 (ediff-barf-if-not-control-buffer)
433d9ace 1829 (let* ((buf-type (ediff-char-to-buftype (ediff-last-command-char)))
bbe6126c 1830 (buffer (ediff-get-buffer buf-type))
e756eb9f 1831 (pt (ediff-with-current-buffer buffer (point)))
bbe6126c
MK
1832 (diff-no (ediff-diff-at-point buf-type nil (if arg 'after)))
1833 (past-last-diff (< ediff-number-of-differences diff-no))
1834 (beg (if past-last-diff
e756eb9f 1835 (ediff-with-current-buffer buffer (point-max))
bbe6126c
MK
1836 (ediff-get-diff-posn buf-type 'beg (1- diff-no))))
1837 ctl-wind wind-A wind-B wind-C
1838 shift)
1839 (if past-last-diff
1840 (ediff-jump-to-difference -1)
1841 (ediff-jump-to-difference diff-no))
1842 (setq ctl-wind (selected-window)
1843 wind-A ediff-window-A
1844 wind-B ediff-window-B
1845 wind-C ediff-window-C)
1846 (if arg
1847 (progn
e756eb9f 1848 (ediff-with-current-buffer buffer
bbe6126c
MK
1849 (setq shift (- beg pt)))
1850 (select-window wind-A)
1851 (if past-last-diff (goto-char (point-max)))
1852 (condition-case nil
1853 (backward-char shift) ; noerror, if beginning of buffer
1854 (error))
1855 (recenter)
1856 (select-window wind-B)
1857 (if past-last-diff (goto-char (point-max)))
1858 (condition-case nil
1859 (backward-char shift) ; noerror, if beginning of buffer
1860 (error))
1861 (recenter)
1862 (if (window-live-p wind-C)
1863 (progn
1864 (select-window wind-C)
1865 (if past-last-diff (goto-char (point-max)))
1866 (condition-case nil
1867 (backward-char shift) ; noerror, if beginning of buffer
1868 (error))
1869 (recenter)
1870 ))
1871 (select-window ctl-wind)
1872 ))
1873 ))
71296446
JB
1874
1875
475f9031 1876;; find region most related to the current point position (or POS, if given)
bbe6126c 1877;; returns diff number as seen by the user (i.e., 1+ the internal
71296446 1878;; representation)
3af0304a
MK
1879;; The optional argument WHICH-DIFF can be `after' or `before'. If `after',
1880;; find the diff after the point. If `before', find the diff before the
1881;; point. If the point is inside a diff, return that diff.
bbe6126c 1882(defun ediff-diff-at-point (buf-type &optional pos which-diff)
475f9031
KH
1883 (let ((buffer (ediff-get-buffer buf-type))
1884 (ctl-buffer ediff-control-buffer)
1885 (max-dif-num (1- ediff-number-of-differences))
1886 (diff-no -1)
1887 (prev-beg 0)
1888 (prev-end 0)
1889 (beg 0)
1890 (end 0))
71296446 1891
e756eb9f 1892 (ediff-with-current-buffer buffer
475f9031
KH
1893 (setq pos (or pos (point)))
1894 (while (and (or (< pos prev-beg) (> pos beg))
1895 (< diff-no max-dif-num))
1896 (setq diff-no (1+ diff-no))
1897 (setq prev-beg beg
1898 prev-end end)
1899 (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
1900 end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
1901 )
71296446 1902
bbe6126c
MK
1903 ;; boost diff-no by 1, if past the last diff region
1904 (if (and (memq which-diff '(after before))
1905 (> pos beg) (= diff-no max-dif-num))
1906 (setq diff-no (1+ diff-no)))
1907
1908 (cond ((eq which-diff 'after) (1+ diff-no))
1909 ((eq which-diff 'before) diff-no)
1910 ((< (abs (count-lines pos (max 1 prev-end)))
1911 (abs (count-lines pos (max 1 beg))))
1912 diff-no) ; choose prev difference
1913 (t
1914 (1+ diff-no))) ; choose next difference
475f9031
KH
1915 )))
1916
1917\f
1918;;; Copying diffs.
1919
1920(defun ediff-diff-to-diff (arg &optional keys)
4ae69eac
MK
1921 "Copy buffer-X'th difference region to buffer Y \(X,Y are A, B, or C\).
1922If numerical prefix argument, copy the difference specified in the arg.
475f9031
KH
1923Otherwise, copy the difference given by `ediff-current-difference'.
1924This command assumes it is bound to a 2-character key sequence, `ab', `ba',
1925`ac', etc., which is used to determine the types of buffers to be used for
3af0304a 1926copying difference regions. The first character in the sequence specifies
475f9031
KH
1927the source buffer and the second specifies the target.
1928
1929If the second optional argument, a 2-character string, is given, use it to
1930determine the source and the target buffers instead of the command keys."
1931 (interactive "P")
651342bc 1932 (ediff-barf-if-not-control-buffer)
475f9031 1933 (or keys (setq keys (this-command-keys)))
bbe6126c
MK
1934 (if (eq arg '-) (setq arg -1)) ; translate neg arg to -1
1935 (if (numberp arg) (ediff-jump-to-difference arg))
1936
475f9031
KH
1937 (let* ((key1 (aref keys 0))
1938 (key2 (aref keys 1))
50a07e18
MK
1939 (char1 (ediff-event-key key1))
1940 (char2 (ediff-event-key key2))
651342bc 1941 ediff-verbose-p)
475f9031
KH
1942 (ediff-copy-diff ediff-current-difference
1943 (ediff-char-to-buftype char1)
1944 (ediff-char-to-buftype char2))
651342bc
MK
1945 ;; recenter with rehighlighting, but no messages
1946 (ediff-recenter)))
475f9031 1947
4ae69eac
MK
1948(defun ediff-copy-A-to-B (arg)
1949 "Copy ARGth difference region from buffer A to B.
3af0304a 1950ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1951 (interactive "P")
1952 (ediff-diff-to-diff arg "ab"))
1953
1954(defun ediff-copy-B-to-A (arg)
1955 "Copy ARGth difference region from buffer B to A.
3af0304a 1956ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1957 (interactive "P")
1958 (ediff-diff-to-diff arg "ba"))
1959
1960(defun ediff-copy-A-to-C (arg)
1961 "Copy ARGth difference region from buffer A to buffer C.
3af0304a 1962ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1963 (interactive "P")
1964 (ediff-diff-to-diff arg "ac"))
1965
1966(defun ediff-copy-B-to-C (arg)
1967 "Copy ARGth difference region from buffer B to buffer C.
3af0304a 1968ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1969 (interactive "P")
1970 (ediff-diff-to-diff arg "bc"))
1971
1972(defun ediff-copy-C-to-B (arg)
1973 "Copy ARGth difference region from buffer C to B.
3af0304a 1974ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1975 (interactive "P")
1976 (ediff-diff-to-diff arg "cb"))
1977
1978(defun ediff-copy-C-to-A (arg)
1979 "Copy ARGth difference region from buffer C to A.
3af0304a 1980ARG is a prefix argument. If nil, copy the current difference region."
4ae69eac
MK
1981 (interactive "P")
1982 (ediff-diff-to-diff arg "ca"))
1983
1984
475f9031
KH
1985
1986;; Copy diff N from FROM-BUF-TYPE \(given as A, B or C\) to TO-BUF-TYPE.
1987;; If optional DO-NOT-SAVE is non-nil, do not save the old value of the
3af0304a 1988;; target diff. This is used in merging, when constructing the merged
475f9031
KH
1989;; version.
1990(defun ediff-copy-diff (n from-buf-type to-buf-type
1991 &optional batch-invocation reg-to-copy)
1992 (let* ((to-buf (ediff-get-buffer to-buf-type))
1993 ;;(from-buf (if (not reg-to-copy) (ediff-get-buffer from-buf-type)))
1994 (ctrl-buf ediff-control-buffer)
1995 (saved-p t)
1996 (three-way ediff-3way-job)
1997 messg
1998 ediff-verbose-p
1999 reg-to-delete reg-to-delete-beg reg-to-delete-end)
71296446 2000
475f9031
KH
2001 (setq reg-to-delete-beg
2002 (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
2003 (setq reg-to-delete-end
2004 (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
71296446 2005
475f9031
KH
2006 (if reg-to-copy
2007 (setq from-buf-type nil)
2008 (setq reg-to-copy (ediff-get-region-contents n from-buf-type ctrl-buf)))
71296446 2009
475f9031
KH
2010 (setq reg-to-delete (ediff-get-region-contents
2011 n to-buf-type ctrl-buf
2012 reg-to-delete-beg reg-to-delete-end))
71296446 2013
475f9031 2014 (if (string= reg-to-delete reg-to-copy)
4ae69eac 2015 (setq saved-p nil) ; don't copy identical buffers
475f9031
KH
2016 ;; seems ok to copy
2017 (if (or batch-invocation (ediff-test-save-region n to-buf-type))
2018 (condition-case conds
2019 (progn
e756eb9f 2020 (ediff-with-current-buffer to-buf
475f9031 2021 ;; to prevent flags from interfering if buffer is writable
41d25ad0 2022 (let ((inhibit-read-only (null buffer-read-only)))
71296446 2023
475f9031 2024 (goto-char reg-to-delete-end)
4ae69eac 2025 (insert reg-to-copy)
71296446 2026
4ae69eac
MK
2027 (if (> reg-to-delete-end reg-to-delete-beg)
2028 (kill-region reg-to-delete-beg reg-to-delete-end))
475f9031
KH
2029 ))
2030 (or batch-invocation
71296446 2031 (setq
475f9031
KH
2032 messg
2033 (ediff-save-diff-region n to-buf-type reg-to-delete))))
2034 (error (message "ediff-copy-diff: %s %s"
2035 (car conds)
2036 (mapconcat 'prin1-to-string (cdr conds) " "))
2037 (beep 1)
651342bc 2038 (sit-for 2) ; let the user see the error msg
475f9031
KH
2039 (setq saved-p nil)
2040 )))
2041 )
71296446 2042
475f9031
KH
2043 ;; adjust state of difference in case 3-way and diff was copied ok
2044 (if (and saved-p three-way)
41d25ad0 2045 (ediff-set-state-of-diff-in-all-buffers n ctrl-buf))
475f9031
KH
2046
2047 (if batch-invocation
2048 (ediff-clear-fine-differences n)
2049 ;; If diff3 job, we should recompute fine diffs so we clear them
2050 ;; before reinserting flags (and thus before ediff-recenter).
2051 (if (and saved-p three-way)
2052 (ediff-clear-fine-differences n))
71296446 2053
41d25ad0 2054 (ediff-refresh-mode-lines)
71296446 2055
475f9031 2056 ;; For diff2 jobs, don't recompute fine diffs, since we know there
3af0304a 2057 ;; aren't any. So we clear diffs after ediff-recenter.
475f9031
KH
2058 (if (and saved-p (not three-way))
2059 (ediff-clear-fine-differences n))
2060 ;; Make sure that the message about saving and how to restore is seen
2061 ;; by the user
8a26c165 2062 (message "%s" messg))
475f9031 2063 ))
71296446 2064
475f9031
KH
2065;; Save Nth diff of buffer BUF-TYPE \(A, B, or C\).
2066;; That is to say, the Nth diff on the `ediff-killed-diffs-alist'. REG
2067;; is the region to save. It is redundant here, but is passed anyway, for
2068;; convenience.
2069(defun ediff-save-diff-region (n buf-type reg)
2070 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
2071 (buf (ediff-get-buffer buf-type))
2072 (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
71296446 2073
475f9031
KH
2074 (if this-buf-n-th-diff-saved
2075 ;; either nothing saved for n-th diff and buffer or we OK'ed
2076 ;; overriding
2077 (setcdr this-buf-n-th-diff-saved reg)
2078 (if n-th-diff-saved ;; n-th diff saved, but for another buffer
2079 (nconc n-th-diff-saved (list (cons buf reg)))
2080 (setq ediff-killed-diffs-alist ;; create record for n-th diff
2081 (cons (list n (cons buf reg))
2082 ediff-killed-diffs-alist))))
3af0304a 2083 (message "Saving old diff region #%d of buffer %S. To recover, type `r%s'"
475f9031
KH
2084 (1+ n) buf-type
2085 (if ediff-merge-job
2086 "" (downcase (symbol-name buf-type))))
2087 ))
71296446 2088
475f9031
KH
2089;; Test if saving Nth difference region of buffer BUF-TYPE is possible.
2090(defun ediff-test-save-region (n buf-type)
2091 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
2092 (buf (ediff-get-buffer buf-type))
2093 (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
71296446 2094
475f9031
KH
2095 (if this-buf-n-th-diff-saved
2096 (if (yes-or-no-p
71296446 2097 (format
ce5a3ac0 2098 "You've previously copied diff region %d to buffer %S. Confirm? "
475f9031
KH
2099 (1+ n) buf-type))
2100 t
2101 (error "Quit"))
2102 t)))
71296446 2103
475f9031
KH
2104(defun ediff-pop-diff (n buf-type)
2105 "Pop last killed Nth diff region from buffer BUF-TYPE."
2106 (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
2107 (buf (ediff-get-buffer buf-type))
2108 (saved-rec (assoc buf (cdr n-th-record)))
2109 (three-way ediff-3way-job)
2110 (ctl-buf ediff-control-buffer)
2111 ediff-verbose-p
2112 saved-diff reg-beg reg-end recovered)
71296446 2113
475f9031
KH
2114 (if (cdr saved-rec)
2115 (setq saved-diff (cdr saved-rec))
2116 (if (> ediff-number-of-differences 0)
2117 (error "Nothing saved for diff %d in buffer %S" (1+ n) buf-type)
4ae69eac 2118 (error ediff-NO-DIFFERENCES)))
71296446 2119
475f9031
KH
2120 (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
2121 (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
71296446 2122
475f9031 2123 (condition-case conds
e756eb9f 2124 (ediff-with-current-buffer buf
41d25ad0 2125 (let ((inhibit-read-only (null buffer-read-only)))
71296446 2126
475f9031 2127 (goto-char reg-end)
4ae69eac 2128 (insert saved-diff)
71296446 2129
4ae69eac
MK
2130 (if (> reg-end reg-beg)
2131 (kill-region reg-beg reg-end))
71296446 2132
475f9031
KH
2133 (setq recovered t)
2134 ))
2135 (error (message "ediff-pop-diff: %s %s"
2136 (car conds)
2137 (mapconcat 'prin1-to-string (cdr conds) " "))
2138 (beep 1)))
71296446 2139
41d25ad0 2140 ;; Clearing fine diffs is necessary for
3af0304a 2141 ;; ediff-unselect-and-select-difference to properly recompute them. We
41d25ad0
KH
2142 ;; can't rely on ediff-copy-diff to clear this vector, as the user might
2143 ;; have modified diff regions after copying and, thus, may have recomputed
2144 ;; fine diffs.
475f9031
KH
2145 (if recovered
2146 (ediff-clear-fine-differences n))
71296446 2147
475f9031
KH
2148 ;; adjust state of difference
2149 (if (and three-way recovered)
2150 (ediff-set-state-of-diff-in-all-buffers n ctl-buf))
71296446 2151
41d25ad0 2152 (ediff-refresh-mode-lines)
71296446 2153
475f9031
KH
2154 (if recovered
2155 (progn
2156 (setq n-th-record (delq saved-rec n-th-record))
2157 (message "Diff region %d in buffer %S restored" (1+ n) buf-type)
2158 ))
2159 ))
71296446 2160
475f9031
KH
2161(defun ediff-restore-diff (arg &optional key)
2162 "Restore ARGth diff from `ediff-killed-diffs-alist'.
4ae69eac 2163ARG is a prefix argument. If ARG is nil, restore the current-difference.
475f9031 2164If the second optional argument, a character, is given, use it to
433d9ace 2165determine the target buffer instead of (ediff-last-command-char)"
475f9031 2166 (interactive "P")
651342bc 2167 (ediff-barf-if-not-control-buffer)
4ae69eac 2168 (if (numberp arg)
475f9031 2169 (ediff-jump-to-difference arg))
71296446 2170 (ediff-pop-diff ediff-current-difference
433d9ace 2171 (ediff-char-to-buftype (or key (ediff-last-command-char))))
651342bc
MK
2172 ;; recenter with rehighlighting, but no messages
2173 (let (ediff-verbose-p)
2174 (ediff-recenter)))
4ae69eac
MK
2175
2176(defun ediff-restore-diff-in-merge-buffer (arg)
2177 "Restore ARGth diff in the merge buffer.
3af0304a 2178ARG is a prefix argument. If nil, restore the current diff."
4ae69eac
MK
2179 (interactive "P")
2180 (ediff-restore-diff arg ?c))
71296446
JB
2181
2182
475f9031
KH
2183(defun ediff-toggle-regexp-match ()
2184 "Toggle between focusing and hiding of difference regions that match
2185a regular expression typed in by the user."
2186 (interactive)
651342bc 2187 (ediff-barf-if-not-control-buffer)
475f9031
KH
2188 (let ((regexp-A "")
2189 (regexp-B "")
2190 (regexp-C "")
2191 msg-connective alt-msg-connective alt-connective)
2192 (cond
2193 ((or (and (eq ediff-skip-diff-region-function
bbe6126c 2194 ediff-focus-on-regexp-matches-function)
433d9ace 2195 (eq (ediff-last-command-char) ?f))
651342bc
MK
2196 (and (eq ediff-skip-diff-region-function
2197 ediff-hide-regexp-matches-function)
433d9ace 2198 (eq (ediff-last-command-char) ?h)))
475f9031
KH
2199 (message "Selective browsing by regexp turned off")
2200 (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
433d9ace 2201 ((eq (ediff-last-command-char) ?h)
651342bc 2202 (setq ediff-skip-diff-region-function ediff-hide-regexp-matches-function
71296446 2203 regexp-A
475f9031 2204 (read-string
71296446 2205 (format
5b76833f 2206 "Ignore A-regions matching this regexp (default %s): "
475f9031
KH
2207 ediff-regexp-hide-A))
2208 regexp-B
2209 (read-string
71296446 2210 (format
5b76833f 2211 "Ignore B-regions matching this regexp (default %s): "
475f9031
KH
2212 ediff-regexp-hide-B)))
2213 (if ediff-3way-comparison-job
2214 (setq regexp-C
2215 (read-string
71296446 2216 (format
5b76833f 2217 "Ignore C-regions matching this regexp (default %s): "
475f9031
KH
2218 ediff-regexp-hide-C))))
2219 (if (eq ediff-hide-regexp-connective 'and)
2220 (setq msg-connective "BOTH"
2221 alt-msg-connective "ONE OF"
2222 alt-connective 'or)
2223 (setq msg-connective "ONE OF"
2224 alt-msg-connective "BOTH"
2225 alt-connective 'and))
2226 (if (y-or-n-p
2227 (format
651342bc 2228 "Ignore regions that match %s regexps, OK? "
e314af72 2229 msg-connective))
651342bc
MK
2230 (message "Will ignore regions that match %s regexps" msg-connective)
2231 (setq ediff-hide-regexp-connective alt-connective)
2232 (message "Will ignore regions that match %s regexps"
71296446 2233 alt-msg-connective))
651342bc 2234
475f9031
KH
2235 (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
2236 (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
2237 (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
651342bc 2238
433d9ace 2239 ((eq (ediff-last-command-char) ?f)
651342bc
MK
2240 (setq ediff-skip-diff-region-function
2241 ediff-focus-on-regexp-matches-function
71296446 2242 regexp-A
475f9031 2243 (read-string
71296446 2244 (format
5b76833f 2245 "Focus on A-regions matching this regexp (default %s): "
475f9031
KH
2246 ediff-regexp-focus-A))
2247 regexp-B
2248 (read-string
71296446 2249 (format
5b76833f 2250 "Focus on B-regions matching this regexp (default %s): "
475f9031
KH
2251 ediff-regexp-focus-B)))
2252 (if ediff-3way-comparison-job
2253 (setq regexp-C
2254 (read-string
71296446 2255 (format
5b76833f 2256 "Focus on C-regions matching this regexp (default %s): "
475f9031
KH
2257 ediff-regexp-focus-C))))
2258 (if (eq ediff-focus-regexp-connective 'and)
2259 (setq msg-connective "BOTH"
2260 alt-msg-connective "ONE OF"
2261 alt-connective 'or)
2262 (setq msg-connective "ONE OF"
2263 alt-msg-connective "BOTH"
2264 alt-connective 'and))
2265 (if (y-or-n-p
2266 (format
651342bc 2267 "Focus on regions that match %s regexps, OK? "
e314af72 2268 msg-connective))
651342bc
MK
2269 (message "Will focus on regions that match %s regexps"
2270 msg-connective)
2271 (setq ediff-focus-regexp-connective alt-connective)
71296446 2272 (message "Will focus on regions that match %s regexps"
651342bc
MK
2273 alt-msg-connective))
2274
475f9031
KH
2275 (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
2276 (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))
2277 (or (string= regexp-C "") (setq ediff-regexp-focus-C regexp-C))))))
71296446 2278
475f9031
KH
2279(defun ediff-toggle-skip-similar ()
2280 (interactive)
651342bc 2281 (ediff-barf-if-not-control-buffer)
475f9031
KH
2282 (if (not (eq ediff-auto-refine 'on))
2283 (error
2284 "Can't skip over whitespace regions: first turn auto-refining on"))
2285 (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
2286 (if ediff-ignore-similar-regions
2287 (message
2288 "Skipping regions that differ only in white space & line breaks")
2289 (message "Skipping over white-space differences turned off")))
71296446 2290
475f9031
KH
2291(defun ediff-focus-on-regexp-matches (n)
2292 "Focus on diffs that match regexp `ediff-regexp-focus-A/B'.
71296446 2293Regions to be ignored according to this function are those where
475f9031
KH
2294buf A region doesn't match `ediff-regexp-focus-A' and buf B region
2295doesn't match `ediff-regexp-focus-B'.
2296This function returns nil if the region number N (specified as
2297an argument) is not to be ignored and t if region N is to be ignored.
2298
3af0304a 2299N is a region number used by Ediff internally. It is 1 less
475f9031
KH
2300the number seen by the user."
2301 (if (ediff-valid-difference-p n)
2302 (let* ((ctl-buf ediff-control-buffer)
2303 (regex-A ediff-regexp-focus-A)
2304 (regex-B ediff-regexp-focus-B)
2305 (regex-C ediff-regexp-focus-C)
e756eb9f 2306 (reg-A-match (ediff-with-current-buffer ediff-buffer-A
4ae69eac
MK
2307 (save-restriction
2308 (narrow-to-region
2309 (ediff-get-diff-posn 'A 'beg n ctl-buf)
2310 (ediff-get-diff-posn 'A 'end n ctl-buf))
2311 (goto-char (point-min))
2312 (re-search-forward regex-A nil t))))
e756eb9f 2313 (reg-B-match (ediff-with-current-buffer ediff-buffer-B
4ae69eac
MK
2314 (save-restriction
2315 (narrow-to-region
2316 (ediff-get-diff-posn 'B 'beg n ctl-buf)
2317 (ediff-get-diff-posn 'B 'end n ctl-buf))
2318 (re-search-forward regex-B nil t))))
475f9031 2319 (reg-C-match (if ediff-3way-comparison-job
e756eb9f 2320 (ediff-with-current-buffer ediff-buffer-C
4ae69eac
MK
2321 (save-restriction
2322 (narrow-to-region
2323 (ediff-get-diff-posn 'C 'beg n ctl-buf)
2324 (ediff-get-diff-posn 'C 'end n ctl-buf))
2325 (re-search-forward regex-C nil t))))))
475f9031
KH
2326 (not (eval (if ediff-3way-comparison-job
2327 (list ediff-focus-regexp-connective
2328 reg-A-match reg-B-match reg-C-match)
2329 (list ediff-focus-regexp-connective
2330 reg-A-match reg-B-match))))
2331 )))
71296446
JB
2332
2333(defun ediff-hide-regexp-matches (n)
475f9031
KH
2334 "Hide diffs that match regexp `ediff-regexp-hide-A/B/C'.
2335Regions to be ignored are those where buf A region matches
2336`ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
2337This function returns nil if the region number N (specified as
2338an argument) is not to be ignored and t if region N is to be ignored.
2339
3af0304a 2340N is a region number used by Ediff internally. It is 1 less
475f9031
KH
2341the number seen by the user."
2342 (if (ediff-valid-difference-p n)
2343 (let* ((ctl-buf ediff-control-buffer)
2344 (regex-A ediff-regexp-hide-A)
2345 (regex-B ediff-regexp-hide-B)
2346 (regex-C ediff-regexp-hide-C)
e756eb9f 2347 (reg-A-match (ediff-with-current-buffer ediff-buffer-A
4ae69eac
MK
2348 (save-restriction
2349 (narrow-to-region
2350 (ediff-get-diff-posn 'A 'beg n ctl-buf)
2351 (ediff-get-diff-posn 'A 'end n ctl-buf))
2352 (goto-char (point-min))
2353 (re-search-forward regex-A nil t))))
e756eb9f 2354 (reg-B-match (ediff-with-current-buffer ediff-buffer-B
4ae69eac
MK
2355 (save-restriction
2356 (narrow-to-region
2357 (ediff-get-diff-posn 'B 'beg n ctl-buf)
2358 (ediff-get-diff-posn 'B 'end n ctl-buf))
2359 (goto-char (point-min))
2360 (re-search-forward regex-B nil t))))
475f9031 2361 (reg-C-match (if ediff-3way-comparison-job
e756eb9f 2362 (ediff-with-current-buffer ediff-buffer-C
4ae69eac
MK
2363 (save-restriction
2364 (narrow-to-region
2365 (ediff-get-diff-posn 'C 'beg n ctl-buf)
2366 (ediff-get-diff-posn 'C 'end n ctl-buf))
2367 (goto-char (point-min))
2368 (re-search-forward regex-C nil t))))))
475f9031
KH
2369 (eval (if ediff-3way-comparison-job
2370 (list ediff-hide-regexp-connective
2371 reg-A-match reg-B-match reg-C-match)
2372 (list ediff-hide-regexp-connective reg-A-match reg-B-match)))
2373 )))
71296446 2374
475f9031
KH
2375
2376\f
2377;;; Quitting, suspending, etc.
2378
651342bc 2379(defun ediff-quit (reverse-default-keep-variants)
475f9031
KH
2380 "Finish an Ediff session and exit Ediff.
2381Unselects the selected difference, if any, restores the read-only and modified
2382flags of the compared file buffers, kills Ediff buffers for this session
651342bc
MK
2383\(but not buffers A, B, C\).
2384
2385If `ediff-keep-variants' is nil, the user will be asked whether the buffers
71296446
JB
2386containing the variants should be removed \(if they haven't been modified\).
2387If it is t, they will be preserved unconditionally. A prefix argument,
651342bc
MK
2388temporarily reverses the meaning of this variable."
2389 (interactive "P")
2390 (ediff-barf-if-not-control-buffer)
65efc538
MK
2391 (let ((ctl-buf (current-buffer))
2392 (ctl-frm (selected-frame))
2393 (minibuffer-auto-raise t))
ddc90f39
MK
2394 (if (y-or-n-p (format "Quit this Ediff session%s? "
2395 (if (ediff-buffer-live-p ediff-meta-buffer)
2396 " & show containing session group" "")))
2397 (progn
2398 (message "")
2399 (set-buffer ctl-buf)
2400 (ediff-really-quit reverse-default-keep-variants))
65efc538
MK
2401 (select-frame ctl-frm)
2402 (raise-frame ctl-frm)
ddc90f39 2403 (message ""))))
475f9031
KH
2404
2405
2406;; Perform the quit operations.
651342bc 2407(defun ediff-really-quit (reverse-default-keep-variants)
475f9031
KH
2408 (ediff-unhighlight-diffs-totally)
2409 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
2410 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
2411 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
651342bc
MK
2412 (ediff-clear-diff-vector 'ediff-difference-vector-Ancestor 'fine-diffs-also)
2413
475f9031 2414 (ediff-delete-temp-files)
71296446 2415
50a07e18 2416 ;; Restore the visibility range. This affects only ediff-*-regions/windows.
475f9031
KH
2417 ;; Since for other job names ediff-visible-region sets
2418 ;; ediff-visible-bounds to ediff-wide-bounds, the settings below are
2419 ;; ignored for such jobs.
2420 (if ediff-quit-widened
2421 (setq ediff-visible-bounds ediff-wide-bounds)
2422 (setq ediff-visible-bounds ediff-narrow-bounds))
71296446 2423
475f9031
KH
2424 ;; Apply selective display to narrow or widen
2425 (ediff-visible-region)
56eaedfe
JB
2426 (mapc (lambda (overl)
2427 (if (ediff-overlayp overl)
2428 (ediff-delete-overlay overl)))
2429 ediff-wide-bounds)
2430 (mapc (lambda (overl)
2431 (if (ediff-overlayp overl)
2432 (ediff-delete-overlay overl)))
2433 ediff-narrow-bounds)
92c51e07 2434
475f9031 2435 ;; restore buffer mode line id's in buffer-A/B/C
651342bc 2436 (let ((control-buffer ediff-control-buffer)
92c51e07 2437 (meta-buffer ediff-meta-buffer)
3af0304a 2438 (after-quit-hook-internal ediff-after-quit-hook-internal)
328b4b70 2439 (session-number ediff-meta-session-number)
92c51e07
MK
2440 ;; suitable working frame
2441 (warp-frame (if (and (ediff-window-display-p) (eq ediff-grab-mouse t))
71296446 2442 (cond ((window-live-p ediff-window-A)
92c51e07 2443 (window-frame ediff-window-A))
71296446 2444 ((window-live-p ediff-window-B)
92c51e07
MK
2445 (window-frame ediff-window-B))
2446 (t (next-frame))))))
475f9031 2447 (condition-case nil
e756eb9f 2448 (ediff-with-current-buffer ediff-buffer-A
71296446 2449 (setq ediff-this-buffer-ediff-sessions
651342bc 2450 (delq control-buffer ediff-this-buffer-ediff-sessions))
475f9031
KH
2451 (kill-local-variable 'mode-line-buffer-identification)
2452 (kill-local-variable 'mode-line-format)
2453 )
2454 (error))
71296446 2455
475f9031 2456 (condition-case nil
e756eb9f 2457 (ediff-with-current-buffer ediff-buffer-B
71296446 2458 (setq ediff-this-buffer-ediff-sessions
651342bc 2459 (delq control-buffer ediff-this-buffer-ediff-sessions))
475f9031
KH
2460 (kill-local-variable 'mode-line-buffer-identification)
2461 (kill-local-variable 'mode-line-format)
2462 )
2463 (error))
71296446 2464
475f9031 2465 (condition-case nil
e756eb9f 2466 (ediff-with-current-buffer ediff-buffer-C
71296446 2467 (setq ediff-this-buffer-ediff-sessions
651342bc
MK
2468 (delq control-buffer ediff-this-buffer-ediff-sessions))
2469 (kill-local-variable 'mode-line-buffer-identification)
2470 (kill-local-variable 'mode-line-format)
2471 )
2472 (error))
2473
2474 (condition-case nil
e756eb9f 2475 (ediff-with-current-buffer ediff-ancestor-buffer
71296446 2476 (setq ediff-this-buffer-ediff-sessions
651342bc 2477 (delq control-buffer ediff-this-buffer-ediff-sessions))
475f9031
KH
2478 (kill-local-variable 'mode-line-buffer-identification)
2479 (kill-local-variable 'mode-line-format)
2480 )
2481 (error))
651342bc
MK
2482
2483 (setq ediff-session-registry
2484 (delq ediff-control-buffer ediff-session-registry))
2485 (ediff-update-registry)
475f9031
KH
2486 ;; restore state of buffers to what it was before ediff
2487 (ediff-restore-protected-variables)
92c51e07
MK
2488
2489 ;; If the user interrupts (canceling saving the merge buffer), continue
2490 ;; normally.
2491 (condition-case nil
2492 (if (ediff-merge-job)
2493 (run-hooks 'ediff-quit-merge-hook))
2494 (quit))
2495
651342bc 2496 (run-hooks 'ediff-cleanup-hook)
3af0304a 2497
50a07e18
MK
2498 (ediff-janitor
2499 'ask
2500 ;; reverse-default-keep-variants is t if the user quits with a prefix arg
2501 (if reverse-default-keep-variants
2502 (not ediff-keep-variants)
2503 ediff-keep-variants))
651342bc 2504
3af0304a
MK
2505 ;; one hook here is ediff-cleanup-mess, which kills the control buffer and
2506 ;; other auxiliary buffers. we made it into a hook to let the users do their
2507 ;; own cleanup, if needed.
651342bc 2508 (run-hooks 'ediff-quit-hook)
328b4b70 2509 (ediff-update-meta-buffer meta-buffer nil session-number)
92c51e07
MK
2510
2511 ;; warp mouse into a working window
2512 (setq warp-frame ; if mouse is over a reasonable frame, use it
28650cf1 2513 (cond ((ediff-good-frame-under-mouse))
92c51e07 2514 (t warp-frame)))
3af0304a 2515 (if (and (ediff-window-display-p) (frame-live-p warp-frame) ediff-grab-mouse)
e83d1fe8 2516 (set-mouse-position (if (featurep 'emacs)
92c51e07
MK
2517 warp-frame
2518 (frame-selected-window warp-frame))
2519 2 1))
2520
3af0304a 2521 (run-hooks 'after-quit-hook-internal)
651342bc 2522 ))
28650cf1
MK
2523
2524;; Returns frame under mouse, if this frame is not a minibuffer
3af0304a 2525;; frame. Otherwise: nil
28650cf1
MK
2526(defun ediff-good-frame-under-mouse ()
2527 (let ((frame-or-win (car (mouse-position)))
2528 (buf-name "")
2529 frame obj-ok)
2530 (setq obj-ok
e83d1fe8 2531 (if (featurep 'emacs)
28650cf1
MK
2532 (frame-live-p frame-or-win)
2533 (window-live-p frame-or-win)))
2534 (if obj-ok
e83d1fe8 2535 (setq frame (if (featurep 'emacs) frame-or-win (window-frame frame-or-win))
28650cf1
MK
2536 buf-name
2537 (buffer-name (window-buffer (frame-selected-window frame)))))
2538 (if (string-match "Minibuf" buf-name)
2539 nil
2540 frame)))
71296446
JB
2541
2542
475f9031 2543(defun ediff-delete-temp-files ()
328b4b70 2544 (if (and (stringp ediff-temp-file-A) (file-exists-p ediff-temp-file-A))
475f9031 2545 (delete-file ediff-temp-file-A))
328b4b70 2546 (if (and (stringp ediff-temp-file-B) (file-exists-p ediff-temp-file-B))
475f9031 2547 (delete-file ediff-temp-file-B))
328b4b70 2548 (if (and (stringp ediff-temp-file-C) (file-exists-p ediff-temp-file-C))
475f9031 2549 (delete-file ediff-temp-file-C)))
71296446 2550
475f9031
KH
2551
2552;; Kill control buffer, other auxiliary Ediff buffers.
2553;; Leave one of the frames split between buffers A/B/C
2554(defun ediff-cleanup-mess ()
3af0304a
MK
2555 (let* ((buff-A ediff-buffer-A)
2556 (buff-B ediff-buffer-B)
2557 (buff-C ediff-buffer-C)
2558 (ctl-buf ediff-control-buffer)
241d963d 2559 (ctl-wind (ediff-get-visible-buffer-window ctl-buf))
3af0304a
MK
2560 (ctl-frame ediff-control-frame)
2561 (three-way-job ediff-3way-job)
71296446 2562 (main-frame (cond ((window-live-p ediff-window-A)
3af0304a 2563 (window-frame ediff-window-A))
71296446 2564 ((window-live-p ediff-window-B)
3af0304a 2565 (window-frame ediff-window-B)))))
71296446 2566
475f9031
KH
2567 (ediff-kill-buffer-carefully ediff-diff-buffer)
2568 (ediff-kill-buffer-carefully ediff-custom-diff-buffer)
2569 (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
2570 (ediff-kill-buffer-carefully ediff-tmp-buffer)
2571 (ediff-kill-buffer-carefully ediff-error-buffer)
475f9031
KH
2572 (ediff-kill-buffer-carefully ediff-msg-buffer)
2573 (ediff-kill-buffer-carefully ediff-debug-buffer)
ddc90f39
MK
2574 (if (boundp 'ediff-patch-diagnostics)
2575 (ediff-kill-buffer-carefully ediff-patch-diagnostics))
475f9031 2576
241d963d
MK
2577 ;; delete control frame or window
2578 (cond ((and (ediff-window-display-p) (frame-live-p ctl-frame))
2579 (delete-frame ctl-frame))
2580 ((window-live-p ctl-wind)
2581 (delete-window ctl-wind)))
2582
bf5d92c5
MK
2583 ;; Hide bottom toolbar. --marcpa
2584 (if (not (ediff-multiframe-setup-p))
2585 (ediff-kill-bottom-toolbar))
2586
475f9031 2587 (ediff-kill-buffer-carefully ctl-buf)
71296446 2588
3af0304a 2589 (if (frame-live-p main-frame)
50a07e18 2590 (select-frame main-frame))
71296446 2591
475f9031
KH
2592 ;; display only if not visible
2593 (condition-case nil
2594 (or (ediff-get-visible-buffer-window buff-B)
2595 (switch-to-buffer buff-B))
2596 (error))
2597 (condition-case nil
2598 (or (ediff-get-visible-buffer-window buff-A)
2599 (progn
50a07e18
MK
2600 (if (and (ediff-get-visible-buffer-window buff-B)
2601 (ediff-buffer-live-p buff-A))
92c51e07 2602 (funcall ediff-split-window-function))
475f9031
KH
2603 (switch-to-buffer buff-A)))
2604 (error))
2605 (if three-way-job
2606 (condition-case nil
2607 (or (ediff-get-visible-buffer-window buff-C)
2608 (progn
50a07e18
MK
2609 (if (and (or (ediff-get-visible-buffer-window buff-A)
2610 (ediff-get-visible-buffer-window buff-B))
2611 (ediff-buffer-live-p buff-C))
92c51e07 2612 (funcall ediff-split-window-function))
241d963d 2613 (switch-to-buffer buff-C)))
475f9031 2614 (error)))
241d963d 2615 (balance-windows)
475f9031
KH
2616 (message "")
2617 ))
41d25ad0 2618
50a07e18 2619(defun ediff-janitor (ask keep-variants)
41d25ad0 2620 "Kill buffers A, B, and, possibly, C, if these buffers aren't modified.
50a07e18
MK
2621In merge jobs, buffer C is not deleted here, but rather according to
2622ediff-quit-merge-hook.
2623A side effect of cleaning up may be that you should be careful when comparing
2624the same buffer in two separate Ediff sessions: quitting one of them might
2625delete this buffer in another session as well."
2626 (ediff-dispose-of-variant-according-to-user
2627 ediff-buffer-A 'A ask keep-variants)
2628 (ediff-dispose-of-variant-according-to-user
2629 ediff-buffer-B 'B ask keep-variants)
41d25ad0 2630 (if ediff-merge-job ; don't del buf C if merging--del ancestor buf instead
50a07e18
MK
2631 (ediff-dispose-of-variant-according-to-user
2632 ediff-ancestor-buffer 'Ancestor ask keep-variants)
2633 (ediff-dispose-of-variant-according-to-user
2634 ediff-buffer-C 'C ask keep-variants)
2635 ))
2636
2637;; Kill the variant buffer, according to user directives (ask, kill
ee7683eb 2638;; unconditionally, keep)
50a07e18
MK
2639;; BUFF is the buffer, BUFF-TYPE is either 'A, or 'B, 'C, 'Ancestor
2640(defun ediff-dispose-of-variant-according-to-user (buff bufftype ask keep-variants)
2641 ;; if this is indirect buffer, kill it and substitute with direct buf
8bdd0bf7
MK
2642 (if (and (ediff-buffer-live-p buff)
2643 (ediff-with-current-buffer buff ediff-temp-indirect-buffer))
50a07e18
MK
2644 (let ((wind (ediff-get-visible-buffer-window buff))
2645 (base (buffer-base-buffer buff))
2646 (modified-p (buffer-modified-p buff)))
2647 (if (and (window-live-p wind) (ediff-buffer-live-p base))
2648 (set-window-buffer wind base))
2649 ;; Kill indirect buffer even if it is modified, because the base buffer
2650 ;; is still there. Note that if the base buffer is dead then so will be
2651 ;; the indirect buffer
71296446 2652 (ediff-with-current-buffer buff
50a07e18
MK
2653 (set-buffer-modified-p nil))
2654 (ediff-kill-buffer-carefully buff)
2655 (ediff-with-current-buffer base
2656 (set-buffer-modified-p modified-p)))
2657 ;; otherwise, ask or use the value of keep-variants
2658 (or (not (ediff-buffer-live-p buff))
2659 keep-variants
2660 (buffer-modified-p buff)
2661 (and ask
2662 (not (y-or-n-p (format "Kill buffer %S [%s]? "
2663 bufftype (buffer-name buff)))))
2664 (ediff-kill-buffer-carefully buff))
2665 ))
41d25ad0 2666
ddc90f39 2667(defun ediff-maybe-save-and-delete-merge (&optional save-and-continue)
92c51e07 2668 "Default hook to run on quitting a merge job.
ddc90f39
MK
2669This can also be used to save merge buffer in the middle of an Ediff session.
2670
2671If the optional SAVE-AND-CONTINUE argument is non-nil, save merge buffer and
3af0304a 2672continue. Otherwise:
92c51e07
MK
2673If `ediff-autostore-merges' is nil, this does nothing.
2674If it is t, it saves the merge buffer in the file `ediff-merge-store-file'
3af0304a 2675or asks the user, if the latter is nil. It then asks the user whether to
92c51e07
MK
2676delete the merge buffer.
2677If `ediff-autostore-merges' is neither nil nor t, the merge buffer is saved
2678only if this merge job is part of a group, i.e., was invoked from within
2679`ediff-merge-directories', `ediff-merge-directory-revisions', and such."
ddc90f39
MK
2680 (let ((merge-store-file ediff-merge-store-file)
2681 (ediff-autostore-merges ; fake ediff-autostore-merges, if necessary
2682 (if save-and-continue t ediff-autostore-merges)))
92c51e07 2683 (if ediff-autostore-merges
50a07e18 2684 (cond ((stringp merge-store-file)
92c51e07 2685 ;; store, ask to delete
ddc90f39
MK
2686 (ediff-write-merge-buffer-and-maybe-kill
2687 ediff-buffer-C merge-store-file 'show-file save-and-continue))
92c51e07
MK
2688 ((eq ediff-autostore-merges t)
2689 ;; ask for file name
2690 (setq merge-store-file
6e31f65f 2691 (read-file-name "Save the result of the merge in file: "))
ddc90f39
MK
2692 (ediff-write-merge-buffer-and-maybe-kill
2693 ediff-buffer-C merge-store-file nil save-and-continue))
bf5d92c5 2694 ((and (ediff-buffer-live-p ediff-meta-buffer)
e756eb9f 2695 (ediff-with-current-buffer ediff-meta-buffer
bf5d92c5 2696 (ediff-merge-metajob)))
3af0304a
MK
2697 ;; The parent metajob passed nil as the autostore file.
2698 nil)))
92c51e07
MK
2699 ))
2700
3af0304a 2701;; write merge buffer. If the optional argument save-and-continue is non-nil,
ddc90f39
MK
2702;; then don't kill the merge buffer
2703(defun ediff-write-merge-buffer-and-maybe-kill (buf file
2704 &optional
2705 show-file save-and-continue)
50a07e18
MK
2706 (if (not (eq (find-buffer-visiting file) buf))
2707 (let ((warn-message
2708 (format "Another buffer is visiting file %s. Too dangerous to save the merge buffer"
2709 file)))
2710 (beep)
8a26c165 2711 (message "%s" warn-message)
50a07e18
MK
2712 (with-output-to-temp-buffer ediff-msg-buffer
2713 (princ "\n\n")
2714 (princ warn-message)
2715 (princ "\n\n")
2716 )
2717 (sit-for 2))
2718 (ediff-with-current-buffer buf
2719 (if (or (not (file-exists-p file))
2720 (y-or-n-p (format "File %s exists, overwrite? " file)))
2721 (progn
ab1d3835 2722 ;;(write-region nil nil file)
50a07e18
MK
2723 (ediff-with-current-buffer buf
2724 (set-visited-file-name file)
2725 (save-buffer))
2726 (if show-file
2727 (progn
2728 (message "Merge buffer saved in: %s" file)
2729 (set-buffer-modified-p nil)
2730 (sit-for 3)))
2731 (if (and
2732 (not save-and-continue)
2733 (y-or-n-p "Merge buffer saved. Now kill the buffer? "))
2734 (ediff-kill-buffer-carefully buf)))))
2735 ))
92c51e07 2736
475f9031
KH
2737;; The default way of suspending Ediff.
2738;; Buries Ediff buffers, kills all windows.
651342bc 2739(defun ediff-default-suspend-function ()
475f9031
KH
2740 (let* ((buf-A ediff-buffer-A)
2741 (buf-B ediff-buffer-B)
2742 (buf-C ediff-buffer-C)
2743 (buf-A-wind (ediff-get-visible-buffer-window buf-A))
2744 (buf-B-wind (ediff-get-visible-buffer-window buf-B))
2745 (buf-C-wind (ediff-get-visible-buffer-window buf-C))
ddc90f39
MK
2746 (buf-patch (if (boundp 'ediff-patchbufer) ediff-patchbufer nil))
2747 (buf-patch-diag (if (boundp 'ediff-patch-diagnostics)
2748 ediff-patch-diagnostics nil))
475f9031
KH
2749 (buf-err ediff-error-buffer)
2750 (buf-diff ediff-diff-buffer)
2751 (buf-custom-diff ediff-custom-diff-buffer)
2752 (buf-fine-diff ediff-fine-diff-buffer))
71296446 2753
475f9031 2754 ;; hide the control panel
41d25ad0
KH
2755 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
2756 (iconify-frame ediff-control-frame)
71296446 2757 (bury-buffer))
475f9031
KH
2758 (if buf-err (bury-buffer buf-err))
2759 (if buf-diff (bury-buffer buf-diff))
2760 (if buf-custom-diff (bury-buffer buf-custom-diff))
2761 (if buf-fine-diff (bury-buffer buf-fine-diff))
2762 (if buf-patch (bury-buffer buf-patch))
2763 (if buf-patch-diag (bury-buffer buf-patch-diag))
2764 (if (window-live-p buf-A-wind)
2765 (progn
2766 (select-window buf-A-wind)
2767 (delete-other-windows)
2768 (bury-buffer))
ddc90f39
MK
2769 (if (ediff-buffer-live-p buf-A)
2770 (progn
2771 (set-buffer buf-A)
2772 (bury-buffer))))
475f9031
KH
2773 (if (window-live-p buf-B-wind)
2774 (progn
2775 (select-window buf-B-wind)
2776 (delete-other-windows)
2777 (bury-buffer))
ddc90f39
MK
2778 (if (ediff-buffer-live-p buf-B)
2779 (progn
2780 (set-buffer buf-B)
2781 (bury-buffer))))
475f9031
KH
2782 (if (window-live-p buf-C-wind)
2783 (progn
2784 (select-window buf-C-wind)
2785 (delete-other-windows)
2786 (bury-buffer))
ddc90f39
MK
2787 (if (ediff-buffer-live-p buf-C)
2788 (progn
2789 (set-buffer buf-C)
2790 (bury-buffer))))
475f9031
KH
2791 ))
2792
71296446 2793
475f9031
KH
2794(defun ediff-suspend ()
2795 "Suspend Ediff.
2796To resume, switch to the appropriate `Ediff Control Panel'
2797buffer and then type \\[ediff-recenter]. Ediff will automatically set
2798up an appropriate window config."
2799 (interactive)
651342bc
MK
2800 (ediff-barf-if-not-control-buffer)
2801 (run-hooks 'ediff-suspend-hook)
475f9031 2802 (message
651342bc 2803 "To resume, type M-x eregistry and select the desired Ediff session"))
475f9031 2804
5786bb71 2805;; ediff-barf-if-not-control-buffer ensures only called from ediff.
acb93bb2 2806(declare-function ediff-version "ediff" ())
5786bb71 2807
475f9031
KH
2808(defun ediff-status-info ()
2809 "Show the names of the buffers or files being operated on by Ediff.
2810Hit \\[ediff-recenter] to reset the windows afterward."
2811 (interactive)
651342bc
MK
2812 (ediff-barf-if-not-control-buffer)
2813 (save-excursion
2814 (ediff-skip-unsuitable-frames))
bbe6126c 2815 (with-output-to-temp-buffer ediff-msg-buffer
5c12aa69
DL
2816 (ediff-with-current-buffer standard-output
2817 (fundamental-mode))
bbe6126c 2818 (raise-frame (selected-frame))
475f9031
KH
2819 (princ (ediff-version))
2820 (princ "\n\n")
e756eb9f 2821 (ediff-with-current-buffer ediff-buffer-A
475f9031
KH
2822 (if buffer-file-name
2823 (princ
2824 (format "File A = %S\n" buffer-file-name))
71296446 2825 (princ
475f9031 2826 (format "Buffer A = %S\n" (buffer-name)))))
e756eb9f 2827 (ediff-with-current-buffer ediff-buffer-B
475f9031
KH
2828 (if buffer-file-name
2829 (princ
2830 (format "File B = %S\n" buffer-file-name))
71296446 2831 (princ
475f9031
KH
2832 (format "Buffer B = %S\n" (buffer-name)))))
2833 (if ediff-3way-job
e756eb9f 2834 (ediff-with-current-buffer ediff-buffer-C
475f9031
KH
2835 (if buffer-file-name
2836 (princ
2837 (format "File C = %S\n" buffer-file-name))
71296446 2838 (princ
475f9031 2839 (format "Buffer C = %S\n" (buffer-name))))))
651342bc
MK
2840 (princ (format "Customized diff output %s\n"
2841 (if (ediff-buffer-live-p ediff-custom-diff-buffer)
2842 (concat "\tin buffer "
2843 (buffer-name ediff-custom-diff-buffer))
ddc90f39 2844 " is not available")))
651342bc
MK
2845 (princ (format "Plain diff output %s\n"
2846 (if (ediff-buffer-live-p ediff-diff-buffer)
2847 (concat "\tin buffer "
2848 (buffer-name ediff-diff-buffer))
ddc90f39 2849 " is not available")))
71296446 2850
e756eb9f 2851 (let* ((A-line (ediff-with-current-buffer ediff-buffer-A
475f9031 2852 (1+ (count-lines (point-min) (point)))))
e756eb9f 2853 (B-line (ediff-with-current-buffer ediff-buffer-B
475f9031
KH
2854 (1+ (count-lines (point-min) (point)))))
2855 C-line)
2856 (princ (format "\Buffer A's point is on line %d\n" A-line))
2857 (princ (format "Buffer B's point is on line %d\n" B-line))
2858 (if ediff-3way-job
2859 (progn
e756eb9f 2860 (setq C-line (ediff-with-current-buffer ediff-buffer-C
475f9031
KH
2861 (1+ (count-lines (point-min) (point)))))
2862 (princ (format "Buffer C's point is on line %d\n" C-line)))))
71296446 2863
475f9031
KH
2864 (princ (format "\nCurrent difference number = %S\n"
2865 (cond ((< ediff-current-difference 0) 'start)
2866 ((>= ediff-current-difference
2867 ediff-number-of-differences) 'end)
2868 (t (1+ ediff-current-difference)))))
2869
4ae69eac 2870 (princ
ddc90f39 2871 (format "\n%s regions that differ in white space & line breaks only"
4ae69eac 2872 (if ediff-ignore-similar-regions
ddc90f39 2873 "Ignoring" "Showing")))
4ae69eac
MK
2874 (if (and ediff-merge-job ediff-show-clashes-only)
2875 (princ
2876 "\nFocusing on regions where both buffers differ from the ancestor"))
3af0304a
MK
2877 (if (and ediff-skip-merge-regions-that-differ-from-default ediff-merge-job)
2878 (princ
2879 "\nSkipping merge regions that differ from default setting"))
71296446 2880
475f9031 2881 (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
4ae69eac 2882 (princ "\nSelective browsing by regexp is off\n"))
651342bc
MK
2883 ((eq ediff-skip-diff-region-function
2884 ediff-hide-regexp-matches-function)
475f9031
KH
2885 (princ
2886 "\nIgnoring regions that match")
2887 (princ
71296446 2888 (format
475f9031
KH
2889 "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
2890 ediff-regexp-hide-A ediff-hide-regexp-connective
2891 ediff-regexp-hide-B)))
651342bc
MK
2892 ((eq ediff-skip-diff-region-function
2893 ediff-focus-on-regexp-matches-function)
475f9031
KH
2894 (princ
2895 "\nFocusing on regions that match")
2896 (princ
2897 (format
2898 "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
2899 ediff-regexp-focus-A ediff-focus-regexp-connective
2900 ediff-regexp-focus-B)))
2901 (t (princ "\nSelective browsing via a user-defined method.\n")))
71296446 2902
475f9031
KH
2903 (princ
2904 (format "\nBugs/suggestions: type `%s' while in Ediff Control Panel."
2905 (substitute-command-keys "\\[ediff-submit-report]")))
651342bc
MK
2906 ) ; with output
2907 (if (frame-live-p ediff-control-frame)
2908 (ediff-reset-mouse ediff-control-frame))
2909 (if (window-live-p ediff-control-window)
2910 (select-window ediff-control-window)))
71296446 2911
475f9031
KH
2912
2913
2914\f
2915;;; Support routines
2916
2917;; Select a difference by placing the ASCII flags around the appropriate
2918;; group of lines in the A, B buffers
2919;; This may have to be modified for buffer C, when it will be supported.
2920(defun ediff-select-difference (n)
2921 (if (and (ediff-buffer-live-p ediff-buffer-A)
2922 (ediff-buffer-live-p ediff-buffer-B)
2923 (ediff-valid-difference-p n))
2924 (progn
743a79af
MK
2925 (cond
2926 ((and (ediff-has-face-support-p) ediff-use-faces)
2927 (ediff-highlight-diff n))
2928 ((eq ediff-highlighting-style 'ascii)
2929 (ediff-place-flags-in-buffer
2930 'A ediff-buffer-A ediff-control-buffer n)
2931 (ediff-place-flags-in-buffer
2932 'B ediff-buffer-B ediff-control-buffer n)
2933 (if ediff-3way-job
2934 (ediff-place-flags-in-buffer
2935 'C ediff-buffer-C ediff-control-buffer n))
2936 (if (ediff-buffer-live-p ediff-ancestor-buffer)
2937 (ediff-place-flags-in-buffer
2938 'Ancestor ediff-ancestor-buffer
2939 ediff-control-buffer n))
71296446
JB
2940 ))
2941
475f9031 2942 (ediff-install-fine-diff-if-necessary n)
81ef8960
MK
2943 ;; set current difference here so the hook will be able to refer to it
2944 (setq ediff-current-difference n)
651342bc 2945 (run-hooks 'ediff-select-hook))))
71296446 2946
475f9031
KH
2947
2948;; Unselect a difference by removing the ASCII flags in the buffers.
2949;; This may have to be modified for buffer C, when it will be supported.
2950(defun ediff-unselect-difference (n)
2951 (if (ediff-valid-difference-p n)
71296446 2952 (progn
4ae69eac 2953 (cond ((and (ediff-has-face-support-p) ediff-use-faces)
475f9031
KH
2954 (ediff-unhighlight-diff))
2955 ((eq ediff-highlighting-style 'ascii)
2956 (ediff-remove-flags-from-buffer
2957 ediff-buffer-A
41d25ad0 2958 (ediff-get-diff-overlay n 'A))
475f9031
KH
2959 (ediff-remove-flags-from-buffer
2960 ediff-buffer-B
41d25ad0 2961 (ediff-get-diff-overlay n 'B))
475f9031
KH
2962 (if ediff-3way-job
2963 (ediff-remove-flags-from-buffer
2964 ediff-buffer-C
41d25ad0 2965 (ediff-get-diff-overlay n 'C)))
651342bc
MK
2966 (if (ediff-buffer-live-p ediff-ancestor-buffer)
2967 (ediff-remove-flags-from-buffer
2968 ediff-ancestor-buffer
2969 (ediff-get-diff-overlay n 'Ancestor)))
475f9031 2970 ))
71296446 2971
475f9031
KH
2972 ;; unhighlight fine diffs
2973 (ediff-set-fine-diff-properties ediff-current-difference 'default)
651342bc 2974 (run-hooks 'ediff-unselect-hook))))
71296446 2975
475f9031
KH
2976
2977;; Unselects prev diff and selects a new one, if FLAG has value other than
2978;; 'select-only or 'unselect-only. If FLAG is 'select-only, the
2979;; next difference is selected, but the current selection is not
2980;; unselected. If FLAG is 'unselect-only then the current selection is
2981;; unselected, but the next one is not selected. If NO-RECENTER is non-nil,
2982;; don't recenter buffers after selecting/unselecting.
475f9031 2983(defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
41d25ad0
KH
2984 (let ((ediff-current-difference n))
2985 (or no-recenter
2986 (ediff-recenter 'no-rehighlight)))
71296446 2987
41d25ad0 2988 (let ((control-buf ediff-control-buffer))
71296446 2989 (unwind-protect
475f9031
KH
2990 (progn
2991 (or (eq flag 'select-only)
2992 (ediff-unselect-difference ediff-current-difference))
71296446 2993
475f9031
KH
2994 (or (eq flag 'unselect-only)
2995 (ediff-select-difference n))
81ef8960
MK
2996 ;; need to set current diff here even though it is also set in
2997 ;; ediff-select-difference because ediff-select-difference might not
2998 ;; be called if unselect-only is specified
475f9031
KH
2999 (setq ediff-current-difference n)
3000 ) ; end protected section
71296446 3001
743a79af
MK
3002 (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines)))
3003 ))
475f9031
KH
3004
3005
50a07e18
MK
3006
3007(defun ediff-highlight-diff-in-one-buffer (n buf-type)
3008 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
3009 (let* ((buff (ediff-get-buffer buf-type))
3010 (last (ediff-with-current-buffer buff (point-max)))
3011 (begin (ediff-get-diff-posn buf-type 'beg n))
3012 (end (ediff-get-diff-posn buf-type 'end n))
3013 (xtra (if (equal begin end) 1 0))
3014 (end-hilit (min last (+ end xtra)))
3015 (current-diff-overlay
3016 (symbol-value
3017 (ediff-get-symbol-from-alist
3018 buf-type ediff-current-diff-overlay-alist))))
3019
e83d1fe8 3020 (if (featurep 'xemacs)
50a07e18
MK
3021 (ediff-move-overlay current-diff-overlay begin end-hilit)
3022 (ediff-move-overlay current-diff-overlay begin end-hilit buff))
3023 (ediff-overlay-put current-diff-overlay 'priority
3024 (ediff-highest-priority begin end-hilit buff))
3025 (ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
3026
3027 ;; unhighlight the background overlay for diff n so it won't
3028 ;; interfere with the current diff overlay
3029 (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
3030 )))
3031
3032
3033(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
3034 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
3035 (let ((current-diff-overlay
3036 (symbol-value
3037 (ediff-get-symbol-from-alist
3038 buf-type ediff-current-diff-overlay-alist)))
3039 (overlay
3040 (ediff-get-diff-overlay ediff-current-difference buf-type))
3041 )
3042
3043 (ediff-move-overlay current-diff-overlay 1 1)
3044
3045 ;; rehighlight the overlay in the background of the
3046 ;; current difference region
3047 (ediff-set-overlay-face
3048 overlay
3049 (if (and (ediff-has-face-support-p)
3050 ediff-use-faces ediff-highlight-all-diffs)
3051 (ediff-background-face buf-type ediff-current-difference)))
3052 )))
3053
3054(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
3055 (ediff-unselect-and-select-difference -1)
3056 (if (and (ediff-has-face-support-p) ediff-use-faces)
3057 (let* ((inhibit-quit t)
3058 (current-diff-overlay-var
3059 (ediff-get-symbol-from-alist
3060 buf-type ediff-current-diff-overlay-alist))
3061 (current-diff-overlay (symbol-value current-diff-overlay-var)))
3062 (ediff-paint-background-regions 'unhighlight)
3063 (if (ediff-overlayp current-diff-overlay)
3064 (ediff-delete-overlay current-diff-overlay))
3065 (set current-diff-overlay-var nil)
3066 )))
3067
3068
b6178721 3069(defun ediff-highlight-diff (n)
50a07e18
MK
3070 "Put face on diff N. Invoked for X displays only."
3071 (ediff-highlight-diff-in-one-buffer n 'A)
3072 (ediff-highlight-diff-in-one-buffer n 'B)
3073 (ediff-highlight-diff-in-one-buffer n 'C)
3074 (ediff-highlight-diff-in-one-buffer n 'Ancestor)
3075 )
3076
3077
b6178721 3078(defun ediff-unhighlight-diff ()
50a07e18
MK
3079 "Remove overlays from buffers A, B, and C."
3080 (ediff-unhighlight-diff-in-one-buffer 'A)
3081 (ediff-unhighlight-diff-in-one-buffer 'B)
3082 (ediff-unhighlight-diff-in-one-buffer 'C)
3083 (ediff-unhighlight-diff-in-one-buffer 'Ancestor)
3084 )
3085
3086;; delete highlighting overlays, restore faces to their original form
b6178721 3087(defun ediff-unhighlight-diffs-totally ()
50a07e18
MK
3088 (ediff-unhighlight-diffs-totally-in-one-buffer 'A)
3089 (ediff-unhighlight-diffs-totally-in-one-buffer 'B)
3090 (ediff-unhighlight-diffs-totally-in-one-buffer 'C)
3091 (ediff-unhighlight-diffs-totally-in-one-buffer 'Ancestor)
3092 )
3093
3094
f8d170a4
JL
3095;; for compatibility
3096(defmacro ediff-minibuffer-with-setup-hook (fun &rest body)
3097 `(if (fboundp 'minibuffer-with-setup-hook)
3098 (minibuffer-with-setup-hook ,fun ,@body)
3099 ,@body))
3100
3af0304a
MK
3101;; This is adapted from a similar function in `emerge.el'.
3102;; PROMPT should not have a trailing ': ', so that it can be modified
3103;; according to context.
3104;; If DEFAULT-FILE is set, it should be used as the default value.
3105;; If DEFAULT-DIR is non-nil, use it as the default directory.
3106;; Otherwise, use the value of Emacs' variable `default-directory.'
50a07e18 3107(defun ediff-read-file-name (prompt default-dir default-file &optional no-dirs)
475f9031
KH
3108 ;; hack default-dir if it is not set
3109 (setq default-dir
3110 (file-name-as-directory
651342bc 3111 (ediff-abbreviate-file-name
475f9031
KH
3112 (expand-file-name (or default-dir
3113 (and default-file
3114 (file-name-directory default-file))
3115 default-directory)))))
3116
3117 ;; strip the directory from default-file
3118 (if default-file
3119 (setq default-file (file-name-nondirectory default-file)))
3120 (if (string= default-file "")
3121 (setq default-file nil))
3122
e237085f
JL
3123 (let ((defaults (and (fboundp 'dired-dwim-target-defaults)
3124 (dired-dwim-target-defaults
3125 (and default-file (list default-file))
3126 default-dir)))
3127 f)
f8d170a4 3128 (setq f (ediff-minibuffer-with-setup-hook
e237085f
JL
3129 (lambda () (when defaults
3130 (setq minibuffer-default defaults)))
3131 (read-file-name
3132 (format "%s%s "
3133 prompt
3134 (cond (default-file
3135 (concat " (default " default-file "):"))
3136 (t (concat " (default " default-dir "):"))))
3137 default-dir
3138 (or default-file default-dir)
3139 t ; must match, no-confirm
3140 (if default-file (file-name-directory default-file)))))
3141 (setq f (expand-file-name f default-dir))
50a07e18 3142 ;; If user entered a directory name, expand the default file in that
475f9031
KH
3143 ;; directory. This allows the user to enter a directory name for the
3144 ;; B-file and diff against the default-file in that directory instead
3145 ;; of a DIRED listing!
3146 (if (and (file-directory-p f) default-file)
3147 (setq f (expand-file-name
3148 (file-name-nondirectory default-file) f)))
50a07e18
MK
3149 (if (and no-dirs (file-directory-p f))
3150 (error "File %s is a directory" f))
71296446
JB
3151 f))
3152
4ae69eac 3153;; If PREFIX is given, then it is used as a prefix for the temp file
3af0304a 3154;; name. Otherwise, `ediff' is used. If FILE is given, use this
475f9031 3155;; file and don't create a new one.
3af0304a 3156;; In MS-DOS, make sure the prefix isn't too long, or else
daafb0e3 3157;; `make-temp-name' isn't guaranteed to return a unique filename.
41d25ad0
KH
3158;; Also, save buffer from START to END in the file.
3159;; START defaults to (point-min), END to (point-max)
651342bc 3160(defun ediff-make-temp-file (buff &optional prefix given-file start end)
daafb0e3
EZ
3161 (let* ((p (ediff-convert-standard-filename (or prefix "ediff")))
3162 (short-p p)
f9fc24a6 3163 (coding-system-for-write ediff-coding-system-for-write)
daafb0e3
EZ
3164 f short-f)
3165 (if (and (fboundp 'msdos-long-file-names)
3166 (not (msdos-long-file-names))
3167 (> (length p) 2))
3168 (setq short-p (substring p 0 2)))
71296446 3169
4ae69eac 3170 (setq f (concat ediff-temp-file-prefix p)
daafb0e3 3171 short-f (concat ediff-temp-file-prefix short-p)
3af0304a 3172 f (cond (given-file)
3cc60763 3173 ((find-file-name-handler f 'insert-file-contents)
4ae69eac
MK
3174 ;; to thwart file handlers in write-region, e.g., if file
3175 ;; name ends with .Z or .gz
3176 ;; This is needed so that patches produced by ediff will
3177 ;; have more meaningful names
3af0304a 3178 (ediff-make-empty-tmp-file short-f))
71296446 3179 (prefix
3af0304a
MK
3180 ;; Prefix is most often the same as the file name for the
3181 ;; variant. Here we are trying to use the original file
3182 ;; name but in the temp directory.
3183 (ediff-make-empty-tmp-file f 'keep-name))
3184 (t
3185 ;; If don't care about name, add some random stuff
3186 ;; to proposed file name.
3187 (ediff-make-empty-tmp-file short-f))))
71296446 3188
475f9031 3189 ;; create the file
e756eb9f 3190 (ediff-with-current-buffer buff
651342bc
MK
3191 (write-region (if start start (point-min))
3192 (if end end (point-max))
3193 f
3194 nil ; don't append---erase
71296446 3195 'no-message)
651342bc 3196 (set-file-modes f ediff-temp-file-mode)
daafb0e3 3197 (expand-file-name f))))
475f9031 3198
3af0304a
MK
3199;; Create a temporary file.
3200;; The returned file name (created by appending some random characters at the
3201;; end of PROPOSED-NAME is guaranteed to point to a newly created empty file.
3202;; This is a replacement for make-temp-name, which eliminates a security hole.
3203;; If KEEP-PROPOSED-NAME isn't nil, try to keep PROPOSED-NAME, unless such file
3204;; already exists.
3205;; It is a modified version of make-temp-file in emacs 20.5
3206(defun ediff-make-empty-tmp-file (proposed-name &optional keep-proposed-name)
3207 (let ((file proposed-name))
3208 (while (condition-case ()
3209 (progn
3210 (if (or (file-exists-p file) (not keep-proposed-name))
3211 (setq file (make-temp-name proposed-name)))
50a07e18
MK
3212 ;; the with-temp-buffer thing is a workaround for an XEmacs
3213 ;; bug: write-region complains that we are trying to visit a
3214 ;; file in an indirect buffer, failing to notice that the
3215 ;; VISIT flag is unset and that we are actually writing from a
3216 ;; string and not from any buffer.
3217 (with-temp-buffer
3218 (write-region "" nil file nil 'silent nil 'excl))
3af0304a
MK
3219 nil)
3220 (file-already-exists t))
3221 ;; the file was somehow created by someone else between
3222 ;; `make-temp-name' and `write-region', let's try again.
3223 nil)
3224 file))
3225
3226
475f9031
KH
3227;; Quote metacharacters (using \) when executing diff in Unix, but not in
3228;; EMX OS/2
651342bc 3229;;(defun ediff-protect-metachars (str)
7c2fb837 3230;; (or (memq system-type '(emx))
651342bc
MK
3231;; (let ((limit 0))
3232;; (while (string-match ediff-metachars str limit)
3233;; (setq str (concat (substring str 0 (match-beginning 0))
3234;; "\\"
3235;; (substring str (match-beginning 0))))
3236;; (setq limit (1+ (match-end 0))))))
3237;; str)
475f9031
KH
3238
3239;; Make sure the current buffer (for a file) has the same contents as the
3240;; file on disk, and attempt to remedy the situation if not.
3241;; Signal an error if we can't make them the same, or the user doesn't want
3242;; to do what is necessary to make them the same.
bbe6126c 3243;; Also, Ediff always offers to revert obsolete buffers, whether they
475f9031
KH
3244;; are modified or not.
3245(defun ediff-verify-file-buffer (&optional file-magic)
3246 ;; First check if the file has been modified since the buffer visited it.
3247 (if (verify-visited-file-modtime (current-buffer))
3248 (if (buffer-modified-p)
3249 ;; If buffer is not obsolete and is modified, offer to save
71296446 3250 (if (yes-or-no-p
50a07e18
MK
3251 (format "Buffer %s has been modified. Save it in file %s? "
3252 (buffer-name)
475f9031 3253 buffer-file-name))
bbe6126c 3254 (condition-case nil
475f9031 3255 (save-buffer)
bbe6126c
MK
3256 (error
3257 (beep)
3258 (message "Couldn't save %s" buffer-file-name)))
3259 (error "Buffer is out of sync for file %s" buffer-file-name))
475f9031
KH
3260 ;; If buffer is not obsolete and is not modified, do nothing
3261 nil)
3262 ;; If buffer is obsolete, offer to revert
3263 (if (yes-or-no-p
50a07e18
MK
3264 (format "File %s was modified since visited by buffer %s. REVERT file %s? "
3265 buffer-file-name
3266 (buffer-name)
475f9031
KH
3267 buffer-file-name))
3268 (progn
3269 (if file-magic
3270 (erase-buffer))
3271 (revert-buffer t t))
3272 (error "Buffer out of sync for file %s" buffer-file-name))))
3273
50a07e18
MK
3274;; if there is another buffer visiting the file of the merge buffer, offer to
3275;; save and delete the buffer; else bark
3276(defun ediff-verify-file-merge-buffer (file)
3277 (let ((buff (if (stringp file) (find-buffer-visiting file)))
3278 warn-message)
3279 (or (null buff)
3280 (progn
3281 (setq warn-message
3282 (format "Buffer %s is visiting %s. Save and kill the buffer? "
3283 (buffer-name buff) file))
3284 (with-output-to-temp-buffer ediff-msg-buffer
3285 (princ "\n\n")
3286 (princ warn-message)
3287 (princ "\n\n"))
3288 (if (y-or-n-p
8a26c165 3289 (message "%s" warn-message))
50a07e18
MK
3290 (with-current-buffer buff
3291 (save-buffer)
3292 (kill-buffer (current-buffer)))
3293 (error "Too dangerous to merge versions of a file visited by another buffer"))))
3294 ))
3295
3296
475f9031 3297
bd698e98
MK
3298(defun ediff-filename-magic-p (file)
3299 (or (ediff-file-compressed-p file)
3300 (ediff-file-remote-p file)))
3301
3302
475f9031
KH
3303(defun ediff-save-buffer (arg)
3304 "Safe way of saving buffers A, B, C, and the diff output.
3305`wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C,
651342bc
MK
3306and `wd' saves the diff output.
3307
3308With prefix argument, `wd' saves plain diff output.
3309Without an argument, it saves customized diff argument, if available
3310\(and plain output, if customized output was not generated\)."
475f9031 3311 (interactive "P")
651342bc
MK
3312 (ediff-barf-if-not-control-buffer)
3313 (ediff-compute-custom-diffs-maybe)
e756eb9f 3314 (ediff-with-current-buffer
433d9ace 3315 (cond ((memq (ediff-last-command-char) '(?a ?b ?c))
41d25ad0 3316 (ediff-get-buffer
433d9ace
MK
3317 (ediff-char-to-buftype (ediff-last-command-char))))
3318 ((eq (ediff-last-command-char) ?d)
651342bc
MK
3319 (message "Saving diff output ...")
3320 (sit-for 1) ; let the user see the message
3321 (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
3322 ediff-diff-buffer)
3323 ((ediff-buffer-live-p ediff-custom-diff-buffer)
3324 ediff-custom-diff-buffer)
3325 ((ediff-buffer-live-p ediff-diff-buffer)
3326 ediff-diff-buffer)
3327 (t (error "Output from `diff' not found"))))
3328 )
42acc581
MK
3329 (let ((window-min-height 2))
3330 (save-buffer))))
651342bc 3331
743a79af
MK
3332
3333;; idea suggested by Hannu Koivisto <azure@iki.fi>
3334(defun ediff-clone-buffer-for-region-comparison (buff region-name)
3335 (let ((cloned-buff (ediff-make-cloned-buffer buff region-name))
743a79af 3336 (pop-up-windows t)
241d963d 3337 wind
743a79af
MK
3338 other-wind
3339 msg-buf)
3340 (ediff-with-current-buffer cloned-buff
3341 (setq ediff-temp-indirect-buffer t))
743a79af 3342 (pop-to-buffer cloned-buff)
241d963d
MK
3343 (setq wind (ediff-get-visible-buffer-window cloned-buff))
3344 (select-window wind)
3345 (delete-other-windows)
279c800c 3346 (ediff-activate-mark)
241d963d
MK
3347 (split-window-vertically)
3348 (ediff-select-lowest-window)
3349 (setq other-wind (selected-window))
743a79af
MK
3350 (with-temp-buffer
3351 (erase-buffer)
3352 (insert
279c800c 3353 (format "\n ******* Mark a region in buffer %s (or confirm the existing one) *******\n"
743a79af
MK
3354 (buffer-name cloned-buff)))
3355 (insert
241d963d
MK
3356 (ediff-with-current-buffer buff
3357 (format "\n\t When done, type %s Use %s to abort\n "
3358 (ediff-format-bindings-of 'exit-recursive-edit)
3359 (ediff-format-bindings-of 'abort-recursive-edit))))
743a79af
MK
3360 (goto-char (point-min))
3361 (setq msg-buf (current-buffer))
241d963d 3362 (set-window-buffer other-wind msg-buf)
743a79af
MK
3363 (shrink-window-if-larger-than-buffer)
3364 (if (window-live-p wind)
3365 (select-window wind))
3366 (condition-case nil
3367 (recursive-edit)
3368 (quit
3369 (ediff-kill-buffer-carefully cloned-buff)))
3370 )
3371 cloned-buff))
3372
3373
3374(defun ediff-clone-buffer-for-window-comparison (buff wind region-name)
3375 (let ((cloned-buff (ediff-make-cloned-buffer buff region-name)))
3376 (ediff-with-current-buffer cloned-buff
3377 (setq ediff-temp-indirect-buffer t))
3378 (set-window-buffer wind cloned-buff)
3379 cloned-buff))
3380
3381(defun ediff-clone-buffer-for-current-diff-comparison (buff buf-type reg-name)
3382 (let ((cloned-buff (ediff-make-cloned-buffer buff reg-name))
3383 (reg-start (ediff-get-diff-posn buf-type 'beg))
3384 (reg-end (ediff-get-diff-posn buf-type 'end)))
3385 (ediff-with-current-buffer cloned-buff
3386 ;; set region to be the current diff region
3387 (goto-char reg-start)
3388 (set-mark reg-end)
3389 (setq ediff-temp-indirect-buffer t))
3390 cloned-buff))
71296446 3391
743a79af
MK
3392
3393
3394(defun ediff-make-cloned-buffer (buff region-name)
3395 (ediff-make-indirect-buffer
241d963d 3396 buff (generate-new-buffer-name
d2049452 3397 (concat (if (stringp buff) buff (buffer-name buff)) region-name))))
743a79af
MK
3398
3399
3400(defun ediff-make-indirect-buffer (base-buf indirect-buf-name)
d2049452
GM
3401 (if (featurep 'xemacs)
3402 (make-indirect-buffer base-buf indirect-buf-name)
3403 (make-indirect-buffer base-buf indirect-buf-name 'clone)))
743a79af
MK
3404
3405
c3912d54 3406;; This function operates only from an ediff control buffer
651342bc 3407(defun ediff-compute-custom-diffs-maybe ()
4ae69eac
MK
3408 (let ((buf-A-file-name (buffer-file-name ediff-buffer-A))
3409 (buf-B-file-name (buffer-file-name ediff-buffer-B))
3410 file-A file-B)
4228da3a
MA
3411 (unless (and buf-A-file-name
3412 (file-exists-p buf-A-file-name)
3413 (not (ediff-file-remote-p buf-A-file-name)))
2d84cc27 3414 (setq file-A (ediff-make-temp-file ediff-buffer-A)))
4228da3a
MA
3415 (unless (and buf-B-file-name
3416 (file-exists-p buf-B-file-name)
3417 (not (ediff-file-remote-p buf-B-file-name)))
2d84cc27 3418 (setq file-B (ediff-make-temp-file ediff-buffer-B)))
4ae69eac
MK
3419 (or (ediff-buffer-live-p ediff-custom-diff-buffer)
3420 (setq ediff-custom-diff-buffer
3421 (get-buffer-create
3422 (ediff-unique-buffer-name "*ediff-custom-diff" "*"))))
c3912d54 3423 (ediff-with-current-buffer ediff-custom-diff-buffer
6d2986fb
MK
3424 (setq buffer-read-only nil)
3425 (erase-buffer))
4ae69eac
MK
3426 (ediff-exec-process
3427 ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
6d2986fb 3428 ediff-custom-diff-options
4fd536b6
MA
3429 (or file-A buf-A-file-name)
3430 (or file-B buf-B-file-name))
513bea45
MK
3431 ;; put the diff file in diff-mode, if it is available
3432 (if (fboundp 'diff-mode)
3433 (with-current-buffer ediff-custom-diff-buffer
3434 (diff-mode)))
2d84cc27
MK
3435 (and file-A (file-exists-p file-A) (delete-file file-A))
3436 (and file-B (file-exists-p file-B) (delete-file file-B))
4ae69eac 3437 ))
651342bc
MK
3438
3439(defun ediff-show-diff-output (arg)
3440 (interactive "P")
3441 (ediff-barf-if-not-control-buffer)
3442 (ediff-compute-custom-diffs-maybe)
3443 (save-excursion
3444 (ediff-skip-unsuitable-frames ' ok-unsplittable))
3445 (let ((buf (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
3446 ediff-diff-buffer)
3447 ((ediff-buffer-live-p ediff-custom-diff-buffer)
3448 ediff-custom-diff-buffer)
3449 ((ediff-buffer-live-p ediff-diff-buffer)
3450 ediff-diff-buffer)
3451 (t
3452 (beep)
3453 (message "Output from `diff' not found")
3454 nil))))
3455 (if buf
3456 (progn
e756eb9f 3457 (ediff-with-current-buffer buf
651342bc
MK
3458 (goto-char (point-min)))
3459 (switch-to-buffer buf)
3460 (raise-frame (selected-frame)))))
3461 (if (frame-live-p ediff-control-frame)
3462 (ediff-reset-mouse ediff-control-frame))
3463 (if (window-live-p ediff-control-window)
3464 (select-window ediff-control-window)))
92c51e07
MK
3465
3466
3467(defun ediff-inferior-compare-regions ()
3468 "Compare regions in an active Ediff session.
3469Like ediff-regions-linewise but is called from under an active Ediff session on
3470the files that belong to that session.
3471
3472After quitting the session invoked via this function, type C-l to the parent
3473Ediff Control Panel to restore highlighting."
3474 (interactive)
3475 (let ((answer "")
3476 (possibilities (list ?A ?B ?C))
bf5d92c5 3477 (zmacs-regions t)
743a79af 3478 use-current-diff-p
92c51e07
MK
3479 begA begB endA endB bufA bufB)
3480
743a79af
MK
3481 (if (ediff-valid-difference-p ediff-current-difference)
3482 (progn
3483 (ediff-set-fine-diff-properties ediff-current-difference 'default)
3484 (ediff-unhighlight-diff)))
3485 (ediff-paint-background-regions 'unhighlight)
3486
92c51e07
MK
3487 (cond ((ediff-merge-job)
3488 (setq bufB ediff-buffer-C)
c3912d54 3489 ;; ask which buffer to compare to the merge buffer
ddc90f39
MK
3490 (while (cond ((eq answer ?A)
3491 (setq bufA ediff-buffer-A
3492 possibilities '(?B))
92c51e07 3493 nil)
ddc90f39
MK
3494 ((eq answer ?B)
3495 (setq bufA ediff-buffer-B
3496 possibilities '(?A))
92c51e07
MK
3497 nil)
3498 ((equal answer ""))
3499 (t (beep 1)
bf5d92c5 3500 (message "Valid values are A or B")
92c51e07
MK
3501 (sit-for 2)
3502 t))
3503 (let ((cursor-in-echo-area t))
c3912d54
MK
3504 (message
3505 "Which buffer to compare to the merge buffer (A or B)? ")
ddc90f39 3506 (setq answer (capitalize (read-char-exclusive))))))
92c51e07
MK
3507
3508 ((ediff-3way-comparison-job)
c3912d54 3509 ;; ask which two buffers to compare
92c51e07
MK
3510 (while (cond ((memq answer possibilities)
3511 (setq possibilities (delq answer possibilities))
3512 (setq bufA
3513 (eval
e756eb9f
MK
3514 (ediff-get-symbol-from-alist
3515 answer ediff-buffer-alist)))
92c51e07
MK
3516 nil)
3517 ((equal answer ""))
3518 (t (beep 1)
71296446 3519 (message
bf5d92c5 3520 "Valid values are %s"
92c51e07
MK
3521 (mapconcat 'char-to-string possibilities " or "))
3522 (sit-for 2)
3523 t))
3524 (let ((cursor-in-echo-area t))
3525 (message "Enter the 1st buffer you want to compare (%s): "
c3912d54 3526 (mapconcat 'char-to-string possibilities " or "))
92c51e07
MK
3527 (setq answer (capitalize (read-char-exclusive)))))
3528 (setq answer "") ; silence error msg
3529 (while (cond ((memq answer possibilities)
3530 (setq possibilities (delq answer possibilities))
3531 (setq bufB
3532 (eval
e756eb9f
MK
3533 (ediff-get-symbol-from-alist
3534 answer ediff-buffer-alist)))
92c51e07
MK
3535 nil)
3536 ((equal answer ""))
3537 (t (beep 1)
71296446 3538 (message
bf5d92c5 3539 "Valid values are %s"
92c51e07
MK
3540 (mapconcat 'char-to-string possibilities " or "))
3541 (sit-for 2)
3542 t))
3543 (let ((cursor-in-echo-area t))
3544 (message "Enter the 2nd buffer you want to compare (%s): "
3545 (mapconcat 'char-to-string possibilities "/"))
3546 (setq answer (capitalize (read-char-exclusive))))))
3547 (t ; 2way comparison
3548 (setq bufA ediff-buffer-A
ddc90f39
MK
3549 bufB ediff-buffer-B
3550 possibilities nil)))
92c51e07 3551
743a79af
MK
3552 (if (and (ediff-valid-difference-p ediff-current-difference)
3553 (y-or-n-p "Compare currently highlighted difference regions? "))
3554 (setq use-current-diff-p t))
3555
3556 (setq bufA (if use-current-diff-p
3557 (ediff-clone-buffer-for-current-diff-comparison
3558 bufA 'A "-Region.A-")
3559 (ediff-clone-buffer-for-region-comparison bufA "-Region.A-")))
e756eb9f 3560 (ediff-with-current-buffer bufA
92c51e07
MK
3561 (setq begA (region-beginning)
3562 endA (region-end))
3563 (goto-char begA)
3564 (beginning-of-line)
3565 (setq begA (point))
3566 (goto-char endA)
3567 (end-of-line)
3568 (or (eobp) (forward-char)) ; include the newline char
3569 (setq endA (point)))
c3912d54 3570
743a79af
MK
3571 (setq bufB (if use-current-diff-p
3572 (ediff-clone-buffer-for-current-diff-comparison
3573 bufB 'B "-Region.B-")
3574 (ediff-clone-buffer-for-region-comparison bufB "-Region.B-")))
e756eb9f 3575 (ediff-with-current-buffer bufB
92c51e07
MK
3576 (setq begB (region-beginning)
3577 endB (region-end))
3578 (goto-char begB)
3579 (beginning-of-line)
3580 (setq begB (point))
3581 (goto-char endB)
3582 (end-of-line)
3583 (or (eobp) (forward-char)) ; include the newline char
3584 (setq endB (point)))
3585
743a79af 3586
92c51e07
MK
3587 (ediff-regions-internal
3588 bufA begA endA bufB begB endB
743a79af
MK
3589 nil ; setup-hook
3590 (if use-current-diff-p ; job name
3591 'ediff-regions-wordwise
3592 'ediff-regions-linewise)
3593 (if use-current-diff-p ; word mode, if diffing current diff
3594 t nil)
ddc90f39
MK
3595 ;; setup param to pass to ediff-setup
3596 (list (cons 'ediff-split-window-function ediff-split-window-function)))
92c51e07 3597 ))
71296446
JB
3598
3599
475f9031 3600
41d25ad0 3601(defun ediff-remove-flags-from-buffer (buffer overlay)
e756eb9f 3602 (ediff-with-current-buffer buffer
41d25ad0 3603 (let ((inhibit-read-only t))
e83d1fe8 3604 (if (featurep 'xemacs)
475f9031 3605 (ediff-overlay-put overlay 'begin-glyph nil)
41d25ad0 3606 (ediff-overlay-put overlay 'before-string nil))
71296446 3607
e83d1fe8 3608 (if (featurep 'xemacs)
475f9031 3609 (ediff-overlay-put overlay 'end-glyph nil)
41d25ad0 3610 (ediff-overlay-put overlay 'after-string nil))
475f9031
KH
3611 )))
3612
3613
3614
475f9031 3615(defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer diff)
e756eb9f 3616 (ediff-with-current-buffer buffer
475f9031
KH
3617 (ediff-place-flags-in-buffer1 buf-type ctl-buffer diff)))
3618
3619
3620(defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer diff-no)
e756eb9f 3621 (let* ((curr-overl (ediff-with-current-buffer ctl-buffer
475f9031 3622 (ediff-get-diff-overlay diff-no buf-type)))
475f9031 3623 (before (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer))
41d25ad0 3624 after beg-of-line flag)
71296446 3625
475f9031
KH
3626 ;; insert flag before the difference
3627 (goto-char before)
3628 (setq beg-of-line (bolp))
71296446 3629
e756eb9f 3630 (setq flag (ediff-with-current-buffer ctl-buffer
41d25ad0
KH
3631 (if (eq ediff-highlighting-style 'ascii)
3632 (if beg-of-line
3633 ediff-before-flag-bol ediff-before-flag-mol))))
71296446 3634
475f9031 3635 ;; insert the flag itself
e83d1fe8 3636 (if (featurep 'xemacs)
475f9031 3637 (ediff-overlay-put curr-overl 'begin-glyph flag)
41d25ad0 3638 (ediff-overlay-put curr-overl 'before-string flag))
71296446 3639
475f9031
KH
3640 ;; insert the flag after the difference
3641 ;; `after' must be set here, after the before-flag was inserted
3642 (setq after (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
3643 (goto-char after)
3644 (setq beg-of-line (bolp))
71296446 3645
e756eb9f 3646 (setq flag (ediff-with-current-buffer ctl-buffer
41d25ad0
KH
3647 (if (eq ediff-highlighting-style 'ascii)
3648 (if beg-of-line
3649 ediff-after-flag-eol ediff-after-flag-mol))))
71296446 3650
475f9031 3651 ;; insert the flag itself
e83d1fe8 3652 (if (featurep 'xemacs)
475f9031 3653 (ediff-overlay-put curr-overl 'end-glyph flag)
41d25ad0 3654 (ediff-overlay-put curr-overl 'after-string flag))
475f9031
KH
3655 ))
3656
50a07e18
MK
3657
3658;;; Some diff region tests
3659
3660;; t if diff region is empty.
3661;; In case of buffer C, t also if it is not a 3way
3662;; comparison job (merging jobs return t as well).
3663(defun ediff-empty-diff-region-p (n buf-type)
3664 (if (eq buf-type 'C)
3665 (or (not ediff-3way-comparison-job)
3666 (= (ediff-get-diff-posn 'C 'beg n)
3667 (ediff-get-diff-posn 'C 'end n)))
3668 (= (ediff-get-diff-posn buf-type 'beg n)
3669 (ediff-get-diff-posn buf-type 'end n))))
3670
3671;; Test if diff region is white space only.
3672;; If 2-way job and buf-type = C, then returns t.
3673(defun ediff-whitespace-diff-region-p (n buf-type)
3674 (or (and (eq buf-type 'C) (not ediff-3way-job))
3675 (ediff-empty-diff-region-p n buf-type)
3676 (let ((beg (ediff-get-diff-posn buf-type 'beg n))
3677 (end (ediff-get-diff-posn buf-type 'end n)))
3678 (ediff-with-current-buffer (ediff-get-buffer buf-type)
3679 (save-excursion
3680 (goto-char beg)
3681 (skip-chars-forward ediff-whitespace)
3682 (>= (point) end))))))
3683
3684
b6178721 3685(defun ediff-get-region-contents (n buf-type ctrl-buf &optional start end)
50a07e18
MK
3686 (ediff-with-current-buffer
3687 (ediff-with-current-buffer ctrl-buf (ediff-get-buffer buf-type))
3688 (buffer-substring
3689 (or start (ediff-get-diff-posn buf-type 'beg n ctrl-buf))
3690 (or end (ediff-get-diff-posn buf-type 'end n ctrl-buf)))))
71296446 3691
bbe6126c 3692;; Returns positions of difference sectors in the BUF-TYPE buffer.
71296446 3693;; BUF-TYPE should be a symbol -- `A', `B', or `C'.
bbe6126c
MK
3694;; POS is either `beg' or `end'--it specifies whether you want the position at
3695;; the beginning of a difference or at the end.
71296446 3696;;
bbe6126c 3697;; The optional argument N says which difference (default:
3af0304a 3698;; `ediff-current-difference'). N is the internal difference number (1- what
bbe6126c
MK
3699;; the user sees). The optional argument CONTROL-BUF says
3700;; which control buffer is in effect in case it is not the current
3701;; buffer.
475f9031 3702(defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
475f9031
KH
3703 (let (diff-overlay)
3704 (or control-buf
3705 (setq control-buf (current-buffer)))
3706
e756eb9f 3707 (ediff-with-current-buffer control-buf
475f9031
KH
3708 (or n (setq n ediff-current-difference))
3709 (if (or (< n 0) (>= n ediff-number-of-differences))
3710 (if (> ediff-number-of-differences 0)
bbe6126c
MK
3711 (error ediff-BAD-DIFF-NUMBER
3712 this-command (1+ n) ediff-number-of-differences)
4ae69eac 3713 (error ediff-NO-DIFFERENCES)))
475f9031 3714 (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
651342bc 3715 (if (not (ediff-buffer-live-p (ediff-overlay-buffer diff-overlay)))
4ae69eac 3716 (error ediff-KILLED-VITAL-BUFFER))
475f9031
KH
3717 (if (eq pos 'beg)
3718 (ediff-overlay-start diff-overlay)
3719 (ediff-overlay-end diff-overlay))
3720 ))
3721
3722
92c51e07
MK
3723;; Restore highlighting to what it should be according to ediff-use-faces,
3724;; ediff-highlighting-style, and ediff-highlight-all-diffs variables.
3725(defun ediff-restore-highlighting (&optional ctl-buf)
e756eb9f 3726 (ediff-with-current-buffer (or ctl-buf (current-buffer))
71296446 3727 (if (and (ediff-has-face-support-p)
92c51e07
MK
3728 ediff-use-faces
3729 ediff-highlight-all-diffs)
3730 (ediff-paint-background-regions))
3731 (ediff-select-difference ediff-current-difference)))
475f9031 3732
475f9031 3733
71296446 3734
475f9031
KH
3735;; null out difference overlays so they won't slow down future
3736;; editing operations
3737;; VEC is either a difference vector or a fine-diff vector
3738(defun ediff-clear-diff-vector (vec-var &optional fine-diffs-also)
3739 (if (vectorp (symbol-value vec-var))
56eaedfe
JB
3740 (mapc (lambda (elt)
3741 (ediff-delete-overlay
3742 (ediff-get-diff-overlay-from-diff-record elt))
3743 (if fine-diffs-also
3744 (ediff-clear-fine-diff-vector elt))
3745 )
3746 (symbol-value vec-var)))
475f9031
KH
3747 ;; allow them to be garbage collected
3748 (set vec-var nil))
651342bc 3749
71296446 3750
475f9031
KH
3751\f
3752;;; Misc
3753
3af0304a 3754;; In Emacs, this just makes overlay. In the future, when Emacs will start
475f9031
KH
3755;; supporting sticky overlays, this function will make a sticky overlay.
3756;; BEG and END are expressions telling where overlay starts.
3af0304a 3757;; If they are numbers or buffers, then all is well. Otherwise, they must
475f9031
KH
3758;; be expressions to be evaluated in buffer BUF in order to get the overlay
3759;; bounds.
3760;; If BUFF is not a live buffer, then return nil; otherwise, return the
3761;; newly created overlay.
3762(defun ediff-make-bullet-proof-overlay (beg end buff)
3763 (if (ediff-buffer-live-p buff)
3764 (let (overl)
e756eb9f 3765 (ediff-with-current-buffer buff
475f9031
KH
3766 (or (number-or-marker-p beg)
3767 (setq beg (eval beg)))
3768 (or (number-or-marker-p end)
3769 (setq end (eval end)))
71296446 3770 (setq overl
d2049452
GM
3771 (if (featurep 'xemacs)
3772 (make-extent beg end buff)
3773 ;; advance front and rear of the overlay
3774 (make-overlay beg end buff nil 'rear-advance)))
71296446 3775
bbe6126c
MK
3776 ;; never detach
3777 (ediff-overlay-put
e83d1fe8 3778 overl (if (featurep 'emacs) 'evaporate 'detachable) nil)
4960e757 3779 ;; make overlay open-ended
bbe6126c 3780 ;; In emacs, it is made open ended at creation time
d2049452
GM
3781 (when (featurep 'xemacs)
3782 (ediff-overlay-put overl 'start-open nil)
3783 (ediff-overlay-put overl 'end-open nil))
651342bc 3784 (ediff-overlay-put overl 'ediff-diff-num 0)
475f9031 3785 overl))))
50a07e18
MK
3786
3787
3788(defun ediff-make-current-diff-overlay (type)
3789 (if (ediff-has-face-support-p)
3790 (let ((overlay (ediff-get-symbol-from-alist
3791 type ediff-current-diff-overlay-alist))
3792 (buffer (ediff-get-buffer type))
33468a59
MK
3793 (face (ediff-get-symbol-from-alist
3794 type ediff-current-diff-face-alist)))
50a07e18
MK
3795 (set overlay
3796 (ediff-make-bullet-proof-overlay (point-max) (point-max) buffer))
3797 (ediff-set-overlay-face (symbol-value overlay) face)
3798 (ediff-overlay-put (symbol-value overlay) 'ediff ediff-control-buffer))
3799 ))
71296446
JB
3800
3801
475f9031
KH
3802;; Like other-buffer, but prefers visible buffers and ignores temporary or
3803;; other insignificant buffers (those beginning with "^[ *]").
3804;; Gets one arg--buffer name or a list of buffer names (it won't return
3805;; these buffers).
71296446 3806;; EXCL-BUFF-LIST is an exclusion list.
3af0304a
MK
3807(defun ediff-other-buffer (excl-buff-lst)
3808 (or (listp excl-buff-lst) (setq excl-buff-lst (list excl-buff-lst)))
657f9cb8
MK
3809 (let* ((all-buffers (nconc (ediff-get-selected-buffers) (buffer-list)))
3810 ;; we compute this the second time because we need to do memq on it
3811 ;; later, and nconc above will break it. Either this or use slow
3812 ;; append instead of nconc
3813 (selected-buffers (ediff-get-selected-buffers))
3af0304a
MK
3814 (prefered-buffer (car all-buffers))
3815 visible-dired-buffers
71296446
JB
3816 (excl-buff-name-list
3817 (mapcar
3af0304a
MK
3818 (lambda (b) (cond ((stringp b) b)
3819 ((bufferp b) (buffer-name b))))
3820 excl-buff-lst))
3821 ;; if at least one buffer on the exclusion list is dired, then force
3822 ;; all others to be dired. This is because this means that the user
3823 ;; has already chosen a dired buffer before
3824 (use-dired-major-mode
3825 (cond ((null (ediff-buffer-live-p (car excl-buff-lst))) 'unknown)
3826 ((eq (ediff-with-current-buffer (car excl-buff-lst) major-mode)
3827 'dired-mode)
3828 'yes)
3829 (t 'no)))
3830 ;; significant-buffers must be visible and not belong
3831 ;; to the exclusion list `buff-list'
3832 ;; We also exclude temporary buffers, but keep mail and gnus buffers
3833 ;; Furthermore, we exclude dired buffers, unless they are the only
3834 ;; ones visible (and there are at least two of them).
3835 ;; Also, any visible window not on the exclusion list that is first in
3836 ;; the buffer list is chosen regardless. (This is because the user
3837 ;; clicked on it or did something to distinguish it).
475f9031
KH
3838 (significant-buffers
3839 (mapcar
3af0304a
MK
3840 (lambda (x)
3841 (cond ((member (buffer-name x) excl-buff-name-list) nil)
657f9cb8
MK
3842 ((memq x selected-buffers) x)
3843 ((not (ediff-get-visible-buffer-window x)) nil)
3844 ((eq x prefered-buffer) x)
3845 ;; if prev selected buffer is dired, look only at
3846 ;; dired.
3847 ((eq use-dired-major-mode 'yes)
3848 (if (eq (ediff-with-current-buffer x major-mode)
3849 'dired-mode)
3850 x nil))
3851 ((eq (ediff-with-current-buffer x major-mode)
3852 'dired-mode)
3853 (if (null use-dired-major-mode)
3854 ;; don't know if we must enforce dired.
3855 ;; Remember this buffer in case
3856 ;; dired buffs are the only ones visible.
3857 (setq visible-dired-buffers
3858 (cons x visible-dired-buffers)))
3859 ;; skip, if dired is not forced
3860 nil)
3861 ((memq (ediff-with-current-buffer x major-mode)
3862 '(rmail-mode
3863 vm-mode
3864 gnus-article-mode
3865 mh-show-mode))
3866 x)
3867 ((string-match "^[ *]" (buffer-name x)) nil)
3868 ((string= "*scratch*" (buffer-name x)) nil)
3869 (t x)))
3af0304a
MK
3870 all-buffers))
3871 (clean-significant-buffers (delq nil significant-buffers))
475f9031 3872 less-significant-buffers)
3af0304a 3873
71296446 3874 (if (and (null clean-significant-buffers)
3af0304a
MK
3875 (> (length visible-dired-buffers) 0))
3876 (setq clean-significant-buffers visible-dired-buffers))
71296446 3877
3af0304a 3878 (cond (clean-significant-buffers (car clean-significant-buffers))
475f9031
KH
3879 ;; try also buffers that are not displayed in windows
3880 ((setq less-significant-buffers
3881 (delq nil
3882 (mapcar
3af0304a
MK
3883 (lambda (x)
3884 (cond ((member (buffer-name x) excl-buff-name-list)
3885 nil)
3886 ((eq use-dired-major-mode 'yes)
3887 (if (eq (ediff-with-current-buffer
3888 x major-mode)
3889 'dired-mode)
3890 x nil))
3891 ((eq (ediff-with-current-buffer x major-mode)
3892 'dired-mode)
3893 nil)
3894 ((string-match "^[ *]" (buffer-name x)) nil)
3895 ((string= "*scratch*" (buffer-name x)) nil)
3896 (t x)))
3897 all-buffers)))
475f9031 3898 (car less-significant-buffers))
3af0304a 3899 (t "*scratch*"))
475f9031 3900 ))
71296446 3901
657f9cb8
MK
3902
3903;; If current buffer is a Buffer-menu buffer, then take the selected buffers
3904;; and append the buffer at the cursor to the end.
3905;; This list would be the preferred list.
3906(defun ediff-get-selected-buffers ()
3907 (if (eq major-mode 'Buffer-menu-mode)
3908 (let ((lis (condition-case nil
3909 (list (Buffer-menu-buffer t))
3910 (error))
3911 ))
3912 (save-excursion
3913 (goto-char (point-max))
3914 (while (search-backward "\n>" nil t)
3915 (forward-char 1)
3916 (setq lis (cons (Buffer-menu-buffer t) lis)))
3917 lis))
3918 ))
71296446 3919
475f9031 3920;; Construct a unique buffer name.
71296446 3921;; The first one tried is prefixsuffix, then prefix<2>suffix,
475f9031
KH
3922;; prefix<3>suffix, etc.
3923(defun ediff-unique-buffer-name (prefix suffix)
3924 (if (null (get-buffer (concat prefix suffix)))
3925 (concat prefix suffix)
3926 (let ((n 2))
3927 (while (get-buffer (format "%s<%d>%s" prefix n suffix))
3928 (setq n (1+ n)))
3929 (format "%s<%d>%s" prefix n suffix))))
71296446 3930
475f9031 3931
475f9031
KH
3932(defun ediff-submit-report ()
3933 "Submit bug report on Ediff."
3934 (interactive)
651342bc 3935 (ediff-barf-if-not-control-buffer)
475f9031
KH
3936 (let ((reporter-prompt-for-summary-p t)
3937 (ctl-buf ediff-control-buffer)
41d25ad0 3938 (ediff-device-type (ediff-device-type))
475f9031
KH
3939 varlist salutation buffer-name)
3940 (setq varlist '(ediff-diff-program ediff-diff-options
b6178721 3941 ediff-diff3-program ediff-diff3-options
475f9031
KH
3942 ediff-patch-program ediff-patch-options
3943 ediff-shell
71296446 3944 ediff-use-faces
475f9031
KH
3945 ediff-auto-refine ediff-highlighting-style
3946 ediff-buffer-A ediff-buffer-B ediff-control-buffer
3947 ediff-forward-word-function
3948 ediff-control-frame
3949 ediff-control-frame-parameters
3950 ediff-control-frame-position-function
3951 ediff-prefer-iconified-control-frame
3952 ediff-window-setup-function
3953 ediff-split-window-function
3954 ediff-job-name
3955 ediff-word-mode
3956 buffer-name
41d25ad0 3957 ediff-device-type
475f9031
KH
3958 ))
3959 (setq salutation "
3af0304a 3960Congratulations! You may have unearthed a bug in Ediff!
475f9031
KH
3961
3962Please make a concise and accurate summary of what happened
3963and mail it to the address above.
3964-----------------------------------------------------------
3965")
71296446 3966
475f9031 3967 (ediff-skip-unsuitable-frames)
41d25ad0 3968 (ediff-reset-mouse)
71296446 3969
475f9031
KH
3970 (switch-to-buffer ediff-msg-buffer)
3971 (erase-buffer)
3972 (delete-other-windows)
3973 (insert "
3974Please read this first:
3975----------------------
3976
3af0304a 3977Some ``bugs'' may actually be no bugs at all. For instance, if you are
475f9031
KH
3978reporting that certain difference regions are not matched as you think they
3979should, this is most likely due to the way Unix diff program decides what
3af0304a 3980constitutes a difference region. Ediff is an Emacs interface to diff, and
475f9031
KH
3981it has nothing to do with those decisions---it only takes the output from
3982diff and presents it in a way that is better suited for human browsing and
3983manipulation.
3984
3985If Emacs happens to dump core, this is NOT an Ediff problem---it is
3af0304a 3986an Emacs bug. Report this to Emacs maintainers.
475f9031
KH
3987
3988Another popular topic for reports is compilation messages. Because Ediff
3989interfaces to several other packages and runs under Emacs and XEmacs,
3990byte-compilation may produce output like this:
3991
3992 While compiling toplevel forms in file ediff.el:
3993 ** reference to free variable pm-color-alist
3994 ........................
3995 While compiling the end of the data:
71296446 3996 ** The following functions are not known to be defined:
3226d6ca 3997 xxx, yyy
475f9031
KH
3998 ........................
3999
4000These are NOT errors, but inevitable warnings, which ought to be ignored.
4001
4002Please do not report those and similar things. However, comments and
4003suggestions are always welcome.
4004
4005Mail anyway? (y or n) ")
71296446 4006
475f9031
KH
4007 (if (y-or-n-p "Mail anyway? ")
4008 (progn
4009 (if (ediff-buffer-live-p ctl-buf)
4010 (set-buffer ctl-buf))
4011 (setq buffer-name (buffer-name))
4012 (require 'reporter)
50a07e18 4013 (reporter-submit-bug-report "kifer@cs.stonybrook.edu"
475f9031
KH
4014 (ediff-version)
4015 varlist
71296446 4016 nil
475f9031
KH
4017 'delete-other-windows
4018 salutation))
4019 (bury-buffer)
4020 (beep 1)(message "Bug report aborted")
4021 (if (ediff-buffer-live-p ctl-buf)
e756eb9f 4022 (ediff-with-current-buffer ctl-buf
475f9031
KH
4023 (ediff-recenter 'no-rehighlight))))
4024 ))
4986c2c6
MK
4025
4026
4027;; Find an appropriate syntax table for everyone to use
4028;; If buffer B is not fundamental or text mode, use its syntax table
4029;; Otherwise, use buffer B's.
4030;; The syntax mode is used in ediff-forward-word-function
4031;; The important thing is that every buffer should use the same syntax table
4032;; during the refinement operation
4033(defun ediff-choose-syntax-table ()
4034 (setq ediff-syntax-table
4035 (ediff-with-current-buffer ediff-buffer-A
71296446 4036 (if (not (memq major-mode
4986c2c6
MK
4037 '(fundamental-mode text-mode indented-text-mode)))
4038 (syntax-table))))
4039 (if (not ediff-syntax-table)
71296446 4040 (setq ediff-syntax-table
4986c2c6
MK
4041 (ediff-with-current-buffer ediff-buffer-B
4042 (syntax-table))))
4043 )
4044
71296446 4045
475f9031 4046(defun ediff-deactivate-mark ()
d2049452
GM
4047 (if (featurep 'xemacs)
4048 (zmacs-deactivate-region)
4049 (deactivate-mark)))
2d84cc27 4050
bf5d92c5 4051(defun ediff-activate-mark ()
d2049452
GM
4052 (if (featurep 'xemacs)
4053 (zmacs-activate-region)
2d84cc27
MK
4054 (make-local-variable 'transient-mark-mode)
4055 (setq mark-active t transient-mark-mode t)))
475f9031 4056
399f21c1
DN
4057(defun ediff-nuke-selective-display ()
4058 (if (featurep 'xemacs)
4059 (nuke-selective-display)
4060 (save-excursion
4061 (save-restriction
4062 (widen)
4063 (goto-char (point-min))
4064 (let ((mod-p (buffer-modified-p))
4065 buffer-read-only end)
4066 (and (eq t selective-display)
4067 (while (search-forward "\^M" nil t)
4068 (end-of-line)
4069 (setq end (point))
4070 (beginning-of-line)
4071 (while (search-forward "\^M" end t)
4072 (delete-char -1)
4073 (insert "\^J"))))
4074 (set-buffer-modified-p mod-p)
4075 (setq selective-display nil))))))
475f9031 4076
71296446 4077
41d25ad0 4078;; The next two are modified versions from emerge.el.
475f9031 4079;; VARS must be a list of symbols
41d25ad0
KH
4080;; ediff-save-variables returns an association list: ((var . val) ...)
4081(defsubst ediff-save-variables (vars)
3af0304a 4082 (mapcar (lambda (v) (cons v (symbol-value v)))
475f9031 4083 vars))
41d25ad0
KH
4084;; VARS is a list of variable symbols.
4085(defun ediff-restore-variables (vars assoc-list)
475f9031 4086 (while vars
41d25ad0
KH
4087 (set (car vars) (cdr (assoc (car vars) assoc-list)))
4088 (setq vars (cdr vars))))
651342bc 4089
41d25ad0
KH
4090(defun ediff-change-saved-variable (var value buf-type)
4091 (let* ((assoc-list
e756eb9f
MK
4092 (symbol-value (ediff-get-symbol-from-alist
4093 buf-type
4094 ediff-buffer-values-orig-alist)))
41d25ad0
KH
4095 (assoc-elt (assoc var assoc-list)))
4096 (if assoc-elt
4097 (setcdr assoc-elt value))))
71296446
JB
4098
4099
475f9031
KH
4100;; must execute in control buf
4101(defun ediff-save-protected-variables ()
41d25ad0 4102 (setq ediff-buffer-values-orig-A
e756eb9f 4103 (ediff-with-current-buffer ediff-buffer-A
475f9031 4104 (ediff-save-variables ediff-protected-variables)))
41d25ad0 4105 (setq ediff-buffer-values-orig-B
e756eb9f 4106 (ediff-with-current-buffer ediff-buffer-B
475f9031
KH
4107 (ediff-save-variables ediff-protected-variables)))
4108 (if ediff-3way-comparison-job
41d25ad0 4109 (setq ediff-buffer-values-orig-C
e756eb9f 4110 (ediff-with-current-buffer ediff-buffer-C
651342bc
MK
4111 (ediff-save-variables ediff-protected-variables))))
4112 (if (ediff-buffer-live-p ediff-ancestor-buffer)
4113 (setq ediff-buffer-values-orig-Ancestor
e756eb9f 4114 (ediff-with-current-buffer ediff-ancestor-buffer
475f9031
KH
4115 (ediff-save-variables ediff-protected-variables)))))
4116
4117;; must execute in control buf
4118(defun ediff-restore-protected-variables ()
41d25ad0
KH
4119 (let ((values-A ediff-buffer-values-orig-A)
4120 (values-B ediff-buffer-values-orig-B)
651342bc
MK
4121 (values-C ediff-buffer-values-orig-C)
4122 (values-Ancestor ediff-buffer-values-orig-Ancestor))
e756eb9f 4123 (ediff-with-current-buffer ediff-buffer-A
651342bc 4124 (ediff-restore-variables ediff-protected-variables values-A))
e756eb9f 4125 (ediff-with-current-buffer ediff-buffer-B
651342bc
MK
4126 (ediff-restore-variables ediff-protected-variables values-B))
4127 (if ediff-3way-comparison-job
e756eb9f 4128 (ediff-with-current-buffer ediff-buffer-C
651342bc
MK
4129 (ediff-restore-variables ediff-protected-variables values-C)))
4130 (if (ediff-buffer-live-p ediff-ancestor-buffer)
e756eb9f 4131 (ediff-with-current-buffer ediff-ancestor-buffer
651342bc
MK
4132 (ediff-restore-variables ediff-protected-variables values-Ancestor)))
4133 ))
475f9031 4134
3af0304a 4135;; save BUFFER in FILE. used in hooks.
4ae69eac 4136(defun ediff-save-buffer-in-file (buffer file)
e756eb9f 4137 (ediff-with-current-buffer buffer
4ae69eac
MK
4138 (write-file file)))
4139
475f9031
KH
4140
4141;;; Debug
4142
4143(ediff-defvar-local ediff-command-begin-time '(0 0 0) "")
4144
4145;; calculate time used by command
4146(defun ediff-calc-command-time ()
0ef923dc
PE
4147 (or (equal ediff-command-begin-time '(0 0 0))
4148 (message "Elapsed time: %g second(s)"
4149 (float-time (time-since ediff-command-begin-time)))))
475f9031
KH
4150
4151(defsubst ediff-save-time ()
4152 (setq ediff-command-begin-time (current-time)))
71296446 4153
475f9031
KH
4154(defun ediff-profile ()
4155 "Toggle profiling Ediff commands."
4156 (interactive)
651342bc 4157 (ediff-barf-if-not-control-buffer)
b9fe4732 4158
d2049452
GM
4159 (if (featurep 'xemacs)
4160 (make-local-hook 'post-command-hook))
b9fe4732 4161
4ae69eac
MK
4162 (let ((pre-hook 'pre-command-hook)
4163 (post-hook 'post-command-hook))
651342bc
MK
4164 (if (not (equal ediff-command-begin-time '(0 0 0)))
4165 (progn (remove-hook pre-hook 'ediff-save-time)
4166 (remove-hook post-hook 'ediff-calc-command-time)
4167 (setq ediff-command-begin-time '(0 0 0))
4168 (message "Ediff profiling disabled"))
b9fe4732
MK
4169 (add-hook pre-hook 'ediff-save-time t 'local)
4170 (add-hook post-hook 'ediff-calc-command-time nil 'local)
651342bc 4171 (message "Ediff profiling enabled"))))
71296446 4172
475f9031
KH
4173(defun ediff-print-diff-vector (diff-vector-var)
4174 (princ (format "\n*** %S ***\n" diff-vector-var))
3af0304a
MK
4175 (mapcar (lambda (overl-vec)
4176 (princ
4177 (format
4178 "Diff %d: \tOverlay: %S
475f9031
KH
4179\t\tFine diffs: %s
4180\t\tNo-fine-diff-flag: %S
4181\t\tState-of-diff:\t %S
4182\t\tState-of-merge:\t %S
71296446 4183"
3af0304a
MK
4184 (1+ (ediff-overlay-get (aref overl-vec 0) 'ediff-diff-num))
4185 (aref overl-vec 0)
4186 ;; fine-diff-vector
4187 (if (= (length (aref overl-vec 1)) 0)
4188 "none\n"
4189 (mapconcat 'prin1-to-string
4190 (aref overl-vec 1) "\n\t\t\t "))
4191 (aref overl-vec 2) ; no fine diff flag
4192 (aref overl-vec 3) ; state-of-diff
4193 (aref overl-vec 4) ; state-of-merge
4194 )))
475f9031
KH
4195 (eval diff-vector-var)))
4196
71296446 4197
475f9031
KH
4198
4199(defun ediff-debug-info ()
4200 (interactive)
651342bc 4201 (ediff-barf-if-not-control-buffer)
475f9031 4202 (with-output-to-temp-buffer ediff-debug-buffer
5c12aa69
DL
4203 (ediff-with-current-buffer standard-output
4204 (fundamental-mode))
475f9031 4205 (princ (format "\nCtl buffer: %S\n" ediff-control-buffer))
651342bc
MK
4206 (ediff-print-diff-vector (intern "ediff-difference-vector-A"))
4207 (ediff-print-diff-vector (intern "ediff-difference-vector-B"))
4208 (ediff-print-diff-vector (intern "ediff-difference-vector-C"))
4209 (ediff-print-diff-vector (intern "ediff-difference-vector-Ancestor"))
475f9031
KH
4210 ))
4211
4ae69eac
MK
4212
4213;;; General utilities
4214
4215;; this uses comparison-func to decide who is a member
4216(defun ediff-member (elt lis comparison-func)
4217 (while (and lis (not (funcall comparison-func (car lis) elt)))
4218 (setq lis (cdr lis)))
4219 lis)
4220
50a07e18
MK
4221;; Make a readable representation of the invocation sequence for FUNC-DEF.
4222;; It would either be a key or M-x something.
4223(defun ediff-format-bindings-of (func-def)
4224 (let ((desc (car (where-is-internal func-def
4225 overriding-local-map
4226 nil nil))))
4227 (if desc
4228 (key-description desc)
4229 (format "M-x %s" func-def))))
4230
4ae69eac
MK
4231;; this uses comparison-func to decide who is a member, and this determines how
4232;; intersection looks like
4233(defun ediff-intersection (lis1 lis2 comparison-func)
4234 (let ((result (list 'a)))
4235 (while lis1
4236 (if (ediff-member (car lis1) lis2 comparison-func)
4237 (nconc result (list (car lis1))))
4238 (setq lis1 (cdr lis1)))
4239 (cdr result)))
71296446 4240
4ae69eac
MK
4241
4242;; eliminates duplicates using comparison-func
4243(defun ediff-union (lis1 lis2 comparison-func)
4244 (let ((result (list 'a)))
4245 (while lis1
4246 (or (ediff-member (car lis1) (cdr result) comparison-func)
4247 (nconc result (list (car lis1))))
4248 (setq lis1 (cdr lis1)))
4249 (while lis2
4250 (or (ediff-member (car lis2) (cdr result) comparison-func)
4251 (nconc result (list (car lis2))))
4252 (setq lis2 (cdr lis2)))
4253 (cdr result)))
4254
4255;; eliminates duplicates using comparison-func
4256(defun ediff-set-difference (lis1 lis2 comparison-func)
4257 (let ((result (list 'a)))
4258 (while lis1
4259 (or (ediff-member (car lis1) (cdr result) comparison-func)
4260 (ediff-member (car lis1) lis2 comparison-func)
4261 (nconc result (list (car lis1))))
4262 (setq lis1 (cdr lis1)))
4263 (cdr result)))
4264
f573c8b0
MK
4265(defun ediff-add-to-history (history-var newelt)
4266 (if (fboundp 'add-to-history)
4267 (add-to-history history-var newelt)
4268 (set history-var (cons newelt (symbol-value history-var)))))
4269
33468a59 4270(defalias 'ediff-copy-list 'copy-sequence)
3af0304a 4271
4ae69eac 4272
475f9031
KH
4273;; don't report error if version control package wasn't found
4274;;(ediff-load-version-control 'silent)
4275
651342bc 4276(run-hooks 'ediff-load-hook)
71296446 4277
41d25ad0 4278
4a107424
SM
4279;; Local Variables:
4280;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
4281;; eval: (put 'ediff-with-current-buffer 'lisp-indent-hook 1)
4282;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
4283;; End:
475f9031 4284
475f9031 4285;;; ediff-util.el ends here