mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
(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.
This commit is contained in:
parent
fe487a7128
commit
24c2a54f4c
1 changed files with 67 additions and 17 deletions
84
src/dired.c
84
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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue