1 ;;; ediff-util.el --- the core commands and utilities of ediff
2 ;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
6 ;; This file is part of GNU Emacs.
8 ;; GNU Emacs is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; GNU Emacs is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31 "Ediff mode is used by the Ediff file-difference package.
32 It is entered only through one of the following commands:
41 `ediff-merge-files-with-ancestor'
43 `ediff-merge-buffers-with-ancestor'
44 `ediff-merge-revisions'
45 `ediff-merge-revisions-with-ancestor'
46 `ediff-windows-wordwise'
47 `ediff-windows-linewise'
48 `ediff-regions-wordwise'
49 `ediff-regions-linewise'
58 (kill-all-local-variables)
59 (setq major-mode
'ediff-mode
)
60 (setq mode-name
"Ediff")
61 (run-hooks 'ediff-mode-hooks
))
63 (defun ediff-version ()
64 "Return string describing the version of Ediff.
65 When called interactively, displays the version."
68 (message (ediff-version))
69 (format "Ediff %s of %s" ediff-version ediff-date
)))
78 (ediff-defvar-local ediff-mode-map nil
79 "Local keymap used in Ediff mode.
80 This is local to each Ediff Control Panel, so they may vary from invocation
83 ;; Set up the keymap in the control buffer
84 (defun ediff-set-keys ()
85 "Set up Ediff keymap, if necessary."
86 (if (null ediff-mode-map
)
88 (use-local-map ediff-mode-map
))
90 ;; Reload Ediff keymap. For debugging only.
91 (defun ediff-reload-keymap ()
93 (setq ediff-mode-map nil
)
97 (defun ediff-setup-keymap ()
98 "Set up the keymap used in the control buffer of Ediff."
99 (setq ediff-mode-map
(make-sparse-keymap))
100 (suppress-keymap ediff-mode-map
)
102 (define-key ediff-mode-map
"p" 'ediff-previous-difference
)
103 (define-key ediff-mode-map
"\C-?" 'ediff-previous-difference
)
104 (define-key ediff-mode-map
[backspace] 'ediff-previous-difference)
105 (define-key ediff-mode-map [delete] 'ediff-previous-difference)
106 (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
107 'ediff-previous-difference nil))
108 (define-key ediff-mode-map [f1] (if ediff-no-emacs-help-in-control-buffer
109 'ediff-previous-difference nil))
110 (define-key ediff-mode-map [help] (if ediff-no-emacs-help-in-control-buffer
111 'ediff-previous-difference nil))
112 (define-key ediff-mode-map "n" 'ediff-next-difference)
113 (define-key ediff-mode-map " " 'ediff-next-difference)
114 (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
115 (define-key ediff-mode-map "g" nil)
116 (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
117 (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
118 (define-key ediff-mode-map "q" 'ediff-quit)
119 (define-key ediff-mode-map "z" 'ediff-suspend)
120 (define-key ediff-mode-map "\C-l" 'ediff-recenter)
121 (define-key ediff-mode-map "|" 'ediff-toggle-split)
122 (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
124 (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
126 (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
127 (define-key ediff-mode-map "~" 'ediff-swap-buffers)
128 (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
129 (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
130 (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
131 (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
132 (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
133 (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
134 (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
135 (define-key ediff-mode-map "i" 'ediff-status-info)
136 (define-key ediff-mode-map "D" 'ediff-documentation)
137 (define-key ediff-mode-map "?" 'ediff-toggle-help)
138 (define-key ediff-mode-map "!" 'ediff-update-diffs)
140 (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
141 (define-key ediff-mode-map "a" nil)
142 (define-key ediff-mode-map "b" nil)
143 (define-key ediff-mode-map "r" nil)
144 (cond (ediff-merge-job
145 ;; In merging, we allow only A->C and B->C copying.
146 (define-key ediff-mode-map "a" (function
149 (ediff-diff-to-diff arg "ac"))))
150 (define-key ediff-mode-map "b" (function
153 (ediff-diff-to-diff arg "bc"))))
154 (define-key ediff-mode-map "r" (function
157 (ediff-restore-diff arg ?c))))
158 (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
159 (define-key ediff-mode-map "+" 'ediff-combine-diffs)
160 (define-key ediff-mode-map "$" 'ediff-toggle-show-clashes-only)
161 (define-key ediff-mode-map "&" 'ediff-re-merge))
162 (ediff-3way-comparison-job
163 (define-key ediff-mode-map "ab" 'ediff-diff-to-diff)
164 (define-key ediff-mode-map "ba" 'ediff-diff-to-diff)
165 (define-key ediff-mode-map "ac" 'ediff-diff-to-diff)
166 (define-key ediff-mode-map "bc" 'ediff-diff-to-diff)
167 (define-key ediff-mode-map "c" nil)
168 (define-key ediff-mode-map "ca" 'ediff-diff-to-diff)
169 (define-key ediff-mode-map "cb" 'ediff-diff-to-diff)
170 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
171 (define-key ediff-mode-map "rb" 'ediff-restore-diff)
172 (define-key ediff-mode-map "rc" 'ediff-restore-diff)
173 (define-key ediff-mode-map "C" 'ediff-toggle-read-only))
174 (t ; 2-way comparison
175 (define-key ediff-mode-map "a" (function
178 (ediff-diff-to-diff arg "ab"))))
179 (define-key ediff-mode-map "b" (function
182 (ediff-diff-to-diff arg "ba"))))
183 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
184 (define-key ediff-mode-map "rb" 'ediff-restore-diff))
186 (define-key ediff-mode-map "G" 'ediff-submit-report)
187 (define-key ediff-mode-map "#" nil)
188 (define-key ediff-mode-map "#h" 'ediff-toggle-regexp-match)
189 (define-key ediff-mode-map "#f" 'ediff-toggle-regexp-match)
191 (define-key ediff-mode-map "##" 'ediff-toggle-skip-similar))
192 (define-key ediff-mode-map "o" nil)
193 (define-key ediff-mode-map "A" 'ediff-toggle-read-only)
194 (define-key ediff-mode-map "B" 'ediff-toggle-read-only)
195 (define-key ediff-mode-map "w" nil)
196 (define-key ediff-mode-map "wa" 'ediff-save-buffer)
197 (define-key ediff-mode-map "wb" 'ediff-save-buffer)
198 (define-key ediff-mode-map "wd" 'ediff-save-buffer)
201 (define-key ediff-mode-map "wc" 'ediff-save-buffer)
202 (define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
205 (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
207 (define-key ediff-mode-map "k" nil)
208 (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ; for debugging
210 ;; Allow ediff-mode-map to be referenced indirectly
211 (fset 'ediff-mode-map ediff-mode-map)
212 (run-hooks 'ediff-keymap-setup-hooks))
217 (require 'ediff-wind)
219 ;; Common startup entry for all Ediff functions
220 ;; It now returns control buffer so other functions can do post-processing
221 (defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
222 startup-hooks setup-parameters)
223 (setq file-A (expand-file-name file-A))
224 (setq file-B (expand-file-name file-B))
226 (setq file-C (expand-file-name file-C)))
227 (let* ((control-buffer-name
228 (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
229 (control-buffer (ediff-eval-in-buffer buffer-A
230 (get-buffer-create control-buffer-name))))
231 (ediff-eval-in-buffer control-buffer
234 ;; unwrap set up parameters passed as argument
235 (while setup-parameters
236 (set (car (car setup-parameters)) (cdr (car setup-parameters)))
237 (setq setup-parameters (cdr setup-parameters)))
239 ;; set variables classifying the current ediff job
240 (setq ediff-3way-comparison-job (ediff-3way-comparison-job)
241 ediff-merge-job (ediff-merge-job)
242 ediff-merge-with-ancestor-job (ediff-merge-with-ancestor-job)
243 ediff-3way-job (ediff-3way-job)
244 ediff-diff3-job (ediff-diff3-job)
245 ediff-narrow-job (ediff-narrow-job)
246 ediff-windows-job (ediff-windows-job)
247 ediff-word-mode-job (ediff-word-mode-job))
249 (make-local-variable 'ediff-prefer-long-help-message)
250 (make-local-variable 'ediff-prefer-iconified-control-frame)
251 (make-local-variable 'ediff-split-window-function)
252 (make-local-variable 'ediff-default-variant)
253 (make-local-variable 'ediff-merge-window-share)
254 (make-local-variable 'ediff-window-setup-function)
256 ;; adjust for merge jobs
259 ;; Use buf A even if `combined'. The right stuff is
260 ;; inserted by ediff-do-merge
261 (if (eq ediff-default-variant 'default-B) buffer-B buffer-A)))
263 (setq ediff-split-window-function
264 ediff-merge-split-window-function)
266 ;; remember the ancestor buffer, if any
267 (setq ediff-ancestor-buffer buffer-C)
271 (ediff-unique-buffer-name "*ediff-merge" "*")))
273 (set-buffer buffer-C)
275 (funcall (ediff-eval-in-buffer buf major-mode))
276 ;; after Stig@hackvan.com
277 (add-hook 'local-write-file-hooks 'ediff-set-merge-mode)
279 (setq buffer-read-only nil
280 ediff-buffer-A buffer-A
281 ediff-buffer-B buffer-B
282 ediff-buffer-C buffer-C
283 ediff-control-buffer control-buffer)
285 (setq ediff-control-buffer-suffix
286 (if (string-match "<[0-9]*>" control-buffer-name)
287 (substring control-buffer-name
288 (match-beginning 0) (match-end 0))
290 ediff-control-buffer-number
296 ediff-control-buffer-suffix
298 (string-match "[0-9]+" ediff-control-buffer-suffix)
301 (setq ediff-error-buffer (get-buffer-create (ediff-unique-buffer-name
302 "*ediff-errors" "*")))
304 (ediff-eval-in-buffer buffer-A (ediff-strip-mode-line-format))
305 (ediff-eval-in-buffer buffer-B (ediff-strip-mode-line-format))
307 (ediff-eval-in-buffer buffer-C (ediff-strip-mode-line-format)))
309 (ediff-save-protected-variables) ; save variables to be restored on exit
311 ;; ediff-setup-diff-regions-function must be set after setup
312 ;; parameters are processed.
313 (setq ediff-setup-diff-regions-function
315 'ediff-setup-diff-regions3
316 'ediff-setup-diff-regions))
318 (setq ediff-wide-bounds
319 (list (ediff-make-bullet-proof-overlay
320 '(point-min) '(point-max) ediff-buffer-A)
321 (ediff-make-bullet-proof-overlay
322 '(point-min) '(point-max) ediff-buffer-B)
323 (ediff-make-bullet-proof-overlay
324 '(point-min) '(point-max) ediff-buffer-C)))
326 ;; This has effect only on ediff-windows/regions
327 ;; In all other cases, ediff-visible-region sets visibility bounds to
328 ;; ediff-wide-bounds, and ediff-narrow-bounds are ignored.
329 (if ediff-start-narrowed
330 (setq ediff-visible-bounds ediff-narrow-bounds)
331 (setq ediff-visible-bounds ediff-wide-bounds))
333 (ediff-set-keys) ; comes after parameter setup
335 ;; set up ediff-narrow-bounds, if not set
336 (or ediff-narrow-bounds
337 (setq ediff-narrow-bounds ediff-wide-bounds))
339 ;; All these must be inside ediff-eval-in-buffer control-buffer,
340 ;; since these vars are local to control-buffer
341 ;; These won't run if there are errors in diff
342 (ediff-eval-in-buffer ediff-buffer-A
343 (ediff-nuke-selective-display)
344 (run-hooks 'ediff-prepare-buffer-hooks)
345 (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
346 (setq buffer-read-only t))
347 ;; add control-buffer to the list of sessions--no longer used, but may
348 ;; be used again in the future
349 (or (memq control-buffer ediff-this-buffer-control-sessions)
350 (setq ediff-this-buffer-control-sessions
351 (cons control-buffer ediff-this-buffer-control-sessions)))
353 (ediff-eval-in-buffer ediff-buffer-B
354 (ediff-nuke-selective-display)
355 (run-hooks 'ediff-prepare-buffer-hooks)
356 (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
357 (setq buffer-read-only t))
358 ;; add control-buffer to the list of sessions
359 (or (memq control-buffer ediff-this-buffer-control-sessions)
360 (setq ediff-this-buffer-control-sessions
361 (cons control-buffer ediff-this-buffer-control-sessions)))
364 (ediff-eval-in-buffer ediff-buffer-C
365 (ediff-nuke-selective-display)
366 (run-hooks 'ediff-prepare-buffer-hooks)
367 ;; add control-buffer to the list of sessions
368 (or (memq control-buffer ediff-this-buffer-control-sessions)
369 (setq ediff-this-buffer-control-sessions
371 ediff-this-buffer-control-sessions)))
374 ;; must come after setting up ediff-narrow-bounds AND after
375 ;; nuking selective display
376 (funcall ediff-setup-diff-regions-function file-A file-B file-C)
377 (setq ediff-number-of-differences (length ediff-difference-vector-A))
378 (setq ediff-current-difference -1)
380 (ediff-make-current-diff-overlay 'A)
381 (ediff-make-current-diff-overlay 'B)
383 (ediff-make-current-diff-overlay 'C))
385 (if (ediff-window-display-p)
386 (ediff-init-var-faces))
388 (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
390 (let ((shift-A (ediff-overlay-start
391 (ediff-get-value-according-to-buffer-type
392 'A ediff-narrow-bounds)))
393 (shift-B (ediff-overlay-start
394 (ediff-get-value-according-to-buffer-type
395 'B ediff-narrow-bounds)))
396 (shift-C (ediff-overlay-start
397 (ediff-get-value-according-to-buffer-type
398 'C ediff-narrow-bounds))))
399 ;; position point in buf A
401 (select-window ediff-window-A)
403 ;; position point in buf B
405 (select-window ediff-window-B)
409 (select-window ediff-window-C)
410 (goto-char shift-C)))
413 (select-window ediff-control-window)
414 (ediff-visible-region)
416 ;; The following is a hack to placate OS/2
417 ;; The problem is that OS/2 doesn't let us delete files used by other
418 ;; processes. Thus, in ediff-buffers and other functions, we can't
419 ;; delete temp files because they might be used by the asynchronous
420 ;; process that computes custom diffs. So, under OS/1 we have to wait
421 ;; for some time until custom diffs are done.
422 (if (eq system-type 'emx)
423 (ediff-eval-in-buffer ediff-custom-diff-buffer
424 (let ((proc (get-buffer-process (current-buffer))))
425 (while (and (processp proc)
426 (eq (process-status proc) 'run))
427 (message "Waiting for the diff program to quit")
432 (run-hooks 'startup-hooks 'ediff-startup-hooks)
433 (ediff-refresh-mode-lines)
434 (setq buffer-read-only t))
438 ;; This function assumes that we are in the window where control buffer is
440 (defun ediff-setup-control-buffer (ctl-buf)
441 "Set up window for control buffer."
442 (if (window-dedicated-p (selected-window))
443 (set-buffer ctl-buf) ; we are in control frame but just in case
444 (switch-to-buffer ctl-buf))
445 (let ((window-min-height 2))
447 (ediff-set-help-message)
448 (insert ediff-help-message)
449 (shrink-window-if-larger-than-buffer)
450 (or (ediff-multiframe-setup-p)
451 (ediff-indent-help-message))
452 (set-buffer-modified-p nil)
453 (ediff-refresh-mode-lines)
454 (setq ediff-control-window (selected-window))
455 (setq ediff-window-config-saved
456 (format "%S%S%S%S%S%S%S"
461 ediff-split-window-function
462 (ediff-multiframe-setup-p)
463 ediff-wide-display-p))
464 (goto-char (point-min))
465 (skip-chars-forward ediff-whitespace)))
467 ;; assuming we are in control window, calculate length of the first line in
469 (defun ediff-help-message-line-length ()
471 (goto-char (point-min))
472 (if ediff-prefer-long-help-message
478 (defun ediff-indent-help-message ()
479 (let* ((shift (/ (max 0 (- (window-width (selected-window))
480 (ediff-help-message-line-length)))
482 (str (make-string shift ?\ )))
484 (goto-char (point-min))
485 (while (< (point) (point-max))
491 (defun ediff-set-help-message ()
492 (setq ediff-long-help-message
493 (cond ((and ediff-long-help-message-custom
494 (or (symbolp ediff-long-help-message-custom)
495 (consp ediff-long-help-message-custom)))
496 (funcall ediff-long-help-message-custom))
498 (concat ediff-long-help-message-head
499 ediff-long-help-message-word-mode
500 ediff-long-help-message-tail))
502 (concat ediff-long-help-message-head
503 ediff-long-help-message-narrow2
504 ediff-long-help-message-tail))
506 (concat ediff-long-help-message-head
507 ediff-long-help-message-merge
508 ediff-long-help-message-tail))
510 (concat ediff-long-help-message-head
511 ediff-long-help-message-compare3
512 ediff-long-help-message-tail))
514 (concat ediff-long-help-message-head
515 ediff-long-help-message-compare2
516 ediff-long-help-message-tail))))
517 (setq ediff-brief-help-message
518 (cond ((and ediff-brief-help-message-custom
519 (or (symbolp ediff-brief-help-message-custom)
520 (consp ediff-brief-help-message-custom)))
521 (funcall ediff-brief-help-message-custom))
522 ((stringp ediff-brief-help-message-custom)
523 ediff-brief-help-message-custom)
524 ((ediff-multiframe-setup-p) ediff-brief-message-string)
525 (t ; long brief msg, not multiframe --- put in the middle
526 ediff-brief-message-string)
528 (setq ediff-help-message (if ediff-prefer-long-help-message
529 ediff-long-help-message
530 ediff-brief-help-message))
531 (run-hooks 'ediff-display-help-hooks)
537 ;;; Commands for working with Ediff
539 (defun ediff-update-diffs ()
540 "Recompute difference regions in buffers A, B, and C.
541 Buffers are not synchronized with their respective files, so changes done
542 to these buffers are not saved at this point---the user can do this later,
545 (let ((point-A (ediff-eval-in-buffer ediff-buffer-A (point)))
546 ;;(point-B (ediff-eval-in-buffer ediff-buffer-B (point)))
547 (tmp-buffer (get-buffer-create ediff-tmp-buffer))
549 (file-name-nondirectory (or (buffer-file-name ediff-buffer-A)
550 (buffer-name ediff-buffer-A)
553 (file-name-nondirectory (or (buffer-file-name ediff-buffer-B)
554 (buffer-name ediff-buffer-B)
557 (file-name-nondirectory (or (buffer-file-name ediff-buffer-C)
558 ;; if (null ediff-buffer-C), there is
559 ;; no danger, since we later check if
560 ;; ediff-buffer-C is alive
561 (buffer-name ediff-buffer-C)
563 (overl-A (ediff-get-value-according-to-buffer-type
564 'A ediff-narrow-bounds))
565 (overl-B (ediff-get-value-according-to-buffer-type
566 'B ediff-narrow-bounds))
567 (overl-C (ediff-get-value-according-to-buffer-type
568 'C ediff-narrow-bounds))
569 beg-A end-A beg-B end-B beg-C end-C
570 file-A file-B file-C)
571 (ediff-unselect-and-select-difference -1)
573 (setq beg-A (ediff-overlay-start overl-A)
574 beg-B (ediff-overlay-start overl-B)
575 beg-C (ediff-overlay-start overl-C)
576 end-A (ediff-overlay-end overl-A)
577 end-B (ediff-overlay-end overl-B)
578 end-C (ediff-overlay-end overl-C))
582 (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
583 (ediff-eval-in-buffer tmp-buffer
584 (setq file-A (ediff-make-temp-file "regA")))
585 (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
586 (ediff-eval-in-buffer tmp-buffer
587 (setq file-B (ediff-make-temp-file "regB")))
590 (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
591 (ediff-eval-in-buffer tmp-buffer
592 (setq file-C (ediff-make-temp-file "regC")))))
595 (ediff-eval-in-buffer ediff-buffer-A
596 (setq file-A (ediff-make-temp-file buf-A-file-name)))
597 (ediff-eval-in-buffer ediff-buffer-B
598 (setq file-B (ediff-make-temp-file buf-B-file-name)))
600 (ediff-eval-in-buffer ediff-buffer-C
601 (setq file-C (ediff-make-temp-file buf-C-file-name))))
604 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
605 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
606 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
607 (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
609 ;; In case of merge job, full it into thinking that it is just doing
611 (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
612 (ediff-job-name ediff-job-name))
614 (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
615 ediff-job-name 'ediff-files3))
616 (funcall ediff-setup-diff-regions-function file-A file-B file-C))
618 (setq ediff-number-of-differences (length ediff-difference-vector-A))
622 (delete-file file-C))
625 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
627 (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
631 ;; Not bound to any key---to dangerous. A user can do it if necessary.
632 (defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
633 "Revert buffers A, B and C. Then rerun Ediff on file A and file B."
635 (let ((bufA ediff-buffer-A)
636 (bufB ediff-buffer-B)
637 (bufC ediff-buffer-C)
638 (ctl-buf ediff-control-buffer)
639 (ancestor-buf ediff-ancestor-buffer)
640 (ancestor-job ediff-merge-with-ancestor-job)
641 (merge ediff-merge-job)
642 (comparison ediff-3way-comparison-job))
643 (ediff-eval-in-buffer bufA
644 (revert-buffer t noconfirm))
645 (ediff-eval-in-buffer bufB
646 (revert-buffer t noconfirm))
647 ;; this should only be executed in a 3way comparison, not in merge
649 (ediff-eval-in-buffer bufC
650 (revert-buffer t noconfirm)))
657 (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
658 (ediff-merge-buffers bufA bufB)))
659 (ediff-update-diffs))))
662 ;; optional NO-REHIGHLIGHT says to not rehighlight buffers
663 (defun ediff-recenter (&optional no-rehighlight)
664 "Bring the highlighted region of all buffers being compared into view.
665 Reestablish the default three-window display."
668 ;; force all minibuffer to display ediff's messages.
669 ;; when xemacs implements minibufferless frames, this won't be necessary
670 (if ediff-xemacs-p (setq synchronize-minibuffers t))
672 (setq ediff-disturbed-overlays nil) ; clear after use
673 (let (buffer-read-only)
674 (if (and (ediff-buffer-live-p ediff-buffer-A)
675 (ediff-buffer-live-p ediff-buffer-B)
676 (or (not ediff-3way-job)
677 (ediff-buffer-live-p ediff-buffer-C)))
679 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
680 (or (eq this-command 'ediff-quit)
682 "You've killed an essential Ediff buffer---Please quit Ediff"
686 ;; set visibility range appropriate to this invocation of Ediff.
687 (ediff-visible-region)
690 (if (and (ediff-window-display-p)
691 (symbolp this-command)
692 (symbolp last-command)
693 ;; Either one of the display-changing commands
694 (or (memq this-command
696 ediff-toggle-wide-display ediff-toggle-multiframe))
697 ;; Or one of the movement cmds and prev cmd was an Ediff cmd
698 ;; This avoids rasing frames unnecessarily.
699 (and (memq this-command
700 '(ediff-next-difference
701 ediff-previous-difference
702 ediff-jump-to-difference
703 ediff-jump-to-difference-at-point))
704 (not (string-match "^ediff-" (symbol-name last-command)))
707 (if (window-live-p ediff-window-A)
708 (raise-frame (window-frame ediff-window-A)))
709 (if (window-live-p ediff-window-B)
710 (raise-frame (window-frame ediff-window-B)))
711 (if (window-live-p ediff-window-C)
712 (raise-frame (window-frame ediff-window-C)))))
713 (if (and (ediff-window-display-p)
714 (frame-live-p ediff-control-frame)
715 (not (ediff-frame-iconified-p ediff-control-frame)))
716 (raise-frame ediff-control-frame))
718 ;; Redisplay whatever buffers are showing, if there is a selected difference
719 (let* ((control-frame ediff-control-frame)
720 (control-buf ediff-control-buffer))
721 (if (and (ediff-buffer-live-p ediff-buffer-A)
722 (ediff-buffer-live-p ediff-buffer-B)
723 (or (not ediff-3way-job)
724 (ediff-buffer-live-p ediff-buffer-C))
725 (ediff-valid-difference-p))
728 (ediff-select-difference ediff-current-difference))
730 (ediff-recenter-one-window 'A)
731 (ediff-recenter-one-window 'B)
733 (ediff-recenter-one-window 'C))
735 (if (and (ediff-multiframe-setup-p)
736 (not (ediff-frame-iconified-p ediff-control-frame)))
738 (ediff-reset-mouse control-frame)
740 (cond ((eq (ediff-device-type) 'ns)
741 (unfocus-frame (selected-frame)))
742 (t (unfocus-frame))))
745 (ediff-eval-in-buffer control-buf
746 (ediff-refresh-mode-lines))
749 ;; this function returns to the window it was called from
750 ;; (which was the control window)
751 (defun ediff-recenter-one-window (buf-type)
752 (let* (;; context must be saved before switching to windows A/B/C
753 (ctl-wind (selected-window))
754 (shift (ediff-overlay-start
755 (ediff-get-value-according-to-buffer-type
756 buf-type ediff-narrow-bounds)))
757 (job-name ediff-job-name)
758 (control-buf ediff-control-buffer)
759 (window-name (intern (format "ediff-window-%S" buf-type)))
760 (window (if (window-live-p (symbol-value window-name))
761 (symbol-value window-name))))
763 (if (and window ediff-windows-job)
764 (set-window-start window shift))
767 (select-window window)
768 (ediff-deactivate-mark)
769 (ediff-position-region
770 (ediff-get-diff-posn buf-type 'beg nil control-buf)
771 (ediff-get-diff-posn buf-type 'end nil control-buf)
772 (ediff-get-diff-posn buf-type 'beg nil control-buf)
775 (select-window ctl-wind)
779 ;; This will have to be refined for 3way jobs
780 (defun ediff-toggle-split ()
781 "Toggle vertical/horizontal window split.
782 Does nothing if file-A and file-B are in different frames."
784 (let* ((wind-A (if (window-live-p ediff-window-A) ediff-window-A))
785 (wind-B (if (window-live-p ediff-window-B) ediff-window-B))
786 (wind-C (if (window-live-p ediff-window-C) ediff-window-C))
787 (frame-A (if wind-A (window-frame wind-A)))
788 (frame-B (if wind-B (window-frame wind-B)))
789 (frame-C (if wind-C (window-frame wind-C))))
790 (if (or (eq frame-A frame-B)
791 (not (frame-live-p frame-A))
792 (not (frame-live-p frame-B))
793 (if ediff-3way-comparison-job
794 (or (not (frame-live-p frame-C))
795 (eq frame-A frame-C) (eq frame-B frame-C))))
796 (setq ediff-split-window-function
797 (if (eq ediff-split-window-function 'split-window-vertically)
798 'split-window-horizontally
799 'split-window-vertically))
800 (message "Buffers being compared are in different frames"))
801 (ediff-recenter 'no-rehighlight)))
803 (defun ediff-toggle-hilit ()
804 "Switch between highlighting using ASCII flags and highlighting using faces.
805 On a dumb terminal, switches between ASCII highlighting and no highlighting."
807 (if (not (ediff-window-display-p))
808 (if (eq ediff-highlighting-style 'ascii)
810 (message "ASCII highlighting flags removed")
811 (ediff-unselect-and-select-difference ediff-current-difference
813 (setq ediff-highlighting-style 'off))
814 (ediff-unselect-and-select-difference ediff-current-difference
816 (ediff-unselect-and-select-difference ediff-current-difference
818 ;; cycle through highlighting
819 (cond ((and ediff-use-faces ediff-highlight-all-diffs)
820 (message "Unhighlighting unselected difference regions")
821 (setq ediff-highlight-all-diffs nil))
823 (message "Highlighting with ASCII flags")
824 (setq ediff-use-faces nil))
826 (message "Re-highlighting all difference regions")
827 (setq ediff-use-faces t
828 ediff-highlight-all-diffs t)))
830 (if (and ediff-use-faces ediff-highlight-all-diffs)
831 (if (not (face-differs-from-default-p 'ediff-odd-diff-face-A-var))
833 (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
834 (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
835 (copy-face ediff-odd-diff-face-C 'ediff-odd-diff-face-C-var)
836 (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
837 (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)
838 (copy-face ediff-even-diff-face-C 'ediff-even-diff-face-C-var)
840 (copy-face 'default 'ediff-odd-diff-face-A-var)
841 (copy-face 'default 'ediff-odd-diff-face-B-var)
842 (copy-face 'default 'ediff-odd-diff-face-C-var)
843 (copy-face 'default 'ediff-even-diff-face-A-var)
844 (copy-face 'default 'ediff-even-diff-face-B-var)
845 (copy-face 'default 'ediff-even-diff-face-C-var))
847 (ediff-unselect-and-select-difference
848 ediff-current-difference 'select-only))
851 (defun ediff-toggle-autorefine ()
852 "Toggle auto-refine mode."
855 (error "No fine differences in this mode"))
856 (cond ((eq ediff-auto-refine 'nix)
857 (setq ediff-auto-refine 'on)
858 (ediff-make-fine-diffs ediff-current-difference 'noforce)
859 (message "Auto-refining is ON"))
860 ((eq ediff-auto-refine 'on)
861 (message "Auto-refining is OFF")
862 (setq ediff-auto-refine 'off))
864 (ediff-set-fine-diff-properties ediff-current-difference 'default)
865 (message "Refinements are HIDDEN")
866 (setq ediff-auto-refine 'nix))
869 (defun ediff-make-or-kill-fine-diffs (arg)
870 "Compute fine diffs. With negative prefix arg, kill fine diffs.
871 In both cases, operates on the currrent difference region."
874 (ediff-clear-fine-differences ediff-current-difference))
875 ((and (numberp arg) (< arg 0))
876 (ediff-clear-fine-differences ediff-current-difference))
877 (t (ediff-make-fine-diffs))))
880 (defun ediff-toggle-help ()
881 "Toggle short/long help message."
883 (let (buffer-read-only)
885 (setq ediff-prefer-long-help-message (not ediff-prefer-long-help-message))
886 (ediff-set-help-message))
887 ;; remember the icon status of the control frame when the user requested
888 ;; full control message
889 (if (and ediff-prefer-long-help-message (ediff-multiframe-setup-p))
890 (setq ediff-prefer-iconified-control-frame
891 (ediff-frame-iconified-p ediff-control-frame)))
893 (setq ediff-window-config-saved "") ; force redisplay
894 (ediff-recenter 'no-rehighlight))
897 ;; If BUF, this is the buffer to toggle, not current buffer.
898 (defun ediff-toggle-read-only (&optional buf)
899 "Toggle read-only in current buffer.
900 If buffer is under version control and locked, check it out first.
901 If optional argument BUF is specified, toggle read-only in that buffer instead
902 of the current buffer."
904 (let ((ctl-buf (if (null buf) (current-buffer))))
905 (or buf (ediff-recenter))
908 (ediff-get-buffer (ediff-char-to-buftype last-command-char))))
910 (ediff-eval-in-buffer buf ; eval in buf A/B/C
911 (let* ((file (buffer-file-name buf))
912 (file-writable (and file
914 (file-writable-p file)))
915 (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
916 ((ediff-file-checked-out-p file)
918 (file-writable 'toggle-read-only)
919 (t (key-binding "\C-x\C-q")))))
920 ;; If the file is checked in, make sure we don't make buffer modifiable
921 ;; without warning the user. The user can fool our checks by making the
922 ;; buffer non-RO without checking the file out. We regard this as a
924 (if (and (ediff-file-checked-in-p file)
925 ;; If ctl-buf is null, this means we called this
926 ;; non-interactively, in which case don't ask questions
928 (cond ((not buffer-read-only)
929 (setq toggle-ro-cmd 'toggle-read-only))
930 ((and (or (beep 1) t) ; always beep
933 "File %s is under version control. Check it out? "
934 (abbreviate-file-name file))))
935 ;; if we checked the file out, we should also change the
936 ;; original state of buffer-read-only to nil. If we don't
937 ;; do this, the mode line will show %%, since the file was
938 ;; RO before ediff started, so the user will think the file
940 (ediff-eval-in-buffer ctl-buf
941 (ediff-change-saved-variable
942 'buffer-read-only nil
943 (ediff-char-to-buftype last-command-char))))
945 (setq toggle-ro-cmd 'toggle-read-only)
948 "Boy, this is risky! Better don't change this file...")
950 (if (and toggle-ro-cmd
951 (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
953 (save-window-excursion
954 (command-execute toggle-ro-cmd)))
955 (error "Don't know how to toggle read-only in buffer %S" buf))
957 ;; Check if we made the current buffer updatable, but its file is RO.
958 ;; Signal a warning in this case.
959 (if (and file (not buffer-read-only)
960 (eq this-command 'ediff-toggle-read-only)
962 (not (file-writable-p file)))
963 (message "Warning: file %s is read-only"
964 (abbreviate-file-name file) (beep 1)))
968 ;; This is a simple-minded check for whether a file is under version control
969 ;; and is checked out.
970 ;; If file,v exists but file doesn't, this file is considered to be not checked
971 ;; in and not checked out for the purpose of patching (since patch won't be
972 ;; able to read such a file anyway).
973 ;; FILE is a string representing file name
974 (defsubst ediff-file-checked-out-p (file)
977 (file-writable-p file)
978 (file-exists-p (concat file ",v"))))
979 (defsubst ediff-file-checked-in-p (file)
982 (not (file-writable-p file))
983 (file-exists-p (concat file ",v"))))
985 (defun ediff-swap-buffers ()
986 "Rotate the display of buffers A, B, and C."
988 (if (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
989 (let ((buf ediff-buffer-A)
990 (values ediff-buffer-values-orig-A)
991 (diff-vec ediff-difference-vector-A)
992 (hide-regexp ediff-regexp-hide-A)
993 (focus-regexp ediff-regexp-focus-A)
994 (wide-visibility-p (eq ediff-visible-bounds ediff-wide-bounds))
995 (overlay (if (ediff-window-display-p)
996 ediff-current-diff-overlay-A)))
997 (if ediff-3way-comparison-job
999 (set-window-buffer ediff-window-A ediff-buffer-C)
1000 (set-window-buffer ediff-window-B ediff-buffer-A)
1001 (set-window-buffer ediff-window-C ediff-buffer-B)
1003 (set-window-buffer ediff-window-A ediff-buffer-B)
1004 (set-window-buffer ediff-window-B ediff-buffer-A))
1005 ;; swap diff buffers
1006 (if ediff-3way-comparison-job
1007 (setq ediff-buffer-A ediff-buffer-C
1008 ediff-buffer-C ediff-buffer-B
1010 (setq ediff-buffer-A ediff-buffer-B
1011 ediff-buffer-B buf))
1013 ;; swap saved buffer characteristics
1014 (if ediff-3way-comparison-job
1015 (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-C
1016 ediff-buffer-values-orig-C ediff-buffer-values-orig-B
1017 ediff-buffer-values-orig-B values)
1018 (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-B
1019 ediff-buffer-values-orig-B values))
1021 ;; swap diff vectors
1022 (if ediff-3way-comparison-job
1023 (setq ediff-difference-vector-A ediff-difference-vector-C
1024 ediff-difference-vector-C ediff-difference-vector-B
1025 ediff-difference-vector-B diff-vec)
1026 (setq ediff-difference-vector-A ediff-difference-vector-B
1027 ediff-difference-vector-B diff-vec))
1029 ;; swap hide/focus regexp
1030 (if ediff-3way-comparison-job
1031 (setq ediff-regexp-hide-A ediff-regexp-hide-C
1032 ediff-regexp-hide-C ediff-regexp-hide-B
1033 ediff-regexp-hide-B hide-regexp
1034 ediff-regexp-focus-A ediff-regexp-focus-C
1035 ediff-regexp-focus-C ediff-regexp-focus-B
1036 ediff-regexp-focus-B focus-regexp)
1037 (setq ediff-regexp-hide-A ediff-regexp-hide-B
1038 ediff-regexp-hide-B hide-regexp
1039 ediff-regexp-focus-A ediff-regexp-focus-B
1040 ediff-regexp-focus-B focus-regexp))
1042 ;; The following is needed for XEmacs, since there one can't move
1043 ;; overlay to another buffer. In Emacs, this swap is redundant.
1044 (if (ediff-window-display-p)
1045 (if ediff-3way-comparison-job
1046 (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-C
1047 ediff-current-diff-overlay-C ediff-current-diff-overlay-B
1048 ediff-current-diff-overlay-B overlay)
1049 (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-B
1050 ediff-current-diff-overlay-B overlay)))
1053 (setq ediff-wide-bounds
1054 (cond (ediff-3way-comparison-job
1055 (list (nth 2 ediff-wide-bounds)
1056 (nth 0 ediff-wide-bounds)
1057 (nth 1 ediff-wide-bounds)))
1059 (list (nth 1 ediff-wide-bounds)
1060 (nth 0 ediff-wide-bounds)
1061 (nth 2 ediff-wide-bounds)))
1063 (list (nth 1 ediff-wide-bounds)
1064 (nth 0 ediff-wide-bounds)))))
1065 ;; swap narrow bounds
1066 (setq ediff-narrow-bounds
1067 (cond (ediff-3way-comparison-job
1068 (list (nth 2 ediff-narrow-bounds)
1069 (nth 0 ediff-narrow-bounds)
1070 (nth 1 ediff-narrow-bounds)))
1072 (list (nth 1 ediff-narrow-bounds)
1073 (nth 0 ediff-narrow-bounds)
1074 (nth 2 ediff-narrow-bounds)))
1076 (list (nth 1 ediff-narrow-bounds)
1077 (nth 0 ediff-narrow-bounds)))))
1078 (if wide-visibility-p
1079 (setq ediff-visible-bounds ediff-wide-bounds)
1080 (setq ediff-visible-bounds ediff-narrow-bounds))
1083 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
1084 (ediff-recenter 'no-rehighlight)
1088 (defun ediff-toggle-wide-display ()
1089 "Toggle wide/regular display.
1090 This is especially useful when comparing buffers side-by-side."
1092 (or (ediff-window-display-p)
1093 (error "%sEmacs is not running as a window application"
1094 (if ediff-emacs-p "" "X")))
1095 (ediff-recenter 'no-rehighlight) ; make sure buffs are displayed in windows
1096 (let ((ctl-buf ediff-control-buffer))
1097 (setq ediff-wide-display-p (not ediff-wide-display-p))
1098 (if (not ediff-wide-display-p)
1099 (ediff-eval-in-buffer ctl-buf
1100 (modify-frame-parameters
1101 ediff-wide-display-frame ediff-wide-display-orig-parameters)
1102 (sit-for (if ediff-xemacs-p 0.4 0))
1103 ;; restore control buf, since ctl window may have been deleted
1105 (set-buffer ctl-buf)
1106 (setq ediff-wide-display-orig-parameters nil
1107 ediff-window-B nil) ; force update of window config
1108 (ediff-recenter 'no-rehighlight))
1109 (funcall ediff-make-wide-display-function)
1110 (sit-for (if ediff-xemacs-p 0.4 0))
1111 (ediff-eval-in-buffer ctl-buf
1112 (setq ediff-window-B nil) ; force update of window config
1113 (ediff-recenter 'no-rehighlight)))))
1115 (defun ediff-toggle-multiframe ()
1116 "Switch from the multiframe display to single-frame display and back.
1117 This is primarily for debugging, but one can use it for fun, too."
1119 (or (ediff-window-display-p)
1120 (error "%sEmacs is not running as a window application"
1121 (if ediff-emacs-p "" "X")))
1122 (cond ((eq ediff-window-setup-function 'ediff-setup-windows-multiframe)
1123 (setq ediff-window-setup-function 'ediff-setup-windows-plain))
1124 ((eq ediff-window-setup-function 'ediff-setup-windows-plain)
1125 (setq ediff-window-setup-function 'ediff-setup-windows-multiframe)))
1126 (setq ediff-window-B nil)
1127 (ediff-recenter 'no-rehighlight))
1131 (defun ediff-toggle-show-clashes-only ()
1132 "Toggle the mode where only the regions where both buffers differ with the ancestor are shown."
1134 (if (not ediff-merge-with-ancestor-job)
1135 (error "This command makes sense only when merging with an ancestor"))
1136 (setq ediff-show-clashes-only (not ediff-show-clashes-only))
1137 (if ediff-show-clashes-only
1138 (message "Focus on regions where both buffers differ from the ancestor")
1139 (message "Canceling focus on regions where changes clash")))
1141 ;; Widening/narrowing
1143 (defun ediff-toggle-narrow-region ()
1144 "Toggle narrowing in buffers A, B, and C.
1145 Used in ediff-windows/regions only."
1147 (if (eq ediff-buffer-A ediff-buffer-B)
1149 "Buffers A and B are the same. Can't narrow to two different regions"))
1150 (if (eq ediff-visible-bounds ediff-wide-bounds)
1151 (setq ediff-visible-bounds ediff-narrow-bounds)
1152 (setq ediff-visible-bounds ediff-wide-bounds))
1153 (ediff-recenter 'no-rehighlight))
1155 ;; Narrow bufs A/B/C to ediff-visible-bounds. If this is currently set to
1156 ;; ediff-wide-bounds, then this actually widens.
1157 ;; This function does nothing if job-name is not
1158 ;; ediff-regions-wordwise/linewise or ediff-windows-wordwise/linewise.
1159 ;; Does nothing if buffer-A = buffer-B since we can't narrow
1160 ;; to two different regions in one buffer.
1161 (defun ediff-visible-region ()
1162 (if (or (eq ediff-buffer-A ediff-buffer-B)
1163 (eq ediff-buffer-A ediff-buffer-C)
1164 (eq ediff-buffer-C ediff-buffer-B))
1166 ;; If ediff-*-regions/windows, ediff-visible-bounds is already set
1167 ;; Otherwise, always use full range.
1168 (if (not ediff-narrow-job)
1169 (setq ediff-visible-bounds ediff-wide-bounds))
1170 (let ((overl-A (ediff-get-value-according-to-buffer-type
1171 'A ediff-visible-bounds))
1172 (overl-B (ediff-get-value-according-to-buffer-type
1173 'B ediff-visible-bounds))
1174 (overl-C (ediff-get-value-according-to-buffer-type
1175 'C ediff-visible-bounds))
1177 (ediff-eval-in-buffer ediff-buffer-A
1179 (ediff-overlay-start overl-A) (ediff-overlay-end overl-A)))
1180 (ediff-eval-in-buffer ediff-buffer-B
1182 (ediff-overlay-start overl-B) (ediff-overlay-end overl-B)))
1185 (ediff-eval-in-buffer ediff-buffer-C
1187 (ediff-overlay-start overl-C) (ediff-overlay-end overl-C))))
1191 ;; Window scrolling operations
1193 ;; Performs some operation on the two file windows (if they are showing).
1194 ;; Traps all errors on the operation in windows A/B/C.
1195 ;; Usually, errors come from scrolling off the
1196 ;; beginning or end of the buffer, and this gives error messages.
1197 (defun ediff-operate-on-windows (operation arg)
1199 ;; make sure windows aren't dead
1200 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1201 (ediff-recenter 'no-rehighlight))
1202 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1203 (ediff-buffer-live-p ediff-buffer-B)
1204 (or (not ediff-3way-job) ediff-buffer-C)
1206 (error "You've killed an essential Ediff buffer---Please quit Ediff"))
1208 (let* ((wind (selected-window))
1209 (wind-A ediff-window-A)
1210 (wind-B ediff-window-B)
1211 (wind-C ediff-window-C)
1212 (three-way ediff-3way-job))
1214 (select-window wind-A)
1216 (funcall operation arg)
1218 (select-window wind-B)
1220 (funcall operation arg)
1224 (select-window wind-C)
1226 (funcall operation arg)
1229 (select-window wind)))
1231 (defun ediff-scroll-vertically (&optional arg)
1232 "Vertically scroll buffers A, B \(and C if appropriate\).
1233 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
1234 the height of window-A."
1237 ;; make sure windows aren't dead
1238 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1239 (ediff-recenter 'no-rehighlight))
1240 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1241 (ediff-buffer-live-p ediff-buffer-B)
1242 (or (not ediff-3way-job)
1243 (ediff-buffer-live-p ediff-buffer-C))
1245 (error "You've killed an essential Ediff buffer---Please quit Ediff"))
1247 (ediff-operate-on-windows
1248 (if (memq last-command-char '(?v ?\C-v))
1251 ;; calculate argument to scroll-up/down
1252 ;; if there is an explicit argument
1253 (if (and arg (not (equal arg '-)))
1255 (prefix-numeric-value arg)
1256 ;; if not, see if we can determine a default amount (the window height)
1257 (let* (default-amount)
1258 (setq default-amount
1259 (- (min (window-height ediff-window-A)
1260 (window-height ediff-window-B)
1262 (window-height ediff-window-C)
1263 123) ; some large number
1265 1 next-screen-context-lines))
1268 ;; C-u as argument means half of default amount
1269 (/ default-amount 2)
1270 ;; no argument means default amount
1274 (defun ediff-scroll-horizontally (&optional arg)
1275 "Horizontally scroll buffers A, B \(and C if appropriate\).
1276 If an argument is given, that is how many columns are scrolled, else nearly
1277 the width of the A/B/C windows."
1280 ;; make sure windows aren't dead
1281 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
1282 (ediff-recenter 'no-rehighlight))
1283 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1284 (ediff-buffer-live-p ediff-buffer-B)
1285 (or (not ediff-3way-job)
1286 (ediff-buffer-live-p ediff-buffer-C))
1288 (error "You've killed an essential Ediff buffer---Please quit Ediff"))
1290 (ediff-operate-on-windows
1291 (if (= last-command-char ?<)
1294 ;; calculate argument to scroll-left/right
1295 ;; if there is an explicit argument
1296 (if (and arg (not (equal arg '-)))
1298 (prefix-numeric-value arg)
1299 ;; if not, see if we can determine a default amount
1300 ;; (half the window width)
1301 (if (null ediff-control-window)
1302 ;; no control window, use nil
1304 (let ((default-amount
1305 (- (/ (min (window-width ediff-window-A)
1306 (window-width ediff-window-B)
1307 (if ediff-3way-comparison-job
1308 (window-width ediff-window-C)
1309 500) ; some large number
1315 ;; C-u as argument means half of default amount
1316 (/ default-amount 2)
1317 ;; no argument means default amount
1318 default-amount))))))
1321 ;;BEG, END show the region to be positioned.
1322 ;;JOB-NAME holds ediff-job-name. Ediff-windows job positions regions
1324 (defun ediff-position-region (beg end pos job-name)
1325 (if (> end (point-max))
1326 (setq end (point-max)))
1327 (if ediff-windows-job
1328 (if (pos-visible-in-window-p end)
1329 () ; do nothing, wind is already positioned
1330 ;; at this point, windows are positioned at the beginning of the
1331 ;; file regions (not diff-regions) being compared.
1333 (move-to-window-line (- (window-height) 2))
1334 (let ((amount (+ 2 (count-lines (point) end))))
1335 (scroll-up amount))))
1336 (set-window-start (selected-window) beg)
1337 (if (pos-visible-in-window-p end)
1338 ;; Determine the number of lines that the region occupies
1341 (while ( and (> end (progn
1342 (move-to-window-line lines)
1344 ;; `end' may be beyond the window bottom, so check
1345 ;; that we are making progres
1346 (< prev-point (point)))
1347 (setq prev-point (point))
1348 (setq lines (1+ lines)))
1349 ;; And position the beginning on the right line
1351 (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
1360 (defun ediff-next-difference (&optional arg)
1361 "Advance to the next difference.
1362 With a prefix argument, go back that many differences."
1364 (if (< ediff-current-difference ediff-number-of-differences)
1365 (let ((n (min ediff-number-of-differences
1366 (+ ediff-current-difference (if arg arg 1))))
1369 (or (>= n ediff-number-of-differences)
1370 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1371 (ediff-install-fine-diff-if-necessary n))
1372 (while (and (< n ediff-number-of-differences)
1376 ;; skip clashes, if necessary
1377 (and ediff-show-clashes-only
1378 (string-match "prefer"
1379 (or (ediff-get-state-of-merge n) "")))
1380 ;; skip difference regions that differ in white space
1381 (and ediff-ignore-similar-regions
1382 (ediff-no-fine-diffs-p n))))
1384 (if (= 0 (mod n 20))
1385 (message "Skipped over region %d and counting ..." n))
1386 (or (>= n ediff-number-of-differences)
1387 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1388 (ediff-install-fine-diff-if-necessary n))
1391 (ediff-unselect-and-select-difference n)
1393 (ediff-visible-region)
1394 (error "At end of the difference list")))
1396 (defun ediff-previous-difference (&optional arg)
1397 "Go to the previous difference.
1398 With a prefix argument, go back that many differences."
1400 (if (> ediff-current-difference -1)
1401 (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
1405 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1406 (ediff-install-fine-diff-if-necessary n))
1407 (while (and (> n -1)
1411 ;; skip clashes, if necessary
1412 (and ediff-show-clashes-only
1413 (string-match "prefer"
1414 (or (ediff-get-state-of-merge n) "")))
1415 ;; skip difference regions that differ in white space
1416 (and ediff-ignore-similar-regions
1417 (ediff-no-fine-diffs-p n))))
1418 (if (= 0 (mod (1+ n) 20))
1419 (message "Skipped over region %d and counting ..." (1+ n)))
1422 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1423 (ediff-install-fine-diff-if-necessary n))
1426 (ediff-unselect-and-select-difference n)
1428 (ediff-visible-region)
1429 (error "At beginning of the difference list")))
1431 (defun ediff-jump-to-difference (difference-number)
1432 "Go to the difference specified as a prefix argument."
1434 (setq difference-number (1- difference-number))
1435 (if (and (>= difference-number -1)
1436 (< difference-number (1+ ediff-number-of-differences)))
1437 (ediff-unselect-and-select-difference difference-number)
1438 (error "Bad difference number, %d" difference-number)))
1440 (defun ediff-jump-to-difference-at-point ()
1441 "Go to difference closest to the point in buffer A, B, or C.
1442 The type of buffer depends on last command character \(a, b, or c\) that
1443 invoked this command."
1445 (let ((buf-type (ediff-char-to-buftype last-command-char)))
1446 (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
1449 ;; find region most related to the current point position (or POS, if given)
1450 (defun ediff-diff-at-point (buf-type &optional pos)
1451 (let ((buffer (ediff-get-buffer buf-type))
1452 (ctl-buffer ediff-control-buffer)
1453 (max-dif-num (1- ediff-number-of-differences))
1460 (ediff-eval-in-buffer buffer
1461 (setq pos (or pos (point)))
1462 (while (and (or (< pos prev-beg) (> pos beg))
1463 (< diff-no max-dif-num))
1464 (setq diff-no (1+ diff-no))
1467 (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
1468 end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
1471 (if (< (abs (- pos prev-end))
1474 (1+ diff-no)) ; jump-to-diff works with diff nums higher by 1
1480 (defun ediff-diff-to-diff (arg &optional keys)
1481 "Copy buffer-X'th diff to buffer Y \(X,Y are A, B, or C\).
1482 If numerical prefix argument, copy this diff specified in the arg.
1483 Otherwise, copy the difference given by `ediff-current-difference'.
1484 This command assumes it is bound to a 2-character key sequence, `ab', `ba',
1485 `ac', etc., which is used to determine the types of buffers to be used for
1486 copying difference regions. The first character in the sequence specifies
1487 the source buffer and the second specifies the target.
1489 If the second optional argument, a 2-character string, is given, use it to
1490 determine the source and the target buffers instead of the command keys."
1492 (or keys (setq keys (this-command-keys)))
1494 (ediff-jump-to-difference arg))
1495 (let* ((key1 (aref keys 0))
1496 (key2 (aref keys 1))
1497 (char1 (if (and ediff-xemacs-p (eventp key1)) (event-key key1) key1))
1498 (char2 (if (and ediff-xemacs-p (eventp key1)) (event-key key2) key2)))
1499 (ediff-copy-diff ediff-current-difference
1500 (ediff-char-to-buftype char1)
1501 (ediff-char-to-buftype char2))
1502 (ediff-recenter 'no-rehighlight)))
1505 ;; Copy diff N from FROM-BUF-TYPE \(given as A, B or C\) to TO-BUF-TYPE.
1506 ;; If optional DO-NOT-SAVE is non-nil, do not save the old value of the
1507 ;; target diff. This is used in merging, when constructing the merged
1509 (defun ediff-copy-diff (n from-buf-type to-buf-type
1510 &optional batch-invocation reg-to-copy)
1511 (let* ((to-buf (ediff-get-buffer to-buf-type))
1512 ;;(from-buf (if (not reg-to-copy) (ediff-get-buffer from-buf-type)))
1513 (ctrl-buf ediff-control-buffer)
1515 (three-way ediff-3way-job)
1518 reg-to-delete reg-to-delete-beg reg-to-delete-end)
1520 (setq reg-to-delete-beg
1521 (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
1522 (setq reg-to-delete-end
1523 (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
1526 (setq from-buf-type nil)
1527 (setq reg-to-copy (ediff-get-region-contents n from-buf-type ctrl-buf)))
1529 (setq reg-to-delete (ediff-get-region-contents
1530 n to-buf-type ctrl-buf
1531 reg-to-delete-beg reg-to-delete-end))
1533 (setq ediff-disturbed-overlays nil) ; clear before use
1535 (if (string= reg-to-delete reg-to-copy)
1536 (setq saved-p nil) ; refuse to copy identical buffers
1538 (if (or batch-invocation (ediff-test-save-region n to-buf-type))
1539 (condition-case conds
1541 (ediff-eval-in-buffer to-buf
1542 ;; to prevent flags from interfering if buffer is writable
1543 (let ((inhibit-read-only (null buffer-read-only)))
1544 ;; these two insert a dummy char to overcome a bug in
1545 ;; XEmacs, which sometimes prevents 0-length extents
1546 ;; from sensing insertion at its end-points.
1549 (goto-char reg-to-delete-end)
1550 (insert-before-markers "@")))
1552 (goto-char reg-to-delete-end)
1553 (insert-before-markers reg-to-copy)
1555 ;; delete the dummy char "@"
1560 (if (> reg-to-delete-end reg-to-delete-beg)
1561 (kill-region reg-to-delete-beg
1563 (if (> reg-to-delete-end reg-to-delete-beg)
1564 (kill-region reg-to-delete-beg reg-to-delete-end)
1565 (ediff-move-disturbed-overlays reg-to-delete-beg)
1568 (or batch-invocation
1571 (ediff-save-diff-region n to-buf-type reg-to-delete))))
1572 (error (message "ediff-copy-diff: %s %s"
1574 (mapconcat 'prin1-to-string (cdr conds) " "))
1581 ;; adjust state of difference in case 3-way and diff was copied ok
1582 (if (and saved-p three-way)
1583 (ediff-set-state-of-diff-in-all-buffers n ctrl-buf))
1585 (if batch-invocation
1586 (ediff-clear-fine-differences n)
1587 ;; If diff3 job, we should recompute fine diffs so we clear them
1588 ;; before reinserting flags (and thus before ediff-recenter).
1589 (if (and saved-p three-way)
1590 (ediff-clear-fine-differences n))
1592 (ediff-refresh-mode-lines)
1594 ;; For diff2 jobs, don't recompute fine diffs, since we know there
1595 ;; aren't any. So we clear diffs after ediff-recenter.
1596 (if (and saved-p (not three-way))
1597 (ediff-clear-fine-differences n))
1598 ;; Make sure that the message about saving and how to restore is seen
1603 ;; Save Nth diff of buffer BUF-TYPE \(A, B, or C\).
1604 ;; That is to say, the Nth diff on the `ediff-killed-diffs-alist'. REG
1605 ;; is the region to save. It is redundant here, but is passed anyway, for
1607 (defun ediff-save-diff-region (n buf-type reg)
1608 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
1609 (buf (ediff-get-buffer buf-type))
1610 (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
1612 (if this-buf-n-th-diff-saved
1613 ;; either nothing saved for n-th diff and buffer or we OK'ed
1615 (setcdr this-buf-n-th-diff-saved reg)
1616 (if n-th-diff-saved ;; n-th diff saved, but for another buffer
1617 (nconc n-th-diff-saved (list (cons buf reg)))
1618 (setq ediff-killed-diffs-alist ;; create record for n-th diff
1619 (cons (list n (cons buf reg))
1620 ediff-killed-diffs-alist))))
1621 (message "Saving old diff region #%d of buffer %S. To recover, type `r%s'"
1624 "" (downcase (symbol-name buf-type))))
1627 ;; Test if saving Nth difference region of buffer BUF-TYPE is possible.
1628 (defun ediff-test-save-region (n buf-type)
1629 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
1630 (buf (ediff-get-buffer buf-type))
1631 (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
1633 (if this-buf-n-th-diff-saved
1636 "You've previously copied diff region %d to buffer %S. Confirm "
1642 (defun ediff-pop-diff (n buf-type)
1643 "Pop last killed Nth diff region from buffer BUF-TYPE."
1644 (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
1645 (buf (ediff-get-buffer buf-type))
1646 (saved-rec (assoc buf (cdr n-th-record)))
1647 (three-way ediff-3way-job)
1648 (ctl-buf ediff-control-buffer)
1650 saved-diff reg-beg reg-end recovered)
1653 (setq saved-diff (cdr saved-rec))
1654 (if (> ediff-number-of-differences 0)
1655 (error "Nothing saved for diff %d in buffer %S" (1+ n) buf-type)
1656 (error "No differences found")))
1658 (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
1659 (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
1660 (setq ediff-disturbed-overlays nil) ; clear before use
1662 (condition-case conds
1663 (ediff-eval-in-buffer buf
1664 (let ((inhibit-read-only (null buffer-read-only)))
1665 ;; these two insert a dummy char to overcome a bug in XEmacs,
1666 ;; which sometimes prevents 0-length extents from sensing
1667 ;; insertion at its end-points.
1671 (insert-before-markers "@")))
1674 (insert-before-markers saved-diff)
1676 ;; delete dummy char
1681 (if (> reg-end reg-beg)
1682 (kill-region reg-beg reg-end))
1683 (if (> reg-end reg-beg)
1684 (kill-region reg-beg reg-end)
1685 (ediff-move-disturbed-overlays reg-beg)
1690 (error (message "ediff-pop-diff: %s %s"
1692 (mapconcat 'prin1-to-string (cdr conds) " "))
1695 ;; Clearing fine diffs is necessary for
1696 ;; ediff-unselect-and-select-difference to properly recompute them. We
1697 ;; can't rely on ediff-copy-diff to clear this vector, as the user might
1698 ;; have modified diff regions after copying and, thus, may have recomputed
1701 (ediff-clear-fine-differences n))
1703 ;; adjust state of difference
1704 (if (and three-way recovered)
1705 (ediff-set-state-of-diff-in-all-buffers n ctl-buf))
1707 (ediff-refresh-mode-lines)
1711 (setq n-th-record (delq saved-rec n-th-record))
1712 (message "Diff region %d in buffer %S restored" (1+ n) buf-type)
1716 (defun ediff-restore-diff (arg &optional key)
1717 "Restore ARGth diff from `ediff-killed-diffs-alist'.
1718 ARG is a prefix argument. If ARG is nil, restore current-difference.
1720 If the second optional argument, a character, is given, use it to
1721 determine the target buffer instead of last-command-char"
1724 (ediff-jump-to-difference arg))
1725 (ediff-pop-diff ediff-current-difference
1726 (ediff-char-to-buftype (or key last-command-char)))
1727 (ediff-recenter 'no-rehighlight))
1729 (defun ediff-toggle-regexp-match ()
1730 "Toggle between focusing and hiding of difference regions that match
1731 a regular expression typed in by the user."
1736 msg-connective alt-msg-connective alt-connective)
1738 ((or (and (eq ediff-skip-diff-region-function
1739 'ediff-focus-on-regexp-matches)
1740 (eq last-command-char ?f))
1741 (and (eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
1742 (eq last-command-char ?h)))
1743 (message "Selective browsing by regexp turned off")
1744 (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
1745 ((eq last-command-char ?h)
1746 (setq ediff-skip-diff-region-function 'ediff-hide-regexp-matches
1750 "Ignore A-regions matching this regexp (default \"%s\"): "
1751 ediff-regexp-hide-A))
1755 "Ignore B-regions matching this regexp (default \"%s\"): "
1756 ediff-regexp-hide-B)))
1757 (if ediff-3way-comparison-job
1761 "Ignore C-regions matching this regexp (default \"%s\"): "
1762 ediff-regexp-hide-C))))
1763 (if (eq ediff-hide-regexp-connective 'and)
1764 (setq msg-connective "BOTH"
1765 alt-msg-connective "ONE OF"
1767 (setq msg-connective "ONE OF"
1768 alt-msg-connective "BOTH"
1769 alt-connective 'and))
1772 "Hiding diff regions that match %s regexps. Use %s instead? "
1773 msg-connective alt-msg-connective))
1775 (setq ediff-hide-regexp-connective alt-connective)
1776 (message "Hiding diff regions that match %s regexps"
1777 alt-msg-connective))
1778 (message "Hiding diff regions that match %s regexps" msg-connective))
1779 (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
1780 (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
1781 (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
1782 ((eq last-command-char ?f)
1783 (setq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches
1787 "Focus on A-regions matching this regexp (default \"%s\"): "
1788 ediff-regexp-focus-A))
1792 "Focus on B-regions matching this regexp (default \"%s\"): "
1793 ediff-regexp-focus-B)))
1794 (if ediff-3way-comparison-job
1798 "Focus on C-regions matching this regexp (default \"%s\"): "
1799 ediff-regexp-focus-C))))
1800 (if (eq ediff-focus-regexp-connective 'and)
1801 (setq msg-connective "BOTH"
1802 alt-msg-connective "ONE OF"
1804 (setq msg-connective "ONE OF"
1805 alt-msg-connective "BOTH"
1806 alt-connective 'and))
1809 "Focusing on diff regions that match %s regexps. Use %s instead? "
1810 msg-connective alt-msg-connective))
1812 (setq ediff-focus-regexp-connective alt-connective)
1813 (message "Focusing on diff regions that match %s regexps"
1814 alt-msg-connective))
1815 (message "Focusing on diff regions that match %s regexps"
1817 (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
1818 (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))
1819 (or (string= regexp-C "") (setq ediff-regexp-focus-C regexp-C))))))
1821 (defun ediff-toggle-skip-similar ()
1823 (if (not (eq ediff-auto-refine 'on))
1825 "Can't skip over whitespace regions: first turn auto-refining on"))
1826 (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
1827 (if ediff-ignore-similar-regions
1829 "Skipping regions that differ only in white space & line breaks")
1830 (message "Skipping over white-space differences turned off")))
1832 (defun ediff-focus-on-regexp-matches (n)
1833 "Focus on diffs that match regexp `ediff-regexp-focus-A/B'.
1834 Regions to be ignored according to this function are those where
1835 buf A region doesn't match `ediff-regexp-focus-A' and buf B region
1836 doesn't match `ediff-regexp-focus-B'.
1837 This function returns nil if the region number N (specified as
1838 an argument) is not to be ignored and t if region N is to be ignored.
1840 N is a region number used by Ediff internally. It is 1 less
1841 the number seen by the user."
1842 (if (ediff-valid-difference-p n)
1843 (let* ((ctl-buf ediff-control-buffer)
1844 (regex-A ediff-regexp-focus-A)
1845 (regex-B ediff-regexp-focus-B)
1846 (regex-C ediff-regexp-focus-C)
1847 (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
1848 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
1851 (ediff-get-diff-posn 'A 'end n ctl-buf)
1853 (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
1854 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
1857 (ediff-get-diff-posn 'B 'end n ctl-buf)
1859 (reg-C-match (if ediff-3way-comparison-job
1860 (ediff-eval-in-buffer ediff-buffer-C
1862 (ediff-get-diff-posn 'C 'beg n ctl-buf))
1865 (ediff-get-diff-posn 'C 'end n ctl-buf)
1867 (not (eval (if ediff-3way-comparison-job
1868 (list ediff-focus-regexp-connective
1869 reg-A-match reg-B-match reg-C-match)
1870 (list ediff-focus-regexp-connective
1871 reg-A-match reg-B-match))))
1874 (defun ediff-hide-regexp-matches (n)
1875 "Hide diffs that match regexp `ediff-regexp-hide-A/B/C'.
1876 Regions to be ignored are those where buf A region matches
1877 `ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
1878 This function returns nil if the region number N (specified as
1879 an argument) is not to be ignored and t if region N is to be ignored.
1881 N is a region number used by Ediff internally. It is 1 less
1882 the number seen by the user."
1883 (if (ediff-valid-difference-p n)
1884 (let* ((ctl-buf ediff-control-buffer)
1885 (regex-A ediff-regexp-hide-A)
1886 (regex-B ediff-regexp-hide-B)
1887 (regex-C ediff-regexp-hide-C)
1888 (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
1889 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
1892 (ediff-get-diff-posn 'A 'end n ctl-buf)
1894 (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
1895 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
1898 (ediff-get-diff-posn 'B 'end n ctl-buf)
1900 (reg-C-match (if ediff-3way-comparison-job
1901 (ediff-eval-in-buffer ediff-buffer-C
1903 (ediff-get-diff-posn 'C 'beg n ctl-buf))
1906 (ediff-get-diff-posn 'C 'end n ctl-buf)
1908 (eval (if ediff-3way-comparison-job
1909 (list ediff-hide-regexp-connective
1910 reg-A-match reg-B-match reg-C-match)
1911 (list ediff-hide-regexp-connective reg-A-match reg-B-match)))
1916 ;;; Quitting, suspending, etc.
1918 (defun ediff-quit ()
1919 "Finish an Ediff session and exit Ediff.
1920 Unselects the selected difference, if any, restores the read-only and modified
1921 flags of the compared file buffers, kills Ediff buffers for this session
1922 \(but not buffers A, B, C\)."
1925 (y-or-n-p "Do you really want to exit Ediff? ")
1927 (ediff-really-quit)))
1930 ;; Perform the quit operations.
1931 (defun ediff-really-quit ()
1932 (ediff-unhighlight-diffs-totally)
1933 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
1934 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
1935 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
1937 (ediff-delete-temp-files)
1939 ;; Restore visibility range. This affects only ediff-*-regions/windows.
1940 ;; Since for other job names ediff-visible-region sets
1941 ;; ediff-visible-bounds to ediff-wide-bounds, the settings below are
1942 ;; ignored for such jobs.
1943 (if ediff-quit-widened
1944 (setq ediff-visible-bounds ediff-wide-bounds)
1945 (setq ediff-visible-bounds ediff-narrow-bounds))
1947 ;; Apply selective display to narrow or widen
1948 (ediff-visible-region)
1949 (mapcar (function (lambda (overl)
1950 (if (ediff-overlayp overl)
1951 (ediff-delete-overlay overl))))
1953 (mapcar (function (lambda (overl)
1954 (if (ediff-overlayp overl)
1955 (ediff-delete-overlay overl))))
1956 ediff-narrow-bounds)
1958 ;; restore buffer mode line id's in buffer-A/B/C
1959 (let ((control-buffer ediff-control-buffer))
1961 (ediff-eval-in-buffer ediff-buffer-A
1962 (setq ediff-this-buffer-control-sessions
1963 (delq control-buffer ediff-this-buffer-control-sessions))
1964 (kill-local-variable 'mode-line-buffer-identification)
1965 (kill-local-variable 'mode-line-format)
1970 (ediff-eval-in-buffer ediff-buffer-B
1971 (setq ediff-this-buffer-control-sessions
1972 (delq control-buffer ediff-this-buffer-control-sessions))
1973 (kill-local-variable 'mode-line-buffer-identification)
1974 (kill-local-variable 'mode-line-format)
1979 (ediff-eval-in-buffer ediff-buffer-C
1980 (kill-local-variable 'mode-line-buffer-identification)
1981 (kill-local-variable 'mode-line-format)
1985 ;; restore state of buffers to what it was before ediff
1986 (ediff-restore-protected-variables)
1987 ;; good place to kill buffers A/B/C
1988 (run-hooks 'ediff-cleanup-hooks)
1989 (run-hooks 'ediff-quit-hooks))
1992 (defun ediff-delete-temp-files ()
1993 (if (stringp ediff-temp-file-A)
1994 (delete-file ediff-temp-file-A))
1995 (if (stringp ediff-temp-file-B)
1996 (delete-file ediff-temp-file-B))
1997 (if (stringp ediff-temp-file-C)
1998 (delete-file ediff-temp-file-C)))
2001 ;; Kill control buffer, other auxiliary Ediff buffers.
2002 ;; Leave one of the frames split between buffers A/B/C
2003 (defun ediff-cleanup-mess ()
2004 (let ((buff-A ediff-buffer-A)
2005 (buff-B ediff-buffer-B)
2006 (buff-C ediff-buffer-C)
2007 (ctl-buf ediff-control-buffer)
2008 (ctl-frame ediff-control-frame)
2009 (three-way-job ediff-3way-job))
2011 (ediff-kill-buffer-carefully ediff-diff-buffer)
2012 (ediff-kill-buffer-carefully ediff-custom-diff-buffer)
2013 (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
2014 (ediff-kill-buffer-carefully ediff-tmp-buffer)
2015 (ediff-kill-buffer-carefully ediff-error-buffer)
2016 (ediff-kill-buffer-carefully ediff-patch-diagnostics)
2017 (ediff-kill-buffer-carefully ediff-msg-buffer)
2018 (ediff-kill-buffer-carefully ediff-debug-buffer)
2021 (if (and (ediff-window-display-p) (frame-live-p ctl-frame))
2022 (delete-frame ctl-frame))
2023 (ediff-kill-buffer-carefully ctl-buf)
2025 (delete-other-windows)
2027 ;; display only if not visible
2029 (or (ediff-get-visible-buffer-window buff-B)
2030 (switch-to-buffer buff-B))
2033 (or (ediff-get-visible-buffer-window buff-A)
2035 (if (ediff-get-visible-buffer-window buff-B)
2036 (split-window-vertically))
2037 (switch-to-buffer buff-A)))
2041 (or (ediff-get-visible-buffer-window buff-C)
2043 (if (or (ediff-get-visible-buffer-window buff-A)
2044 (ediff-get-visible-buffer-window buff-B))
2045 (split-window-vertically))
2046 (switch-to-buffer buff-C)
2052 (defun ediff-janitor ()
2053 "Kill buffers A, B, and, possibly, C, if these buffers aren't modified.
2054 In merge jobs, buffer C is never deleted.
2055 However, the side effect of cleaning up may be that you cannot compare the same
2056 buffer in two separate Ediff sessions: quitting one of them will delete this
2057 buffer in another session as well."
2058 (or (not (ediff-buffer-live-p ediff-buffer-A))
2059 (buffer-modified-p ediff-buffer-A)
2060 (ediff-kill-buffer-carefully ediff-buffer-A))
2061 (or (not (ediff-buffer-live-p ediff-buffer-B))
2062 (buffer-modified-p ediff-buffer-B)
2063 (ediff-kill-buffer-carefully ediff-buffer-B))
2064 (if ediff-merge-job ; don't del buf C if merging--del ancestor buf instead
2065 (or (not (ediff-buffer-live-p ediff-ancestor-buffer))
2066 (buffer-modified-p ediff-ancestor-buffer)
2067 (ediff-kill-buffer-carefully ediff-ancestor-buffer))
2068 (or (not (ediff-buffer-live-p ediff-buffer-C))
2069 (buffer-modified-p ediff-buffer-C)
2070 (ediff-kill-buffer-carefully ediff-buffer-C))))
2072 ;; The default way of suspending Ediff.
2073 ;; Buries Ediff buffers, kills all windows.
2074 (defun ediff-default-suspend-hook ()
2075 (let* ((buf-A ediff-buffer-A)
2076 (buf-B ediff-buffer-B)
2077 (buf-C ediff-buffer-C)
2078 (buf-A-wind (ediff-get-visible-buffer-window buf-A))
2079 (buf-B-wind (ediff-get-visible-buffer-window buf-B))
2080 (buf-C-wind (ediff-get-visible-buffer-window buf-C))
2081 (buf-patch ediff-patch-buf)
2082 (buf-patch-diag ediff-patch-diagnostics)
2083 (buf-err ediff-error-buffer)
2084 (buf-diff ediff-diff-buffer)
2085 (buf-custom-diff ediff-custom-diff-buffer)
2086 (buf-fine-diff ediff-fine-diff-buffer))
2088 ;; hide the control panel
2089 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
2090 (iconify-frame ediff-control-frame)
2092 (if buf-err (bury-buffer buf-err))
2093 (if buf-diff (bury-buffer buf-diff))
2094 (if buf-custom-diff (bury-buffer buf-custom-diff))
2095 (if buf-fine-diff (bury-buffer buf-fine-diff))
2096 (if buf-patch (bury-buffer buf-patch))
2097 (if buf-patch-diag (bury-buffer buf-patch-diag))
2098 (if (window-live-p buf-A-wind)
2100 (select-window buf-A-wind)
2101 (delete-other-windows)
2103 (if (ediff-buffer-live-p buf-A) (bury-buffer buf-A)))
2104 (if (window-live-p buf-B-wind)
2106 (select-window buf-B-wind)
2107 (delete-other-windows)
2109 (if (ediff-buffer-live-p buf-B) (bury-buffer buf-B)))
2110 (if (window-live-p buf-C-wind)
2112 (select-window buf-C-wind)
2113 (delete-other-windows)
2115 (if (ediff-buffer-live-p buf-C) (bury-buffer buf-C)))
2120 (defun ediff-suspend ()
2122 To resume, switch to the appropriate `Ediff Control Panel'
2123 buffer and then type \\[ediff-recenter]. Ediff will automatically set
2124 up an appropriate window config."
2126 (let ((key (substitute-command-keys "\\[ediff-recenter]")))
2127 (run-hooks 'ediff-suspend-hooks)
2129 "To resume, switch to Ediff Control Panel and hit `%s'" key)))
2132 (defun ediff-status-info ()
2133 "Show the names of the buffers or files being operated on by Ediff.
2134 Hit \\[ediff-recenter] to reset the windows afterward."
2136 (with-output-to-temp-buffer " *ediff-info*"
2137 (princ (ediff-version))
2139 (ediff-eval-in-buffer ediff-buffer-A
2140 (if buffer-file-name
2142 (format "File A = %S\n" buffer-file-name))
2144 (format "Buffer A = %S\n" (buffer-name)))))
2145 (ediff-eval-in-buffer ediff-buffer-B
2146 (if buffer-file-name
2148 (format "File B = %S\n" buffer-file-name))
2150 (format "Buffer B = %S\n" (buffer-name)))))
2152 (ediff-eval-in-buffer ediff-buffer-C
2153 (if buffer-file-name
2155 (format "File C = %S\n" buffer-file-name))
2157 (format "Buffer C = %S\n" (buffer-name))))))
2159 (let* ((A-line (ediff-eval-in-buffer ediff-buffer-A
2160 (1+ (count-lines (point-min) (point)))))
2161 (B-line (ediff-eval-in-buffer ediff-buffer-B
2162 (1+ (count-lines (point-min) (point)))))
2164 (princ (format "\Buffer A's point is on line %d\n" A-line))
2165 (princ (format "Buffer B's point is on line %d\n" B-line))
2168 (setq C-line (ediff-eval-in-buffer ediff-buffer-C
2169 (1+ (count-lines (point-min) (point)))))
2170 (princ (format "Buffer C's point is on line %d\n" C-line)))))
2172 (princ (format "\nCurrent difference number = %S\n"
2173 (cond ((< ediff-current-difference 0) 'start)
2174 ((>= ediff-current-difference
2175 ediff-number-of-differences) 'end)
2176 (t (1+ ediff-current-difference)))))
2178 (cond (ediff-ignore-similar-regions
2179 (princ "\nSkipping regions that differ only in white space & line breaks"))
2181 (princ "\nNot skipping regions that differ in white space & line breaks")))
2183 (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
2184 (princ "\nSelective browsing by regexp is off.\n"))
2185 ((eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
2187 "\nIgnoring regions that match")
2190 "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
2191 ediff-regexp-hide-A ediff-hide-regexp-connective
2192 ediff-regexp-hide-B)))
2193 ((eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
2195 "\nFocusing on regions that match")
2198 "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
2199 ediff-regexp-focus-A ediff-focus-regexp-connective
2200 ediff-regexp-focus-B)))
2201 (t (princ "\nSelective browsing via a user-defined method.\n")))
2204 (format "\nBugs/suggestions: type `%s' while in Ediff Control Panel."
2205 (substitute-command-keys "\\[ediff-submit-report]")))
2208 (defun ediff-documentation ()
2209 "Jump to Ediff's Info file."
2211 (let ((ctl-window ediff-control-window)
2212 (ctl-buf ediff-control-buffer))
2214 (ediff-skip-unsuitable-frames)
2217 (pop-to-buffer (get-buffer-create "*info*"))
2219 (message "Type `i' to search for a specific topic"))
2221 (with-output-to-temp-buffer " *ediff-info*"
2223 The Info file for Ediff does not seem to be installed.
2225 This file is part of the distribution of %sEmacs.
2226 Please contact your system administrator. "
2227 (if ediff-xemacs-p "X" ""))))
2228 (if (window-live-p ctl-window)
2230 (select-window ctl-window)
2231 (switch-to-buffer ctl-buf)))))))
2236 ;;; Support routines
2238 ;; Select a difference by placing the ASCII flags around the appropriate
2239 ;; group of lines in the A, B buffers
2240 ;; This may have to be modified for buffer C, when it will be supported.
2241 (defun ediff-select-difference (n)
2242 (if (and (ediff-buffer-live-p ediff-buffer-A)
2243 (ediff-buffer-live-p ediff-buffer-B)
2244 (ediff-valid-difference-p n))
2246 (if (and (ediff-window-display-p) ediff-use-faces)
2248 (ediff-highlight-diff n)
2249 (setq ediff-highlighting-style 'face))
2250 (setq ediff-highlighting-style 'ascii)
2251 (ediff-place-flags-in-buffer
2252 'A ediff-buffer-A ediff-control-buffer n)
2253 (ediff-place-flags-in-buffer
2254 'B ediff-buffer-B ediff-control-buffer n)
2256 (ediff-place-flags-in-buffer
2257 'C ediff-buffer-C ediff-control-buffer n))
2260 (ediff-install-fine-diff-if-necessary n)
2261 (run-hooks 'ediff-select-hooks))))
2264 ;; Unselect a difference by removing the ASCII flags in the buffers.
2265 ;; This may have to be modified for buffer C, when it will be supported.
2266 (defun ediff-unselect-difference (n)
2267 (if (ediff-valid-difference-p n)
2269 (cond ((and (ediff-window-display-p) ediff-use-faces)
2270 (ediff-unhighlight-diff))
2271 ((eq ediff-highlighting-style 'ascii)
2272 (ediff-remove-flags-from-buffer
2274 (ediff-get-diff-overlay n 'A))
2275 (ediff-remove-flags-from-buffer
2277 (ediff-get-diff-overlay n 'B))
2279 (ediff-remove-flags-from-buffer
2281 (ediff-get-diff-overlay n 'C)))
2283 (setq ediff-highlighting-style nil)
2285 ;; unhighlight fine diffs
2286 (ediff-set-fine-diff-properties ediff-current-difference 'default)
2287 (run-hooks 'ediff-unselect-hooks))))
2290 ;; Unselects prev diff and selects a new one, if FLAG has value other than
2291 ;; 'select-only or 'unselect-only. If FLAG is 'select-only, the
2292 ;; next difference is selected, but the current selection is not
2293 ;; unselected. If FLAG is 'unselect-only then the current selection is
2294 ;; unselected, but the next one is not selected. If NO-RECENTER is non-nil,
2295 ;; don't recenter buffers after selecting/unselecting.
2297 (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
2298 (let ((ediff-current-difference n))
2300 (ediff-recenter 'no-rehighlight)))
2302 (let ((control-buf ediff-control-buffer))
2305 (or (eq flag 'select-only)
2306 (ediff-unselect-difference ediff-current-difference))
2308 (or (eq flag 'unselect-only)
2309 (ediff-select-difference n))
2310 (setq ediff-current-difference n)
2311 ) ; end protected section
2313 (ediff-eval-in-buffer control-buf
2314 (ediff-refresh-mode-lines))
2318 (defun ediff-read-file-name (prompt default-dir default-file)
2319 ; This is a modified version of a similar function in `emerge.el'.
2320 ; PROMPT should not have trailing ': ', so that it can be modified
2321 ; according to context.
2322 ; If default-file is set, it should be used as the default value.
2323 ; If default-dir is non-nil, use it as the default directory.
2324 ; Otherwise, use the value of Emacs' variable `default-directory.'
2326 ;; hack default-dir if it is not set
2328 (file-name-as-directory
2329 (abbreviate-file-name
2330 (expand-file-name (or default-dir
2332 (file-name-directory default-file))
2333 default-directory)))))
2335 ;; strip the directory from default-file
2337 (setq default-file (file-name-nondirectory default-file)))
2338 (if (string= default-file "")
2339 (setq default-file nil))
2342 (setq f (expand-file-name
2347 (concat " (default " default-file ")")
2351 t ; must match, no-confirm
2352 (if default-file (file-name-directory default-file))
2356 ;; If user enters a directory name, expand the default file in that
2357 ;; directory. This allows the user to enter a directory name for the
2358 ;; B-file and diff against the default-file in that directory instead
2359 ;; of a DIRED listing!
2360 (if (and (file-directory-p f) default-file)
2361 (setq f (expand-file-name
2362 (file-name-nondirectory default-file) f)))
2365 ;; If `prefix' is given, then it is used as a prefix for the temp file
2366 ;; name. Otherwise, `_buffer-name' is used. If `file' is given, use this
2367 ;; file and don't create a new one.
2368 ;; Also, save buffer from START to END in the file.
2369 ;; START defaults to (point-min), END to (point-max)
2370 (defun ediff-make-temp-file (&optional prefix given-file start end)
2371 (let ((f (or given-file
2372 (make-temp-name (concat
2373 ediff-temp-file-prefix
2378 (write-region (if start start (point-min))
2379 (if end end (point-max))
2381 nil ; don't append---erase
2383 (set-file-modes f ediff-temp-file-mode)
2386 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
2388 (defun ediff-protect-metachars (str)
2389 (or (memq system-type '(emx vax-vms axp-vms))
2391 (while (string-match ediff-metachars str limit)
2392 (setq str (concat (substring str 0 (match-beginning 0))
2394 (substring str (match-beginning 0))))
2395 (setq limit (1+ (match-end 0))))))
2398 ;; Make sure the current buffer (for a file) has the same contents as the
2399 ;; file on disk, and attempt to remedy the situation if not.
2400 ;; Signal an error if we can't make them the same, or the user doesn't want
2401 ;; to do what is necessary to make them the same.
2402 ;; If file has file handlers (indicated by the optional arg), then we
2403 ;; offer to instead of saving. This is one difference with Emerge.
2404 ;; Another is that we always offer to revert obsolete files, whether they
2405 ;; are modified or not.
2406 (defun ediff-verify-file-buffer (&optional file-magic)
2407 ;; First check if the file has been modified since the buffer visited it.
2408 (if (verify-visited-file-modtime (current-buffer))
2409 (if (buffer-modified-p)
2410 ;; If buffer is not obsolete and is modified, offer to save
2412 (format "Buffer out of sync with visited file. %s file %s? "
2413 (if file-magic "Revert" "Save")
2415 (if (not file-magic)
2417 ;; for some reason, file-name-handlers append instead of
2418 ;; replacing, so we have to erase first.
2420 (revert-buffer t t))
2421 (error "Buffer out of sync for file %s" buffer-file-name))
2422 ;; If buffer is not obsolete and is not modified, do nothing
2424 ;; If buffer is obsolete, offer to revert
2426 (format "Buffer out of sync with visited file. Revert file %s? "
2431 (revert-buffer t t))
2432 (error "Buffer out of sync for file %s" buffer-file-name))))
2436 (defun ediff-check-for-ascii-flags ()
2439 (mapcar (function (lambda (buf)
2440 (if (ediff-buffer-live-p buf)
2441 (ediff-eval-in-buffer buf
2442 (eq ediff-highlighting-style 'ascii)))))
2443 ediff-this-buffer-control-sessions))))
2445 ;; It would be nice to use these two functions as hooks instead of
2446 ;; ediff-insert-in-front and ediff-move-disturbed-overlays.
2447 ;; However, Emacs has a bug that causes BEG and END, below, to be
2448 ;; the same, i.e., the end of inserted text is not passed correctly.
2449 ;; Since the overlay doesn't move when these hooks run,
2450 ;; there is no way to correctly determine the new (desired) position of
2452 ;; Either this bug is fixed, or (better) use sticky overlays when they will
2453 ;; be implemented in Emacs, like they are in XEmacs.
2454 ;;(defun ediff-capture-inserts-in-front (overl beg end)
2455 ;; (if (ediff-overlay-get overl 'ediff-diff-num)
2456 ;; (ediff-move-overlay
2457 ;; overl beg (+ (- end beg) (ediff-overlay-end overl)))
2459 ;;(defun ediff-capture-inserts-behind (overl beg end)
2460 ;; (if (ediff-overlay-get overl 'ediff-diff-num)
2461 ;; (ediff-move-overlay overl (ediff-overlay-start overl) end))
2464 ;; to be deleted in due time
2465 ;; Capture overlays that had insertions in the front.
2466 ;; Called when overlay OVERL gets insertion in front.
2467 (defun ediff-insert-in-front (overl &optional flag beg end length)
2468 (if (ediff-overlay-get overl 'ediff-diff-num)
2469 (setq ediff-disturbed-overlays
2470 (cons overl ediff-disturbed-overlays))))
2473 ;; to be deleted in due time
2474 ;; We can't move overlays directly in insert-in-front-hooks
2475 ;; because when diff is highlighted with ascii flags, they will disturb
2476 ;; overlays and so they will be included in them, which we don't want.
2477 (defun ediff-move-disturbed-overlays (posn)
2478 (mapcar (function (lambda (overl)
2479 (ediff-move-overlay overl
2481 (ediff-overlay-end overl))
2483 ediff-disturbed-overlays)
2484 (setq ediff-disturbed-overlays nil))
2487 (defun ediff-save-buffer (arg)
2488 "Safe way of saving buffers A, B, C, and the diff output.
2489 `wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C,
2490 and `wd' saves the diff output."
2492 (ediff-eval-in-buffer
2493 (cond ((memq last-command-char '(?a ?b ?c))
2495 (ediff-char-to-buftype last-command-char)))
2496 ((eq last-command-char ?d)
2497 (message "Saving diff output ...")(sit-for 1)
2498 (if arg ediff-diff-buffer ediff-custom-diff-buffer)
2503 ;; will simplify it in due time, when emacs acquires before/after strings
2504 (defun ediff-remove-flags-from-buffer (buffer overlay)
2505 (ediff-eval-in-buffer buffer
2506 (let ((inhibit-read-only t))
2508 (ediff-overlay-put overlay 'begin-glyph nil)
2509 ;; before-string is not yet implemented in emacs.
2510 ;; when it will be, I will be able to delete much of the rest of
2512 (ediff-overlay-put overlay 'before-string nil))
2515 (ediff-overlay-put overlay 'end-glyph nil)
2516 ;; after-string is not yet implemented in emacs.
2517 (ediff-overlay-put overlay 'after-string nil))
2522 ;; will simplify it in due time, when emacs acquires before/after strings
2523 (defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer diff)
2524 (ediff-eval-in-buffer buffer
2525 (ediff-place-flags-in-buffer1 buf-type ctl-buffer diff)))
2528 (defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer diff-no)
2529 (let* ((curr-overl (ediff-eval-in-buffer ctl-buffer
2530 (ediff-get-diff-overlay diff-no buf-type)))
2531 (before (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer))
2532 after beg-of-line flag)
2534 ;; insert flag before the difference
2536 (setq beg-of-line (bolp))
2538 (setq flag (ediff-eval-in-buffer ctl-buffer
2539 (if (eq ediff-highlighting-style 'ascii)
2541 ediff-before-flag-bol ediff-before-flag-mol))))
2543 ;; insert the flag itself
2545 (ediff-overlay-put curr-overl 'begin-glyph flag)
2546 (ediff-overlay-put curr-overl 'before-string flag))
2548 ;; insert the flag after the difference
2549 ;; `after' must be set here, after the before-flag was inserted
2550 (setq after (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
2552 (setq beg-of-line (bolp))
2554 (setq flag (ediff-eval-in-buffer ctl-buffer
2555 (if (eq ediff-highlighting-style 'ascii)
2557 ediff-after-flag-eol ediff-after-flag-mol))))
2559 ;; insert the flag itself
2561 (ediff-overlay-put curr-overl 'end-glyph flag)
2562 (ediff-overlay-put curr-overl 'after-string flag))
2566 (defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
2567 "Returns positions of difference sectors in the BUF-TYPE buffer.
2568 BUF-TYPE should be a symbol--either `A' or `B'.
2569 POS is either `beg' or `end'--it specifies whether you want the position at the
2570 beginning of a difference or at the end.
2572 The optional argument N says which difference \(default:
2573 `ediff-current-difference'\). The optional argument CONTROL-BUF says
2574 which control buffer is in effect in case it is not the current
2578 (setq control-buf (current-buffer)))
2580 (ediff-eval-in-buffer control-buf
2581 (or n (setq n ediff-current-difference))
2582 (if (or (< n 0) (>= n ediff-number-of-differences))
2583 (if (> ediff-number-of-differences 0)
2584 (error "There is no diff %d. Valid diffs are 1 to %d"
2585 (1+ n) ediff-number-of-differences)
2586 (error "No differences found")))
2587 (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
2590 (ediff-overlay-start diff-overlay)
2591 (ediff-overlay-end diff-overlay))
2596 (defun ediff-highlight-diff-in-one-buffer (n buf-type)
2597 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
2598 (let* ((buff (ediff-get-buffer buf-type))
2599 (last (ediff-eval-in-buffer buff (point-max)))
2600 (begin (ediff-get-diff-posn buf-type 'beg n))
2601 (end (ediff-get-diff-posn buf-type 'end n))
2602 (xtra (if (equal begin end) 1 0))
2603 (end-hilit (min last (+ end xtra)))
2604 (current-diff-overlay
2606 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2609 (intern (format "ediff-odd-diff-face-%S" buf-type))))
2612 (intern (format "ediff-even-diff-face-%S" buf-type))))
2614 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2616 (intern (format "ediff-even-diff-face-%S-var" buf-type)))
2620 (ediff-move-overlay current-diff-overlay begin end-hilit)
2621 (ediff-move-overlay current-diff-overlay begin end-hilit buff))
2622 ;; giving priority of 0 and then changing it may look funny, but
2623 ;; this overcomes an obscure Emacs bug.
2624 (ediff-overlay-put current-diff-overlay 'priority 0)
2625 (ediff-overlay-put current-diff-overlay 'priority
2626 (ediff-highest-priority begin end-hilit buff))
2628 (or (face-differs-from-default-p odd-diff-face-var)
2629 (not ediff-highlight-all-diffs)
2631 (copy-face odd-diff-face odd-diff-face-var)
2632 (copy-face even-diff-face even-diff-face-var)))
2634 ;; unhighlight the background overlay for diff n so they won't
2635 ;; interfere with the current diff overlay
2636 (ediff-overlay-put (ediff-get-diff-overlay n buf-type) 'face nil)
2640 (defun ediff-unhighlight-diff-in-one-buffer (buf-type)
2641 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
2642 (let ((current-diff-overlay
2644 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2646 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2648 (intern (format "ediff-even-diff-face-%S-var" buf-type)))
2650 (ediff-get-diff-overlay ediff-current-difference buf-type))
2653 (ediff-move-overlay current-diff-overlay 1 1)
2655 ;; rehighlight the overlay in the background of the
2656 ;; current difference region
2657 (ediff-overlay-put overlay
2658 'face (if (ediff-odd-p ediff-current-difference)
2660 even-diff-face-var))
2663 (defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
2664 (ediff-unselect-and-select-difference -1)
2665 (if (and (ediff-window-display-p) ediff-use-faces)
2666 (let* ((inhibit-quit t)
2667 (current-diff-overlay-var
2668 (intern (format "ediff-current-diff-overlay-%S" buf-type)))
2669 (current-diff-overlay (symbol-value current-diff-overlay-var))
2671 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2673 (intern (format "ediff-even-diff-face-%S-var" buf-type))))
2674 (if (face-differs-from-default-p odd-diff-face-var)
2676 (copy-face 'default odd-diff-face-var)
2677 (copy-face 'default even-diff-face-var)))
2678 (if (ediff-overlayp current-diff-overlay)
2679 (ediff-delete-overlay current-diff-overlay))
2680 (set current-diff-overlay-var nil)
2684 ;; null out difference overlays so they won't slow down future
2685 ;; editing operations
2686 ;; VEC is either a difference vector or a fine-diff vector
2687 (defun ediff-clear-diff-vector (vec-var &optional fine-diffs-also)
2688 (if (vectorp (symbol-value vec-var))
2691 (ediff-delete-overlay
2692 (ediff-get-diff-overlay-from-diff-record elt))
2694 (ediff-clear-fine-diff-vector elt))
2696 (symbol-value vec-var)))
2697 ;; allow them to be garbage collected
2704 ;; These two functions are here to neutralize XEmacs unwillingless to
2705 ;; handle overlays whose buffers were deleted.
2706 (defun ediff-move-overlay (overlay beg end &optional buffer)
2707 "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
2708 Checks if overlay's buffer exists before actually doing the move."
2709 (let ((buf (and overlay (ediff-overlay-buffer overlay))))
2710 (if (ediff-buffer-live-p buf)
2712 (set-extent-endpoints overlay beg end)
2713 (move-overlay overlay beg end buffer))
2716 (ediff-delete-overlay overlay)))))
2718 (defun ediff-overlay-put (overlay prop value)
2719 "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
2720 Checks if overlay's buffer exists."
2721 (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
2723 (set-extent-property overlay prop value)
2724 (overlay-put overlay prop value))
2725 (ediff-delete-overlay overlay)))
2728 ;; In Emacs, this just makes overlay. In the future, when Emacs will start
2729 ;; supporting sticky overlays, this function will make a sticky overlay.
2730 ;; BEG and END are expressions telling where overlay starts.
2731 ;; If they are numbers or buffers, then all is well. Otherwise, they must
2732 ;; be expressions to be evaluated in buffer BUF in order to get the overlay
2734 ;; If BUFF is not a live buffer, then return nil; otherwise, return the
2735 ;; newly created overlay.
2736 (defun ediff-make-bullet-proof-overlay (beg end buff)
2737 (if (ediff-buffer-live-p buff)
2739 (ediff-eval-in-buffer buff
2740 (or (number-or-marker-p beg)
2741 (setq beg (eval beg)))
2742 (or (number-or-marker-p end)
2743 (setq end (eval end)))
2744 (setq overl (ediff-make-overlay beg end buff))
2748 ;; take precautions against detached extents
2749 (ediff-overlay-put overl 'detachable nil)
2750 ;; chars inserted at both ends will be inside extent
2751 (ediff-overlay-put overl 'start-open nil)
2752 (ediff-overlay-put overl 'end-open nil))
2753 (ediff-overlay-put overl 'ediff-diff-num 0)
2754 ;;(ediff-overlay-put overl 'insert-in-front-hooks
2755 ;; (list 'ediff-capture-inserts-in-front))
2756 ;;(ediff-overlay-put overl 'insert-behind-hooks
2757 ;; (list 'ediff-capture-inserts-behind))
2758 ;; These two are not yet implemented in Emacs
2759 ;;(ediff-overlay-put overl 'rear-sticky t)
2760 ;;(ediff-overlay-put overl 'front-sticky t)
2764 (defsubst ediff-overlay-start (overl)
2765 (if (ediff-overlayp overl)
2767 (overlay-start overl)
2768 (extent-start-position overl))))
2770 (defsubst ediff-overlay-end (overl)
2771 (if (ediff-overlayp overl)
2774 (extent-end-position overl))))
2777 ;; Like other-buffer, but prefers visible buffers and ignores temporary or
2778 ;; other insignificant buffers (those beginning with "^[ *]").
2779 ;; Gets one arg--buffer name or a list of buffer names (it won't return
2781 (defun ediff-other-buffer (buff)
2782 (if (not (listp buff)) (setq buff (list buff)))
2783 (let* ((frame-buffers (buffer-list))
2784 (significant-buffers
2786 (function (lambda (x)
2787 (cond ((member (buffer-name x) buff)
2789 ((not (ediff-get-visible-buffer-window x))
2791 ((string-match "^ " (buffer-name x))
2795 (buffers (delq nil significant-buffers))
2796 less-significant-buffers)
2798 (cond (buffers (car buffers))
2799 ;; try also buffers that are not displayed in windows
2800 ((setq less-significant-buffers
2805 (cond ((member (buffer-name x) buff) nil)
2806 ((string-match "^[ *]" (buffer-name x)) nil)
2809 (car less-significant-buffers))
2810 (t (other-buffer (current-buffer))))
2814 ;; Construct a unique buffer name.
2815 ;; The first one tried is prefixsuffix, then prefix<2>suffix,
2816 ;; prefix<3>suffix, etc.
2817 (defun ediff-unique-buffer-name (prefix suffix)
2818 (if (null (get-buffer (concat prefix suffix)))
2819 (concat prefix suffix)
2821 (while (get-buffer (format "%s<%d>%s" prefix n suffix))
2823 (format "%s<%d>%s" prefix n suffix))))
2826 (defun ediff-submit-report ()
2827 "Submit bug report on Ediff."
2829 (let ((reporter-prompt-for-summary-p t)
2830 (ctl-buf ediff-control-buffer)
2831 (ediff-device-type (ediff-device-type))
2832 varlist salutation buffer-name)
2833 (setq varlist '(ediff-diff-program ediff-diff-options
2834 ediff-patch-program ediff-patch-options
2837 ediff-auto-refine ediff-highlighting-style
2838 ediff-buffer-A ediff-buffer-B ediff-control-buffer
2839 ediff-forward-word-function
2841 ediff-control-frame-parameters
2842 ediff-control-frame-position-function
2843 ediff-prefer-iconified-control-frame
2844 ediff-window-setup-function
2845 ediff-split-window-function
2852 Congratulations! You may have unearthed a bug in Ediff!
2854 Please make a concise and accurate summary of what happened
2855 and mail it to the address above.
2856 -----------------------------------------------------------
2859 (ediff-skip-unsuitable-frames)
2862 (switch-to-buffer ediff-msg-buffer)
2864 (delete-other-windows)
2866 Please read this first:
2867 ----------------------
2869 Some ``bugs'' may actually be no bugs at all. For instance, if you are
2870 reporting that certain difference regions are not matched as you think they
2871 should, this is most likely due to the way Unix diff program decides what
2872 constitutes a difference region. Ediff is an Emacs interface to diff, and
2873 it has nothing to do with those decisions---it only takes the output from
2874 diff and presents it in a way that is better suited for human browsing and
2877 If Emacs happens to dump core, this is NOT an Ediff problem---it is
2878 an Emacs bug. Report this to Emacs maintainers.
2880 Another popular topic for reports is compilation messages. Because Ediff
2881 interfaces to several other packages and runs under Emacs and XEmacs,
2882 byte-compilation may produce output like this:
2884 While compiling toplevel forms in file ediff.el:
2885 ** reference to free variable pm-color-alist
2886 ........................
2887 While compiling the end of the data:
2888 ** The following functions are not known to be defined:
2889 ediff-valid-color-p, ediff-set-face,
2890 ........................
2892 These are NOT errors, but inevitable warnings, which ought to be ignored.
2894 Please do not report those and similar things. However, comments and
2895 suggestions are always welcome.
2897 Mail anyway? (y or n) ")
2899 (if (y-or-n-p "Mail anyway? ")
2901 (if (ediff-buffer-live-p ctl-buf)
2902 (set-buffer ctl-buf))
2903 (setq buffer-name (buffer-name))
2905 (reporter-submit-bug-report "kifer@cs.sunysb.edu"
2909 'delete-other-windows
2912 (beep 1)(message "Bug report aborted")
2913 (if (ediff-buffer-live-p ctl-buf)
2914 (ediff-eval-in-buffer ctl-buf
2915 (ediff-recenter 'no-rehighlight))))
2919 (defun ediff-union (list1 list2)
2920 "Combine LIST1 and LIST2 using a set-union operation.
2921 The result list contains all items that appear in either LIST1 or LIST2.
2922 This is a non-destructive function; it makes a copy of the data if necessary
2923 to avoid corrupting the original LIST1 and LIST2.
2924 This is a slightly simplified version from `cl-seq.el'. Added here to
2925 avoid loading cl-*."
2926 (cond ((null list1) list2) ((null list2) list1)
2927 ((equal list1 list2) list1)
2929 (or (>= (length list1) (length list2))
2930 (setq list1 (prog1 list2 (setq list2 list1))))
2932 (or (memq (car list2) list1)
2933 (setq list1 (cons (car list2) list1)))
2934 (setq list2 (cdr list2)))
2937 (defun ediff-deactivate-mark ()
2939 (zmacs-deactivate-region)
2942 (cond ((fboundp 'nuke-selective-display)
2943 ;; XEmacs 19.12 has nuke-selective-display
2944 (fset 'ediff-nuke-selective-display 'nuke-selective-display))
2946 (defun ediff-nuke-selective-display ()
2950 (goto-char (point-min))
2951 (let ((mod-p (buffer-modified-p))
2952 buffer-read-only end)
2953 (and (eq t selective-display)
2954 (while (search-forward "\^M" nil t)
2958 (while (search-forward "\^M" end t)
2961 (set-buffer-modified-p mod-p)
2962 (setq selective-display nil)))))
2966 ;; The next two are modified versions from emerge.el.
2967 ;; VARS must be a list of symbols
2968 ;; ediff-save-variables returns an association list: ((var . val) ...)
2969 (defsubst ediff-save-variables (vars)
2970 (mapcar (function (lambda (v) (cons v (symbol-value v))))
2972 ;; VARS is a list of variable symbols.
2973 (defun ediff-restore-variables (vars assoc-list)
2975 (set (car vars) (cdr (assoc (car vars) assoc-list)))
2976 (setq vars (cdr vars))))
2977 (defun ediff-change-saved-variable (var value buf-type)
2979 (symbol-value (intern
2980 (concat "ediff-buffer-values-orig-"
2981 (symbol-name buf-type)))))
2982 (assoc-elt (assoc var assoc-list)))
2984 (setcdr assoc-elt value))))
2987 ;; must execute in control buf
2988 (defun ediff-save-protected-variables ()
2989 (setq ediff-buffer-values-orig-A
2990 (ediff-eval-in-buffer ediff-buffer-A
2991 (ediff-save-variables ediff-protected-variables)))
2992 (setq ediff-buffer-values-orig-B
2993 (ediff-eval-in-buffer ediff-buffer-B
2994 (ediff-save-variables ediff-protected-variables)))
2995 (if ediff-3way-comparison-job
2996 (setq ediff-buffer-values-orig-C
2997 (ediff-eval-in-buffer ediff-buffer-C
2998 (ediff-save-variables ediff-protected-variables)))))
3000 ;; must execute in control buf
3001 (defun ediff-restore-protected-variables ()
3002 (let ((values-A ediff-buffer-values-orig-A)
3003 (values-B ediff-buffer-values-orig-B)
3004 (values-C ediff-buffer-values-orig-C))
3005 (ediff-eval-in-buffer ediff-buffer-A
3006 (ediff-restore-variables ediff-protected-variables values-A))
3007 (ediff-eval-in-buffer ediff-buffer-B
3008 (ediff-restore-variables ediff-protected-variables values-B))
3009 (if ediff-3way-comparison-job
3010 (ediff-eval-in-buffer ediff-buffer-C
3011 (ediff-restore-variables ediff-protected-variables values-C)))))
3016 (ediff-defvar-local ediff-command-begin-time '(0 0 0) "")
3018 ;; calculate time used by command
3019 (defun ediff-calc-command-time ()
3020 (let ((end (current-time))
3023 (if (>= (nth 2 end) (nth 2 ediff-command-begin-time))
3024 (- (nth 2 end) (nth 2 ediff-command-begin-time))
3025 (+ (nth 2 end) (- 1000000 (nth 2 ediff-command-begin-time)))))
3026 (setq sec (- (nth 1 end) (nth 1 ediff-command-begin-time)))
3027 (or (equal ediff-command-begin-time '(0 0 0))
3028 (message "Elapsed time: %d second(s) + %d microsecond(s)" sec micro))))
3030 (defsubst ediff-save-time ()
3031 (setq ediff-command-begin-time (current-time)))
3033 (defun ediff-profile ()
3034 "Toggle profiling Ediff commands."
3036 (or (ediff-buffer-live-p ediff-control-buffer)
3037 (error "This command runs only out of Ediff Control Buffer"))
3038 (make-local-variable 'pre-command-hook)
3039 (make-local-variable 'post-command-hook)
3040 (if (memq 'ediff-save-time pre-command-hook)
3041 (progn (remove-hook 'pre-command-hook 'ediff-save-time)
3042 (remove-hook 'post-command-hook 'ediff-calc-command-time)
3043 (setq ediff-command-begin-time '(0 0 0))
3044 (message "Ediff profiling disabled"))
3045 (add-hook 'pre-command-hook 'ediff-save-time t)
3046 (add-hook 'post-command-hook 'ediff-calc-command-time)
3047 (message "Ediff profiling enabled")))
3049 (defun ediff-print-diff-vector (diff-vector-var)
3050 (princ (format "\n*** %S ***\n" diff-vector-var))
3055 "Diff %d: \tOverlay: %S
3057 \t\tNo-fine-diff-flag: %S
3058 \t\tState-of-diff:\t %S
3059 \t\tState-of-merge:\t %S
3061 (1+ (ediff-overlay-get (aref overl-vec 0) 'ediff-diff-num))
3064 (if (= (length (aref overl-vec 1)) 0)
3066 (mapconcat 'prin1-to-string
3067 (aref overl-vec 1) "\n\t\t\t "))
3068 (aref overl-vec 2) ; no fine diff flag
3069 (aref overl-vec 3) ; state-of-diff
3070 (aref overl-vec 4) ; state-of-merge
3072 (eval diff-vector-var)))
3076 (defun ediff-debug-info ()
3078 (or (ediff-buffer-live-p ediff-control-buffer)
3079 (error "This command runs only out of Ediff Control Buffer"))
3080 (with-output-to-temp-buffer ediff-debug-buffer
3081 (princ (format "\nCtl buffer: %S\n" ediff-control-buffer))
3082 (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "A")))
3083 (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "B")))
3084 (ediff-print-diff-vector (intern (concat "ediff-difference-vector-" "C")))
3087 ;; don't report error if version control package wasn't found
3088 ;;(ediff-load-version-control 'silent)
3090 (run-hooks 'ediff-load-hooks)
3093 ;;; Local Variables:
3094 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
3095 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
3098 (provide 'ediff-util)
3100 ;;; ediff-util.el ends here