]> code.delx.au - gnu-emacs/blobdiff - lisp/ediff-mult.el
(enum event_kind) [MAC_OS]: Update comment for MAC_APPLE_EVENT.
[gnu-emacs] / lisp / ediff-mult.el
index 83dde656a15efa363c033f51a19e2d0f243135a2..0bbd3298c7a0538a33f67473fdc8c5112eaaf3c0 100644 (file)
@@ -1,6 +1,7 @@
 ;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff
 
-;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+;;   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 
@@ -18,8 +19,8 @@
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -27,7 +28,7 @@
 ;; The present file contains all the infrastructure needed for that.
 ;;
 ;; Generally, to implement a new multisession capability within Ediff,
-;; you need to tell it 
+;; you need to tell it
 ;;
 ;;     1. How to display the session group buffer.
 ;;        This function must indicate which Ediff sessions are active (+) and
 ;;     3. Provide a list of pairs or triples of file names (or buffers,
 ;;        depending on the particular Ediff operation you want to invoke)
 ;;        in the following format:
-;;             (descriptor-header (nil nil (obj1 nil) (obj2 nil) (obj3 nil))
+;;             (HEADER (nil nil (obj1 nil) (obj2 nil) (obj3 nil))
 ;;                                 (...) ...)
 ;;         The function ediff-make-new-meta-list-element can be used to create
-;;         2nd and subsequent elements of that list.
-;;        Actually, the format of this list is pretty much up to the
-;;        developer.  The only thing is that it must be a list of lists,
-;;        and the first list must describe the meta session, and subsequent
-;;        elements must describe individual sessions.
-;;        This descriptor-header must be a list of SIX elements (nil or
-;;         string).  The function ediff-redraw-registry-buffer displays the 
-;;        1st - 4th of these in the registry buffer. 
+;;         2nd and subsequent elements of that list (i.e., after the
+;;         description header). See ediff-make-new-meta-list-element for the
+;;         explanation of the two nil placeholders in such elements.
+;;
+;;         There is API for extracting the components of the members of the
+;;         above list. Search for `API for ediff-meta-list' for details.
+;;
+;;        HEADER must be a list of SIX elements (nil or string):
+;;             (regexp metaobj1 metaobj2 metaobj3 merge-save-buffer
+;;              comparison-function)
+;;         The function ediff-redraw-registry-buffer displays the
+;;        1st - 4th of these in the registry buffer.
+;;         For some jobs some of the members of the header might be nil.
+;;         The meaning of metaobj1, metaobj2, and metaobj3 depend on the job.
+;;         Typically these are directories where the files to be compared are
+;;         found.
 ;;        Also, keep in mind that the function ediff-prepare-meta-buffer
 ;;        (which see) prepends the session group buffer to the descriptor, so
 ;;        the descriptor becomes 7-long.
 ;;        to any of Ediff major entries (such as ediff-files, epatch, etc.).
 ;;        See how this is done in ediff-filegroup-action.
 ;;
-;;        Session descriptions are of the form (obj1 obj2 obj3), which
-;;        describe objects relevant to the session.  Usually they are names of
-;;        files, but sometimes they may be other things.  For instance, obj3
-;;        is nil for jobs that involve only two files.  For patch jobs, obj2
-;;        and obj3 are markers that specify the patch corresponding to the
-;;        file (whose name is obj1).
+;;        Session descriptions are of the form
+;;            (nil nil (obj1 . nil) (obj2 . nil) (obj3 . nil))
+;;         which describe the objects relevant to the session.
+;;         Use ediff-make-new-meta-list-element to create these things.
+;;         Usually obj1/2/3 are names of files, but they may also be other
+;;         things for some jobs.  For instance, obj3 is nil for jobs that
+;;         involve only two files.  For patch jobs, obj2 and obj3 are markers
+;;                that specify the patch corresponding to the file
+;;         (whose name is obj1).
+;;         The nil's are placeholders, which are used internally by ediff.
 ;;     4. Write a function that makes a call to ediff-prepare-meta-buffer
-;;        passing all this info. 
+;;        passing all this info.
 ;;        You may be able to use ediff-directories-internal as a template.
 ;;     5. If you intend to add several related pieces of functionality,
 ;;        you may want to keep the function in 4 as an internal version
@@ -76,7 +89,7 @@
 ;;        with different parameters.
 ;;        See how ediff-directories, ediff-merge-directories, and
 ;;        ediff-merge-directories-with-ancestor all use
-;;        ediff-directories-internal. 
+;;        ediff-directories-internal.
 ;;
 ;; A useful addition here could be session groups selected by patterns
 ;; (which are different in each directory).  For instance, one may want to
 ;; which may be in the same or different directories.  Or, one may want to
 ;; compare all files of the form {something} to files of the form {something}~.
 ;;
-;; Implementing this requires writing an collating function, which should pair
+;; Implementing this requires writing a collating function, which should pair
 ;; up appropriate files.  It will also require a generalization of the
 ;; functions that do the layout of the meta- and differences buffers and of
 ;; ediff-filegroup-action.
 
 ;;; Code:
 
-(provide 'ediff-mult)
 
 (defgroup ediff-mult nil
-  "Multi-file and multi-buffer processing in Ediff"
+  "Multi-file and multi-buffer processing in Ediff."
   :prefix "ediff-"
   :group 'ediff)
 
 ;; end pacifier
 
 (require 'ediff-init)
-(require 'ediff-util)
 
 ;; meta-buffer
 (ediff-defvar-local ediff-meta-buffer nil "")
@@ -155,9 +166,18 @@ directories.")
 ;; buffer used to collect custom diffs from individual sessions in the group
 (ediff-defvar-local ediff-meta-diff-buffer nil "")
 
-;; history var to use for filtering groups
+;; t means recurse into subdirs when deciding which files have same contents
+(ediff-defvar-local ediff-recurse-to-subdirectories nil "")
+
+;; history var to use for filtering groups of files
 (defvar ediff-filtering-regexp-history nil "")
 
+(defcustom ediff-default-filtering-regexp nil
+  "The default regular expression used as a filename filter in multifile comparisons.
+Should be a sexp.  For instance (car ediff-filtering-regexp-history) or nil."
+  :type 'sexp
+  :group 'ediff-mult)
+
 ;; This has the form ((meta-buf regexp dir1 dir2 dir3 merge-auto-store-dir)
 ;; (ctl-buf session-status (file1 . eq-status) (file2 . eq-status) (file3
 ;; . eq-status)) (ctl-buf session-status (file1 . eq-status) (file2
@@ -182,8 +202,14 @@ directories.")
 (defcustom ediff-meta-truncate-filenames t
   "*If non-nil, truncate long file names in the session group buffers.
 This can be toggled with `ediff-toggle-filename-truncation'."
+  :type 'boolean
+  :group 'ediff-mult)
+
+(defcustom ediff-meta-mode-hook nil
+  "*Hooks run just after setting up meta mode."
   :type 'hook
   :group 'ediff-mult)
+
 (defcustom ediff-registry-setup-hook nil
   "*Hooks run just after the registry control panel is set up."
   :type 'hook
@@ -191,11 +217,11 @@ This can be toggled with `ediff-toggle-filename-truncation'."
 
 (defcustom ediff-before-session-group-setup-hooks nil
   "*Hooks to run before Ediff arranges the window for group-level operations.
-It is used by commands such as ediff-directories.
+It is used by commands such as `ediff-directories'.
 This hook can be used to save the previous window config, which can be restored
-on ediff-quit, ediff-suspend, or ediff-quit-session-group-hook."
+on `ediff-quit', `ediff-suspend', or `ediff-quit-session-group-hook'."
   :type 'hook
-  :group 'ediff-hook) 
+  :group 'ediff-hook)
 (defcustom ediff-after-session-group-setup-hook nil
   "*Hooks run just after a meta-buffer controlling a session group, such as
 ediff-directories, is run."
@@ -214,7 +240,7 @@ ediff-directories, is run."
   :type 'hook
   :group 'ediff-mult)
 (defcustom ediff-meta-buffer-keymap-setup-hook nil
-  "*Hooks run just after setting up the ediff-meta-buffer-map.
+  "*Hooks run just after setting up the `ediff-meta-buffer-map'.
 This keymap controls key bindings in the meta buffer and is a local variable.
 This means that you can set different bindings for different kinds of meta
 buffers."
@@ -278,6 +304,8 @@ buffers."
   (nth 3 elt))
 (defsubst ediff-get-session-objC (elt)
   (nth 4 elt))
+;; Take the "name" component of the object into acount. ObjA/C/B is of the form
+;; (name . equality-indicator)
 (defsubst ediff-get-session-objA-name (elt)
   (car (nth 2 elt)))
 (defsubst ediff-get-session-objB-name (elt)
@@ -293,17 +321,27 @@ buffers."
 ;; Create a new element for the meta list out of obj1/2/3, which usually are
 ;; files
 ;;
-;; The first nil in such an is later replaced with the session buffer.  The
-;; second nil is reserved for session status.
+;; The first nil in such an element is later replaced with the session buffer.
+;; The second nil is reserved for session status.
 ;;
 ;; Also, session objects A/B/C are turned into lists of the form (obj nil).
-;; This nill is a placeholder for eq-indicator. It is either nil or =.
+;; This nil is a placeholder for eq-indicator. It is either nil or =.
 ;; If it is discovered that this file is = to some other
 ;; file in the same session, eq-indicator is changed to `='.
 ;; Curently, the eq-indicator is used only for 2 and 3-file jobs.
 (defun ediff-make-new-meta-list-element (obj1 obj2 obj3)
   (list nil nil (list obj1 nil) (list obj2 nil) (list obj3 nil)))
 
+;; Constructs a meta list header.
+;; OBJA, OBJB, OBJC are usually directories involved, but can be different for
+;; different jobs. For instance, multifile patch has only OBJA, which is the
+;; patch buffer.
+(defun ediff-make-new-meta-list-header (regexp
+                                       objA objB objC
+                                       merge-auto-store-dir
+                                       comparison-func)
+  (list regexp objA objB objC merge-auto-store-dir comparison-func))
+
 ;; The activity marker is either or + (active session, i.e., ediff is currently
 ;; run in it), or - (finished session, i.e., we've ran ediff in it and then
 ;; exited).  Return nil, if session is neither active nor finished
@@ -316,14 +354,14 @@ buffers."
 ;; checks if the session is a meta session
 (defun ediff-meta-session-p (session-info)
   (and (stringp (ediff-get-session-objA-name session-info))
-       (file-directory-p (ediff-get-session-objA-name session-info)) 
+       (file-directory-p (ediff-get-session-objA-name session-info))
        (stringp (ediff-get-session-objB-name session-info))
        (file-directory-p (ediff-get-session-objB-name session-info))
        (if (stringp (ediff-get-session-objC-name session-info))
           (file-directory-p (ediff-get-session-objC-name session-info)) t)))
 
 ;; set up the keymap in the meta buffer
-(defun ediff-setup-meta-map()
+(defun ediff-setup-meta-map ()
   (setq ediff-meta-buffer-map (make-sparse-keymap))
   (suppress-keymap ediff-meta-buffer-map)
   (define-key ediff-meta-buffer-map "q" 'ediff-quit-meta-buffer)
@@ -377,7 +415,9 @@ Commands:
 \\{ediff-meta-buffer-map}"
   (kill-all-local-variables)
   (setq major-mode 'ediff-meta-mode)
-  (setq mode-name "MetaEdiff"))
+  (setq mode-name "MetaEdiff")
+  ;; don't use run-mode-hooks here!
+  (run-hooks 'ediff-meta-mode-hook))
 
 
 ;; the keymap for the buffer showing directory differences
@@ -444,7 +484,7 @@ Moves in circular fashion.  With numeric prefix arg, skip this many items."
 ;;;    (while (ediff-get-session-status
 ;;;        (ediff-get-meta-info (current-buffer) pos 'noerror))
 ;;;      (setq pos (ediff-previous-meta-overlay-start pos)))
-    
+
     (if pos (goto-char pos))
     (if (eq ediff-metajob-name 'ediff-registry)
        (if (and (ediff-get-meta-info (current-buffer) pos 'noerror)
@@ -481,22 +521,36 @@ behavior."
 ;; DIR1, DIR2, DIR3 are directories.  DIR3 can be nil.
 ;; OUTPUT-DIR is a directory for auto-storing the results of merge jobs.
 ;;           Can be nil.
-;; REGEXP is a regexp used to filter out files in the directories.
+;; REGEXP is nil or a filter regexp; only file names that match the regexp
+;; are considered.
 ;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not
 ;; included in the intersection.  However, a regular file that is a dir in dir3
 ;; is included, since dir3 files are supposed to be ancestors for merging.
-;; Returns a list of the form:
-;;     (DIFF-LIST META-HEADER (f1 f2 f3) (f1 f2 f3) ...)
-;; dir3, f3 can be nil if intersecting only 2 directories.
 ;; If COMPARISON-FUNC is given, use it.  Otherwise, use string=
+;;
+;; Returns a list of the form:
+;;      (COMMON-PART DIFF-LIST)
+;; COMMON-PART is car and DIFF-LIST is cdr.
+;;
+;; COMMON-PART is of the form:
+;;     (META-HEADER (f1 f2 f3) (f1 f2 f3) ...)
+;; f3 can be nil if intersecting only 2 directories.
+;; Each triple (f1 f2 f3) represents the files to be compared in the
+;; corresponding ediff subsession.
+;;
 ;; DIFF-LIST is of the form:
 ;;     (META-HEADER (file . num) (file . num)...)
 ;; where num encodes the set of dirs where the file is found:
 ;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc.
-;; META-HEADER is of the form
-;;       It contains the meta info about this ediff operation
+;; META-HEADER:
+;;       Contains the meta info about this ediff operation
 ;;       (regexp dir1 dir2 dir3 merge-auto-store-dir comparison-func)
 ;;       Later the meta-buffer is prepended to this list.
+;;
+;; Some operations might use a different meta header. For instance,
+;; ediff-multifile-patch doesn't have dir2 and dir3, and regexp,
+;; comparison-func don't apply.
+;;
 (defun ediff-intersect-directories (jobname
                                    regexp dir1 dir2
                                    &optional
@@ -508,22 +562,28 @@ behavior."
          lis1          (directory-files auxdir1 nil regexp)
          lis1          (delete "."  lis1)
          lis1          (delete ".." lis1)
-         lis1          (mapcar 
+         lis1          (mapcar
                         (lambda (elt)
                           (ediff-add-slash-if-directory auxdir1 elt))
                         lis1)
          auxdir2       (file-name-as-directory dir2)
-         lis2          (mapcar 
+         lis2          (directory-files auxdir2 nil regexp)
+         lis2          (delete "."  lis2)
+         lis2          (delete ".." lis2)
+         lis2          (mapcar
                         (lambda (elt)
                           (ediff-add-slash-if-directory auxdir2 elt))
-                        (directory-files auxdir2 nil regexp)))
+                        lis2))
 
     (if (stringp dir3)
        (setq auxdir3   (file-name-as-directory dir3)
-             lis3      (mapcar 
+             lis3      (directory-files auxdir3 nil regexp)
+             lis3      (delete "."  lis3)
+             lis3      (delete ".." lis3)
+             lis3      (mapcar
                         (lambda (elt)
                           (ediff-add-slash-if-directory auxdir3 elt))
-                        (directory-files auxdir3 nil regexp))))
+                        lis3)))
 
     (if (ediff-nonempty-string-p merge-autostore-dir)
        (setq merge-autostore-dir
@@ -572,21 +632,21 @@ behavior."
            difflist)
     (setq difflist (cons
                    ;; diff metalist header
-                   (list regexp
-                         auxdir1 auxdir2 auxdir3
-                         merge-autostore-dir
-                         comparison-func)
+                   (ediff-make-new-meta-list-header regexp
+                                                    auxdir1 auxdir2 auxdir3
+                                                    merge-autostore-dir
+                                                    comparison-func)
                    difflist))
-    
+
     (setq common-part
-         (cons 
+         (cons
           ;; metalist header
-          (list regexp
-                auxdir1 auxdir2 auxdir3
-                merge-autostore-dir
-                comparison-func)
+          (ediff-make-new-meta-list-header regexp
+                                           auxdir1 auxdir2 auxdir3
+                                           merge-autostore-dir
+                                           comparison-func)
           (mapcar
-           (lambda (elt) 
+           (lambda (elt)
              (ediff-make-new-meta-list-element
               (concat auxdir1 elt)
               (concat auxdir2 elt)
@@ -649,15 +709,17 @@ behavior."
     (setq common (sort (ediff-copy-list common) 'string-lessp))
 
     ;; return result
-    (cons 
+    (cons
      ;; header -- has 6 elements. Meta buffer is prepended later by
-     ;; ediff-prepare-meta-buffer 
-     (list regexp auxdir1 nil nil merge-autostore-dir nil)
+     ;; ediff-prepare-meta-buffer
+     (ediff-make-new-meta-list-header regexp
+                                     auxdir1 nil nil
+                                     merge-autostore-dir nil)
      (mapcar (lambda (elt) (ediff-make-new-meta-list-element
                            (concat auxdir1 elt) nil nil))
             common))
     ))
-      
+
 
 ;; If file groups selected by patterns will ever be implemented, this
 ;; comparison function might become useful.
@@ -694,7 +756,7 @@ behavior."
 (defun ediff-prepare-meta-buffer (action-func meta-list
                                  meta-buffer-name redraw-function
                                  jobname &optional startup-hooks)
-  (let* ((meta-buffer-name 
+  (let* ((meta-buffer-name
          (ediff-unique-buffer-name meta-buffer-name "*"))
         (meta-buffer (get-buffer-create meta-buffer-name)))
     (ediff-with-current-buffer meta-buffer
@@ -709,7 +771,7 @@ behavior."
 
       ;; comes after ediff-meta-action-function is set
       (ediff-setup-meta-map)
-      
+
       (if (eq ediff-metajob-name 'ediff-registry)
          (progn
            (setq ediff-registry-buffer meta-buffer
@@ -723,14 +785,14 @@ behavior."
              ;; add meta-buffer to the list header
              (cons (cons meta-buffer (car meta-list))
                    (cdr meta-list))))
-       
+
       (or (eq meta-buffer ediff-registry-buffer)
          (setq ediff-session-registry
                (cons meta-buffer ediff-session-registry)))
-       
+
       ;; redraw-function uses ediff-meta-list
       (funcall redraw-function ediff-meta-list)
-      
+
       ;; set read-only/non-modified
       (setq buffer-read-only t)
       (set-buffer-modified-p nil)
@@ -749,15 +811,15 @@ behavior."
 
            (or (ediff-one-filegroup-metajob jobname)
                (ediff-draw-dir-diffs ediff-dir-difference-list))
-           (define-key 
+           (define-key
              ediff-meta-buffer-map "h" 'ediff-mark-for-hiding-at-pos)
            (define-key ediff-meta-buffer-map "x" 'ediff-hide-marked-sessions)
-           (define-key 
+           (define-key
              ediff-meta-buffer-map "m" 'ediff-mark-for-operation-at-pos)
            (define-key ediff-meta-buffer-map "u" nil)
            (define-key
              ediff-meta-buffer-map "um" 'ediff-unmark-all-for-operation)
-           (define-key 
+           (define-key
              ediff-meta-buffer-map "uh" 'ediff-unmark-all-for-hiding)
            (cond ((ediff-collect-diffs-metajob jobname)
                   (define-key
@@ -787,7 +849,7 @@ behavior."
 ;; Insert session status at point.  Status is either ?H (marked for hiding), or
 ;; ?I (hidden or invalid), or ?* (meaning marked for an operation; currently,
 ;; such op can only be checking for equality)), or SPC (meaning neither marked
-;; nor invalid) 
+;; nor invalid)
 (defun ediff-insert-session-status-in-meta-buffer (session)
   (insert
    (cond ((ediff-get-session-status session)) ; session has status: ?H, ?I, ?*
@@ -801,7 +863,7 @@ behavior."
         (session-info (ediff-overlay-get overl 'ediff-meta-info))
         (activity-marker (ediff-get-session-activity-marker session-info))
         buffer-read-only)
-    (or new-marker activity-marker (setq new-marker ?\ ))
+    (or new-marker activity-marker (setq new-marker ?\s))
     (goto-char (ediff-overlay-start overl))
     (if (eq (char-after (point)) new-marker)
        () ; if marker shown in buffer is the same as new-marker, do nothing
@@ -816,7 +878,7 @@ behavior."
         (session-info (ediff-overlay-get overl 'ediff-meta-info))
         (status (ediff-get-session-status session-info))
         buffer-read-only)
-    (setq new-status (or new-status status ?\ ))
+    (setq new-status (or new-status status ?\s))
     (goto-char (ediff-overlay-start overl))
     (forward-char 1) ; status is the second char in session record
     (if (eq (char-after (point)) new-status)
@@ -861,14 +923,14 @@ behavior."
        (map-extents 'delete-extent)   ; xemacs
        (mapcar 'delete-overlay (overlays-in 1 1))  ; emacs
        )
-      
+
       (insert (format ediff-meta-buffer-message
                      (ediff-abbrev-jobname ediff-metajob-name)))
 
       (setq regexp (ediff-get-group-regexp meta-list)
            merge-autostore-dir
            (ediff-get-group-merge-autostore-dir meta-list))
-      
+
       (cond ((ediff-collect-diffs-metajob)
             (insert
              "     P:\tcollect custom diffs of all marked sessions\n"))
@@ -899,7 +961,7 @@ behavior."
     ----------------------------------------------
 
 ")
-      
+
       ;; discard info on directories and regexp
       (setq meta-list (cdr meta-list)
            tmp-list meta-list)
@@ -912,7 +974,7 @@ behavior."
       (if empty
          (insert
           "     ******   ******   This session group has no members\n"))
-      
+
       ;; now organize file names like this:
       ;;     use-mark sizeA dateA  sizeB dateB  filename
       ;; make sure directories are displayed with a trailing slash.
@@ -1174,7 +1236,7 @@ Useful commands:
        (if (stringp dir3)
            (if (= (mod membership-code ediff-membership-code3) 0) ; dir3
                (let ((beg (point)))
-                 (insert (format " %-25s" 
+                 (insert (format " %-25s"
                                  (ediff-truncate-string-left
                                   (ediff-abbreviate-file-name
                                    (if (file-directory-p (concat dir3 file))
@@ -1250,7 +1312,7 @@ Useful commands:
         (if otherfile
             (or (file-exists-p otherfile)
                 (if (y-or-n-p
-                     (format "Copy %s to %s ? " file-abs otherfile))
+                     (format "Copy %s to %s? " file-abs otherfile))
                     (let* ((file-diff-record (assoc file-tail dir-diff-list))
                            (new-mem-code
                             (* (cdr file-diff-record) file-mem-code)))
@@ -1288,7 +1350,7 @@ Useful commands:
       (ediff-show-meta-buffer
        ediff-parent-meta-buffer ediff-meta-session-number)
     (error "This session group has no parent")))
-  
+
 
 ;; argument is ignored
 (defun ediff-redraw-registry-buffer (&optional ignore)
@@ -1334,7 +1396,7 @@ Useful commands:
       (while registry-list
        (setq elt (car registry-list)
              registry-list (cdr registry-list))
-       
+
        (if (ediff-buffer-live-p elt)
            (if (ediff-with-current-buffer elt
                  (setq job-name ediff-metajob-name
@@ -1409,6 +1471,7 @@ Useful commands:
       (ediff-overlay-put overl 'highlight t))
     (ediff-overlay-put overl 'ediff-meta-info prop)
     (ediff-overlay-put overl 'invisible hidden)
+    (ediff-overlay-put overl 'follow-link t)
     (if (numberp session-number)
        (ediff-overlay-put overl 'ediff-meta-session-number session-number))))
 
@@ -1440,7 +1503,7 @@ Useful commands:
 ;;;      (error "Can't hide active session, %s" (buffer-name session-buf)))
          (t (ediff-set-session-status info ?H))))
   unmark)
-  
+
 
 (defun ediff-mark-for-operation-at-pos (unmark)
   "Mark session for a group operation.  With prefix arg, unmark."
@@ -1523,11 +1586,11 @@ Useful commands:
               (funcall operation elt sessionNum)))
            ;; The following goes into a session represented by a subdirectory
            ;; and applies operation to marked sessions there
-           ((and  (ediff-meta-session-p elt) 
-                  (ediff-buffer-live-p 
+           ((and  (ediff-meta-session-p elt)
+                  (ediff-buffer-live-p
                    (setq session-buf (ediff-get-session-buffer elt))))
             (setq numMarked
-                  (+ numMarked 
+                  (+ numMarked
                      (ediff-with-current-buffer session-buf
                        ;; pass meta-diff along
                        (setq ediff-meta-diff-buffer diff-buffer)
@@ -1560,10 +1623,10 @@ Useful commands:
           (save-excursion
             (set-buffer meta-diff-buff)
             (goto-char (point-max))
-            (insert-buffer custom-diff-buf)
+            (insert-buffer-substring custom-diff-buf)
             (insert "\n")))
          ;; if ediff session is not live, run diff directly on the files
-         ((memq metajob '(ediff-directories 
+         ((memq metajob '(ediff-directories
                           ediff-merge-directories
                           ediff-merge-directories-with-ancestor))
           ;; get diffs by calling shell command on ediff-custom-diff-program
@@ -1579,7 +1642,7 @@ Useful commands:
           (save-excursion
             (set-buffer meta-diff-buff)
             (goto-char (point-max))
-            (insert-buffer tmp-buf)
+            (insert-buffer-substring tmp-buf)
             (insert "\n")))
          (t
           (ediff-kill-buffer-carefully meta-diff-buff)
@@ -1627,12 +1690,13 @@ all marked sessions must be active."
               (ediff-get-session-objC-name info)))
            (set-buffer (get-buffer-create ediff-tmp-buffer))
            (erase-buffer)
-           (insert-buffer patchbuffer)
+           (insert-buffer-substring patchbuffer)
+           (goto-char (point-min))
            (display-buffer ediff-tmp-buffer 'not-this-window)
            ))
       (error "The patch buffer wasn't found"))))
 
-             
+
 ;; This function executes in meta buffer.  It knows where event happened.
 (defun ediff-filegroup-action ()
   "Execute appropriate action for a selected session."
@@ -1643,6 +1707,7 @@ all marked sessions must be active."
         (info (ediff-get-meta-info meta-buf pos))
         (session-buf (ediff-get-session-buffer info))
         (session-number (ediff-get-session-number-at-pos pos meta-buf))
+        (default-regexp (eval ediff-default-filtering-regexp))
         merge-autostore-dir file1 file2 file3 regexp)
 
     (setq file1 (ediff-get-session-objA-name info)
@@ -1671,14 +1736,22 @@ all marked sessions must be active."
             ;; do ediff/ediff-merge on subdirectories
             (if (ediff-buffer-live-p session-buf)
                 (ediff-show-meta-buffer session-buf)
-              (setq regexp (read-string "Filter through regular expression: " 
-                                        nil 'ediff-filtering-regexp-history))
+              (setq regexp
+                    (read-string
+                     (if (stringp default-regexp)
+                         (format
+                          "Filter through regular expression (default %s): "
+                          default-regexp)
+                       "Filter through regular expression: ")
+                     nil
+                     'ediff-filtering-regexp-history
+                     (eval ediff-default-filtering-regexp)))
               (ediff-directories-internal
                file1 file2 file3 regexp
                ediff-session-action-function
-               ediff-metajob-name 
+               ediff-metajob-name
                ;; make it update (car info) after startup
-               `(list (lambda () 
+               `(list (lambda ()
                         ;; child session group should know its parent
                         (setq ediff-parent-meta-buffer
                               (quote ,ediff-meta-buffer)
@@ -1693,13 +1766,13 @@ all marked sessions must be active."
                  (file-directory-p file1))
             (if (ediff-buffer-live-p session-buf)
                 (ediff-show-meta-buffer session-buf)
-              (setq regexp (read-string "Filter through regular expression: " 
+              (setq regexp (read-string "Filter through regular expression: "
                                         nil 'ediff-filtering-regexp-history))
               (ediff-directory-revisions-internal
                file1 regexp
                ediff-session-action-function ediff-metajob-name
                ;; make it update (car info) after startup
-               `(list (lambda () 
+               `(list (lambda ()
                         ;; child session group should know its parent and
                         ;; its number
                         (setq ediff-parent-meta-buffer
@@ -1723,8 +1796,8 @@ all marked sessions must be active."
                  "This session has no ancestor.  Merge without the ancestor? ")
                 (ediff-merge-files
                  file1 file2
-                 ;; provide startup hooks 
-                 `(list (lambda () 
+                 ;; provide startup hooks
+                 `(list (lambda ()
                             (add-hook
                              'ediff-after-quit-hook-internal
                              (lambda ()
@@ -1752,8 +1825,8 @@ all marked sessions must be active."
            ((ediff-one-filegroup-metajob)      ; needs 1 file arg
             (funcall ediff-session-action-function
                      file1
-                     ;; provide startup hooks 
-                     `(list (lambda () 
+                     ;; provide startup hooks
+                     `(list (lambda ()
                               (add-hook
                                'ediff-after-quit-hook-internal
                                (lambda ()
@@ -1781,8 +1854,8 @@ all marked sessions must be active."
            ((not (ediff-metajob3))      ; need 2 file args
             (funcall ediff-session-action-function
                      file1 file2
-                     ;; provide startup hooks 
-                     `(list (lambda () 
+                     ;; provide startup hooks
+                     `(list (lambda ()
                               (add-hook
                                'ediff-after-quit-hook-internal
                                (lambda ()
@@ -1810,8 +1883,8 @@ all marked sessions must be active."
            ((ediff-metajob3)      ; need 3 file args
             (funcall ediff-session-action-function
                      file1 file2 file3
-                     ;; arrange startup hooks 
-                     `(list (lambda () 
+                     ;; arrange startup hooks
+                     `(list (lambda ()
                               (add-hook
                                'ediff-after-quit-hook-internal
                                (lambda ()
@@ -1917,7 +1990,7 @@ all marked sessions must be active."
                 (set-window-buffer (selected-window) meta-buf)))
        ))
     (if (and (ediff-window-display-p)
-            (window-live-p 
+            (window-live-p
              (setq wind (ediff-get-visible-buffer-window meta-buf))))
        (progn
          (setq frame (window-frame wind))
@@ -1979,7 +2052,7 @@ all marked sessions must be active."
        ))
     (if (ediff-window-display-p)
        (progn
-         (setq frame 
+         (setq frame
                (window-frame
                 (ediff-get-visible-buffer-window ediff-registry-buffer)))
          (raise-frame frame)
@@ -2019,7 +2092,7 @@ all marked sessions must be active."
   (ediff-with-current-buffer (current-buffer)
     (if (ediff-buffer-live-p ediff-registry-buffer)
        (ediff-redraw-registry-buffer)
-      (ediff-prepare-meta-buffer 
+      (ediff-prepare-meta-buffer
        'ediff-registry-action
        ediff-session-registry
        "*Ediff Registry"
@@ -2027,7 +2100,7 @@ all marked sessions must be active."
        'ediff-registry))
     ))
 
-;; If meta-buf exists, it is redrawn along with parent. 
+;; If meta-buf exists, it is redrawn along with parent.
 ;; Otherwise, nothing happens.
 (defun ediff-cleanup-meta-buffer (meta-buffer)
   (if (ediff-buffer-live-p meta-buffer)
@@ -2095,7 +2168,7 @@ If this is a session registry buffer then just bury it."
     (if (ediff-buffer-live-p ediff-dir-diffs-buffer)
        (kill-buffer ediff-dir-diffs-buffer)))
   (kill-buffer buf))
-    
+
 
 ;; Obtain information on a meta record where the user clicked or typed
 ;; BUF is the buffer where this happened and POINT is the position
@@ -2222,7 +2295,7 @@ If this is a session registry buffer then just bury it."
     (or (ediff-buffer-live-p session-buf) ; either an active patch session
        (null session-buf)                ; or it is a virgin session
        (error
-        "Patch has been already applied to this file--cannot be repeated!"))
+        "Patch has already been applied to this file -- can't repeat!"))
 
     (ediff-with-current-buffer meta-patchbuf
       (save-restriction
@@ -2258,8 +2331,8 @@ If this is a session registry buffer then just bury it."
   "Run through the session list and mark identical files.
 This is used only for sessions that involve 2 or 3 files at the same time.
 ACTION is an optional argument that can be ?h, ?m, ?=, to mark for hiding, mark
-for operation, or simply indicate which are equal files. If it is nil, then
-last-command-char is used to decide which action to take."
+for operation, or simply indicate which are equal files.  If it is nil, then
+`last-command-char' is used to decide which action to take."
   (interactive)
   (if (null action)
       (setq action last-command-char))
@@ -2294,6 +2367,7 @@ last-command-char is used to decide which action to take."
                ))
       (setq list (cdr list)))
     (message "Comparing files ... Done"))
+  (setq ediff-recurse-to-subdirectories nil)
   (ediff-update-meta-buffer (current-buffer) 'must-redraw))
 
 ;; mark files 1 and 2 as equal, if they are.
@@ -2301,15 +2375,16 @@ last-command-char is used to decide which action to take."
 (defun ediff-mark-if-equal (fileinfo1 fileinfo2)
   (let ((f1 (car fileinfo1))
        (f2 (car fileinfo2)))
-    (cond ((file-directory-p f1) nil)
-         ((file-directory-p f2) nil)
-         ((ediff-same-file-contents f1 f2)
-          (ediff-set-file-eqstatus fileinfo1 t)
-          (ediff-set-file-eqstatus fileinfo2 t)
-          t))
+    (if (and (stringp f1) (stringp f2) (ediff-same-contents f1 f2))
+       (progn
+         (ediff-set-file-eqstatus fileinfo1 t)
+         (ediff-set-file-eqstatus fileinfo2 t)
+         ))
     ))
 
 
+(provide 'ediff-mult)
+
 
 ;;; Local Variables:
 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
@@ -2317,4 +2392,5 @@ last-command-char is used to decide which action to take."
 ;;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
 ;;; End:
 
+;;; arch-tag: c8a76898-f96f-4d9c-be9d-129134017188
 ;;; ediff-mult.el ends here