]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
(recover-file): Fix error message.
[gnu-emacs] / lisp / files.el
index 380ab5398d55a80c5a9b7659f269c1dbb93ada0b..15f9c3af56470b8e724b3691a7eb6f9aad666b31 100644 (file)
 
 ;;; Code:
 
-(defconst delete-auto-save-files t
+(defvar delete-auto-save-files t
   "*Non-nil means delete auto-save file when a buffer is saved or killed.")
 
-(defconst directory-abbrev-alist
+(defvar directory-abbrev-alist
   nil
   "*Alist of abbreviations for file directories.
 A list of elements of the form (FROM . TO), each meaning to replace
@@ -49,7 +49,7 @@ via absolute symbolic links.  Make TO the name of the link, and FROM
 the name it is linked to.")
 
 ;;; Turn off backup files on VMS since it has version numbers.
-(defconst make-backup-files (not (eq system-type 'vax-vms))
+(defvar make-backup-files (not (eq system-type 'vax-vms))
   "*Non-nil means make a backup of a file the first time it is saved.
 This can be done by renaming the file or by copying.
 
@@ -75,16 +75,16 @@ This variable is intended for use by making it local to a buffer.
 But it is local only if you make it local.")
 (put 'backup-inhibited 'permanent-local t)
 
-(defconst backup-by-copying nil
+(defvar backup-by-copying nil
  "*Non-nil means always use copying to create backup files.
 See documentation of variable `make-backup-files'.")
 
-(defconst backup-by-copying-when-linked nil
+(defvar backup-by-copying-when-linked nil
  "*Non-nil means use copying to create backups for files with multiple names.
 This causes the alternate names to refer to the latest version as edited.
 This variable is relevant only if `backup-by-copying' is nil.")
 
-(defconst backup-by-copying-when-mismatch nil
+(defvar backup-by-copying-when-mismatch nil
   "*Non-nil means create backups by copying if this preserves owner or group.
 Renaming may still be used (subject to control of other variables)
 when it would not result in changing the owner or group of the file;
@@ -99,22 +99,30 @@ This variable is relevant only if `backup-by-copying' is nil.")
   "Predicate that looks at a file name and decides whether to make backups.
 Called with an absolute file name as argument, it returns t to enable backup.")
 
-(defconst buffer-offer-save nil
+(defvar buffer-offer-save nil
   "*Non-nil in a buffer means offer to save the buffer on exit
 even if the buffer is not visiting a file.
 Automatically local in all buffers.")
 (make-variable-buffer-local 'buffer-offer-save)
 
-(defconst find-file-existing-other-name t
+(defvar find-file-existing-other-name t
   "*Non-nil means find a file under alternative names, in existing buffers.
 This means if any existing buffer is visiting the file you want
 under another name, you get the existing buffer instead of a new buffer.")
 
-(defconst find-file-visit-truename nil
+(defvar find-file-visit-truename nil
   "*Non-nil means visit a file under its truename.
 The truename of a file is found by chasing all links
 both at the file level and at the levels of the containing directories.")
 
+(defvar find-file-revert-without-query
+  nil
+  "*Specify which files should be reverted without query.
+The value is a list of regular expressions.
+If the file name matches one of these regular expressions,
+then `find-file' reverts the file without querying
+if the file has changed on disk and you have not edited the buffer.")
+
 (defvar buffer-file-number nil
   "The device number and file number of the file visited in the current buffer.
 The value is a list of the form (FILENUM DEVNUM).
@@ -126,7 +134,7 @@ If the buffer is visiting a new file, the value is nil.")
 (defvar buffer-file-numbers-unique (not (memq system-type '(windows-nt)))
   "Non-nil means that buffer-file-number uniquely identifies files.")
 
-(defconst file-precious-flag nil
+(defvar file-precious-flag nil
   "*Non-nil means protect against I/O errors while saving files.
 Some modes set this non-nil in particular buffers.
 
@@ -159,23 +167,23 @@ If nil, ask confirmation.  Any other value prevents any trimming.")
   "*Number of newest versions to keep when a new numbered backup is made.
 Includes the new backup.  Must be > 0")
 
-(defconst require-final-newline nil
+(defvar require-final-newline nil
   "*Value of t says silently ensure a file ends in a newline when it is saved.
 Non-nil but not t says ask user whether to add a newline when there isn't one.
 nil means don't add newlines.")
 
-(defconst auto-save-default t
+(defvar auto-save-default t
   "*Non-nil says by default do auto-saving of every file-visiting buffer.")
 
-(defconst auto-save-visited-file-name nil
+(defvar auto-save-visited-file-name nil
   "*Non-nil says auto-save a buffer in the file it is visiting, when practical.
 Normally auto-save files are written under other names.")
 
-(defconst save-abbrevs nil
+(defvar save-abbrevs nil
   "*Non-nil means save word abbrevs too when files are saved.
 Loading an abbrev file sets this to t.")
 
-(defconst find-file-run-dired t
+(defvar find-file-run-dired t
   "*Non-nil says run dired if `find-file' is given the name of a directory.")
 
 ;;;It is not useful to make this a local variable.
@@ -228,22 +236,22 @@ buffer's contents, not to the particular visited file; thus,
 major mode does clear it.
 
 This variable automatically becomes buffer-local whenever it is set.
-If you use `add-hooks' to add elements to the list, use nil for the
+If you use `add-hook' to add elements to the list, use nil for the
 LOCAL argument.
 
 See also `write-file-hooks'.")
 (make-variable-buffer-local 'write-contents-hooks)
 
-(defconst enable-local-variables t
-  "*Control use of local-variables lists in files you visit.
+(defvar enable-local-variables t
+  "*Control use of local variables in files you visit.
 The value can be t, nil or something else.
-A value of t means local-variables lists are obeyed;
+A value of t means file local variables specifications are obeyed;
 nil means they are ignored; anything else means query.
 
-The command \\[normal-mode] always obeys local-variables lists
-and ignores this variable.")
+The command \\[normal-mode] always obeys file local variable
+specifications and ignores this variable.")
 
-(defconst enable-local-eval 'maybe
+(defvar enable-local-eval 'maybe
   "*Control processing of the \"variable\" `eval' in a file's local variables.
 The value can be t, nil or something else.
 A value of t means obey `eval' variables;
@@ -257,6 +265,8 @@ and ignores this variable.")
     (defalias 'lock-buffer 'ignore))
 (or (fboundp 'unlock-buffer)
     (defalias 'unlock-buffer 'ignore))
+(or (fboundp 'file-locked-p)
+    (defalias 'file-locked-p 'ignore))
 
 ;; This hook function provides support for ange-ftp host name
 ;; completion.  It runs the usual ange-ftp hook, but only for
@@ -479,70 +489,90 @@ unlike `file-truename'."
       (setq count (1- count)))
     newname))
 \f
-(defun switch-to-buffer-other-window (buffer)
-  "Select buffer BUFFER in another window."
+(defun switch-to-buffer-other-window (buffer &optional norecord)
+  "Select buffer BUFFER in another window.
+Optional second arg NORECORD non-nil means
+do not put this buffer at the front of the list of recently selected ones."
   (interactive "BSwitch to buffer in other window: ")
   (let ((pop-up-windows t))
-    (pop-to-buffer buffer t)))
+    (pop-to-buffer buffer t norecord)))
 
-(defun switch-to-buffer-other-frame (buffer)
-  "Switch to buffer BUFFER in another frame."
+(defun switch-to-buffer-other-frame (buffer &optional norecord)
+  "Switch to buffer BUFFER in another frame.
+Optional second arg NORECORD non-nil means
+do not put this buffer at the front of the list of recently selected ones."
   (interactive "BSwitch to buffer in other frame: ")
   (let ((pop-up-frames t))
-    (pop-to-buffer buffer t)
+    (pop-to-buffer buffer t norecord)
     (raise-frame (window-frame (selected-window)))))
 
-(defun find-file (filename)
+(defun find-file (filename &optional coding-system)
   "Edit file FILENAME.
 Switch to a buffer visiting file FILENAME,
-creating one if none already exists."
-  (interactive "FFind file: ")
-  (switch-to-buffer (find-file-noselect filename)))
-
-(defun find-file-other-window (filename)
+creating one if none already exists.
+A prefix argument enables user to specify the coding-system interactively."
+  (interactive "FFind file: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer (find-file-noselect filename)))
+    (switch-to-buffer (find-file-noselect filename))))
+
+(defun find-file-other-window (filename &optional coding-system)
   "Edit file FILENAME, in another window.
 May create a new window, or reuse an existing one.
+A prefix argument enables user to specify the coding-system interactively.
 See the function `display-buffer'."
-  (interactive "FFind file in other window: ")
-  (switch-to-buffer-other-window (find-file-noselect filename)))
+  (interactive "FFind file in other window: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer-other-window (find-file-noselect filename)))
+    (switch-to-buffer-other-window (find-file-noselect filename))))
 
-(defun find-file-other-frame (filename)
+(defun find-file-other-frame (filename &optional coding-system)
   "Edit file FILENAME, in another frame.
 May create a new frame, or reuse an existing one.
+A prefix argument enables user to specify the coding-system interactively.
 See the function `display-buffer'."
-  (interactive "FFind file in other frame: ")
-  (switch-to-buffer-other-frame (find-file-noselect filename)))
+  (interactive "FFind file in other frame: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer-other-frame (find-file-noselect filename)))
+    (switch-to-buffer-other-frame (find-file-noselect filename))))
 
-(defun find-file-read-only (filename)
+(defun find-file-read-only (filename &optional coding-system)
   "Edit file FILENAME but don't allow changes.
 Like \\[find-file] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only: ")
-  (find-file filename)
+  (interactive "fFind file read-only: \nZCoding-system: ")
+  (find-file filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-file-read-only-other-window (filename)
+(defun find-file-read-only-other-window (filename &optional coding-system)
   "Edit file FILENAME in another window but don't allow changes.
 Like \\[find-file-other-window] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other window: ")
-  (find-file-other-window filename)
+  (interactive "fFind file read-only other window: \nZCoding-system: ")
+  (find-file-other-window filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-file-read-only-other-frame (filename)
+(defun find-file-read-only-other-frame (filename &optional coding-system)
   "Edit file FILENAME in another frame but don't allow changes.
 Like \\[find-file-other-frame] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other frame: ")
-  (find-file-other-frame filename)
+  (interactive "fFind file read-only other frame: \nZCoding-system: ")
+  (find-file-other-frame filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-alternate-file-other-window (filename)
+(defun find-alternate-file-other-window (filename &optional coding-system)
   "Find file FILENAME as a replacement for the file in the next window.
-This command does not select that window."
+This command does not select that window.
+A prefix argument enables user to specify the coding-system interactively."
   (interactive
    (save-selected-window
      (other-window 1)
@@ -553,17 +583,20 @@ This command does not select that window."
            (setq file-name (file-name-nondirectory file)
                  file-dir (file-name-directory file)))
        (list (read-file-name
-             "Find alternate file: " file-dir nil nil file-name)))))
+             "Find alternate file: " file-dir nil nil file-name)
+            (if current-prefix-arg
+                (read-coding-system "Coding-system: "))))))
   (if (one-window-p)
-      (find-file-other-window filename)
+      (find-file-other-window filename coding-system)
     (save-selected-window
       (other-window 1)
-      (find-alternate-file filename))))
+      (find-alternate-file filename coding-system))))
 
-(defun find-alternate-file (filename)
+(defun find-alternate-file (filename &optional coding-system)
   "Find file FILENAME, select its buffer, kill previous buffer.
 If the current buffer now contains an empty file that you just visited
-\(presumably by mistake), use this command to visit the file you really want."
+\(presumably by mistake), use this command to visit the file you really want.
+A prefix argument enables user to specify the coding-system interactively."
   (interactive
    (let ((file buffer-file-name)
         (file-name nil)
@@ -572,7 +605,9 @@ If the current buffer now contains an empty file that you just visited
          (setq file-name (file-name-nondirectory file)
                file-dir (file-name-directory file)))
      (list (read-file-name
-           "Find alternate file: " file-dir nil nil file-name))))
+           "Find alternate file: " file-dir nil nil file-name)
+          (if current-prefix-arg
+              (read-coding-system "Coding-system: ")))))
   (and (buffer-modified-p) (buffer-file-name)
        ;; (not buffer-read-only)
        (not (yes-or-no-p (format "Buffer %s is modified; kill anyway? "
@@ -592,7 +627,7 @@ If the current buffer now contains an empty file that you just visited
          (setq buffer-file-name nil)
          (setq buffer-file-number nil)
          (setq buffer-file-truename nil)
-         (find-file filename))
+         (find-file filename coding-system))
       (cond ((eq obuf (current-buffer))
             (setq buffer-file-name ofile)
             (setq buffer-file-number onum)
@@ -616,7 +651,7 @@ otherwise a string <2> or <3> or ... is appended to get an unused name."
 Choose the buffer's name using `generate-new-buffer-name'."
   (get-buffer-create (generate-new-buffer-name name)))
 
-(defconst automount-dir-prefix "^/tmp_mnt/"
+(defvar automount-dir-prefix "^/tmp_mnt/"
   "Regexp to match the automounter prefix in a directory name.")
 
 (defvar abbreviated-home-dir nil
@@ -716,7 +751,10 @@ If there is no such live buffer, return nil."
 A buffer may be modified in several ways after reading into the buffer due
 to advanced Emacs features, such as file-name-handlers, format decoding,
 find-file-hooks, etc.
-  This function ensures that none of these modifications will take place."
+  This function ensures that none of these modifications will take place.
+
+This function does not work for remote files, because it turns off
+file name handlers and remote file access uses a file name handler."
   (let ((file-name-handler-alist nil)
        (format-alist nil)
        (after-insert-file-functions nil)
@@ -736,7 +774,9 @@ find-file-hooks, etc.
   "Read file FILENAME into a buffer and return the buffer.
 If a buffer exists visiting FILENAME, return that one, but
 verify that the file has not changed since visited or saved.
-The buffer is not selected, just returned to the caller."
+The buffer is not selected, just returned to the caller.
+Optional first arg NOWARN non-nil means suppress any warning messages.
+Optional second arg RAWFILE non-nil means the file is read literally"
   (setq filename
        (abbreviate-file-name
         (expand-file-name filename)))
@@ -767,6 +807,20 @@ The buffer is not selected, just returned to the caller."
              (verify-visited-file-modtime buf)
              (cond ((not (file-exists-p filename))
                     (error "File %s no longer exists!" filename))
+                   ;; Certain files should be reverted automatically
+                   ;; if they have changed on disk and not in the buffer.
+                   ((and (not (buffer-modified-p buf))
+                         (let ((tail find-file-revert-without-query)
+                               (found nil))
+                           (while tail
+                             (if (string-match (car tail) filename)
+                                 (setq found t))
+                             (setq tail (cdr tail)))
+                           found))
+                    (with-current-buffer buf
+                     (message "Reverting file %s..." filename)
+                     (revert-buffer t t)
+                     (message "Reverting file %s...done" filename)))
                    ((yes-or-no-p
                      (if (string= (file-name-nondirectory filename)
                                   (buffer-name buf))
@@ -781,8 +835,7 @@ The buffer is not selected, just returned to the caller."
       "File %s changed on disk.  Reread from disk into %s? ")
                         (file-name-nondirectory filename)
                         (buffer-name buf))))
-                    (save-excursion
-                      (set-buffer buf)
+                    (with-current-buffer buf
                       (revert-buffer t t)))))
        (save-excursion
 ;;; The truename stuff makes this obsolete.
@@ -943,6 +996,7 @@ run `normal-mode' explicitly."
     ("\\.pm\\'" . perl-mode)
     ("\\.cc\\'" . c++-mode)
     ("\\.hh\\'" . c++-mode)
+    ("\\.hpp\\'" . c++-mode)
     ("\\.C\\'" . c++-mode)
     ("\\.H\\'" . c++-mode)
     ("\\.cpp\\'" . c++-mode)
@@ -950,7 +1004,9 @@ run `normal-mode' explicitly."
     ("\\.hxx\\'" . c++-mode)
     ("\\.c\\+\\+\\'" . c++-mode)
     ("\\.h\\+\\+\\'" . c++-mode)
+    ("\\.m\\'" . objc-mode)
     ("\\.java\\'" . java-mode)
+    ("\\.sim\\'" . simula-mode)
     ("\\.mk\\'" . makefile-mode)
     ("\\(M\\|m\\|GNUm\\)akefile\\(.in\\)?\\'" . makefile-mode)
 ;;; Less common extensions come here
@@ -964,6 +1020,9 @@ run `normal-mode' explicitly."
     ("change.log\\'" . change-log-mode)
     ("changelo\\'" . change-log-mode)
     ("ChangeLog.[0-9]+\\'" . change-log-mode)
+    ;; for MSDOS and MS-Windows (which are case-insensitive)
+    ("changelog\\'" . change-log-mode)
+    ("changelog.[0-9]+\\'" . change-log-mode)
     ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
     ("\\.scm\\.[0-9]*\\'" . scheme-mode)
     ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
@@ -1004,6 +1063,7 @@ run `normal-mode' explicitly."
     ("\\.oak\\'" . scheme-mode)
     ("\\.sgml?\\'" . sgml-mode)
     ("\\.dtd\\'" . sgml-mode)
+    ("\\.ds\\(ss\\)?l\\'" . dsssl-mode)
     ("\\.s?html?\\'" . html-mode)
     ;; .emacs following a directory delimiter
     ;; in either Unix or VMS syntax.
@@ -1023,7 +1083,7 @@ If the element has the form (REGEXP FUNCTION NON-NIL), then after
 calling FUNCTION (if it's not nil), we delete the suffix that matched
 REGEXP and search the list again for another match.")
 
-(defconst interpreter-mode-alist
+(defvar interpreter-mode-alist
   '(("perl" . perl-mode)
     ("perl5" . perl-mode)
     ("wish" . tcl-mode)
@@ -1063,10 +1123,10 @@ The car of each element is compared with
 the name of the interpreter specified in the first line.
 If it matches, mode MODE is selected.")
 
-(defconst inhibit-first-line-modes-regexps '("\\.tar\\'" "\\.tgz\\'")
+(defvar inhibit-first-line-modes-regexps '("\\.tar\\'" "\\.tgz\\'")
   "List of regexps; if one matches a file name, don't look for `-*-'.")
 
-(defconst inhibit-first-line-modes-suffixes nil
+(defvar inhibit-first-line-modes-suffixes nil
   "List of regexps for what to ignore, for `inhibit-first-line-modes-regexps'.
 When checking `inhibit-first-line-modes-regexps', we first discard
 from the end of the file name anything that matches one of these regexps.")
@@ -1232,7 +1292,11 @@ If `enable-local-variables' is nil, this function does not check for a
                     (val (save-restriction
                            (narrow-to-region (point) end)
                            (read (current-buffer)))))
-                (or (eq key 'mode)
+                ;; It is traditional to ignore
+                ;; case when checking for `mode' in set-auto-mode,
+                ;; so we must do that here as well.
+                ;; That is inconsistent, but we're stuck with it.
+                (or (equal (downcase (symbol-name key)) "mode")
                     (setq result (cons (cons key val) result)))
                 (skip-chars-forward " \t;")))
             (setq result (nreverse result))))
@@ -1336,7 +1400,7 @@ in order to initialize other data structure based on them.")
                (hack-one-local-variable var val)))))))
   (run-hooks 'hack-local-variables-hook))
 
-(defconst ignored-local-variables
+(defvar ignored-local-variables
   '(enable-local-eval)
   "Variables to be ignored in a file's local variable spec.")
 
@@ -1417,7 +1481,7 @@ in order to initialize other data structure based on them.")
           (set var val))))
 
 \f
-(defun set-visited-file-name (filename &optional no-query)
+(defun set-visited-file-name (filename &optional no-query along-with-file)
   "Change name of file visited in current buffer to FILENAME.
 The next time the buffer is saved it will go in the newly specified file.
 nil or empty string as argument means make buffer not be visiting any file.
@@ -1425,7 +1489,10 @@ Remember to delete the initial contents of the minibuffer
 if you wish to pass an empty string as the argument.
 
 The optional second argument NO-QUERY, if non-nil, inhibits asking for
-confirmation in the case where the file FILENAME already exists."
+confirmation in the case where another buffer is already visiting FILENAME.
+
+The optional third argument ALONG-WITH-FILE, if non-nil, means that
+the old visited file has been renamed to the new name FILENAME."
   (interactive "FSet visited file name: ")
   (if (buffer-base-buffer)
       (error "An indirect buffer cannot visit a file"))
@@ -1461,7 +1528,8 @@ confirmation in the case where the file FILENAME already exists."
          (or (string= new-name (buffer-name))
              (rename-buffer new-name t))))
     (setq buffer-backed-up nil)
-    (clear-visited-file-modtime)
+    (or along-with-file
+       (clear-visited-file-modtime))
     ;; Abbreviate the file names of the buffer.
     (if truename
        (progn
@@ -1506,10 +1574,11 @@ confirmation in the case where the file FILENAME already exists."
     (and oauto buffer-auto-save-file-name
         (file-exists-p oauto)
         (rename-file oauto buffer-auto-save-file-name t)))
-  (if buffer-file-name
-      (set-buffer-modified-p t)))
+  (and buffer-file-name
+       (not along-with-file)
+       (set-buffer-modified-p t)))
 
-(defun write-file (filename &optional confirm)
+(defun write-file (filename &optional confirm coding-system)
   "Write current buffer into file FILENAME.
 Makes buffer visit that file, and marks it not modified.
 If the buffer is already visiting a file, you can specify
@@ -1518,7 +1587,10 @@ old name in that directory.
 
 If optional second arg CONFIRM is non-nil,
 ask for confirmation for overwriting an existing file.
-Interactively, confirmation is required unless you supply a prefix argument."
+Interactively, confirmation is required unless you supply a prefix argument.
+
+A prefix argument also enables user to interactively specify a
+coding-system for encoding the file."
 ;;  (interactive "FWrite file: ")
   (interactive
    (list (if buffer-file-name
@@ -1528,7 +1600,10 @@ Interactively, confirmation is required unless you supply a prefix argument."
                               (cdr (assq 'default-directory
                                          (buffer-local-variables)))
                               nil nil (buffer-name)))
-        (not current-prefix-arg)))
+        (not current-prefix-arg)
+        (if current-prefix-arg
+            (read-coding-system "Coding-system: "))
+        ))
   (or (null filename) (string-equal filename "")
       (progn
        ;; If arg is just a directory,
@@ -1540,16 +1615,26 @@ Interactively, confirmation is required unless you supply a prefix argument."
             (file-exists-p filename)
             (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
                 (error "Canceled")))
-       (set-visited-file-name filename)))
+       (set-visited-file-name filename (not confirm))))
   (set-buffer-modified-p t)
-  (save-buffer))
+  (if coding-system
+      (let ((coding-system-for-write coding-system))
+       ;; It is convenient to change buffer-file-coding-system to the
+       ;; specified one.
+       (set-buffer-file-coding-system coding-system)
+       (save-buffer))
+    (save-buffer)))
 \f
 (defun backup-buffer ()
   "Make a backup of the disk file visited by the current buffer, if appropriate.
 This is normally done before saving the buffer the first time.
 If the value is non-nil, it is the result of `file-modes' on the original
 file; this means that the caller, after saving the buffer, should change
-the modes of the new file to agree with the old modes."
+the modes of the new file to agree with the old modes.
+
+A backup may be done by renaming or by copying; see documentation of
+variable `make-backup-files'.  If it's done by renaming, then the file is
+no longer accessible under its old name."
   (if (and make-backup-files (not backup-inhibited)
           (not buffer-backed-up)
           (file-exists-p buffer-file-name)
@@ -1678,6 +1763,22 @@ The extension, in a file name, is the part that follows the last `.'."
            (substring file 0 (match-beginning 0)))
        filename))))
 
+(defun file-name-extension (filename &optional period)
+  "Return FILENAME's final \"extension\".
+The extension, in a file name, is the part that follows the last `.'.
+Return nil for extensionless file names such as `foo'.
+Return the empty string for file names such as `foo.'.
+
+If PERIOD is non-nil, then the returned value includes the period
+that delimits the extension, and if FILENAME has no extension,
+the value is \"\"."
+  (save-match-data
+    (let ((file (file-name-sans-versions (file-name-nondirectory filename))))
+      (if (string-match "\\.[^.]*\\'" file)
+          (substring file (+ (match-beginning 0) (if period 0 1)))
+        (if period
+            "")))))
+
 (defun make-backup-file-name (file)
   "Create the non-numeric backup file name for FILE.
 This is a separate function so you can redefine it for customization."
@@ -1764,15 +1865,28 @@ If the value is nil, don't make a backup."
   (car (cdr (file-attributes filename))))
 
 (defun file-relative-name (filename &optional directory)
-  "Convert FILENAME to be relative to DIRECTORY (default: default-directory)."
-  (setq filename (expand-file-name filename)
-       directory (file-name-as-directory (expand-file-name
-                                          (or directory default-directory))))
-  (let ((ancestor ""))
-    (while (not (string-match (concat "^" (regexp-quote directory)) filename))
-      (setq directory (file-name-directory (substring directory 0 -1))
-           ancestor (concat "../" ancestor)))
-    (concat ancestor (substring filename (match-end 0)))))
+  "Convert FILENAME to be relative to DIRECTORY (default: default-directory).
+This function returns a relative file name which is equivalent to FILENAME
+when used with that default directory as the default.
+If this is impossible (which can happen on MSDOS and Windows
+when the file name and directory use different drive names)
+then it returns FILENAME."
+  (save-match-data
+    (setq fname (expand-file-name filename)
+         directory (file-name-as-directory
+                    (expand-file-name (or directory default-directory))))
+    ;; On Microsoft OSes, if FILENAME and DIRECTORY have different
+    ;; drive names, they can't be relative, so return the absolute name.
+    (if (and (or (eq system-type 'ms-dos)
+                (eq system-type 'windows-nt))
+            (not (string-equal (substring fname  0 2)
+                               (substring directory 0 2))))
+       filename
+      (let ((ancestor ""))
+       (while (not (string-match (concat "^" (regexp-quote directory)) fname))
+         (setq directory (file-name-directory (substring directory 0 -1))
+               ancestor (concat "../" ancestor)))
+       (concat ancestor (substring fname (match-end 0)))))))
 \f
 (defun save-buffer (&optional args)
   "Save current buffer in visited file if modified.  Versions described below.
@@ -2050,27 +2164,36 @@ With arg, set read-only iff arg is positive."
             (> (prefix-numeric-value arg) 0)))
   (force-mode-line-update))
 
-(defun insert-file (filename)
+(defun insert-file (filename &optional coding-system)
   "Insert contents of file FILENAME into buffer after point.
 Set mark after the inserted text.
+A prefix argument enables user to specify the coding-system interactively.
 
 This function is meant for the user to run interactively.
 Don't call it from programs!  Use `insert-file-contents' instead.
 \(Its calling sequence is different; see its documentation)."
-  (interactive "*fInsert file: ")
+  (interactive "*fInsert file: \nZCoding-system: ")
   (if (file-directory-p filename)
       (signal 'file-error (list "Opening input file" "file is a directory"
                                filename)))
-  (let ((tem (insert-file-contents filename)))
+  (let ((tem
+        (if coding-system
+            (let ((coding-system-for-read coding-system))
+              (insert-file-contents filename))
+          (insert-file-contents filename))))
     (push-mark (+ (point) (car (cdr tem))))))
 
-(defun append-to-file (start end filename)
+(defun append-to-file (start end filename &optional coding-system)
   "Append the contents of the region to the end of file FILENAME.
 When called from a function, expects three arguments,
 START, END and FILENAME.  START and END are buffer positions
-saying what text to write."
-  (interactive "r\nFAppend to file: ")
-  (write-region start end filename t))
+saying what text to write.
+A prefix argument enables user to specify the coding-system interactively."
+  (interactive "r\nFAppend to file: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-write coding-system))
+       (write-region start end filename t))
+    (write-region start end filename t)))
 
 (defun file-newest-backup (filename)
   "Return most recent backup file for FILENAME or nil if no backups exist."
@@ -2166,11 +2289,16 @@ If `revert-buffer-function' is used to override the normal revert
 mechanism, this hook is not used.")
 
 (defun revert-buffer (&optional ignore-auto noconfirm preserve-modes)
-  "Replace the buffer text with the text of the visited file on disk.
+  "Replace current buffer text with the text of the visited file on disk.
 This undoes all changes since the file was visited or saved.
 With a prefix argument, offer to revert from latest auto-save file, if
 that is more recent than the visited file.
 
+This command also works for special buffers that contain text which
+doesn't come from a file, but reflects some other data base instead:
+for example, Dired buffers and buffer-list buffers.  In these cases,
+it reconstructs the buffer contents from the appropriate data base.
+
 When called from Lisp, the first argument is IGNORE-AUTO; only offer
 to revert from the auto-save file when this is nil.  Note that the
 sense of this argument is the reverse of the prefix argument, for the
@@ -2184,10 +2312,11 @@ Optional third argument PRESERVE-MODES non-nil means don't alter
 the files modes.  Normally we reinitialize them using `normal-mode'.
 
 If the value of `revert-buffer-function' is non-nil, it is called to
-do the work.
+do all the work for this command.  Otherwise, the hooks
+`before-revert-hook' and `after-revert-hook' are run at the beginning
+and the end, and if `revert-buffer-insert-file-contents-function' is
+non-nil, it is called instead of rereading visited file contents."
 
-The default revert function runs the hook `before-revert-hook' at the
-beginning and `after-revert-hook' at the end."
   ;; I admit it's odd to reverse the sense of the prefix argument, but
   ;; there is a lot of code out there which assumes that the first
   ;; argument should be t to avoid consulting the auto-save file, and
@@ -2283,11 +2412,13 @@ beginning and `after-revert-hook' at the end."
                                 file file-name)))
             (yes-or-no-p (format "Recover auto save file %s? " file-name)))
           (switch-to-buffer (find-file-noselect file t))
-          (let ((buffer-read-only nil))
+          (let ((buffer-read-only nil)
+                ;; Auto-saved file shoule be read without any code conversion.
+                (coding-system-for-read 'no-conversion))
             (erase-buffer)
             (insert-file-contents file-name nil))
           (after-find-file nil nil t))
-         (t (error "Recover-file cancelled.")))))
+         (t (error "Recover-file cancelled")))))
 
 (defun recover-session ()
   "Recover auto save files from a previous Emacs session.
@@ -2296,8 +2427,11 @@ previous sessions that you could recover from.
 To choose one, move point to the proper line and then type C-c C-c.
 Then you'll be asked about a number of files to recover."
   (interactive)
+  (if (null auto-save-list-file-prefix)
+      (error "You set `auto-save-list-file-prefix' to disable making session files"))
   (let ((ls-lisp-support-shell-wildcards t))
-    (dired (concat auto-save-list-file-prefix "*")))
+    (dired (concat auto-save-list-file-prefix "*")
+          (concat dired-listing-switches "t")))
   (goto-char (point-min))
   (or (looking-at "Move to the session you want to recover,")
       (let ((inhibit-read-only t))
@@ -2457,20 +2591,17 @@ See also `auto-save-file-name-p'."
 
     (let ((buffer-name (buffer-name))
          (limit 0))
-      ;; Use technique from Sebastian Kremer's auto-save
-      ;; package to turn slashes into \\!.  This ensures that
-      ;; the auto-save buffer name is unique.
-
-      (while (string-match "[/\\]" buffer-name limit)
-       (setq buffer-name (concat (substring buffer-name 0 (match-beginning 0))
-                       (if (string= (substring buffer-name
-                                               (match-beginning 0)
-                                               (match-end 0))
-                                    "/")
-                           "\\!"
-                         "\\\\")
-                       (substring buffer-name (match-end 0))))
-       (setq limit (1+ (match-end 0))))
+      ;; Eliminate all slashes and backslashes by
+      ;; replacing them with sequences that start with %.
+      ;; Quote % also, to keep distinct names distinct.
+      (while (string-match "[/\\%]" buffer-name limit)
+       (let* ((character (aref buffer-name (match-beginning 0)))
+              (replacement
+               (cond ((eq character ?%) "%%")
+                     ((eq character ?/) "%+")
+                     ((eq character ?\\) "%-"))))
+         (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 ""))
@@ -2503,6 +2634,10 @@ by `sh' are supported."
             result
             (concat result
                     (cond
+                     ((and (eq ch ?\[)
+                           (< (1+ i) len)
+                           (eq (aref wildcard (1+ i)) ?\]))
+                      "\\[")
                      ((eq ch ?\[)      ; [...] maps to regexp char class
                       (progn
                         (setq i (1+ i))
@@ -2552,11 +2687,11 @@ by `sh' are supported."
     ;; not its part.  Make the regexp say so.
     (concat "\\`" result "\\'")))
 \f
-(defconst list-directory-brief-switches
+(defvar list-directory-brief-switches
   (if (eq system-type 'vax-vms) "" "-CF")
   "*Switches for list-directory to pass to `ls' for brief listing,")
 
-(defconst list-directory-verbose-switches
+(defvar list-directory-verbose-switches
   (if (eq system-type 'vax-vms)
       "/PROTECTION/SIZE/DATE/OWNER/WIDTH=(OWNER:10)"
     "-l")
@@ -2658,7 +2793,7 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
                                                (if (stringp switches)
                                                    switches
                                                  (mapconcat 'identity switches " "))
-                                               " "
+                                               " -- "
                                                pattern)))
                 ;; SunOS 4.1.3, SVr4 and others need the "." to list the
                 ;; directory if FILE is a symbolic link.
@@ -2677,6 +2812,8 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
                                          switches (substring switches (match-end 0))))
                                  (setq list (nreverse (cons switches list))))))
                          (append list
+                                 ;; Avoid lossage if FILE starts with `-'.
+                                 '("--")
                                  (list
                                   (if full-directory-p
                                       (concat (file-name-as-directory file) ".")
@@ -2719,6 +2856,50 @@ With prefix arg, silently save all file-visiting buffers, then kill."
        (run-hook-with-args-until-failure 'kill-emacs-query-functions)
        (kill-emacs)))
 \f
+;; We use /: as a prefix to "quote" a file name 
+;; so that magic file name handlers will not apply to it.
+
+(setq file-name-handler-alist
+      (cons '("\\`/:" . file-name-non-special)
+           file-name-handler-alist))
+
+;; We depend on being the last handler on the list,
+;; so that anything else which does need handling
+;; has been handled already.
+;; So it is safe for us to inhibit *all* magic file name handlers.
+
+(defun file-name-non-special (operation &rest arguments)
+  (let ((file-name-handler-alist nil)
+       ;; 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
+                       ;; 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)
+                         (file-name-directory . nil)
+                         (file-name-as-directory . nil)
+                         (directory-file-name . nil)
+                         (rename-file 0 1)
+                         (copy-file 0 1)
+                         (make-symbolic-link 0 1)
+                         (add-name-to-file 0 1)))
+                 ;; For all other operations, treat the first argument only
+                 ;; as the file name.
+                 '(nil 0))))
+       ;; Copy ARGUMENTS so we can replace elements in it.
+       (arguments (copy-sequence arguments)))
+    ;; Strip off the /: from the file names that have this handler.
+    (save-match-data
+      (while file-arg-indices
+       (and (nth (car file-arg-indices) arguments)
+            (string-match "\\`/:" (nth (car file-arg-indices) arguments))
+            (setcar (nthcdr (car file-arg-indices) arguments)
+                    (substring (nth (car file-arg-indices) arguments) 2)))
+       (setq file-arg-indices (cdr file-arg-indices))))
+    (apply operation arguments)))
+\f
 (define-key ctl-x-map "\C-f" 'find-file)
 (define-key ctl-x-map "\C-q" 'toggle-read-only)
 (define-key ctl-x-map "\C-r" 'find-file-read-only)