changeset 94493:41892e1c80a1

(file_name_completion): Fix up the encoding/decoding issue some more. Copy some of the code from Ftry_completions. Remove special case code that dates back to revision 1.1 when the slash was only added when necessary and that can't trigger nowadays.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 30 Apr 2008 07:16:08 +0000
parents 15e98f48709e
children 07fb6a1d5233
files src/ChangeLog src/dired.c
diffstat 2 files changed, 52 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Apr 30 05:50:02 2008 +0000
+++ b/src/ChangeLog	Wed Apr 30 07:16:08 2008 +0000
@@ -1,3 +1,10 @@
+2008-04-30  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* dired.c (file_name_completion): Fix up the encoding/decoding issue
+	some more.  Copy some of the code from Ftry_completions.
+	Remove special case code that dates back to revision 1.1 when the
+	slash was only added when necessary and that can't trigger nowadays.
+
 2008-04-27  Kenichi Handa  <handa@m17n.org>
 
 	* font.c (font_prop_validate): Signal `error' instead of `font'.
--- a/src/dired.c	Wed Apr 30 05:50:02 2008 +0000
+++ b/src/dired.c	Wed Apr 30 07:16:08 2008 +0000
@@ -465,7 +465,6 @@
   DIR *d;
   int bestmatchsize = 0, skip;
   register int compare, matchsize;
-  unsigned char *p1, *p2;
   int matchcount = 0;
   /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
      If ALL_FLAG is 0, BESTMATCH is either nil
@@ -508,6 +507,9 @@
   /* 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.  */
+  /* Actually, this is not quite true any more: we do most of the completion
+     work with decoded file names, but we still do some filtering based
+     on the encoded file name.  */
   encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
 
   encoded_dir = ENCODE_FILE (dirname);
@@ -539,7 +541,6 @@
 	{
 	  DIRENTRY *dp;
 	  int len;
-	  Lisp_Object decoded_name;
 
 #ifdef VMS
 	  dp = (*readfunc) (d);
@@ -589,6 +590,7 @@
 		     CONSP (tem); tem = XCDR (tem))
 		  {
 		    int elt_len;
+		    unsigned char *p1;
 
 		    elt = XCAR (tem);
 		    if (!STRINGP (elt))
@@ -641,8 +643,10 @@
 	  if (!passcount && CONSP (tem))
 	    continue;
 
+	  /* FIXME: If we move this `decode' earlier we can eliminate
+	     the repeated ENCODE_FILE on Vcompletion_ignored_extensions.  */
 	  name = make_unibyte_string (dp->d_name, len);
-	  decoded_name = DECODE_FILE (name);
+	  name = DECODE_FILE (name);
 
 	  if (!passcount)
 	    {
@@ -653,11 +657,8 @@
 	      /* Ignore this element if it fails to match all the regexps.  */
 	      for (regexps = Vcompletion_regexp_list; CONSP (regexps);
 		   regexps = XCDR (regexps))
-		{
-		  tem = Fstring_match (XCAR (regexps), decoded_name, zero);
-		  if (NILP (tem))
-		    break;
-		}
+		if (fast_string_match (XCAR (regexps), name) < 0)
+		  break;
 	      if (CONSP (regexps))
 		continue;
 	    }
@@ -666,7 +667,7 @@
 	  if (directoryp)
 	    {
 	      /* This completion is a directory; make it end with '/' */
-	      name = ENCODE_FILE (Ffile_name_as_directory (decoded_name));
+	      name = Ffile_name_as_directory (name);
 	    }
 
 	  /* Test the predicate, if any.  */
@@ -675,10 +676,10 @@
 	    {
 	      Lisp_Object decoded;
 	      Lisp_Object val;
-	      struct gcpro gcpro1, gcpro2;
+	      struct gcpro gcpro1;
 
-	      GCPRO2 (name, decoded_name);
-	      decoded = Fexpand_file_name (decoded_name, dirname);
+	      GCPRO1 (name);
+	      decoded = Fexpand_file_name (name, dirname);
 	      val = call1 (predicate, decoded);
 	      UNGCPRO;
 
@@ -691,7 +692,7 @@
 	  matchcount++;
 
 	  if (all_flag)
-	    bestmatch = Fcons (decoded_name, bestmatch);
+	    bestmatch = Fcons (name, bestmatch);
 	  else if (NILP (bestmatch))
 	    {
 	      bestmatch = name;
@@ -699,12 +700,21 @@
 	    }
 	  else
 	    {
-	      compare = min (bestmatchsize, len);
-	      p1 = SDATA (bestmatch);
-	      p2 = (unsigned char *) dp->d_name;
-	      matchsize = scmp (p1, p2, compare);
-	      if (matchsize < 0)
+	      Lisp_Object zero = make_number (0);
+	      /* FIXME: This is a copy of the code in Ftry_completion.  */
+	      compare = min (bestmatchsize, SCHARS (name));
+	      tem = Fcompare_strings (bestmatch, zero,
+				      make_number (compare),
+				      name, zero,
+				      make_number (compare),
+				      completion_ignore_case ? Qt : Qnil);
+	      if (EQ (tem, Qt))
 		matchsize = compare;
+	      else if (XINT (tem) < 0)
+		matchsize = - XINT (tem) - 1;
+	      else
+		matchsize = XINT (tem) - 1;
+
 	      if (completion_ignore_case)
 		{
 		  /* If this is an exact match except for case,
@@ -713,9 +723,9 @@
 		     of the actual match.  */
 		  /* This tests that the current file is an exact match
 		     but BESTMATCH is not (it is too long).  */
-		  if ((matchsize == len
+		  if ((matchsize == SCHARS (name)
 		       && matchsize + !!directoryp
-			  < SCHARS (bestmatch))
+		          < SCHARS (bestmatch))
 		      ||
 		      /* If there is no exact match ignoring case,
 			 prefer a match that does not change the case
@@ -725,21 +735,23 @@
 			 prefer that one.  */
 		      /* This == checks that, of current file and BESTMATCH,
 			 either both or neither are exact.  */
-		      (((matchsize == len)
+		      (((matchsize == SCHARS (name))
 			==
 			(matchsize + !!directoryp == SCHARS (bestmatch)))
-		       && !bcmp (p2, SDATA (encoded_file), SCHARS (encoded_file))
-		       && bcmp (p1, SDATA (encoded_file), SCHARS (encoded_file))))
+		       && (tem = Fcompare_strings (name, zero,
+						   make_number (SCHARS (file)),
+						   file, zero,
+						   Qnil,
+						   Qnil),
+			   EQ (Qt, tem))
+		       && (tem = Fcompare_strings (bestmatch, zero,
+						   make_number (SCHARS (file)),
+						   file, zero,
+						   Qnil,
+						   Qnil),
+			   ! EQ (Qt, tem))))
 		    bestmatch = name;
 		}
-
-	      /* If this dirname all matches, see if implicit following
-		 slash does too.  */
-	      if (directoryp
-		  && compare == matchsize
-		  && bestmatchsize > matchsize
-		  && IS_ANY_SEP (p1[matchsize]))
-		matchsize++;
 	      bestmatchsize = matchsize;
 	    }
 	}
@@ -751,18 +763,11 @@
   bestmatch = unbind_to (count, bestmatch);
 
   if (all_flag || NILP (bestmatch))
-    {
-      if (STRINGP (bestmatch))
-	bestmatch = DECODE_FILE (bestmatch);
-      return bestmatch;
-    }
-  if (matchcount == 1 && bestmatchsize == SCHARS (encoded_file))
+    return bestmatch;
+  if (matchcount == 1 && bestmatchsize == SCHARS (file))
     return Qt;
   bestmatch = Fsubstring (bestmatch, make_number (0),
 			  make_number (bestmatchsize));
-  /* Now that we got the right initial segment of BESTMATCH,
-     decode it from the coding system in use.  */
-  bestmatch = DECODE_FILE (bestmatch);
   return bestmatch;
 }