diff src/dired.c @ 19816:902043a3c18a

(ENCODE_FILE): New macro. (Ffile_attributes): Encode the file names to operate on. (file_name_completion): Do completion on encoded name, then decode. (Fdirectory_files): Encode the argument. Decode all result file names using Vfile_name_coding_system.
author Richard M. Stallman <rms@gnu.org>
date Mon, 08 Sep 1997 10:09:15 +0000
parents e97df3d7af25
children 8e7e791c49ca
line wrap: on
line diff
--- a/src/dired.c	Mon Sep 08 10:00:48 1997 +0000
+++ b/src/dired.c	Mon Sep 08 10:09:15 1997 +0000
@@ -86,6 +86,14 @@
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
+/* Encode the file name NAME using the specified coding system
+   for file names, if any.  */
+#define ENCODE_FILE(name)					\
+  (! NILP (Vfile_name_coding_system)				\
+   && XFASTINT (Vfile_name_coding_system) != 0			\
+   ? Fencode_coding_string (name, Vfile_name_coding_system, Qt)	\
+   : name)
+
 /* if system does not have symbolic links, it does not have lstat.
    In that case, use ordinary stat instead.  */
 
@@ -95,6 +103,7 @@
 
 extern int completion_ignore_case;
 extern Lisp_Object Vcompletion_regexp_list;
+extern Lisp_Object Vfile_name_coding_system;
 
 Lisp_Object Vcompletion_ignored_extensions;
 Lisp_Object Qcompletion_ignore_case;
@@ -117,6 +126,7 @@
   DIR *d;
   int dirnamelen;
   Lisp_Object list, name, dirfilename;
+  Lisp_Object encoded_directory;
   Lisp_Object handler;
   struct re_pattern_buffer *bufp;
 
@@ -164,6 +174,10 @@
 #endif
     }
 
+  dirfilename = ENCODE_FILE (dirfilename);
+
+  encoded_directory = ENCODE_FILE (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!  */
 
@@ -176,7 +190,7 @@
     report_file_error ("Opening directory", Fcons (directory, Qnil));
 
   list = Qnil;
-  dirnamelen = XSTRING (directory)->size;
+  dirnamelen = XSTRING (encoded_directory)->size;
   re_match_object = Qt;
 
   /* Loop reading blocks */
@@ -201,12 +215,12 @@
 		  /* Decide whether we need to add a directory separator.  */
 #ifndef VMS
 		  if (dirnamelen == 0
-		      || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
+		      || !IS_ANY_SEP (XSTRING (encoded_directory)->data[dirnamelen - 1]))
 		    needsep = 1;
 #endif /* VMS */
 
 		  name = make_uninit_string (total + needsep);
-		  bcopy (XSTRING (directory)->data, XSTRING (name)->data,
+		  bcopy (XSTRING (encoded_directory)->data, XSTRING (name)->data,
 			 dirnamelen);
 		  if (needsep)
 		    XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
@@ -215,6 +229,9 @@
 		}
 	      else
 		name = make_string (dp->d_name, len);
+	      if (! NILP (Vfile_name_coding_system))
+		name = Fdecode_coding_string (name, Vfile_name_coding_system,
+					      Qt);
 	      list = Fcons (name, list);
 	    }
 	}
@@ -290,11 +307,13 @@
   unsigned char *p1, *p2;
   int matchcount = 0;
   Lisp_Object bestmatch, tem, elt, name;
+  Lisp_Object encoded_file;
+  Lisp_Object encoded_dir;
   struct stat st;
   int directoryp;
   int passcount;
   int count = specpdl_ptr - specpdl;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
 
 #ifdef VMS
   extern DIRENTRY * readdirver ();
@@ -316,9 +335,17 @@
   file = FILE_SYSTEM_CASE (file);
 #endif
   bestmatch = Qnil;
-  GCPRO3 (file, dirname, bestmatch);
+  encoded_file = encoded_dir = Qnil;
+  GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir);
   dirname = Fexpand_file_name (dirname, Qnil);
 
+  /* 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_dir = ENCODE_FILE (dirname);
+
   /* With passcount = 0, ignore files that end in an ignored extension.
      If nothing found then try again with passcount = 1, don't ignore them.
      If looking for all completions, start with passcount = 1,
@@ -329,7 +356,8 @@
 
   for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
     {
-      if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
+      d = opendir (XSTRING (Fdirectory_file_name (encoded_dir))->data);
+      if (!d)
 	report_file_error ("Opening directory", Fcons (dirname, Qnil));
 
       /* Loop reading blocks */
@@ -351,12 +379,12 @@
 	  if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
 	    goto quit;
 	  if (! DIRENTRY_NONEMPTY (dp)
-	      || len < XSTRING (file)->size
-	      || 0 <= scmp (dp->d_name, XSTRING (file)->data,
-			    XSTRING (file)->size))
+	      || len < XSTRING (encoded_file)->size
+	      || 0 <= scmp (dp->d_name, XSTRING (encoded_file)->data,
+			    XSTRING (encoded_file)->size))
 	    continue;
 
-          if (file_name_completion_stat (dirname, dp, &st) < 0)
+          if (file_name_completion_stat (encoded_dir, dp, &st) < 0)
             continue;
 
           directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
@@ -375,7 +403,7 @@
             {
 	      /* Compare extensions-to-be-ignored against end of this file name */
 	      /* if name is not an exact match against specified string */
-	      if (!passcount && len > XSTRING (file)->size)
+	      if (!passcount && len > XSTRING (encoded_file)->size)
 		/* and exit this for loop if a match is found */
 		for (tem = Vcompletion_ignored_extensions;
 		     CONSP (tem); tem = XCONS (tem)->cdr)
@@ -432,6 +460,9 @@
 		name = make_string (dp->d_name, len);
 	      if (all_flag)
 		{
+		  if (! NILP (Vfile_name_coding_system))
+		    name = Fdecode_coding_string (name,
+						  Vfile_name_coding_system, Qt);
 		  bestmatch = Fcons (name, bestmatch);
 		}
 	      else
@@ -472,8 +503,8 @@
 			==
 			(matchsize + !!directoryp 
 			 == XSTRING (bestmatch)->size))
-		       && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size)
-		       && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size)))
+		       && !bcmp (p2, XSTRING (encoded_file)->data, XSTRING (encoded_file)->size)
+		       && bcmp (p1, XSTRING (encoded_file)->data, XSTRING (encoded_file)->size)))
 		    {
 		      bestmatch = make_string (dp->d_name, len);
 		      if (directoryp)
@@ -498,10 +529,24 @@
   bestmatch = unbind_to (count, bestmatch);
 
   if (all_flag || NILP (bestmatch))
-    return bestmatch;
+    {
+      if (! NILP (Vfile_name_coding_system)
+	  && STRINGP (bestmatch))
+	bestmatch = Fdecode_coding_string (bestmatch,
+					   Vfile_name_coding_system, Qt);
+      return bestmatch;
+    }
   if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
     return Qt;
-  return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
+  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.  */
+  if (! NILP (Vfile_name_coding_system))
+    bestmatch = Fdecode_coding_string (bestmatch,
+				       Vfile_name_coding_system, Qt);
+  return bestmatch;
+
  quit:
   if (d) closedir (d);
   Vquit_flag = Qnil;
@@ -631,6 +676,7 @@
 {
   Lisp_Object values[12];
   Lisp_Object dirname;
+  Lisp_Object encoded;
   struct stat s;
   struct stat sdir;
   char modes[10];
@@ -644,7 +690,9 @@
   if (!NILP (handler))
     return call2 (handler, Qfile_attributes, filename);
 
-  if (lstat (XSTRING (filename)->data, &s) < 0)
+  encoded = ENCODE_FILE (filename);
+
+  if (lstat (XSTRING (encoded)->data, &s) < 0)
     return Qnil;
 
   switch (s.st_mode & S_IFMT)
@@ -675,7 +723,9 @@
 #endif
 #ifdef BSD4_2			/* file gid will be dir gid */
   dirname = Ffile_name_directory (filename);
-  if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0)
+  if (! NILP (dirname))
+    encoded = ENCODE_FILE (dirname);
+  if (! NILP (dirname) && stat (XSTRING (encoded)->data, &sdir) == 0)
     values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
   else					/* if we can't tell, assume worst */
     values[9] = Qt;