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