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