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