diff src/dired.c @ 219:262b8bb4a523 r20-4b8

Import from CVS: tag r20-4b8
author cvs
date Mon, 13 Aug 2007 10:09:35 +0200
parents 41ff10fd062f
children 0e522484dd2a
line wrap: on
line diff
--- a/src/dired.c	Mon Aug 13 10:08:36 2007 +0200
+++ b/src/dired.c	Mon Aug 13 10:09:35 2007 +0200
@@ -182,10 +182,10 @@
 	      if (!NILP (full))
 		name = concat2 (name_as_dir,
 				make_ext_string ((Bufbyte *)dp->d_name,
-						 len, FORMAT_BINARY));
+						 len, FORMAT_FILENAME));
 	      else
 		name = make_ext_string ((Bufbyte *)dp->d_name,
-					len, FORMAT_BINARY);
+					len, FORMAT_FILENAME);
 
 	      list = Fcons (name, list);
 	    }
@@ -292,6 +292,20 @@
 }
 
 static Lisp_Object
+file_name_completion_unwind (Lisp_Object unwind_obj)
+{
+  DIR *d;
+  Lisp_Object obj = XCAR (unwind_obj);
+
+  if (NILP (obj))
+    return Qnil;
+  d = (DIR *)get_opaque_ptr (obj);
+  closedir (d);
+  free_opaque_ptr (obj);
+  return Qnil;
+}
+
+static Lisp_Object
 file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag,
 		      int ver_flag)
 {
@@ -305,20 +319,18 @@
   int speccount = specpdl_depth ();
   Charcount file_name_length;
   DIRENTRY *((*readfunc) (DIR *)) = readdir;
+  Lisp_Object unwind_closure;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   GCPRO3 (file, dirname, bestmatch);
 
   CHECK_STRING (file);
 
-/* #### The following is valid not only for VMS, but for NT too. */
-#ifdef VMS
-  /* Filename completion on VMS ignores case, since VMS filesys does.  */
+#ifdef WINDOWSNT
+  /* Filename completion on Windows ignores case, since Windows
+     filesystems do.  */
   specbind (Qcompletion_ignore_case, Qt);
-
-  if (ver_flag)
-    readfunc = readdirver;
-#endif /* VMS */
+#endif /* HAVE_WINDOWS */
 
 #ifdef FILE_SYSTEM_CASE
   file = FILE_SYSTEM_CASE (file);
@@ -334,11 +346,20 @@
      ** It would not actually be helpful to the user to ignore any possible
      completions when making a list of them.**  */
 
+  /* We cannot use close_directory_unwind() because we change the
+     directory.  The old code used to just avoid signaling errors, and
+     call closedir, but it was wrong, because it made sane handling of
+     QUIT impossible and, besides, various utility functions like
+     regexp_ignore_completion_p can signal errors.  */
+  unwind_closure = Fcons (Qnil, Qnil);
+  record_unwind_protect (file_name_completion_unwind, unwind_closure);
+
   for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
     {
       d = opendir ((char *) XSTRING_DATA (Fdirectory_file_name (dirname)));
       if (!d)
 	report_file_error ("Opening directory", list1 (dirname));
+      XCAR (unwind_closure) = make_opaque_ptr ((void *)d);
 
       /* Loop reading blocks */
       while (1)
@@ -355,17 +376,14 @@
 	  dp = (*readfunc) (d);
 	  if (!dp) break;
 
+	  /* #### This is a bad idea, because d_name can contain
+             control characters, which can make XEmacs crash.  This
+             should be handled properly with FORMAT_FILENAME.  */
 	  d_name = (Bufbyte *) dp->d_name;
 	  len = NAMLEN (dp);
 	  cclen = bytecount_to_charcount (d_name, len);
 
-	  /* Can't just use QUIT because we have to make sure the file
-             descriptor gets closed. */
-	  if (QUITP)
-	    {
-	      closedir (d);
-	      signal_quit ();
-	    }
+	  QUIT;
 
 	  if (! DIRENTRY_NONEMPTY (dp)
 	      || cclen < file_name_length
@@ -394,14 +412,13 @@
 		{
 		  Lisp_Object tem;
 		  /* and exit this for loop if a match is found */
-		  for (tem = Vcompletion_ignored_extensions;
-		       CONSP (tem);
-                       tem = XCDR (tem))
+		  EXTERNAL_LIST_LOOP (tem, Vcompletion_ignored_extensions)
 		    {
 		      Lisp_Object elt = XCAR (tem);
 		      Charcount skip;
 
-		      if (!STRINGP (elt)) continue;
+		      CHECK_STRING (elt);
+
 		      skip = cclen - string_char_length (XSTRING (elt));
 		      if (skip < 0) continue;
 
@@ -498,6 +515,8 @@
             }
         }
       closedir (d);
+      free_opaque_ptr (XCAR (unwind_closure));
+      XCAR (unwind_closure) = Qnil;
     }
 
   unbind_to (speccount, Qnil);
@@ -527,7 +546,7 @@
 	  len = NAMLEN (dp);
 	  if (DIRENTRY_NONEMPTY (dp))
 	    Fputhash (make_ext_string ((Bufbyte *) dp->d_name, len,
-				       FORMAT_BINARY), Qt, hash);
+				       FORMAT_FILENAME), Qt, hash);
 	}
       closedir (d);
     }