(vip-leave-region-active): new function.
[emacs.git] / lisp / ediff-util.el
blobd12d19f1f02fac6c0da858bac7ad32c9c7a88b91
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)
11 ;; any later version.
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.
23 ;;; Code:
25 (require 'ediff-init)
28 ;;; Functions
30 (defun ediff-mode ()
31 "Ediff mode is used by the Ediff file-difference package.
32 It is entered only through one of the following commands:
33 `ediff'
34 `ediff-files'
35 `ediff-buffers'
36 `ediff3'
37 `ediff-files3'
38 `ediff-buffers3'
39 `ediff-merge'
40 `ediff-merge-files'
41 `ediff-merge-files-with-ancestor'
42 `ediff-merge-buffers'
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'
50 `epatch'
51 `ediff-patch-file'
52 `ediff-patch-buffer'
53 `epatch-buffer'
54 `ediff-revision'
56 Commands:
57 \\{ediff-mode-map}"
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."
66 (interactive)
67 (if (interactive-p)
68 (message (ediff-version))
69 (format "Ediff %s of %s" ediff-version ediff-date)))
72 (require 'ediff-diff)
73 (require 'ediff-merg)
76 ;;; Build keymaps
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
81 to 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)
87 (ediff-setup-keymap))
88 (use-local-map ediff-mode-map))
90 ;; Reload Ediff keymap. For debugging only.
91 (defun ediff-reload-keymap ()
92 (interactive)
93 (setq ediff-mode-map nil)
94 (ediff-set-keys))
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)
123 (or ediff-word-mode
124 (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
125 (if ediff-narrow-job
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)
139 (or ediff-word-mode
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
147 (lambda (arg)
148 (interactive "P")
149 (ediff-diff-to-diff arg "ac"))))
150 (define-key ediff-mode-map "b" (function
151 (lambda (arg)
152 (interactive "P")
153 (ediff-diff-to-diff arg "bc"))))
154 (define-key ediff-mode-map "r" (function
155 (lambda (arg)
156 (interactive "P")
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
176 (lambda (arg)
177 (interactive "P")
178 (ediff-diff-to-diff arg "ab"))))
179 (define-key ediff-mode-map "b" (function
180 (lambda (arg)
181 (interactive "P")
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))
185 ) ; cond
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)
190 (or ediff-word-mode
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)
199 (if ediff-3way-job
200 (progn
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))
215 ;;; Setup functions
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))
225 (if (stringp file-C)
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
232 (ediff-mode)
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
257 (if ediff-merge-job
258 (let ((buf
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)
269 (setq buffer-C
270 (get-buffer-create
271 (ediff-unique-buffer-name "*ediff-merge" "*")))
272 (save-excursion
273 (set-buffer buffer-C)
274 (insert-buffer buf)
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
291 (max
294 (string-to-number
295 (substring
296 ediff-control-buffer-suffix
298 (string-match "[0-9]+" ediff-control-buffer-suffix)
299 0))))))
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))
306 (if ediff-3way-job
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
314 (if ediff-diff3-job
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)))
363 (if ediff-3way-job
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
370 (cons control-buffer
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)
382 (if ediff-3way-job
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
400 (save-excursion
401 (select-window ediff-window-A)
402 (goto-char shift-A))
403 ;; position point in buf B
404 (save-excursion
405 (select-window ediff-window-B)
406 (goto-char shift-B))
407 (if ediff-3way-job
408 (save-excursion
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")
428 (sleep-for 1))
429 (message "")
432 (run-hooks 'startup-hooks 'ediff-startup-hooks)
433 (ediff-refresh-mode-lines)
434 (setq buffer-read-only t))
435 control-buffer))
438 ;; This function assumes that we are in the window where control buffer is
439 ;; to reside.
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))
446 (erase-buffer)
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"
457 ediff-control-window
458 ediff-window-A
459 ediff-window-B
460 ediff-window-C
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
468 ;; help message
469 (defun ediff-help-message-line-length ()
470 (save-excursion
471 (goto-char (point-min))
472 (if ediff-prefer-long-help-message
473 (next-line 1))
474 (end-of-line)
475 (current-column)))
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 ?\ )))
483 (save-excursion
484 (goto-char (point-min))
485 (while (< (point) (point-max))
486 (insert str)
487 (beginning-of-line)
488 (forward-line 1)))))
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))
497 (ediff-word-mode
498 (concat ediff-long-help-message-head
499 ediff-long-help-message-word-mode
500 ediff-long-help-message-tail))
501 (ediff-narrow-job
502 (concat ediff-long-help-message-head
503 ediff-long-help-message-narrow2
504 ediff-long-help-message-tail))
505 (ediff-merge-job
506 (concat ediff-long-help-message-head
507 ediff-long-help-message-merge
508 ediff-long-help-message-tail))
509 (ediff-diff3-job
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,
543 if necessary."
544 (interactive)
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))
548 (buf-A-file-name
549 (file-name-nondirectory (or (buffer-file-name ediff-buffer-A)
550 (buffer-name ediff-buffer-A)
552 (buf-B-file-name
553 (file-name-nondirectory (or (buffer-file-name ediff-buffer-B)
554 (buffer-name ediff-buffer-B)
556 (buf-C-file-name
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))
580 (if ediff-word-mode
581 (progn
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")))
588 (if ediff-3way-job
589 (progn
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")))))
594 ;; not word-mode
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)))
599 (if ediff-3way-job
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
610 ;; comparison
611 (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
612 (ediff-job-name ediff-job-name))
613 (if ediff-merge-job
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))
619 (delete-file file-A)
620 (delete-file file-B)
621 (if file-C
622 (delete-file file-C))
624 (if ediff-3way-job
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))
628 (message "")
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."
634 (interactive "P")
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
648 (if comparison
649 (ediff-eval-in-buffer bufC
650 (revert-buffer t noconfirm)))
651 (if merge
652 (progn
653 (set-buffer ctl-buf)
654 (ediff-really-quit)
655 (kill-buffer bufC)
656 (if ancestor-job
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."
666 (interactive)
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)))
678 (ediff-setup-windows
679 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
680 (or (eq this-command 'ediff-quit)
681 (message
682 "You've killed an essential Ediff buffer---Please quit Ediff"
683 (beep 1)))
686 ;; set visibility range appropriate to this invocation of Ediff.
687 (ediff-visible-region)
689 ;; raise
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
695 '(ediff-recenter
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)))
706 (progn
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))
726 (progn
727 (or no-rehighlight
728 (ediff-select-difference ediff-current-difference))
730 (ediff-recenter-one-window 'A)
731 (ediff-recenter-one-window 'B)
732 (if ediff-3way-job
733 (ediff-recenter-one-window 'C))
735 (if (and (ediff-multiframe-setup-p)
736 (not (ediff-frame-iconified-p ediff-control-frame)))
737 (progn
738 (ediff-reset-mouse control-frame)
739 (or ediff-xemacs-p
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))
765 (if window
766 (progn
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)
773 job-name
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."
783 (interactive)
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."
806 (interactive)
807 (if (not (ediff-window-display-p))
808 (if (eq ediff-highlighting-style 'ascii)
809 (progn
810 (message "ASCII highlighting flags removed")
811 (ediff-unselect-and-select-difference ediff-current-difference
812 'unselect-only)
813 (setq ediff-highlighting-style 'off))
814 (ediff-unselect-and-select-difference ediff-current-difference
815 'select-only))
816 (ediff-unselect-and-select-difference ediff-current-difference
817 'unselect-only)
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))
822 (ediff-use-faces
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))
832 (progn
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."
853 (interactive)
854 (if ediff-word-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))
863 (t ;; nix 'em
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."
872 (interactive "P")
873 (cond ((eq arg '-)
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."
882 (interactive)
883 (let (buffer-read-only)
884 (erase-buffer)
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."
903 (interactive)
904 (let ((ctl-buf (if (null buf) (current-buffer))))
905 (or buf (ediff-recenter))
906 (or buf
907 (setq buf
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
913 (file-exists-p file)
914 (file-writable-p file)))
915 (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
916 ((ediff-file-checked-out-p file)
917 'toggle-read-only)
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
923 ;; user problem.
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
927 ctl-buf)
928 (cond ((not buffer-read-only)
929 (setq toggle-ro-cmd 'toggle-read-only))
930 ((and (or (beep 1) t) ; always beep
931 (y-or-n-p
932 (format
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
939 ;; is checked in.
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)
946 (beep 1) (beep 1)
947 (message
948 "Boy, this is risky! Better don't change this file...")
949 (sit-for 3))))
950 (if (and toggle-ro-cmd
951 (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
952 (save-excursion
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)
961 (file-exists-p file)
962 (not (file-writable-p file)))
963 (message "Warning: file %s is read-only"
964 (abbreviate-file-name file) (beep 1)))
965 ))))
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)
975 (and (stringp file)
976 (file-exists-p file)
977 (file-writable-p file)
978 (file-exists-p (concat file ",v"))))
979 (defsubst ediff-file-checked-in-p (file)
980 (and (stringp file)
981 (file-exists-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."
987 (interactive)
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
998 (progn
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
1009 ediff-buffer-B buf)
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)))
1052 ;; swap wide bounds
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)))
1058 (ediff-3way-job
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)))
1071 (ediff-3way-job
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))
1082 (if ediff-3way-job
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."
1091 (interactive)
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
1104 ;; during resizing
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."
1118 (interactive)
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))
1129 ;; Merging
1131 (defun ediff-toggle-show-clashes-only ()
1132 "Toggle the mode where only the regions where both buffers differ with the ancestor are shown."
1133 (interactive)
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."
1146 (interactive)
1147 (if (eq ediff-buffer-A ediff-buffer-B)
1148 (error
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
1178 (narrow-to-region
1179 (ediff-overlay-start overl-A) (ediff-overlay-end overl-A)))
1180 (ediff-eval-in-buffer ediff-buffer-B
1181 (narrow-to-region
1182 (ediff-overlay-start overl-B) (ediff-overlay-end overl-B)))
1184 (if ediff-3way-job
1185 (ediff-eval-in-buffer ediff-buffer-C
1186 (narrow-to-region
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)
1215 (condition-case nil
1216 (funcall operation arg)
1217 (error))
1218 (select-window wind-B)
1219 (condition-case nil
1220 (funcall operation arg)
1221 (error))
1222 (if three-way
1223 (progn
1224 (select-window wind-C)
1225 (condition-case nil
1226 (funcall operation arg)
1227 (error))))
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."
1235 (interactive "P")
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))
1249 'scroll-up
1250 'scroll-down)
1251 ;; calculate argument to scroll-up/down
1252 ;; if there is an explicit argument
1253 (if (and arg (not (equal arg '-)))
1254 ;; use it
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)
1261 (if ediff-3way-job
1262 (window-height ediff-window-C)
1263 123) ; some large number
1265 1 next-screen-context-lines))
1266 ;; window found
1267 (if arg
1268 ;; C-u as argument means half of default amount
1269 (/ default-amount 2)
1270 ;; no argument means default amount
1271 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."
1278 (interactive "P")
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 ?<)
1292 'scroll-left
1293 'scroll-right)
1294 ;; calculate argument to scroll-left/right
1295 ;; if there is an explicit argument
1296 (if (and arg (not (equal arg '-)))
1297 ;; use it
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
1312 3)))
1313 ;; window found
1314 (if arg
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
1323 ;;differently.
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.
1332 (save-excursion
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
1339 (let ((lines 0)
1340 (prev-point 0))
1341 (while ( and (> end (progn
1342 (move-to-window-line lines)
1343 (point)))
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
1350 (goto-char beg)
1351 (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
1352 lines)
1355 2))))
1356 (goto-char pos)
1360 (defun ediff-next-difference (&optional arg)
1361 "Advance to the next difference.
1362 With a prefix argument, go back that many differences."
1363 (interactive "P")
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))))
1367 regexp-skip)
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)
1374 ;; regexp skip
1375 regexp-skip
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))))
1383 (setq n (1+ 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))
1390 (message "")
1391 (ediff-unselect-and-select-difference n)
1392 ) ; let
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."
1399 (interactive "P")
1400 (if (> ediff-current-difference -1)
1401 (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
1402 regexp-skip)
1404 (or (< n 0)
1405 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1406 (ediff-install-fine-diff-if-necessary n))
1407 (while (and (> n -1)
1409 ;; regexp skip
1410 regexp-skip
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)))
1420 (setq n (1- n))
1421 (or (< n 0)
1422 (setq regexp-skip (funcall ediff-skip-diff-region-function n))
1423 (ediff-install-fine-diff-if-necessary n))
1425 (message "")
1426 (ediff-unselect-and-select-difference n)
1427 ) ; let
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."
1433 (interactive "p")
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."
1444 (interactive)
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))
1454 (diff-no -1)
1455 (prev-beg 0)
1456 (prev-end 0)
1457 (beg 0)
1458 (end 0))
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))
1465 (setq prev-beg beg
1466 prev-end end)
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))
1472 (abs (- pos beg)))
1473 diff-no
1474 (1+ diff-no)) ; jump-to-diff works with diff nums higher by 1
1478 ;;; Copying diffs.
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."
1491 (interactive "P")
1492 (or keys (setq keys (this-command-keys)))
1493 (if arg
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
1508 ;; version.
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)
1514 (saved-p t)
1515 (three-way ediff-3way-job)
1516 messg
1517 ediff-verbose-p
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))
1525 (if reg-to-copy
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
1537 ;; seems ok to copy
1538 (if (or batch-invocation (ediff-test-save-region n to-buf-type))
1539 (condition-case conds
1540 (progn
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.
1547 (if ediff-xemacs-p
1548 (progn
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 "@"
1556 (if ediff-xemacs-p
1557 (delete-char 1))
1559 (if ediff-xemacs-p
1560 (if (> reg-to-delete-end reg-to-delete-beg)
1561 (kill-region reg-to-delete-beg
1562 reg-to-delete-end))
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
1569 (setq
1570 messg
1571 (ediff-save-diff-region n to-buf-type reg-to-delete))))
1572 (error (message "ediff-copy-diff: %s %s"
1573 (car conds)
1574 (mapconcat 'prin1-to-string (cdr conds) " "))
1575 (beep 1)
1576 (sit-for 2)
1577 (setq saved-p nil)
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
1599 ;; by the user
1600 (message messg))
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
1606 ;; convenience.
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
1614 ;; overriding
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'"
1622 (1+ n) buf-type
1623 (if ediff-merge-job
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
1634 (if (yes-or-no-p
1635 (format
1636 "You've previously copied diff region %d to buffer %S. Confirm "
1637 (1+ n) buf-type))
1639 (error "Quit"))
1640 t)))
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)
1649 ediff-verbose-p
1650 saved-diff reg-beg reg-end recovered)
1652 (if (cdr saved-rec)
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.
1668 (if ediff-xemacs-p
1669 (progn
1670 (goto-char reg-end)
1671 (insert-before-markers "@")))
1673 (goto-char reg-end)
1674 (insert-before-markers saved-diff)
1676 ;; delete dummy char
1677 (if ediff-xemacs-p
1678 (delete-char 1))
1680 (if ediff-xemacs-p
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)
1688 (setq recovered t)
1690 (error (message "ediff-pop-diff: %s %s"
1691 (car conds)
1692 (mapconcat 'prin1-to-string (cdr conds) " "))
1693 (beep 1)))
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
1699 ;; fine diffs.
1700 (if recovered
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)
1709 (if recovered
1710 (progn
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"
1722 (interactive "P")
1723 (if arg
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."
1732 (interactive)
1733 (let ((regexp-A "")
1734 (regexp-B "")
1735 (regexp-C "")
1736 msg-connective alt-msg-connective alt-connective)
1737 (cond
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
1747 regexp-A
1748 (read-string
1749 (format
1750 "Ignore A-regions matching this regexp (default \"%s\"): "
1751 ediff-regexp-hide-A))
1752 regexp-B
1753 (read-string
1754 (format
1755 "Ignore B-regions matching this regexp (default \"%s\"): "
1756 ediff-regexp-hide-B)))
1757 (if ediff-3way-comparison-job
1758 (setq regexp-C
1759 (read-string
1760 (format
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"
1766 alt-connective 'or)
1767 (setq msg-connective "ONE OF"
1768 alt-msg-connective "BOTH"
1769 alt-connective 'and))
1770 (if (y-or-n-p
1771 (format
1772 "Hiding diff regions that match %s regexps. Use %s instead? "
1773 msg-connective alt-msg-connective))
1774 (progn
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
1784 regexp-A
1785 (read-string
1786 (format
1787 "Focus on A-regions matching this regexp (default \"%s\"): "
1788 ediff-regexp-focus-A))
1789 regexp-B
1790 (read-string
1791 (format
1792 "Focus on B-regions matching this regexp (default \"%s\"): "
1793 ediff-regexp-focus-B)))
1794 (if ediff-3way-comparison-job
1795 (setq regexp-C
1796 (read-string
1797 (format
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"
1803 alt-connective 'or)
1804 (setq msg-connective "ONE OF"
1805 alt-msg-connective "BOTH"
1806 alt-connective 'and))
1807 (if (y-or-n-p
1808 (format
1809 "Focusing on diff regions that match %s regexps. Use %s instead? "
1810 msg-connective alt-msg-connective))
1811 (progn
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"
1816 msg-connective))
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 ()
1822 (interactive)
1823 (if (not (eq ediff-auto-refine 'on))
1824 (error
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
1828 (message
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))
1849 (re-search-forward
1850 regex-A
1851 (ediff-get-diff-posn 'A 'end n ctl-buf)
1852 t)))
1853 (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
1854 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
1855 (re-search-forward
1856 regex-B
1857 (ediff-get-diff-posn 'B 'end n ctl-buf)
1858 t)))
1859 (reg-C-match (if ediff-3way-comparison-job
1860 (ediff-eval-in-buffer ediff-buffer-C
1861 (goto-char
1862 (ediff-get-diff-posn 'C 'beg n ctl-buf))
1863 (re-search-forward
1864 regex-C
1865 (ediff-get-diff-posn 'C 'end n ctl-buf)
1866 t)))))
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))
1890 (re-search-forward
1891 regex-A
1892 (ediff-get-diff-posn 'A 'end n ctl-buf)
1893 t)))
1894 (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
1895 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
1896 (re-search-forward
1897 regex-B
1898 (ediff-get-diff-posn 'B 'end n ctl-buf)
1899 t)))
1900 (reg-C-match (if ediff-3way-comparison-job
1901 (ediff-eval-in-buffer ediff-buffer-C
1902 (goto-char
1903 (ediff-get-diff-posn 'C 'beg n ctl-buf))
1904 (re-search-forward
1905 regex-C
1906 (ediff-get-diff-posn 'C 'end n ctl-buf)
1907 t)))))
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\)."
1923 (interactive)
1924 (if (prog1
1925 (y-or-n-p "Do you really want to exit Ediff? ")
1926 (message ""))
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))))
1952 ediff-wide-bounds)
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))
1960 (condition-case nil
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)
1967 (error))
1969 (condition-case nil
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)
1976 (error))
1978 (condition-case nil
1979 (ediff-eval-in-buffer ediff-buffer-C
1980 (kill-local-variable 'mode-line-buffer-identification)
1981 (kill-local-variable 'mode-line-format)
1983 (error))
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)
2020 ;;(redraw-display)
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
2028 (condition-case nil
2029 (or (ediff-get-visible-buffer-window buff-B)
2030 (switch-to-buffer buff-B))
2031 (error))
2032 (condition-case nil
2033 (or (ediff-get-visible-buffer-window buff-A)
2034 (progn
2035 (if (ediff-get-visible-buffer-window buff-B)
2036 (split-window-vertically))
2037 (switch-to-buffer buff-A)))
2038 (error))
2039 (if three-way-job
2040 (condition-case nil
2041 (or (ediff-get-visible-buffer-window buff-C)
2042 (progn
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)
2047 (balance-windows)))
2048 (error)))
2049 (message "")
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)
2091 (bury-buffer))
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)
2099 (progn
2100 (select-window buf-A-wind)
2101 (delete-other-windows)
2102 (bury-buffer))
2103 (if (ediff-buffer-live-p buf-A) (bury-buffer buf-A)))
2104 (if (window-live-p buf-B-wind)
2105 (progn
2106 (select-window buf-B-wind)
2107 (delete-other-windows)
2108 (bury-buffer))
2109 (if (ediff-buffer-live-p buf-B) (bury-buffer buf-B)))
2110 (if (window-live-p buf-C-wind)
2111 (progn
2112 (select-window buf-C-wind)
2113 (delete-other-windows)
2114 (bury-buffer))
2115 (if (ediff-buffer-live-p buf-C) (bury-buffer buf-C)))
2120 (defun ediff-suspend ()
2121 "Suspend Ediff.
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."
2125 (interactive)
2126 (let ((key (substitute-command-keys "\\[ediff-recenter]")))
2127 (run-hooks 'ediff-suspend-hooks)
2128 (message
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."
2135 (interactive)
2136 (with-output-to-temp-buffer " *ediff-info*"
2137 (princ (ediff-version))
2138 (princ "\n\n")
2139 (ediff-eval-in-buffer ediff-buffer-A
2140 (if buffer-file-name
2141 (princ
2142 (format "File A = %S\n" buffer-file-name))
2143 (princ
2144 (format "Buffer A = %S\n" (buffer-name)))))
2145 (ediff-eval-in-buffer ediff-buffer-B
2146 (if buffer-file-name
2147 (princ
2148 (format "File B = %S\n" buffer-file-name))
2149 (princ
2150 (format "Buffer B = %S\n" (buffer-name)))))
2151 (if ediff-3way-job
2152 (ediff-eval-in-buffer ediff-buffer-C
2153 (if buffer-file-name
2154 (princ
2155 (format "File C = %S\n" buffer-file-name))
2156 (princ
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)))))
2163 C-line)
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))
2166 (if ediff-3way-job
2167 (progn
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)
2186 (princ
2187 "\nIgnoring regions that match")
2188 (princ
2189 (format
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)
2194 (princ
2195 "\nFocusing on regions that match")
2196 (princ
2197 (format
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")))
2203 (princ
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."
2210 (interactive)
2211 (let ((ctl-window ediff-control-window)
2212 (ctl-buf ediff-control-buffer))
2214 (ediff-skip-unsuitable-frames)
2215 (condition-case nil
2216 (progn
2217 (pop-to-buffer (get-buffer-create "*info*"))
2218 (info "ediff")
2219 (message "Type `i' to search for a specific topic"))
2220 (error (beep 1)
2221 (with-output-to-temp-buffer " *ediff-info*"
2222 (princ (format "
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)
2229 (progn
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))
2245 (progn
2246 (if (and (ediff-window-display-p) ediff-use-faces)
2247 (progn
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)
2255 (if ediff-3way-job
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)
2268 (progn
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
2273 ediff-buffer-A
2274 (ediff-get-diff-overlay n 'A))
2275 (ediff-remove-flags-from-buffer
2276 ediff-buffer-B
2277 (ediff-get-diff-overlay n 'B))
2278 (if ediff-3way-job
2279 (ediff-remove-flags-from-buffer
2280 ediff-buffer-C
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))
2299 (or no-recenter
2300 (ediff-recenter 'no-rehighlight)))
2302 (let ((control-buf ediff-control-buffer))
2303 (unwind-protect
2304 (progn
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
2327 (setq default-dir
2328 (file-name-as-directory
2329 (abbreviate-file-name
2330 (expand-file-name (or default-dir
2331 (and default-file
2332 (file-name-directory default-file))
2333 default-directory)))))
2335 ;; strip the directory from default-file
2336 (if default-file
2337 (setq default-file (file-name-nondirectory default-file)))
2338 (if (string= default-file "")
2339 (setq default-file nil))
2341 (let (f)
2342 (setq f (expand-file-name
2343 (read-file-name
2344 (format "%s%s: "
2345 prompt
2346 (if default-file
2347 (concat " (default " default-file ")")
2348 ""))
2349 default-dir
2350 default-file
2351 t ; must match, no-confirm
2352 (if default-file (file-name-directory default-file))
2354 default-dir
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)))
2363 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
2374 (if prefix
2375 (concat prefix "_")
2376 "ediff_"))))))
2377 ;; create the file
2378 (write-region (if start start (point-min))
2379 (if end end (point-max))
2381 nil ; don't append---erase
2382 'no-message)
2383 (set-file-modes f ediff-temp-file-mode)
2386 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
2387 ;; EMX OS/2
2388 (defun ediff-protect-metachars (str)
2389 (or (memq system-type '(emx vax-vms axp-vms))
2390 (let ((limit 0))
2391 (while (string-match ediff-metachars str limit)
2392 (setq str (concat (substring str 0 (match-beginning 0))
2393 "\\"
2394 (substring str (match-beginning 0))))
2395 (setq limit (1+ (match-end 0))))))
2396 str)
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
2411 (if (yes-or-no-p
2412 (format "Buffer out of sync with visited file. %s file %s? "
2413 (if file-magic "Revert" "Save")
2414 buffer-file-name))
2415 (if (not file-magic)
2416 (save-buffer)
2417 ;; for some reason, file-name-handlers append instead of
2418 ;; replacing, so we have to erase first.
2419 (erase-buffer)
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
2423 nil)
2424 ;; If buffer is obsolete, offer to revert
2425 (if (yes-or-no-p
2426 (format "Buffer out of sync with visited file. Revert file %s? "
2427 buffer-file-name))
2428 (progn
2429 (if file-magic
2430 (erase-buffer))
2431 (revert-buffer t t))
2432 (error "Buffer out of sync for file %s" buffer-file-name))))
2436 (defun ediff-check-for-ascii-flags ()
2437 (eval
2438 (cons 'or
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
2451 ;; the overlay end.
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)))
2458 ;; ))
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))
2462 ;; ))
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
2480 posn
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."
2491 (interactive "P")
2492 (ediff-eval-in-buffer
2493 (cond ((memq last-command-char '(?a ?b ?c))
2494 (ediff-get-buffer
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)
2500 (save-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))
2507 (if ediff-xemacs-p
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
2511 ;; this function
2512 (ediff-overlay-put overlay 'before-string nil))
2514 (if ediff-xemacs-p
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
2535 (goto-char before)
2536 (setq beg-of-line (bolp))
2538 (setq flag (ediff-eval-in-buffer ctl-buffer
2539 (if (eq ediff-highlighting-style 'ascii)
2540 (if beg-of-line
2541 ediff-before-flag-bol ediff-before-flag-mol))))
2543 ;; insert the flag itself
2544 (if ediff-xemacs-p
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))
2551 (goto-char after)
2552 (setq beg-of-line (bolp))
2554 (setq flag (ediff-eval-in-buffer ctl-buffer
2555 (if (eq ediff-highlighting-style 'ascii)
2556 (if beg-of-line
2557 ediff-after-flag-eol ediff-after-flag-mol))))
2559 ;; insert the flag itself
2560 (if ediff-xemacs-p
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
2575 buffer."
2576 (let (diff-overlay)
2577 (or control-buf
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)))
2589 (if (eq pos 'beg)
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
2605 (symbol-value
2606 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2607 (odd-diff-face
2608 (symbol-value
2609 (intern (format "ediff-odd-diff-face-%S" buf-type))))
2610 (even-diff-face
2611 (symbol-value
2612 (intern (format "ediff-even-diff-face-%S" buf-type))))
2613 (odd-diff-face-var
2614 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2615 (even-diff-face-var
2616 (intern (format "ediff-even-diff-face-%S-var" buf-type)))
2619 (if ediff-xemacs-p
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)
2630 (progn
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
2643 (symbol-value
2644 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2645 (odd-diff-face-var
2646 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2647 (even-diff-face-var
2648 (intern (format "ediff-even-diff-face-%S-var" buf-type)))
2649 (overlay
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)
2659 odd-diff-face-var
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))
2670 (odd-diff-face-var
2671 (intern (format "ediff-odd-diff-face-%S-var" buf-type)))
2672 (even-diff-face-var
2673 (intern (format "ediff-even-diff-face-%S-var" buf-type))))
2674 (if (face-differs-from-default-p odd-diff-face-var)
2675 (progn
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))
2689 (mapcar (function
2690 (lambda (elt)
2691 (ediff-delete-overlay
2692 (ediff-get-diff-overlay-from-diff-record elt))
2693 (if fine-diffs-also
2694 (ediff-clear-fine-diff-vector elt))
2696 (symbol-value vec-var)))
2697 ;; allow them to be garbage collected
2698 (set vec-var nil))
2702 ;;; Misc
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)
2711 (if ediff-xemacs-p
2712 (set-extent-endpoints overlay beg end)
2713 (move-overlay overlay beg end buffer))
2714 ;; buffer's dead
2715 (if overlay
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))
2722 (if ediff-xemacs-p
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
2733 ;; bounds.
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)
2738 (let (overl)
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))
2746 (if ediff-xemacs-p
2747 (progn
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)
2762 overl))))
2764 (defsubst ediff-overlay-start (overl)
2765 (if (ediff-overlayp overl)
2766 (if ediff-emacs-p
2767 (overlay-start overl)
2768 (extent-start-position overl))))
2770 (defsubst ediff-overlay-end (overl)
2771 (if (ediff-overlayp overl)
2772 (if ediff-emacs-p
2773 (overlay-end 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
2780 ;; these buffers).
2781 (defun ediff-other-buffer (buff)
2782 (if (not (listp buff)) (setq buff (list buff)))
2783 (let* ((frame-buffers (buffer-list))
2784 (significant-buffers
2785 (mapcar
2786 (function (lambda (x)
2787 (cond ((member (buffer-name x) buff)
2788 nil)
2789 ((not (ediff-get-visible-buffer-window x))
2790 nil)
2791 ((string-match "^ " (buffer-name x))
2792 nil)
2793 (t x))))
2794 frame-buffers))
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
2801 (delq nil
2802 (mapcar
2803 (function
2804 (lambda (x)
2805 (cond ((member (buffer-name x) buff) nil)
2806 ((string-match "^[ *]" (buffer-name x)) nil)
2807 (t x))))
2808 frame-buffers)))
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)
2820 (let ((n 2))
2821 (while (get-buffer (format "%s<%d>%s" prefix n suffix))
2822 (setq n (1+ n)))
2823 (format "%s<%d>%s" prefix n suffix))))
2826 (defun ediff-submit-report ()
2827 "Submit bug report on Ediff."
2828 (interactive)
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
2835 ediff-shell
2836 ediff-use-faces
2837 ediff-auto-refine ediff-highlighting-style
2838 ediff-buffer-A ediff-buffer-B ediff-control-buffer
2839 ediff-forward-word-function
2840 ediff-control-frame
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
2846 ediff-job-name
2847 ediff-word-mode
2848 buffer-name
2849 ediff-device-type
2851 (setq salutation "
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)
2860 (ediff-reset-mouse)
2862 (switch-to-buffer ediff-msg-buffer)
2863 (erase-buffer)
2864 (delete-other-windows)
2865 (insert "
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
2875 manipulation.
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? ")
2900 (progn
2901 (if (ediff-buffer-live-p ctl-buf)
2902 (set-buffer ctl-buf))
2903 (setq buffer-name (buffer-name))
2904 (require 'reporter)
2905 (reporter-submit-bug-report "kifer@cs.sunysb.edu"
2906 (ediff-version)
2907 varlist
2908 nil
2909 'delete-other-windows
2910 salutation))
2911 (bury-buffer)
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))))
2931 (while list2
2932 (or (memq (car list2) list1)
2933 (setq list1 (cons (car list2) list1)))
2934 (setq list2 (cdr list2)))
2935 list1)))
2937 (defun ediff-deactivate-mark ()
2938 (if ediff-xemacs-p
2939 (zmacs-deactivate-region)
2940 (deactivate-mark)))
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 ()
2947 (save-excursion
2948 (save-restriction
2949 (widen)
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)
2955 (end-of-line)
2956 (setq end (point))
2957 (beginning-of-line)
2958 (while (search-forward "\^M" end t)
2959 (delete-char -1)
2960 (insert "\^J"))))
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))))
2971 vars))
2972 ;; VARS is a list of variable symbols.
2973 (defun ediff-restore-variables (vars assoc-list)
2974 (while vars
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)
2978 (let* ((assoc-list
2979 (symbol-value (intern
2980 (concat "ediff-buffer-values-orig-"
2981 (symbol-name buf-type)))))
2982 (assoc-elt (assoc var assoc-list)))
2983 (if assoc-elt
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)))))
3014 ;;; Debug
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))
3021 micro sec)
3022 (setq micro
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."
3035 (interactive)
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))
3051 (mapcar (function
3052 (lambda (overl-vec)
3053 (princ
3054 (format
3055 "Diff %d: \tOverlay: %S
3056 \t\tFine diffs: %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))
3062 (aref overl-vec 0)
3063 ;; fine-diff-vector
3064 (if (= (length (aref overl-vec 1)) 0)
3065 "none\n"
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
3071 ))))
3072 (eval diff-vector-var)))
3076 (defun ediff-debug-info ()
3077 (interactive)
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)
3096 ;;; End:
3098 (provide 'ediff-util)
3100 ;;; ediff-util.el ends here