(read-abbrev-file): Don't set save-abbrevs.
[bpt/emacs.git] / src / dired.c
index eb124f5..eb10f7f 100644 (file)
@@ -1,5 +1,6 @@
 /* Lisp functions for making directory listings.
-   Copyright (C) 1985, 1986, 1993, 1994, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1994, 1999, 2000, 2001
+     Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -26,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/stat.h>
 
 #include "systime.h"
+#include <errno.h>
 
 #ifdef VMS
 #include <string.h>
@@ -96,8 +98,6 @@ extern struct re_pattern_buffer *compile_pattern ();
 /* From filemode.c.  Can't go in Lisp.h because of `stat'.  */
 extern void filemodestring P_ ((struct stat *, char *));
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
 /* if system does not have symbolic links, it does not have lstat.
    In that case, use ordinary stat instead.  */
 
@@ -131,6 +131,7 @@ directory_files_internal_unwind (dh)
 /* Function shared by Fdirectory_files and Fdirectory_files_and_attributes.  
    When ATTRS is zero, return a list of directory filenames; when
    non-zero, return a list of directory filenames and their attributes.  */
+
 Lisp_Object
 directory_files_internal (directory, full, match, nosort, attrs)
      Lisp_Object directory, full, match, nosort;
@@ -155,7 +156,7 @@ directory_files_internal (directory, full, match, nosort, attrs)
 
   if (!NILP (match))
     {
-      CHECK_STRING (match, 3);
+      CHECK_STRING (match);
 
       /* MATCH might be a flawed regular expression.  Rather than
         catching and signaling our own errors, we just call
@@ -207,8 +208,19 @@ directory_files_internal (directory, full, match, nosort, attrs)
 #endif /* not VMS */
 
   /* Loop reading blocks until EOF or error.  */
-  while ((dp = readdir (d)) != NULL)
+  for (;;)
     {
+      errno = 0;
+      dp = readdir (d);
+
+#ifdef EAGAIN
+      if (dp == NULL && errno == EAGAIN)
+       continue;
+#endif
+      
+      if (dp == NULL)
+       break;
+
       if (DIRENTRY_NONEMPTY (dp))
        {
          int len;
@@ -217,7 +229,7 @@ directory_files_internal (directory, full, match, nosort, attrs)
          struct gcpro gcpro1, gcpro2;
 
          len = NAMLEN (dp);
-         name = finalname = make_string (dp->d_name, len);
+         name = finalname = make_unibyte_string (dp->d_name, len);
          GCPRO2 (finalname, name);
          
          /* Note: ENCODE_FILE can GC; it should protect its argument,
@@ -296,9 +308,6 @@ directory_files_internal (directory, full, match, nosort, attrs)
     }
 
   retry_p = 0;
-#ifdef EAGAIN
-  retry_p |= errno == EAGAIN;
-#endif
 #ifdef EINTR
   retry_p |= errno == EINTR;
 #endif
@@ -309,7 +318,10 @@ directory_files_internal (directory, full, match, nosort, attrs)
   specpdl_ptr = specpdl + count;
 
   if (retry_p)
-    goto retry;
+    {
+      list = Qnil;
+      goto retry;
+    }
 
   if (NILP (nosort))
     list = Fsort (Fnreverse (list),
@@ -392,7 +404,10 @@ DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
 Returns the longest string\n\
 common to all file names in DIRECTORY that start with FILE.\n\
 If there is only one and FILE matches it exactly, returns t.\n\
-Returns nil if DIR contains no name starting with FILE.")
+Returns nil if DIR contains no name starting with FILE.\n\
+\n\
+This function ignores some of the possible completions as\n\
+determined by the variable `completion-ignored-extensions', which see.")
   (file, directory)
      Lisp_Object file, directory;
 {
@@ -473,7 +488,7 @@ file_name_completion (file, dirname, all_flag, ver_flag)
     readfunc = readdirver;
   file = Fupcase (file);
 #else  /* not VMS */
-  CHECK_STRING (file, 0);
+  CHECK_STRING (file);
 #endif /* not VMS */
 
 #ifdef FILE_SYSTEM_CASE
@@ -543,6 +558,31 @@ file_name_completion (file, dirname, all_flag, ver_flag)
                 actually in the way in a directory contains only one file.  */
              if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
                continue;
+             if (!passcount && len > XSTRING (encoded_file)->size)
+               /* Ignore directories if they match an element of
+                  completion-ignored-extensions which ends in a slash.  */
+               for (tem = Vcompletion_ignored_extensions;
+                    CONSP (tem); tem = XCDR (tem))
+                 {
+                   int elt_len;
+
+                   elt = XCAR (tem);
+                   if (!STRINGP (elt))
+                     continue;
+                   elt_len = XSTRING (elt)->size - 1; /* -1 for trailing / */
+                   if (elt_len <= 0)
+                     continue;
+                   p1 = XSTRING (elt)->data;
+                   if (p1[elt_len] != '/')
+                     continue;
+                   skip = len - elt_len;
+                   if (skip < 0)
+                     continue;
+
+                   if (0 <= scmp (dp->d_name + skip, p1, elt_len))
+                     continue;
+                   break;
+                 }
            }
          else
             {
@@ -581,7 +621,8 @@ file_name_completion (file, dirname, all_flag, ver_flag)
              for (regexps = Vcompletion_regexp_list; CONSP (regexps);
                   regexps = XCDR (regexps))
                {
-                 tem = Fstring_match (XCAR (regexps), elt, zero);
+                 tem = Fstring_match (XCAR (regexps),
+                                      make_string (dp->d_name, len), zero);
                  if (NILP (tem))
                    break;
                }
@@ -811,7 +852,8 @@ Otherwise, list elements are:\n\
 10. inode number.  If inode number is larger than the Emacs integer,\n\
   this is a cons cell containing two integers: first the high part,\n\
   then the low 16 bits.\n\
-11. Device number.\n\
+11. Device number.  If it is larger than the Emacs integer, this is\n\
+  a cons cell, similar to the inode number.\n\
 \n\
 If file does not exist, returns nil.")
   (filename)
@@ -820,7 +862,7 @@ If file does not exist, returns nil.")
   Lisp_Object values[12];
   Lisp_Object encoded;
   struct stat s;
-#ifdef BSD4_2
+#if defined (BSD4_2) || defined (BSD4_3)
   Lisp_Object dirname;
   struct stat sdir;
 #endif
@@ -863,10 +905,7 @@ If file does not exist, returns nil.")
     values[7] = make_float ((double)s.st_size);
   filemodestring (&s, modes);
   values[8] = make_string (modes, 10);
-#ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
-#define BSD4_2 /* A new meaning to the term `backwards compatibility' */
-#endif
-#ifdef BSD4_2                  /* file gid will be dir gid */
+#if defined (BSD4_2) || defined (BSD4_3) /* file gid will be dir gid */
   dirname = Ffile_name_directory (filename);
   if (! NILP (dirname))
     encoded = ENCODE_FILE (dirname);
@@ -877,11 +916,8 @@ If file does not exist, returns nil.")
 #else                                  /* file gid will be egid */
   values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
 #endif /* BSD4_2 (or BSD4_3) */
-#ifdef BSD4_3
-#undef BSD4_2 /* ok, you can look again without throwing up */
-#endif
   /* Cast -1 to avoid warning if int is not as wide as VALBITS.  */
-  if (s.st_ino & (((EMACS_INT) (-1)) << VALBITS))
+  if (FIXNUM_OVERFLOW_P (s.st_ino))
     /* To allow inode numbers larger than VALBITS, separate the bottom
        16 bits.  */
     values[10] = Fcons (make_number (s.st_ino >> 16),
@@ -891,7 +927,7 @@ If file does not exist, returns nil.")
     values[10] = make_number (s.st_ino);
 
   /* Likewise for device.  */
-  if (s.st_dev & (((EMACS_INT) (-1)) << VALBITS))
+  if (FIXNUM_OVERFLOW_P (s.st_dev))
     values[11] = Fcons (make_number (s.st_dev >> 16),
                        make_number (s.st_dev & 0xffff));
   else
@@ -944,6 +980,8 @@ syms_of_dired ()
 
   DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
     "*Completion ignores filenames ending in any string in this list.\n\
+Directories are ignored if they match any string in this list which\n\
+ends in a slash.\n\
 This variable does not affect lists of possible completions,\n\
 but does affect the commands that actually do completions.");
   Vcompletion_ignored_extensions = Qnil;