aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Kifer1996-09-20 01:10:05 +0000
committerMichael Kifer1996-09-20 01:10:05 +0000
commit92c51e075e8bc9c2ace8487bfc42f23389d09b73 (patch)
treec1d584dd76b465b332fb990530a5987752ea5054
parentf49e14457537c130733cb10a20ff8d16d1a0bcc1 (diff)
downloademacs-92c51e075e8bc9c2ace8487bfc42f23389d09b73.tar.gz
emacs-92c51e075e8bc9c2ace8487bfc42f23389d09b73.zip
*** empty log message ***
-rw-r--r--lisp/ediff-diff.el63
-rw-r--r--lisp/ediff-hook.el2
-rw-r--r--lisp/ediff-init.el372
-rw-r--r--lisp/ediff-merg.el6
-rw-r--r--lisp/ediff-mult.el282
-rw-r--r--lisp/ediff-ptch.el132
-rw-r--r--lisp/ediff-util.el412
-rw-r--r--lisp/ediff-vers.el28
-rw-r--r--lisp/ediff-wind.el5
-rw-r--r--lisp/ediff.el96
-rw-r--r--lisp/emulation/viper-util.el6
-rw-r--r--lisp/emulation/viper.el15
12 files changed, 877 insertions, 542 deletions
diff --git a/lisp/ediff-diff.el b/lisp/ediff-diff.el
index 8f714318f15..31e126c2292 100644
--- a/lisp/ediff-diff.el
+++ b/lisp/ediff-diff.el
@@ -140,31 +140,45 @@ one optional arguments, diff-number to refine.")
140;; Run the diff program on FILE1 and FILE2 and put the output in DIFF-BUFFER 140;; Run the diff program on FILE1 and FILE2 and put the output in DIFF-BUFFER
141;; Return the size of DIFF-BUFFER 141;; Return the size of DIFF-BUFFER
142(defun ediff-make-diff2-buffer (diff-buffer file1 file2) 142(defun ediff-make-diff2-buffer (diff-buffer file1 file2)
143 (cond ((< (ediff-file-size file1) 0) 143 (let ((file1-size (ediff-file-size file1))
144 (message "Can't diff remote files: %s" 144 (file2-size (ediff-file-size file2)))
145 (ediff-abbreviate-file-name file1)) 145 (cond ((not (numberp file1-size))
146 (sit-for 2) 146 (message "Can't find file: %s"
147 ;; 1 is an error exit code 147 (ediff-abbreviate-file-name file1))
148 1) 148 (sit-for 2)
149 ((< (ediff-file-size file2) 0) 149 ;; 1 is an error exit code
150 (message "Can't diff remote file: %s" 150 1)
151 (ediff-abbreviate-file-name file2)) 151 ((not (numberp file2-size))
152 (sit-for 2) 152 (message "Can't find file: %s"
153 (message "") 153 (ediff-abbreviate-file-name file2))
154 ;; 1 is an error exit code 154 (sit-for 2)
155 1) 155 ;; 1 is an error exit code
156 (t (message "Computing differences between %s and %s ..." 156 1)
157 (file-name-nondirectory file1) 157 ((< file1-size 0)
158 (file-name-nondirectory file2)) 158 (message "Can't diff remote files: %s"
159 ;; this erases the diff buffer automatically 159 (ediff-abbreviate-file-name file1))
160 (ediff-exec-process ediff-diff-program 160 (sit-for 2)
161 diff-buffer 161 ;; 1 is an error exit code
162 'synchronize 162 1)
163 ediff-diff-options file1 file2) 163 ((< file2-size 0)
164 ;;(message "Computing differences ... done") 164 (message "Can't diff remote file: %s"
165 (ediff-abbreviate-file-name file2))
166 (sit-for 2)
165 (message "") 167 (message "")
166 (ediff-eval-in-buffer diff-buffer 168 ;; 1 is an error exit code
167 (buffer-size))))) 169 1)
170 (t (message "Computing differences between %s and %s ..."
171 (file-name-nondirectory file1)
172 (file-name-nondirectory file2))
173 ;; this erases the diff buffer automatically
174 (ediff-exec-process ediff-diff-program
175 diff-buffer
176 'synchronize
177 ediff-diff-options file1 file2)
178 ;;(message "Computing differences ... done")
179 (message "")
180 (ediff-eval-in-buffer diff-buffer
181 (buffer-size))))))
168 182
169 183
170 184
@@ -1187,6 +1201,7 @@ argument to `skip-chars-forward'."
1187;;; Local Variables: 1201;;; Local Variables:
1188;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 1202;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1189;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 1203;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1204;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1190;;; End: 1205;;; End:
1191 1206
1192(provide 'ediff-diff) 1207(provide 'ediff-diff)
diff --git a/lisp/ediff-hook.el b/lisp/ediff-hook.el
index 4b20d083b16..0b9dc1fb61c 100644
--- a/lisp/ediff-hook.el
+++ b/lisp/ediff-hook.el
@@ -299,7 +299,7 @@
299 299
300 ;; misc 300 ;; misc
301 (autoload 'ediff-show-registry 301 (autoload 'ediff-show-registry
302 "ediff-meta" 302 "ediff-mult"
303 "Display the registry of active Ediff sessions." 303 "Display the registry of active Ediff sessions."
304 t) 304 t)
305 (autoload 'ediff-documentation 305 (autoload 'ediff-documentation
diff --git a/lisp/ediff-init.el b/lisp/ediff-init.el
index 9eadd0b8556..f6aa724ee44 100644
--- a/lisp/ediff-init.el
+++ b/lisp/ediff-init.el
@@ -192,10 +192,6 @@ that Ediff doesn't know about.")
192 (error ediff-KILLED-VITAL-BUFFER)) 192 (error ediff-KILLED-VITAL-BUFFER))
193 )))) 193 ))))
194 194
195(put 'ediff-eval-in-buffer 'lisp-indent-function 1)
196(put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
197(put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
198
199 195
200(defsubst ediff-multiframe-setup-p () 196(defsubst ediff-multiframe-setup-p ()
201 (and (ediff-window-display-p) ediff-multiframe)) 197 (and (ediff-window-display-p) ediff-multiframe))
@@ -286,6 +282,15 @@ that Ediff doesn't know about.")
286 ediff-merge-directory-revisions-with-ancestor 282 ediff-merge-directory-revisions-with-ancestor
287 ;; add more here 283 ;; add more here
288 ))) 284 )))
285(defsubst ediff-merge-metajob (&optional metajob)
286 (memq (or metajob ediff-metajob-name)
287 '(ediff-merge-directories
288 ediff-merge-directories-with-ancestor
289 ediff-merge-directory-revisions
290 ediff-merge-directory-revisions-with-ancestor
291 ediff-merge-filegroups-with-ancestor
292 ;; add more here
293 )))
289 294
290(defsubst ediff-metajob3 (&optional metajob) 295(defsubst ediff-metajob3 (&optional metajob)
291 (memq (or metajob ediff-metajob-name) 296 (memq (or metajob ediff-metajob-name)
@@ -349,126 +354,11 @@ set local variables that determine how the display looks like.")
349 "*Hooks to run on exiting Ediff but before killing the control buffer. 354 "*Hooks to run on exiting Ediff but before killing the control buffer.
350This is a place to do various cleanups, such as deleting the variant buffers. 355This is a place to do various cleanups, such as deleting the variant buffers.
351Ediff provides a function, `ediff-janitor', as one such possible hook.") 356Ediff provides a function, `ediff-janitor', as one such possible hook.")
357(defvar ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge
358 "*Hooks to run before quitting a merge job.
359The most common use is to save and delete the merge buffer.")
352 360
353 361
354;; Help messages
355
356(defconst ediff-long-help-message-head
357 " Moving around | Toggling features | Manipulations
358=====================|===========================|============================="
359 "The head of the full help message.")
360(defconst ediff-long-help-message-tail
361 "=====================|===========================|=============================
362 R -show registry | | M -show session group
363 D -diff output | E -browse Ediff manual| G -send bug report
364 i -status info | ? -help off | z/q -suspend/quit
365-------------------------------------------------------------------------------
366X,Y (x,y) on the left are meta-symbols for the keys A,B,C (a,b,c).
367X,Y on the right are meta-symbols for buffers A,B,C.
368A,B,C on the right denote the working buffers A,B,C, respectively."
369 "The tail of the full-help message.")
370
371(defconst ediff-long-help-message-compare3
372 "
373p,DEL -previous diff | | -vert/horiz split | xy -copy buf X's region to Y
374n,SPC -next diff | h -hiliting | rx -restore buf X's old diff
375 j -jump to diff | @ -auto-refinement | * -refine current region
376 gx -goto X's point| | ! -update diff regions
377 C-l -recenter | ## -ignore whitespace |
378 v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
379 </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
380 | m -wide display | ~ -rotate buffers
381"
382 "Help message usually used for 3-way comparison.
383Normally, not a user option. See `ediff-help-message' for details.")
384
385(defconst ediff-long-help-message-compare2
386 "
387p,DEL -previous diff | | -vert/horiz split |a/b -copy A/B's region to B/A
388n,SPC -next diff | h -hiliting | rx -restore buf X's old diff
389 j -jump to diff | @ -auto-refinement | * -refine current region
390 gx -goto X's point| | ! -update diff regions
391 C-l -recenter | ## -ignore whitespace |
392 v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
393 </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
394 ~ -swap variants | m -wide display |
395"
396 "Help message usually used for 2-way comparison.
397Normally, not a user option. See `ediff-help-message' for details.")
398
399(defconst ediff-long-help-message-narrow2
400 "
401p,DEL -previous diff | | -vert/horiz split |a/b -copy A/B's region to B/A
402n,SPC -next diff | h -hiliting | rx -restore buf X's old diff
403 j -jump to diff | @ -auto-refinement | * -refine current region
404 gx -goto X's point| % -narrow/widen buffs | ! -update diff regions
405 C-l -recenter | ## -ignore whitespace |
406 v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
407 </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
408 ~ -swap variants | m -wide display |
409"
410 "Help message when comparing windows or regions line-by-line.
411Normally, not a user option. See `ediff-help-message' for details.")
412
413(defconst ediff-long-help-message-word-mode
414 "
415p,DEL -previous diff | | -vert/horiz split | xy -copy buf X's region to Y
416n,SPC -next diff | h -hiliting | rx -restore buf X's old diff
417 j -jump to diff | |
418 gx -goto X's point| % -narrow/widen buffs | ! -recompute diffs
419 C-l -recenter | |
420 v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
421 </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
422 ~ -swap variants | m -wide display |
423"
424 "Help message when comparing windows or regions word-by-word.
425Normally, not a user option. See `ediff-help-message' for details.")
426
427(defconst ediff-long-help-message-merge
428 "
429p,DEL -previous diff | | -vert/horiz split | x -copy buf X's region to C
430n,SPC -next diff | h -hiliting | r -restore buf C's old diff
431 j -jump to diff | @ -auto-refinement | * -refine current region
432 gx -goto X's point| ## -ignore whitespace | ! -update diff regions
433 C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions
434 v/V -scroll up/dn | X -read-only in buf X | wx -save buf X
435 </> -scroll lt/rt | m -wide display | wd -save diff output
436 ~ -swap variants | s -shrink window C | / -show ancestor buff
437 | $ -show clashes only | & -merge w/new default
438"
439 "Help message during merging.
440Normally, not a user option. See `ediff-help-message' for details.")
441
442;; The actual long help message.
443(ediff-defvar-local ediff-long-help-message ""
444 "Normally, not a user option. See `ediff-help-message' for details.")
445
446(defconst ediff-brief-message-string
447 " ? - help "
448 "Contents of the brief help message.")
449;; The actual brief help message
450(ediff-defvar-local ediff-brief-help-message ""
451 "Normally, not a user option. See `ediff-help-message' for details.")
452
453(ediff-defvar-local ediff-brief-help-message-function nil
454 "The brief help message that the user can customize.
455If the user sets this to a parameter-less function, Ediff will use it to
456produce the brief help message. This function must return a string.")
457(ediff-defvar-local ediff-long-help-message-function nil
458 "The long help message that the user can customize.
459See `ediff-brief-help-message-function' for more.")
460
461(defvar ediff-use-long-help-message nil
462 "*If t, Ediff displays a long help message. Short help message otherwise.")
463
464;; The actual help message.
465(ediff-defvar-local ediff-help-message ""
466 "The actual help message.
467Normally, the user shouldn't touch this. However, if you want Ediff to
468start up with different help messages for different jobs, you can change
469the value of this variable and the variables `ediff-help-message-*' in
470`ediff-startup-hook'.")
471
472;; Error messages 362;; Error messages
473(defconst ediff-KILLED-VITAL-BUFFER 363(defconst ediff-KILLED-VITAL-BUFFER
474 "You have killed a vital Ediff buffer---you must leave Ediff now!") 364 "You have killed a vital Ediff buffer---you must leave Ediff now!")
@@ -477,6 +367,12 @@ the value of this variable and the variables `ediff-help-message-*' in
477(defconst ediff-BAD-DIFF-NUMBER 367(defconst ediff-BAD-DIFF-NUMBER
478 ;; %S stands for this-command, %d - diff number, %d - max diff 368 ;; %S stands for this-command, %d - diff number, %d - max diff
479 "%S: Bad diff region number, %d. Valid numbers are 1 to %d") 369 "%S: Bad diff region number, %d. Valid numbers are 1 to %d")
370(defconst ediff-BAD-INFO (format "
371*** The Info file for Ediff, a part of the standard distribution
372*** of %sEmacs, does not seem to be properly installed.
373***
374*** Please contact your system administrator. "
375 (if ediff-xemacs-p "X" "")))
480 376
481;; Selective browsing 377;; Selective browsing
482 378
@@ -517,12 +413,6 @@ See the documentation string of `ediff-focus-on-regexp-matches' for details.")
517(ediff-defvar-local ediff-hide-regexp-connective 'and "") 413(ediff-defvar-local ediff-hide-regexp-connective 'and "")
518 414
519 415
520(defvar ediff-ange-ftp-ftp-name (if ediff-xemacs-p
521 'ange-ftp-ftp-path
522 'ange-ftp-ftp-name)
523 "Function ange-ftp uses to find out if file is remote.")
524
525
526;; Copying difference regions between buffers. 416;; Copying difference regions between buffers.
527(ediff-defvar-local ediff-killed-diffs-alist nil 417(ediff-defvar-local ediff-killed-diffs-alist nil
528 "A list of killed diffs. 418 "A list of killed diffs.
@@ -617,8 +507,8 @@ ediff-toggle-hilit. Use `setq-default' to set it.")
617(ediff-defvar-local ediff-buffer-values-orig-Ancestor nil "") 507(ediff-defvar-local ediff-buffer-values-orig-Ancestor nil "")
618;; Buffer-local variables to be saved then restored during Ediff sessions 508;; Buffer-local variables to be saved then restored during Ediff sessions
619;; Buffer-local variables to be saved then restored during Ediff sessions 509;; Buffer-local variables to be saved then restored during Ediff sessions
620(defconst ediff-protected-variables '(buffer-read-only 510(defconst ediff-protected-variables '(
621;;; synchronize-minibuffers 511 ;;buffer-read-only
622 mode-line-format)) 512 mode-line-format))
623 513
624;; Vector of differences between the variants. Each difference is 514;; Vector of differences between the variants. Each difference is
@@ -863,6 +753,15 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
863 (copy-face 'secondary-selection face)))) 753 (copy-face 'secondary-selection face))))
864 )) 754 ))
865 755
756(defun ediff-set-face-pixmap (face pixmap)
757 "Set face pixmap on a monochrome display."
758 (if (and (ediff-window-display-p) (not (ediff-color-display-p)))
759 (condition-case nil
760 (set-face-background-pixmap face pixmap)
761 (error
762 (message "Pixmap not found for %S: %s" (face-name face) pixmap)
763 (sit-for 1)))))
764
866(defun ediff-hide-face (face) 765(defun ediff-hide-face (face)
867 (if (and (ediff-has-face-support-p) ediff-emacs-p) 766 (if (and (ediff-has-face-support-p) ediff-emacs-p)
868 (add-to-list 'facemenu-unlisted-faces face))) 767 (add-to-list 'facemenu-unlisted-faces face)))
@@ -935,6 +834,13 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
935 'ediff-current-diff-face-C 'ediff-current-diff-face-Ancestor)))) 834 'ediff-current-diff-face-C 'ediff-current-diff-face-Ancestor))))
936 "Face for highlighting the selected difference in the ancestor buffer.") 835 "Face for highlighting the selected difference in the ancestor buffer.")
937 836
837(defvar ediff-fine-diff-pixmap "gray3"
838 "Pixmap to use for highlighting fine differences.")
839(defvar ediff-odd-diff-pixmap "gray1"
840 "Pixmap to use for highlighting odd differences.")
841(defvar ediff-even-diff-pixmap "Stipple"
842 "Pixmap to use for highlighting even differences.")
843
938(defvar ediff-fine-diff-face-A 844(defvar ediff-fine-diff-face-A
939 (if (ediff-has-face-support-p) 845 (if (ediff-has-face-support-p)
940 (progn 846 (progn
@@ -946,7 +852,11 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
946 "Navy") 852 "Navy")
947 (ediff-set-face 'background 'ediff-fine-diff-face-A 853 (ediff-set-face 'background 'ediff-fine-diff-face-A
948 "sky blue")) 854 "sky blue"))
949 (t (set-face-underline-p 'ediff-fine-diff-face-A t)))) 855 (t
856 (set-face-underline-p 'ediff-fine-diff-face-A t)
857 (ediff-set-face-pixmap 'ediff-fine-diff-face-A
858 ediff-fine-diff-pixmap)
859 )))
950 'ediff-fine-diff-face-A)) 860 'ediff-fine-diff-face-A))
951 "Face for highlighting the refinement of the selected diff in buffer A.") 861 "Face for highlighting the refinement of the selected diff in buffer A.")
952 862
@@ -959,7 +869,11 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
959 (cond ((ediff-color-display-p) 869 (cond ((ediff-color-display-p)
960 (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black") 870 (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
961 (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan")) 871 (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
962 (t (set-face-underline-p 'ediff-fine-diff-face-B t)))) 872 (t
873 (set-face-underline-p 'ediff-fine-diff-face-B t)
874 (ediff-set-face-pixmap 'ediff-fine-diff-face-B
875 ediff-fine-diff-pixmap)
876 )))
963 'ediff-fine-diff-face-B)) 877 'ediff-fine-diff-face-B))
964 "Face for highlighting the refinement of the selected diff in buffer B.") 878 "Face for highlighting the refinement of the selected diff in buffer B.")
965 879
@@ -973,7 +887,11 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
973 (ediff-set-face 'foreground 'ediff-fine-diff-face-C "black") 887 (ediff-set-face 'foreground 'ediff-fine-diff-face-C "black")
974 (ediff-set-face 888 (ediff-set-face
975 'background 'ediff-fine-diff-face-C "Turquoise")) 889 'background 'ediff-fine-diff-face-C "Turquoise"))
976 (t (set-face-underline-p 'ediff-fine-diff-face-C t)))) 890 (t
891 (set-face-underline-p 'ediff-fine-diff-face-C t)
892 (ediff-set-face-pixmap 'ediff-fine-diff-face-C
893 ediff-fine-diff-pixmap)
894 )))
977 'ediff-fine-diff-face-C)) 895 'ediff-fine-diff-face-C))
978 "Face for highlighting the refinement of the selected diff in buffer C.") 896 "Face for highlighting the refinement of the selected diff in buffer C.")
979 897
@@ -983,8 +901,12 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
983 (make-face 'ediff-fine-diff-face-Ancestor) 901 (make-face 'ediff-fine-diff-face-Ancestor)
984 (ediff-hide-face 'ediff-fine-diff-face-Ancestor) 902 (ediff-hide-face 'ediff-fine-diff-face-Ancestor)
985 (or (face-differs-from-default-p 'ediff-fine-diff-face-Ancestor) 903 (or (face-differs-from-default-p 'ediff-fine-diff-face-Ancestor)
986 (copy-face 904 (progn
987 'ediff-fine-diff-face-C 'ediff-fine-diff-face-Ancestor)))) 905 (copy-face
906 'ediff-fine-diff-face-C 'ediff-fine-diff-face-Ancestor)
907 (ediff-set-face-pixmap 'ediff-fine-diff-face-Ancestor
908 ediff-fine-diff-pixmap))
909 )))
988 "Face highlighting refinements of the selected diff in ancestor buffer. 910 "Face highlighting refinements of the selected diff in ancestor buffer.
989Presently, this is not used, as difference regions are not refined in the 911Presently, this is not used, as difference regions are not refined in the
990ancestor buffer.") 912ancestor buffer.")
@@ -1001,7 +923,10 @@ ancestor buffer.")
1001 (ediff-set-face 923 (ediff-set-face
1002 'background 'ediff-even-diff-face-A "light grey")) 924 'background 'ediff-even-diff-face-A "light grey"))
1003 (t 925 (t
1004 (copy-face 'italic 'ediff-even-diff-face-A)))) 926 (copy-face 'italic 'ediff-even-diff-face-A)
927 (ediff-set-face-pixmap 'ediff-even-diff-face-A
928 ediff-even-diff-pixmap)
929 )))
1005 'ediff-even-diff-face-A)) 930 'ediff-even-diff-face-A))
1006 "Face used to highlight even-numbered differences in buffer A.") 931 "Face used to highlight even-numbered differences in buffer A.")
1007 932
@@ -1017,7 +942,10 @@ ancestor buffer.")
1017 (ediff-set-face 942 (ediff-set-face
1018 'background 'ediff-even-diff-face-B "Gray")) 943 'background 'ediff-even-diff-face-B "Gray"))
1019 (t 944 (t
1020 (copy-face 'italic 'ediff-even-diff-face-B)))) 945 (copy-face 'italic 'ediff-even-diff-face-B)
946 (ediff-set-face-pixmap 'ediff-even-diff-face-B
947 ediff-even-diff-pixmap)
948 )))
1021 'ediff-even-diff-face-B)) 949 'ediff-even-diff-face-B))
1022 "Face used to highlight even-numbered differences in buffer B.") 950 "Face used to highlight even-numbered differences in buffer B.")
1023 951
@@ -1027,7 +955,10 @@ ancestor buffer.")
1027 (make-face 'ediff-even-diff-face-C) 955 (make-face 'ediff-even-diff-face-C)
1028 (ediff-hide-face 'ediff-even-diff-face-C) 956 (ediff-hide-face 'ediff-even-diff-face-C)
1029 (or (face-differs-from-default-p 'ediff-even-diff-face-C) 957 (or (face-differs-from-default-p 'ediff-even-diff-face-C)
1030 (copy-face 'ediff-even-diff-face-A 'ediff-even-diff-face-C)) 958 (progn
959 (copy-face 'ediff-even-diff-face-A 'ediff-even-diff-face-C)
960 (ediff-set-face-pixmap 'ediff-even-diff-face-C
961 ediff-even-diff-pixmap)))
1031 'ediff-even-diff-face-C)) 962 'ediff-even-diff-face-C))
1032 "Face used to highlight even-numbered differences in buffer C.") 963 "Face used to highlight even-numbered differences in buffer C.")
1033 964
@@ -1037,7 +968,11 @@ ancestor buffer.")
1037 (make-face 'ediff-even-diff-face-Ancestor) 968 (make-face 'ediff-even-diff-face-Ancestor)
1038 (ediff-hide-face 'ediff-even-diff-face-Ancestor) 969 (ediff-hide-face 'ediff-even-diff-face-Ancestor)
1039 (or (face-differs-from-default-p 'ediff-even-diff-face-Ancestor) 970 (or (face-differs-from-default-p 'ediff-even-diff-face-Ancestor)
1040 (copy-face 'ediff-even-diff-face-C 'ediff-even-diff-face-Ancestor)) 971 (progn
972 (copy-face
973 'ediff-even-diff-face-C 'ediff-even-diff-face-Ancestor)
974 (ediff-set-face-pixmap 'ediff-even-diff-face-Ancestor
975 ediff-even-diff-pixmap)))
1041 'ediff-even-diff-face-Ancestor)) 976 'ediff-even-diff-face-Ancestor))
1042 "Face highlighting even-numbered differences in the ancestor buffer.") 977 "Face highlighting even-numbered differences in the ancestor buffer.")
1043 978
@@ -1053,7 +988,10 @@ ancestor buffer.")
1053 (ediff-set-face 988 (ediff-set-face
1054 'background 'ediff-odd-diff-face-A "Gray")) 989 'background 'ediff-odd-diff-face-A "Gray"))
1055 (t 990 (t
1056 (copy-face 'italic 'ediff-odd-diff-face-A)))) 991 (copy-face 'italic 'ediff-odd-diff-face-A)
992 (ediff-set-face-pixmap 'ediff-odd-diff-face-A
993 ediff-odd-diff-pixmap)
994 )))
1057 'ediff-odd-diff-face-A)) 995 'ediff-odd-diff-face-A))
1058 "Face used to highlight odd-numbered differences in buffer A.") 996 "Face used to highlight odd-numbered differences in buffer A.")
1059 997
@@ -1069,7 +1007,10 @@ ancestor buffer.")
1069 (ediff-set-face 1007 (ediff-set-face
1070 'background 'ediff-odd-diff-face-B "light grey")) 1008 'background 'ediff-odd-diff-face-B "light grey"))
1071 (t 1009 (t
1072 (copy-face 'italic 'ediff-odd-diff-face-B)))) 1010 (copy-face 'italic 'ediff-odd-diff-face-B)
1011 (ediff-set-face-pixmap 'ediff-odd-diff-face-B
1012 ediff-odd-diff-pixmap)
1013 )))
1073 'ediff-odd-diff-face-B)) 1014 'ediff-odd-diff-face-B))
1074 "Face used to highlight odd-numbered differences in buffer B.") 1015 "Face used to highlight odd-numbered differences in buffer B.")
1075 1016
@@ -1079,7 +1020,10 @@ ancestor buffer.")
1079 (make-face 'ediff-odd-diff-face-C) 1020 (make-face 'ediff-odd-diff-face-C)
1080 (ediff-hide-face 'ediff-odd-diff-face-C) 1021 (ediff-hide-face 'ediff-odd-diff-face-C)
1081 (or (face-differs-from-default-p 'ediff-odd-diff-face-C) 1022 (or (face-differs-from-default-p 'ediff-odd-diff-face-C)
1082 (copy-face 'ediff-odd-diff-face-A 'ediff-odd-diff-face-C)) 1023 (progn
1024 (copy-face 'ediff-odd-diff-face-A 'ediff-odd-diff-face-C)
1025 (ediff-set-face-pixmap 'ediff-odd-diff-face-C
1026 ediff-odd-diff-pixmap)))
1083 'ediff-odd-diff-face-C)) 1027 'ediff-odd-diff-face-C))
1084 "Face used to highlight odd-numbered differences in buffer C.") 1028 "Face used to highlight odd-numbered differences in buffer C.")
1085 1029
@@ -1089,7 +1033,10 @@ ancestor buffer.")
1089 (make-face 'ediff-odd-diff-face-Ancestor) 1033 (make-face 'ediff-odd-diff-face-Ancestor)
1090 (ediff-hide-face 'ediff-odd-diff-face-Ancestor) 1034 (ediff-hide-face 'ediff-odd-diff-face-Ancestor)
1091 (or (face-differs-from-default-p 'ediff-odd-diff-face-Ancestor) 1035 (or (face-differs-from-default-p 'ediff-odd-diff-face-Ancestor)
1092 (copy-face 'ediff-odd-diff-face-C 'ediff-odd-diff-face-Ancestor)) 1036 (progn
1037 (copy-face 'ediff-odd-diff-face-C 'ediff-odd-diff-face-Ancestor)
1038 (ediff-set-face-pixmap 'ediff-odd-diff-face-Ancestor
1039 ediff-odd-diff-pixmap)))
1093 'ediff-odd-diff-face-Ancestor)) 1040 'ediff-odd-diff-face-Ancestor))
1094 "Face used to highlight even-numbered differences in the ancestor buffer.") 1041 "Face used to highlight even-numbered differences in the ancestor buffer.")
1095 1042
@@ -1147,6 +1094,15 @@ control is used, it could be `vc-toggle-read-only' or `rcs-toggle-read-only'.")
1147 1094
1148;; if nil, this silences some messages 1095;; if nil, this silences some messages
1149(defconst ediff-verbose-p t) 1096(defconst ediff-verbose-p t)
1097
1098(ediff-defvar-local ediff-autostore-merges 'group-jobs-only
1099 "*Save the results of merge jobs automatically.
1100Nil means don't save automatically. t means always save. Anything but nil or t
1101means save automatically only if the merge job is part of a group of jobs, such
1102as `ediff-merge-directory' or `ediff-merge-directory-revisions'.")
1103
1104;; file where the result of the merge is to be saved. used internally
1105(ediff-defvar-local ediff-merge-store-file nil "")
1150 1106
1151(defvar ediff-no-emacs-help-in-control-buffer nil 1107(defvar ediff-no-emacs-help-in-control-buffer nil
1152 "*Non-nil means C-h should not invoke Emacs help in control buffer. 1108 "*Non-nil means C-h should not invoke Emacs help in control buffer.
@@ -1192,8 +1148,10 @@ More precisely, a regexp to match any one such character.")
1192;;; In-line functions 1148;;; In-line functions
1193 1149
1194(defsubst ediff-file-remote-p (file-name) 1150(defsubst ediff-file-remote-p (file-name)
1195 (if (fboundp ediff-ange-ftp-ftp-name) 1151 (require 'ange-ftp)
1196 (funcall ediff-ange-ftp-ftp-name file-name))) 1152 (car (if ediff-xemacs-p
1153 (ange-ftp-ftp-path file-name)
1154 (ange-ftp-ftp-name file-name))))
1197 1155
1198 1156
1199(defsubst ediff-frame-unsplittable-p (frame) 1157(defsubst ediff-frame-unsplittable-p (frame)
@@ -1210,6 +1168,93 @@ More precisely, a regexp to match any one such character.")
1210 "Kill buffer BUF if it exists." 1168 "Kill buffer BUF if it exists."
1211 (if (ediff-buffer-live-p buf) 1169 (if (ediff-buffer-live-p buf)
1212 (kill-buffer (get-buffer buf)))) 1170 (kill-buffer (get-buffer buf))))
1171
1172
1173;; activate faces on diff regions in buffer
1174(defun ediff-paint-background-regions-in-one-buffer (buf-type unhighlight)
1175 (let ((diff-vector
1176 (eval (intern (format "ediff-difference-vector-%S" buf-type))))
1177 overl diff-num)
1178 (mapcar (function
1179 (lambda (rec)
1180 (setq overl (ediff-get-diff-overlay-from-diff-record rec)
1181 diff-num (ediff-overlay-get overl 'ediff-diff-num))
1182 (ediff-set-overlay-face
1183 overl
1184 (if (not unhighlight)
1185 (ediff-background-face buf-type diff-num))
1186 )))
1187 diff-vector)))
1188
1189
1190;; activate faces on diff regions in all buffers
1191(defun ediff-paint-background-regions (&optional unhighlight)
1192 (ediff-paint-background-regions-in-one-buffer
1193 'A unhighlight)
1194 (ediff-paint-background-regions-in-one-buffer
1195 'B unhighlight)
1196 (ediff-paint-background-regions-in-one-buffer
1197 'C unhighlight)
1198 (ediff-paint-background-regions-in-one-buffer
1199 'Ancestor unhighlight))
1200
1201(defun ediff-highlight-diff-in-one-buffer (n buf-type)
1202 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
1203 (let* ((buff (ediff-get-buffer buf-type))
1204 (last (ediff-eval-in-buffer buff (point-max)))
1205 (begin (ediff-get-diff-posn buf-type 'beg n))
1206 (end (ediff-get-diff-posn buf-type 'end n))
1207 (xtra (if (equal begin end) 1 0))
1208 (end-hilit (min last (+ end xtra)))
1209 (current-diff-overlay
1210 (symbol-value
1211 (intern (format "ediff-current-diff-overlay-%S" buf-type)))))
1212
1213 (if ediff-xemacs-p
1214 (ediff-move-overlay current-diff-overlay begin end-hilit)
1215 (ediff-move-overlay current-diff-overlay begin end-hilit buff))
1216 (ediff-overlay-put current-diff-overlay 'priority
1217 (ediff-highest-priority begin end-hilit buff))
1218 (ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
1219
1220 ;; unhighlight the background overlay for diff n so it won't
1221 ;; interfere with the current diff overlay
1222 (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
1223 )))
1224
1225
1226(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
1227 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
1228 (let ((current-diff-overlay
1229 (symbol-value
1230 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
1231 (overlay
1232 (ediff-get-diff-overlay ediff-current-difference buf-type))
1233 )
1234
1235 (ediff-move-overlay current-diff-overlay 1 1)
1236
1237 ;; rehighlight the overlay in the background of the
1238 ;; current difference region
1239 (ediff-set-overlay-face
1240 overlay
1241 (if (and (ediff-has-face-support-p)
1242 ediff-use-faces ediff-highlight-all-diffs)
1243 (ediff-background-face buf-type ediff-current-difference)))
1244 )))
1245
1246(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
1247 (ediff-unselect-and-select-difference -1)
1248 (if (and (ediff-has-face-support-p) ediff-use-faces)
1249 (let* ((inhibit-quit t)
1250 (current-diff-overlay-var
1251 (intern (format "ediff-current-diff-overlay-%S" buf-type)))
1252 (current-diff-overlay (symbol-value current-diff-overlay-var)))
1253 (ediff-paint-background-regions 'unhighlight)
1254 (if (ediff-overlayp current-diff-overlay)
1255 (ediff-delete-overlay current-diff-overlay))
1256 (set current-diff-overlay-var nil)
1257 )))
1213 1258
1214 1259
1215(defsubst ediff-highlight-diff (n) 1260(defsubst ediff-highlight-diff (n)
@@ -1367,6 +1412,7 @@ More precisely, a regexp to match any one such character.")
1367 (glyph-height ediff-H-glyph (selected-window frame)) 1412 (glyph-height ediff-H-glyph (selected-window frame))
1368 (frame-char-height frame))) 1413 (frame-char-height frame)))
1369 1414
1415;; Some overlay functions
1370 1416
1371(defsubst ediff-empty-overlay-p (overl) 1417(defsubst ediff-empty-overlay-p (overl)
1372 (= (ediff-overlay-start overl) (ediff-overlay-end overl))) 1418 (= (ediff-overlay-start overl) (ediff-overlay-end overl)))
@@ -1384,6 +1430,32 @@ More precisely, a regexp to match any one such character.")
1384 (if ediff-emacs-p 1430 (if ediff-emacs-p
1385 (overlay-get overl property) 1431 (overlay-get overl property)
1386 (and (extent-live-p overl) (extent-property overl property)))) 1432 (and (extent-live-p overl) (extent-property overl property))))
1433
1434
1435;; These two functions are here because XEmacs refuses to
1436;; handle overlays whose buffers were deleted.
1437(defun ediff-move-overlay (overlay beg end &optional buffer)
1438 "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
1439Checks if overlay's buffer exists before actually doing the move."
1440 (let ((buf (and overlay (ediff-overlay-buffer overlay))))
1441 (if (ediff-buffer-live-p buf)
1442 (if ediff-xemacs-p
1443 (set-extent-endpoints overlay beg end)
1444 (move-overlay overlay beg end buffer))
1445 ;; buffer's dead
1446 (if overlay
1447 (ediff-delete-overlay overlay)))))
1448
1449(defun ediff-overlay-put (overlay prop value)
1450 "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
1451Checks if overlay's buffer exists."
1452 (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
1453 (if ediff-xemacs-p
1454 (set-extent-property overlay prop value)
1455 (overlay-put overlay prop value))
1456 (ediff-delete-overlay overlay)))
1457
1458;; Some diff region tests
1387 1459
1388;; t if diff region is empty. 1460;; t if diff region is empty.
1389;; In case of buffer C, t also if it is not a 3way 1461;; In case of buffer C, t also if it is not a 3way
@@ -1516,8 +1588,18 @@ More precisely, a regexp to match any one such character.")
1516 (ediff-file-attributes filename 5)) 1588 (ediff-file-attributes filename 5))
1517 1589
1518 1590
1591(defun ediff-convert-standard-filename (fname)
1592 (if ediff-emacs-p
1593 (convert-standard-filename fname)
1594 ;; hopefully, XEmacs adds this functionality
1595 fname))
1519 1596
1520 1597
1598;;; Local Variables:
1599;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1600;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1601;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1602;;; End:
1521 1603
1522(provide 'ediff-init) 1604(provide 'ediff-init)
1523 1605
diff --git a/lisp/ediff-merg.el b/lisp/ediff-merg.el
index 80275c46f30..a07dc8d8c16 100644
--- a/lisp/ediff-merg.el
+++ b/lisp/ediff-merg.el
@@ -264,6 +264,12 @@ Combining is done according to the specifications in variable
264 ))) 264 )))
265 265
266 266
267;;; Local Variables:
268;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
269;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
270;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
271;;; End:
272
267(provide 'ediff-merg) 273(provide 'ediff-merg)
268 274
269;; ediff-merg.el ends here 275;; ediff-merg.el ends here
diff --git a/lisp/ediff-mult.el b/lisp/ediff-mult.el
index 7bfdd81e477..2a88f9dc036 100644
--- a/lisp/ediff-mult.el
+++ b/lisp/ediff-mult.el
@@ -155,6 +155,8 @@ directories.")
155(defvar ediff-session-group-setup-hook nil 155(defvar ediff-session-group-setup-hook nil
156 "*Hooks run just after a meta-buffer controlling a session group, such as 156 "*Hooks run just after a meta-buffer controlling a session group, such as
157ediff-directories, is run.") 157ediff-directories, is run.")
158(defvar ediff-quit-session-group-hook nil
159 "*Hooks run just before exiting a session group.")
158(defvar ediff-show-registry-hook nil 160(defvar ediff-show-registry-hook nil
159 "*Hooks run just after the registry buffer is shown.") 161 "*Hooks run just after the registry buffer is shown.")
160(defvar ediff-show-session-group-hook nil 162(defvar ediff-show-session-group-hook nil
@@ -168,6 +170,7 @@ ediff-directories, is run.")
168;; group buffer/regexp 170;; group buffer/regexp
169(defun ediff-get-group-buffer (meta-list) 171(defun ediff-get-group-buffer (meta-list)
170 (nth 0 (car meta-list))) 172 (nth 0 (car meta-list)))
173
171(defun ediff-get-group-regexp (meta-list) 174(defun ediff-get-group-regexp (meta-list)
172 (nth 1 (car meta-list))) 175 (nth 1 (car meta-list)))
173;; group objects 176;; group objects
@@ -177,6 +180,9 @@ ediff-directories, is run.")
177 (nth 3 (car meta-list))) 180 (nth 3 (car meta-list)))
178(defun ediff-get-group-objC (meta-list) 181(defun ediff-get-group-objC (meta-list)
179 (nth 4 (car meta-list))) 182 (nth 4 (car meta-list)))
183(defun ediff-get-group-merge-autostore-dir (meta-list)
184 (nth 5 (car meta-list)))
185
180;; session buffer 186;; session buffer
181(defun ediff-get-session-buffer (elt) 187(defun ediff-get-session-buffer (elt)
182 (nth 0 elt)) 188 (nth 0 elt))
@@ -313,11 +319,16 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
313 (backward-char 1))) 319 (backward-char 1)))
314 )) 320 ))
315 321
322(defsubst ediff-add-slash-if-directory (dir file)
323 (if (file-directory-p (concat dir file))
324 (file-name-as-directory file)
325 file))
316 326
317 327
318;; DIR1, DIR2, DIR3 are directories. 328;; DIR1, DIR2, DIR3 are directories. DIR3 can be nil.
319;; REGEXP is a regexp used to filter 329;; OUTPUT-DIR is a directory for auto-storing the results of merge jobs.
320;; files in the directories. 330;; Can be nil.
331;; REGEXP is a regexp used to filter out files in the directories.
321;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not 332;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not
322;; included in the intersection. However, a regular file that is a dir in dir3 333;; included in the intersection. However, a regular file that is a dir in dir3
323;; is included, since dir3 files are supposed to be ancestors for merging. 334;; is included, since dir3 files are supposed to be ancestors for merging.
@@ -325,44 +336,53 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
325;; ((dir1 dir2 dir3) (f1 f2 f3) (f1 f2 f3) ...) 336;; ((dir1 dir2 dir3) (f1 f2 f3) (f1 f2 f3) ...)
326;; dir3, f3 can be nil if intersecting only 2 directories. 337;; dir3, f3 can be nil if intersecting only 2 directories.
327;; If COMPARISON-FUNC is given, use it. Otherwise, use string= 338;; If COMPARISON-FUNC is given, use it. Otherwise, use string=
328;; DIFF-VAR is contains the name of the variable in which to return the 339;; DIFF-VAR contains the name of the variable in which to return the
329;; difference list. The diff list is of the form: 340;; difference list (which represents the differences among the contents of
341;; directories). The diff list is of the form:
330;; ((dir1 dir2 dir3) (file . num) (file . num)...) 342;; ((dir1 dir2 dir3) (file . num) (file . num)...)
331;; where num encodes the set of dirs where the file is found: 343;; where num encodes the set of dirs where the file is found:
332;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc. 344;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc.
333(defun ediff-intersect-directories (jobname 345(defun ediff-intersect-directories (jobname
334 diff-var regexp dir1 dir2 346 diff-var regexp dir1 dir2
335 &optional dir3 comparison-func) 347 &optional
348 dir3 merge-autostore-dir comparison-func)
336 (setq comparison-func (or comparison-func 'string=)) 349 (setq comparison-func (or comparison-func 'string=))
337 (let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 difflist) 350 (let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 difflist)
338 351
339 (setq auxdir1 (file-name-as-directory dir1) 352 (setq auxdir1 (file-name-as-directory dir1)
340 lis1 (directory-files auxdir1 nil regexp) 353 lis1 (directory-files auxdir1 nil regexp)
354 lis1 (delete "." lis1)
355 lis1 (delete ".." lis1)
356 lis1 (mapcar
357 (function
358 (lambda (elt)
359 (ediff-add-slash-if-directory auxdir1 elt)))
360 lis1)
341 auxdir2 (file-name-as-directory dir2) 361 auxdir2 (file-name-as-directory dir2)
342 lis2 (directory-files auxdir2 nil regexp)) 362 lis2 (mapcar
363 (function
364 (lambda (elt)
365 (ediff-add-slash-if-directory auxdir2 elt)))
366 (directory-files auxdir2 nil regexp)))
343 367
344 (if (stringp dir3) 368 (if (stringp dir3)
345 (setq auxdir3 (file-name-as-directory dir3) 369 (setq auxdir3 (file-name-as-directory dir3)
346 lis3 (directory-files auxdir3 nil regexp))) 370 lis3 (mapcar
347 371 (function
348 (setq lis1 (delete "." lis1) 372 (lambda (elt)
349 lis1 (delete ".." lis1)) 373 (ediff-add-slash-if-directory auxdir3 elt)))
350 374 (directory-files auxdir3 nil regexp))))
375
376 (if (stringp merge-autostore-dir)
377 (setq merge-autostore-dir
378 (file-name-as-directory merge-autostore-dir)))
351 (setq common (ediff-intersection lis1 lis2 comparison-func)) 379 (setq common (ediff-intersection lis1 lis2 comparison-func))
352 ;; get rid of files that are directories in dir1 but not dir2 380
353 (mapcar (function (lambda (elt) 381 ;; In merge with ancestor jobs, we don't intersect with lis3.
354 (if (Xor (file-directory-p (concat auxdir1 elt)) 382 ;; If there is no ancestor, we'll offer to merge without the ancestor.
355 (file-directory-p (concat auxdir2 elt))) 383 ;; So, we intersect with lis3 only when we are doing 3-way file comparison
356 (setq common (delq elt common))))) 384 (if (and lis3 (ediff-comparison-metajob3 jobname))
357 common) 385 (setq common (ediff-intersection common lis3 comparison-func)))
358 ;; intersect with the third dir
359 (if lis3 (setq common (ediff-intersection common lis3 comparison-func)))
360 (if (ediff-comparison-metajob3 jobname)
361 (mapcar (function (lambda (elt)
362 (if (Xor (file-directory-p (concat auxdir1 elt))
363 (file-directory-p (concat auxdir3 elt)))
364 (setq common (delq elt common)))))
365 common))
366 386
367 ;; copying is needed because sort sorts via side effects 387 ;; copying is needed because sort sorts via side effects
368 (setq common (sort (ediff-copy-list common) 'string-lessp)) 388 (setq common (sort (ediff-copy-list common) 'string-lessp))
@@ -393,25 +413,47 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
393 difflist) 413 difflist)
394 (setq difflist (cons (list regexp auxdir1 auxdir2 auxdir3) difflist)) 414 (setq difflist (cons (list regexp auxdir1 auxdir2 auxdir3) difflist))
395 415
416 ;; return the difference list back to the calling function
396 (set diff-var difflist) 417 (set diff-var difflist)
397 418
398 ;; return result 419 ;; return result
399 (cons (list regexp auxdir1 auxdir2 auxdir3) 420 (cons (list regexp auxdir1 auxdir2 auxdir3 merge-autostore-dir)
400 (mapcar (function (lambda (elt) 421 (mapcar
401 (list (concat auxdir1 elt) 422 (function
402 (concat auxdir2 elt) 423 (lambda (elt)
403 (if lis3 424 (list (concat auxdir1 elt)
404 (concat auxdir3 elt))))) 425 (concat auxdir2 elt)
405 common)) 426 (if lis3
427 (progn
428 ;; The following is done because:
429 ;; In merging with ancestor, we don't intersect
430 ;; with lis3. So, it is possible that elt is a
431 ;; file in auxdir1/2 but a directory in auxdir3
432 ;; Or elt may not exist in auxdir3 at all.
433 ;; In the first case, we add a slash at the end.
434 ;; In the second case, we insert nil.
435 (setq elt (ediff-add-slash-if-directory auxdir3 elt))
436 (if (file-exists-p (concat auxdir3 elt))
437 (concat auxdir3 elt)))))))
438 common))
406 )) 439 ))
407 440
408;; find directory files that are under revision. 441;; find directory files that are under revision.
409;; display subdirectories, too, since we may visit them recursively. 442;; Include subdirectories, since we may visit them recursively.
410(defun ediff-get-directory-files-under-revision (jobname regexp dir1) 443;; DIR1 is the directory to inspect.
444;; OUTPUT-DIR is the directory where to auto-store the results of merges. Can
445;; be nil.
446(defun ediff-get-directory-files-under-revision (jobname
447 regexp dir1
448 &optional merge-autostore-dir)
411 (let (lis1 elt common auxdir1) 449 (let (lis1 elt common auxdir1)
412 (setq auxdir1 (file-name-as-directory dir1) 450 (setq auxdir1 (file-name-as-directory dir1)
413 lis1 (directory-files auxdir1 nil regexp)) 451 lis1 (directory-files auxdir1 nil regexp))
414 452
453 (if (stringp merge-autostore-dir)
454 (setq merge-autostore-dir
455 (file-name-as-directory merge-autostore-dir)))
456
415 (while lis1 457 (while lis1
416 (setq elt (car lis1) 458 (setq elt (car lis1)
417 lis1 (cdr lis1)) 459 lis1 (cdr lis1))
@@ -426,13 +468,14 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
426 ) ; while 468 ) ; while
427 469
428 (setq common (delete "." common) 470 (setq common (delete "." common)
429 common (delete ".." common)) 471 common (delete ".." common)
472 common (delete "RCS" common))
430 473
431 ;; copying is needed because sort sorts via side effects 474 ;; copying is needed because sort sorts via side effects
432 (setq common (sort (ediff-copy-list common) 'string-lessp)) 475 (setq common (sort (ediff-copy-list common) 'string-lessp))
433 476
434 ;; return result 477 ;; return result
435 (cons (list regexp auxdir1 nil nil) 478 (cons (list regexp auxdir1 nil nil merge-autostore-dir)
436 (mapcar (function (lambda (elt) 479 (mapcar (function (lambda (elt)
437 (list (concat auxdir1 elt) 480 (list (concat auxdir1 elt)
438 nil nil))) 481 nil nil)))
@@ -499,28 +542,32 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
499 ;; meta-buffs. 542 ;; meta-buffs.
500 (define-key 543 (define-key
501 ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry)) 544 ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry))
502 ;; initialize the meta list -- don't do this for registry we prepend 545 ;; Initialize the meta list -- don't do this for registry.
503 ;; '(nil nil) to all elts of meta-list, except the first. The 546 ;;
504 ;; first nil will later be replaced by the session buffer. The second 547 ;; We prepend '(nil nil) to all elts of meta-list, except the first.
505 ;; is reserved for session status. 548 ;; The first nil will later be replaced by the session buffer. The
549 ;; second is reserved for session status.
550 ;;
506 ;; (car ediff-meta-list) gets cons'ed with the session group buffer. 551 ;; (car ediff-meta-list) gets cons'ed with the session group buffer.
507 ;; Also, session objA/B/C are turned into lists (obj eq-indicator) 552 ;; Also, session objects A/B/C are turned into lists of the form
553 ;; (obj eq-indicator). Eq-indicator is either nil or =. Initialized to
554 ;; nil. If later it is discovered that this file is = to some other
555 ;; file in the same session, eq-indicator is changed to `='.
508 ;; For now, the eq-indicator is used only for 2 and 3-file jobs. 556 ;; For now, the eq-indicator is used only for 2 and 3-file jobs.
509 (setq ediff-meta-list 557 (setq ediff-meta-list
510 (cons (cons meta-buffer (car meta-list)) 558 (cons (cons meta-buffer (car meta-list))
511 (mapcar (function 559 (mapcar
512 (lambda (elt) 560 (function
513 (cons nil 561 (lambda (elt)
514 (cons nil 562 (cons nil
515 ;; convert each obj to (obj nil), 563 (cons nil
516 ;; where nil may later be replaced 564 ;; convert each obj to (obj nil),
517 ;; by =, if this file equals some 565 ;; where nil is the initial value
518 ;; other file in the same session 566 ;; for eq-indicator -- see above
519 (mapcar (function 567 (mapcar
520 (lambda (obj) 568 (function (lambda (obj) (list obj nil)))
521 (list obj nil))) 569 elt)))))
522 elt))))) 570 (cdr meta-list)))))
523 (cdr meta-list)))))
524 571
525 (or (eq meta-buffer ediff-registry-buffer) 572 (or (eq meta-buffer ediff-registry-buffer)
526 (setq ediff-session-registry 573 (setq ediff-session-registry
@@ -534,8 +581,9 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
534 (set-buffer-modified-p nil) 581 (set-buffer-modified-p nil)
535 582
536 (run-hooks 'startup-hooks) 583 (run-hooks 'startup-hooks)
537 ;; arrange for showing directory contents differences 584
538 ;; must be after run startup-hooks, since ediff-dir-difference-list is 585 ;; Arrange to show directory contents differences
586 ;; Must be after run startup-hooks, since ediff-dir-difference-list is
539 ;; set inside these hooks 587 ;; set inside these hooks
540 (if (eq action-func 'ediff-filegroup-action) 588 (if (eq action-func 'ediff-filegroup-action)
541 (progn 589 (progn
@@ -574,6 +622,7 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
574 (empty t) 622 (empty t)
575 (sessionNum 0) 623 (sessionNum 0)
576 regexp elt session-buf f1 f2 f3 pt 624 regexp elt session-buf f1 f2 f3 pt
625 merge-autostore-dir
577 point tmp-list buffer-read-only) 626 point tmp-list buffer-read-only)
578 (ediff-eval-in-buffer meta-buf 627 (ediff-eval-in-buffer meta-buf
579 (setq point (point)) 628 (setq point (point))
@@ -581,7 +630,8 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
581 (insert (format ediff-meta-buffer-message 630 (insert (format ediff-meta-buffer-message
582 (ediff-abbrev-jobname ediff-metajob-name))) 631 (ediff-abbrev-jobname ediff-metajob-name)))
583 632
584 (setq regexp (ediff-get-group-regexp meta-list)) 633 (setq regexp (ediff-get-group-regexp meta-list)
634 merge-autostore-dir (ediff-get-group-merge-autostore-dir meta-list))
585 635
586 (cond ((ediff-collect-diffs-metajob) 636 (cond ((ediff-collect-diffs-metajob)
587 (insert 637 (insert
@@ -598,7 +648,11 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
598 648
599 (if (and (stringp regexp) (> (length regexp) 0)) 649 (if (and (stringp regexp) (> (length regexp) 0))
600 (insert (format "Filter-through regular expression: %s\n" regexp))) 650 (insert (format "Filter-through regular expression: %s\n" regexp)))
601 651 (if (and ediff-autostore-merges (ediff-merge-metajob)
652 (stringp merge-autostore-dir))
653 (insert (format
654 "\nMerges are automatically stored in directory: %s\n"
655 merge-autostore-dir)))
602 (insert "\n 656 (insert "\n
603 Size Last modified Name 657 Size Last modified Name
604 ----------------------------------------------------------------------- 658 -----------------------------------------------------------------------
@@ -621,7 +675,6 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
621 ;; now organize file names like this: 675 ;; now organize file names like this:
622 ;; use-mark sizeA dateA sizeB dateB filename 676 ;; use-mark sizeA dateA sizeB dateB filename
623 ;; make sure directories are displayed with a trailing slash. 677 ;; make sure directories are displayed with a trailing slash.
624 ;; If one is a directory and another isn't, indicate this with a `?'
625 (while meta-list 678 (while meta-list
626 (setq elt (car meta-list) 679 (setq elt (car meta-list)
627 meta-list (cdr meta-list) 680 meta-list (cdr meta-list)
@@ -652,50 +705,63 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
652;; Check if this is a problematic session. 705;; Check if this is a problematic session.
653;; Return nil if not. Otherwise, return symbol representing the problem 706;; Return nil if not. Otherwise, return symbol representing the problem
654;; At present, problematic sessions occur only in -with-ancestor comparisons 707;; At present, problematic sessions occur only in -with-ancestor comparisons
655;; when the ancestor is a directory rather than a file. 708;; when the ancestor is a directory rather than a file, or when there is no
709;; suitable ancestor file in the ancestor directory
656(defun ediff-problematic-session-p (session) 710(defun ediff-problematic-session-p (session)
657 (let ((f1 (ediff-get-session-objA-name session)) 711 (let ((f1 (ediff-get-session-objA-name session))
658 (f2 (ediff-get-session-objB-name session)) 712 (f2 (ediff-get-session-objB-name session))
659 (f3 (ediff-get-session-objC-name session))) 713 (f3 (ediff-get-session-objC-name session)))
660 (cond ((and (stringp f1) (not (file-directory-p f1)) 714 (cond ((and (stringp f1) (not (file-directory-p f1))
661 (stringp f2) (not (file-directory-p f2)) 715 (stringp f2) (not (file-directory-p f2))
662 (stringp f3) (file-directory-p f3) 716 ;; either invalid file name or a directory
717 (or (not (stringp f3)) (file-directory-p f3))
663 (ediff-ancestor-metajob)) 718 (ediff-ancestor-metajob))
664 ;; more may be added later 719 ;; more may be added later
665 'ancestor-is-dir) 720 'ancestor-is-dir)
666 (t nil)))) 721 (t nil))))
667 722
668(defun ediff-meta-insert-file-info (fileinfo) 723(defun ediff-meta-insert-file-info (fileinfo)
669 (let ((file-size -1) 724 (let ((fname (car fileinfo))
670 (fname (car fileinfo))
671 (feq (ediff-get-file-eqstatus fileinfo)) 725 (feq (ediff-get-file-eqstatus fileinfo))
672 (file-modtime "*file doesn't exist*")) 726 file-modtime file-size)
673 727
674 (if (and (stringp fname) (file-exists-p fname)) 728 (cond ((not (stringp fname)) (setq file-size -2)) ; file doesn't exits
675 (setq file-size (ediff-file-size fname) 729 ((not (ediff-file-remote-p fname))
676 file-modtime (ediff-file-modtime fname))) 730 (if (file-exists-p fname)
731 ;; set real size and modtime
732 (setq file-size (ediff-file-size fname)
733 file-modtime (ediff-file-modtime fname))
734 (setq file-size -2))) ; file doesn't exist
735 ( t (setq file-size -1))) ; remote file
677 (if (stringp fname) 736 (if (stringp fname)
678 (insert 737 (insert
679 (format 738 (format
680 "%s %s %-20s %s\n" 739 "%s %s %-20s %s\n"
681 (if feq "=" " ") ; equality indicator 740 (if feq "=" " ") ; equality indicator
682 (format "%10s" (if (< file-size 0) 741 (format "%10s" (cond ((= file-size -1) "--")
683 "remote" 742 ((< file-size -1) "--")
684 file-size)) 743 (t file-size)))
685 (if (< file-size 0) 744 (cond ((= file-size -1) "*remote file*")
686 "file" 745 ((< file-size -1) "*file doesn't exist*")
687 (ediff-format-date (decode-time file-modtime))) 746 (t (ediff-format-date (decode-time file-modtime))))
688 ;; dir names in meta lists have no trailing `/' so insert it 747
689 (cond ((file-directory-p fname) 748 ;; dir names in meta lists have training slashes, so we just
690 (file-name-as-directory (ediff-abbreviate-file-name fname))) 749 ;; abbreviate the file name, if file exists
691 (t (ediff-abbreviate-file-name fname))))) 750 (if (and (not (stringp fname)) (< file-size -1))
692 ))) 751 "-------" ; file doesn't exist
752 (ediff-abbreviate-file-name fname)))))))
693 753
694(defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr") 754(defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr")
695 (5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug") 755 (5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug")
696 (9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec")) 756 (9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec"))
697 "Months' associative array.") 757 "Months' associative array.")
698 758
759;; returns 2char string
760(defsubst ediff-fill-leading-zero (num)
761 (if (< num 10)
762 (format "0%d" num)
763 (number-to-string num)))
764
699;; TIME is like the output of decode-time 765;; TIME is like the output of decode-time
700(defun ediff-format-date (time) 766(defun ediff-format-date (time)
701 (format "%s %2d %4d %s:%s:%s" 767 (format "%s %2d %4d %s:%s:%s"
@@ -707,12 +773,6 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
707 (ediff-fill-leading-zero (nth 0 time)) ; sec 773 (ediff-fill-leading-zero (nth 0 time)) ; sec
708 )) 774 ))
709 775
710;; returns 2char string
711(defsubst ediff-fill-leading-zero (num)
712 (if (< num 10)
713 (format "0%d" num)
714 (number-to-string num)))
715
716(defun ediff-draw-dir-diffs (diff-list) 776(defun ediff-draw-dir-diffs (diff-list)
717 (if (null diff-list) (error "Lost difference info on these directories")) 777 (if (null diff-list) (error "Lost difference info on these directories"))
718 (let* ((buf-name (ediff-unique-buffer-name 778 (let* ((buf-name (ediff-unique-buffer-name
@@ -1130,6 +1190,7 @@ all marked sessions must be active."
1130 (meta-buf (ediff-event-buffer last-command-event)) 1190 (meta-buf (ediff-event-buffer last-command-event))
1131 ;; ediff-get-meta-info gives error if meta-buf or pos are invalid 1191 ;; ediff-get-meta-info gives error if meta-buf or pos are invalid
1132 (info (ediff-get-meta-info meta-buf pos)) 1192 (info (ediff-get-meta-info meta-buf pos))
1193 merge-autostore-dir
1133 session-buf file1 file2 file3 regexp) 1194 session-buf file1 file2 file3 regexp)
1134 1195
1135 (setq session-buf (ediff-get-session-buffer info) 1196 (setq session-buf (ediff-get-session-buffer info)
@@ -1149,6 +1210,8 @@ all marked sessions must be active."
1149 (error "Aborted")))) 1210 (error "Aborted"))))
1150 1211
1151 (ediff-eval-in-buffer meta-buf 1212 (ediff-eval-in-buffer meta-buf
1213 (setq merge-autostore-dir
1214 (ediff-get-group-merge-autostore-dir ediff-meta-list))
1152 (goto-char pos) ; if the user clicked on session--move point there 1215 (goto-char pos) ; if the user clicked on session--move point there
1153 ;; First handle sessions involving directories (which are themselves 1216 ;; First handle sessions involving directories (which are themselves
1154 ;; session groups) 1217 ;; session groups)
@@ -1203,13 +1266,19 @@ all marked sessions must be active."
1203 ((ediff-problematic-session-p info) 1266 ((ediff-problematic-session-p info)
1204 (beep) 1267 (beep)
1205 (if (y-or-n-p 1268 (if (y-or-n-p
1206 "This session's ancestor is a directory, merge without the ancestor? ") 1269 "This session has no ancestor. Merge without the ancestor? ")
1207 (ediff-merge-files 1270 (ediff-merge-files
1208 file1 file2 1271 file1 file2
1209 ;; provide startup hooks 1272 ;; provide startup hooks
1210 (` (list (lambda () 1273 (` (list (lambda ()
1211 (setq ediff-meta-buffer (, (current-buffer))) 1274 (setq ediff-meta-buffer (, (current-buffer)))
1212 ;; see below for the explanation of what this does 1275 (setq ediff-merge-store-file
1276 (, (concat
1277 merge-autostore-dir
1278 (file-name-nondirectory file1))))
1279 ;; make ediff-startup pass
1280 ;; ediff-control-buffer back to the meta
1281 ;; level; see below
1213 (setcar 1282 (setcar
1214 (quote (, info)) ediff-control-buffer))))) 1283 (quote (, info)) ediff-control-buffer)))))
1215 (error "Aborted"))) 1284 (error "Aborted")))
@@ -1219,7 +1288,13 @@ all marked sessions must be active."
1219 ;; provide startup hooks 1288 ;; provide startup hooks
1220 (` (list (lambda () 1289 (` (list (lambda ()
1221 (setq ediff-meta-buffer (, (current-buffer))) 1290 (setq ediff-meta-buffer (, (current-buffer)))
1222 ;; see below for explanation of what this does 1291 (setq ediff-merge-store-file
1292 (, (concat
1293 merge-autostore-dir
1294 (file-name-nondirectory file1))))
1295 ;; make ediff-startup pass
1296 ;; ediff-control-buffer back to the meta
1297 ;; level; see below
1223 (setcar 1298 (setcar
1224 (quote (, info)) ediff-control-buffer)))))) 1299 (quote (, info)) ediff-control-buffer))))))
1225 ((not (ediff-metajob3)) ; need 2 file args 1300 ((not (ediff-metajob3)) ; need 2 file args
@@ -1228,12 +1303,13 @@ all marked sessions must be active."
1228 ;; provide startup hooks 1303 ;; provide startup hooks
1229 (` (list (lambda () 1304 (` (list (lambda ()
1230 (setq ediff-meta-buffer (, (current-buffer))) 1305 (setq ediff-meta-buffer (, (current-buffer)))
1231 ;; this makes ediff-startup pass the value of 1306 (setq ediff-merge-store-file
1307 (, (concat
1308 merge-autostore-dir
1309 (file-name-nondirectory file1))))
1310 ;; make ediff-startup pass
1232 ;; ediff-control-buffer back to the meta 1311 ;; ediff-control-buffer back to the meta
1233 ;; level, to the record in the meta list 1312 ;; level; see below
1234 ;; containing the information about the
1235 ;; session associated with that
1236 ;; ediff-control-buffer
1237 (setcar 1313 (setcar
1238 (quote (, info)) ediff-control-buffer)))))) 1314 (quote (, info)) ediff-control-buffer))))))
1239 ((ediff-metajob3) ; need 3 file args 1315 ((ediff-metajob3) ; need 3 file args
@@ -1241,7 +1317,17 @@ all marked sessions must be active."
1241 file1 file2 file3 1317 file1 file2 file3
1242 ;; arrange startup hooks 1318 ;; arrange startup hooks
1243 (` (list (lambda () 1319 (` (list (lambda ()
1320 (setq ediff-merge-store-file
1321 (, (concat
1322 merge-autostore-dir
1323 (file-name-nondirectory file1))))
1244 (setq ediff-meta-buffer (, (current-buffer))) 1324 (setq ediff-meta-buffer (, (current-buffer)))
1325 ;; this arranges that ediff-startup will pass
1326 ;; the value of ediff-control-buffer back to
1327 ;; the meta level, to the record in the meta
1328 ;; list containing the information about the
1329 ;; session associated with that
1330 ;; ediff-control-buffer
1245 (setcar 1331 (setcar
1246 (quote (, info)) ediff-control-buffer)))))) 1332 (quote (, info)) ediff-control-buffer))))))
1247 ) ; cond 1333 ) ; cond
@@ -1404,8 +1490,8 @@ all marked sessions must be active."
1404 'ediff-registry)) 1490 'ediff-registry))
1405 )) 1491 ))
1406 1492
1407;; if meta-buf exists, it is redrawn along with parent. Otherwise, nothing 1493;; If meta-buf exists, it is redrawn along with parent.
1408;; happens 1494;; Otherwise, nothing happens.
1409(defun ediff-cleanup-meta-buffer (meta-buffer) 1495(defun ediff-cleanup-meta-buffer (meta-buffer)
1410 (if (ediff-buffer-live-p meta-buffer) 1496 (if (ediff-buffer-live-p meta-buffer)
1411 (ediff-eval-in-buffer meta-buffer 1497 (ediff-eval-in-buffer meta-buffer
@@ -1430,7 +1516,7 @@ all marked sessions must be active."
1430 cont)))) 1516 cont))))
1431 1517
1432(defun ediff-quit-meta-buffer () 1518(defun ediff-quit-meta-buffer ()
1433 "If no unprocessed sessions in the group, delete the meta buffer. 1519 "If the group has no active session, delete the meta buffer.
1434If no session is in progress, ask to confirm before deleting meta buffer. 1520If no session is in progress, ask to confirm before deleting meta buffer.
1435Otherwise, bury the meta buffer. 1521Otherwise, bury the meta buffer.
1436If this is a session registry buffer then just bury it." 1522If this is a session registry buffer then just bury it."
@@ -1445,6 +1531,7 @@ If this is a session registry buffer then just bury it."
1445 (ediff-cleanup-meta-buffer buf) 1531 (ediff-cleanup-meta-buffer buf)
1446 (cond ((and (ediff-safe-to-quit buf) 1532 (cond ((and (ediff-safe-to-quit buf)
1447 (y-or-n-p "Quit this session group? ")) 1533 (y-or-n-p "Quit this session group? "))
1534 (run-hooks 'ediff-quit-session-group-hook)
1448 (message "") 1535 (message "")
1449 (ediff-dispose-of-meta-buffer buf)) 1536 (ediff-dispose-of-meta-buffer buf))
1450 ((ediff-safe-to-quit buf) 1537 ((ediff-safe-to-quit buf)
@@ -1617,6 +1704,7 @@ This is used only for sessions that involve 2 or 3 files at the same time."
1617;;; Local Variables: 1704;;; Local Variables:
1618;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 1705;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1619;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 1706;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1707;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1620;;; End: 1708;;; End:
1621 1709
1622(provide 'ediff-mult) 1710(provide 'ediff-mult)
diff --git a/lisp/ediff-ptch.el b/lisp/ediff-ptch.el
index bd74071388c..960eb6fda93 100644
--- a/lisp/ediff-ptch.el
+++ b/lisp/ediff-ptch.el
@@ -32,7 +32,25 @@
32(defvar ediff-backup-extension 32(defvar ediff-backup-extension
33 (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95)) 33 (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95))
34 "_orig" ".orig") 34 "_orig" ".orig")
35 "Default backup extension for the patch program.") 35 "Backup extension used by the patch program.
36See also `ediff-backup-specs'.")
37
38(defvar ediff-backup-specs (format "-b %s" ediff-backup-extension)
39 "*Backup directives to pass to the patch program.
40Ediff requires that the old version of the file \(before applying the patch\)
41is saved in a file named `the-patch-file.extension'. Usually `extension' is
42`.orig', but this can be changed by the user and may depend on the system.
43Therefore, Ediff needs to know the backup extension used by the patch program.
44
45Some versions of the patch program let you specify `-b backup-extension'.
46Other versions only permit `-b', which assumes some canned extension
47 \(usually `.orig'\).
48
49Note that both `ediff-backup-extension' and `ediff-backup-specs'
50must be properly set. If your patch program takes the option `-b',
51but not `-b extension', the variable `ediff-backup-extension' must
52still be set so Ediff will know which extension to use.")
53
36 54
37(defvar ediff-patch-default-directory nil 55(defvar ediff-patch-default-directory nil
38 "*Default directory to look for patches.") 56 "*Default directory to look for patches.")
@@ -46,9 +64,16 @@
46 "*Regexp matching filename 2-liners at the start of each context diff.") 64 "*Regexp matching filename 2-liners at the start of each context diff.")
47 65
48(defvar ediff-patch-program "patch" 66(defvar ediff-patch-program "patch"
49 "*Name of the program that applies patches.") 67 "*Name of the program that applies patches.
50(defvar ediff-patch-options "" 68It is recommended to use GNU-compatible versions.")
51 "*Options to pass to ediff-patch-program.") 69(defvar ediff-patch-options "-f"
70 "*Options to pass to ediff-patch-program.
71
72Note: the `-b' option should be specified in `ediff-backup-specs'.
73
74It is recommended to pass the `-f' option to the patch program, so it won't ask
75questions. However, some implementations don't accept this option, in which
76case the default value for this variable should be changed.")
52 77
53;; The buffer of the patch file. Local to control buffer. 78;; The buffer of the patch file. Local to control buffer.
54(ediff-defvar-local ediff-patchbufer nil "") 79(ediff-defvar-local ediff-patchbufer nil "")
@@ -113,9 +138,9 @@
113 (setq mark2 (move-marker (make-marker) (match-beginning 0)) 138 (setq mark2 (move-marker (make-marker) (match-beginning 0))
114 mark2-end (match-end 0) 139 mark2-end (match-end 0)
115 beg1 (or (match-beginning 2) (match-beginning 4)) 140 beg1 (or (match-beginning 2) (match-beginning 4))
116 end1 (or (match-end 2) (match-end 4)) 141 end1 (or (match-end 2) (match-end 4))
117 beg2 (or (match-beginning 3) (match-beginning 5)) 142 beg2 (or (match-beginning 3) (match-beginning 5))
118 end2 (or (match-end 3) (match-end 5))) 143 end2 (or (match-end 3) (match-end 5)))
119 ;; possible-file-names is holding the new file names until we 144 ;; possible-file-names is holding the new file names until we
120 ;; insert the old file name in the patch map 145 ;; insert the old file name in the patch map
121 ;; It is a pair (filename from 1st header line . fn from 2nd line) 146 ;; It is a pair (filename from 1st header line . fn from 2nd line)
@@ -199,6 +224,7 @@
199 (princ 224 (princ
200 (format " 225 (format "
201The patch file contains a context diff for 226The patch file contains a context diff for
227
202 %s 228 %s
203 %s 229 %s
204 230
@@ -320,7 +346,8 @@ Else, read patch file into a new buffer."
320 (current-buffer) 'must-match))) 346 (current-buffer) 'must-match)))
321 (setq patch-buf 347 (setq patch-buf
322 (find-file-noselect 348 (find-file-noselect
323 (read-file-name "Which file contains the patch? " dir)))) 349 (read-file-name "Which file contains the patch? "
350 dir nil 'must-match))))
324 351
325 (ediff-eval-in-buffer patch-buf 352 (ediff-eval-in-buffer patch-buf
326 (goto-char (point-min)) 353 (goto-char (point-min))
@@ -406,15 +433,7 @@ Else, read patch file into a new buffer."
406 &optional startup-hooks) 433 &optional startup-hooks)
407 (setq source-filename (expand-file-name source-filename)) 434 (setq source-filename (expand-file-name source-filename))
408 435
409 (let* ((backup-extension 436 (let* ((shell-file-name ediff-shell)
410 ;; if the user specified a -b option, extract the backup
411 ;; extension from there; else use ediff-backup-extension
412 (substring ediff-patch-options
413 (if (string-match "-b[ \t]+" ediff-patch-options)
414 (match-end 0) 0)
415 (if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options)
416 (match-end 0) 0)))
417 (shell-file-name ediff-shell)
418 (patch-diagnostics (get-buffer-create "*ediff patch diagnostics*")) 437 (patch-diagnostics (get-buffer-create "*ediff patch diagnostics*"))
419 ;; ediff-find-file may use a temp file to do the patch 438 ;; ediff-find-file may use a temp file to do the patch
420 ;; so, we save source-filename and true-source-filename as a var 439 ;; so, we save source-filename and true-source-filename as a var
@@ -422,12 +441,9 @@ Else, read patch file into a new buffer."
422 ;; file for the purpose of patching. 441 ;; file for the purpose of patching.
423 (true-source-filename source-filename) 442 (true-source-filename source-filename)
424 (target-filename source-filename) 443 (target-filename source-filename)
425 target-buf buf-to-patch file-name-magic-p ctl-buf backup-style) 444 target-buf buf-to-patch file-name-magic-p
445 patch-return-code ctl-buf backup-style aux-wind)
426 446
427 ;; if the user didn't specify a backup extension, use
428 ;; ediff-backup-extension
429 (if (string= backup-extension "")
430 (setq backup-extension ediff-backup-extension))
431 (if (string-match "-V" ediff-patch-options) 447 (if (string-match "-V" ediff-patch-options)
432 (error 448 (error
433 "Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) 449 "Ediff doesn't take the -V option in `ediff-patch-options'--sorry"))
@@ -457,14 +473,21 @@ Else, read patch file into a new buffer."
457 ;; fix environment for gnu patch, so it won't make numbered extensions 473 ;; fix environment for gnu patch, so it won't make numbered extensions
458 (setq backup-style (getenv "VERSION_CONTROL")) 474 (setq backup-style (getenv "VERSION_CONTROL"))
459 (setenv "VERSION_CONTROL" nil) 475 (setenv "VERSION_CONTROL" nil)
460 ;; always pass patch the -f option, so it won't ask any questions 476 (setq patch-return-code
461 (shell-command-on-region 477 (call-process-region
462 (point-min) (point-max) 478 (point-min) (point-max)
463 (format "%s -f %s -b %s %s" 479 shell-file-name
464 ediff-patch-program ediff-patch-options 480 t ; delete region (which contains the patch
465 backup-extension 481 t ; insert output (patch diagnostics) in current buffer
466 (expand-file-name true-source-filename)) 482 nil ; don't redisplay
467 t) 483 shell-command-switch ; usually -c
484 (format "%s %s %s %s"
485 ediff-patch-program
486 ediff-patch-options
487 ediff-backup-specs
488 (expand-file-name true-source-filename))
489 ))
490
468 ;; restore environment for gnu patch 491 ;; restore environment for gnu patch
469 (setenv "VERSION_CONTROL" backup-style)) 492 (setenv "VERSION_CONTROL" backup-style))
470 493
@@ -474,9 +497,46 @@ Else, read patch file into a new buffer."
474 (switch-to-buffer patch-diagnostics) 497 (switch-to-buffer patch-diagnostics)
475 (sit-for 0) ; synchronize - let the user see diagnostics 498 (sit-for 0) ; synchronize - let the user see diagnostics
476 499
477 (or (file-exists-p (concat true-source-filename backup-extension)) 500 (or (and (eq patch-return-code 0) ; patch reported success
478 (error "Patch appears to have failed")) 501 (file-exists-p
479 502 (concat true-source-filename ediff-backup-extension)))
503 (progn
504 (with-output-to-temp-buffer ediff-msg-buffer
505 (princ (format "
506Patch has failed OR the backup version of the patched file was not created by
507the patch program.
508
509A possible reason is that the values of the variables
510
511ediff-patch-options = %S
512ediff-backup-extension = %S
513ediff-backup-specs = %S
514
515are not appropriate for the program specified in the variable
516
517ediff-patch-program = %S
518
519See Ediff on-line manual for more details on these variables.
520\(Or use a GNU-compatible patch program and stay out of trouble.\)
521
522Type any key to continue... "
523 ediff-patch-options
524 ediff-backup-extension
525 ediff-backup-specs
526 ediff-patch-program)))
527 (beep 1)
528 (if (setq aux-wind (get-buffer-window ediff-msg-buffer))
529 (progn
530 (select-window aux-wind)
531 (goto-char (point-max))))
532 (read-char-exclusive)
533 (if aux-wind (bury-buffer)) ; ediff-msg-buffer
534 (if (setq aux-wind (get-buffer-window patch-diagnostics))
535 (progn
536 (select-window aux-wind)
537 (bury-buffer)))
538 (error "Patch appears to have failed")))
539
480 ;; If black magic is involved, apply patch to a temp copy of the 540 ;; If black magic is involved, apply patch to a temp copy of the
481 ;; file. Otherwise, apply patch to the orig copy. If patch is applied 541 ;; file. Otherwise, apply patch to the orig copy. If patch is applied
482 ;; to temp copy, we name the result old-name_patched for local files 542 ;; to temp copy, we name the result old-name_patched for local files
@@ -487,7 +547,8 @@ Else, read patch file into a new buffer."
487 ;; the original. 547 ;; the original.
488 (if (not file-name-magic-p) 548 (if (not file-name-magic-p)
489 (ediff-eval-in-buffer buf-to-patch 549 (ediff-eval-in-buffer buf-to-patch
490 (set-visited-file-name (concat source-filename backup-extension)) 550 (set-visited-file-name
551 (concat source-filename ediff-backup-extension))
491 (set-buffer-modified-p nil)) 552 (set-buffer-modified-p nil))
492 553
493 ;; Black magic in effect. 554 ;; Black magic in effect.
@@ -504,7 +565,7 @@ Else, read patch file into a new buffer."
504 (rename-file true-source-filename target-filename t) 565 (rename-file true-source-filename target-filename t)
505 566
506 ;; arrange that the temp copy of orig will be deleted 567 ;; arrange that the temp copy of orig will be deleted
507 (rename-file (concat true-source-filename backup-extension) 568 (rename-file (concat true-source-filename ediff-backup-extension)
508 true-source-filename t)) 569 true-source-filename t))
509 570
510 ;; make orig buffer read-only 571 ;; make orig buffer read-only
@@ -557,6 +618,7 @@ Else, read patch file into a new buffer."
557;;; Local Variables: 618;;; Local Variables:
558;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 619;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
559;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 620;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
621;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
560;;; End: 622;;; End:
561 623
562(provide 'ediff-ptch) 624(provide 'ediff-ptch)
diff --git a/lisp/ediff-util.el b/lisp/ediff-util.el
index 76eaaddae1f..f248135b5bf 100644
--- a/lisp/ediff-util.el
+++ b/lisp/ediff-util.el
@@ -24,11 +24,17 @@
24;;; Code: 24;;; Code:
25 25
26(require 'ediff-init) 26(require 'ediff-init)
27(require 'ediff-help)
27(require 'ediff-mult) 28(require 'ediff-mult)
28 29
29;; Pacify compiler and avoid the need in checking for boundp 30;; Pacify compiler and avoid the need in checking for boundp
30(defvar ediff-patch-diagnostics nil) 31(defvar ediff-patch-diagnostics nil)
31(defvar ediff-patchbufer nil) 32(defvar ediff-patchbufer nil)
33(and noninteractive
34 (eval-when-compile
35 (let ((load-path (cons (expand-file-name ".") load-path)))
36 (load-file "ediff-init.el")
37 (load-file "ediff-help.el"))))
32;; end pacifier 38;; end pacifier
33 39
34 40
@@ -100,6 +106,10 @@ to invocation.")
100 (setq ediff-mode-map (make-sparse-keymap)) 106 (setq ediff-mode-map (make-sparse-keymap))
101 (suppress-keymap ediff-mode-map) 107 (suppress-keymap ediff-mode-map)
102 108
109 (define-key ediff-mode-map
110 (if ediff-emacs-p [mouse-2] [button2]) 'ediff-help-for-quick-help)
111 (define-key ediff-mode-map "\C-m" 'ediff-help-for-quick-help)
112
103 (define-key ediff-mode-map "p" 'ediff-previous-difference) 113 (define-key ediff-mode-map "p" 'ediff-previous-difference)
104 (define-key ediff-mode-map "\C-?" 'ediff-previous-difference) 114 (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
105 (define-key ediff-mode-map [backspace] 'ediff-previous-difference) 115 (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
@@ -183,6 +193,7 @@ to invocation.")
183 (define-key ediff-mode-map "wa" 'ediff-save-buffer) 193 (define-key ediff-mode-map "wa" 'ediff-save-buffer)
184 (define-key ediff-mode-map "wb" 'ediff-save-buffer) 194 (define-key ediff-mode-map "wb" 'ediff-save-buffer)
185 (define-key ediff-mode-map "wd" 'ediff-save-buffer) 195 (define-key ediff-mode-map "wd" 'ediff-save-buffer)
196 (define-key ediff-mode-map "=" 'ediff-inferior-compare-regions)
186 (if (fboundp 'ediff-show-patch-diagnostics) 197 (if (fboundp 'ediff-show-patch-diagnostics)
187 (define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics)) 198 (define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics))
188 (if ediff-3way-job 199 (if ediff-3way-job
@@ -210,10 +221,13 @@ to invocation.")
210;; It now returns control buffer so other functions can do post-processing 221;; It now returns control buffer so other functions can do post-processing
211(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C 222(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
212 startup-hooks setup-parameters) 223 startup-hooks setup-parameters)
213 (setq file-A (expand-file-name file-A)) 224 ;; ediff-convert-standard-filename puts file names in the form appropriate
214 (setq file-B (expand-file-name file-B)) 225 ;; for the OS at hand.
226 (setq file-A (ediff-convert-standard-filename (expand-file-name file-A)))
227 (setq file-B (ediff-convert-standard-filename (expand-file-name file-B)))
215 (if (stringp file-C) 228 (if (stringp file-C)
216 (setq file-C (expand-file-name file-C))) 229 (setq file-C
230 (ediff-convert-standard-filename (expand-file-name file-C))))
217 (let* ((control-buffer-name 231 (let* ((control-buffer-name
218 (ediff-unique-buffer-name "*Ediff Control Panel" "*")) 232 (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
219 (control-buffer (ediff-eval-in-buffer buffer-A 233 (control-buffer (ediff-eval-in-buffer buffer-A
@@ -461,6 +475,8 @@ to invocation.")
461 (shrink-window-if-larger-than-buffer) 475 (shrink-window-if-larger-than-buffer)
462 (or (ediff-multiframe-setup-p) 476 (or (ediff-multiframe-setup-p)
463 (ediff-indent-help-message)) 477 (ediff-indent-help-message))
478 (ediff-set-help-overlays)
479
464 (set-buffer-modified-p nil) 480 (set-buffer-modified-p nil)
465 (ediff-refresh-mode-lines) 481 (ediff-refresh-mode-lines)
466 (setq ediff-control-window (selected-window)) 482 (setq ediff-control-window (selected-window))
@@ -476,72 +492,7 @@ to invocation.")
476 (goto-char (point-min)) 492 (goto-char (point-min))
477 (skip-chars-forward ediff-whitespace))) 493 (skip-chars-forward ediff-whitespace)))
478 494
479;; assuming we are in control window, calculate length of the first line in
480;; help message
481(defun ediff-help-message-line-length ()
482 (save-excursion
483 (goto-char (point-min))
484 (if ediff-use-long-help-message
485 (next-line 1))
486 (end-of-line)
487 (current-column)))
488
489 495
490(defun ediff-indent-help-message ()
491 (let* ((shift (/ (max 0 (- (window-width (selected-window))
492 (ediff-help-message-line-length)))
493 2))
494 (str (make-string shift ?\ )))
495 (save-excursion
496 (goto-char (point-min))
497 (while (< (point) (point-max))
498 (insert str)
499 (beginning-of-line)
500 (forward-line 1)))))
501
502
503(defun ediff-set-help-message ()
504 (setq ediff-long-help-message
505 (cond ((and ediff-long-help-message-function
506 (or (symbolp ediff-long-help-message-function)
507 (consp ediff-long-help-message-function)))
508 (funcall ediff-long-help-message-function))
509 (ediff-word-mode
510 (concat ediff-long-help-message-head
511 ediff-long-help-message-word-mode
512 ediff-long-help-message-tail))
513 (ediff-narrow-job
514 (concat ediff-long-help-message-head
515 ediff-long-help-message-narrow2
516 ediff-long-help-message-tail))
517 (ediff-merge-job
518 (concat ediff-long-help-message-head
519 ediff-long-help-message-merge
520 ediff-long-help-message-tail))
521 (ediff-diff3-job
522 (concat ediff-long-help-message-head
523 ediff-long-help-message-compare3
524 ediff-long-help-message-tail))
525 (t
526 (concat ediff-long-help-message-head
527 ediff-long-help-message-compare2
528 ediff-long-help-message-tail))))
529 (setq ediff-brief-help-message
530 (cond ((and ediff-brief-help-message-function
531 (or (symbolp ediff-brief-help-message-function)
532 (consp ediff-brief-help-message-function)))
533 (funcall ediff-brief-help-message-function))
534 ((stringp ediff-brief-help-message-function)
535 ediff-brief-help-message-function)
536 ((ediff-multiframe-setup-p) ediff-brief-message-string)
537 (t ; long brief msg, not multiframe --- put in the middle
538 ediff-brief-message-string)
539 ))
540 (setq ediff-help-message (if ediff-use-long-help-message
541 ediff-long-help-message
542 ediff-brief-help-message))
543 (run-hooks 'ediff-display-help-hook))
544
545 496
546 497
547;;; Commands for working with Ediff 498;;; Commands for working with Ediff
@@ -770,8 +721,9 @@ Reestablish the default three-window display."
770 control-frame 721 control-frame
771 (eq this-command 'ediff-quit)))) 722 (eq this-command 'ediff-quit))))
772 )) 723 ))
773 (ediff-eval-in-buffer control-buf 724
774 (ediff-refresh-mode-lines)) 725 (ediff-restore-highlighting)
726 (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines))
775 )) 727 ))
776 728
777;; this function returns to the window it was called from 729;; this function returns to the window it was called from
@@ -881,12 +833,13 @@ On a dumb terminal, switches between ASCII highlighting and no highlighting."
881 ediff-highlight-all-diffs t))) 833 ediff-highlight-all-diffs t)))
882 834
883 (if (and ediff-use-faces ediff-highlight-all-diffs) 835 (if (and ediff-use-faces ediff-highlight-all-diffs)
884 (ediff-color-background-regions) 836 (ediff-paint-background-regions)
885 (ediff-color-background-regions 'unhighlight)) 837 (ediff-paint-background-regions 'unhighlight))
886 838
887 (ediff-unselect-and-select-difference 839 (ediff-unselect-and-select-difference
888 ediff-current-difference 'select-only)) 840 ediff-current-difference 'select-only))
889 ) 841 )
842
890 843
891(defun ediff-toggle-autorefine () 844(defun ediff-toggle-autorefine ()
892 "Toggle auto-refine mode." 845 "Toggle auto-refine mode."
@@ -1033,7 +986,10 @@ of the current buffer."
1033 (file-writable-p file) 986 (file-writable-p file)
1034 (or 987 (or
1035 (file-exists-p (concat file ",v")) 988 (file-exists-p (concat file ",v"))
1036 (file-exists-p (concat "RCS/" file ",v"))) 989 (file-exists-p (concat (file-name-directory file)
990 "RCS/"
991 (file-name-nondirectory file)
992 ",v")))
1037 )) 993 ))
1038(defun ediff-file-checked-in-p (file) 994(defun ediff-file-checked-in-p (file)
1039 (and (stringp file) 995 (and (stringp file)
@@ -2188,10 +2144,17 @@ temporarily reverses the meaning of this variable."
2188 (if (ediff-overlayp overl) 2144 (if (ediff-overlayp overl)
2189 (ediff-delete-overlay overl)))) 2145 (ediff-delete-overlay overl))))
2190 ediff-narrow-bounds) 2146 ediff-narrow-bounds)
2191 2147
2192 ;; restore buffer mode line id's in buffer-A/B/C 2148 ;; restore buffer mode line id's in buffer-A/B/C
2193 (let ((control-buffer ediff-control-buffer) 2149 (let ((control-buffer ediff-control-buffer)
2194 (meta-buffer ediff-meta-buffer)) 2150 (meta-buffer ediff-meta-buffer)
2151 ;; suitable working frame
2152 (warp-frame (if (and (ediff-window-display-p) (eq ediff-grab-mouse t))
2153 (cond ((window-live-p ediff-window-A)
2154 (window-frame ediff-window-A))
2155 ((window-live-p ediff-window-B)
2156 (window-frame ediff-window-B))
2157 (t (next-frame))))))
2195 (condition-case nil 2158 (condition-case nil
2196 (ediff-eval-in-buffer ediff-buffer-A 2159 (ediff-eval-in-buffer ediff-buffer-A
2197 (setq ediff-this-buffer-ediff-sessions 2160 (setq ediff-this-buffer-ediff-sessions
@@ -2233,6 +2196,14 @@ temporarily reverses the meaning of this variable."
2233 (ediff-update-registry) 2196 (ediff-update-registry)
2234 ;; restore state of buffers to what it was before ediff 2197 ;; restore state of buffers to what it was before ediff
2235 (ediff-restore-protected-variables) 2198 (ediff-restore-protected-variables)
2199
2200 ;; If the user interrupts (canceling saving the merge buffer), continue
2201 ;; normally.
2202 (condition-case nil
2203 (if (ediff-merge-job)
2204 (run-hooks 'ediff-quit-merge-hook))
2205 (quit))
2206
2236 ;; good place to kill buffers A/B/C 2207 ;; good place to kill buffers A/B/C
2237 (run-hooks 'ediff-cleanup-hook) 2208 (run-hooks 'ediff-cleanup-hook)
2238 (let ((ediff-keep-variants ediff-keep-variants)) 2209 (let ((ediff-keep-variants ediff-keep-variants))
@@ -2242,6 +2213,20 @@ temporarily reverses the meaning of this variable."
2242 2213
2243 (run-hooks 'ediff-quit-hook) 2214 (run-hooks 'ediff-quit-hook)
2244 (ediff-cleanup-meta-buffer meta-buffer) 2215 (ediff-cleanup-meta-buffer meta-buffer)
2216
2217 ;; warp mouse into a working window
2218 (setq warp-frame ; if mouse is over a reasonable frame, use it
2219 (cond ((and ediff-xemacs-p (window-live-p (car (mouse-position))))
2220 (window-frame (car (mouse-position))))
2221 ((frame-live-p (car (mouse-position)))
2222 (car (mouse-position)))
2223 (t warp-frame)))
2224 (if (frame-live-p warp-frame)
2225 (set-mouse-position (if ediff-emacs-p
2226 warp-frame
2227 (frame-selected-window warp-frame))
2228 2 1))
2229
2245 (if (ediff-buffer-live-p meta-buffer) 2230 (if (ediff-buffer-live-p meta-buffer)
2246 (ediff-show-meta-buffer meta-buffer)) 2231 (ediff-show-meta-buffer meta-buffer))
2247 )) 2232 ))
@@ -2290,7 +2275,7 @@ temporarily reverses the meaning of this variable."
2290 (or (ediff-get-visible-buffer-window buff-A) 2275 (or (ediff-get-visible-buffer-window buff-A)
2291 (progn 2276 (progn
2292 (if (ediff-get-visible-buffer-window buff-B) 2277 (if (ediff-get-visible-buffer-window buff-B)
2293 (split-window-vertically)) 2278 (funcall ediff-split-window-function))
2294 (switch-to-buffer buff-A))) 2279 (switch-to-buffer buff-A)))
2295 (error)) 2280 (error))
2296 (if three-way-job 2281 (if three-way-job
@@ -2299,7 +2284,7 @@ temporarily reverses the meaning of this variable."
2299 (progn 2284 (progn
2300 (if (or (ediff-get-visible-buffer-window buff-A) 2285 (if (or (ediff-get-visible-buffer-window buff-A)
2301 (ediff-get-visible-buffer-window buff-B)) 2286 (ediff-get-visible-buffer-window buff-B))
2302 (split-window-vertically)) 2287 (funcall ediff-split-window-function))
2303 (switch-to-buffer buff-C) 2288 (switch-to-buffer buff-C)
2304 (balance-windows))) 2289 (balance-windows)))
2305 (error))) 2290 (error)))
@@ -2337,6 +2322,52 @@ buffer in another session as well."
2337 (buffer-name ediff-buffer-C))))) 2322 (buffer-name ediff-buffer-C)))))
2338 (ediff-kill-buffer-carefully ediff-buffer-C)))) 2323 (ediff-kill-buffer-carefully ediff-buffer-C))))
2339 2324
2325(defun ediff-maybe-save-and-delete-merge ()
2326 "Default hook to run on quitting a merge job.
2327If `ediff-autostore-merges' is nil, this does nothing.
2328If it is t, it saves the merge buffer in the file `ediff-merge-store-file'
2329or asks the user, if the latter is nil. It then then asks the user whether to
2330delete the merge buffer.
2331If `ediff-autostore-merges' is neither nil nor t, the merge buffer is saved
2332only if this merge job is part of a group, i.e., was invoked from within
2333`ediff-merge-directories', `ediff-merge-directory-revisions', and such."
2334 (let ((merge-store-file ediff-merge-store-file))
2335 (if ediff-autostore-merges
2336 (cond ((stringp ediff-merge-store-file)
2337 ;; store, ask to delete
2338 (ediff-write-merge-buffer-then-kill
2339 ediff-buffer-C merge-store-file 'show-file))
2340 ((eq ediff-autostore-merges t)
2341 ;; ask for file name
2342 (setq merge-store-file
2343 (read-file-name "Save the result of the merge in: "))
2344 (ediff-write-merge-buffer-then-kill
2345 ediff-buffer-C merge-store-file))
2346 ((ediff-eval-in-buffer ediff-meta-buffer
2347 (ediff-merge-metajob))
2348 ;; This case shouldn't occur, as the parent metajob must pass on
2349 ;; a file name, ediff-merge-store-file, where to save the result
2350 ;; of the merge.
2351 ;; Ask where to save anyway--will decide what to do here later.
2352 (setq merge-store-file
2353 (read-file-name "The result of the merge goes into: "))
2354 (ediff-write-merge-buffer-then-kill
2355 ediff-buffer-C merge-store-file))))
2356 ))
2357
2358(defun ediff-write-merge-buffer-then-kill (buf file &optional show-file)
2359 (ediff-eval-in-buffer buf
2360 (if (or (not (file-exists-p file))
2361 (y-or-n-p (format "File %s exists, overwrite? " file)))
2362 (progn
2363 (write-region (point-min) (point-max) file)
2364 (if show-file
2365 (progn
2366 (message "Merge buffer saved in: %s" file)
2367 (sit-for 2)))
2368 (if (y-or-n-p "Merge buffer saved in file. Now kill the buffer? ")
2369 (ediff-kill-buffer-carefully buf))))))
2370
2340;; The default way of suspending Ediff. 2371;; The default way of suspending Ediff.
2341;; Buries Ediff buffers, kills all windows. 2372;; Buries Ediff buffers, kills all windows.
2342(defun ediff-default-suspend-function () 2373(defun ediff-default-suspend-function ()
@@ -2583,8 +2614,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
2583 (setq ediff-current-difference n) 2614 (setq ediff-current-difference n)
2584 ) ; end protected section 2615 ) ; end protected section
2585 2616
2586 (ediff-eval-in-buffer control-buf 2617 (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines))
2587 (ediff-refresh-mode-lines))
2588 ))) 2618 )))
2589 2619
2590 2620
@@ -2618,7 +2648,6 @@ Hit \\[ediff-recenter] to reset the windows afterward."
2618 prompt 2648 prompt
2619 (cond (default-file 2649 (cond (default-file
2620 (concat " (default " default-file "):")) 2650 (concat " (default " default-file "):"))
2621 ;;((string-match "[?:!,;][ \t]*$" prompt) "")
2622 (t (concat " (default " default-dir "):")))) 2651 (t (concat " (default " default-dir "):"))))
2623 default-dir 2652 default-dir
2624 (or default-file default-dir) 2653 (or default-file default-dir)
@@ -2673,7 +2702,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
2673 nil ; don't append---erase 2702 nil ; don't append---erase
2674 'no-message) 2703 'no-message)
2675 (set-file-modes f ediff-temp-file-mode) 2704 (set-file-modes f ediff-temp-file-mode)
2676 f))) 2705 (ediff-convert-standard-filename (expand-file-name f)))))
2677 2706
2678;; Quote metacharacters (using \) when executing diff in Unix, but not in 2707;; Quote metacharacters (using \) when executing diff in Unix, but not in
2679;; EMX OS/2 2708;; EMX OS/2
@@ -2796,6 +2825,108 @@ Without an argument, it saves customized diff argument, if available
2796 (ediff-reset-mouse ediff-control-frame)) 2825 (ediff-reset-mouse ediff-control-frame))
2797 (if (window-live-p ediff-control-window) 2826 (if (window-live-p ediff-control-window)
2798 (select-window ediff-control-window))) 2827 (select-window ediff-control-window)))
2828
2829
2830(defun ediff-inferior-compare-regions ()
2831 "Compare regions in an active Ediff session.
2832Like ediff-regions-linewise but is called from under an active Ediff session on
2833the files that belong to that session.
2834
2835After quitting the session invoked via this function, type C-l to the parent
2836Ediff Control Panel to restore highlighting."
2837 (interactive)
2838 (let ((answer "")
2839 (possibilities (list ?A ?B ?C))
2840 begA begB endA endB bufA bufB)
2841
2842 (cond ((ediff-merge-job)
2843 (setq bufB ediff-buffer-C)
2844 (while (cond ((memq answer '(?A ?a))
2845 (setq bufA ediff-buffer-A)
2846 nil)
2847 ((memq answer '(?B ?b))
2848 (setq bufA ediff-buffer-B)
2849 nil)
2850 ((equal answer ""))
2851 (t (beep 1)
2852 (message "Valid answers are A or B")
2853 (sit-for 2)
2854 t))
2855 (let ((cursor-in-echo-area t))
2856 (message "Which buffer to compare to the merge buffer (A/B)? ")
2857 (setq answer (read-char-exclusive)))))
2858
2859 ((ediff-3way-comparison-job)
2860 (while (cond ((memq answer possibilities)
2861 (setq possibilities (delq answer possibilities))
2862 (setq bufA
2863 (eval
2864 (intern (format "ediff-buffer-%c" answer))))
2865 nil)
2866 ((equal answer ""))
2867 (t (beep 1)
2868 (message
2869 "Valid answers are %s"
2870 (mapconcat 'char-to-string possibilities " or "))
2871 (sit-for 2)
2872 t))
2873 (let ((cursor-in-echo-area t))
2874 (message "Enter the 1st buffer you want to compare (%s): "
2875 (mapconcat 'char-to-string possibilities "/"))
2876 (setq answer (capitalize (read-char-exclusive)))))
2877 (setq answer "") ; silence error msg
2878 (while (cond ((memq answer possibilities)
2879 (setq possibilities (delq answer possibilities))
2880 (setq bufB
2881 (eval
2882 (intern (format "ediff-buffer-%c" answer))))
2883 nil)
2884 ((equal answer ""))
2885 (t (beep 1)
2886 (message
2887 "Valid answers are %s"
2888 (mapconcat 'char-to-string possibilities " or "))
2889 (sit-for 2)
2890 t))
2891 (let ((cursor-in-echo-area t))
2892 (message "Enter the 2nd buffer you want to compare (%s): "
2893 (mapconcat 'char-to-string possibilities "/"))
2894 (setq answer (capitalize (read-char-exclusive))))))
2895 (t ; 2way comparison
2896 (setq bufA ediff-buffer-A
2897 bufB ediff-buffer-B)))
2898
2899 (ediff-eval-in-buffer bufA
2900 (setq begA (region-beginning)
2901 endA (region-end))
2902 (goto-char begA)
2903 (beginning-of-line)
2904 (setq begA (point))
2905 (goto-char endA)
2906 (end-of-line)
2907 (or (eobp) (forward-char)) ; include the newline char
2908 (setq endA (point)))
2909 (ediff-eval-in-buffer bufB
2910 (setq begB (region-beginning)
2911 endB (region-end))
2912 (goto-char begB)
2913 (beginning-of-line)
2914 (setq begB (point))
2915 (goto-char endB)
2916 (end-of-line)
2917 (or (eobp) (forward-char)) ; include the newline char
2918 (setq endB (point)))
2919
2920 (ediff-unselect-and-select-difference
2921 ediff-current-difference 'unselect-only)
2922 (ediff-paint-background-regions 'unhighlight)
2923
2924 (ediff-regions-internal
2925 bufA begA endA bufB begB endB
2926 nil ; startup hook
2927 'ediff-regions-linewise ; job name
2928 nil) ; no word mode
2929 ))
2799 2930
2800 2931
2801 2932
@@ -2893,68 +3024,16 @@ Without an argument, it saves customized diff argument, if available
2893 )) 3024 ))
2894 3025
2895 3026
3027;; Restore highlighting to what it should be according to ediff-use-faces,
3028;; ediff-highlighting-style, and ediff-highlight-all-diffs variables.
3029(defun ediff-restore-highlighting (&optional ctl-buf)
3030 (ediff-eval-in-buffer (or ctl-buf (current-buffer))
3031 (if (and (ediff-has-face-support-p)
3032 ediff-use-faces
3033 ediff-highlight-all-diffs)
3034 (ediff-paint-background-regions))
3035 (ediff-select-difference ediff-current-difference)))
2896 3036
2897(defun ediff-highlight-diff-in-one-buffer (n buf-type)
2898 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
2899 (let* ((buff (ediff-get-buffer buf-type))
2900 (last (ediff-eval-in-buffer buff (point-max)))
2901 (begin (ediff-get-diff-posn buf-type 'beg n))
2902 (end (ediff-get-diff-posn buf-type 'end n))
2903 (xtra (if (equal begin end) 1 0))
2904 (end-hilit (min last (+ end xtra)))
2905 (current-diff-overlay
2906 (symbol-value
2907 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2908 )
2909
2910 (if ediff-xemacs-p
2911 (ediff-move-overlay current-diff-overlay begin end-hilit)
2912 (ediff-move-overlay current-diff-overlay begin end-hilit buff))
2913 ;; giving priority of 0 and then changing it may look funny, but
2914 ;; this overcomes an obscure Emacs bug.
2915 (ediff-overlay-put current-diff-overlay 'priority 0)
2916 (ediff-overlay-put current-diff-overlay 'priority
2917 (ediff-highest-priority begin end-hilit buff))
2918 (ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
2919
2920 ;; unhighlight the background overlay for diff n so it won't
2921 ;; interfere with the current diff overlay
2922 (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
2923 )))
2924
2925
2926(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
2927 (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
2928 (let ((current-diff-overlay
2929 (symbol-value
2930 (intern (format "ediff-current-diff-overlay-%S" buf-type))))
2931 (overlay
2932 (ediff-get-diff-overlay ediff-current-difference buf-type))
2933 )
2934
2935 (ediff-move-overlay current-diff-overlay 1 1)
2936
2937 ;; rehighlight the overlay in the background of the
2938 ;; current difference region
2939 (ediff-set-overlay-face
2940 overlay
2941 (if (and (ediff-has-face-support-p)
2942 ediff-use-faces ediff-highlight-all-diffs)
2943 (ediff-background-face buf-type ediff-current-difference)))
2944 )))
2945
2946(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
2947 (ediff-unselect-and-select-difference -1)
2948 (if (and (ediff-has-face-support-p) ediff-use-faces)
2949 (let* ((inhibit-quit t)
2950 (current-diff-overlay-var
2951 (intern (format "ediff-current-diff-overlay-%S" buf-type)))
2952 (current-diff-overlay (symbol-value current-diff-overlay-var)))
2953 (ediff-color-background-regions 'unhighlight)
2954 (if (ediff-overlayp current-diff-overlay)
2955 (ediff-delete-overlay current-diff-overlay))
2956 (set current-diff-overlay-var nil)
2957 )))
2958 3037
2959 3038
2960;; null out difference overlays so they won't slow down future 3039;; null out difference overlays so they won't slow down future
@@ -2973,58 +3052,10 @@ Without an argument, it saves customized diff argument, if available
2973 ;; allow them to be garbage collected 3052 ;; allow them to be garbage collected
2974 (set vec-var nil)) 3053 (set vec-var nil))
2975 3054
2976(defun ediff-color-background-regions (&optional unhighlight)
2977 (ediff-color-background-regions-in-one-buffer
2978 'A unhighlight)
2979 (ediff-color-background-regions-in-one-buffer
2980 'B unhighlight)
2981 (ediff-color-background-regions-in-one-buffer
2982 'C unhighlight)
2983 (ediff-color-background-regions-in-one-buffer
2984 'Ancestor unhighlight))
2985
2986(defun ediff-color-background-regions-in-one-buffer (buf-type unhighlight)
2987 (let ((diff-vector
2988 (eval (intern (format "ediff-difference-vector-%S" buf-type))))
2989 overl diff-num)
2990 (mapcar (function
2991 (lambda (rec)
2992 (setq overl (ediff-get-diff-overlay-from-diff-record rec)
2993 diff-num (ediff-overlay-get overl 'ediff-diff-num))
2994 (ediff-set-overlay-face
2995 overl
2996 (if (not unhighlight)
2997 (ediff-background-face buf-type diff-num))
2998 )))
2999 diff-vector)))
3000 3055
3001 3056
3002;;; Misc 3057;;; Misc
3003 3058
3004;; These two functions are here to neutralize XEmacs unwillingless to
3005;; handle overlays whose buffers were deleted.
3006(defun ediff-move-overlay (overlay beg end &optional buffer)
3007 "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
3008Checks if overlay's buffer exists before actually doing the move."
3009 (let ((buf (and overlay (ediff-overlay-buffer overlay))))
3010 (if (ediff-buffer-live-p buf)
3011 (if ediff-xemacs-p
3012 (set-extent-endpoints overlay beg end)
3013 (move-overlay overlay beg end buffer))
3014 ;; buffer's dead
3015 (if overlay
3016 (ediff-delete-overlay overlay)))))
3017
3018(defun ediff-overlay-put (overlay prop value)
3019 "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
3020Checks if overlay's buffer exists."
3021 (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
3022 (if ediff-xemacs-p
3023 (set-extent-property overlay prop value)
3024 (overlay-put overlay prop value))
3025 (ediff-delete-overlay overlay)))
3026
3027
3028;; In Emacs, this just makes overlay. In the future, when Emacs will start 3059;; In Emacs, this just makes overlay. In the future, when Emacs will start
3029;; supporting sticky overlays, this function will make a sticky overlay. 3060;; supporting sticky overlays, this function will make a sticky overlay.
3030;; BEG and END are expressions telling where overlay starts. 3061;; BEG and END are expressions telling where overlay starts.
@@ -3462,6 +3493,7 @@ Mail anyway? (y or n) ")
3462;;; Local Variables: 3493;;; Local Variables:
3463;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 3494;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
3464;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 3495;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
3496;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
3465;;; End: 3497;;; End:
3466 3498
3467(provide 'ediff-util) 3499(provide 'ediff-util)
diff --git a/lisp/ediff-vers.el b/lisp/ediff-vers.el
index 5730d52062d..cec2d6f2ccf 100644
--- a/lisp/ediff-vers.el
+++ b/lisp/ediff-vers.el
@@ -31,15 +31,16 @@
31(defvar cvs-program) 31(defvar cvs-program)
32(defvar cvs-cookie-handle) 32(defvar cvs-cookie-handle)
33 33
34(eval-when-compile 34(and noninteractive
35 (load "pcl-cvs" 'noerror) 35 (eval-when-compile
36 (load "rcs" 'noerror) 36 (load "pcl-cvs" 'noerror)
37 (load "generic-sc" 'noerror) 37 (load "rcs" 'noerror)
38 (load "vc" 'noerror)) 38 (load "generic-sc" 'noerror)
39 (load "vc" 'noerror)))
39;; end pacifier 40;; end pacifier
40 41
41;; VC.el support 42;; VC.el support
42(defun vc-ediff-internal (rev1 rev2 &optional startup-hooks) 43(defun ediff-vc-internal (rev1 rev2 &optional startup-hooks)
43;; Run Ediff on versions of the current buffer. 44;; Run Ediff on versions of the current buffer.
44;; If REV2 is "" then compare current buffer with REV1. 45;; If REV2 is "" then compare current buffer with REV1.
45;; If the current buffer is named `F', the version is named `F.~REV~'. 46;; If the current buffer is named `F', the version is named `F.~REV~'.
@@ -103,7 +104,7 @@
103 (erase-buffer)) 104 (erase-buffer))
104 buf)) 105 buf))
105 106
106(defun rcs-ediff-internal (rev1 rev2 &optional startup-hooks) 107(defun ediff-rcs-internal (rev1 rev2 &optional startup-hooks)
107;; Run Ediff on versions of the current buffer. 108;; Run Ediff on versions of the current buffer.
108;; If REV2 is "" then use current buffer. 109;; If REV2 is "" then use current buffer.
109 (let ((rev2buf (if (string= rev2 "") 110 (let ((rev2buf (if (string= rev2 "")
@@ -124,7 +125,7 @@
124 (eval "main/LATEST")) 125 (eval "main/LATEST"))
125 (t (eval "")))) 126 (t (eval ""))))
126 127
127(defun generic-sc-ediff-internal (rev1 rev2 &optional startup-hooks) 128(defun ediff-generic-sc-internal (rev1 rev2 &optional startup-hooks)
128;; Run Ediff on versions of the current buffer. 129;; Run Ediff on versions of the current buffer.
129;; If REV2 is "" then compare current buffer with REV1. 130;; If REV2 is "" then compare current buffer with REV1.
130;; If the current buffer is named `F', the version is named `F.~REV~'. 131;; If the current buffer is named `F', the version is named `F.~REV~'.
@@ -144,7 +145,7 @@
144 145
145;;; Merge with Version Control 146;;; Merge with Version Control
146 147
147(defun vc-ediff-merge-internal (rev1 rev2 ancestor-rev &optional startup-hooks) 148(defun ediff-vc-merge-internal (rev1 rev2 ancestor-rev &optional startup-hooks)
148;; If ANCESTOR-REV non-nil, merge with ancestor 149;; If ANCESTOR-REV non-nil, merge with ancestor
149 (let (buf1 buf2 ancestor-buf) 150 (let (buf1 buf2 ancestor-buf)
150 (save-excursion 151 (save-excursion
@@ -177,7 +178,7 @@
177 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions)) 178 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions))
178 )) 179 ))
179 180
180(defun rcs-ediff-merge-internal (rev1 rev2 ancestor-rev 181(defun ediff-rcs-merge-internal (rev1 rev2 ancestor-rev
181 &optional startup-hooks) 182 &optional startup-hooks)
182 ;; If ANCESTOR-REV non-nil, merge with ancestor 183 ;; If ANCESTOR-REV non-nil, merge with ancestor
183 (let (buf1 buf2 ancestor-buf) 184 (let (buf1 buf2 ancestor-buf)
@@ -197,7 +198,7 @@
197 startup-hooks 'ediff-merge-revisions-with-ancestor) 198 startup-hooks 'ediff-merge-revisions-with-ancestor)
198 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions)))) 199 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions))))
199 200
200(defun generic-sc-ediff-merge-internal (rev1 rev2 ancestor-rev 201(defun ediff-generic-sc-merge-internal (rev1 rev2 ancestor-rev
201 &optional startup-hooks) 202 &optional startup-hooks)
202 ;; If ANCESTOR-REV non-nil, merge with ancestor 203 ;; If ANCESTOR-REV non-nil, merge with ancestor
203 (let (buf1 buf2 ancestor-buf) 204 (let (buf1 buf2 ancestor-buf)
@@ -224,7 +225,7 @@
224 225
225;; PCL-CVS.el support 226;; PCL-CVS.el support
226 227
227(defun pcl-cvs-ediff-internal (rev1 rev2 &optional startup-hooks) 228(defun ediff-pcl-cvs-internal (rev1 rev2 &optional startup-hooks)
228;; Run Ediff on a pair of revisions of the current buffer. 229;; Run Ediff on a pair of revisions of the current buffer.
229;; If REV1 is "", use the latest revision. 230;; If REV1 is "", use the latest revision.
230;; If REV2 is "", use the current buffer as the second file to compare. 231;; If REV2 is "", use the current buffer as the second file to compare.
@@ -251,7 +252,7 @@
251;; This function is the standard Ediff's interface to pcl-cvs. 252;; This function is the standard Ediff's interface to pcl-cvs.
252;; Works like with other interfaces: runs ediff on versions of the file in the 253;; Works like with other interfaces: runs ediff on versions of the file in the
253;; current buffer. 254;; current buffer.
254(defun pcl-cvs-ediff-merge-internal (rev1 rev2 ancestor-rev 255(defun ediff-pcl-cvs-merge-internal (rev1 rev2 ancestor-rev
255 &optional startup-hooks) 256 &optional startup-hooks)
256;; Ediff-merge appropriate revisions of the selected file. 257;; Ediff-merge appropriate revisions of the selected file.
257;; If REV1 is "" then use the latest revision. 258;; If REV1 is "" then use the latest revision.
@@ -358,6 +359,7 @@
358;;; Local Variables: 359;;; Local Variables:
359;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 360;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
360;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 361;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
362;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
361;;; End: 363;;; End:
362 364
363(provide 'ediff-vers) 365(provide 'ediff-vers)
diff --git a/lisp/ediff-wind.el b/lisp/ediff-wind.el
index f4033cf5b85..58cae39a191 100644
--- a/lisp/ediff-wind.el
+++ b/lisp/ediff-wind.el
@@ -853,7 +853,7 @@ into icons, regardless of the window manager.")
853 ;; 1 more line for the modeline 853 ;; 1 more line for the modeline
854 (setq lines (1+ (count-lines (point-min) (point-max))) 854 (setq lines (1+ (count-lines (point-min) (point-max)))
855 fheight lines 855 fheight lines
856 fwidth (+ (ediff-help-message-line-length) 2) 856 fwidth (+ (ediff-help-message-line-length) 1)
857 adjusted-parameters (append (list 857 adjusted-parameters (append (list
858 ;; possibly change surrogate minibuffer 858 ;; possibly change surrogate minibuffer
859 (cons 'minibuffer 859 (cons 'minibuffer
@@ -1061,7 +1061,7 @@ It assumes that it is called from within the control buffer."
1061 (setq mode-line-format 1061 (setq mode-line-format
1062 (list (if (ediff-narrow-control-frame-p) " " "-- ") 1062 (list (if (ediff-narrow-control-frame-p) " " "-- ")
1063 mode-line-buffer-identification 1063 mode-line-buffer-identification
1064 " Quick Help")) 1064 " Quick Help"))
1065 ;; control buffer id 1065 ;; control buffer id
1066 (setq mode-line-buffer-identification 1066 (setq mode-line-buffer-identification
1067 (if (ediff-narrow-control-frame-p) 1067 (if (ediff-narrow-control-frame-p)
@@ -1199,6 +1199,7 @@ It assumes that it is called from within the control buffer."
1199;;; Local Variables: 1199;;; Local Variables:
1200;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 1200;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1201;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 1201;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1202;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1202;;; End: 1203;;; End:
1203 1204
1204(provide 'ediff-wind) 1205(provide 'ediff-wind)
diff --git a/lisp/ediff.el b/lisp/ediff.el
index d071c72114d..be9c1d143d4 100644
--- a/lisp/ediff.el
+++ b/lisp/ediff.el
@@ -6,8 +6,8 @@
6;; Created: February 2, 1994 6;; Created: February 2, 1994
7;; Keywords: comparing, merging, patching, version control. 7;; Keywords: comparing, merging, patching, version control.
8 8
9(defconst ediff-version "2.61" "The current version of Ediff") 9(defconst ediff-version "2.63" "The current version of Ediff")
10(defconst ediff-date "June 10, 1996" "Date of last update") 10(defconst ediff-date "September 12, 1996" "Date of last update")
11 11
12 12
13;; This file is part of GNU Emacs. 13;; This file is part of GNU Emacs.
@@ -110,11 +110,13 @@
110;; ediff-mult is always required, because of the registry stuff 110;; ediff-mult is always required, because of the registry stuff
111(require 'ediff-mult) 111(require 'ediff-mult)
112 112
113(eval-when-compile 113(and noninteractive
114 (load "dired") 114 (eval-when-compile
115 (load-file "./ediff-ptch.el") 115 (let ((load-path (cons (expand-file-name ".") load-path)))
116 (load-file "./ediff-vers.el") 116 (load-library "dired")
117 (load "pcl-cvs" 'noerror)) 117 (load-file "ediff-ptch.el")
118 (load-file "ediff-vers.el")
119 (load "pcl-cvs" 'noerror))))
118 120
119(defvar ediff-use-last-dir nil 121(defvar ediff-use-last-dir nil
120 "*If t, Ediff uses previous directory as default when reading file name.") 122 "*If t, Ediff uses previous directory as default when reading file name.")
@@ -127,6 +129,8 @@
127 "Last directory used by an Ediff command for file-C.") 129 "Last directory used by an Ediff command for file-C.")
128(defvar ediff-last-dir-ancestor nil 130(defvar ediff-last-dir-ancestor nil
129 "Last directory used by an Ediff command for the ancestor file.") 131 "Last directory used by an Ediff command for the ancestor file.")
132(defvar ediff-last-merge-autostore-dir
133 "Last directory used by an Ediff command as the output directory for merge.")
130 134
131;; Some defvars to reduce the number of compiler warnings 135;; Some defvars to reduce the number of compiler warnings
132(defvar cvs-cookie-handle) 136(defvar cvs-cookie-handle)
@@ -562,7 +566,7 @@ can be used to filter out certain file names."
562The second argument, REGEXP, is a regular expression that filters the file 566The second argument, REGEXP, is a regular expression that filters the file
563names. Only the files that are under revision control are taken into account." 567names. Only the files that are under revision control are taken into account."
564 (interactive 568 (interactive
565 (let ((dir-A (ediff-get-default-directory-name))) 569 (let* ((dir-A (ediff-get-default-directory-name)))
566 (list (ediff-read-file-name 570 (list (ediff-read-file-name
567 "Directory to merge with revisions:" dir-A nil) 571 "Directory to merge with revisions:" dir-A nil)
568 (read-string "Filter through regular expression: " 572 (read-string "Filter through regular expression: "
@@ -581,7 +585,7 @@ names. Only the files that are under revision control are taken into account."
581The second argument, REGEXP, is a regular expression that filters the file 585The second argument, REGEXP, is a regular expression that filters the file
582names. Only the files that are under revision control are taken into account." 586names. Only the files that are under revision control are taken into account."
583 (interactive 587 (interactive
584 (let ((dir-A (ediff-get-default-directory-name))) 588 (let* ((dir-A (ediff-get-default-directory-name)))
585 (list (ediff-read-file-name 589 (list (ediff-read-file-name
586 "Directory to merge with revisions and ancestors:" dir-A nil) 590 "Directory to merge with revisions and ancestors:" dir-A nil)
587 (read-string "Filter through regular expression: " 591 (read-string "Filter through regular expression: "
@@ -605,8 +609,8 @@ names. Only the files that are under revision control are taken into account."
605;; The third argument, REGEXP, is a regular expression that can be used to 609;; The third argument, REGEXP, is a regular expression that can be used to
606;; filter out certain file names. 610;; filter out certain file names.
607;; JOBNAME is the symbol indicating the meta-job to be performed. 611;; JOBNAME is the symbol indicating the meta-job to be performed.
608(defun ediff-directories-internal (dir1 dir2 dir3 regexp 612;; MERGE-DIR is the directory in which to store merged files.
609 action jobname 613(defun ediff-directories-internal (dir1 dir2 dir3 regexp action jobname
610 &optional startup-hooks) 614 &optional startup-hooks)
611 ;; ediff-read-file-name is set to attach a previously entered file name if 615 ;; ediff-read-file-name is set to attach a previously entered file name if
612 ;; the currently entered file is a directory. This code takes care of that. 616 ;; the currently entered file is a directory. This code takes care of that.
@@ -626,9 +630,31 @@ names. Only the files that are under revision control are taken into account."
626 (error "Directories B and C are the same: %s" dir1))) 630 (error "Directories B and C are the same: %s" dir1)))
627 631
628 (let (diffs ; var where ediff-intersect-directories returns the diff list 632 (let (diffs ; var where ediff-intersect-directories returns the diff list
633 merge-autostore-dir
629 file-list meta-buf) 634 file-list meta-buf)
635 (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
636 (setq merge-autostore-dir
637 (ediff-read-file-name "Directory to save merged files:"
638 (if ediff-use-last-dir
639 ediff-last-merge-autostore-dir
640 (ediff-strip-last-dir dir1))
641 nil)))
642 ;; verify we are not merging into an orig directory
643 (if (stringp merge-autostore-dir)
644 (cond ((and (stringp dir1) (string= merge-autostore-dir dir1))
645 (or (y-or-n-p "Merge directory same as directory A, sure? ")
646 (error "Directory merge aborted")))
647 ((and (stringp dir2) (string= merge-autostore-dir dir2))
648 (or (y-or-n-p "Merge directory same as directory B, sure? ")
649 (error "Directory merge aborted")))
650 ((and (stringp dir3) (string= merge-autostore-dir dir3))
651 (or (y-or-n-p
652 "Merge directory same as ancestor directory, sure? ")
653 (error "Directory merge aborted")))))
654
630 (setq file-list (ediff-intersect-directories 655 (setq file-list (ediff-intersect-directories
631 jobname 'diffs regexp dir1 dir2 dir3)) 656 jobname 'diffs
657 regexp dir1 dir2 dir3 merge-autostore-dir))
632 (setq startup-hooks 658 (setq startup-hooks
633 ;; this sets various vars in the meta buffer inside 659 ;; this sets various vars in the meta buffer inside
634 ;; ediff-prepare-meta-buffer 660 ;; ediff-prepare-meta-buffer
@@ -651,9 +677,26 @@ names. Only the files that are under revision control are taken into account."
651(defun ediff-directory-revisions-internal (dir1 regexp action jobname 677(defun ediff-directory-revisions-internal (dir1 regexp action jobname
652 &optional startup-hooks) 678 &optional startup-hooks)
653 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1))) 679 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1)))
654 (let (file-list meta-buf) 680
681 (let (file-list meta-buf merge-autostore-dir)
682 (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
683 (setq merge-autostore-dir
684 (ediff-read-file-name "Directory to save merged files:"
685 (if ediff-use-last-dir
686 ediff-last-merge-autostore-dir
687 (ediff-strip-last-dir dir1))
688 nil)))
689 ;; verify merge-autostore-dir != dir1
690 (if (and (stringp merge-autostore-dir)
691 (stringp dir1)
692 (string= merge-autostore-dir dir1))
693 (or (y-or-n-p
694 "Directory for saving merges is the same as directory A. Sure? ")
695 (error "Merge of directory revisions aborted")))
696
655 (setq file-list 697 (setq file-list
656 (ediff-get-directory-files-under-revision jobname regexp dir1)) 698 (ediff-get-directory-files-under-revision
699 jobname regexp dir1 merge-autostore-dir))
657 (setq startup-hooks 700 (setq startup-hooks
658 ;; this sets various vars in the meta buffer inside 701 ;; this sets various vars in the meta buffer inside
659 ;; ediff-prepare-meta-buffer 702 ;; ediff-prepare-meta-buffer
@@ -804,7 +847,6 @@ lines. For small regions, use `ediff-regions-wordwise'."
804 (setq reg-B-beg (region-beginning) 847 (setq reg-B-beg (region-beginning)
805 reg-B-end (region-end)) 848 reg-B-end (region-end))
806 ;; enlarge the region to hold full lines 849 ;; enlarge the region to hold full lines
807 (goto-char reg-A-beg)
808 (goto-char reg-B-beg) 850 (goto-char reg-B-beg)
809 (beginning-of-line) 851 (beginning-of-line)
810 (setq reg-B-beg (point)) 852 (setq reg-B-beg (point))
@@ -1052,7 +1094,7 @@ buffer."
1052 (ediff-load-version-control) 1094 (ediff-load-version-control)
1053 ;; ancestor-revision=nil 1095 ;; ancestor-revision=nil
1054 (funcall 1096 (funcall
1055 (intern (format "%S-ediff-merge-internal" ediff-version-control-package)) 1097 (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
1056 rev1 rev2 nil startup-hooks))) 1098 rev1 rev2 nil startup-hooks)))
1057 1099
1058 1100
@@ -1084,7 +1126,7 @@ buffer."
1084 (file-name-nondirectory file) "current buffer")))) 1126 (file-name-nondirectory file) "current buffer"))))
1085 (ediff-load-version-control) 1127 (ediff-load-version-control)
1086 (funcall 1128 (funcall
1087 (intern (format "%S-ediff-merge-internal" ediff-version-control-package)) 1129 (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
1088 rev1 rev2 ancestor-rev startup-hooks))) 1130 rev1 rev2 ancestor-rev startup-hooks)))
1089 1131
1090;;;###autoload 1132;;;###autoload
@@ -1168,7 +1210,7 @@ buffer. Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'."
1168 (file-name-nondirectory file) "current buffer")))) 1210 (file-name-nondirectory file) "current buffer"))))
1169 (ediff-load-version-control) 1211 (ediff-load-version-control)
1170 (funcall 1212 (funcall
1171 (intern (format "%S-ediff-internal" ediff-version-control-package)) 1213 (intern (format "ediff-%S-internal" ediff-version-control-package))
1172 rev1 rev2 startup-hooks) 1214 rev1 rev2 startup-hooks)
1173 )) 1215 ))
1174 1216
@@ -1198,8 +1240,9 @@ When called interactively, displays the version."
1198 1240
1199 1241
1200;;;###autoload 1242;;;###autoload
1201(defun ediff-documentation () 1243(defun ediff-documentation (&optional node)
1202 "Display Ediff's manual." 1244 "Display Ediff's manual.
1245With optional NODE, goes to that node."
1203 (interactive) 1246 (interactive)
1204 (let ((ctl-window ediff-control-window) 1247 (let ((ctl-window ediff-control-window)
1205 (ctl-buf ediff-control-buffer)) 1248 (ctl-buf ediff-control-buffer))
@@ -1209,15 +1252,13 @@ When called interactively, displays the version."
1209 (progn 1252 (progn
1210 (pop-to-buffer (get-buffer-create "*info*")) 1253 (pop-to-buffer (get-buffer-create "*info*"))
1211 (info (if ediff-xemacs-p "ediff.info" "ediff")) 1254 (info (if ediff-xemacs-p "ediff.info" "ediff"))
1212 (message "Type `i' to search for a specific topic")) 1255 (if node
1256 (Info-goto-node node)
1257 (message "Type `i' to search for a specific topic"))
1258 (raise-frame (selected-frame)))
1213 (error (beep 1) 1259 (error (beep 1)
1214 (with-output-to-temp-buffer ediff-msg-buffer 1260 (with-output-to-temp-buffer ediff-msg-buffer
1215 (princ (format " 1261 (princ ediff-BAD-INFO))
1216The Info file for Ediff does not seem to be installed.
1217
1218This file is part of the distribution of %sEmacs.
1219Please contact your system administrator. "
1220 (if ediff-xemacs-p "X" ""))))
1221 (if (window-live-p ctl-window) 1262 (if (window-live-p ctl-window)
1222 (progn 1263 (progn
1223 (select-window ctl-window) 1264 (select-window ctl-window)
@@ -1229,6 +1270,7 @@ Please contact your system administrator. "
1229;;; Local Variables: 1270;;; Local Variables:
1230;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 1271;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1231;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 1272;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1273;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1232;;; End: 1274;;; End:
1233 1275
1234(provide 'ediff) 1276(provide 'ediff)
diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el
index baf8c889250..09e2787ccad 100644
--- a/lisp/emulation/viper-util.el
+++ b/lisp/emulation/viper-util.el
@@ -553,7 +553,11 @@ to write a custom function, similar to `vip-ex-nontrivial-find-file-unix'."
553 (setq tmp (cdr tmp))) 553 (setq tmp (cdr tmp)))
554 (reverse (apply 'append tmp2)))) 554 (reverse (apply 'append tmp2))))
555 555
556 556(defun vip-convert-standard-file-name (fname)
557 (if vip-emacs-p
558 (convert-standard-filename fname)
559 ;; hopefully, XEmacs adds this functionality
560 fname))
557 561
558 562
559 563
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 5711d448a26..f3ede946449 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -821,7 +821,7 @@ These buffers can be cycled through via :R and :P commands.")
821(defvar vip-always t 821(defvar vip-always t
822 "t means, arrange that vi-state will be a default.") 822 "t means, arrange that vi-state will be a default.")
823 823
824(defvar vip-custom-file-name (convert-standard-filename "~/.vip") 824(defvar vip-custom-file-name (vip-convert-standard-file-name "~/.vip")
825 "Viper customisation file. 825 "Viper customisation file.
826This variable must be set _before_ loading Viper.") 826This variable must be set _before_ loading Viper.")
827 827
@@ -2847,10 +2847,8 @@ Undo previous insertion and inserts new."
2847 (setq vip-cted t) 2847 (setq vip-cted t)
2848 (if vip-electric-mode 2848 (if vip-electric-mode
2849 (indent-according-to-mode) 2849 (indent-according-to-mode)
2850 (indent-to col)) 2850 (indent-to col))))
2851 )) 2851 (vip-change-state-to-insert)))))
2852 (vip-change-state-to-insert)
2853 ))))
2854 2852
2855(defun vip-Open-line (arg) 2853(defun vip-Open-line (arg)
2856 "Open line above." 2854 "Open line above."
@@ -3851,8 +3849,9 @@ controlled by the sign of prefix numeric value."
3851(defun vip-paren-match (arg) 3849(defun vip-paren-match (arg)
3852 "Go to the matching parenthesis." 3850 "Go to the matching parenthesis."
3853 (interactive "P") 3851 (interactive "P")
3852 (vip-leave-region-active)
3854 (let ((com (vip-getcom arg)) 3853 (let ((com (vip-getcom arg))
3855 anchor-point) 3854 parse-sexp-ignore-comments anchor-point)
3856 (if (integerp arg) 3855 (if (integerp arg)
3857 (if (or (> arg 99) (< arg 1)) 3856 (if (or (> arg 99) (< arg 1))
3858 (error "Prefix must be between 1 and 99") 3857 (error "Prefix must be between 1 and 99")
@@ -4904,7 +4903,9 @@ One can use `` and '' to temporarily jump 1 step back."
4904 vip-open-line vip-Open-line 4903 vip-open-line vip-Open-line
4905 vip-replace-state-exit-cmd)) 4904 vip-replace-state-exit-cmd))
4906 (indent-to-left-margin)) 4905 (indent-to-left-margin))
4907 (newline 1) 4906 ;; use \n instead of newline, or else <Return> will move the insert point
4907 ;;(newline 1)
4908 (insert "\n")
4908 (if vip-auto-indent 4909 (if vip-auto-indent
4909 (progn 4910 (progn
4910 (setq vip-cted t) 4911 (setq vip-cted t)