Sync up with r21-4-12-chise-0_21-gt-j90-r165.
[chise/xemacs-chise.git] / lisp / files.el
index 05d5011..2b713c8 100644 (file)
@@ -371,23 +371,11 @@ and ignores this variable."
 ;      (apply op args))
 
 (defun convert-standard-filename (filename)
-  "Convert a standard file's name to something suitable for the current OS."
-  (if (eq system-type 'windows-nt)
-      (let ((name (copy-sequence filename))
-           (start 0))
-       ;; leave ':' if part of drive specifier
-       (if (and (> (length name) 1)
-                (eq (aref name 1) ?:))
-           (setq start 2))
-       ;; destructively replace invalid filename characters with !
-       (while (string-match "[?*:<>|\"\000-\037]" name start)
-         (aset name (match-beginning 0) ?!)
-         (setq start (match-end 0)))
-       ;; FSF: [convert directory separators to Windows format ...]
-       ;; unneeded in XEmacs.
-       name)
-    filename))
-
+  "Convert a standard file's name to something suitable for the current OS.
+This function's standard definition is trivial; it just returns the argument.
+However, on some systems, the function is redefined
+with a definition that really does change some file names."
+  filename)
 \f
 (defun pwd ()
   "Show the current default directory."
@@ -899,6 +887,7 @@ conversion, find-file-hooks, automatic uncompression, etc.
            (after-insert-file-functions nil)
            (coding-system-for-read 'binary)
            (coding-system-for-write 'binary)
+           (jka-compr-compression-info-list nil)
            (find-buffer-file-type-function
             (if (fboundp 'find-buffer-file-type)
                 (symbol-function 'find-buffer-file-type)
@@ -1186,7 +1175,6 @@ run `normal-mode' explicitly."
     ("\\.icn\\'" . icon-mode)
     ("\\.\\(?:[ckz]?sh\\|shar\\)\\'" . sh-mode)
     ("\\.[Pp][Rr][Oo]\\'" . idlwave-mode)
-    ("\\.si\\(v\\|eve\\)\\'" . sieve-mode)
     ;; #### Unix-specific!
     ("/\\.\\(?:bash_\\|z\\)?\\(profile\\|login\\|logout\\)\\'" . sh-mode)
     ("/\\.\\(?:[ckz]sh\\|bash\\|tcsh\\|es\\|xinit\\|startx\\)rc\\'" . sh-mode)
@@ -1194,7 +1182,7 @@ run `normal-mode' explicitly."
     ("\\.m?spec$" .sh-mode)
     ;; The following come after the ChangeLog pattern for the sake of
     ;; ChangeLog.1, etc. and after the .scm.[0-9] pattern too.
-    ("\\.[123456789]\\'" . nroff-mode)
+    ("\\.[12345678]\\'" . nroff-mode)
     ("\\.[tT]e[xX]\\'" . tex-mode)
     ("\\.\\(?:sty\\|cls\\|bbl\\)\\'" . latex-mode)
     ("\\.bib\\'" . bibtex-mode)
@@ -1225,11 +1213,11 @@ run `normal-mode' explicitly."
     ;; Windows syntax.
     ("[/\\][._].*emacs\\'" . emacs-lisp-mode)
     ("\\.m4\\'" . autoconf-mode)
-    ("configure\\(\\.in\\|\\.ac\\)\\'" . autoconf-mode)
+    ("configure\\.in\\'" . autoconf-mode)
     ("\\.ml\\'" . lisp-mode)
     ("\\.ma?ke?\\'" . makefile-mode)
-    ("\\(GNU\\)?[Mm]akefile\\(\\.\\|\\'\\)" . makefile-mode)
-    ("[./\\]X\\(defaults\\|environment\\|resources\\|modmap\\)\\'" . xrdb-mode)
+    ("[Mm]akefile\\(\\.\\|\\'\\)" . makefile-mode)
+    ("\\.X\\(defaults\\|environment\\|resources\\|modmap\\)\\'" . xrdb-mode)
     ;; #### The following three are Unix-specific (but do we care?)
     ("/app-defaults/" . xrdb-mode)
     ("\\.[^/]*wm2?\\(?:rc\\)?\\'" . winmgr-mode)
@@ -1272,7 +1260,8 @@ with the name of the interpreter specified in the first line.
 If it matches, mode MODE is selected.")
 
 (defvar binary-file-regexps
-  '("\\.\\(?:bz2\\|elc\\|g\\(if\\|z\\)\\|jp\\(eg\\|g\\)\\|png\\|t\\(ar\\|gz\\|iff\\)\\|[Zo]\\)\\'")
+  (purecopy
+   '("\\.\\(?:bz2\\|elc\\|g\\(if\\|z\\)\\|jp\\(eg\\|g\\)\\|png\\|PNG\\|t\\(ar\\|gz\\|iff\\)\\|[Zo]\\)\\'"))
   "List of regexps of filenames containing binary (non-text) data.")
 
 ;   (eval-when-compile
@@ -1940,9 +1929,7 @@ of the new file to agree with the old modes."
                                (setq setmodes (file-modes backupname)))
                            (file-error
                             ;; If trouble writing the backup, write it in ~.
-                            (setq backupname
-                                  (expand-file-name
-                                   (convert-standard-filename "~/%backup%~")))
+                            (setq backupname (expand-file-name "~/%backup%~"))
                             (message "Cannot write backup file; backing up in ~/%%backup%%~")
                             (sleep-for 1)
                             (condition-case ()
@@ -2028,7 +2015,6 @@ the value is \"\"."
 (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."
-  ;; FSF has code here for MS-DOS short filenames, not supported in XEmacs.
     (concat file "~"))
 
 (defun backup-file-name-p (file)
@@ -2056,7 +2042,6 @@ the index in the name where the version number begins."
 Value is a list whose car is the name for the backup file
  and whose cdr is a list of old versions to consider deleting now.
 If the value is nil, don't make a backup."
-  (declare (special bv-length))
   (let ((handler (find-file-name-handler fn 'find-backup-file-name)))
     ;; Run a handler for this function so that ange-ftp can refuse to do it.
     (if handler
@@ -2426,43 +2411,38 @@ Optional second argument EXITING means ask about certain non-file buffers
 ;; XEmacs - do not use queried flag
 (defun save-some-buffers-1 (arg exiting switch-buffer)
   (let* ((switched nil)
-        (last-buffer nil)
         (files-done
          (map-y-or-n-p
           (lambda (buffer)
-            (prog1
-                (and (buffer-modified-p buffer)
-                     (not (buffer-base-buffer buffer))
-                     ;; XEmacs addition:
-                     (not (symbol-value-in-buffer 'save-buffers-skip buffer))
-                     (or
-                      (buffer-file-name buffer)
-                      (and exiting
-                           (progn
-                             (set-buffer buffer)
-                             (and buffer-offer-save (> (buffer-size) 0)))))
-                     (if arg
-                         t
-                       ;; #### We should provide a per-buffer means to
-                       ;; disable the switching.  For instance, you might
-                       ;; want to turn it off for buffers the contents of
-                       ;; which is meaningless to humans, such as
-                       ;; `.newsrc.eld'.
-                       (when (and switch-buffer
-                                  ;; map-y-or-n-p is displaying help
-                                  (not (eq last-buffer buffer)))
-                         (unless (one-window-p)
-                           (delete-other-windows))
-                         (setq switched t)
-                         ;; #### Consider using `display-buffer' here for 21.1!
-                         ;;(display-buffer buffer nil (selected-frame)))
-                         (switch-to-buffer buffer t))
-                       (if (buffer-file-name buffer)
-                           (format "Save file %s? "
-                                   (buffer-file-name buffer))
-                         (format "Save buffer %s? "
-                                 (buffer-name buffer)))))
-              (setq last-buffer buffer)))
+            (and (buffer-modified-p buffer)
+                 (not (buffer-base-buffer buffer))
+                 ;; XEmacs addition:
+                 (not (symbol-value-in-buffer 'save-buffers-skip buffer))
+                 (or
+                  (buffer-file-name buffer)
+                  (and exiting
+                       (progn
+                         (set-buffer buffer)
+                         (and buffer-offer-save (> (buffer-size) 0)))))
+                 (if arg
+                     t
+                   ;; #### We should provide a per-buffer means to
+                   ;; disable the switching.  For instance, you might
+                   ;; want to turn it off for buffers the contents of
+                   ;; which is meaningless to humans, such as
+                   ;; `.newsrc.eld'.
+                   (when switch-buffer
+                     (unless (one-window-p)
+                       (delete-other-windows))
+                     (setq switched t)
+                     ;; #### Consider using `display-buffer' here for 21.1!
+                     ;;(display-buffer buffer nil (selected-frame)))
+                     (switch-to-buffer buffer t))
+                   (if (buffer-file-name buffer)
+                       (format "Save file %s? "
+                               (buffer-file-name buffer))
+                     (format "Save buffer %s? "
+                             (buffer-name buffer))))))
           (lambda (buffer)
             (set-buffer buffer)
             (condition-case ()
@@ -2642,9 +2622,7 @@ which are the arguments that `revert-buffer' received.")
 (defvar revert-buffer-insert-file-contents-function nil
   "Function to use to insert contents when reverting this buffer.
 Gets two args, first the nominal file name to use,
-and second, t if reading the auto-save file.
-If the current buffer contents are to be discarded, the function must do
-so itself.")
+and second, t if reading the auto-save file.")
 
 (defvar before-revert-hook nil
   "Normal hook for `revert-buffer' to run before reverting.
@@ -2669,10 +2647,10 @@ 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 refreshes certain 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.  This is
-implemented by having the modes set `revert-buffer-function'.
+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
@@ -2684,17 +2662,13 @@ Optional second argument NOCONFIRM means don't ask for confirmation at
 all.
 
 Optional third argument PRESERVE-MODES non-nil means don't alter
-the buffer's modes.  Otherwise, reinitialize them using `normal-mode'.
+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 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.
-
-If the buffer-modified flag is nil, and we are not reverting from an
-auto-save file, then compare the contents of the buffer and the file.
-Revert only if they differ."
+non-nil, it is called instead of rereading visited file contents."
 
   ;; 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
@@ -2706,9 +2680,6 @@ Revert only if they differ."
   (if revert-buffer-function
       (funcall revert-buffer-function ignore-auto noconfirm)
     (let* ((opoint (point))
-          (newbuf nil)
-          (found nil)
-          (delay-prompt nil)
           (auto-save-p (and (not ignore-auto)
                              (recent-auto-save-p)
                             buffer-auto-save-file-name
@@ -2722,114 +2693,62 @@ Revert only if they differ."
             (error "Buffer does not seem to be associated with any file"))
            ((or noconfirm
                 (and (not (buffer-modified-p))
-                     (dolist (rx revert-without-query found)
-                       (when (string-match rx file-name)
-                         (setq found t))))
-                ;; If we will call revert-buffer-internal, delay prompting
-                (and (not auto-save-p)
-                     (not (buffer-modified-p))
-                     (setq delay-prompt t))
+                     (let (found)
+                       (dolist (rx revert-without-query found)
+                         (when (string-match rx file-name)
+                           (setq found t)))))
                 (yes-or-no-p (format "Revert buffer from file %s? "
                                      file-name)))
             (run-hooks 'before-revert-hook)
-            (cond ((or auto-save-p
-                       (buffer-modified-p)
-                       ;; Do we need to do expensive reversion?  Compare ...
-                       (and (setq newbuf (revert-buffer-internal
-                                          file-name))
-                            ;; ... and if different, prompt
-                            (or noconfirm found
-                                (and delay-prompt
-                                     (yes-or-no-p 
-                                      (format "Revert buffer from file %s? "
-                                              file-name))))))
-                   ;; If file was backed up but has changed since,
-                   ;; we should make another backup.
-                   (and (not auto-save-p)
-                        (not (verify-visited-file-modtime (current-buffer)))
-                        (setq buffer-backed-up nil))
-                   ;; Get rid of all undo records for this buffer.
-                   (or (eq buffer-undo-list t)
-                       (setq buffer-undo-list nil))
-                   ;; Effectively copy the after-revert-hook status,
-                   ;; since after-find-file will clobber it.
-                   (let ((global-hook (default-value 'after-revert-hook))
-                         (local-hook-p (local-variable-p 'after-revert-hook
-                                                         (current-buffer)))
-                         (local-hook (and (local-variable-p 'after-revert-hook
-                                                            (current-buffer))
-                                          after-revert-hook)))
-                     (let (buffer-read-only
-                           ;; Don't make undo records for the reversion.
-                           (buffer-undo-list t))
-                       (if revert-buffer-insert-file-contents-function
-                           (funcall revert-buffer-insert-file-contents-function
-                                    file-name auto-save-p)
-                         (if (not (file-exists-p file-name))
-                             (error "File %s no longer exists!" file-name))
-                         ;; Bind buffer-file-name to nil
-                         ;; so that we don't try to lock the file.
-                         (let ((buffer-file-name nil))
-                           (or auto-save-p
-                               (unlock-buffer)))
-                         (widen)
-                         (insert-file-contents file-name (not auto-save-p)
-                                               nil nil t)))
-                     (goto-char (min opoint (point-max)))
-                     ;; Recompute the truename in case changes in symlinks
-                     ;; have changed the truename.
-                     ;;XEmacs: already done by insert-file-contents
-                     ;;(setq buffer-file-truename
-                     ;;(abbreviate-file-name (file-truename buffer-file-name)))
-                     (after-find-file nil nil t t preserve-modes)
-                     ;; Run after-revert-hook as it was before we reverted.
-                     (setq-default revert-buffer-internal-hook global-hook)
-                     (if local-hook-p
-                         (progn
-                           (make-local-variable 'revert-buffer-internal-hook)
-                           (setq revert-buffer-internal-hook local-hook))
-                       (kill-local-variable 'revert-buffer-internal-hook))
-                     (run-hooks 'revert-buffer-internal-hook)))
-                  ((null newbuf)
-                   ;; The resultant buffer is identical, alter
-                   ;; modtime, update mods and exit
-                   (set-visited-file-modtime)
-                   (after-find-file nil nil t t t))
-                  (t t))
+            ;; If file was backed up but has changed since,
+            ;; we should make another backup.
+            (and (not auto-save-p)
+                 (not (verify-visited-file-modtime (current-buffer)))
+                 (setq buffer-backed-up nil))
+            ;; Get rid of all undo records for this buffer.
+            (or (eq buffer-undo-list t)
+                (setq buffer-undo-list nil))
+            ;; Effectively copy the after-revert-hook status,
+            ;; since after-find-file will clobber it.
+            (let ((global-hook (default-value 'after-revert-hook))
+                  (local-hook-p (local-variable-p 'after-revert-hook
+                                                  (current-buffer)))
+                  (local-hook (and (local-variable-p 'after-revert-hook
+                                                     (current-buffer))
+                                   after-revert-hook)))
+              (let (buffer-read-only
+                    ;; Don't make undo records for the reversion.
+                    (buffer-undo-list t))
+                (if revert-buffer-insert-file-contents-function
+                    (funcall revert-buffer-insert-file-contents-function
+                             file-name auto-save-p)
+                  (if (not (file-exists-p file-name))
+                      (error "File %s no longer exists!" file-name))
+                  ;; Bind buffer-file-name to nil
+                  ;; so that we don't try to lock the file.
+                  (let ((buffer-file-name nil))
+                    (or auto-save-p
+                        (unlock-buffer)))
+                  (widen)
+                  (insert-file-contents file-name (not auto-save-p)
+                                        nil nil t)))
+              (goto-char (min opoint (point-max)))
+              ;; Recompute the truename in case changes in symlinks
+              ;; have changed the truename.
+              ;XEmacs: already done by insert-file-contents
+              ;;(setq buffer-file-truename
+                    ;;(abbreviate-file-name (file-truename buffer-file-name)))
+              (after-find-file nil nil t t preserve-modes)
+              ;; Run after-revert-hook as it was before we reverted.
+              (setq-default revert-buffer-internal-hook global-hook)
+              (if local-hook-p
+                  (progn
+                    (make-local-variable 'revert-buffer-internal-hook)
+                    (setq revert-buffer-internal-hook local-hook))
+                (kill-local-variable 'revert-buffer-internal-hook))
+              (run-hooks 'revert-buffer-internal-hook))
             t)))))
 
-;; #### something like `revert-buffer-compare-with-file' is a better name
-;; #### why is the argument optional?
-(defun revert-buffer-internal (&optional file-name)
-  "Read contents of FILE-NAME into a buffer, and compare to current buffer.
-Return nil if identical, and the new buffer if different."
-
-  (let* ((newbuf (get-buffer-create " *revert*"))
-        bmin bmax)
-    (save-excursion
-      (set-buffer newbuf)
-      (let (buffer-read-only
-           (buffer-undo-list t)
-           after-change-function
-           after-change-functions
-           before-change-function
-           before-change-functions)
-       (if revert-buffer-insert-file-contents-function
-           (funcall revert-buffer-insert-file-contents-function
-                    file-name nil)
-         (if (not (file-exists-p file-name))
-             (error "File %s no longer exists!" file-name))
-         (widen)
-         (insert-file-contents file-name nil nil nil t)
-         (setq bmin (point-min)
-               bmax (point-max)))))
-    (if (not (and (eq bmin (point-min))
-                 (eq bmax (point-max))
-                 (eq (compare-buffer-substrings 
-                      newbuf bmin bmax (current-buffer) bmin bmax) 0)))
-       newbuf
-      (and (kill-buffer newbuf) nil))))
-
 (defun recover-file (file)
   "Visit file FILE, but get contents from its last auto-save file."
   ;; Actually putting the file name in the minibuffer should be used
@@ -2844,7 +2763,7 @@ Return nil if identical, and the new buffer if different."
                     'recover-file))))
     (if handler
        (funcall handler 'recover-file file)
-      (if (auto-save-file-name-p (file-name-nondirectory file))
+      (if (auto-save-file-name-p file)
          (error "%s is an auto-save file" file))
       (let ((file-name (let ((buffer-file-name file))
                         (make-auto-save-file-name))))
@@ -2853,17 +2772,12 @@ Return nil if identical, and the new buffer if different."
                 (not (file-exists-p file-name)))
               (error "Auto-save file %s not current" file-name))
              ((save-window-excursion
-                ;; XEmacs change: use insert-directory instead of
-                ;; calling ls directly.
-                (with-output-to-temp-buffer "*Directory*"
-                  (buffer-disable-undo standard-output)
-                  (save-excursion
-                    (set-buffer "*Directory*")
-                    (setq default-directory (file-name-directory file))
-                    (insert-directory file
-                                      (if (file-symlink-p file) "-lL" "-l"))
-                    (setq default-directory (file-name-directory file-name))
-                    (insert-directory file-name "-l")))
+                (if (not (eq system-type 'windows-nt))
+                    (with-output-to-temp-buffer "*Directory*"
+                      (buffer-disable-undo standard-output)
+                      (call-process "ls" nil standard-output nil
+                                    (if (file-symlink-p file) "-lL" "-l")
+                                    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))
@@ -3029,9 +2943,72 @@ Also rename any existing auto save file, if it was made in this session."
             (recent-auto-save-p))
        (rename-file osave buffer-auto-save-file-name t))))
 
-;; make-auto-save-file-name and auto-save-file-name-p are now only in
-;; auto-save.el.
-
+;; see also ../packages/auto-save.el
+(defun make-auto-save-file-name (&optional filename)
+  "Return file name to use for auto-saves of current buffer.
+Does not consider `auto-save-visited-file-name' as that variable is checked
+before calling this function.  You can redefine this for customization.
+See also `auto-save-file-name-p'."
+  (let ((fname (or filename buffer-file-name))
+       name)
+    (setq name
+         (if fname
+             (concat (file-name-directory fname)
+                     "#"
+                     (file-name-nondirectory fname)
+                     "#")
+
+           ;; 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))
+             ;; Use technique from Sebastian Kremer's auto-save
+             ;; package to turn slashes into \\!.  This ensures that
+             ;; the auto-save buffer name is unique.
+
+             ;; #### - yuck!  yuck!  yuck!  move this functionality
+             ;; somewhere else and make the name translation customizable.
+             ;; Using "\!" as part of a filename on a UNIX filesystem is nearly
+             ;; IMPOSSIBLE to get past a shell parser.  -stig
+
+             (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))))
+
+             ;;    (expand-file-name (format "#%s#%s#" (buffer-name) (make-temp-name "")))
+
+             ;; jwz: putting the emacs PID in the auto-save file name
+             ;; is bad news, because that defeats auto-save-recovery of
+             ;; *mail* buffers -- the (sensible) code in sendmail.el
+             ;; calls (make-auto-save-file-name) to determine whether
+             ;; there is unsent, auto-saved mail to recover.  If that
+             ;; mail came from a previous emacs process (far and away
+             ;; the most likely case) then this can never succeed as
+             ;; the pid differs.
+
+             (expand-file-name (format "#%s#" buffer-name)))
+           ))
+    ;; don't try to write auto-save files in unwritable places.  Unless
+    ;; there's already an autosave file here, put ours somewhere safe. --Stig
+    (if (or (file-writable-p name)
+           (file-exists-p name))
+       name
+      (expand-file-name (concat "~/" (file-name-nondirectory name))))))
+
+(defun auto-save-file-name-p (filename)
+  "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
+FILENAME should lack slashes.
+You can redefine this for customization."
+  (string-match "\\`#.*#\\'" filename))
 \f
 (defun wildcard-to-regexp (wildcard)
   "Given a shell file name pattern WILDCARD, return an equivalent regexp.
@@ -3175,9 +3152,8 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
        (funcall handler 'insert-directory file switches
                 wildcard full-directory-p)
       (cond
-       ;; [mswindows-insert-directory should be called
-       ;; nt-insert-directory - kkm].  not true any more according to
-       ;; my new naming scheme. --ben
+       ;; #### mswindows-insert-directory should be called
+       ;; nt-insert-directory - kkm.
        ((and (fboundp 'mswindows-insert-directory)
             (eq system-type 'windows-nt))
        (mswindows-insert-directory file switches wildcard full-directory-p))