summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1997-09-08 10:09:15 +0000
committerRichard M. Stallman <rms@gnu.org>1997-09-08 10:09:15 +0000
commit55b405c779348dc0216f82d153d0e36933db563c (patch)
treee4670ea9dd205625a4beed0bcc14caee0d308a22
parent881a4deeb9385acf24340cd2deada9571c248a33 (diff)
downloademacs-55b405c779348dc0216f82d153d0e36933db563c.tar.gz
(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.
-rw-r--r--src/dired.c84
1 files changed, 67 insertions, 17 deletions
diff --git a/src/dired.c b/src/dired.c
index 7fc39dcd722..60fba4f6839 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -86,6 +86,14 @@ extern struct re_pattern_buffer *compile_pattern ();
#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 struct re_pattern_buffer *compile_pattern ();
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 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
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 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
#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 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
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 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
/* 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 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
}
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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
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_name_completion (file, dirname, all_flag, ver_flag)
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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
{
/* 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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
==
(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 @@ file_name_completion (file, dirname, all_flag, ver_flag)
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 @@ If file does not exist, returns nil.")
{
Lisp_Object values[12];
Lisp_Object dirname;
+ Lisp_Object encoded;
struct stat s;
struct stat sdir;
char modes[10];
@@ -644,7 +690,9 @@ If file does not exist, returns nil.")
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 @@ If file does not exist, returns nil.")
#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;