(dired-recursive-deletes, dired-recursive-copies): Change default to
[bpt/emacs.git] / lisp / dired.el
index 474b4f3..ba488fc 100644 (file)
@@ -1,7 +1,7 @@
 ;;; dired.el --- directory-browsing commands
 
 ;; Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995, 1996, 1997, 2000,
-;;   2001, 2003, 2004  Free Software Foundation, Inc.
+;;   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
 ;; Maintainer: FSF
@@ -21,8 +21,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:
 
 
 ;;;###autoload
 (defcustom dired-listing-switches "-al"
-  "*Switches passed to `ls' for dired.  MUST contain the `l' option.
+  "*Switches passed to `ls' for Dired.  MUST contain the `l' option.
 May contain all other options that don't contradict `-l';
 may contain even `F', `b', `i' and `s'.  See also the variable
 `dired-ls-F-marks-symlinks' concerning the `F' switch.
 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
 some of the `ls' switches are not supported; see the doc string of
-`insert-directory' on ls-lisp.el for more details."
+`insert-directory' in `ls-lisp.el' for more details."
   :type 'string
   :group 'dired)
 
@@ -88,7 +88,7 @@ If nil, `dired-listing-switches' is used.")
 
 ;;;###autoload
 (defcustom dired-ls-F-marks-symlinks nil
-  "*Informs dired about how `ls -lF' marks symbolic links.
+  "*Informs Dired about how `ls -lF' marks symbolic links.
 Set this to t if `ls' (or whatever program is specified by
 `insert-directory-program') with `-lF' marks the symbolic link
 itself with a trailing @ (usually the case under Ultrix).
@@ -153,7 +153,7 @@ If a character, new links are unconditionally marked with that character."
 
 ;;;###autoload
 (defcustom dired-dwim-target nil
-  "*If non-nil, dired tries to guess a default target directory.
+  "*If non-nil, Dired tries to guess a default target directory.
 This means: if there is a dired buffer displayed in the next window,
 use its current subdir, instead of the current subdir of this dired buffer.
 
@@ -176,13 +176,13 @@ The target is used in the prompt for file copy, rename etc."
 ;;; Hook variables
 
 (defcustom dired-load-hook nil
-  "Run after loading dired.
+  "Run after loading Dired.
 You can customize key bindings or load extensions with this."
   :group 'dired
   :type 'hook)
 
 (defcustom dired-mode-hook nil
-  "Run at the very end of dired-mode."
+  "Run at the very end of `dired-mode'."
   :group 'dired
   :type 'hook)
 
@@ -200,6 +200,19 @@ with the buffer narrowed to the listing."
 ;; Note this can't simply be run inside function `dired-ls' as the hook
 ;; functions probably depend on the dired-subdir-alist to be OK.
 
+(defcustom dired-dnd-protocol-alist
+  '(("^file:///" . dired-dnd-handle-local-file)
+    ("^file://"  . dired-dnd-handle-file)
+    ("^file:"    . dired-dnd-handle-local-file))
+  "The functions to call when a drop in `dired-mode' is made.
+See `dnd-protocol-alist' for more information.  When nil, behave
+as in other buffers.  Changing this option is effective only for
+new dired buffers."
+  :type '(choice (repeat (cons (regexp) (function)))
+                (const :tag "Behave as in other buffers" nil))
+  :version "22.1"
+  :group 'dired)
+
 ;; Internal variables
 
 (defvar dired-marker-char ?*           ; the answer is 42
@@ -212,13 +225,12 @@ with the buffer narrowed to the listing."
   ;; concentric sets or an order for the marked files.
   ;; The code depends on dynamic scoping on the marker char.
   "In Dired, the current mark character.
-This is what the `do' commands look for and what the `mark' commands store.")
+This is what the do-commands look for, and what the mark-commands store.")
 
 (defvar dired-del-marker ?D
   "Character used to flag files for deletion.")
 
-(defvar dired-shrink-to-fit
-  t
+(defvar dired-shrink-to-fit t
 ;; I see no reason ever to make this nil -- rms.
 ;;  (> baud-rate search-slow-speed)
   "Non-nil means Dired shrinks the display buffer to fit the marked files.")
@@ -229,7 +241,7 @@ This is what the `do' commands look for and what the `mark' commands store.")
 
 ;;;###autoload
 (defvar dired-directory nil
-  "The directory name or wildcard spec that this Dired directory lists.
+  "The directory name or wildcard spec that this dired directory lists.
 Local to each dired buffer.  May be a list, in which case the car is the
 directory name and the cdr is the list of files to mention.
 The directory name must be absolute, but need not be fully expanded.")
@@ -275,6 +287,9 @@ In simple cases, this list contains one element.")
 This is an alist of the form (SUBDIR . SWITCHES).")
 (make-variable-buffer-local 'dired-switches-alist)
 
+(defvaralias 'dired-move-to-filename-regexp
+  'directory-listing-before-filename-regexp)
+
 (defvar dired-subdir-regexp "^. \\([^\n\r]+\\)\\(:\\)[\n\r]"
   "Regexp matching a maybe hidden subdirectory line in `ls -lR' output.
 Subexpression 1 is the subdirectory proper, no trailing colon.
@@ -283,7 +298,7 @@ of the line (\\n or \\r).
 Subexpression 2 must end right before the \\n or \\r.")
 
 (defgroup dired-faces nil
-  "Faces used by dired."
+  "Faces used by Dired."
   :group 'dired
   :group 'faces)
 
@@ -344,7 +359,7 @@ Subexpression 2 must end right before the \\n or \\r.")
   "Face name used for symbolic links.")
 
 (defface dired-ignored
-  '((t (:inherit font-lock-string-face)))
+  '((t (:inherit shadow)))
   "Face used for files suffixed with `completion-ignored-extensions'."
   :group 'dired-faces
   :version "22.1")
@@ -406,8 +421,27 @@ Subexpression 2 must end right before the \\n or \\r.")
      ;; It is quicker to first find just an extension, then go back to the
      ;; start of that file name.  So we do this complex MATCH-ANCHORED form.
      (list (concat "\\(" (regexp-opt completion-ignored-extensions) "\\|#\\)$")
-          '(".+" (dired-move-to-filename) nil (0 dired-ignored-face)))))
+          '(".+" (dired-move-to-filename) nil (0 dired-ignored-face))))
+   ;;
+   ;; Files suffixed with `completion-ignored-extensions'
+   ;; plus a character put in by -F.
+   '(eval .
+     (list (concat "\\(" (regexp-opt completion-ignored-extensions)
+                  "\\|#\\)[*=|]$")
+          '(".+" (progn
+                   (end-of-line)
+                   ;; If the last character is not part of the filename,
+                   ;; move back to the start of the filename
+                   ;; so it can be fontified.
+                   ;; Otherwise, leave point at the end of the line;
+                   ;; that way, nothing is fontified.
+                   (unless (get-text-property (1- (point)) 'mouse-face)
+                     (dired-move-to-filename)))
+            nil (0 dired-ignored-face))))
+)
   "Additional expressions to highlight in Dired mode.")
+
+(defvar dnd-protocol-alist)
 \f
 ;;; Macros must be defined before they are used, for the byte compiler.
 
@@ -438,7 +472,8 @@ Return value is the number of files marked, or nil if none were marked."
                             "flagged" "marked"))))
     (and (> count 0) count)))
 
-(defmacro dired-map-over-marks (body arg &optional show-progress)
+(defmacro dired-map-over-marks (body arg &optional show-progress
+                                    distinguish-one-marked)
   "Eval BODY with point on each marked line.  Return a list of BODY's results.
 If no marked file could be found, execute BODY on the current line.
   If ARG is an integer, use the next ARG (or previous -ARG, if ARG<0)
@@ -453,7 +488,10 @@ No guarantee is made about the position on the marked line.
 Search starts at the beginning of the buffer, thus the car of the list
   corresponds to the line nearest to the buffer's bottom.  This
   is also true for (positive and negative) integer values of ARG.
-BODY should not be too long as it is expanded four times."
+BODY should not be too long as it is expanded four times.
+
+If DISTINGUISH-ONE-MARKED is non-nil, then if we find just one marked file,
+return (t FILENAME) instead of (FILENAME)."
   ;;
   ;;Warning: BODY must not add new lines before point - this may cause an
   ;;endless loop.
@@ -493,13 +531,15 @@ BODY should not be too long as it is expanded four times."
                 (set-marker next-position nil)
                 (setq next-position (and (re-search-forward regexp nil t)
                                          (point-marker)))))
+            (if (and ,distinguish-one-marked (= (length results) 1))
+                (setq results (cons t results)))
             (if found
                 results
               (list ,body)))))
      ;; save-excursion loses, again
      (dired-move-to-filename)))
 
-(defun dired-get-marked-files (&optional localp arg filter)
+(defun dired-get-marked-files (&optional localp arg filter distinguish-one-marked)
   "Return the marked files' names as list of strings.
 The list is in the same order as the buffer, that is, the car is the
   first marked file.
@@ -510,13 +550,21 @@ Optional second argument ARG specifies files near point
   If ARG is otherwise non-nil, use file.  Usually ARG comes from
   the command's prefix arg.
 Optional third argument FILTER, if non-nil, is a function to select
-  some of the files--those for which (funcall FILTER FILENAME) is non-nil."
-  (let ((all-of-them
-        (save-excursion
-          (dired-map-over-marks (dired-get-filename localp) arg)))
-       result)
+  some of the files--those for which (funcall FILTER FILENAME) is non-nil.
+
+If DISTINGUISH-ONE-MARKED is non-nil, then if we find just one marked file,
+return (t FILENAME) instead of (FILENAME).
+Don't use that together with FILTER."
+  (let* ((all-of-them
+         (save-excursion
+           (dired-map-over-marks
+            (dired-get-filename localp)
+            arg nil distinguish-one-marked)))
+        result)
     (if (not filter)
-       (nreverse all-of-them)
+       (if (and distinguish-one-marked (eq (car all-of-them) t))
+           all-of-them
+         (nreverse all-of-them))
       (dolist (file all-of-them)
        (if (funcall filter file)
            (push file result)))
@@ -553,7 +601,7 @@ list of files to make directory entries for.
 You can move around in it with the usual commands.
 You can flag files for deletion with \\[dired-flag-file-deletion] and then
 delete them by typing \\[dired-do-flagged-delete].
-Type \\[describe-mode] after entering dired for more info.
+Type \\[describe-mode] after entering Dired for more info.
 
 If DIRNAME is already in a dired buffer, that buffer is used without refresh."
   ;; Cannot use (interactive "D") because of wildcards.
@@ -743,6 +791,9 @@ wildcards, erases the buffer, and builds the subdir-alist anew
       (run-hooks 'dired-before-readin-hook)
       (if (consp buffer-undo-list)
          (setq buffer-undo-list nil))
+      (make-local-variable 'file-name-coding-system)
+      (setq file-name-coding-system
+           (or coding-system-for-read file-name-coding-system))
       (let (buffer-read-only
            ;; Don't make undo entries for readin.
            (buffer-undo-list t))
@@ -798,16 +849,17 @@ BEG..END is the line where the file info is located."
   ;; line, the alignment if this line w.r.t the rest is messed up because
   ;; the fields of that one line will generally be smaller.
   ;;
-  ;; To work around this problem, we here add spaces to try and re-align the
-  ;; fields as needed.  Since this is purely aesthetic, it is of utmost
-  ;; importance that it doesn't mess up anything like
-  ;; `dired-move-to-filename'.  To this end, we limit ourselves to adding
-  ;; spaces only, and to only add them at places where there was already at
-  ;; least one space.  This way, as long as `dired-move-to-filename-regexp'
-  ;; always matches spaces with "*" or "+", we know we haven't made anything
-  ;; worse.  There is one spot where the exact number of spaces is
-  ;; important, which is just before the actual filename, so we refrain from
-  ;; adding spaces there (and within the filename as well, of course).
+  ;; To work around this problem, we here add spaces to try and
+  ;; re-align the fields as needed.  Since this is purely aesthetic,
+  ;; it is of utmost importance that it doesn't mess up anything like
+  ;; `dired-move-to-filename'.  To this end, we limit ourselves to
+  ;; adding spaces only, and to only add them at places where there
+  ;; was already at least one space.  This way, as long as
+  ;; `directory-listing-before-filename-regexp' always matches spaces
+  ;; with "*" or "+", we know we haven't made anything worse.  There
+  ;; is one spot where the exact number of spaces is important, which
+  ;; is just before the actual filename, so we refrain from adding
+  ;; spaces there (and within the filename as well, of course).
   (save-excursion
     (let (file file-col other other-col)
       ;; Check the there is indeed a file, and that there is anoter adjacent
@@ -866,7 +918,7 @@ BEG..END is the line where the file info is located."
                    (move-to-column curcol)
                    (when (looking-at
                           (concat
-                           (if (eq (char-before) ?\ ) " *" "[^ ]* *")
+                           (if (eq (char-before) ?\s) " *" "[^ ]* *")
                            (if num-align "[0-9][^ ]*")))
                      (- (match-end 0) (match-beginning 0)))))
                 ;; Now, the number of spaces to insert is align-pt-offset
@@ -909,7 +961,7 @@ If HDR is non-nil, insert a header line with the directory name."
        (setq switches (concat "--dired " switches)))
     ;; We used to specify the C locale here, to force English month names;
     ;; but this should not be necessary any more,
-    ;; with the new value of dired-move-to-filename-regexp.
+    ;; with the new value of `directory-listing-before-filename-regexp'.
     (if file-list
        (dolist (f file-list)
          (let ((beg (point)))
@@ -975,7 +1027,7 @@ If HDR is non-nil, insert a header line with the directory name."
 
 (defun dired-revert (&optional arg noconfirm)
   "Reread the dired buffer.
-Must also be called after dired-actual-switches have changed.
+Must also be called after `dired-actual-switches' have changed.
 Should not fail even on completely garbaged buffers.
 Preserves old cursor, marks/flags, hidden-p."
   (widen)                              ; just in case user narrowed
@@ -993,9 +1045,9 @@ Preserves old cursor, marks/flags, hidden-p."
     ;; treat top level dir extra (it may contain wildcards)
     (dired-uncache
      (if (consp dired-directory) (car dired-directory) dired-directory))
-    (dired-readin)
+    ;; Run dired-after-readin-hook just once, below.
     (let ((dired-after-readin-hook nil))
-      ;; don't run that hook for each subdir...
+      (dired-readin)
       (dired-insert-old-subdirs old-subdir-alist))
     (dired-mark-remembered mark-alist) ; mark files that were marked
     ;; ... run the hook for the whole buffer, and only after markers
@@ -1163,9 +1215,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
     (define-key map "f" 'dired-find-file)
     (define-key map "\C-m" 'dired-advertised-find-file)
     (define-key map "g" 'revert-buffer)
-    (define-key map "\M-g" 'dired-goto-file)
     (define-key map "h" 'describe-mode)
     (define-key map "i" 'dired-maybe-insert-subdir)
+    (define-key map "j" 'dired-goto-file)
     (define-key map "k" 'dired-do-kill-lines)
     (define-key map "l" 'dired-do-redisplay)
     (define-key map "m" 'dired-mark)
@@ -1199,6 +1251,19 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
     (define-key map "\177" 'dired-unmark-backward)
     (define-key map [remap undo] 'dired-undo)
     (define-key map [remap advertised-undo] 'dired-undo)
+    ;; thumbnail manipulation (image-dired)
+    (define-key map "\C-td" 'image-dired-display-thumbs)
+    (define-key map "\C-tt" 'image-dired-tag-files)
+    (define-key map "\C-tr" 'image-dired-delete-tag)
+    (define-key map "\C-tj" 'image-dired-jump-thumbnail-buffer)
+    (define-key map "\C-ti" 'image-dired-dired-display-image)
+    (define-key map "\C-tx" 'image-dired-dired-display-external)
+    (define-key map "\C-ta" 'image-dired-display-thumbs-append)
+    (define-key map "\C-t." 'image-dired-display-thumb)
+    (define-key map "\C-tc" 'image-dired-dired-comment-files)
+    (define-key map "\C-tf" 'image-dired-mark-tagged-files)
+    (define-key map "\C-t\C-t" 'image-dired-dired-insert-marked-thumbs)
+    (define-key map "\C-te" 'image-dired-dired-edit-comment-and-tags)
 
     ;; Make menu bar items.
 
@@ -1244,6 +1309,18 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
     (define-key map [menu-bar immediate]
       (cons "Immediate" (make-sparse-keymap "Immediate")))
 
+    (define-key map
+      [menu-bar immediate image-dired-dired-display-external]
+      '(menu-item "Display Image Externally" image-dired-dired-display-external
+                  :help "Display image in external viewer"))
+    (define-key map
+      [menu-bar immediate image-dired-dired-display-image]
+      '(menu-item "Display Image" image-dired-dired-display-image
+                  :help "Display sized image in a separate window"))
+
+    (define-key map [menu-bar immediate dashes-4]
+      '("--"))
+
     (define-key map [menu-bar immediate revert-buffer]
       '(menu-item "Refresh" revert-buffer
                  :help "Update contents of shown directories"))
@@ -1252,7 +1329,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
       '("--"))
 
     (define-key map [menu-bar immediate compare-directories]
-      '(menu-item "Compare directories..." dired-compare-directories
+      '(menu-item "Compare Directories..." dired-compare-directories
                  :help "Mark files with different attributes in two dired buffers"))
     (define-key map [menu-bar immediate backup-diff]
       '(menu-item "Compare with Backup" dired-backup-diff
@@ -1280,6 +1357,14 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
     (define-key map [menu-bar regexp]
       (cons "Regexp" (make-sparse-keymap "Regexp")))
 
+    (define-key map
+      [menu-bar regexp image-dired-mark-tagged-files]
+      '(menu-item "Mark From Image Tag..." image-dired-mark-tagged-files
+                  :help "Mark files whose image tags matches regexp"))
+
+    (define-key map [menu-bar regexp dashes-1]
+      '("--"))
+
     (define-key map [menu-bar regexp downcase]
       '(menu-item "Downcase" dired-downcase
                  ;; When running on plain MS-DOS, there's only one
@@ -1366,6 +1451,25 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
 
     (define-key map [menu-bar operate]
       (cons "Operate" (make-sparse-keymap "Operate")))
+    (define-key map
+      [menu-bar operate image-dired-delete-tag]
+      '(menu-item "Delete Image Tag..." image-dired-delete-tag
+                  :help "Delete image tag from current or marked files"))
+    (define-key map
+      [menu-bar operate image-dired-tag-files]
+      '(menu-item "Add Image Tags..." image-dired-tag-files
+                  :help "Add image tags to current or marked files"))
+    (define-key map
+      [menu-bar operate image-dired-dired-comment-files]
+      '(menu-item "Add Image Comment..." image-dired-dired-comment-files
+                  :help "Add image comment to current or marked files"))
+    (define-key map
+      [menu-bar operate image-dired-display-thumbs]
+      '(menu-item "Display Image-Dired" image-dired-display-thumbs
+                  :help "Display image-dired for current or marked image files"))
+
+    (define-key map [menu-bar operate dashes-3]
+      '("--"))
 
     (define-key map [menu-bar operate query-replace]
       '(menu-item "Query Replace in Files..." dired-do-query-replace-regexp
@@ -1425,6 +1529,8 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
 ;; Dired mode is suitable only for specially formatted data.
 (put 'dired-mode 'mode-class 'special)
 
+;; Autoload cookie needed by desktop.el
+;;;###autoload
 (defun dired-mode (&optional dirname switches)
   "\
 Mode for \"editing\" directory listings.
@@ -1455,12 +1561,12 @@ Type \\[dired-find-file-other-window] to find file or dired directory in Other w
 Type \\[dired-maybe-insert-subdir] to Insert a subdirectory in this buffer.
 Type \\[dired-do-rename] to Rename a file or move the marked files to another directory.
 Type \\[dired-do-copy] to Copy files.
-Type \\[dired-sort-toggle-or-edit] to toggle sorting by name/date or change the `ls' switches.
-Type \\[revert-buffer] to read all currently expanded directories again.
+Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches.
+Type \\[revert-buffer] to read all currently expanded directories aGain.
   This retains all marks and hides subdirs again that were hidden before.
 SPC and DEL can be used to move down and up by lines.
 
-If dired ever gets confused, you can either type \\[revert-buffer] \
+If Dired ever gets confused, you can either type \\[revert-buffer] \
 to read the
 directories again, type \\[dired-do-redisplay] \
 to relist a single or the marked files or a
@@ -1522,19 +1628,15 @@ Keybindings:
        'dired-desktop-buffer-misc-data)
   (setq dired-switches-alist nil)
   (dired-sort-other dired-actual-switches t)
-  (run-mode-hooks 'dired-mode-hook)
   (when (featurep 'dnd)
-    (make-variable-buffer-local 'dnd-protocol-alist)
-    (setq dnd-protocol-alist
-         (append '(("^file:///" . dired-dnd-handle-local-file)
-                   ("^file://"  . dired-dnd-handle-file)
-                   ("^file:"    . dired-dnd-handle-local-file))
-                 dnd-protocol-alist))))
+    (set (make-local-variable 'dnd-protocol-alist)
+        (append dired-dnd-protocol-alist dnd-protocol-alist)))
+  (run-mode-hooks 'dired-mode-hook))
 \f
 ;; Idiosyncratic dired commands that don't deal with marks.
 
 (defun dired-summary ()
-  "Summarize basic Dired commands and show recent Dired errors."
+  "Summarize basic Dired commands and show recent dired errors."
   (interactive)
   (dired-why)
   ;>> this should check the key-bindings and use substitute-command-keys if non-standard
@@ -1549,7 +1651,7 @@ You can use it to recover marks, killed lines or subdirs."
   (let (buffer-read-only)
     (undo))
   (dired-build-subdir-alist)
-  (message "Change in Dired buffer undone.
+  (message "Change in dired buffer undone.
 Actual changes in files cannot be undone by Emacs."))
 
 (defun dired-next-line (arg)
@@ -1613,7 +1715,7 @@ Creates a buffer if necessary."
        file-name
       (if (file-symlink-p file-name)
          (error "File is a symlink to a nonexistent target")
-       (error "File no longer exists; type `g' to update Dired buffer")))))
+       (error "File no longer exists; type `g' to update dired buffer")))))
 
 ;; Force `f' rather than `e' in the mode doc:
 (defalias 'dired-advertised-find-file 'dired-find-file)
@@ -1655,7 +1757,7 @@ Creates a buffer if necessary."
       (find-file-other-window (file-name-sans-versions file t)))))
 
 (defun dired-view-file ()
-  "In Dired, examine a file in view mode, returning to dired when done.
+  "In Dired, examine a file in view mode, returning to Dired when done.
 When file is a directory, show it in this buffer if it is inserted.
 Otherwise, display it in another buffer."
   (interactive)
@@ -1795,47 +1897,6 @@ DIR must be a directory name, not a file name."
 \f
 ;;; Functions for finding the file name in a dired buffer line.
 
-(defvar dired-move-to-filename-regexp
-  (let* ((l "\\([A-Za-z]\\|[^\0-\177]\\)")
-        (l-or-quote "\\([A-Za-z']\\|[^\0-\177]\\)")
-        ;; In some locales, month abbreviations are as short as 2 letters,
-        ;; and they can be followed by ".".
-        ;; In Breton, a month name  can include a quote character.
-        (month (concat l-or-quote l-or-quote "+\\.?"))
-        (s " ")
-        (yyyy "[0-9][0-9][0-9][0-9]")
-        (dd "[ 0-3][0-9]")
-        (HH:MM "[ 0-2][0-9][:.][0-5][0-9]")
-        (seconds "[0-6][0-9]\\([.,][0-9]+\\)?")
-        (zone "[-+][0-2][0-9][0-5][0-9]")
-        (iso-mm-dd "[01][0-9]-[0-3][0-9]")
-        (iso-time (concat HH:MM "\\(:" seconds "\\( ?" zone "\\)?\\)?"))
-        (iso (concat "\\(\\(" yyyy "-\\)?" iso-mm-dd "[ T]" iso-time
-                     "\\|" yyyy "-" iso-mm-dd "\\)"))
-        (western (concat "\\(" month s "+" dd "\\|" dd "\\.?" s month "\\)"
-                         s "+"
-                         "\\(" HH:MM "\\|" yyyy "\\)"))
-        (western-comma (concat month s "+" dd "," s "+" yyyy))
-        ;; Japanese MS-Windows ls-lisp has one-digit months, and
-        ;; omits the Kanji characters after month and day-of-month.
-        (mm "[ 0-1]?[0-9]")
-        (japanese
-         (concat mm l "?" s dd l "?" s "+"
-                 "\\(" HH:MM "\\|" yyyy l "?" "\\)")))
-        ;; The "[0-9]" below requires the previous column to end in a digit.
-        ;; This avoids recognizing `1 may 1997' as a date in the line:
-        ;; -r--r--r--   1 may      1997        1168 Oct 19 16:49 README
-        ;; The "[kKMGTPEZY]?" below supports "ls -alh" output.
-        ;; The ".*" below finds the last match if there are multiple matches.
-        ;; This avoids recognizing `jservice  10  1024' as a date in the line:
-        ;; drwxr-xr-x  3 jservice  10  1024 Jul  2  1997 esg-host
-    (concat ".*[0-9][kKMGTPEZY]?" s
-           "\\(" western "\\|" western-comma "\\|" japanese "\\|" iso "\\)"
-           s "+"))
-  "Regular expression to match up to the file name in a directory listing.
-The default value is designed to recognize dates and times
-regardless of the language.")
-
 (defvar dired-permission-flags-regexp
   "\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)"
   "Regular expression to match the permission flags in `ls -l'.")
@@ -1853,12 +1914,12 @@ Return the position of the beginning of the filename, or nil if none found."
     (cond
      ((and change (< change eol))
       (goto-char change))
-     ((re-search-forward dired-move-to-filename-regexp eol t)
+     ((re-search-forward directory-listing-before-filename-regexp eol t)
       (goto-char (match-end 0)))
      ((re-search-forward dired-permission-flags-regexp eol t)
       ;; Ha!  There *is* a file.  Our regexp-from-hell just failed to find it.
       (if raise-error
-         (error "Unrecognized line!  Check dired-move-to-filename-regexp"))
+         (error "Unrecognized line!  Check directory-listing-before-filename-regexp"))
       (beginning-of-line)
       nil)
      (raise-error
@@ -1911,11 +1972,11 @@ Return the position of the beginning of the filename, or nil if none found."
                       (eq (preceding-char) ?@) ;; did ls really mark the link?
                       (forward-char -1))))
          (goto-char eol) ;; else not a symbolic link
-         ;; ls -lF marks dirs, sockets and executables with exactly one
-         ;; trailing character. (Executable bits on symlinks ain't mean
+         ;; ls -lF marks dirs, sockets, fifos and executables with exactly
+         ;; one trailing character. (Executable bits on symlinks ain't mean
          ;; a thing, even to ls, but we know it's not a symlink.)
          (and used-F
-              (or (memq file-type '(?d ?s))
+              (or (memq file-type '(?d ?s ?p))
                   executable)
               (forward-char -1))))
       (or no-error
@@ -1935,7 +1996,7 @@ Return the position of the beginning of the filename, or nil if none found."
   "Copy names of marked (or next ARG) files into the kill ring.
 The names are separated by a space.
 With a zero prefix arg, use the absolute file name of each marked file.
-With \\[universal-argument], use the file name relative to the Dired buffer's
+With \\[universal-argument], use the file name relative to the dired buffer's
 `default-directory'.  (This still may contain slashes if in a subdirectory.)
 
 If on a subdir headerline, use absolute subdirname instead;
@@ -2142,40 +2203,40 @@ instead of `dired-actual-switches'."
                 (concat "\\`" (match-string 1 default-directory)))))
       (goto-char (point-min))
       (setq dired-subdir-alist nil)
-      (while (and (re-search-forward dired-subdir-regexp nil t)
-                 ;; Avoid taking a file name ending in a colon
-                 ;; as a subdir name.
-                 (not (save-excursion
-                        (goto-char (match-beginning 0))
-                        (beginning-of-line)
-                        (forward-char 2)
-                        (save-match-data (looking-at dired-re-perms)))))
-       (save-excursion
-         (goto-char (match-beginning 1))
-         (setq new-dir-name
-               (buffer-substring-no-properties (point) (match-end 1))
-               new-dir-name
-               (save-match-data
-                 (if (and R-ftp-base-dir-regex
-                          (not (string= new-dir-name default-directory))
-                          (string-match R-ftp-base-dir-regex new-dir-name))
-                     (concat default-directory
-                             (substring new-dir-name (match-end 0)))
-                   (expand-file-name new-dir-name))))
-         (delete-region (point) (match-end 1))
-         (insert new-dir-name))
-       (setq count (1+ count))
-       (dired-alist-add-1 new-dir-name
-                          ;; Place a sub directory boundary between lines.
-                          (save-excursion
-                            (goto-char (match-beginning 0))
-                            (beginning-of-line)
-                            (point-marker))))
+      (while (re-search-forward dired-subdir-regexp nil t)
+       ;; Avoid taking a file name ending in a colon
+       ;; as a subdir name.
+       (unless (save-excursion
+                 (goto-char (match-beginning 0))
+                 (beginning-of-line)
+                 (forward-char 2)
+                 (save-match-data (looking-at dired-re-perms)))
+         (save-excursion
+           (goto-char (match-beginning 1))
+           (setq new-dir-name
+                 (buffer-substring-no-properties (point) (match-end 1))
+                 new-dir-name
+                 (save-match-data
+                   (if (and R-ftp-base-dir-regex
+                            (not (string= new-dir-name default-directory))
+                            (string-match R-ftp-base-dir-regex new-dir-name))
+                       (concat default-directory
+                               (substring new-dir-name (match-end 0)))
+                     (expand-file-name new-dir-name))))
+           (delete-region (point) (match-end 1))
+           (insert new-dir-name))
+         (setq count (1+ count))
+         (dired-alist-add-1 new-dir-name
+                            ;; Place a sub directory boundary between lines.
+                            (save-excursion
+                              (goto-char (match-beginning 0))
+                              (beginning-of-line)
+                              (point-marker)))))
       (if (and (> count 1) (interactive-p))
-         (message "Buffer includes %d directories" count))
-      ;; We don't need to sort it because it is in buffer order per
-      ;; constructionem.  Return new alist:
-      dired-subdir-alist)))
+         (message "Buffer includes %d directories" count)))
+    ;; We don't need to sort it because it is in buffer order per
+    ;; constructionem.  Return new alist:
+    dired-subdir-alist))
 
 (defun dired-alist-add-1 (dir new-marker)
   ;; Add new DIR at NEW-MARKER.  Don't sort.
@@ -2200,7 +2261,7 @@ instead of `dired-actual-switches'."
       (forward-line 1))))
 
 (defun dired-goto-file (file)
-  "Go to file line of FILE in this dired buffer."
+  "Go to line describing file FILE in this dired buffer."
   ;; Return value of point on success, else nil.
   ;; FILE must be an absolute file name.
   ;; Loses if FILE contains control chars like "\007" for which ls
@@ -2297,9 +2358,9 @@ Optional argument means return a file name relative to `default-directory'."
 \f
 ;; Deleting files
 
-(defcustom dired-recursive-deletes nil ; Default only delete empty directories.
+(defcustom dired-recursive-deletes 'top
   "*Decide whether recursive deletes are allowed.
-nil means no recursive deletes.
+A value of nil means no recursive deletes.
 `always' means delete recursively without asking.  This is DANGEROUS!
 `top' means ask for each directory at top level, but delete its subdirectories
 without asking.
@@ -2320,7 +2381,7 @@ Anything else means ask for each directory."
 (defun dired-delete-file (file &optional recursive) "\
 Delete FILE or directory (possibly recursively if optional RECURSIVE is true.)
 RECURSIVE determines what to do with a non-empty directory.  If RECURSIVE is:
-Nil, do not delete.
+nil, do not delete.
 `always', delete recursively without asking.
 `top', ask for each directory at top level.
 Anything else, ask for each sub-directory."
@@ -2334,7 +2395,7 @@ Anything else, ask for each sub-directory."
               (setq files
                     (directory-files file t dired-re-no-dot)) ; Not empty.
               (or (eq recursive 'always)
-                  (yes-or-no-p (format "Recursive delete of %s "
+                  (yes-or-no-p (format "Recursive delete of %s? "
                                        (dired-make-relative file)))))
        (if (eq recursive 'top) (setq recursive 'always)) ; Don't ask again.
        (while files            ; Recursively delete (possibly asking).
@@ -2345,7 +2406,9 @@ Anything else, ask for each sub-directory."
 (defun dired-do-flagged-delete (&optional nomessage)
   "In Dired, delete the files flagged for deletion.
 If NOMESSAGE is non-nil, we don't display any message
-if there are no flagged files."
+if there are no flagged files.
+`dired-recursive-deletes' controls whether 
+deletion of non-empty directories is allowed."
   (interactive)
   (let* ((dired-marker-char dired-del-marker)
         (regexp (dired-marker-regexp))
@@ -2361,7 +2424,9 @@ if there are no flagged files."
          (message "(No deletions requested)")))))
 
 (defun dired-do-delete (&optional arg)
-  "Delete all marked (or next ARG) files."
+  "Delete all marked (or next ARG) files.
+`dired-recursive-deletes' controls whether 
+deletion of non-empty directories is allowed."
   ;; This is more consistent with the file marking feature than
   ;; dired-do-flagged-delete.
   (interactive "P")
@@ -2512,11 +2577,18 @@ if there are no flagged files."
       (set-window-start w2 1)
       )))
 
-(defvar dired-no-confirm nil
-  "A list of symbols for commands dired should not confirm.
+(defcustom dired-no-confirm nil
+  "A list of symbols for commands Dired should not confirm.
 Command symbols are `byte-compile', `chgrp', `chmod', `chown', `compress',
 `copy', `delete', `hardlink', `load', `move', `print', `shell', `symlink',
-`touch' and `uncompress'.")
+`touch' and `uncompress'."
+  :group 'dired
+  :type '(set (const byte-compile) (const chgrp)
+             (const chmod) (const chown) (const compress)
+             (const copy) (const delete) (const hardlink)
+             (const load) (const move) (const print)
+             (const shell) (const symlink) (const touch)
+             (const uncompress)))
 
 (defun dired-mark-pop-up (bufname op-symbol files function &rest args)
   "Return FUNCTION's result on ARGS after showing which files are marked.
@@ -2528,15 +2600,21 @@ FUNCTION should not manipulate files, just read input
  (an argument or confirmation).
 The window is not shown if there is just one file or
  OP-SYMBOL is a member of the list in `dired-no-confirm'.
-FILES is the list of marked files."
+FILES is the list of marked files.  It can also be (t FILENAME)
+in the case of one marked file, to distinguish that from using
+just the current file."
   (or bufname (setq bufname  " *Marked Files*"))
   (if (or (eq dired-no-confirm t)
          (memq op-symbol dired-no-confirm)
+         ;; If FILES defaulted to the current line's file.
          (= (length files) 1))
       (apply function args)
     (with-current-buffer (get-buffer-create bufname)
       (erase-buffer)
-      (dired-format-columns-of-files files)
+      ;; Handle (t FILE) just like (FILE), here.
+      ;; That value is used (only in some cases), to mean
+      ;; just one file that was marked, rather than the current line file.
+      (dired-format-columns-of-files (if (eq (car files) t) (cdr files) files))
       (remove-text-properties (point-min) (point-max)
                              '(mouse-face nil help-echo nil)))
     (save-window-excursion
@@ -2844,7 +2922,7 @@ A prefix argument says to unflag those files instead."
   "Flag all backup files (names ending with `~') for deletion.
 With prefix argument, unflag these files."
   (interactive "P")
-  (let ((dired-marker-char (if unflag-p ?\  dired-del-marker)))
+  (let ((dired-marker-char (if unflag-p ?\s dired-del-marker)))
     (dired-mark-if
      ;; Don't call backup-file-name-p unless the last character looks like
      ;; it might be the end of a backup file name.  This isn't very general,
@@ -2878,7 +2956,7 @@ OLD and NEW are both characters used to mark files."
       (save-excursion
        (goto-char (point-min))
        (while (search-forward string nil t)
-         (if (if (= old ?\ )
+         (if (if (= old ?\s)
                  (save-match-data
                    (dired-get-filename 'no-dir t))
                t)
@@ -2886,7 +2964,7 @@ OLD and NEW are both characters used to mark files."
                                    (match-end 0) old new)))))))
 
 (defun dired-unmark-all-marks ()
-  "Remove all marks from all files in the Dired buffer."
+  "Remove all marks from all files in the dired buffer."
   (interactive)
   (dired-unmark-all-files ?\r))
 
@@ -2914,7 +2992,7 @@ Type SPC or `y' to unmark one file, DEL or `n' to skip to next,
                       (dired-query 'query "Unmark file `%s'? "
                                    file))))
            (progn (subst-char-in-region (1- (point)) (point)
-                                        (preceding-char) ?\ )
+                                        (preceding-char) ?\s)
                   (setq count (1+ count)))))
       (message (if (= count 1) "1 mark removed"
                 "%d marks removed")
@@ -2957,7 +3035,7 @@ Thus, use \\[backward-page] to find the beginning of a group of errors."
                           (apply (function format) log args)
                         log)))
              ((bufferp log)
-              (insert-buffer log))
+              (insert-buffer-substring log))
              ((eq t log)
               (backward-page 1)
               (unless (bolp)
@@ -2968,6 +3046,10 @@ Thus, use \\[backward-page] to find the beginning of a group of errors."
               (insert "\f\n")))))))
 
 (defun dired-log-summary (string failures)
+  "State a summary of a command's failures, in echo area and log buffer.
+STRING is an overall summary of the failures.
+FAILURES is a list of file names that we failed to operate on,
+or nil if file names are not applicable."
   (if (= (length failures) 1)
       (message "%s"
               (with-current-buffer dired-log-buffer
@@ -3001,37 +3083,40 @@ format, use `\\[universal-argument] \\[dired]'.")
 (defvar dired-sort-by-date-regexp
   (concat "^-[^" dired-ls-sorting-switches
          "]*t[^" dired-ls-sorting-switches "]*$")
-  "Regexp recognized by dired to set `by date' mode.")
+  "Regexp recognized by Dired to set `by date' mode.")
 
 (defvar dired-sort-by-name-regexp
   (concat "^-[^t" dired-ls-sorting-switches "]+$")
-  "Regexp recognized by dired to set `by name' mode.")
+  "Regexp recognized by Dired to set `by name' mode.")
 
 (defvar dired-sort-inhibit nil
   "Non-nil means the Dired sort command is disabled.
-The idea is to set this buffer-locally in special Dired buffers.")
+The idea is to set this buffer-locally in special dired buffers.")
 
 (defun dired-sort-set-modeline ()
   ;; Set modeline display according to dired-actual-switches.
   ;; Modeline display of "by name" or "by date" guarantees the user a
   ;; match with the corresponding regexps.  Non-matching switches are
   ;; shown literally.
-  (setq mode-name
-       (let (case-fold-search)
-         (cond ((string-match dired-sort-by-name-regexp dired-actual-switches)
-                "Dired by name")
-               ((string-match dired-sort-by-date-regexp dired-actual-switches)
-                "Dired by date")
-               (t
-                (concat "Dired " dired-actual-switches)))))
-  (force-mode-line-update))
+  (when (eq major-mode 'dired-mode)
+    (setq mode-name
+         (let (case-fold-search)
+           (cond ((string-match
+                   dired-sort-by-name-regexp dired-actual-switches)
+                  "Dired by name")
+                 ((string-match
+                   dired-sort-by-date-regexp dired-actual-switches)
+                  "Dired by date")
+                 (t
+                  (concat "Dired " dired-actual-switches)))))
+    (force-mode-line-update)))
 
 (defun dired-sort-toggle-or-edit (&optional arg)
   "Toggle between sort by date/name and refresh the dired buffer.
 With a prefix argument you can edit the current listing switches instead."
   (interactive "P")
   (when dired-sort-inhibit
-    (error "Cannot sort this Dired buffer"))
+    (error "Cannot sort this dired buffer"))
   (if arg
       (dired-sort-other
        (read-string "ls switches (must contain -l): " dired-actual-switches))
@@ -3074,18 +3159,18 @@ With a prefix argument you can edit the current listing switches instead."
     (concat result (substring string start))))
 
 (defun dired-sort-other (switches &optional no-revert)
-  "Specify new ls SWITCHES for current dired buffer.
+  "Specify new `ls' SWITCHES for current dired buffer.
 Values matching `dired-sort-by-date-regexp' or `dired-sort-by-name-regexp'
 set the minor mode accordingly, others appear literally in the mode line.
 With optional second arg NO-REVERT, don't refresh the listing afterwards."
   (dired-sort-R-check switches)
   (setq dired-actual-switches switches)
-  (if (eq major-mode 'dired-mode) (dired-sort-set-modeline))
+  (dired-sort-set-modeline)
   (or no-revert (revert-buffer)))
 
-(make-variable-buffer-local
- (defvar dired-subdir-alist-pre-R nil
-   "Value of `dired-subdir-alist' before -R switch added."))
+(defvar dired-subdir-alist-pre-R nil
+  "Value of `dired-subdir-alist' before -R switch added.")
+(make-variable-buffer-local 'dired-subdir-alist-pre-R)
 
 (defun dired-sort-R-check (switches)
   "Additional processing of -R in ls option string SWITCHES.
@@ -3121,9 +3206,9 @@ To be called first in body of `dired-sort-other', etc."
 
 ;;;;  Drag and drop support
 
-(defcustom dired-recursive-copies nil
+(defcustom dired-recursive-copies 'top
   "*Decide whether recursive copies are allowed.
-nil means no recursive copies.
+A value of nil means no recursive copies.
 `always' means copy recursively without asking.
 `top' means ask for each directory at top level.
 Anything else means ask for each directory."
@@ -3135,10 +3220,8 @@ Anything else means ask for each directory."
   :group 'dired)
 
 (defun dired-dnd-popup-notice ()
-  (x-popup-dialog
-   t
-   '("Recursive copies not enabled.\nSee variable dired-recursive-copies."
-     ("Ok" . nil))))
+  (message-box
+   "Recursive copies not enabled.\nSee variable dired-recursive-copies."))
 
 
 (defun dired-dnd-do-ask-action (uri)
@@ -3217,7 +3300,7 @@ Ask means pop up a menu for the user to select one of copy, move or link."
        ;; Directory name followed by list of files.
        (cons (desktop-file-name (car dired-directory) desktop-dirname)
              (cdr dired-directory))
-     ;; Directory name, optionally with with shell wildcard.
+     ;; Directory name, optionally with shell wildcard.
      (desktop-file-name dired-directory desktop-dirname))
    ;; Subdirectories in `dired-subdir-alist'.
    (cdr
@@ -3226,13 +3309,12 @@ Ask means pop up a menu for the user to select one of copy, move or link."
          (function (lambda (f) (desktop-file-name (car f) desktop-dirname)))
          dired-subdir-alist)))))
 
-;;;###autoload
 (defun dired-restore-desktop-buffer (desktop-buffer-file-name
                                      desktop-buffer-name
                                      desktop-buffer-misc)
   "Restore a dired buffer specified in a desktop file."
   ;; First element of `desktop-buffer-misc' is the value of `dired-directory'.
-  ;; This value is a directory name, optionally with with shell wildcard or
+  ;; This value is a directory name, optionally with shell wildcard or
   ;; a directory name followed by list of files.
   (let* ((dired-dir (car desktop-buffer-misc))
          (dir (if (consp dired-dir) (car dired-dir) dired-dir)))
@@ -3247,6 +3329,9 @@ Ask means pop up a menu for the user to select one of copy, move or link."
       (when desktop-missing-file-warning (sit-for 1))
       nil)))
 
+(add-to-list 'desktop-buffer-mode-handlers
+            '(dired-mode . dired-restore-desktop-buffer))
+
 \f
 (if (eq system-type 'vax-vms)
     (load "dired-vms"))