]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
*** empty log message ***
[gnu-emacs] / src / fileio.c
index 71036912bbcb1254a3bbfe76eb0af5110c76391f..7f73a55bce906abc742a6fc75bf176634b62e9c4 100644 (file)
@@ -1,6 +1,6 @@
 /* File IO for GNU Emacs.
-   Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000, 2001
-     Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998,
+     1999, 2000, 2001, 2003, 2004  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -134,6 +134,7 @@ extern int errno;
 
 #include "commands.h"
 extern int use_dialog_box;
+extern int use_file_dialog;
 
 #ifndef O_WRONLY
 #define O_WRONLY 1
@@ -147,6 +148,10 @@ extern int use_dialog_box;
 #  define lstat stat
 #endif
 
+#ifndef FILE_SYSTEM_CASE
+#define FILE_SYSTEM_CASE(filename)  (filename)
+#endif
+
 /* Nonzero during writing of auto-save files */
 int auto_saving;
 
@@ -154,6 +159,13 @@ int auto_saving;
    a new file with the same mode as the original */
 int auto_save_mode_bits;
 
+/* The symbol bound to coding-system-for-read when
+   insert-file-contents is called for recovering a file.  This is not
+   an actual coding system name, but just an indicator to tell
+   insert-file-contents to use `emacs-mule' with a special flag for
+   auto saving and recovering a file.  */
+Lisp_Object Qauto_save_coding;
+
 /* Coding system for file names, or nil if none.  */
 Lisp_Object Vfile_name_coding_system;
 
@@ -165,9 +177,6 @@ Lisp_Object Vdefault_file_name_coding_system;
    whose I/O is done with a special handler.  */
 Lisp_Object Vfile_name_handler_alist;
 
-/* Format for auto-save files */
-Lisp_Object Vauto_save_file_format;
-
 /* Lisp functions for translating file formats */
 Lisp_Object Qformat_decode, Qformat_annotate_function;
 
@@ -198,6 +207,9 @@ Lisp_Object Vread_file_name_function;
 /* Current predicate used by read_file_name_internal.  */
 Lisp_Object Vread_file_name_predicate;
 
+/* Nonzero means completion ignores case when reading file name.  */
+int read_file_name_completion_ignore_case;
+
 /* Nonzero means, when reading a filename in the minibuffer,
  start out by inserting the default directory into the minibuffer. */
 int insert_default_directory;
@@ -220,6 +232,8 @@ extern int minibuf_level;
 
 extern int minibuffer_auto_raise;
 
+extern int history_delete_duplicates;
+
 /* These variables describe handlers that have "already" had a chance
    to handle the current operation.
 
@@ -315,6 +329,7 @@ Lisp_Object Qfile_regular_p;
 Lisp_Object Qfile_accessible_directory_p;
 Lisp_Object Qfile_modes;
 Lisp_Object Qset_file_modes;
+Lisp_Object Qset_file_times;
 Lisp_Object Qfile_newer_than_file_p;
 Lisp_Object Qinsert_file_contents;
 Lisp_Object Qwrite_region;
@@ -402,9 +417,7 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_name_directory, filename);
 
-#ifdef FILE_SYSTEM_CASE
   filename = FILE_SYSTEM_CASE (filename);
-#endif
   beg = SDATA (filename);
 #ifdef DOS_NT
   beg = strcpy (alloca (strlen (beg) + 1), beg);
@@ -874,7 +887,7 @@ make_temp_name (prefix, base64_p)
      int base64_p;
 {
   Lisp_Object val;
-  int len;
+  int len, clen;
   int pid;
   unsigned char *p, *data;
   char pidbuf[20];
@@ -909,8 +922,10 @@ make_temp_name (prefix, base64_p)
 #endif
     }
 
-  len = SCHARS (prefix);
-  val = make_uninit_string (len + 3 + pidlen);
+  len = SBYTES (prefix); clen = SCHARS (prefix);
+  val = make_uninit_multibyte_string (clen + 3 + pidlen, len + 3 + pidlen);
+  if (!STRING_MULTIBYTE (prefix))
+    STRING_SET_UNIBYTE (val);
   data = SDATA (val);
   bcopy(SDATA (prefix), data, len);
   p = data + len;
@@ -1107,14 +1122,7 @@ See also the function `substitute-in-file-name'.  */)
       UNGCPRO;
     }
 
-#ifdef VMS
-  /* Filenames on VMS are always upper case.  */
-  name = Fupcase (name);
-#endif
-#ifdef FILE_SYSTEM_CASE
   name = FILE_SYSTEM_CASE (name);
-#endif
-
   nm = SDATA (name);
 
 #ifdef DOS_NT
@@ -1214,23 +1222,23 @@ See also the function `substitute-in-file-name'.  */)
            slash = p;
          }
          if (p[0] == '-')
-#ifndef VMS4_4
-           /* VMS pre V4.4,convert '-'s in filenames. */
+#ifdef NO_HYPHENS_IN_FILENAMES
            if (lbrack == rbrack)
              {
-               if (dots < 2)   /* this is to allow negative version numbers */
+                /* Avoid clobbering negative version numbers.  */
+                if (dots < 2)
                  p[0] = '_';
              }
            else
-#endif /* VMS4_4 */
+#endif /* NO_HYPHENS_IN_FILENAMES */
              if (lbrack > rbrack &&
                  ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
                   (p[1] == '.' || p[1] == ']' || p[1] == '>')))
                lose = 1;
-#ifndef VMS4_4
+#ifdef NO_HYPHENS_IN_FILENAMES
              else
                p[0] = '_';
-#endif /* VMS4_4 */
+#endif /* NO_HYPHENS_IN_FILENAMES */
          /* count open brackets, reset close bracket pointer */
          if (p[0] == '[' || p[0] == '<')
            lbrack++, brack = 0;
@@ -1610,12 +1618,12 @@ See also the function `substitute-in-file-name'.  */)
        }
       else
        {
-#ifndef VMS4_4
+#ifdef NO_HYPHENS_IN_FILENAMES
          if (*p == '-' &&
              o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
              p[1] != ']' && p[1] != '>' && p[1] != '.')
            *p = '_';
-#endif /* VMS4_4 */
+#endif /* NO_HYPHENS_IN_FILENAMES */
          *o++ = *p++;
        }
 #else /* not VMS */
@@ -2340,7 +2348,7 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
 
   /* stat is a good way to tell whether the file exists,
      regardless of what access permissions it has.  */
-  if (stat (SDATA (encoded_filename), &statbuf) >= 0)
+  if (lstat (SDATA (encoded_filename), &statbuf) >= 0)
     {
       if (! interactive)
        Fsignal (Qfile_already_exists,
@@ -2377,7 +2385,8 @@ Signals a `file-already-exists' error if file NEWNAME already exists,
 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
 A number as third arg means request confirmation if NEWNAME already exists.
 This is what happens in interactive use with M-x.
-Fourth arg KEEP-TIME non-nil means give the new file the same
+Always sets the file modes of the output file to match the input file.
+Fourth arg KEEP-TIME non-nil means give the output file the same
 last-modified time as the old one.  (This works on only some systems.)
 A prefix arg makes KEEP-TIME non-nil.  */)
      (file, newname, ok_if_already_exists, keep_time)
@@ -2398,7 +2407,7 @@ A prefix arg makes KEEP-TIME non-nil.  */)
   CHECK_STRING (newname);
 
   if (!NILP (Ffile_directory_p (newname)))
-    newname = Fexpand_file_name (file, newname);
+    newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
   else
     newname = Fexpand_file_name (newname, Qnil);
 
@@ -2623,7 +2632,8 @@ If file has multiple names, it continues to exist with the other names.  */)
   struct gcpro gcpro1;
 
   GCPRO1 (filename);
-  if (!NILP (Ffile_directory_p (filename)))
+  if (!NILP (Ffile_directory_p (filename))
+      && NILP (Ffile_symlink_p (filename)))
     Fsignal (Qfile_error,
             Fcons (build_string ("Removing old name: is a directory"),
                    Fcons (filename, Qnil)));
@@ -2673,11 +2683,11 @@ This is what happens in interactive use with M-x.  */)
   Lisp_Object args[2];
 #endif
   Lisp_Object handler;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  Lisp_Object encoded_file, encoded_newname;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  Lisp_Object encoded_file, encoded_newname, symlink_target;
 
-  encoded_file = encoded_newname = Qnil;
-  GCPRO4 (file, newname, encoded_file, encoded_newname);
+  symlink_target = encoded_file = encoded_newname = Qnil;
+  GCPRO5 (file, newname, encoded_file, encoded_newname, symlink_target);
   CHECK_STRING (file);
   CHECK_STRING (newname);
   file = Fexpand_file_name (file, Qnil);
@@ -2714,10 +2724,17 @@ This is what happens in interactive use with M-x.  */)
     {
       if (errno == EXDEV)
        {
-         Fcopy_file (file, newname,
-                     /* We have already prompted if it was an integer,
-                        so don't have copy-file prompt again.  */
-                     NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
+#ifdef S_IFLNK
+          symlink_target = Ffile_symlink_p (file);
+          if (! NILP (symlink_target))
+            Fmake_symbolic_link (symlink_target, newname,
+                                 NILP (ok_if_already_exists) ? Qnil : Qt);
+          else
+#endif
+            Fcopy_file (file, newname,
+                        /* We have already prompted if it was an integer,
+                           so don't have copy-file prompt again.  */
+                        NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
          Fdelete_file (file);
        }
       else
@@ -3192,11 +3209,6 @@ Otherwise returns nil.  */)
      (filename)
      Lisp_Object filename;
 {
-#ifdef S_IFLNK
-  char *buf;
-  int bufsize;
-  int valsize;
-  Lisp_Object val;
   Lisp_Object handler;
 
   CHECK_STRING (filename);
@@ -3208,6 +3220,13 @@ Otherwise returns nil.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_symlink_p, filename);
 
+#ifdef S_IFLNK
+  {
+  char *buf;
+  int bufsize;
+  int valsize;
+  Lisp_Object val;
+
   filename = ENCODE_FILE (filename);
 
   bufsize = 50;
@@ -3242,6 +3261,7 @@ Otherwise returns nil.  */)
   xfree (buf);
   val = DECODE_FILE (val);
   return val;
+  }
 #else /* not S_IFLNK */
   return Qnil;
 #endif /* not S_IFLNK */
@@ -3343,7 +3363,8 @@ This is the sort of file that holds an ordinary stream of data bytes.  */)
 }
 \f
 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
-       doc: /* Return mode bits of file named FILENAME, as an integer.  */)
+       doc: /* Return mode bits of file named FILENAME, as an integer.
+Return nil, if file does not exist or is not accessible.  */)
      (filename)
      Lisp_Object filename;
 {
@@ -3425,7 +3446,59 @@ The value is an integer.  */)
   XSETINT (value, (~ realmask) & 0777);
   return value;
 }
+\f
+extern int lisp_time_argument P_ ((Lisp_Object, time_t *, int *));
+
+DEFUN ("set-file-times", Fset_file_times, Sset_file_times, 1, 2, 0,
+       doc: /* Set times of file FILENAME to TIME.
+Set both access and modification times.
+Return t on success, else nil.
+Use the current time if TIME is nil.  TIME is in the format of
+`current-time'. */)
+  (filename, time)
+     Lisp_Object filename, time;
+{
+  Lisp_Object absname, encoded_absname;
+  Lisp_Object handler;
+  time_t sec;
+  int usec;
+
+  if (! lisp_time_argument (time, &sec, &usec))
+    error ("Invalid time specification");
+
+  absname = Fexpand_file_name (filename, current_buffer->directory);
+
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (absname, Qset_file_times);
+  if (!NILP (handler))
+    return call3 (handler, Qset_file_times, absname, time);
+
+  encoded_absname = ENCODE_FILE (absname);
+
+  {
+    EMACS_TIME t;
+
+    EMACS_SET_SECS (t, sec);
+    EMACS_SET_USECS (t, usec);
+
+    if (set_file_times (SDATA (encoded_absname), t, t))
+      {
+#ifdef DOS_NT
+        struct stat st;
+
+        /* Setting times on a directory always fails.  */
+        if (stat (SDATA (encoded_absname), &st) == 0
+            && (st.st_mode & S_IFMT) == S_IFDIR)
+          return Qnil;
+#endif
+        report_file_error ("Setting file times", Fcons (absname, Qnil));
+        return Qnil;
+      }
+  }
 
+  return Qt;
+}
 \f
 #ifdef __NetBSD__
 #define unix 42
@@ -3760,7 +3833,20 @@ actually used.  */)
        }
     }
 
-  if (BEG < Z)
+  if (EQ (Vcoding_system_for_read, Qauto_save_coding))
+    {
+      /* We use emacs-mule for auto saving... */
+      setup_coding_system (Qemacs_mule, &coding);
+      /* ... but with the special flag to indicate to read in a
+        multibyte sequence for eight-bit-control char as is.  */
+      coding.flags = 1;
+      coding.src_multibyte = 0;
+      coding.dst_multibyte
+       = !NILP (current_buffer->enable_multibyte_characters);
+      coding.eol_type = CODING_EOL_LF;
+      coding_system_decided = 1;
+    }
+  else if (BEG < Z)
     {
       /* Decide the coding system to use for reading the file now
          because we can't use an optimized method for handling
@@ -3770,10 +3856,6 @@ actually used.  */)
 
       if (!NILP (Vcoding_system_for_read))
        val = Vcoding_system_for_read;
-      else if (! NILP (replace))
-       /* In REPLACE mode, we can use the same coding system
-          that was used to visit the file.  */
-       val = current_buffer->buffer_file_coding_system;
       else
        {
          /* Don't try looking inside a file for a coding system
@@ -3815,12 +3897,13 @@ actually used.  */)
                  buffer = Fget_buffer_create (build_string (" *code-converting-work*"));
                  buf = XBUFFER (buffer);
 
+                 delete_all_overlays (buf);
                  buf->directory = current_buffer->directory;
                  buf->read_only = Qnil;
                  buf->filename = Qnil;
                  buf->undo_list = Qt;
-                 buf->overlays_before = Qnil;
-                 buf->overlays_after = Qnil;
+                 eassert (buf->overlays_before == NULL);
+                 eassert (buf->overlays_after == NULL);
 
                  set_buffer_internal (buf);
                  Ferase_buffer ();
@@ -4171,7 +4254,7 @@ actually used.  */)
       if (how_much < 0)
        {
          xfree (conversion_buffer);
-
+         coding_free_composition_data (&coding);
          if (how_much == -1)
            error ("IO error reading %s: %s",
                   SDATA (orig_filename), emacs_strerror (errno));
@@ -4193,6 +4276,7 @@ actually used.  */)
       if (bufpos == inserted)
        {
          xfree (conversion_buffer);
+         coding_free_composition_data (&coding);
          emacs_close (fd);
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
@@ -4238,7 +4322,7 @@ actually used.  */)
       /* Replace the chars that we need to replace,
         and update INSERTED to equal the number of bytes
         we are taking from the file.  */
-      inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
+      inserted -= (ZV_BYTE - same_at_end) + (same_at_start - BEGV_BYTE);
 
       if (same_at_end != same_at_start)
        {
@@ -4252,7 +4336,7 @@ actually used.  */)
        }
       /* Insert from the file at the proper position.  */
       SET_PT_BOTH (temp, same_at_start);
-      insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
+      insert_1 (conversion_buffer + same_at_start - BEGV_BYTE, inserted,
                0, 0, 0);
       if (coding.cmp_data && coding.cmp_data->used)
        coding_restore_composition (&coding, Fcurrent_buffer ());
@@ -4550,7 +4634,8 @@ actually used.  */)
 
   if (! NILP (Ffboundp (Qafter_insert_file_set_coding)))
     {
-      insval = call1 (Qafter_insert_file_set_coding, make_number (inserted));
+      insval = call2 (Qafter_insert_file_set_coding, make_number (inserted),
+                     visit);
       if (! NILP (insval))
        {
          CHECK_NUMBER (insval);
@@ -4658,8 +4743,17 @@ choose_write_coding_system (start, end, filename,
 {
   Lisp_Object val;
 
-  if (auto_saving)
-    val = Qnil;
+  if (auto_saving
+      && NILP (Fstring_equal (current_buffer->filename,
+                             current_buffer->auto_save_file_name)))
+    {
+      /* We use emacs-mule for auto saving... */
+      setup_coding_system (Qemacs_mule, coding);
+      /* ... but with the special flag to indicate not to strip off
+        leading code of eight-bit-control chars.  */
+      coding->flags = 1;
+      goto done_setup_coding;
+    }
   else if (!NILP (Vcoding_system_for_write))
     {
       val = Vcoding_system_for_write;
@@ -4767,7 +4861,7 @@ instead of any buffer contents; END is ignored.
 Optional fourth argument APPEND if non-nil means
   append to existing file contents (if any).  If it is an integer,
   seek to that offset in the file before writing.
-Optional fifth argument VISIT if t means
+Optional fifth argument VISIT, if t or a string, means
   set the last-save-file-modtime of buffer to this file's modtime
   and mark buffer not modified.
 If VISIT is a string, it is a second file name;
@@ -4861,11 +4955,14 @@ This does code conversion according to the value of
       return val;
     }
 
+  record_unwind_protect (save_restriction_restore, save_restriction_save ());
+
   /* Special kludge to simplify auto-saving.  */
   if (NILP (start))
     {
       XSETFASTINT (start, BEG);
       XSETFASTINT (end, Z);
+      Fwiden ();
     }
 
   record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
@@ -5184,10 +5281,22 @@ This does code conversion according to the value of
       update_mode_lines++;
     }
   else if (quietly)
-    return Qnil;
+    {
+      if (auto_saving
+         && ! NILP (Fstring_equal (current_buffer->filename,
+                                   current_buffer->auto_save_file_name)))
+       SAVE_MODIFF = MODIFF;
+
+      return Qnil;
+    }
 
   if (!auto_saving)
-    message_with_string ("Wrote %s", visit_file, 1);
+    message_with_string ((INTEGERP (append)
+                         ? "Updated %s"
+                         : ! NILP (append)
+                         ? "Added to %s"
+                         : "Wrote %s"),
+                        visit_file, 1);
 
   return Qnil;
 }
@@ -5256,8 +5365,8 @@ build_annotations (start, end)
     }
 
   /* Now do the same for annotation functions implied by the file-format */
-  if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
-    p = Vauto_save_file_format;
+  if (auto_saving && (!EQ (current_buffer->auto_save_file_format, Qt)))
+    p = current_buffer->auto_save_file_format;
   else
     p = current_buffer->file_format;
   for (i = 0; CONSP (p); p = XCDR (p), ++i)
@@ -5458,7 +5567,8 @@ e_write (desc, string, start, end, coding)
 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
        Sverify_visited_file_modtime, 1, 1, 0,
        doc: /* Return t if last mod time of BUF's visited file matches what BUF records.
-This means that the file has not been changed since it was visited or saved.  */)
+This means that the file has not been changed since it was visited or saved.
+See Info node `(elisp)Modification Time' for more details.  */)
      (buf)
      Lisp_Object buf;
 {
@@ -5513,11 +5623,17 @@ Next attempt to save will certainly not complain of a discrepancy.  */)
 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
        Svisited_file_modtime, 0, 0, 0,
        doc: /* Return the current buffer's recorded visited file modification time.
-The value is a list of the form (HIGH . LOW), like the time values
-that `file-attributes' returns.  */)
+The value is a list of the form (HIGH LOW), like the time values
+that `file-attributes' returns.  If the current buffer has no recorded
+file modification time, this function returns 0.
+See Info node `(elisp)Modification Time' for more details.  */)
      ()
 {
-  return long_to_cons ((unsigned long) current_buffer->modtime);
+  Lisp_Object tcons;
+  tcons = long_to_cons ((unsigned long) current_buffer->modtime);
+  if (CONSP (tcons))
+    return list2 (XCAR (tcons), XCDR (tcons));
+  return tcons;
 }
 
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5591,14 +5707,21 @@ Lisp_Object
 auto_save_1 ()
 {
   struct stat st;
+  Lisp_Object modes;
+
+  auto_save_mode_bits = 0666;
 
   /* Get visited file's mode to become the auto save file's mode.  */
-  if (! NILP (current_buffer->filename)
-      && stat (SDATA (current_buffer->filename), &st) >= 0)
-    /* But make sure we can overwrite it later!  */
-    auto_save_mode_bits = st.st_mode | 0600;
-  else
-    auto_save_mode_bits = 0666;
+  if (! NILP (current_buffer->filename))
+    {
+      if (stat (SDATA (current_buffer->filename), &st) >= 0)
+       /* But make sure we can overwrite it later!  */
+       auto_save_mode_bits = st.st_mode | 0600;
+      else if ((modes = Ffile_modes (current_buffer->filename),
+               INTEGERP (modes)))
+       /* Remote files don't cooperate with stat.  */
+       auto_save_mode_bits = XINT (modes) | 0600;
+    }
 
   return
     Fwrite_region (Qnil, Qnil,
@@ -5734,11 +5857,14 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   minibuffer_auto_raise = 0;
   auto_saving = 1;
 
-  /* First, save all files which don't have handlers.  If Emacs is
-     crashing, the handlers may tweak what is causing Emacs to crash
-     in the first place, and it would be a shame if Emacs failed to
-     autosave perfectly ordinary files because it couldn't handle some
-     ange-ftp'd file.  */
+  /* On first pass, save all files that don't have handlers.
+     On second pass, save all files that do have handlers.
+
+     If Emacs is crashing, the handlers may tweak what is causing
+     Emacs to crash in the first place, and it would be a shame if
+     Emacs failed to autosave perfectly ordinary files because it
+     couldn't handle some ange-ftp'd file.  */
+
   for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
     for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
       {
@@ -6041,27 +6167,53 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
   if (SCHARS (name) == 0)
     return Qt;
 #endif /* VMS */
+  string = Fexpand_file_name (string, dir);
   if (!NILP (Vread_file_name_predicate))
     return call1 (Vread_file_name_predicate, string);
   return Ffile_exists_p (string);
 }
 
+DEFUN ("next-read-file-uses-dialog-p", Fnext_read_file_uses_dialog_p,
+       Snext_read_file_uses_dialog_p, 0, 0, 0,
+       doc: /* Return t if a call to `read-file-name' will use a dialog.
+The return value is only relevant for a call to `read-file-name' that happens
+before any other event (mouse or keypress) is handeled.  */)
+  ()
+{
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
+  if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
+      && use_dialog_box
+      && use_file_dialog
+      && have_menus_p ())
+    return Qt;
+#endif
+  return Qnil;
+}
+
 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 6, 0,
        doc: /* Read file name, prompting with PROMPT and completing in directory DIR.
 Value is not expanded---you must call `expand-file-name' yourself.
-Default name to DEFAULT-FILENAME if user enters a null string.
+Default name to DEFAULT-FILENAME if user exits the minibuffer with
+the same non-empty string that was inserted by this function.
  (If DEFAULT-FILENAME is omitted, the visited file name is used,
   except that if INITIAL is specified, that combined with DIR is used.)
+If the user exits with an empty minibuffer, this function returns
+an empty string.  (This can only happen if the user erased the
+pre-inserted contents or if `insert-default-directory' is nil.)
 Fourth arg MUSTMATCH non-nil means require existing file's name.
  Non-nil and non-t means also require confirmation after completion.
 Fifth arg INITIAL specifies text to start with.
-If optional sixth arg PREDICATE is non-nil, possible completions and the
-resulting file name must satisfy (funcall PREDICATE NAME).
-DIR defaults to current buffer's directory default.
+If optional sixth arg PREDICATE is non-nil, possible completions and
+the resulting file name must satisfy (funcall PREDICATE NAME).
+DIR should be an absolute directory name.  It defaults to the value of
+`default-directory'.
 
 If this command was invoked with the mouse, use a file dialog box if
 `use-dialog-box' is non-nil, and the window system or X toolkit in use
-provides a file dialog box.  */)
+provides a file dialog box.
+
+See also `read-file-name-completion-ignore-case'
+and `read-file-name-function'.  */)
      (prompt, dir, default_filename, mustmatch, initial, predicate)
      Lisp_Object prompt, dir, default_filename, mustmatch, initial, predicate;
 {
@@ -6075,10 +6227,13 @@ provides a file dialog box.  */)
 
   if (NILP (dir))
     dir = current_buffer->directory;
+  if (NILP (Ffile_name_absolute_p (dir)))
+    dir = Fexpand_file_name (dir, Qnil);
   if (NILP (default_filename))
-    default_filename = !NILP (initial)
-      ? Fexpand_file_name (initial, dir)
-      : current_buffer->filename;
+    default_filename
+      = (!NILP (initial)
+        ? Fexpand_file_name (initial, dir)
+        : current_buffer->filename);
 
   /* If dir starts with user's homedir, change that to ~. */
   homedir = (char *) egetenv ("HOME");
@@ -6158,20 +6313,16 @@ provides a file dialog box.  */)
     }
 
   count = SPECPDL_INDEX ();
-#ifdef VMS
-  specbind (intern ("completion-ignore-case"), Qt);
-#endif
-
+  specbind (intern ("completion-ignore-case"),
+           read_file_name_completion_ignore_case ? Qt : Qnil);
   specbind (intern ("minibuffer-completing-file-name"), Qt);
   specbind (intern ("read-file-name-predicate"),
            (NILP (predicate) ? Qfile_exists_p : predicate));
 
   GCPRO2 (insdef, default_filename);
 
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
-  if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
-      && use_dialog_box
-      && have_menus_p ())
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
+  if (! NILP (Fnext_read_file_uses_dialog_p ()))
     {
       /* If DIR contains a file name, split it.  */
       Lisp_Object file;
@@ -6183,7 +6334,8 @@ provides a file dialog box.  */)
        }
       if (!NILP(default_filename))
         default_filename = Fexpand_file_name (default_filename, dir);
-      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
+      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch,
+                            EQ (predicate, Qfile_directory_p) ? Qt : Qnil);
       add_to_history = 1;
     }
   else
@@ -6220,19 +6372,18 @@ provides a file dialog box.  */)
 
   if (!NILP (tem) && !NILP (default_filename))
     val = default_filename;
-  else if (SCHARS (val) == 0 && NILP (insdef))
-    {
-      if (!NILP (default_filename))
-       val = default_filename;
-      else
-       error ("No default file name");
-    }
   val = Fsubstitute_in_file_name (val);
 
   if (replace_in_history)
     /* Replace what Fcompleting_read added to the history
        with what we will actually return.  */
-    XSETCAR (Fsymbol_value (Qfile_name_history), double_dollars (val));
+    {
+       Lisp_Object val1 = double_dollars (val);
+       tem = Fsymbol_value (Qfile_name_history);
+       if (history_delete_duplicates)
+        XSETCDR (tem, Fdelete (val1, XCDR(tem)));
+       XSETCAR (tem, val1);
+    }
   else if (add_to_history)
     {
       /* Add the value to the history--but not if it matches
@@ -6240,8 +6391,10 @@ provides a file dialog box.  */)
       Lisp_Object val1 = double_dollars (val);
       tem = Fsymbol_value (Qfile_name_history);
       if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
-       Fset (Qfile_name_history,
-             Fcons (val1, tem));
+       {
+         if (history_delete_duplicates) tem = Fdelete (val1, tem);
+         Fset (Qfile_name_history, Fcons (val1, tem));
+       }
     }
 
   return val;
@@ -6285,11 +6438,13 @@ syms_of_fileio ()
   Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
   Qfile_modes = intern ("file-modes");
   Qset_file_modes = intern ("set-file-modes");
+  Qset_file_times = intern ("set-file-times");
   Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
   Qinsert_file_contents = intern ("insert-file-contents");
   Qwrite_region = intern ("write-region");
   Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
   Qset_visited_file_modtime = intern ("set-visited-file-modtime");
+  Qauto_save_coding = intern ("auto-save-coding");
 
   staticpro (&Qexpand_file_name);
   staticpro (&Qsubstitute_in_file_name);
@@ -6317,11 +6472,13 @@ syms_of_fileio ()
   staticpro (&Qfile_accessible_directory_p);
   staticpro (&Qfile_modes);
   staticpro (&Qset_file_modes);
+  staticpro (&Qset_file_times);
   staticpro (&Qfile_newer_than_file_p);
   staticpro (&Qinsert_file_contents);
   staticpro (&Qwrite_region);
   staticpro (&Qverify_visited_file_modtime);
   staticpro (&Qset_visited_file_modtime);
+  staticpro (&Qauto_save_coding);
 
   Qfile_name_history = intern ("file-name-history");
   Fset (Qfile_name_history, Qnil);
@@ -6357,13 +6514,6 @@ instead use `file-name-coding-system' to get a constant encoding
 of file names regardless of the current language environment.  */);
   Vdefault_file_name_coding_system = Qnil;
 
-  DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
-    doc: /* *Format in which to write auto-save files.
-Should be a list of symbols naming formats that are defined in `format-alist'.
-If it is t, which is the default, auto-save files are written in the
-same format as a regular save would use.  */);
-  Vauto_save_file_format = Qt;
-
   Qformat_decode = intern ("format-decode");
   staticpro (&Qformat_decode);
   Qformat_annotate_function = intern ("format-annotate-function");
@@ -6399,8 +6549,29 @@ same format as a regular save would use.  */);
               doc: /* Current predicate used by `read-file-name-internal'.  */);
   Vread_file_name_predicate = Qnil;
 
+  DEFVAR_BOOL ("read-file-name-completion-ignore-case", &read_file_name_completion_ignore_case,
+              doc: /* *Non-nil means when reading a file name completion ignores case.  */);
+#if defined VMS || defined DOS_NT || defined MAC_OS
+  read_file_name_completion_ignore_case = 1;
+#else
+  read_file_name_completion_ignore_case = 0;
+#endif
+
   DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
-              doc: /* *Non-nil means when reading a filename start with default dir in minibuffer.  */);
+              doc: /* *Non-nil means when reading a filename start with default dir in minibuffer.
+If the initial minibuffer contents are non-empty, you can usually
+request a default filename by typing RETURN without editing.  For some
+commands, exiting with an empty minibuffer has a special meaning,
+such as making the current buffer visit no file in the case of
+`set-visited-file-name'.
+If this variable is non-nil, the minibuffer contents are always
+initially non-empty and typing RETURN without editing will fetch the
+default name, if one is provided.  Note however that this default name
+is not necessarily the name originally inserted in the minibuffer, if
+that is just the default directory.
+If this variable is nil, the minibuffer often starts out empty.  In
+that case you may have to explicitly fetch the next history element to
+request the default name.  */);
   insert_default_directory = 1;
 
   DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
@@ -6526,6 +6697,7 @@ a non-nil value.  */);
   defsubr (&Sfile_regular_p);
   defsubr (&Sfile_modes);
   defsubr (&Sset_file_modes);
+  defsubr (&Sset_file_times);
   defsubr (&Sset_default_file_modes);
   defsubr (&Sdefault_file_modes);
   defsubr (&Sfile_newer_than_file_p);
@@ -6543,8 +6715,12 @@ a non-nil value.  */);
 
   defsubr (&Sread_file_name_internal);
   defsubr (&Sread_file_name);
+  defsubr (&Snext_read_file_uses_dialog_p);
 
 #ifdef unix
   defsubr (&Sunix_sync);
 #endif
 }
+
+/* arch-tag: 64ba3fd7-f844-4fb2-ba4b-427eb928786c
+   (do not change this comment) */