]> code.delx.au - gnu-emacs/blobdiff - src/dired.c
(redraw_overlapping_rows): Fix detection of
[gnu-emacs] / src / dired.c
index 2d82c4bfdc39c8f0ff306573995a544f1d8c87bc..3505448017ebe9ede096e1490fe106f99aaabcac 100644 (file)
@@ -1,6 +1,6 @@
 /* Lisp functions for making directory listings.
    Copyright (C) 1985, 1986, 1993, 1994, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -27,18 +27,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
-#ifndef VMS
 #include <grp.h>
-#endif
 
 #include <errno.h>
 
-#ifdef VMS
-#include <string.h>
-#include <rms.h>
-#include <rmsdef.h>
-#endif
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -62,15 +54,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #else /* not SYSV_SYSTEM_DIR */
 
-#ifdef NONSYSTEM_DIR_LIBRARY
-#include "ndir.h"
-#else /* not NONSYSTEM_DIR_LIBRARY */
 #ifdef MSDOS
 #include <dirent.h>
 #else
 #include <sys/dir.h>
 #endif
-#endif /* not NONSYSTEM_DIR_LIBRARY */
 
 #include <sys/stat.h>
 
@@ -174,10 +162,6 @@ directory_files_internal (directory, full, match, nosort, attrs, id_format)
         compile_pattern to do the work for us.  */
       /* Pass 1 for the MULTIBYTE arg
         because we do make multibyte strings if the contents warrant.  */
-#ifdef VMS
-      bufp = compile_pattern (match, 0,
-                             buffer_defaults.downcase_table, 0, 1);
-#else  /* !VMS */
 # ifdef WINDOWSNT
       /* Windows users want case-insensitive wildcards.  */
       bufp = compile_pattern (match, 0,
@@ -185,7 +169,6 @@ directory_files_internal (directory, full, match, nosort, attrs, id_format)
 # else /* !WINDOWSNT */
       bufp = compile_pattern (match, 0, Qnil, 0, 1);
 # endif         /* !WINDOWSNT */
-#endif  /* !VMS */
     }
 
   /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
@@ -215,11 +198,9 @@ directory_files_internal (directory, full, match, nosort, attrs, id_format)
   re_match_object = Qt;
 
   /* Decide whether we need to add a directory separator.  */
-#ifndef VMS
   if (directory_nbytes == 0
       || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
     needsep = 1;
-#endif /* not VMS */
 
   /* Loop reading blocks until EOF or error.  */
   for (;;)
@@ -348,7 +329,8 @@ If FULL is non-nil, return absolute file names.  Otherwise return names
  that are relative to the specified directory.
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
- NOSORT is useful if you plan to sort the result yourself.  */)
+  Otherwise, the list returned is sorted with `stringp-lessp'.
+  NOSORT is useful if you plan to sort the result yourself.  */)
      (directory, full, match, nosort)
      Lisp_Object directory, full, match, nosort;
 {
@@ -483,21 +465,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
 
   elt = Qnil;
 
-#ifdef VMS
-  extern DIRENTRY * readdirver ();
-
-  DIRENTRY *((* readfunc) ());
-
-  /* Filename completion on VMS ignores case, since VMS filesys does.  */
-  specbind (Qcompletion_ignore_case, Qt);
-
-  readfunc = readdir;
-  if (ver_flag)
-    readfunc = readdirver;
-  file = Fupcase (file);
-#else  /* not VMS */
   CHECK_STRING (file);
-#endif /* not VMS */
 
 #ifdef FILE_SYSTEM_CASE
   file = FILE_SYSTEM_CASE (file);
@@ -535,9 +503,6 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
       int len;
       int canexclude = 0;
 
-#ifdef VMS
-      dp = (*readfunc) (d);
-#else
       errno = 0;
       dp = readdir (d);
       if (dp == NULL && (0
@@ -549,7 +514,6 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
 # endif
                         ))
        { QUIT; continue; }
-#endif
 
       if (!dp) break;
 
@@ -573,6 +537,20 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
       if (!all_flag)
        {
          int skip;
+
+#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */
+         /* If this entry matches the current bestmatch, the only
+            thing it can do is increase matchcount, so don't bother
+            investigating it any further.  */
+         if (!completion_ignore_case
+             /* The return result depends on whether it's the sole match.  */
+             && matchcount > 1
+             && !includeall /* This match may allow includeall to 0.  */
+             && len >= bestmatchsize
+             && 0 > scmp (dp->d_name, SDATA (bestmatch), bestmatchsize))
+           continue;
+#endif
+
          if (directoryp)
            {
 #ifndef TRIVIAL_DIRECTORY_ENTRY
@@ -667,10 +645,21 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
        XSETFASTINT (zero, 0);
 
        /* Ignore this element if it fails to match all the regexps.  */
-       for (regexps = Vcompletion_regexp_list; CONSP (regexps);
-            regexps = XCDR (regexps))
-         if (fast_string_match (XCAR (regexps), name) < 0)
-           break;
+       if (completion_ignore_case)
+         {
+           for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+                regexps = XCDR (regexps))
+             if (fast_string_match_ignore_case (XCAR (regexps), name) < 0)
+               break;
+         }
+       else
+         {
+           for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+                regexps = XCDR (regexps))
+             if (fast_string_match (XCAR (regexps), name) < 0)
+               break;
+         }
+
        if (CONSP (regexps))
          continue;
       }
@@ -730,8 +719,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
              /* This tests that the current file is an exact match
                 but BESTMATCH is not (it is too long).  */
              if ((matchsize == SCHARS (name)
-                  && matchsize + !!directoryp
-                  < SCHARS (bestmatch))
+                  && matchsize + !!directoryp < SCHARS (bestmatch))
                  ||
                  /* If there is no exact match ignoring case,
                     prefer a match that does not change the case
@@ -759,6 +747,20 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
                bestmatch = name;
            }
          bestmatchsize = matchsize;
+
+         /* If the best completion so far is reduced to the string
+            we're trying to complete, then we already know there's no
+            other completion, so there's no point looking any further.  */
+         if (matchsize <= SCHARS (file)
+             && !includeall /* A future match may allow includeall to 0.  */
+             /* If completion-ignore-case is non-nil, don't
+                short-circuit because we want to find the best
+                possible match *including* case differences.  */
+             && (!completion_ignore_case || matchsize == 0)
+             /* The return value depends on whether it's the sole match.  */
+             && matchcount > 1)
+           break;
+
        }
     }
 
@@ -830,10 +832,8 @@ file_name_completion_stat (dirname, dp, st_addr)
 #endif /* MSDOS */
 
   bcopy (SDATA (dirname), fullname, pos);
-#ifndef VMS
   if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
     fullname[pos++] = DIRECTORY_SEP;
-#endif
 
   bcopy (dp->d_name, fullname + pos, len);
   fullname[pos + len] = 0;
@@ -856,47 +856,6 @@ file_name_completion_stat (dirname, dp, st_addr)
 #endif /* S_IFLNK */
 }
 \f
-#ifdef VMS
-
-DEFUN ("file-name-all-versions", Ffile_name_all_versions,
-       Sfile_name_all_versions, 2, 2, 0,
-       doc: /* Return a list of all versions of file name FILE in directory DIRECTORY.  */)
-     (file, directory)
-     Lisp_Object file, directory;
-{
-  return file_name_completion (file, directory, 1, 1, Qnil);
-}
-
-DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
-       doc: /* Return the maximum number of versions allowed for FILE.
-Returns nil if the file cannot be opened or if there is no version limit.  */)
-     (filename)
-     Lisp_Object filename;
-{
-  Lisp_Object retval;
-  struct FAB    fab;
-  struct RAB    rab;
-  struct XABFHC xabfhc;
-  int status;
-
-  filename = Fexpand_file_name (filename, Qnil);
-  fab      = cc$rms_fab;
-  xabfhc   = cc$rms_xabfhc;
-  fab.fab$l_fna = SDATA (filename);
-  fab.fab$b_fns = strlen (fab.fab$l_fna);
-  fab.fab$l_xab = (char *) &xabfhc;
-  status = sys$open (&fab, 0, 0);
-  if (status != RMS$_NORMAL)   /* Probably non-existent file */
-    return Qnil;
-  sys$close (&fab, 0, 0);
-  if (xabfhc.xab$w_verlimit == 32767)
-    return Qnil;               /* No version limit */
-  else
-    return make_number (xabfhc.xab$w_verlimit);
-}
-
-#endif /* VMS */
-\f
 Lisp_Object
 make_time (time)
      time_t time;
@@ -935,6 +894,29 @@ stat_gname (struct stat *st)
 #endif
 }
 
+/* Make an integer or float number for UID and GID, while being
+   careful not to produce negative numbers due to signed integer
+   overflow.  */
+static Lisp_Object
+make_uid (struct stat *st)
+{
+  EMACS_INT uid = st->st_uid;
+
+  if (sizeof (st->st_uid) > sizeof (uid) || uid < 0 || FIXNUM_OVERFLOW_P (uid))
+    return make_float ((double)st->st_uid);
+  return make_number (uid);
+}
+
+static Lisp_Object
+make_gid (struct stat *st)
+{
+  EMACS_INT gid = st->st_gid;
+
+  if (sizeof (st->st_gid) > sizeof (gid) || gid < 0 || FIXNUM_OVERFLOW_P (gid))
+    return make_float ((double)st->st_gid);
+  return make_number (gid);
+}
+
 DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0,
        doc: /* Return a list of attributes of file FILENAME.
 Value is nil if specified file cannot be opened.
@@ -947,8 +929,8 @@ ID-FORMAT if you use the returned uid or gid.
 Elements of the attribute list are:
  0. t for directory, string (name linked to) for symbolic link, or nil.
  1. Number of links to file.
- 2. File uid as a string or an integer.  If a string value cannot be
-  looked up, the integer value is returned.
+ 2. File uid as a string or a number.  If a string value cannot be
+  looked up, a numeric value, either an integer or a float, is returned.
  3. File gid, likewise.
  4. Last access time, as a list of two integers.
   First integer has high-order 16 bits of time, second has low 16 bits.
@@ -982,7 +964,7 @@ which see.  */)
   Lisp_Object handler;
   struct gcpro gcpro1;
   EMACS_INT ino, uid, gid;
-  char *uname, *gname;
+  char *uname = NULL, *gname = NULL;
 
   filename = Fexpand_file_name (filename, Qnil);
 
@@ -1017,24 +999,23 @@ which see.  */)
 #endif
     }
   values[1] = make_number (s.st_nlink);
-  uid = s.st_uid;
-  gid = s.st_gid;
-  if (NILP (id_format) || EQ (id_format, Qinteger))
-    {
-      values[2] = make_fixnum_or_float (uid);
-      values[3] = make_fixnum_or_float (gid);
-    }
-  else
+
+  if (!(NILP (id_format) || EQ (id_format, Qinteger)))
     {
       BLOCK_INPUT;
       uname = stat_uname (&s);
-      values[2] = (uname ? build_string (uname)
-                  : make_fixnum_or_float (uid));
       gname = stat_gname (&s);
-      values[3] = (gname ? build_string (gname)
-                  : make_fixnum_or_float (gid));
       UNBLOCK_INPUT;
     }
+  if (uname)
+    values[2] = build_string (uname);
+  else
+    values[2] = make_uid (&s);
+  if (gname)
+    values[3] = build_string (gname);
+  else
+    values[3] = make_gid (&s);
+
   values[4] = make_time (s.st_atime);
   values[5] = make_time (s.st_mtime);
   values[6] = make_time (s.st_ctime);
@@ -1078,8 +1059,10 @@ which see.  */)
   else
     {
       /* To allow inode numbers beyond 32 bits, separate into 2 24-bit
-        high parts and a 16-bit bottom part.  */
-      EMACS_INT high_ino = s.st_ino >> 32;
+        high parts and a 16-bit bottom part.
+        The code on the next line avoids a compiler warning on
+        systems where st_ino is 32 bit wide. (bug#766).  */
+      EMACS_INT high_ino = s.st_ino >> 31 >> 1;
       EMACS_INT low_ino  = s.st_ino & 0xffffffff;
 
       values[10] = Fcons (make_number (high_ino >> 8),
@@ -1132,10 +1115,6 @@ syms_of_dired ()
   defsubr (&Sdirectory_files);
   defsubr (&Sdirectory_files_and_attributes);
   defsubr (&Sfile_name_completion);
-#ifdef VMS
-  defsubr (&Sfile_name_all_versions);
-  defsubr (&Sfile_version_limit);
-#endif /* VMS */
   defsubr (&Sfile_name_all_completions);
   defsubr (&Sfile_attributes);
   defsubr (&Sfile_attributes_lessp);