(toplevel): Provide `descr-text'.
[bpt/emacs.git] / lisp / files.el
index 8c89bc8..34fdefd 100644 (file)
@@ -1,6 +1,6 @@
 ;;; files.el --- file input and output commands for Emacs
 
-;; Copyright (C) 1985, 86, 87, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
+;; Copyright (C) 1985, 86, 87, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002
 ;;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -203,7 +203,7 @@ If non-nil, this directory is used instead of `temporary-file-directory'
 by programs that create small temporary files.  This is for systems that
 have fast storage with limited space, such as a RAM disk."
   :group 'files
-  :type 'directory)
+  :type '(choice (const nil) directory))
 
 ;; The system null device. (Should reference NULL_DEVICE from C.)
 (defvar null-device "/dev/null" "The system null device.")
@@ -294,21 +294,33 @@ Normally auto-save files are written under other names."
 
 (defcustom auto-save-file-name-transforms
   `(("\\`/[^/]*:\\(.+/\\)*\\(.*\\)"
-     ,(expand-file-name "\\2" temporary-file-directory)))
+     ;; Don't put "\\2" inside expand-file-name, since it will be
+     ;; transformed to "/2" on DOS/Windows.
+     ,(concat temporary-file-directory "\\2") t))
   "*Transforms to apply to buffer file name before making auto-save file name.
-Each transform is a list (REGEXP REPLACEMENT):
+Each transform is a list (REGEXP REPLACEMENT UNIQUIFY):
 REGEXP is a regular expression to match against the file name.
 If it matches, `replace-match' is used to replace the
 matching part with REPLACEMENT.
+If the optional element UNIQUIFY is non-nil, the auto-save file name is
+constructed by taking the directory part of the replaced file-name,
+concatenated with the buffer file name with all directory separators
+changed to `!' to prevent clashes.  This will not work
+correctly if your filesystem truncates the resulting name.
+
 All the transforms in the list are tried, in the order they are listed.
 When one transform applies, its result is final;
 no further transforms are tried.
 
 The default value is set up to put the auto-save file into the
 temporary directory (see the variable `temporary-file-directory') for
-editing a remote file."
+editing a remote file.
+
+On MS-DOS filesystems without long names this variable is always
+ignored."
   :group 'auto-save
-  :type '(repeat (list (string :tag "Regexp") (string :tag "Replacement")))
+  :type '(repeat (list (string :tag "Regexp") (string :tag "Replacement")
+                                          (boolean :tag "Uniquify")))
   :version "21.1")
 
 (defcustom save-abbrevs t
@@ -457,6 +469,25 @@ However, on some systems, the function is redefined with a definition
 that really does change some file names to canonicalize certain
 patterns and to guarantee valid names."
   filename)
+
+(defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
+  "Read directory name, prompting with PROMPT and completing in directory DIR.
+Value is not expanded---you must call `expand-file-name' yourself.
+Default name to DEFAULT-DIRNAME if user enters a null string.
+ (If DEFAULT-DIRNAME is omitted, the current buffer's directory is used,
+  except that if INITIAL is specified, that combined with DIR is used.)
+Fourth arg MUSTMATCH non-nil means require existing directory's name.
+ Non-nil and non-t means also require confirmation after completion.
+Fifth arg INITIAL specifies text to start with.
+DIR defaults to current buffer's directory default."
+  (unless dir
+    (setq dir default-directory))
+  (unless default-dirname
+    (setq default-dirname
+         (if initial (concat dir initial) default-directory)))
+  (read-file-name prompt dir default-dirname mustmatch initial
+                 'file-directory-p))
+
 \f
 (defun pwd ()
   "Show the current default directory."
@@ -505,7 +536,7 @@ Not actually set up until the first time you use it.")
 If your environment includes a `CDPATH' variable, try each one of that
 colon-separated list of directories when resolving a relative directory name."
   (interactive
-   (list (read-file-name "Change default directory: "
+   (list (read-directory-name "Change default directory: "
                         default-directory default-directory
                         (and (member cd-path '(nil ("./")))
                              (null (getenv "CDPATH"))))))
@@ -534,10 +565,54 @@ colon-separated list of directories when resolving a relative directory name."
                       (read-file-name "Load file: "))))
   (load (expand-file-name file) nil nil t))
 
+(defun locate-file (filename path &optional suffixes predicate)
+  "Search for FILENAME through PATH.
+If SUFFIXES is non-nil, it should be a list of suffixes to append to
+file name when searching.  If SUFFIXES is nil, it is equivalent to '(\"\").
+If non-nil, PREDICATE is used instead of `file-readable-p'.
+PREDICATE can also be an integer to pass to the `access' system call,
+in which case file-name handlers are ignored.  This usage is deprecated.
+
+For compatibility, PREDICATE can also be one of the symbols
+`executable', `readable', `writable', or `exists', or a list of
+one or more of those symbols."
+  (if (and predicate (symbolp predicate) (not (functionp predicate)))
+      (setq predicate (list predicate)))
+  (when (and (consp predicate) (not (functionp predicate)))
+    (setq predicate
+         (logior (if (memq 'executable predicate) 1 0)
+                 (if (memq 'writable predicate) 2 0)
+                 (if (memq 'readable predicate) 4 0))))
+  (locate-file-internal filename path suffixes predicate))
+
+(defun locate-file-completion (string path-and-suffixes action)
+  "Do completion for file names passed to `locate-file'.
+PATH-AND-SUFFIXES is a pair of lists (DIRECTORIES . SUFFIXES)."
+  (if (file-name-absolute-p string)
+      (read-file-name-internal string nil action)
+    (let ((names nil)
+         (suffix (concat (regexp-opt (cdr path-and-suffixes) t) "\\'"))
+         (string-dir (file-name-directory string)))
+      (dolist (dir (car path-and-suffixes))
+       (if string-dir (setq dir (expand-file-name string-dir dir)))
+       (when (file-directory-p dir)
+         (dolist (file (file-name-all-completions
+                        (file-name-nondirectory string) dir))
+           (push (if string-dir (concat string-dir file) file) names)
+           (when (string-match suffix file)
+             (setq file (substring file 0 (match-beginning 0)))
+             (push (if string-dir (concat string-dir file) file) names)))))
+      (if action
+         (all-completions string (mapcar 'list names))
+       (try-completion string (mapcar 'list names))))))
+
 (defun load-library (library)
   "Load the library named LIBRARY.
 This is an interface to the function `load'."
-  (interactive "sLoad library: ")
+  (interactive
+   (list (completing-read "Load library: "
+                         'locate-file-completion
+                         (cons load-path load-suffixes))))
   (load library))
 
 (defun file-local-copy (file)
@@ -713,14 +788,38 @@ documentation for additional customization information."
     (pop-to-buffer buffer t norecord)
     (raise-frame (window-frame (selected-window)))))
 
+(defvar find-file-default nil
+  "Used within `find-file-read-args'.")
+
+(defun find-file-read-args (prompt)
+  (list (let ((find-file-default
+              (and buffer-file-name
+                   (abbreviate-file-name buffer-file-name)))
+             (munge-default-fun
+              (lambda ()
+                (setq minibuffer-default find-file-default)
+                ;; Clear out this hook so it does not interfere
+                ;; with any recursive minibuffer usage.
+                (pop minibuffer-setup-hook)))
+             (minibuffer-setup-hook
+              minibuffer-setup-hook))
+         (add-hook 'minibuffer-setup-hook munge-default-fun)
+         (read-file-name prompt nil default-directory))
+       current-prefix-arg))
+
 (defun find-file (filename &optional wildcards)
   "Edit file FILENAME.
 Switch to a buffer visiting file FILENAME,
 creating one if none already exists.
+Interactively, the default if you just type RET is the current directory,
+but the visited file name is available through the minibuffer history:
+type M-n to pull it into the minibuffer.
+
 Interactively, or if WILDCARDS is non-nil in a call from Lisp,
 expand wildcards (if any) and visit multiple files.  Wildcard expansion
 can be suppressed by setting `find-file-wildcards'."
-  (interactive "FFind file: \np")
+  (interactive
+   (find-file-read-args "Find file: "))
   (let ((value (find-file-noselect filename nil nil wildcards)))
     (if (listp value)
        (mapcar 'switch-to-buffer (nreverse value))
@@ -730,9 +829,14 @@ can be suppressed by setting `find-file-wildcards'."
   "Edit file FILENAME, in another window.
 May create a new window, or reuse an existing one.
 See the function `display-buffer'.
+
+Interactively, the default if you just type RET is the current directory,
+but the visited file name is available through the minibuffer history:
+type M-n to pull it into the minibuffer.
+
 Interactively, or if WILDCARDS is non-nil in a call from Lisp,
 expand wildcards (if any) and visit multiple files."
-  (interactive "FFind file in other window: \np")
+  (interactive (find-file-read-args "FFind file in other window: "))
   (let ((value (find-file-noselect filename nil nil wildcards)))
     (if (listp value)
        (progn
@@ -745,9 +849,14 @@ expand wildcards (if any) and visit multiple files."
   "Edit file FILENAME, in another frame.
 May create a new frame, or reuse an existing one.
 See the function `display-buffer'.
+
+Interactively, the default if you just type RET is the current directory,
+but the visited file name is available through the minibuffer history:
+type M-n to pull it into the minibuffer.
+
 Interactively, or if WILDCARDS is non-nil in a call from Lisp,
 expand wildcards (if any) and visit multiple files."
-  (interactive "FFind file in other frame: \np")
+  (interactive (find-file-read-args "FFind file in other frame: "))
   (let ((value (find-file-noselect filename nil nil wildcards)))
     (if (listp value)
        (progn
@@ -758,9 +867,9 @@ expand wildcards (if any) and visit multiple files."
 
 (defun find-file-read-only (filename &optional wildcards)
   "Edit file FILENAME but don't allow changes.
-Like `find-file' but marks buffer as read-only.
+Like \\[find-file] but marks buffer as read-only.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only: \np")
+  (interactive (find-file-read-args "fFind file read-only: "))
   (find-file filename wildcards)
   (toggle-read-only 1)
   (current-buffer))
@@ -769,7 +878,7 @@ Use \\[toggle-read-only] to permit editing."
   "Edit file FILENAME in another window but don't allow changes.
 Like \\[find-file-other-window] but marks buffer as read-only.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other window: \np")
+  (interactive (find-file-read-args "fFind file read-only other window: "))
   (find-file-other-window filename wildcards)
   (toggle-read-only 1)
   (current-buffer))
@@ -778,7 +887,7 @@ Use \\[toggle-read-only] to permit editing."
   "Edit file FILENAME in another frame but don't allow changes.
 Like \\[find-file-other-frame] but marks buffer as read-only.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other frame: \np")
+  (interactive (find-file-read-args "fFind file read-only other frame: "))
   (find-file-other-frame filename wildcards)
   (toggle-read-only 1)
   (current-buffer))
@@ -1070,7 +1179,7 @@ that are visiting the various files."
                  (unless (or (eq read-only buffer-file-read-only)
                              (eq read-only buffer-read-only))
                    (when (or nowarn
-                             (let ((question 
+                             (let ((question
                                     (format "File %s is %s on disk.  Change buffer mode? "
                                             buffer-file-name
                                             (if read-only "read-only" "writable"))))
@@ -1078,8 +1187,12 @@ that are visiting the various files."
                      (setq buffer-read-only read-only)))
                  (setq buffer-file-read-only read-only))
 
-               (when (not (eq (not (null rawfile))
-                              (not (null find-file-literally))))
+               (when (and (not (eq (not (null rawfile))
+                                   (not (null find-file-literally))))
+                          ;; It is confusing to ask whether to visit
+                          ;; non-literally if they have the file in
+                          ;; hexl-mode.
+                          (not (eq major-mode 'hexl-mode)))
                  (if (buffer-modified-p)
                      (if (y-or-n-p (if rawfile
                                        "Save file and revisit literally? "
@@ -1297,7 +1410,7 @@ unless NOMODES is non-nil."
                  "Use M-x make-directory RET RET to create the directory"
                "Use C-u M-x make-directory RET RET to create directory and its parents")))))
       (when msg
-       (message msg)
+       (message "%s" msg)
        (or not-serious (sit-for 1 nil t))))
     (when (and auto-save-default (not noauto))
       (auto-save-mode t)))
@@ -1347,7 +1460,8 @@ in that case, this function acts as if `enable-local-variables' were t."
   (mapc
    (lambda (elt)
      (cons (purecopy (car elt)) (cdr elt)))
-   '(("\\.te?xt\\'" . text-mode)
+   '(("\\.in\\'" nil t)
+     ("\\.te?xt\\'" . text-mode)
      ("\\.c\\'" . c-mode)
      ("\\.h\\'" . c-mode)
      ("\\.tex\\'" . tex-mode)
@@ -1362,6 +1476,7 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.p\\'" . pascal-mode)
      ("\\.pas\\'" . pascal-mode)
      ("\\.ad[abs]\\'" . ada-mode)
+     ("\\.ad[bs].dg\\'" . ada-mode)
      ("\\.\\([pP]\\([Llm]\\|erl\\)\\|al\\)\\'" . perl-mode)
      ("\\.s?html?\\'" . html-mode)
      ("\\.cc\\'" . c++-mode)
@@ -1377,7 +1492,7 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.m\\'" . objc-mode)
      ("\\.java\\'" . java-mode)
      ("\\.mk\\'" . makefile-mode)
-     ("\\(M\\|m\\|GNUm\\)akefile\\(\\.in\\)?\\'" . makefile-mode)
+     ("\\(M\\|m\\|GNUm\\)akefile\\'" . makefile-mode)
      ("\\.am\\'" . makefile-mode)      ;For Automake.
      ;; Less common extensions come here
      ;; so more common ones above are found faster.
@@ -1427,6 +1542,7 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.sim\\'" . simula-mode)
      ("\\.mss\\'" . scribe-mode)
      ("\\.f90\\'" . f90-mode)
+     ("\\.f95\\'" . f90-mode)
      ("\\.indent\\.pro\\'" . fundamental-mode) ; to avoid idlwave-mode
      ("\\.pro\\'" . idlwave-mode)
      ("\\.lsp\\'" . lisp-mode)
@@ -1872,11 +1988,18 @@ is specified, returning t if it is specified."
 (put 'ignored-local-variables 'risky-local-variable t)
 (put 'eval 'risky-local-variable t)
 (put 'file-name-handler-alist 'risky-local-variable t)
+(put 'minor-mode-alist 'risky-local-variable t)
 (put 'minor-mode-map-alist 'risky-local-variable t)
+(put 'minor-mode-overriding-map-alist 'risky-local-variable t)
+(put 'overriding-local-map 'risky-local-variable t)
+(put 'overriding-terminal-local-map 'risky-local-variable t)
+(put 'auto-mode-alist 'risky-local-variable t)
 (put 'after-load-alist 'risky-local-variable t)
 (put 'buffer-file-name 'risky-local-variable t)
+(put 'buffer-undo-list 'risky-local-variable t)
 (put 'buffer-auto-save-file-name 'risky-local-variable t)
 (put 'buffer-file-truename 'risky-local-variable t)
+(put 'default-text-properties 'risky-local-variable t)
 (put 'exec-path 'risky-local-variable t)
 (put 'load-path 'risky-local-variable t)
 (put 'exec-directory 'risky-local-variable t)
@@ -1887,6 +2010,28 @@ is specified, returning t if it is specified."
 (put 'outline-level 'risky-local-variable t)
 (put 'rmail-output-file-alist 'risky-local-variable t)
 (put 'font-lock-defaults 'risky-local-variable t)
+(put 'special-display-buffer-names 'risky-local-variable t)
+(put 'frame-title-format 'risky-local-variable t)
+(put 'global-mode-string 'risky-local-variable t)
+(put 'header-line-format 'risky-local-variable t)
+(put 'icon-title-format 'risky-local-variable t)
+(put 'input-method-alist 'risky-local-variable t)
+(put 'format-alist 'risky-local-variable t)
+(put 'vc-mode 'risky-local-variable t)
+(put 'imenu-generic-expression 'risky-local-variable t)
+(put 'imenu-index-alist 'risky-local-variable t)
+(put 'standard-input 'risky-local-variable t)
+(put 'standard-output 'risky-local-variable t)
+(put 'unread-command-events 'risky-local-variable t)
+(put 'max-lisp-eval-depth 'risky-local-variable t)
+(put 'max-specpdl-size 'risky-local-variable t)
+(put 'mode-line-format 'risky-local-variable t)
+(put 'mode-line-modified 'risky-local-variable t)
+(put 'mode-line-mule-info 'risky-local-variable t)
+(put 'mode-line-buffer-identification 'risky-local-variable t)
+(put 'mode-line-modes 'risky-local-variable t)
+(put 'mode-line-position 'risky-local-variable t)
+(put 'display-time-string 'risky-local-variable t)
 
 ;; This one is safe because the user gets to check it before it is used.
 (put 'compile-command 'safe-local-variable t)
@@ -1896,7 +2041,8 @@ is specified, returning t if it is specified."
 
 (defun hack-one-local-variable (var val)
   "\"Set\" one variable in a local variables spec.
-A few variable names are treated specially."
+A few patterns are specified so that any name which matches one
+is considered risky."
   (cond ((eq var 'mode)
         (funcall (intern (concat (downcase (symbol-name val))
                                  "-mode"))))
@@ -1909,7 +2055,7 @@ A few variable names are treated specially."
        ;; Likewise for setting hook variables.
        ((or (get var 'risky-local-variable)
             (and
-             (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$\\|-predicate$\\|font-lock-keywords$\\|font-lock-keywords-[0-9]+$\\|font-lock-syntactic-keywords$"
+             (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$\\|-predicate$\\|font-lock-keywords$\\|font-lock-keywords-[0-9]+$\\|font-lock-syntactic-keywords$\\|-frame-alist$\\|-mode-alist$\\|-map$\\|-map-alist$"
                            (symbol-name var))
              (not (get var 'safe-local-variable))))
         ;; Permit evalling a put of a harmless property.
@@ -1946,6 +2092,11 @@ A few variable names are treated specially."
           (message "Ignoring `eval:' in the local variables list")))
        ;; Ordinary variable, really set it.
        (t (make-local-variable var)
+          ;; Make sure the string has no text properties.
+          ;; Some text properties can get evaluated in various ways,
+          ;; so it is risky to put them on with a local variable list.
+          (if (stringp val)
+              (set-text-properties 0 (length val) nil val))
           (set var val))))
 
 \f
@@ -2741,7 +2892,9 @@ After saving the buffer, this function runs `after-save-hook'."
              ;; delete the temp file.
              (or succeed
                  (progn
-                   (delete-file tempname)
+                   (condition-case nil
+                       (delete-file tempname)
+                     (file-error nil))
                    (set-visited-file-modtime old-modtime))))
            ;; Since we have created an entirely new file
            ;; and renamed it, make sure it gets the
@@ -2882,7 +3035,8 @@ saying what text to write."
   ;; `make-backup-file-name' will get us the right directory for
   ;; ordinary or numeric backups.  It might create a directory for
   ;; backups as a side-effect, according to `backup-directory-alist'.
-  (let* ((filename (make-backup-file-name filename))
+  (let* ((filename (file-name-sans-versions
+                   (make-backup-file-name filename)))
         (file (file-name-nondirectory filename))
         (dir  (file-name-directory    filename))
         (comp (file-name-all-completions file dir))
@@ -3068,8 +3222,12 @@ non-nil, it is called instead of rereading visited file contents."
                          (if auto-save-p 'emacs-mule-unix
                            coding-system-for-read)))
                     ;; Note that this preserves point in an intelligent way.
-                    (insert-file-contents file-name (not auto-save-p)
-                                          nil nil t))))
+                    (if preserve-modes
+                        (let ((buffer-file-formats buffer-file-formats))
+                          (insert-file-contents file-name (not auto-save-p)
+                                                nil nil t))
+                      (insert-file-contents file-name (not auto-save-p)
+                                            nil nil t)))))
               ;; Recompute the truename in case changes in symlinks
               ;; have changed the truename.
               (setq buffer-file-truename
@@ -3292,38 +3450,58 @@ See also `auto-save-file-name-p'."
   (if buffer-file-name
       (let ((list auto-save-file-name-transforms)
            (filename buffer-file-name)
-           result)
+           result uniq)
        ;; Apply user-specified translations
        ;; to the file name.
        (while (and list (not result))
          (if (string-match (car (car list)) filename)
              (setq result (replace-match (cadr (car list)) t nil
-                                         filename)))
+                                         filename)
+                   uniq (car (cddr (car list)))))
          (setq list (cdr list)))
-       (if result (setq filename result))
-
-       (if (and (eq system-type 'ms-dos)
-                (not (msdos-long-file-names)))
-           ;; We truncate the file name to DOS 8+3 limits before
-           ;; doing anything else, because the regexp passed to
-           ;; string-match below cannot handle extensions longer than
-           ;; 3 characters, multiple dots, and other atrocities.
-           (let ((fn (dos-8+3-filename
-                      (file-name-nondirectory buffer-file-name))))
-             (string-match "\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'" fn)
-             (concat (file-name-directory buffer-file-name)
-                     "#" (match-string 1 fn)
-                     "." (match-string 3 fn) "#"))
-         (concat (file-name-directory filename)
-                 "#"
-                 (file-name-nondirectory filename)
-                 "#")))
+       (if result
+           (if uniq
+               (setq filename (concat
+                               (file-name-directory result)
+                               (subst-char-in-string
+                                directory-sep-char ?!
+                                (replace-regexp-in-string "!" "!!"
+                                                          filename))))
+             (setq filename result)))
+       (setq result
+             (if (and (eq system-type 'ms-dos)
+                      (not (msdos-long-file-names)))
+                 ;; We truncate the file name to DOS 8+3 limits
+                 ;; before doing anything else, because the regexp
+                 ;; passed to string-match below cannot handle
+                 ;; extensions longer than 3 characters, multiple
+                 ;; dots, and other atrocities.
+                 (let ((fn (dos-8+3-filename
+                            (file-name-nondirectory buffer-file-name))))
+                   (string-match
+                    "\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'"
+                    fn)
+                   (concat (file-name-directory buffer-file-name)
+                           "#" (match-string 1 fn)
+                           "." (match-string 3 fn) "#"))
+               (concat (file-name-directory filename)
+                       "#"
+                       (file-name-nondirectory filename)
+                       "#")))
+       ;; Make sure auto-save file names don't contain characters
+       ;; invalid for the underlying filesystem.
+       (if (and (memq system-type '(ms-dos windows-nt))
+                ;; Don't modify remote (ange-ftp) filenames
+                (not (string-match "^/\\w+@[-A-Za-z0-9._]+:" result)))
+           (convert-standard-filename result)
+         result))
 
     ;; Deal with buffers that don't have any associated files.  (Mail
     ;; mode tends to create a good number of these.)
 
     (let ((buffer-name (buffer-name))
-         (limit 0))
+         (limit 0)
+         filename)
       ;; Eliminate all slashes and backslashes by
       ;; replacing them with sequences that start with %.
       ;; Quote % also, to keep distinct names distinct.
@@ -3336,13 +3514,34 @@ See also `auto-save-file-name-p'."
          (setq buffer-name (replace-match replacement t t buffer-name))
          (setq limit (1+ (match-end 0)))))
       ;; Generate the file name.
-      (expand-file-name
-       (format "#%s#%s#" buffer-name (make-temp-name ""))
-       ;; Try a few alternative directories, to get one we can write it.
-       (cond
-       ((file-writable-p default-directory) default-directory)
-       ((file-writable-p "/var/tmp/") "/var/tmp/")
-       ("~/"))))))
+      (setq file-name
+           (make-temp-file
+            (let ((fname
+                   (expand-file-name
+                    (format "#%s#" buffer-name)
+                    ;; Try a few alternative directories, to get one we can
+                    ;; write it.
+                    (cond
+                     ((file-writable-p default-directory) default-directory)
+                     ((file-writable-p "/var/tmp/") "/var/tmp/")
+                     ("~/")))))
+              (if (and (memq system-type '(ms-dos windows-nt))
+                       ;; Don't modify remote (ange-ftp) filenames
+                       (not (string-match "^/\\w+@[-A-Za-z0-9._]+:" fname)))
+                  ;; The call to convert-standard-filename is in case
+                  ;; buffer-name includes characters not allowed by the
+                  ;; DOS/Windows filesystems.  make-temp-file writes to the
+                  ;; file it creates, so we must fix the file name _before_
+                  ;; make-temp-file is called.
+                  (convert-standard-filename fname)
+                fname))
+            nil "#"))
+      ;; make-temp-file creates the file,
+      ;; but we don't want it to exist until we do an auto-save.
+      (condition-case ()
+         (delete-file file-name)
+       (file-error nil))
+      file-name)))
 
 (defun auto-save-file-name-p (filename)
   "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
@@ -3445,37 +3644,38 @@ If PATTERN is written as a relative file name, it is interpreted
 relative to the current default directory, `default-directory'.
 The file names returned are normally also relative to the current
 default directory.  However, if FULL is non-nil, they are absolute."
-  (let* ((nondir (file-name-nondirectory pattern))
-        (dirpart (file-name-directory pattern))
-        ;; A list of all dirs that DIRPART specifies.
-        ;; This can be more than one dir
-        ;; if DIRPART contains wildcards.
-        (dirs (if (and dirpart (string-match "[[*?]" dirpart))
-                  (mapcar 'file-name-as-directory
-                          (file-expand-wildcards (directory-file-name dirpart)))
-                (list dirpart)))
-        contents)
-    (while dirs
-      (when (or (null (car dirs))      ; Possible if DIRPART is not wild.
-               (file-directory-p (directory-file-name (car dirs))))
-       (let ((this-dir-contents
-              ;; Filter out "." and ".."
-              (delq nil
-                    (mapcar #'(lambda (name)
-                                (unless (string-match "\\`\\.\\.?\\'"
-                                                      (file-name-nondirectory name))
-                                  name))
-                            (directory-files (or (car dirs) ".") full
-                                             (wildcard-to-regexp nondir))))))
-         (setq contents
-               (nconc
-                (if (and (car dirs) (not full))
-                    (mapcar (function (lambda (name) (concat (car dirs) name)))
-                            this-dir-contents)
-                  this-dir-contents)
-                contents))))
-      (setq dirs (cdr dirs)))
-    contents))
+  (save-match-data
+    (let* ((nondir (file-name-nondirectory pattern))
+          (dirpart (file-name-directory pattern))
+          ;; A list of all dirs that DIRPART specifies.
+          ;; This can be more than one dir
+          ;; if DIRPART contains wildcards.
+          (dirs (if (and dirpart (string-match "[[*?]" dirpart))
+                    (mapcar 'file-name-as-directory
+                            (file-expand-wildcards (directory-file-name dirpart)))
+                  (list dirpart)))
+          contents)
+      (while dirs
+       (when (or (null (car dirs))     ; Possible if DIRPART is not wild.
+                 (file-directory-p (directory-file-name (car dirs))))
+         (let ((this-dir-contents
+                ;; Filter out "." and ".."
+                (delq nil
+                      (mapcar #'(lambda (name)
+                                  (unless (string-match "\\`\\.\\.?\\'"
+                                                        (file-name-nondirectory name))
+                                    name))
+                              (directory-files (or (car dirs) ".") full
+                                               (wildcard-to-regexp nondir))))))
+           (setq contents
+                 (nconc
+                  (if (and (car dirs) (not full))
+                      (mapcar (function (lambda (name) (concat (car dirs) name)))
+                              this-dir-contents)
+                    this-dir-contents)
+                  contents))))
+       (setq dirs (cdr dirs)))
+      contents)))
 
 (defun list-directory (dirname &optional verbose)
   "Display a list of files in or matching DIRNAME, a la `ls'.
@@ -3489,22 +3689,26 @@ and `list-directory-verbose-switches'."
                                       nil default-directory nil)
                       pfx)))
   (let ((switches (if verbose list-directory-verbose-switches
-                   list-directory-brief-switches)))
+                   list-directory-brief-switches))
+       buffer)
     (or dirname (setq dirname default-directory))
     (setq dirname (expand-file-name dirname))
     (with-output-to-temp-buffer "*Directory*"
+      (setq buffer standard-output)
       (buffer-disable-undo standard-output)
       (princ "Directory ")
       (princ dirname)
       (terpri)
       (save-excursion
        (set-buffer "*Directory*")
-       (setq default-directory
-             (if (file-directory-p dirname)
-                 (file-name-as-directory dirname)
-               (file-name-directory dirname)))
        (let ((wildcard (not (file-directory-p dirname))))
-         (insert-directory dirname switches wildcard (not wildcard)))))))
+         (insert-directory dirname switches wildcard (not wildcard)))))
+    ;; Finishing with-output-to-temp-buffer seems to clobber default-directory.
+    (with-current-buffer buffer
+      (setq default-directory
+           (if (file-directory-p dirname)
+               (file-name-as-directory dirname)
+             (file-name-directory dirname))))))
 
 (defun shell-quote-wildcard-pattern (pattern)
   "Quote characters special to the shell in PATTERN, leave wildcards alone.
@@ -3561,7 +3765,10 @@ We assume the output has the format of `df'.
 The value of this variable must be just a command name or file name;
 if you want to specify options, use `directory-free-space-args'.
 
-A value of nil disables this feature."
+A value of nil disables this feature.
+
+If the function `file-system-info' is defined, it is always used in
+preference to the program given by this variable."
   :type '(choice (string :tag "Program") (const :tag "None" nil))
   :group 'dired)
 
@@ -3570,6 +3777,42 @@ A value of nil disables this feature."
   :type 'string
   :group 'dired)
 
+(defun get-free-disk-space (dir)
+  "Return the mount of free space on directory DIR's file system.
+The result is a string that gives the number of free 1KB blocks,
+or nil if the system call or the program which retrieve the infornmation
+fail.
+
+This function calls `file-system-info' if it is available, or invokes the
+program specified by `directory-free-space-program' if that is non-nil."
+  ;; Try to find the number of free blocks.  Non-Posix systems don't
+  ;; always have df, but might have an equivalent system call.
+  (if (fboundp 'file-system-info)
+      (let ((fsinfo (file-system-info dir)))
+       (if fsinfo
+           (format "%.0f" (/ (nth 2 fsinfo) 1024))))
+    (save-match-data
+      (with-temp-buffer
+       (when (and directory-free-space-program
+                  (zerop (call-process directory-free-space-program
+                                       nil t nil
+                                       directory-free-space-args
+                                       dir)))
+         ;; Usual format is a header line followed by a line of
+         ;; numbers.
+         (goto-char (point-min))
+         (forward-line 1)
+         (if (not (eobp))
+             (progn
+               ;; Move to the end of the "available blocks" number.
+               (skip-chars-forward "^ \t")
+               (forward-word 3)
+               ;; Copy it into AVAILABLE.
+               (let ((end (point)))
+                 (forward-word -1)
+                 (buffer-substring (point) end)))))))))
+
+
 ;; insert-directory
 ;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
 ;;   FULL-DIRECTORY-P is nil.
@@ -3689,38 +3932,12 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
            (goto-char (point-min))
            ;; First find the line to put it on.
            (when (re-search-forward "^total" nil t)
-             ;; Try to find the number of free blocks.
-             ;; Non-Posix systems don't always have df,
-             ;; but might have an equivalent system call.
-             (if (fboundp 'file-system-info)
-                 (let ((fsinfo (file-system-info ".")))
-                   (if fsinfo
-                       (setq available (format "%.0f" (/ (nth 2 fsinfo) 1024)))))
-               (save-match-data
-                 (with-temp-buffer
-                   (when (and directory-free-space-program
-                              (zerop (call-process directory-free-space-program
-                                                   nil t nil
-                                                   directory-free-space-args
-                                                   ".")))
-                     ;; Usual format is a header line
-                     ;; followed by a line of numbers.
-                     (goto-char (point-min))
-                     (forward-line 1)
-                     (if (not (eobp))
-                         (progn
-                           ;; Move to the end of the "available blocks" number.
-                           (skip-chars-forward "^ \t")
-                           (forward-word 3)
-                           ;; Copy it into AVAILABLE.
-                           (let ((end (point)))
-                             (forward-word -1)
-                             (setq available (buffer-substring (point) end)))))))))
-             (when available
-               ;; Replace "total" with "used", to avoid confusion.
-               (replace-match "used")
-               (end-of-line)
-               (insert " available " available)))))))))
+             (let ((available (get-free-disk-space ".")))
+               (when available
+                 ;; Replace "total" with "used", to avoid confusion.
+                 (replace-match "total used in directory")
+                 (end-of-line)
+                 (insert " available " available))))))))))
 
 (defun insert-directory-safely (file switches
                                     &optional wildcard full-directory-p)
@@ -3765,14 +3982,12 @@ With prefix arg, silently save all file-visiting buffers, then kill."
           (let ((processes (process-list))
                 active)
             (while processes
-              (and (memq (process-status (car processes)) '(run stop open))
-                   (let ((val (process-kill-without-query (car processes))))
-                     (process-kill-without-query (car processes) val)
-                     val)
+              (and (memq (process-status (car processes)) '(run stop open listen))
+                   (process-query-on-exit-flag (car processes))
                    (setq active t))
               (setq processes (cdr processes)))
             (or (not active)
-                (list-processes)
+                (list-processes t)
                 (yes-or-no-p "Active processes exist; kill them and exit anyway? "))))
        ;; Query the user for other things, perhaps.
        (run-hook-with-args-until-failure 'kill-emacs-query-functions)
@@ -3803,19 +4018,20 @@ With prefix arg, silently save all file-visiting buffers, then kill."
        ;; Get a list of the indices of the args which are file names.
        (file-arg-indices
         (cdr (or (assq operation
-                       ;; The first four are special because they
+                       ;; The first five are special because they
                        ;; return a file name.  We want to include the /:
                        ;; in the return value.
                        ;; So just avoid stripping it in the first place.
                        '((expand-file-name . nil)
-                         ;; `identity' means just return the first arg
-                         ;; as stripped of its quoting.
-                         (substitute-in-file-name . identity)
                          (file-name-directory . nil)
                          (file-name-as-directory . nil)
                          (directory-file-name . nil)
-                         (file-name-completion 0 1)
-                         (file-name-all-completions 0 1)
+                         (file-name-sans-versions . nil)
+                         ;; `identity' means just return the first arg
+                         ;; as stripped of its quoting.
+                         (substitute-in-file-name . identity)
+                         (file-name-completion 1)
+                         (file-name-all-completions 1)
                          (rename-file 0 1)
                          (copy-file 0 1)
                          (make-symbolic-link 0 1)