(tex-command-end): New variable.
[bpt/emacs.git] / lisp / files.el
index f12606e..1fde283 100644 (file)
@@ -1,7 +1,7 @@
 ;;; files.el --- file input and output commands for Emacs
 
 ;; Copyright (C) 1985, 86, 87, 92, 93,
-;;              94, 95, 1996 Free Software Foundation, Inc.
+;;              94, 95, 96, 97, 1998 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 
 
 
 (defcustom delete-auto-save-files t
-  "*Non-nil means delete auto-save file when a buffer is saved or killed."
+  "*Non-nil means delete auto-save file when a buffer is saved or killed.
+
+Note that auto-save file will not be deleted if the buffer is killed
+when it has unsaved changes."
   :type 'boolean
   :group 'auto-save)
 
@@ -153,7 +156,7 @@ The value is a list of regular expressions.
 If the file name matches one of these regular expressions,
 then `revert-buffer' reverts the file without querying
 if the file has changed on disk and you have not edited the buffer."
-  :type 'boolean
+  :type '(repeat regexp)
   :group 'find-file)
 
 (defvar buffer-file-number nil
@@ -340,6 +343,16 @@ and ignores this variable."
 (defvar view-read-only nil
   "*Non-nil means buffers visiting files read-only, do it in view mode.")
 
+(defvar system-tmp-directory
+  (directory-file-name 
+   (cond ((memq system-type '(ms-dos windows-nt))
+         (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
+        ((memq system-type '(vax-vms axp-vms))
+         (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "SYS$SCRATCH:"))
+        (t
+         (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
+  "The directory for writing temporary files--actually, its name as a file.")
+
 ;; This hook function provides support for ange-ftp host name
 ;; completion.  It runs the usual ange-ftp hook, but only for
 ;; completion operations.  Having this here avoids the need
@@ -370,9 +383,6 @@ with a definition that really does change some file names."
   "Value of the CDPATH environment variable, as a list.
 Not actually set up until the first time you you use it.")
 
-(defvar path-separator ":"
-  "Character used to separate directories in search paths.")
-
 (defun parse-colon-path (cd-path)
   "Explode a colon-separated search path into a list of directory names."
   (and cd-path
@@ -914,11 +924,21 @@ Optional second arg RAWFILE non-nil means the file is read literally."
              (condition-case ()
                  (insert-file-contents-literally filename t)
                (file-error
+                (when (and (file-exists-p filename)
+                           (not (file-readable-p filename)))
+                  (kill-buffer buf)
+                  (signal 'file-error (list "File is not readable"
+                                            filename)))
                 ;; Unconditionally set error
                 (setq error t)))
            (condition-case ()
                (insert-file-contents filename t)
              (file-error
+              (when (and (file-exists-p filename)
+                         (not (file-readable-p filename)))
+                (kill-buffer buf)
+                (signal 'file-error (list "File is not readable"
+                                          filename)))
               ;; Run find-file-not-found-hooks until one returns non-nil.
               (or (run-hook-with-args-until-success 'find-file-not-found-hooks)
                   ;; If they fail too, set error.
@@ -949,7 +969,8 @@ Optional second arg RAWFILE non-nil means the file is read literally."
                 (setq backup-inhibited t)))
          (if rawfile
              (progn
-               (setq enable-multibyte-characters nil)
+               (set-buffer-multibyte nil)
+               (setq buffer-file-coding-system 'no-conversion)
                (make-local-variable 'find-file-literally)
                (setq find-file-literally t))
            (after-find-file error (not nowarn))
@@ -1118,8 +1139,7 @@ run `normal-mode' explicitly."
     ("\\.p\\'" . pascal-mode)
     ("\\.pas\\'" . pascal-mode)
     ("\\.ad[abs]\\'" . ada-mode)
-    ("\\.pl\\'" . perl-mode)
-    ("\\.pm\\'" . perl-mode)
+    ("\\.\\([pP][Llm]\\|al\\)\\'" . perl-mode)
     ("\\.s?html?\\'" . html-mode)
     ("\\.cc\\'" . c++-mode)
     ("\\.hh\\'" . c++-mode)
@@ -1135,6 +1155,7 @@ run `normal-mode' explicitly."
     ("\\.java\\'" . java-mode)
     ("\\.mk\\'" . makefile-mode)
     ("\\(M\\|m\\|GNUm\\)akefile\\(.in\\)?\\'" . makefile-mode)
+    ("\\.am\\'" . makefile-mode)       ;For Automake.
 ;;; Less common extensions come here
 ;;; so more common ones above are found faster.
     ("\\.texinfo\\'" . texinfo-mode)
@@ -1169,6 +1190,7 @@ run `normal-mode' explicitly."
     ("\\.mc\\'" . m4-mode)
     ("\\.mf\\'" . metafont-mode)
     ("\\.mp\\'" . metapost-mode)
+    ("\\.vhdl?\\'" . vhdl-mode)
     ("\\.article\\'" . text-mode)
     ("\\.letter\\'" . text-mode)
     ("\\.tcl\\'" . tcl-mode)
@@ -1190,6 +1212,7 @@ run `normal-mode' explicitly."
     ("\\`/tmp/Re" . text-mode)
     ("/Message[0-9]*\\'" . text-mode)
     ("/drafts/[0-9]+\\'" . mh-letter-mode)
+    ("\\.zone\\'" . zone-mode)
     ;; some news reader is reported to use this
     ("\\`/tmp/fol/" . text-mode)
     ("\\.y\\'" . c-mode)
@@ -1216,9 +1239,11 @@ 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.")
 
+
 (defvar interpreter-mode-alist
   '(("perl" . perl-mode)
     ("perl5" . perl-mode)
+    ("miniperl" . perl-mode)
     ("wish" . tcl-mode)
     ("wishx" . tcl-mode)
     ("tcl" . tcl-mode)
@@ -1376,7 +1401,13 @@ and we don't even do that unless it would come from the file name."
                              keep-going nil)))
                  (setq alist (cdr alist))))
              (if mode
-                 (funcall mode)
+                 ;; When JUST-FROM-FILE-NAME is set,
+                 ;; we are working on behalf of set-visited-file-name.
+                 ;; In that case, if the major mode specified is the
+                 ;; same one we already have, don't actually reset it.
+                 ;; We don't want to lose minor modes such as Font Lock.
+                 (unless (and just-from-file-name (eq mode major-mode))
+                   (funcall mode))
                ;; If we can't deduce a mode from the file name,
                ;; look for an interpreter specified in the first line.
                ;; As a special case, allow for things like "#!/bin/env perl",
@@ -1599,7 +1630,7 @@ is specified, returning t if it is specified."
        ;; Likewise for setting hook variables.
        ((or (get var 'risky-local-variable)
             (and
-             (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$"
+             (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$\\|-predicate$"
                            (symbol-name var))
              (not (get var 'safe-local-variable))))
         ;; Permit evalling a put of a harmless property.
@@ -1720,7 +1751,8 @@ the old visited file has been renamed to the new name FILENAME."
   (kill-local-variable 'vc-mode)
   ;; Turn off backup files for certain file names.
   ;; Since this is a permanent local, the major mode won't eliminate it.
-  (and (not (funcall backup-enable-predicate buffer-file-name))
+  (and buffer-file-name
+       (not (funcall backup-enable-predicate buffer-file-name))
        (progn
         (make-local-variable 'backup-inhibited)
         (setq backup-inhibited t)))
@@ -1771,7 +1803,7 @@ Interactively, confirmation is required unless you supply a prefix argument."
           (read-file-name "Write file: "
                               (cdr (assq 'default-directory
                                          (buffer-local-variables)))
-                              nil nil (buffer-name)))
+                              nil nil (file-name-nondirectory (buffer-name))))
         (not current-prefix-arg)))
   (or (null filename) (string-equal filename "")
       (progn
@@ -1786,6 +1818,10 @@ Interactively, confirmation is required unless you supply a prefix argument."
                 (error "Canceled")))
        (set-visited-file-name filename (not confirm))))
   (set-buffer-modified-p t)
+  ;; Make buffer writable if file is writable.
+  (and buffer-file-name
+       (file-writable-p buffer-file-name)
+       (setq buffer-read-only nil))
   (save-buffer))
 \f
 (defun backup-buffer ()
@@ -2121,11 +2157,19 @@ the last real save, but optional arg FORCE non-nil means delete anyway."
 (defvar after-save-hook nil
   "Normal hook that is run after a buffer is saved to its file.")
 
+(defvar save-buffer-coding-system nil
+  "If non-nil, use this coding system for saving the buffer.
+More precisely, use this coding system in place of the
+value of `buffer-file-coding-system', when saving the buffer.
+Calling `write-region' for any purpose other than saving the buffer
+will still use `buffer-file-coding-system'; this variable has no effect
+in such cases.")
+
 (defun basic-save-buffer ()
   "Save the current buffer in its visited file, if it has been modified.
 After saving the buffer, run `after-save-hook'."
   (interactive)
-  (save-excursion
+  (save-current-buffer
     ;; In an indirect buffer, save its base buffer instead.
     (if (buffer-base-buffer)
        (set-buffer (buffer-base-buffer)))
@@ -2163,24 +2207,31 @@ After saving the buffer, run `after-save-hook'."
              (error "Save not confirmed"))
          (save-restriction
            (widen)
-           (and (> (point-max) 1)
-                (/= (char-after (1- (point-max))) ?\n)
-                (not (and (eq selective-display t)
-                          (= (char-after (1- (point-max))) ?\r)))
-                (or (eq require-final-newline t)
-                    (and require-final-newline
-                         (y-or-n-p
-                          (format "Buffer %s does not end in newline.  Add one? "
-                                  (buffer-name)))))
-                (save-excursion
-                  (goto-char (point-max))
-                  (insert ?\n)))
+           (save-excursion
+             (and (> (point-max) 1)
+                  (/= (char-after (1- (point-max))) ?\n)
+                  (not (and (eq selective-display t)
+                            (= (char-after (1- (point-max))) ?\r)))
+                  (or (eq require-final-newline t)
+                      (and require-final-newline
+                           (y-or-n-p
+                            (format "Buffer %s does not end in newline.  Add one? "
+                                    (buffer-name)))))
+                  (save-excursion
+                    (goto-char (point-max))
+                    (insert ?\n))))
            (or (run-hook-with-args-until-success 'write-contents-hooks)
                (run-hook-with-args-until-success 'local-write-file-hooks)
                (run-hook-with-args-until-success 'write-file-hooks)
                ;; If a hook returned t, file is already "written".
                ;; Otherwise, write it the usual way now.
                (setq setmodes (basic-save-buffer-1)))
+           ;; Now we have saved the current buffer.  Let's make sure
+           ;; that buffer-file-coding-system is fixed to what
+           ;; actually used for saving by binding it locally.
+           (if save-buffer-coding-system
+               (setq save-buffer-coding-system last-coding-system-used)
+             (setq buffer-file-coding-system last-coding-system-used))
            (setq buffer-file-number
                  (nthcdr 10 (file-attributes buffer-file-name)))
            (if setmodes
@@ -2200,7 +2251,10 @@ After saving the buffer, run `after-save-hook'."
 ;; but inhibited if one of write-file-hooks returns non-nil.
 ;; It returns a value to store in setmodes.
 (defun basic-save-buffer-1 ()
-  (let (tempsetmodes setmodes)
+  (let ((buffer-file-coding-system
+        (or save-buffer-coding-system
+            buffer-file-coding-system))
+       tempsetmodes setmodes)
     (if (not (file-writable-p buffer-file-name))
        (let ((dir (file-name-directory buffer-file-name)))
          (if (not (file-directory-p dir))
@@ -2401,20 +2455,16 @@ This function is useful for creating multiple shell process buffers
 or multiple mail buffers, etc."
   (interactive)
   (save-match-data
-    (let* ((base-name (if (and (string-match "<[0-9]+>\\'" (buffer-name))
-                              (not (and buffer-file-name
-                                        (string= (buffer-name)
-                                                 (file-name-nondirectory
-                                                  buffer-file-name)))))
-                         ;; If the existing buffer name has a <NNN>,
-                         ;; which isn't part of the file name (if any),
-                         ;; then get rid of that.
-                         (substring (buffer-name) 0 (match-beginning 0))
-                       (buffer-name)))
-          (new-buf (generate-new-buffer base-name))
-          (name (buffer-name new-buf)))
-      (kill-buffer new-buf)
-      (rename-buffer name)
+    (let ((base-name (buffer-name)))
+      (and (string-match "<[0-9]+>\\'" base-name)
+          (not (and buffer-file-name
+                    (string= base-name
+                             (file-name-nondirectory buffer-file-name))))
+          ;; If the existing buffer name has a <NNN>,
+          ;; which isn't part of the file name (if any),
+          ;; then get rid of that.
+          (setq base-name (substring base-name 0 (match-beginning 0))))
+      (rename-buffer (generate-new-buffer-name base-name))
       (force-mode-line-update))))
 
 (defun make-directory (dir &optional parents)
@@ -2645,6 +2695,7 @@ This command is used in the special Dired buffer created by
   (let ((file (dired-get-filename))
        files
        (buffer (get-buffer-create " *recover*")))
+    (dired-unmark 1)
     (dired-do-flagged-delete t)
     (unwind-protect
        (save-excursion
@@ -2964,61 +3015,68 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
                 wildcard full-directory-p)
       (if (eq system-type 'vax-vms)
          (vms-read-directory file switches (current-buffer))
-       (or (= 0
-              (if wildcard
-                  ;; Run ls in the directory of the file pattern we asked for.
-                  (let ((default-directory
-                          (if (file-name-absolute-p file)
-                              (file-name-directory file)
-                            (file-name-directory (expand-file-name file))))
-                        (pattern (file-name-nondirectory file))
-                        (beg 0))
-                    ;; Quote some characters that have special meanings in shells;
-                    ;; but don't quote the wildcards--we want them to be special.
-                    ;; We also currently don't quote the quoting characters
-                    ;; in case people want to use them explicitly to quote
-                    ;; wildcard characters.
-                    (while (string-match "[ \t\n;<>&|()#$]" pattern beg)
-                      (setq pattern
-                            (concat (substring pattern 0 (match-beginning 0))
-                                    "\\"
-                                    (substring pattern (match-beginning 0)))
-                            beg (1+ (match-end 0))))
-                    (call-process shell-file-name nil t nil
-                                  "-c" (concat "\\"  ;; Disregard shell aliases!
-                                               insert-directory-program
-                                               " -d "
-                                               (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.
-                (apply 'call-process
-                       insert-directory-program nil t nil
-                       (let (list)
-                         (if (listp switches)
-                             (setq list switches)
-                           (if (not (equal switches ""))
-                               (progn
-                                 ;; Split the switches at any spaces
-                                 ;; so we can pass separate options as separate args.
-                                 (while (string-match " " switches)
-                                   (setq list (cons (substring switches 0 (match-beginning 0))
-                                                    list)
-                                         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) ".")
-                                    file)))))))
-           ;; We get here if ls failed.
-           ;; Access the file to get a suitable error.
-           (access-file file "Reading directory"))))))
+       (let* ((coding-system-for-read
+               (and enable-multibyte-characters
+                    (or file-name-coding-system
+                        default-file-name-coding-system)))
+              ;; This binding is for encoding arguements by call-process.
+              (coding-system-for-write coding-system-for-read)
+              (result
+               (if wildcard
+                   ;; Run ls in the directory of the file pattern we asked for.
+                   (let ((default-directory
+                           (if (file-name-absolute-p file)
+                               (file-name-directory file)
+                             (file-name-directory (expand-file-name file))))
+                         (pattern (file-name-nondirectory file))
+                         (beg 0))
+                     ;; Quote some characters that have special meanings in shells;
+                     ;; but don't quote the wildcards--we want them to be special.
+                     ;; We also currently don't quote the quoting characters
+                     ;; in case people want to use them explicitly to quote
+                     ;; wildcard characters.
+                     (while (string-match "[ \t\n;<>&|()#$]" pattern beg)
+                       (setq pattern
+                             (concat (substring pattern 0 (match-beginning 0))
+                                     "\\"
+                                     (substring pattern (match-beginning 0)))
+                             beg (1+ (match-end 0))))
+                     (call-process shell-file-name nil t nil
+                                   "-c" (concat "\\";; Disregard shell aliases!
+                                                insert-directory-program
+                                                " -d "
+                                                (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.
+                 (apply 'call-process
+                         insert-directory-program nil t nil
+                         (let (list)
+                           (if (listp switches)
+                               (setq list switches)
+                             (if (not (equal switches ""))
+                                 (progn
+                                   ;; Split the switches at any spaces
+                                   ;; so we can pass separate options as separate args.
+                                   (while (string-match " " switches)
+                                     (setq list (cons (substring switches 0 (match-beginning 0))
+                                                      list)
+                                           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) ".")
+                                      file))))))))
+         (if (/= result 0)
+             ;; We get here if ls failed.
+             ;; Access the file to get a suitable error.
+             (access-file file "Reading directory")))))))
 
 (defvar kill-emacs-query-functions nil
   "Functions to call with no arguments to query about killing Emacs.
@@ -3068,6 +3126,12 @@ With prefix arg, silently save all file-visiting buffers, then kill."
 
 (defun file-name-non-special (operation &rest arguments)
   (let ((file-name-handler-alist nil)
+       (default-directory
+         (if (eq operation 'insert-directory)
+             (directory-file-name
+              (expand-file-name 
+               (unhandled-file-name-directory default-directory)))
+           default-directory))
        ;; Get a list of the indices of the args which are file names.
        (file-arg-indices
         (cdr (or (assq operation
@@ -3096,10 +3160,13 @@ With prefix arg, silently save all file-visiting buffers, then kill."
     ;; Strip off the /: from the file names that have this handler.
     (save-match-data
       (while (consp 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)))
+       (let ((pair (nthcdr (car file-arg-indices) arguments)))
+         (and (car pair)
+              (string-match "\\`/:" (car pair))
+              (setcar pair
+                      (if (= (length (car pair)) 2)
+                          "/"
+                        (substring (car pair) 2)))))
        (setq file-arg-indices (cdr file-arg-indices))))
     (if (eq file-arg-indices 'identity)
        (car arguments)