(file_name_completion): Fix inappropriate mixing of
[bpt/emacs.git] / src / dired.c
index 09c72f6..3fa32b4 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 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -96,6 +96,7 @@ extern struct direct *readdir ();
 #include "systime.h"
 #include "buffer.h"
 #include "commands.h"
+#include "character.h"
 #include "charset.h"
 #include "coding.h"
 #include "regex.h"
@@ -192,8 +193,10 @@ directory_files_internal (directory, full, match, nosort, attrs, id_format)
   /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
      run_pre_post_conversion_on_str which calls Lisp directly and
      indirectly.  */
-  dirfilename = ENCODE_FILE (dirfilename);
-  encoded_directory = ENCODE_FILE (directory);
+  if (STRING_MULTIBYTE (dirfilename))
+    dirfilename = ENCODE_FILE (dirfilename);
+  encoded_directory = (STRING_MULTIBYTE (directory)
+                      ? ENCODE_FILE (directory) : directory);
 
   /* Now *bufp is the compiled form of MATCH; don't call anything
      which might compile a new regexp until we're done with the loop!  */
@@ -250,7 +253,7 @@ directory_files_internal (directory, full, match, nosort, attrs, id_format)
          name = finalname = make_unibyte_string (dp->d_name, len);
          GCPRO2 (finalname, name);
 
-         /* Note: ENCODE_FILE can GC; it should protect its argument,
+         /* Note: DECODE_FILE can GC; it should protect its argument,
             though.  */
          name = DECODE_FILE (name);
          len = SBYTES (name);
@@ -505,7 +508,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
   /* Do completion on the encoded file name
      because the other names in the directory are (we presume)
      encoded likewise.  We decode the completed string at the end.  */
-  encoded_file = ENCODE_FILE (file);
+  encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
 
   encoded_dir = ENCODE_FILE (dirname);
 
@@ -536,6 +539,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
        {
          DIRENTRY *dp;
          int len;
+         Lisp_Object decoded_name;
 
 #ifdef VMS
          dp = (*readfunc) (d);
@@ -637,6 +641,9 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
          if (!passcount && CONSP (tem))
            continue;
 
+         name = make_unibyte_string (dp->d_name, len);
+         decoded_name = DECODE_FILE (name);
+
          if (!passcount)
            {
              Lisp_Object regexps;
@@ -647,8 +654,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
              for (regexps = Vcompletion_regexp_list; CONSP (regexps);
                   regexps = XCDR (regexps))
                {
-                 tem = Fstring_match (XCAR (regexps),
-                                      make_string (dp->d_name, len), zero);
+                 tem = Fstring_match (XCAR (regexps), decoded_name, zero);
                  if (NILP (tem))
                    break;
                }
@@ -660,10 +666,8 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
          if (directoryp)
            {
              /* This completion is a directory; make it end with '/' */
-             name = Ffile_name_as_directory (make_string (dp->d_name, len));
+             name = ENCODE_FILE (Ffile_name_as_directory (decoded_name));
            }
-         else
-           name = make_string (dp->d_name, len);
 
          /* Test the predicate, if any.  */
 
@@ -671,10 +675,10 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
            {
              Lisp_Object decoded;
              Lisp_Object val;
-             struct gcpro gcpro1;
+             struct gcpro gcpro1, gcpro2;
 
-             GCPRO1 (name);
-             decoded = Fexpand_file_name (DECODE_FILE (name), dirname);
+             GCPRO2 (name, decoded_name);
+             decoded = Fexpand_file_name (decoded_name, dirname);
              val = call1 (predicate, decoded);
              UNGCPRO;
 
@@ -687,10 +691,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
          matchcount++;
 
          if (all_flag)
-           {
-             name = DECODE_FILE (name);
-             bestmatch = Fcons (name, bestmatch);
-           }
+           bestmatch = Fcons (decoded_name, bestmatch);
          else if (NILP (bestmatch))
            {
              bestmatch = name;
@@ -726,8 +727,7 @@ file_name_completion (file, dirname, all_flag, ver_flag, predicate)
                         either both or neither are exact.  */
                      (((matchsize == len)
                        ==
-                       (matchsize + !!directoryp
-                        == SCHARS (bestmatch)))
+                       (matchsize + !!directoryp == SCHARS (bestmatch)))
                       && !bcmp (p2, SDATA (encoded_file), SCHARS (encoded_file))
                       && bcmp (p1, SDATA (encoded_file), SCHARS (encoded_file))))
                    bestmatch = name;
@@ -918,8 +918,10 @@ Elements of the attribute list are:
  8. File modes, as a string of ten letters or dashes as in ls -l.
  9. t if file's gid would change if file were deleted and recreated.
 10. inode number.  If inode number is larger than the Emacs integer,
-  this is a cons cell containing two integers: first the high part,
-  then the low 16 bits.
+  but still fits into a 32-bit number, this is a cons cell containing two
+  integers: first the high part, then the low 16 bits.  If the inode number
+  is wider than 32 bits, this is a cons cell containing three integers:
+  first the high 24 bits, then middle 24 bits, and finally the low 16 bits.
 11. Device number.  If it is larger than the Emacs integer, this is
   a cons cell, similar to the inode number.  */)
      (filename, id_format)
@@ -937,7 +939,7 @@ Elements of the attribute list are:
   char modes[10];
   Lisp_Object handler;
   struct gcpro gcpro1;
-  EMACS_INT uid, gid, ino;
+  EMACS_INT ino;
 
   filename = Fexpand_file_name (filename, Qnil);
 
@@ -972,26 +974,20 @@ Elements of the attribute list are:
 #endif
     }
   values[1] = make_number (s.st_nlink);
-  /* When make_fixnum_or_float is called below with types that are
-     shorter than an int (e.g., `short'), GCC whines about comparison
-     being always false due to limited range of data type.  Fix by
-     copying s.st_uid and s.st_gid into int variables.  */
-  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);
+      values[2] = make_fixnum_or_float (s.st_uid);
+      values[3] = make_fixnum_or_float (s.st_gid);
     }
   else
     {
       BLOCK_INPUT;
-      pw = (struct passwd *) getpwuid (uid);
+      pw = (struct passwd *) getpwuid (s.st_uid);
       values[2] = (pw ? build_string (pw->pw_name)
-                  : make_fixnum_or_float (uid));
-      gr = (struct group *) getgrgid (gid);
+                  : make_fixnum_or_float (s.st_uid));
+      gr = (struct group *) getgrgid (s.st_gid);
       values[3] = (gr ? build_string (gr->gr_name)
-                  : make_fixnum_or_float (gid));
+                  : make_fixnum_or_float (s.st_gid));
       UNBLOCK_INPUT;
     }
   values[4] = make_time (s.st_atime);
@@ -1013,22 +1009,39 @@ Elements of the attribute list are:
   if (! NILP (dirname))
     encoded = ENCODE_FILE (dirname);
   if (! NILP (dirname) && stat (SDATA (encoded), &sdir) == 0)
-    values[9] = (sdir.st_gid != gid) ? Qt : Qnil;
+    values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
   else                                 /* if we can't tell, assume worst */
     values[9] = Qt;
 #else                                  /* file gid will be egid */
-  values[9] = (gid != getegid ()) ? Qt : Qnil;
+  values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
 #endif /* BSD4_2 (or BSD4_3) */
   /* Shut up GCC warnings in FIXNUM_OVERFLOW_P below.  */
-  ino = s.st_ino;
-  if (FIXNUM_OVERFLOW_P (ino))
+  if (sizeof (s.st_ino) > sizeof (ino))
+    ino = (EMACS_INT)(s.st_ino & 0xffffffff);
+  else
+    ino = s.st_ino;
+  if (!FIXNUM_OVERFLOW_P (ino)
+      && (sizeof (s.st_ino) <= sizeof (ino) || (s.st_ino & ~INTMASK) == 0))
+    /* Keep the most common cases as integers.  */
+    values[10] = make_number (ino);
+  else if (sizeof (s.st_ino) <= sizeof (ino)
+          || ((s.st_ino >> 16) & ~INTMASK) == 0)
     /* To allow inode numbers larger than VALBITS, separate the bottom
        16 bits.  */
-    values[10] = Fcons (make_number (ino >> 16),
-                       make_number (ino & 0xffff));
+    values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
+                       make_number ((EMACS_INT)(s.st_ino & 0xffff)));
   else
-    /* But keep the most common cases as integers.  */
-    values[10] = make_number (ino);
+    {
+      /* 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;
+      EMACS_INT low_ino  = s.st_ino & 0xffffffff;
+
+      values[10] = Fcons (make_number (high_ino >> 8),
+                         Fcons (make_number (((high_ino & 0xff) << 16)
+                                             + (low_ino >> 16)),
+                                make_number (low_ino & 0xffff)));
+    }
 
   /* Likewise for device.  */
   if (FIXNUM_OVERFLOW_P (s.st_dev))