Fix default-directory for vc-root-diff.
[bpt/emacs.git] / lisp / ediff-util.el
index 120228c..77284a1 100644 (file)
@@ -1,16 +1,16 @@
 ;;; ediff-util.el --- the core commands and utilities of ediff
 
 ;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-;;   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;;   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,9 +18,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -30,8 +28,6 @@
 (provide 'ediff-util)
 
 ;; Compiler pacifier
-(defvar ediff-patch-diagnostics)
-(defvar ediff-patchbufer)
 (defvar ediff-use-toolbar-p)
 (defvar ediff-toolbar-height)
 (defvar ediff-toolbar)
   (unless (fboundp 'declare-function) (defmacro declare-function (&rest  r))))
 
 (eval-when-compile
-  (require 'ediff-init)
-  (require 'ediff-help)
-  (if (not (featurep 'ediff-mult))
-      (require 'ediff-mult))
-  (require 'ediff-mult)
-  (require 'ediff-wind)
-  (if (not (featurep 'ediff-diff))
-      (require 'ediff-diff))
-  (require 'ediff-merg)
-  (require 'ediff)
-  ;; for compatibility with current stable version of xemacs
-  (if (featurep 'xemacs)
-      (require 'ediff-tbar))
-  )
+  (require 'ediff))
+
 ;; end pacifier
 
 
@@ -70,7 +54,6 @@
 (require 'ediff-wind)
 (require 'ediff-diff)
 (require 'ediff-merg)
-
 ;; for compatibility with current stable version of xemacs
 (if (featurep 'xemacs)
     (require 'ediff-tbar))
@@ -360,8 +343,7 @@ to invocation.")
            (setq buffer-C
                  (get-buffer-create
                   (ediff-unique-buffer-name "*ediff-merge" "*")))
-           (save-excursion
-             (set-buffer buffer-C)
+           (with-current-buffer buffer-C
              (insert-buffer-substring buf)
              (goto-char (point-min))
              (funcall (ediff-with-current-buffer buf major-mode))
@@ -1029,7 +1011,7 @@ of the current buffer."
   (interactive)
   (ediff-barf-if-not-control-buffer)
   (let ((ctl-buf (if (null buf) (current-buffer)))
-       (buf-type (ediff-char-to-buftype last-command-char)))
+       (buf-type (ediff-char-to-buftype (ediff-last-command-char))))
     (or buf (ediff-recenter))
     (or buf
        (setq buf (ediff-get-buffer buf-type)))
@@ -1144,8 +1126,8 @@ of the current buffer."
 
 (defun ediff-file-checked-in-p (file)
   (and (featurep 'vc-hooks)
-       ;; CVS files are considered not checked in
-       (not (memq (vc-backend file) '(nil CVS)))
+       ;; Only RCS and SCCS files are considered checked in
+       (memq (vc-backend file) '(RCS SCCS))
        (if (fboundp 'vc-state)
           (and
            (not (memq (vc-state file) '(edited needs-merge)))
@@ -1311,12 +1293,14 @@ which see."
        ((eq ediff-window-setup-function 'ediff-setup-windows-plain)
         (if (ediff-in-control-buffer-p)
             (ediff-kill-bottom-toolbar))
-        (if (ediff-buffer-live-p ediff-control-buffer)
+        (if (and (ediff-buffer-live-p ediff-control-buffer)
+                 (window-live-p ediff-control-window))
             (set-window-dedicated-p ediff-control-window nil))
         (setq ediff-multiframe t)
         (setq window-setup-func 'ediff-setup-windows-multiframe))
        (t
-        (if (ediff-buffer-live-p ediff-control-buffer)
+        (if (and (ediff-buffer-live-p ediff-control-buffer)
+                 (window-live-p ediff-control-window))
             (set-window-dedicated-p ediff-control-window nil))
         (setq ediff-multiframe t)
         (setq window-setup-func 'ediff-setup-windows-multiframe))
@@ -1330,7 +1314,9 @@ which see."
                             ediff-window-B nil)))
        ediff-session-registry)
   (if (ediff-in-control-buffer-p)
-      (ediff-recenter 'no-rehighlight))))
+      (progn
+       (set-window-dedicated-p (selected-window) nil)
+       (ediff-recenter 'no-rehighlight)))))
 
 
 ;;;###autoload
@@ -1527,7 +1513,7 @@ the one half of the height of window-A."
       (error ediff-KILLED-VITAL-BUFFER))
 
   (ediff-operate-on-windows
-   (if (memq last-command-char '(?v ?\C-v))
+   (if (memq (ediff-last-command-char) '(?v ?\C-v))
        'scroll-up
      'scroll-down)
    ;; calculate argument to scroll-up/down
@@ -1575,7 +1561,7 @@ the width of the A/B/C windows."
    ;; interactively so that they set the window's min_hscroll.
    ;; Otherwise, automatic hscrolling will undo the effect of
    ;; hscrolling.
-   (if (= last-command-char ?<)
+   (if (= (ediff-last-command-char) ?<)
        (lambda (arg)
         (let ((prefix-arg arg))
           (call-interactively 'scroll-left)))
@@ -1839,7 +1825,7 @@ With a prefix argument, synchronize all files around the current point position
 in the specified buffer."
   (interactive "P")
   (ediff-barf-if-not-control-buffer)
-  (let* ((buf-type (ediff-char-to-buftype last-command-char))
+  (let* ((buf-type (ediff-char-to-buftype (ediff-last-command-char)))
         (buffer (ediff-get-buffer buf-type))
         (pt (ediff-with-current-buffer buffer (point)))
         (diff-no (ediff-diff-at-point buf-type nil (if arg 'after)))
@@ -2175,13 +2161,13 @@ ARG is a prefix argument.  If nil, copy the current difference region."
   "Restore ARGth diff from `ediff-killed-diffs-alist'.
 ARG is a prefix argument.  If ARG is nil, restore the current-difference.
 If the second optional argument, a character, is given, use it to
-determine the target buffer instead of last-command-char"
+determine the target buffer instead of (ediff-last-command-char)"
   (interactive "P")
   (ediff-barf-if-not-control-buffer)
   (if (numberp arg)
       (ediff-jump-to-difference arg))
   (ediff-pop-diff ediff-current-difference
-                 (ediff-char-to-buftype (or key last-command-char)))
+                 (ediff-char-to-buftype (or key (ediff-last-command-char))))
   ;; recenter with rehighlighting, but no messages
   (let (ediff-verbose-p)
     (ediff-recenter)))
@@ -2205,13 +2191,13 @@ a regular expression typed in by the user."
     (cond
      ((or (and (eq ediff-skip-diff-region-function
                   ediff-focus-on-regexp-matches-function)
-              (eq last-command-char ?f))
+              (eq (ediff-last-command-char) ?f))
          (and (eq ediff-skip-diff-region-function
                   ediff-hide-regexp-matches-function)
-              (eq last-command-char ?h)))
+              (eq (ediff-last-command-char) ?h)))
       (message "Selective browsing by regexp turned off")
       (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
-     ((eq last-command-char ?h)
+     ((eq (ediff-last-command-char) ?h)
       (setq ediff-skip-diff-region-function ediff-hide-regexp-matches-function
            regexp-A
            (read-string
@@ -2249,7 +2235,7 @@ a regular expression typed in by the user."
       (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
       (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
 
-     ((eq last-command-char ?f)
+     ((eq (ediff-last-command-char) ?f)
       (setq ediff-skip-diff-region-function
            ediff-focus-on-regexp-matches-function
            regexp-A
@@ -2732,7 +2718,7 @@ only if this merge job is part of a group, i.e., was invoked from within
       (if (or (not (file-exists-p file))
              (y-or-n-p (format "File %s exists, overwrite? " file)))
          (progn
-           ;;(write-region (point-min) (point-max) file)
+           ;;(write-region nil nil file)
            (ediff-with-current-buffer buf
              (set-visited-file-name file)
              (save-buffer))
@@ -3105,6 +3091,12 @@ Hit \\[ediff-recenter] to reset the windows afterward."
   )
 
 
+;; for compatibility
+(defmacro ediff-minibuffer-with-setup-hook (fun &rest body)
+  `(if (fboundp 'minibuffer-with-setup-hook)
+       (minibuffer-with-setup-hook ,fun ,@body)
+     ,@body))
+
 ;; This is adapted from a similar function in `emerge.el'.
 ;; PROMPT should not have a trailing ': ', so that it can be modified
 ;; according to context.
@@ -3127,21 +3119,25 @@ Hit \\[ediff-recenter] to reset the windows afterward."
   (if (string= default-file "")
       (setq default-file nil))
 
-  (let (f)
-    (setq f (expand-file-name
-            (read-file-name
-             (format "%s%s "
-                     prompt
-                     (cond (default-file
-                             (concat " (default " default-file "):"))
-                           (t (concat " (default " default-dir "):"))))
-             default-dir
-             (or default-file default-dir)
-             t  ; must match, no-confirm
-             (if default-file (file-name-directory default-file))
-             )
-            default-dir
-            ))
+  (let ((defaults (and (fboundp 'dired-dwim-target-defaults)
+                      (dired-dwim-target-defaults
+                       (and default-file (list default-file))
+                       default-dir)))
+       f)
+    (setq f (ediff-minibuffer-with-setup-hook
+               (lambda () (when defaults
+                            (setq minibuffer-default defaults)))
+             (read-file-name
+              (format "%s%s "
+                      prompt
+                      (cond (default-file
+                              (concat " (default " default-file "):"))
+                            (t (concat " (default " default-dir "):"))))
+              default-dir
+              (or default-file default-dir)
+              t                        ; must match, no-confirm
+              (if default-file (file-name-directory default-file)))))
+    (setq f (expand-file-name f default-dir))
     ;; If user entered a directory name, expand the default file in that
     ;; directory.  This allows the user to enter a directory name for the
     ;; B-file and diff against the default-file in that directory instead
@@ -3163,11 +3159,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
 (defun ediff-make-temp-file (buff &optional prefix given-file start end)
   (let* ((p (ediff-convert-standard-filename (or prefix "ediff")))
         (short-p p)
-        (coding-system-for-write
-         (ediff-with-current-buffer buff
-           (if (boundp 'buffer-file-coding-system)
-               buffer-file-coding-system
-             ediff-coding-system-for-write)))
+        (coding-system-for-write ediff-coding-system-for-write)
         f short-f)
     (if (and (fboundp 'msdos-long-file-names)
             (not (msdos-long-file-names))
@@ -3234,7 +3226,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
 ;; EMX OS/2
 ;;(defun ediff-protect-metachars (str)
-;;  (or (memq system-type '(emx vax-vms axp-vms))
+;;  (or (memq system-type '(emx))
 ;;      (let ((limit 0))
 ;;     (while (string-match ediff-metachars str limit)
 ;;       (setq str (concat (substring str 0 (match-beginning 0))
@@ -3319,10 +3311,10 @@ Without an argument, it saves customized diff argument, if available
   (ediff-barf-if-not-control-buffer)
   (ediff-compute-custom-diffs-maybe)
   (ediff-with-current-buffer
-      (cond ((memq last-command-char '(?a ?b ?c))
+      (cond ((memq (ediff-last-command-char) '(?a ?b ?c))
             (ediff-get-buffer
-             (ediff-char-to-buftype last-command-char)))
-           ((eq last-command-char ?d)
+             (ediff-char-to-buftype (ediff-last-command-char))))
+           ((eq (ediff-last-command-char) ?d)
             (message "Saving diff output ...")
             (sit-for 1) ; let the user see the message
             (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
@@ -3333,7 +3325,8 @@ Without an argument, it saves customized diff argument, if available
                    ediff-diff-buffer)
                   (t (error "Output from `diff' not found"))))
            )
-    (save-buffer)))
+    (let ((window-min-height 2))
+      (save-buffer))))
 
 
 ;; idea suggested by Hannu Koivisto <azure@iki.fi>
@@ -3432,11 +3425,8 @@ Without an argument, it saves customized diff argument, if available
     (ediff-exec-process
      ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
      ediff-custom-diff-options
-     ;; repetition of buf-A-file-name is needed so it'll return a file
-     (or (and buf-A-file-name (file-exists-p buf-A-file-name) buf-A-file-name)
-        file-A)
-     (or (and buf-B-file-name (file-exists-p buf-B-file-name) buf-B-file-name)
-        file-B))
+     (or file-A buf-A-file-name)
+     (or file-B buf-B-file-name))
     ;; put the diff file in diff-mode, if it is available
     (if (fboundp 'diff-mode)
        (with-current-buffer ediff-custom-diff-buffer