]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
(set_text_properties): New function. Like
[gnu-emacs] / src / fileio.c
index 9b2fe645910a212a0cd2c4334099566cda66176b..7b3084c7aa3a74907dcd2e1301ee7e8e7b3db4c7 100644 (file)
@@ -1,5 +1,5 @@
 /* File IO for GNU Emacs.
 /* File IO for GNU Emacs.
-   Copyright (C) 1985,86,87,88,93,94,95,96,97,1998 Free Software Foundation, Inc.
+   Copyright (C) 1985,86,87,88,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -50,15 +50,6 @@ Boston, MA 02111-1307, USA.  */
 #include <pwd.h>
 #endif
 
 #include <pwd.h>
 #endif
 
-#ifdef MSDOS
-#include "msdos.h"
-#include <sys/param.h>
-#if __DJGPP__ >= 2
-#include <fcntl.h>
-#include <string.h>
-#endif
-#endif
-
 #include <ctype.h>
 
 #ifdef VMS
 #include <ctype.h>
 
 #ifdef VMS
@@ -74,8 +65,6 @@ Boston, MA 02111-1307, USA.  */
 extern int errno;
 #endif
 
 extern int errno;
 #endif
 
-extern char *strerror ();
-
 #ifdef APOLLO
 #include <sys/time.h>
 #endif
 #ifdef APOLLO
 #include <sys/time.h>
 #endif
@@ -104,6 +93,15 @@ extern char *strerror ();
 #include <fcntl.h>
 #endif /* not WINDOWSNT */
 
 #include <fcntl.h>
 #endif /* not WINDOWSNT */
 
+#ifdef MSDOS
+#include "msdos.h"
+#include <sys/param.h>
+#if __DJGPP__ >= 2
+#include <fcntl.h>
+#include <string.h>
+#endif
+#endif
+
 #ifdef DOS_NT
 #define CORRECT_DIR_SEPS(s) \
   do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
 #ifdef DOS_NT
 #define CORRECT_DIR_SEPS(s) \
   do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
@@ -141,6 +139,9 @@ extern char *strerror ();
 #endif
 #endif
 
 #endif
 #endif
 
+#include "commands.h"
+extern int use_dialog_box;
+
 #ifndef O_WRONLY
 #define O_WRONLY 1
 #endif
 #ifndef O_WRONLY
 #define O_WRONLY 1
 #endif
@@ -149,6 +150,10 @@ extern char *strerror ();
 #define O_RDONLY 0
 #endif
 
 #define O_RDONLY 0
 #endif
 
+#ifndef S_ISLNK
+#  define lstat stat
+#endif
+
 #define min(a, b) ((a) < (b) ? (a) : (b))
 #define max(a, b) ((a) > (b) ? (a) : (b))
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
 #define max(a, b) ((a) > (b) ? (a) : (b))
 
@@ -206,6 +211,10 @@ Lisp_Object Vdirectory_sep_char;
 
 extern Lisp_Object Vuser_login_name;
 
 
 extern Lisp_Object Vuser_login_name;
 
+#ifdef WINDOWSNT
+extern Lisp_Object Vw32_get_true_file_attributes;
+#endif
+
 extern int minibuf_level;
 
 extern int minibuffer_auto_raise;
 extern int minibuf_level;
 
 extern int minibuffer_auto_raise;
@@ -221,7 +230,7 @@ static Lisp_Object Vinhibit_file_name_handlers;
 static Lisp_Object Vinhibit_file_name_operation;
 
 Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
 static Lisp_Object Vinhibit_file_name_operation;
 
 Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
-
+Lisp_Object Qexcl;
 Lisp_Object Qfile_name_history;
 
 Lisp_Object Qcar_less_than_car;
 Lisp_Object Qfile_name_history;
 
 Lisp_Object Qcar_less_than_car;
@@ -236,24 +245,34 @@ report_file_error (string, data)
      Lisp_Object data;
 {
   Lisp_Object errstring;
      Lisp_Object data;
 {
   Lisp_Object errstring;
+  int errorno = errno;
 
 
-  errstring = build_string (strerror (errno));
-
-  /* System error messages are capitalized.  Downcase the initial
-     unless it is followed by a slash.  */
-  if (XSTRING (errstring)->data[1] != '/')
-    XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
+  synchronize_system_messages_locale ();
+  errstring = code_convert_string_norecord (build_string (strerror (errorno)),
+                                           Vlocale_coding_system, 0);
 
   while (1)
 
   while (1)
-    Fsignal (Qfile_error,
-            Fcons (build_string (string), Fcons (errstring, data)));
+    switch (errorno)
+      {
+      case EEXIST:
+       Fsignal (Qfile_already_exists, Fcons (errstring, data));
+       break;
+      default:
+       /* System error messages are capitalized.  Downcase the initial
+          unless it is followed by a slash.  */
+       if (XSTRING (errstring)->data[1] != '/')
+         XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
+
+       Fsignal (Qfile_error,
+                Fcons (build_string (string), Fcons (errstring, data)));
+      }
 }
 
 Lisp_Object
 close_file_unwind (fd)
      Lisp_Object fd;
 {
 }
 
 Lisp_Object
 close_file_unwind (fd)
      Lisp_Object fd;
 {
-  close (XFASTINT (fd));
+  emacs_close (XFASTINT (fd));
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -322,19 +341,19 @@ use the standard functions without calling themselves recursively.")
     inhibited_handlers = Qnil;
 
   for (chain = Vfile_name_handler_alist; CONSP (chain);
     inhibited_handlers = Qnil;
 
   for (chain = Vfile_name_handler_alist; CONSP (chain);
-       chain = XCONS (chain)->cdr)
+       chain = XCDR (chain))
     {
       Lisp_Object elt;
     {
       Lisp_Object elt;
-      elt = XCONS (chain)->car;
+      elt = XCAR (chain);
       if (CONSP (elt))
        {
          Lisp_Object string;
       if (CONSP (elt))
        {
          Lisp_Object string;
-         string = XCONS (elt)->car;
+         string = XCAR (elt);
          if (STRINGP (string) && fast_string_match (string, filename) >= 0)
            {
              Lisp_Object handler, tem;
 
          if (STRINGP (string) && fast_string_match (string, filename) >= 0)
            {
              Lisp_Object handler, tem;
 
-             handler = XCONS (elt)->cdr;
+             handler = XCDR (elt);
              tem = Fmemq (handler, inhibited_handlers);
              if (NILP (tem))
                return handler;
              tem = Fmemq (handler, inhibited_handlers);
              if (NILP (tem))
                return handler;
@@ -382,8 +401,11 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.")
         && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
 #endif /* VMS */
 #ifdef DOS_NT
         && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
 #endif /* VMS */
 #ifdef DOS_NT
-        /* only recognise drive specifier at beginning */
-        && !(p[-1] == ':' && p == beg + 2)
+        /* only recognise drive specifier at the beginning */
+        && !(p[-1] == ':'
+             /* handle the "/:d:foo" and "/:foo" cases correctly  */
+             && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
+                 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
 #endif
         ) p--;
 
 #endif
         ) p--;
 
@@ -391,11 +413,20 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.")
     return Qnil;
 #ifdef DOS_NT
   /* Expansion of "c:" to drive and default directory.  */
     return Qnil;
 #ifdef DOS_NT
   /* Expansion of "c:" to drive and default directory.  */
-  if (p == beg + 2 && beg[1] == ':')
+  if (p[-1] == ':')
     {
       /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir.  */
       unsigned char *res = alloca (MAXPATHLEN + 1);
     {
       /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir.  */
       unsigned char *res = alloca (MAXPATHLEN + 1);
-      if (getdefdir (toupper (*beg) - 'A' + 1, res))
+      unsigned char *r = res;
+
+      if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
+       {
+         strncpy (res, beg, 2);
+         beg += 2;
+         r += 2;
+       }
+
+      if (getdefdir (toupper (*beg) - 'A' + 1, r))
        {
          if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
            strcat (res, "/");
        {
          if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
            strcat (res, "/");
@@ -440,7 +471,9 @@ or the entire name if it contains no slash.")
 #endif /* VMS */
 #ifdef DOS_NT
         /* only recognise drive specifier at beginning */
 #endif /* VMS */
 #ifdef DOS_NT
         /* only recognise drive specifier at beginning */
-        && !(p[-1] == ':' && p == beg + 2)
+        && !(p[-1] == ':'
+             /* handle the "/:d:foo" case correctly  */
+             && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
 #endif
         )
     p--;
 #endif
         )
     p--;
@@ -484,8 +517,9 @@ file_name_as_directory (out, in)
 
   if (size < 0)
     {
 
   if (size < 0)
     {
-      out[0] = '/';
-      out[1] = 0;
+      out[0] = '.';
+      out[1] = '/';
+      out[2] = 0;
       return out;
     }
 
       return out;
     }
 
@@ -599,6 +633,7 @@ On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
  * Value is nonzero if the string output is different from the input.
  */
 
  * Value is nonzero if the string output is different from the input.
  */
 
+int
 directory_file_name (src, dst)
      char *src, *dst;
 {
 directory_file_name (src, dst)
      char *src, *dst;
 {
@@ -788,33 +823,122 @@ it returns a file name such as \"[X]Y.DIR.1\".")
   return build_string (buf);
 }
 
   return build_string (buf);
 }
 
+static char make_temp_name_tbl[64] =
+{
+  'A','B','C','D','E','F','G','H',
+  'I','J','K','L','M','N','O','P',
+  'Q','R','S','T','U','V','W','X',
+  'Y','Z','a','b','c','d','e','f',
+  'g','h','i','j','k','l','m','n',
+  'o','p','q','r','s','t','u','v',
+  'w','x','y','z','0','1','2','3',
+  '4','5','6','7','8','9','-','_'
+};
+static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
+
 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
   "Generate temporary file name (string) starting with PREFIX (a string).\n\
 The Emacs process number forms part of the result,\n\
 so there is no danger of generating a name being used by another process.\n\
 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
   "Generate temporary file name (string) starting with PREFIX (a string).\n\
 The Emacs process number forms part of the result,\n\
 so there is no danger of generating a name being used by another process.\n\
+\n\
 In addition, this function makes an attempt to choose a name\n\
 In addition, this function makes an attempt to choose a name\n\
-which has no existing file.")
+which has no existing file.  To make this work,\n\
+PREFIX should be an absolute file name.\n\
+\n\
+There is a race condition between calling `make-temp-name' and creating the\n\
+file which opens all kinds of security holes.  For that reason, you should\n\
+probably use `make-temp-file' instead.")
   (prefix)
      Lisp_Object prefix;
 {
   (prefix)
      Lisp_Object prefix;
 {
-  char *temp;
   Lisp_Object val;
   Lisp_Object val;
-#ifdef MSDOS
-  /* Don't use too many characters of the restricted 8+3 DOS
-     filename space.  */
-  val = concat2 (prefix, build_string ("a.XXX"));
+  int len;
+  int pid;
+  unsigned char *p, *data;
+  char pidbuf[20];
+  int pidlen;
+
+  CHECK_STRING (prefix, 0);
+
+  /* VAL is created by adding 6 characters to PREFIX.  The first
+     three are the PID of this process, in base 64, and the second
+     three are incremented if the file already exists.  This ensures
+     262144 unique file names per PID per PREFIX.  */
+
+  pid = (int) getpid ();
+
+#ifdef HAVE_LONG_FILE_NAMES
+  sprintf (pidbuf, "%d", pid);
+  pidlen = strlen (pidbuf);
 #else
 #else
-  val = concat2 (prefix, build_string ("XXXXXX"));
+  pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
+  pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
+  pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
+  pidlen = 3;
 #endif
 #endif
-  temp = mktemp (XSTRING (val)->data);
-  if (! temp)
-    error ("No temporary file names based on %s are available",
-          XSTRING (prefix)->data);
-#ifdef DOS_NT
-  CORRECT_DIR_SEPS (XSTRING (val)->data);
-#endif
-  return val;
+
+  len = XSTRING (prefix)->size;
+  val = make_uninit_string (len + 3 + pidlen);
+  data = XSTRING (val)->data;
+  bcopy(XSTRING (prefix)->data, data, len);
+  p = data + len;
+
+  bcopy (pidbuf, p, pidlen);
+  p += pidlen;
+
+  /* Here we try to minimize useless stat'ing when this function is
+     invoked many times successively with the same PREFIX.  We achieve
+     this by initializing count to a random value, and incrementing it
+     afterwards.
+
+     We don't want make-temp-name to be called while dumping,
+     because then make_temp_name_count_initialized_p would get set
+     and then make_temp_name_count would not be set when Emacs starts.  */
+
+  if (!make_temp_name_count_initialized_p)
+    {
+      make_temp_name_count = (unsigned) time (NULL);
+      make_temp_name_count_initialized_p = 1;
+    }
+
+  while (1)
+    {
+      struct stat ignored;
+      unsigned num = make_temp_name_count;
+
+      p[0] = make_temp_name_tbl[num & 63], num >>= 6;
+      p[1] = make_temp_name_tbl[num & 63], num >>= 6;
+      p[2] = make_temp_name_tbl[num & 63], num >>= 6;
+
+      /* Poor man's congruential RN generator.  Replace with
+         ++make_temp_name_count for debugging.  */
+      make_temp_name_count += 25229;
+      make_temp_name_count %= 225307;
+
+      if (stat (data, &ignored) < 0)
+       {
+         /* We want to return only if errno is ENOENT.  */
+         if (errno == ENOENT)
+           return val;
+         else
+           /* The error here is dubious, but there is little else we
+              can do.  The alternatives are to return nil, which is
+              as bad as (and in many cases worse than) throwing the
+              error, or to ignore the error, which will likely result
+              in looping through 225307 stat's, which is not only
+              dog-slow, but also useless since it will fallback to
+              the errow below, anyway.  */
+           report_file_error ("Cannot create temporary name for prefix `%s'",
+                              Fcons (prefix, Qnil));
+         /* not reached */
+       }
+    }
+
+  error ("Cannot create temporary name for prefix `%s'",
+        XSTRING (prefix)->data);
+  return Qnil;
 }
 }
+
 \f
 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
   "Convert filename NAME to absolute, and canonicalize it.\n\
 \f
 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
   "Convert filename NAME to absolute, and canonicalize it.\n\
@@ -848,6 +972,7 @@ See also the function `substitute-in-file-name'.")
 #ifdef DOS_NT
   int drive = 0;
   int collapse_newdir = 1;
 #ifdef DOS_NT
   int drive = 0;
   int collapse_newdir = 1;
+  int is_escaped = 0;
 #endif /* DOS_NT */
   int length;
   Lisp_Object handler;
 #endif /* DOS_NT */
   int length;
   Lisp_Object handler;
@@ -891,7 +1016,7 @@ See also the function `substitute-in-file-name'.")
         is needed at all) without requiring it to be expanded now.  */
 #ifdef DOS_NT
       /* Detect MSDOS file names with drive specifiers.  */
         is needed at all) without requiring it to be expanded now.  */
 #ifdef DOS_NT
       /* Detect MSDOS file names with drive specifiers.  */
-      && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
+      && ! (IS_DRIVE (o[0]) && IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))
 #ifdef WINDOWSNT
       /* Detect Windows file names in UNC format.  */
       && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
 #ifdef WINDOWSNT
       /* Detect Windows file names in UNC format.  */
       && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
@@ -925,33 +1050,21 @@ See also the function `substitute-in-file-name'.")
      a local copy to modify, even if there ends up being no change. */
   nm = strcpy (alloca (strlen (nm) + 1), nm);
 
      a local copy to modify, even if there ends up being no change. */
   nm = strcpy (alloca (strlen (nm) + 1), nm);
 
+  /* Note if special escape prefix is present, but remove for now.  */
+  if (nm[0] == '/' && nm[1] == ':')
+    {
+      is_escaped = 1;
+      nm += 2;
+    }
+
   /* Find and remove drive specifier if present; this makes nm absolute
   /* Find and remove drive specifier if present; this makes nm absolute
-     even if the rest of the name appears to be relative. */
-  {
-    unsigned char *colon = rindex (nm, ':');
-
-    if (colon)
-      /* Only recognize colon as part of drive specifier if there is a
-        single alphabetic character preceeding the colon (and if the
-        character before the drive letter, if present, is a directory
-        separator); this is to support the remote system syntax used by
-        ange-ftp, and the "po:username" syntax for POP mailboxes. */
-    look_again:
-      if (nm == colon)
-       nm++;
-      else if (IS_DRIVE (colon[-1])
-              && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
-       {
-         drive = colon[-1];
-         nm = colon + 1;
-       }
-      else
-       {
-         while (--colon >= nm)
-           if (colon[0] == ':')
-             goto look_again;
-       }
-  }
+     even if the rest of the name appears to be relative.  Only look for
+     drive specifier at the beginning.  */
+  if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
+    {
+      drive = nm[0];
+      nm += 2;
+    }
 
 #ifdef WINDOWSNT
   /* If we see "c://somedir", we want to strip the first slash after the
 
 #ifdef WINDOWSNT
   /* If we see "c://somedir", we want to strip the first slash after the
@@ -976,10 +1089,10 @@ See also the function `substitute-in-file-name'.")
   if (
       IS_DIRECTORY_SEP (nm[0])
 #ifdef MSDOS
   if (
       IS_DIRECTORY_SEP (nm[0])
 #ifdef MSDOS
-      && drive
+      && drive && !is_escaped
 #endif
 #ifdef WINDOWSNT
 #endif
 #ifdef WINDOWSNT
-      && (drive || IS_DIRECTORY_SEP (nm[1]))
+      && (drive || IS_DIRECTORY_SEP (nm[1])) && !is_escaped
 #endif
 #ifdef VMS
       || index (nm, ':')
 #endif
 #ifdef VMS
       || index (nm, ':')
@@ -1225,6 +1338,14 @@ See also the function `substitute-in-file-name'.")
       && !newdir)
     {
       newdir = XSTRING (default_directory)->data;
       && !newdir)
     {
       newdir = XSTRING (default_directory)->data;
+#ifdef DOS_NT
+      /* Note if special escape prefix is present, but remove for now.  */
+      if (newdir[0] == '/' && newdir[1] == ':')
+       {
+         is_escaped = 1;
+         newdir += 2;
+       }
+#endif
     }
 
 #ifdef DOS_NT
     }
 
 #ifdef DOS_NT
@@ -1300,9 +1421,9 @@ See also the function `substitute-in-file-name'.")
   if (newdir)
     {
       /* Get rid of any slash at the end of newdir, unless newdir is
   if (newdir)
     {
       /* Get rid of any slash at the end of newdir, unless newdir is
-        just // (an incomplete UNC name).  */
+        just / or // (an incomplete UNC name).  */
       length = strlen (newdir);
       length = strlen (newdir);
-      if (length > 0 && IS_DIRECTORY_SEP (newdir[length - 1])
+      if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
 #ifdef WINDOWSNT
          && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
 #endif
 #ifdef WINDOWSNT
          && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
 #endif
@@ -1321,10 +1442,11 @@ See also the function `substitute-in-file-name'.")
   /* Now concatenate the directory and name to new space in the stack frame */
   tlen += strlen (nm) + 1;
 #ifdef DOS_NT
   /* Now concatenate the directory and name to new space in the stack frame */
   tlen += strlen (nm) + 1;
 #ifdef DOS_NT
-  /* Add reserved space for drive name.  (The Microsoft x86 compiler
+  /* Reserve space for drive specifier and escape prefix, since either
+     or both may need to be inserted.  (The Microsoft x86 compiler
      produces incorrect code if the following two lines are combined.)  */
      produces incorrect code if the following two lines are combined.)  */
-  target = (unsigned char *) alloca (tlen + 2);
-  target += 2;
+  target = (unsigned char *) alloca (tlen + 4);
+  target += 4;
 #else  /* not DOS_NT */
   target = (unsigned char *) alloca (tlen);
 #endif /* not DOS_NT */
 #else  /* not DOS_NT */
   target = (unsigned char *) alloca (tlen);
 #endif /* not DOS_NT */
@@ -1334,7 +1456,18 @@ See also the function `substitute-in-file-name'.")
     {
 #ifndef VMS
       if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
     {
 #ifndef VMS
       if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
-       strcpy (target, newdir);
+       {
+#ifdef DOS_NT
+         /* If newdir is effectively "C:/", then the drive letter will have
+            been stripped and newdir will be "/".  Concatenating with an
+            absolute directory in nm produces "//", which will then be
+            incorrectly treated as a network share.  Ignore newdir in
+            this case (keeping the drive letter).  */
+         if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) 
+               && newdir[1] == '\0'))
+#endif
+           strcpy (target, newdir);
+       }
       else
 #endif
        file_name_as_directory (target, newdir);
       else
 #endif
        file_name_as_directory (target, newdir);
@@ -1443,6 +1576,13 @@ See also the function `substitute-in-file-name'.")
       target[0] = DRIVE_LETTER (drive);
       target[1] = ':';
     }
       target[0] = DRIVE_LETTER (drive);
       target[1] = ':';
     }
+  /* Reinsert the escape prefix if required.  */
+  if (is_escaped)
+    {
+      target -= 2;
+      target[0] = '/';
+      target[1] = ':';
+    }
   CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
   CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
@@ -1990,7 +2130,7 @@ duplicates what `expand-file-name' does.")
       xnm = p;
 #ifdef DOS_NT
     else if (IS_DRIVE (p[0]) && p[1] == ':'
       xnm = p;
 #ifdef DOS_NT
     else if (IS_DRIVE (p[0]) && p[1] == ':'
-            && p > nm && IS_DIRECTORY_SEP (p[-1]))
+            && p > xnm && IS_DIRECTORY_SEP (p[-1]))
       xnm = p;
 #endif
 
       xnm = p;
 #endif
 
@@ -2057,13 +2197,15 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
      struct stat *statptr;
      int quick;
 {
      struct stat *statptr;
      int quick;
 {
-  register Lisp_Object tem;
+  register Lisp_Object tem, encoded_filename;
   struct stat statbuf;
   struct gcpro gcpro1;
 
   struct stat statbuf;
   struct gcpro gcpro1;
 
+  encoded_filename = ENCODE_FILE (absname);
+
   /* stat is a good way to tell whether the file exists,
      regardless of what access permissions it has.  */
   /* stat is a good way to tell whether the file exists,
      regardless of what access permissions it has.  */
-  if (stat (XSTRING (absname)->data, &statbuf) >= 0)
+  if (stat (XSTRING (encoded_filename)->data, &statbuf) >= 0)
     {
       if (! interactive)
        Fsignal (Qfile_already_exists,
     {
       if (! interactive)
        Fsignal (Qfile_already_exists,
@@ -2142,7 +2284,7 @@ A prefix arg makes KEEP-TIME non-nil.")
   else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
     out_st.st_mode = 0;
 
   else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
     out_st.st_mode = 0;
 
-  ifd = open (XSTRING (encoded_file)->data, O_RDONLY);
+  ifd = emacs_open (XSTRING (encoded_file)->data, O_RDONLY, 0);
   if (ifd < 0)
     report_file_error ("Opening input file", Fcons (file, Qnil));
 
   if (ifd < 0)
     report_file_error ("Opening input file", Fcons (file, Qnil));
 
@@ -2152,7 +2294,7 @@ A prefix arg makes KEEP-TIME non-nil.")
      copyable by us. */
   input_file_statable_p = (fstat (ifd, &st) >= 0);
 
      copyable by us. */
   input_file_statable_p = (fstat (ifd, &st) >= 0);
 
-#if !defined (MSDOS) || __DJGPP__ > 1
+#if !defined (DOS_NT) || __DJGPP__ > 1
   if (out_st.st_mode != 0
       && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
     {
   if (out_st.st_mode != 0
       && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
     {
@@ -2194,13 +2336,13 @@ A prefix arg makes KEEP-TIME non-nil.")
 
   immediate_quit = 1;
   QUIT;
 
   immediate_quit = 1;
   QUIT;
-  while ((n = read (ifd, buf, sizeof buf)) > 0)
-    if (write (ofd, buf, n) != n)
+  while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
+    if (emacs_write (ofd, buf, n) != n)
       report_file_error ("I/O error", Fcons (newname, Qnil));
   immediate_quit = 0;
 
   /* Closing the output clobbers the file times on some systems.  */
       report_file_error ("I/O error", Fcons (newname, Qnil));
   immediate_quit = 0;
 
   /* Closing the output clobbers the file times on some systems.  */
-  if (close (ofd) < 0)
+  if (emacs_close (ofd) < 0)
     report_file_error ("I/O error", Fcons (newname, Qnil));
 
   if (input_file_statable_p)
     report_file_error ("I/O error", Fcons (newname, Qnil));
 
   if (input_file_statable_p)
@@ -2230,7 +2372,7 @@ A prefix arg makes KEEP-TIME non-nil.")
 #endif /* MSDOS */
     }
 
 #endif /* MSDOS */
     }
 
-  close (ifd);
+  emacs_close (ifd);
 
   /* Discard the unwind protects.  */
   specpdl_ptr = specpdl + count;
 
   /* Discard the unwind protects.  */
   specpdl_ptr = specpdl + count;
@@ -2769,10 +2911,10 @@ See also `file-exists-p' and `file-attributes'.")
   if (S_ISFIFO (statbuf.st_mode))
     flags |= O_NONBLOCK;
 #endif
   if (S_ISFIFO (statbuf.st_mode))
     flags |= O_NONBLOCK;
 #endif
-  desc = open (XSTRING (absname)->data, flags);
+  desc = emacs_open (XSTRING (absname)->data, flags, 0);
   if (desc < 0)
     return Qnil;
   if (desc < 0)
     return Qnil;
-  close (desc);
+  emacs_close (desc);
   return Qt;
 #endif /* not DOS_NT */
 }
   return Qt;
 #endif /* not DOS_NT */
 }
@@ -2828,6 +2970,7 @@ If there is no error, we return nil.")
   int fd;
 
   CHECK_STRING (filename, 0);
   int fd;
 
   CHECK_STRING (filename, 0);
+  CHECK_STRING (string, 1);
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -2837,10 +2980,10 @@ If there is no error, we return nil.")
 
   encoded_filename = ENCODE_FILE (filename);
 
 
   encoded_filename = ENCODE_FILE (filename);
 
-  fd = open (XSTRING (encoded_filename)->data, O_RDONLY);
+  fd = emacs_open (XSTRING (encoded_filename)->data, O_RDONLY, 0);
   if (fd < 0)
     report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
   if (fd < 0)
     report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
-  close (fd);
+  emacs_close (fd);
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -2896,7 +3039,9 @@ Otherwise returns nil.")
 }
 
 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
 }
 
 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
-  "Return t if FILENAME names an existing directory.")
+  "Return t if FILENAME names an existing directory.\n\
+Symbolic links to directories count as directories.\n\
+See `file-symlink-p' to distinguish symlinks.")
   (filename)
      Lisp_Object filename;
 {
   (filename)
      Lisp_Object filename;
 {
@@ -2972,9 +3117,25 @@ This is the sort of file that holds an ordinary stream of data bytes.")
 
   absname = ENCODE_FILE (absname);
 
 
   absname = ENCODE_FILE (absname);
 
+#ifdef WINDOWSNT
+  {
+    int result;
+    Lisp_Object tem = Vw32_get_true_file_attributes;
+
+    /* Tell stat to use expensive method to get accurate info.  */
+    Vw32_get_true_file_attributes = Qt;
+    result = stat (XSTRING (absname)->data, &st);
+    Vw32_get_true_file_attributes = tem;
+
+    if (result < 0)
+      return Qnil;
+    return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
+  }
+#else
   if (stat (XSTRING (absname)->data, &st) < 0)
     return Qnil;
   return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
   if (stat (XSTRING (absname)->data, &st) < 0)
     return Qnil;
   return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
+#endif
 }
 \f
 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
 }
 \f
 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
@@ -3127,6 +3288,26 @@ Lisp_Object Qfind_buffer_file_type;
 #define READ_BUF_SIZE (64 << 10)
 #endif
 
 #define READ_BUF_SIZE (64 << 10)
 #endif
 
+/* This function is called when a function bound to
+   Vset_auto_coding_function causes some error.  At that time, a text
+   of a file has already been inserted in the current buffer, but,
+   markers has not yet been adjusted.  Thus we must adjust markers
+   here.  We are sure that the buffer was empty before the text of the
+   file was inserted.  */
+
+static Lisp_Object
+set_auto_coding_unwind (multibyte)
+     Lisp_Object multibyte;
+{
+  int inserted = Z_BYTE - BEG_BYTE;
+
+  if (!NILP (multibyte))
+    inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted);
+  adjust_after_insert (PT, PT_BYTE, Z, Z_BYTE, inserted);
+
+  return Qnil;
+}
+
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
   1, 5, 0,
   "Insert contents of file FILENAME after point.\n\
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
   1, 5, 0,
   "Insert contents of file FILENAME after point.\n\
@@ -3147,10 +3328,11 @@ the whole thing because (1) it preserves some marker positions\n\
 and (2) it puts less data in the undo list.\n\
 When REPLACE is non-nil, the value is the number of characters actually read,\n\
 which is often less than the number of characters to be read.\n\
 and (2) it puts less data in the undo list.\n\
 When REPLACE is non-nil, the value is the number of characters actually read,\n\
 which is often less than the number of characters to be read.\n\
+\n\
 This does code conversion according to the value of\n\
 This does code conversion according to the value of\n\
-  `coding-system-for-read' or `file-coding-system-alist',\n\
-  and sets the variable `last-coding-system-used' to the coding system\n\
-  actually used.")
+`coding-system-for-read' or `file-coding-system-alist',\n\
+and sets the variable `last-coding-system-used' to the coding system\n\
+actually used.")
   (filename, visit, beg, end, replace)
      Lisp_Object filename, visit, beg, end, replace;
 {
   (filename, visit, beg, end, replace)
      Lisp_Object filename, visit, beg, end, replace;
 {
@@ -3165,11 +3347,12 @@ This does code conversion according to the value of\n\
   Lisp_Object p;
   int total;
   int not_regular = 0;
   Lisp_Object p;
   int total;
   int not_regular = 0;
-  char read_buf[READ_BUF_SIZE];
+  unsigned char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
   unsigned char buffer[1 << 14];
   int replace_handled = 0;
   int set_coding_system = 0;
   struct coding_system coding;
   unsigned char buffer[1 << 14];
   int replace_handled = 0;
   int set_coding_system = 0;
+  int coding_system_decided = 0;
 
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
 
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
@@ -3193,6 +3376,8 @@ This does code conversion according to the value of\n\
     {
       val = call6 (handler, Qinsert_file_contents, filename,
                   visit, beg, end, replace);
     {
       val = call6 (handler, Qinsert_file_contents, filename,
                   visit, beg, end, replace);
+      if (CONSP (val) && CONSP (XCDR (val)))
+       inserted = XINT (XCAR (XCDR (val)));
       goto handled;
     }
 
       goto handled;
     }
 
@@ -3201,21 +3386,33 @@ This does code conversion according to the value of\n\
 
   fd = -1;
 
 
   fd = -1;
 
+#ifdef WINDOWSNT
+  {
+    Lisp_Object tem = Vw32_get_true_file_attributes;
+
+    /* Tell stat to use expensive method to get accurate info.  */
+    Vw32_get_true_file_attributes = Qt;
+    total = stat (XSTRING (filename)->data, &st);
+    Vw32_get_true_file_attributes = tem;
+  }
+  if (total < 0)
+#else
 #ifndef APOLLO
   if (stat (XSTRING (filename)->data, &st) < 0)
 #else
 #ifndef APOLLO
   if (stat (XSTRING (filename)->data, &st) < 0)
 #else
-  if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
+  if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0
       || fstat (fd, &st) < 0)
 #endif /* not APOLLO */
       || fstat (fd, &st) < 0)
 #endif /* not APOLLO */
+#endif /* WINDOWSNT */
     {
     {
-      if (fd >= 0) close (fd);
+      if (fd >= 0) emacs_close (fd);
     badopen:
       if (NILP (visit))
        report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
       st.st_mtime = -1;
       how_much = 0;
       if (!NILP (Vcoding_system_for_read))
     badopen:
       if (NILP (visit))
        report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
       st.st_mtime = -1;
       how_much = 0;
       if (!NILP (Vcoding_system_for_read))
-       current_buffer->buffer_file_coding_system = Vcoding_system_for_read;
+       Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
       goto notfound;
     }
 
       goto notfound;
     }
 
@@ -3238,7 +3435,7 @@ This does code conversion according to the value of\n\
 #endif
 
   if (fd < 0)
 #endif
 
   if (fd < 0)
-    if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
+    if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0)
       goto badopen;
 
   /* Replacement should preserve point as it preserves markers.  */
       goto badopen;
 
   /* Replacement should preserve point as it preserves markers.  */
@@ -3251,6 +3448,9 @@ This does code conversion according to the value of\n\
   if (! not_regular && st.st_size < 0)
     error ("File size is negative");
 
   if (! not_regular && st.st_size < 0)
     error ("File size is negative");
 
+  /* Prevent redisplay optimizations.  */
+  current_buffer->clip_changed = 1;
+
   if (!NILP (beg) || !NILP (end))
     if (!NILP (visit))
       error ("Attempt to visit less than an entire file");
   if (!NILP (beg) || !NILP (end))
     if (!NILP (visit))
       error ("Attempt to visit less than an entire file");
@@ -3267,82 +3467,113 @@ This does code conversion according to the value of\n\
       if (! not_regular)
        {
          XSETINT (end, st.st_size);
       if (! not_regular)
        {
          XSETINT (end, st.st_size);
-         if (XINT (end) != st.st_size)
+
+         /* Arithmetic overflow can occur if an Emacs integer cannot
+            represent the file size, or if the calculations below
+            overflow.  The calculations below double the file size
+            twice, so check that it can be multiplied by 4 safely.  */
+         if (XINT (end) != st.st_size
+             || ((int) st.st_size * 4) / 4 != st.st_size)
            error ("Maximum buffer size exceeded");
        }
     }
 
            error ("Maximum buffer size exceeded");
        }
     }
 
-  /* Decide the coding-system of the file.  */
-  {
-    Lisp_Object val = Qnil;
+  if (BEG < Z)
+    {
+      /* Decide the coding system to use for reading the file now
+         because we can't use an optimized method for handling
+         `coding:' tag if the current buffer is not empty.  */
+      Lisp_Object val;
+      val = Qnil;
 
 
-    if (!NILP (Vcoding_system_for_read))
-      val = Vcoding_system_for_read;
-    else
-      {
-       if (! NILP (Vset_auto_coding_function))
-         {
-           /* Find a coding system specified in the heading two lines
-              or in the tailing several lines of the file.  We assume
-              that the 1K-byte and 3K-byte for heading and tailing
-              respectively are sufficient fot this purpose.  */
-           int how_many, nread;
-
-           if (st.st_size <= (1024 * 4))
-             nread = read (fd, read_buf, 1024 * 4);
-           else
-             {
-               nread = read (fd, read_buf, 1024);
-               if (nread >= 0)
-                 {
-                   if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
-                     report_file_error ("Setting file position",
-                                        Fcons (orig_filename, Qnil));
-                   nread += read (fd, read_buf + nread, 1024 * 3);
-                 }
-             }
-        
-           if (nread < 0)
-             error ("IO error reading %s: %s",
-                    XSTRING (orig_filename)->data, strerror (errno));
-           else if (nread > 0)
-             {
-               Lisp_Object tem;
-               /* Always make this a unibyte string
-                  because we have not yet decoded it.  */
-               tem = make_unibyte_string (read_buf, nread);
-               val = call1 (Vset_auto_coding_function, tem);
-               /* Rewind the file for the actual read done later.  */
-               if (lseek (fd, 0, 0) < 0)
-                 report_file_error ("Setting file position",
-                                    Fcons (orig_filename, Qnil));
-             }
-         }
-       if (NILP (val))
-         {
-           Lisp_Object args[6], coding_systems;
+      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
+            specification if it is not seekable.  */
+         if (! not_regular && ! NILP (Vset_auto_coding_function))
+           {
+             /* Find a coding system specified in the heading two
+                lines or in the tailing several lines of the file.
+                We assume that the 1K-byte and 3K-byte for heading
+                and tailing respectively are sufficient for this
+                purpose.  */
+             int how_many, nread;
+
+             if (st.st_size <= (1024 * 4))
+               nread = emacs_read (fd, read_buf, 1024 * 4);
+             else
+               {
+                 nread = emacs_read (fd, read_buf, 1024);
+                 if (nread >= 0)
+                   {
+                     if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
+                       report_file_error ("Setting file position",
+                                          Fcons (orig_filename, Qnil));
+                     nread += emacs_read (fd, read_buf + nread, 1024 * 3);
+                   }
+               }
 
 
-           args[0] = Qinsert_file_contents, args[1] = orig_filename,
-             args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
-           coding_systems = Ffind_operation_coding_system (6, args);
-           if (CONSP (coding_systems)) val = XCONS (coding_systems)->car;
-         }
-      }
+             if (nread < 0)
+               error ("IO error reading %s: %s",
+                      XSTRING (orig_filename)->data, emacs_strerror (errno));
+             else if (nread > 0)
+               {
+                 int count = specpdl_ptr - specpdl;
+                 struct buffer *prev = current_buffer;
+
+                 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+                 temp_output_buffer_setup (" *code-converting-work*");
+                 set_buffer_internal (XBUFFER (Vstandard_output));
+                 current_buffer->enable_multibyte_characters = Qnil;
+                 insert_1_both (read_buf, nread, nread, 0, 0, 0);
+                 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+                 val = call2 (Vset_auto_coding_function,
+                              filename, make_number (nread));
+                 set_buffer_internal (prev);
+                 /* Discard the unwind protect for recovering the
+                     current buffer.  */
+                 specpdl_ptr--;
+
+                 /* Rewind the file for the actual read done later.  */
+                 if (lseek (fd, 0, 0) < 0)
+                   report_file_error ("Setting file position",
+                                      Fcons (orig_filename, Qnil));
+               }
+           }
 
 
-    if (NILP (Vcoding_system_for_read)
-       && NILP (current_buffer->enable_multibyte_characters))
-      {
-       /* We must suppress all text conversion except for end-of-line
-          conversion.  */
-       struct coding_system coding_temp;
+         if (NILP (val))
+           {
+             /* If we have not yet decided a coding system, check
+                 file-coding-system-alist.  */
+             Lisp_Object args[6], coding_systems;
+
+             args[0] = Qinsert_file_contents, args[1] = orig_filename;
+             args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
+             coding_systems = Ffind_operation_coding_system (6, args);
+             if (CONSP (coding_systems))
+               val = XCAR (coding_systems);
+           }
+       }
 
 
-       setup_coding_system (Fcheck_coding_system (val), &coding_temp);
-       setup_coding_system (Qraw_text, &coding);
-       coding.eol_type = coding_temp.eol_type;
-      }
-    else
       setup_coding_system (Fcheck_coding_system (val), &coding);
       setup_coding_system (Fcheck_coding_system (val), &coding);
-  }
+
+      if (NILP (current_buffer->enable_multibyte_characters)
+         && ! NILP (val))
+       /* We must suppress all character code conversion except for
+          end-of-line conversion.  */
+       setup_raw_text_coding_system (&coding);
+
+      coding_system_decided = 1;
+    }
+
+  /* Ensure we always set Vlast_coding_system_used.  */
+  set_coding_system = 1;
 
   /* If requested, replace the accessible part of the buffer
      with the file contents.  Avoid replacing text at the
 
   /* If requested, replace the accessible part of the buffer
      with the file contents.  Avoid replacing text at the
@@ -3359,7 +3590,10 @@ This does code conversion according to the value of\n\
      But if we discover the need for conversion, we give up on this method
      and let the following if-statement handle the replace job.  */
   if (!NILP (replace)
      But if we discover the need for conversion, we give up on this method
      and let the following if-statement handle the replace job.  */
   if (!NILP (replace)
-      && ! CODING_REQUIRE_DECODING (&coding))
+      && BEGV < ZV
+      && ! CODING_REQUIRE_DECODING (&coding)
+      && (coding.eol_type == CODING_EOL_UNDECIDED
+         || coding.eol_type == CODING_EOL_LF))
     {
       /* same_at_start and same_at_end count bytes,
         because file access counts bytes
     {
       /* same_at_start and same_at_end count bytes,
         because file access counts bytes
@@ -3387,10 +3621,10 @@ This does code conversion according to the value of\n\
        {
          int nread, bufpos;
 
        {
          int nread, bufpos;
 
-         nread = read (fd, buffer, sizeof buffer);
+         nread = emacs_read (fd, buffer, sizeof buffer);
          if (nread < 0)
            error ("IO error reading %s: %s",
          if (nread < 0)
            error ("IO error reading %s: %s",
-                  XSTRING (orig_filename)->data, strerror (errno));
+                  XSTRING (orig_filename)->data, emacs_strerror (errno));
          else if (nread == 0)
            break;
 
          else if (nread == 0)
            break;
 
@@ -3429,7 +3663,7 @@ This does code conversion according to the value of\n\
         there's no need to replace anything.  */
       if (same_at_start - BEGV_BYTE == XINT (end))
        {
         there's no need to replace anything.  */
       if (same_at_start - BEGV_BYTE == XINT (end))
        {
-         close (fd);
+         emacs_close (fd);
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
          del_range_1 (same_at_start, same_at_end, 0);
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
          del_range_1 (same_at_start, same_at_end, 0);
@@ -3458,10 +3692,10 @@ This does code conversion according to the value of\n\
          total_read = 0;
          while (total_read < trial)
            {
          total_read = 0;
          while (total_read < trial)
            {
-             nread = read (fd, buffer + total_read, trial - total_read);
+             nread = emacs_read (fd, buffer + total_read, trial - total_read);
              if (nread <= 0)
                error ("IO error reading %s: %s",
              if (nread <= 0)
                error ("IO error reading %s: %s",
-                      XSTRING (orig_filename)->data, strerror (errno));
+                      XSTRING (orig_filename)->data, emacs_strerror (errno));
              total_read += nread;
            }
          /* Scan this bufferful from the end, comparing with
              total_read += nread;
            }
          /* Scan this bufferful from the end, comparing with
@@ -3495,7 +3729,14 @@ This does code conversion according to the value of\n\
 
          /* We win!  We can handle REPLACE the optimized way.  */
 
 
          /* We win!  We can handle REPLACE the optimized way.  */
 
-         /* Extends the end of non-matching text area to multibyte
+         /* Extend the start of non-matching text area to multibyte
+             character boundary.  */
+         if (! NILP (current_buffer->enable_multibyte_characters))
+           while (same_at_start > BEGV_BYTE
+                  && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
+             same_at_start--;
+
+         /* Extend the end of non-matching text area to multibyte
              character boundary.  */
          if (! NILP (current_buffer->enable_multibyte_characters))
            while (same_at_end < ZV_BYTE
              character boundary.  */
          if (! NILP (current_buffer->enable_multibyte_characters))
            while (same_at_end < ZV_BYTE
@@ -3535,7 +3776,7 @@ This does code conversion according to the value of\n\
      is needed, in a simple way that needs a lot of memory.
      The preceding if-statement handles the case of no conversion
      in a more optimized way.  */
      is needed, in a simple way that needs a lot of memory.
      The preceding if-statement handles the case of no conversion
      in a more optimized way.  */
-  if (!NILP (replace) && ! replace_handled)
+  if (!NILP (replace) && ! replace_handled && BEGV < ZV)
     {
       int same_at_start = BEGV_BYTE;
       int same_at_end = ZV_BYTE;
     {
       int same_at_start = BEGV_BYTE;
       int same_at_end = ZV_BYTE;
@@ -3551,7 +3792,7 @@ This does code conversion according to the value of\n\
 
       if (lseek (fd, XINT (beg), 0) < 0)
        {
 
       if (lseek (fd, XINT (beg), 0) < 0)
        {
-         free (conversion_buffer);
+         xfree (conversion_buffer);
          report_file_error ("Setting file position",
                             Fcons (orig_filename, Qnil));
        }
          report_file_error ("Setting file position",
                             Fcons (orig_filename, Qnil));
        }
@@ -3565,13 +3806,13 @@ This does code conversion according to the value of\n\
        {
          /* try is reserved in some compilers (Microsoft C) */
          int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
        {
          /* try is reserved in some compilers (Microsoft C) */
          int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
-         char *destination = read_buf + unprocessed;
+         unsigned char *destination = read_buf + unprocessed;
          int this;
 
          /* Allow quitting out of the actual I/O.  */
          immediate_quit = 1;
          QUIT;
          int this;
 
          /* Allow quitting out of the actual I/O.  */
          immediate_quit = 1;
          QUIT;
-         this = read (fd, destination, trytry);
+         this = emacs_read (fd, destination, trytry);
          immediate_quit = 0;
 
          if (this < 0 || this + unprocessed == 0)
          immediate_quit = 0;
 
          if (this < 0 || this + unprocessed == 0)
@@ -3620,11 +3861,11 @@ This does code conversion according to the value of\n\
 
       if (how_much < 0)
        {
 
       if (how_much < 0)
        {
-         free (conversion_buffer);
+         xfree (conversion_buffer);
 
          if (how_much == -1)
            error ("IO error reading %s: %s",
 
          if (how_much == -1)
            error ("IO error reading %s: %s",
-                  XSTRING (orig_filename)->data, strerror (errno));
+                  XSTRING (orig_filename)->data, emacs_strerror (errno));
          else if (how_much == -2)
            error ("maximum buffer size exceeded");
        }
          else if (how_much == -2)
            error ("maximum buffer size exceeded");
        }
@@ -3642,14 +3883,22 @@ This does code conversion according to the value of\n\
 
       if (bufpos == inserted)
        {
 
       if (bufpos == inserted)
        {
-         free (conversion_buffer);
-         close (fd);
+         xfree (conversion_buffer);
+         emacs_close (fd);
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
-         del_range_1 (same_at_start, same_at_end, 0);
+         del_range_byte (same_at_start, same_at_end, 0);
+         inserted = 0;
          goto handled;
        }
 
          goto handled;
        }
 
+      /* Extend the start of non-matching text area to multibyte
+        character boundary.  */
+      if (! NILP (current_buffer->enable_multibyte_characters))
+       while (same_at_start > BEGV_BYTE
+              && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
+         same_at_start--;
+
       /* Scan this bufferful from the end, comparing with
         the Emacs buffer.  */
       bufpos = inserted;
       /* Scan this bufferful from the end, comparing with
         the Emacs buffer.  */
       bufpos = inserted;
@@ -3660,6 +3909,13 @@ This does code conversion according to the value of\n\
             && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
        same_at_end--, bufpos--;
 
             && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
        same_at_end--, bufpos--;
 
+      /* Extend the end of non-matching text area to multibyte
+        character boundary.  */
+      if (! NILP (current_buffer->enable_multibyte_characters))
+       while (same_at_end < ZV_BYTE
+              && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
+         same_at_end++;
+
       /* Don't try to reuse the same piece of text twice.  */
       overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
       if (overlap > 0)
       /* Don't try to reuse the same piece of text twice.  */
       overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
       if (overlap > 0)
@@ -3674,14 +3930,26 @@ This does code conversion according to the value of\n\
         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);
         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);
-      del_range_byte (same_at_start, same_at_end, 0);
-      SET_PT_BOTH (GPT, GPT_BYTE);
 
 
+      if (same_at_end != same_at_start)
+       {
+         del_range_byte (same_at_start, same_at_end, 0);
+         temp = GPT;
+         same_at_start = GPT_BYTE;
+       }
+      else
+       {
+         temp = BYTE_TO_CHAR (same_at_start);
+       }
+      /* 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,
                0, 0, 0);
       insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
                0, 0, 0);
+      /* Set `inserted' to the number of inserted characters.  */
+      inserted = PT - temp;
 
       free (conversion_buffer);
 
       free (conversion_buffer);
-      close (fd);
+      emacs_close (fd);
       specpdl_ptr--;
 
       goto handled;
       specpdl_ptr--;
 
       goto handled;
@@ -3738,7 +4006,8 @@ This does code conversion according to the value of\n\
       /* Allow quitting out of the actual I/O.  */
       immediate_quit = 1;
       QUIT;
       /* Allow quitting out of the actual I/O.  */
       immediate_quit = 1;
       QUIT;
-      this = read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1, trytry);
+      this = emacs_read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
+                        trytry);
       immediate_quit = 0;
 
       if (this <= 0)
       immediate_quit = 0;
 
       if (this <= 0)
@@ -3769,16 +4038,81 @@ This does code conversion according to the value of\n\
     /* Put an anchor to ensure multi-byte form ends at gap.  */
     *GPT_ADDR = 0;
 
     /* Put an anchor to ensure multi-byte form ends at gap.  */
     *GPT_ADDR = 0;
 
-  close (fd);
+  emacs_close (fd);
 
   /* Discard the unwind protect for closing the file.  */
   specpdl_ptr--;
 
   if (how_much < 0)
     error ("IO error reading %s: %s",
 
   /* Discard the unwind protect for closing the file.  */
   specpdl_ptr--;
 
   if (how_much < 0)
     error ("IO error reading %s: %s",
-          XSTRING (orig_filename)->data, strerror (errno));
+          XSTRING (orig_filename)->data, emacs_strerror (errno));
 
 
-  if (inserted > 0)
+  if (! coding_system_decided)
+    {
+      /* The coding system is not yet decided.  Decide it by an
+        optimized method for handling `coding:' tag.  */
+      Lisp_Object val;
+      val = Qnil;
+
+      if (!NILP (Vcoding_system_for_read))
+       val = Vcoding_system_for_read;
+      else
+       {
+         if (inserted > 0 && ! NILP (Vset_auto_coding_function))
+           {
+             /* Since we are sure that the current buffer was
+                empty before the insertion, we can toggle
+                enable-multibyte-characters directly here without
+                taking care of marker adjustment and byte
+                combining problem.  */
+             Lisp_Object prev_multibyte;
+             int count = specpdl_ptr - specpdl;
+
+             prev_multibyte = current_buffer->enable_multibyte_characters;
+             current_buffer->enable_multibyte_characters = Qnil;
+             record_unwind_protect (set_auto_coding_unwind,
+                                    prev_multibyte);
+             val = call2 (Vset_auto_coding_function,
+                          filename, make_number (inserted));
+             /* Discard the unwind protect for recovering the
+                error of Vset_auto_coding_function.  */
+             specpdl_ptr--;
+             current_buffer->enable_multibyte_characters = prev_multibyte;
+             TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+           }
+
+         if (NILP (val))
+           {
+             /* If the coding system is not yet decided, check
+                file-coding-system-alist.  */
+             Lisp_Object args[6], coding_systems;
+
+             args[0] = Qinsert_file_contents, args[1] = orig_filename;
+             args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
+             coding_systems = Ffind_operation_coding_system (6, args);
+             if (CONSP (coding_systems))
+               val = XCAR (coding_systems);
+           }
+       }
+
+      /* The following kludgy code is to avoid some compiler bug.
+        We can't simply do
+        setup_coding_system (val, &coding);
+        on some system.  */
+      {
+       struct coding_system temp_coding;
+       setup_coding_system (val, &temp_coding);
+       bcopy (&temp_coding, &coding, sizeof coding);
+      }
+
+      if (NILP (current_buffer->enable_multibyte_characters)
+         && ! NILP (val))
+       /* We must suppress all character code conversion except for
+          end-of-line conversion.  */
+       setup_raw_text_coding_system (&coding);
+    }
+
+  if (inserted > 0 || coding.type == coding_type_ccl)
     {
       if (CODING_MAY_REQUIRE_DECODING (&coding))
        {
     {
       if (CODING_MAY_REQUIRE_DECODING (&coding))
        {
@@ -3803,20 +4137,22 @@ This does code conversion according to the value of\n\
                               PT + inserted_byte, PT_BYTE + inserted_byte,
                               inserted);
        }
                               PT + inserted_byte, PT_BYTE + inserted_byte,
                               inserted);
        }
-
-#ifdef DOS_NT
-      /* Use the conversion type to determine buffer-file-type
-        (find-buffer-file-type is now used to help determine the
-        conversion).  */
-      if (coding.eol_type != CODING_EOL_UNDECIDED 
-         && coding.eol_type != CODING_EOL_LF)
-       current_buffer->buffer_file_type = Qnil;
       else
       else
-       current_buffer->buffer_file_type = Qt;
-#endif
+       adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
+                            inserted);
     }
 
     }
 
-  set_coding_system = 1;
+#ifdef DOS_NT
+  /* Use the conversion type to determine buffer-file-type
+     (find-buffer-file-type is now used to help determine the
+     conversion).  */
+  if ((coding.eol_type == CODING_EOL_UNDECIDED 
+       || coding.eol_type == CODING_EOL_LF)
+      && ! CODING_REQUIRE_DECODING (&coding))
+    current_buffer->buffer_file_type = Qt;
+  else
+    current_buffer->buffer_file_type = Qnil;
+#endif
 
  notfound:
  handled:
 
  notfound:
  handled:
@@ -3941,12 +4277,22 @@ If VISIT is neither t nor nil nor a string,\n\
   that means do not print the \"Wrote file\" message.\n\
 The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
   use for locking and unlocking, overriding FILENAME and VISIT.\n\
   that means do not print the \"Wrote file\" message.\n\
 The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
   use for locking and unlocking, overriding FILENAME and VISIT.\n\
-The optional seventh arg CONFIRM, if non-nil, says ask for confirmation\n\
-  before overwriting an existing file.\n\
+The optional seventh arg MUSTBENEW, if non-nil, insists on a check\n\
+  for an existing file with the same name.  If MUSTBENEW is `excl',\n\
+  that means to get an error if the file already exists; never overwrite.\n\
+  If MUSTBENEW is neither nil nor `excl', that means ask for\n\
+  confirmation before overwriting, but do go ahead and overwrite the file\n\
+  if the user confirms.\n\
 Kludgy feature: if START is a string, then that string is written\n\
 Kludgy feature: if START is a string, then that string is written\n\
-to the file, instead of any buffer contents, and END is ignored.")
-  (start, end, filename, append, visit, lockname, confirm)
-     Lisp_Object start, end, filename, append, visit, lockname, confirm;
+to the file, instead of any buffer contents, and END is ignored.\n\
+\n\
+This does code conversion according to the value of\n\
+`coding-system-for-write', `buffer-file-coding-system', or\n\
+`file-coding-system-alist', and sets the variable\n\
+`last-coding-system-used' to the coding system actually used.")
+
+  (start, end, filename, append, visit, lockname, mustbenew)
+     Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
 {
   register int desc;
   int failure;
 {
   register int desc;
   int failure;
@@ -3987,7 +4333,7 @@ to the file, instead of any buffer contents, and END is ignored.")
       val = Qnil;
     else if (!NILP (Vcoding_system_for_write))
       val = Vcoding_system_for_write;
       val = Qnil;
     else if (!NILP (Vcoding_system_for_write))
       val = Vcoding_system_for_write;
-    else if (NILP (current_buffer->enable_multibyte_characters))
+    else
       {
        /* If the variable `buffer-file-coding-system' is set locally,
           it means that the file was read with some kind of code
       {
        /* If the variable `buffer-file-coding-system' is set locally,
           it means that the file was read with some kind of code
@@ -3998,38 +4344,72 @@ to the file, instead of any buffer contents, and END is ignored.")
           If it is not set locally, we anyway have to convert EOL
           format if the default value of `buffer-file-coding-system'
           tells that it is not Unix-like (LF only) format.  */
           If it is not set locally, we anyway have to convert EOL
           format if the default value of `buffer-file-coding-system'
           tells that it is not Unix-like (LF only) format.  */
+       int using_default_coding = 0;
+       int force_raw_text = 0;
+
        val = current_buffer->buffer_file_coding_system;
        val = current_buffer->buffer_file_coding_system;
-       if (NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
+       if (NILP (val)
+           || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
          {
          {
-           struct coding_system coding_temp;
+           val = Qnil;
+           if (NILP (current_buffer->enable_multibyte_characters))
+             force_raw_text = 1;
+         }
+       
+       if (NILP (val))
+         {
+           /* Check file-coding-system-alist.  */
+           Lisp_Object args[7], coding_systems;
+
+           args[0] = Qwrite_region; args[1] = start; args[2] = end;
+           args[3] = filename; args[4] = append; args[5] = visit;
+           args[6] = lockname;
+           coding_systems = Ffind_operation_coding_system (7, args);
+           if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
+             val = XCDR (coding_systems);
+         }
+
+       if (NILP (val)
+           && !NILP (current_buffer->buffer_file_coding_system))
+         {
+           /* If we still have not decided a coding system, use the
+              default value of buffer-file-coding-system.  */
+           val = current_buffer->buffer_file_coding_system;
+           using_default_coding = 1;
+         }
+           
+       if (!force_raw_text
+           && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
+         /* Confirm that VAL can surely encode the current region.  */
+         val = call3 (Vselect_safe_coding_system_function, start, end, val);
 
 
-           setup_coding_system (Fcheck_coding_system (val), &coding_temp);
-           if (coding_temp.eol_type == CODING_EOL_CRLF
-               || coding_temp.eol_type == CODING_EOL_CR)
+       setup_coding_system (Fcheck_coding_system (val), &coding);
+       if (coding.eol_type == CODING_EOL_UNDECIDED
+           && !using_default_coding)
+         {
+           if (! EQ (default_buffer_file_coding.symbol,
+                     buffer_defaults.buffer_file_coding_system))
+             setup_coding_system (buffer_defaults.buffer_file_coding_system,
+                                  &default_buffer_file_coding);
+           if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
              {
              {
-               setup_coding_system (Qraw_text, &coding);
-               coding.eol_type = coding_temp.eol_type;
-               goto done_setup_coding;
+               Lisp_Object subsidiaries;
+
+               coding.eol_type = default_buffer_file_coding.eol_type;
+               subsidiaries = Fget (coding.symbol, Qeol_type);
+               if (VECTORP (subsidiaries)
+                   && XVECTOR (subsidiaries)->size == 3)
+                 coding.symbol
+                   = XVECTOR (subsidiaries)->contents[coding.eol_type];
              }
              }
-           val = Qnil;
          }
          }
+
+       if (force_raw_text)
+         setup_raw_text_coding_system (&coding);
+       goto done_setup_coding;
       }
       }
-    else
-      {
-       Lisp_Object args[7], coding_systems;
-
-       args[0] = Qwrite_region; args[1] = start; args[2] = end;
-       args[3] = filename; args[4] = append; args[5] = visit;
-       args[6] = lockname;
-       coding_systems = Ffind_operation_coding_system (7, args);
-       val = (CONSP (coding_systems) && !NILP (XCONS (coding_systems)->cdr)
-              ? XCONS (coding_systems)->cdr
-              : current_buffer->buffer_file_coding_system);
-       /* Confirm that VAL can surely encode the current region.  */
-       if (Ffboundp (Vselect_safe_coding_system_function))
-         val = call3 (Vselect_safe_coding_system_function, start, end, val);
-      }
-    setup_coding_system (Fcheck_coding_system (val), &coding); 
+
+    setup_coding_system (Fcheck_coding_system (val), &coding);
 
   done_setup_coding:
     if (!STRINGP (start) && !NILP (current_buffer->selective_display))
 
   done_setup_coding:
     if (!STRINGP (start) && !NILP (current_buffer->selective_display))
@@ -4040,7 +4420,7 @@ to the file, instead of any buffer contents, and END is ignored.")
 
   filename = Fexpand_file_name (filename, Qnil);
 
 
   filename = Fexpand_file_name (filename, Qnil);
 
-  if (! NILP (confirm))
+  if (! NILP (mustbenew) && mustbenew != Qexcl)
     barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
 
   if (STRINGP (visit))
     barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
 
   if (STRINGP (visit))
@@ -4120,9 +4500,9 @@ to the file, instead of any buffer contents, and END is ignored.")
   desc = -1;
   if (!NILP (append))
 #ifdef DOS_NT
   desc = -1;
   if (!NILP (append))
 #ifdef DOS_NT
-    desc = open (fn, O_WRONLY | buffer_file_type);
+    desc = emacs_open (fn, O_WRONLY | buffer_file_type, 0);
 #else  /* not DOS_NT */
 #else  /* not DOS_NT */
-    desc = open (fn, O_WRONLY);
+    desc = emacs_open (fn, O_WRONLY, 0);
 #endif /* not DOS_NT */
 
   if (desc < 0 && (NILP (append) || errno == ENOENT))
 #endif /* not DOS_NT */
 
   if (desc < 0 && (NILP (append) || errno == ENOENT))
@@ -4130,7 +4510,7 @@ to the file, instead of any buffer contents, and END is ignored.")
     if (auto_saving)    /* Overwrite any previous version of autosave file */
       {
        vms_truncate (fn);      /* if fn exists, truncate to zero length */
     if (auto_saving)    /* Overwrite any previous version of autosave file */
       {
        vms_truncate (fn);      /* if fn exists, truncate to zero length */
-       desc = open (fn, O_RDWR);
+       desc = emacs_open (fn, O_RDWR, 0);
        if (desc < 0)
          desc = creat_copy_attrs (STRINGP (current_buffer->filename)
                                   ? XSTRING (current_buffer->filename)->data : 0,
        if (desc < 0)
          desc = creat_copy_attrs (STRINGP (current_buffer->filename)
                                   ? XSTRING (current_buffer->filename)->data : 0,
@@ -4163,7 +4543,7 @@ to the file, instead of any buffer contents, and END is ignored.")
                    /* We can't make a new version;
                       try to truncate and rewrite existing version if any.  */
                    vms_truncate (fn);
                    /* We can't make a new version;
                       try to truncate and rewrite existing version if any.  */
                    vms_truncate (fn);
-                   desc = open (fn, O_RDWR);
+                   desc = emacs_open (fn, O_RDWR, 0);
                  }
 #endif
              }
                  }
 #endif
              }
@@ -4173,11 +4553,14 @@ to the file, instead of any buffer contents, and END is ignored.")
       }
 #else /* not VMS */
 #ifdef DOS_NT
       }
 #else /* not VMS */
 #ifdef DOS_NT
-  desc = open (fn,
-              O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
-              S_IREAD | S_IWRITE);
+  desc = emacs_open (fn,
+                    O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type
+                    | (mustbenew == Qexcl ? O_EXCL : 0),
+                    S_IREAD | S_IWRITE);
 #else  /* not DOS_NT */
 #else  /* not DOS_NT */
-  desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
+  desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
+                    | (mustbenew == Qexcl ? O_EXCL : 0),
+                    auto_saving ? auto_save_mode_bits : 0666);
 #endif /* not DOS_NT */
 #endif /* not VMS */
 
 #endif /* not DOS_NT */
 #endif /* not VMS */
 
@@ -4195,7 +4578,7 @@ to the file, instead of any buffer contents, and END is ignored.")
 
   record_unwind_protect (close_file_unwind, make_number (desc));
 
 
   record_unwind_protect (close_file_unwind, make_number (desc));
 
-  if (!NILP (append))
+  if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
     if (lseek (desc, 0, 2) < 0)
       {
 #ifdef CLASH_DETECTION
     if (lseek (desc, 0, 2) < 0)
       {
 #ifdef CLASH_DETECTION
@@ -4322,7 +4705,7 @@ to the file, instead of any buffer contents, and END is ignored.")
 #endif
 
   /* NFS can report a write failure now.  */
 #endif
 
   /* NFS can report a write failure now.  */
-  if (close (desc) < 0)
+  if (emacs_close (desc) < 0)
     failure = 1, save_errno = errno;
 
 #ifdef VMS
     failure = 1, save_errno = errno;
 
 #ifdef VMS
@@ -4356,7 +4739,7 @@ to the file, instead of any buffer contents, and END is ignored.")
 
   if (failure)
     error ("IO error writing %s: %s", XSTRING (filename)->data,
 
   if (failure)
     error ("IO error writing %s: %s", XSTRING (filename)->data,
-          strerror (save_errno));
+          emacs_strerror (save_errno));
 
   if (visiting)
     {
 
   if (visiting)
     {
@@ -4519,6 +4902,7 @@ a_write (desc, addr, nbytes, bytepos, annot, coding)
        }
       *annot = Fcdr (*annot);
     }
        }
       *annot = Fcdr (*annot);
     }
+  return 0;
 }
 
 #ifndef WRITE_BUF_SIZE
 }
 
 #ifndef WRITE_BUF_SIZE
@@ -4541,13 +4925,22 @@ e_write (desc, addr, nbytes, coding)
      now it is handled within encode_coding.  */
   while (1)
     {
      now it is handled within encode_coding.  */
   while (1)
     {
-      encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
+      int result;
+
+      result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
       nbytes -= coding->consumed, addr += coding->consumed;
       if (coding->produced > 0)
        {
       nbytes -= coding->consumed, addr += coding->consumed;
       if (coding->produced > 0)
        {
-         coding->produced -= write (desc, buf, coding->produced);
+         coding->produced -= emacs_write (desc, buf, coding->produced);
          if (coding->produced) return -1;
        }
          if (coding->produced) return -1;
        }
+      if (result == CODING_FINISH_INSUFFICIENT_SRC)
+       {
+         /* The source text ends by an incomplete multibyte form.
+             There's no way other than write it out as is.  */
+         nbytes -= emacs_write (desc, addr, nbytes);
+         if (nbytes) return -1;
+       }
       if (nbytes <= 0)
        break;
     }
       if (nbytes <= 0)
        break;
     }
@@ -4694,8 +5087,8 @@ do_auto_save_unwind (stream)  /* used as unwind-protect function */
 {
   auto_saving = 0;
   if (!NILP (stream))
 {
   auto_saving = 0;
   if (!NILP (stream))
-    fclose ((FILE *) (XFASTINT (XCONS (stream)->car) << 16
-                     | XFASTINT (XCONS (stream)->cdr)));
+    fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
+                     | XFASTINT (XCDR (stream))));
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -4723,9 +5116,6 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf;
   int auto_saved = 0;
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf;
   int auto_saved = 0;
-  char *omessage = echo_area_glyphs;
-  int omessage_length = echo_area_glyphs_length;
-  int oldmultibyte = message_enable_multibyte;
   int do_handled_files;
   Lisp_Object oquit;
   FILE *stream;
   int do_handled_files;
   Lisp_Object oquit;
   FILE *stream;
@@ -4733,7 +5123,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
   int count = specpdl_ptr - specpdl;
   int *ptr;
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
   int count = specpdl_ptr - specpdl;
   int *ptr;
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
-
+  int message_p = push_message ();
+  
   /* Ordinarily don't quit within this function,
      but don't make it impossible to quit (in case we get hung in I/O).  */
   oquit = Vquit_flag;
   /* Ordinarily don't quit within this function,
      but don't make it impossible to quit (in case we get hung in I/O).  */
   oquit = Vquit_flag;
@@ -4758,8 +5149,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
          /* Arrange to close that file whether or not we get an error.
             Also reset auto_saving to 0.  */
          lispstream = Fcons (Qnil, Qnil);
          /* Arrange to close that file whether or not we get an error.
             Also reset auto_saving to 0.  */
          lispstream = Fcons (Qnil, Qnil);
-         XSETFASTINT (XCONS (lispstream)->car, (EMACS_UINT)stream >> 16);
-         XSETFASTINT (XCONS (lispstream)->cdr, (EMACS_UINT)stream & 0xffff);
+         XSETFASTINT (XCAR (lispstream), (EMACS_UINT)stream >> 16);
+         XSETFASTINT (XCDR (lispstream), (EMACS_UINT)stream & 0xffff);
        }
       else
        lispstream = Qnil;
        }
       else
        lispstream = Qnil;
@@ -4782,9 +5173,9 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
      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++)
      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 = XCONS (tail)->cdr)
+    for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
       {
       {
-       buf = XCONS (XCONS (tail)->car)->cdr;
+       buf = XCDR (XCAR (tail));
        b = XBUFFER (buf);
 
        /* Record all the buffers that have auto save mode
        b = XBUFFER (buf);
 
        /* Record all the buffers that have auto save mode
@@ -4877,10 +5268,10 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
 
   if (auto_saved && NILP (no_message))
     {
 
   if (auto_saved && NILP (no_message))
     {
-      if (omessage)
+      if (message_p)
        {
          sit_for (1, 0, 0, 0, 0);
        {
          sit_for (1, 0, 0, 0, 0);
-         message2 (omessage, omessage_length, oldmultibyte);
+         restore_message ();
        }
       else
        message1 ("Auto-saving...done");
        }
       else
        message1 ("Auto-saving...done");
@@ -4888,6 +5279,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
 
   Vquit_flag = oquit;
 
 
   Vquit_flag = oquit;
 
+  pop_message ();
   unbind_to (count, Qnil);
   return Qnil;
 }
   unbind_to (count, Qnil);
   return Qnil;
 }
@@ -5046,7 +5438,7 @@ DIR defaults to current buffer's directory default.")
   (prompt, dir, default_filename, mustmatch, initial)
      Lisp_Object prompt, dir, default_filename, mustmatch, initial;
 {
   (prompt, dir, default_filename, mustmatch, initial)
      Lisp_Object prompt, dir, default_filename, mustmatch, initial;
 {
-  Lisp_Object val, insdef, insdef1, tem;
+  Lisp_Object val, insdef, tem;
   struct gcpro gcpro1, gcpro2;
   register char *homedir;
   int replace_in_history = 0;
   struct gcpro gcpro1, gcpro2;
   register char *homedir;
   int replace_in_history = 0;
@@ -5078,6 +5470,22 @@ DIR defaults to current buffer's directory default.")
                         STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
       XSTRING (dir)->data[0] = '~';
     }
                         STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
       XSTRING (dir)->data[0] = '~';
     }
+  /* Likewise for default_filename.  */
+  if (homedir != 0
+      && STRINGP (default_filename)
+      && !strncmp (homedir, XSTRING (default_filename)->data, strlen (homedir))
+      && IS_DIRECTORY_SEP (XSTRING (default_filename)->data[strlen (homedir)]))
+    {
+      default_filename
+       = make_string (XSTRING (default_filename)->data + strlen (homedir) - 1,
+                      STRING_BYTES (XSTRING (default_filename)) - strlen (homedir) + 1);
+      XSTRING (default_filename)->data[0] = '~';
+    }
+  if (!NILP (default_filename))
+    {
+      CHECK_STRING (default_filename, 3);
+      default_filename = double_dollars (default_filename);
+    }
 
   if (insert_default_directory && STRINGP (dir))
     {
 
   if (insert_default_directory && STRINGP (dir))
     {
@@ -5090,31 +5498,41 @@ DIR defaults to current buffer's directory default.")
          args[1] = initial;
          insdef = Fconcat (2, args);
          pos = make_number (XSTRING (double_dollars (dir))->size);
          args[1] = initial;
          insdef = Fconcat (2, args);
          pos = make_number (XSTRING (double_dollars (dir))->size);
-         insdef1 = Fcons (double_dollars (insdef), pos);
+         insdef = Fcons (double_dollars (insdef), pos);
        }
       else
        }
       else
-       insdef1 = double_dollars (insdef);
+       insdef = double_dollars (insdef);
     }
   else if (STRINGP (initial))
     }
   else if (STRINGP (initial))
-    {
-      insdef = initial;
-      insdef1 = Fcons (double_dollars (insdef), make_number (0));
-    }
+    insdef = Fcons (double_dollars (initial), make_number (0));
   else
   else
-    insdef = Qnil, insdef1 = Qnil;
+    insdef = Qnil;
 
 
-#ifdef VMS
   count = specpdl_ptr - specpdl;
   count = specpdl_ptr - specpdl;
+#ifdef VMS
   specbind (intern ("completion-ignore-case"), Qt);
 #endif
 
   specbind (intern ("completion-ignore-case"), Qt);
 #endif
 
+  specbind (intern ("minibuffer-completing-file-name"), Qt);
+
   GCPRO2 (insdef, default_filename);
   GCPRO2 (insdef, default_filename);
-  val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
-                         dir, mustmatch, insdef1,
-                         Qfile_name_history, default_filename, Qnil);
+  
+#ifdef USE_MOTIF
+  if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
+      && use_dialog_box
+      && have_menus_p ())
+    {
+      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
+      add_to_history = 1;
+    }
+  else
+#endif
+    val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
+                           dir, mustmatch, insdef,
+                           Qfile_name_history, default_filename, Qnil);
 
   tem = Fsymbol_value (Qfile_name_history);
 
   tem = Fsymbol_value (Qfile_name_history);
-  if (CONSP (tem) && EQ (XCONS (tem)->car, val))
+  if (CONSP (tem) && EQ (XCAR (tem), val))
     replace_in_history = 1;
 
   /* If Fcompleting_read returned the inserted default string itself
     replace_in_history = 1;
 
   /* If Fcompleting_read returned the inserted default string itself
@@ -5132,15 +5550,12 @@ DIR defaults to current buffer's directory default.")
       val = build_string ("");
     }
 
       val = build_string ("");
     }
 
-#ifdef VMS
   unbind_to (count, Qnil);
   unbind_to (count, Qnil);
-#endif
-
   UNGCPRO;
   if (NILP (val))
     error ("No file name specified");
 
   UNGCPRO;
   if (NILP (val))
     error ("No file name specified");
 
-  tem = Fstring_equal (val, insdef);
+  tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
 
   if (!NILP (tem) && !NILP (default_filename))
     val = default_filename;
 
   if (!NILP (tem) && !NILP (default_filename))
     val = default_filename;
@@ -5156,19 +5571,31 @@ DIR defaults to current buffer's directory default.")
   if (replace_in_history)
     /* Replace what Fcompleting_read added to the history
        with what we will actually return.  */
   if (replace_in_history)
     /* Replace what Fcompleting_read added to the history
        with what we will actually return.  */
-    XCONS (Fsymbol_value (Qfile_name_history))->car = val;
+    XCAR (Fsymbol_value (Qfile_name_history)) = double_dollars (val);
   else if (add_to_history)
     {
       /* Add the value to the history--but not if it matches
         the last value already there.  */
   else if (add_to_history)
     {
       /* Add the value to the history--but not if it matches
         the last value already there.  */
+      Lisp_Object val1 = double_dollars (val);
       tem = Fsymbol_value (Qfile_name_history);
       tem = Fsymbol_value (Qfile_name_history);
-      if (! CONSP (tem) || NILP (Fequal (XCONS (tem)->car, val)))
+      if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
        Fset (Qfile_name_history,
        Fset (Qfile_name_history,
-             Fcons (val, tem));
+             Fcons (val1, tem));
     }
     }
+    
   return val;
 }
   return val;
 }
+
+\f
+void
+init_fileio_once ()
+{
+  /* Must be set before any path manipulation is performed.  */
+  XSETFASTINT (Vdirectory_sep_char, '/');
+}
+
 \f
 \f
+void
 syms_of_fileio ()
 {
   Qexpand_file_name = intern ("expand-file-name");
 syms_of_fileio ()
 {
   Qexpand_file_name = intern ("expand-file-name");
@@ -5243,6 +5670,8 @@ syms_of_fileio ()
   staticpro (&Qfile_already_exists);
   Qfile_date_error = intern ("file-date-error");
   staticpro (&Qfile_date_error);
   staticpro (&Qfile_already_exists);
   Qfile_date_error = intern ("file-date-error");
   staticpro (&Qfile_date_error);
+  Qexcl = intern ("excl");
+  staticpro (&Qexcl);
 
 #ifdef DOS_NT
   Qfind_buffer_file_type = intern ("find-buffer-file-type");
 
 #ifdef DOS_NT
   Qfind_buffer_file_type = intern ("find-buffer-file-type");
@@ -5312,7 +5741,6 @@ The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
 This variable affects the built-in functions only on Windows,\n\
 on other platforms, it is initialized so that Lisp code can find out\n\
 what the normal separator is.");
 This variable affects the built-in functions only on Windows,\n\
 on other platforms, it is initialized so that Lisp code can find out\n\
 what the normal separator is.");
-  XSETFASTINT (Vdirectory_sep_char, '/');
 
   DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
     "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
 
   DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
     "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
@@ -5332,9 +5760,11 @@ for its argument.");
   DEFVAR_LISP ("set-auto-coding-function",
               &Vset_auto_coding_function,
     "If non-nil, a function to call to decide a coding system of file.\n\
   DEFVAR_LISP ("set-auto-coding-function",
               &Vset_auto_coding_function,
     "If non-nil, a function to call to decide a coding system of file.\n\
-One argument is passed to this function: the string of concatination\n\
-or the heading 1K-byte and the tailing 3K-byte of a file to be read.\n\
-This function should return a coding system to decode the file contents\n\
+Two arguments are passed to this function: the file name\n\
+and the length of a file contents following the point.\n\
+This function should return a coding system to decode the file contents.\n\
+It should check the file name against `auto-coding-alist'.\n\
+If no coding system is decided, it should check a coding system\n\
 specified in the heading lines with the format:\n\
        -*- ... coding: CODING-SYSTEM; ... -*-\n\
 or local variable spec of the tailing lines with `coding:' tag.");
 specified in the heading lines with the format:\n\
        -*- ... coding: CODING-SYSTEM; ... -*-\n\
 or local variable spec of the tailing lines with `coding:' tag.");