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