Mercurial > emacs
comparison 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 |
comparison
equal
deleted
inserted
replaced
19815:e68cab4f1f70 | 19816:902043a3c18a |
---|---|
84 /* Returns a search buffer, with a fastmap allocated and ready to go. */ | 84 /* Returns a search buffer, with a fastmap allocated and ready to go. */ |
85 extern struct re_pattern_buffer *compile_pattern (); | 85 extern struct re_pattern_buffer *compile_pattern (); |
86 | 86 |
87 #define min(a, b) ((a) < (b) ? (a) : (b)) | 87 #define min(a, b) ((a) < (b) ? (a) : (b)) |
88 | 88 |
89 /* Encode the file name NAME using the specified coding system | |
90 for file names, if any. */ | |
91 #define ENCODE_FILE(name) \ | |
92 (! NILP (Vfile_name_coding_system) \ | |
93 && XFASTINT (Vfile_name_coding_system) != 0 \ | |
94 ? Fencode_coding_string (name, Vfile_name_coding_system, Qt) \ | |
95 : name) | |
96 | |
89 /* if system does not have symbolic links, it does not have lstat. | 97 /* if system does not have symbolic links, it does not have lstat. |
90 In that case, use ordinary stat instead. */ | 98 In that case, use ordinary stat instead. */ |
91 | 99 |
92 #ifndef S_IFLNK | 100 #ifndef S_IFLNK |
93 #define lstat stat | 101 #define lstat stat |
94 #endif | 102 #endif |
95 | 103 |
96 extern int completion_ignore_case; | 104 extern int completion_ignore_case; |
97 extern Lisp_Object Vcompletion_regexp_list; | 105 extern Lisp_Object Vcompletion_regexp_list; |
106 extern Lisp_Object Vfile_name_coding_system; | |
98 | 107 |
99 Lisp_Object Vcompletion_ignored_extensions; | 108 Lisp_Object Vcompletion_ignored_extensions; |
100 Lisp_Object Qcompletion_ignore_case; | 109 Lisp_Object Qcompletion_ignore_case; |
101 Lisp_Object Qdirectory_files; | 110 Lisp_Object Qdirectory_files; |
102 Lisp_Object Qfile_name_completion; | 111 Lisp_Object Qfile_name_completion; |
115 Lisp_Object directory, full, match, nosort; | 124 Lisp_Object directory, full, match, nosort; |
116 { | 125 { |
117 DIR *d; | 126 DIR *d; |
118 int dirnamelen; | 127 int dirnamelen; |
119 Lisp_Object list, name, dirfilename; | 128 Lisp_Object list, name, dirfilename; |
129 Lisp_Object encoded_directory; | |
120 Lisp_Object handler; | 130 Lisp_Object handler; |
121 struct re_pattern_buffer *bufp; | 131 struct re_pattern_buffer *bufp; |
122 | 132 |
123 /* If the file name has special constructs in it, | 133 /* If the file name has special constructs in it, |
124 call the corresponding file handler. */ | 134 call the corresponding file handler. */ |
162 #else | 172 #else |
163 bufp = compile_pattern (match, 0, 0, 0); | 173 bufp = compile_pattern (match, 0, 0, 0); |
164 #endif | 174 #endif |
165 } | 175 } |
166 | 176 |
177 dirfilename = ENCODE_FILE (dirfilename); | |
178 | |
179 encoded_directory = ENCODE_FILE (directory); | |
180 | |
167 /* Now *bufp is the compiled form of MATCH; don't call anything | 181 /* Now *bufp is the compiled form of MATCH; don't call anything |
168 which might compile a new regexp until we're done with the loop! */ | 182 which might compile a new regexp until we're done with the loop! */ |
169 | 183 |
170 /* Do this opendir after anything which might signal an error; if | 184 /* Do this opendir after anything which might signal an error; if |
171 an error is signaled while the directory stream is open, we | 185 an error is signaled while the directory stream is open, we |
174 d = opendir (XSTRING (dirfilename)->data); | 188 d = opendir (XSTRING (dirfilename)->data); |
175 if (! d) | 189 if (! d) |
176 report_file_error ("Opening directory", Fcons (directory, Qnil)); | 190 report_file_error ("Opening directory", Fcons (directory, Qnil)); |
177 | 191 |
178 list = Qnil; | 192 list = Qnil; |
179 dirnamelen = XSTRING (directory)->size; | 193 dirnamelen = XSTRING (encoded_directory)->size; |
180 re_match_object = Qt; | 194 re_match_object = Qt; |
181 | 195 |
182 /* Loop reading blocks */ | 196 /* Loop reading blocks */ |
183 while (1) | 197 while (1) |
184 { | 198 { |
199 int needsep = 0; | 213 int needsep = 0; |
200 | 214 |
201 /* Decide whether we need to add a directory separator. */ | 215 /* Decide whether we need to add a directory separator. */ |
202 #ifndef VMS | 216 #ifndef VMS |
203 if (dirnamelen == 0 | 217 if (dirnamelen == 0 |
204 || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1])) | 218 || !IS_ANY_SEP (XSTRING (encoded_directory)->data[dirnamelen - 1])) |
205 needsep = 1; | 219 needsep = 1; |
206 #endif /* VMS */ | 220 #endif /* VMS */ |
207 | 221 |
208 name = make_uninit_string (total + needsep); | 222 name = make_uninit_string (total + needsep); |
209 bcopy (XSTRING (directory)->data, XSTRING (name)->data, | 223 bcopy (XSTRING (encoded_directory)->data, XSTRING (name)->data, |
210 dirnamelen); | 224 dirnamelen); |
211 if (needsep) | 225 if (needsep) |
212 XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP; | 226 XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP; |
213 bcopy (dp->d_name, | 227 bcopy (dp->d_name, |
214 XSTRING (name)->data + afterdirindex, len); | 228 XSTRING (name)->data + afterdirindex, len); |
215 } | 229 } |
216 else | 230 else |
217 name = make_string (dp->d_name, len); | 231 name = make_string (dp->d_name, len); |
232 if (! NILP (Vfile_name_coding_system)) | |
233 name = Fdecode_coding_string (name, Vfile_name_coding_system, | |
234 Qt); | |
218 list = Fcons (name, list); | 235 list = Fcons (name, list); |
219 } | 236 } |
220 } | 237 } |
221 } | 238 } |
222 closedir (d); | 239 closedir (d); |
288 int bestmatchsize, skip; | 305 int bestmatchsize, skip; |
289 register int compare, matchsize; | 306 register int compare, matchsize; |
290 unsigned char *p1, *p2; | 307 unsigned char *p1, *p2; |
291 int matchcount = 0; | 308 int matchcount = 0; |
292 Lisp_Object bestmatch, tem, elt, name; | 309 Lisp_Object bestmatch, tem, elt, name; |
310 Lisp_Object encoded_file; | |
311 Lisp_Object encoded_dir; | |
293 struct stat st; | 312 struct stat st; |
294 int directoryp; | 313 int directoryp; |
295 int passcount; | 314 int passcount; |
296 int count = specpdl_ptr - specpdl; | 315 int count = specpdl_ptr - specpdl; |
297 struct gcpro gcpro1, gcpro2, gcpro3; | 316 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
298 | 317 |
299 #ifdef VMS | 318 #ifdef VMS |
300 extern DIRENTRY * readdirver (); | 319 extern DIRENTRY * readdirver (); |
301 | 320 |
302 DIRENTRY *((* readfunc) ()); | 321 DIRENTRY *((* readfunc) ()); |
314 | 333 |
315 #ifdef FILE_SYSTEM_CASE | 334 #ifdef FILE_SYSTEM_CASE |
316 file = FILE_SYSTEM_CASE (file); | 335 file = FILE_SYSTEM_CASE (file); |
317 #endif | 336 #endif |
318 bestmatch = Qnil; | 337 bestmatch = Qnil; |
319 GCPRO3 (file, dirname, bestmatch); | 338 encoded_file = encoded_dir = Qnil; |
339 GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir); | |
320 dirname = Fexpand_file_name (dirname, Qnil); | 340 dirname = Fexpand_file_name (dirname, Qnil); |
341 | |
342 /* Do completion on the encoded file name | |
343 because the other names in the directory are (we presume) | |
344 encoded likewise. We decode the completed string at the end. */ | |
345 encoded_file = ENCODE_FILE (file); | |
346 | |
347 encoded_dir = ENCODE_FILE (dirname); | |
321 | 348 |
322 /* With passcount = 0, ignore files that end in an ignored extension. | 349 /* With passcount = 0, ignore files that end in an ignored extension. |
323 If nothing found then try again with passcount = 1, don't ignore them. | 350 If nothing found then try again with passcount = 1, don't ignore them. |
324 If looking for all completions, start with passcount = 1, | 351 If looking for all completions, start with passcount = 1, |
325 so always take even the ignored ones. | 352 so always take even the ignored ones. |
327 ** It would not actually be helpful to the user to ignore any possible | 354 ** It would not actually be helpful to the user to ignore any possible |
328 completions when making a list of them.** */ | 355 completions when making a list of them.** */ |
329 | 356 |
330 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++) | 357 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++) |
331 { | 358 { |
332 if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data))) | 359 d = opendir (XSTRING (Fdirectory_file_name (encoded_dir))->data); |
360 if (!d) | |
333 report_file_error ("Opening directory", Fcons (dirname, Qnil)); | 361 report_file_error ("Opening directory", Fcons (dirname, Qnil)); |
334 | 362 |
335 /* Loop reading blocks */ | 363 /* Loop reading blocks */ |
336 /* (att3b compiler bug requires do a null comparison this way) */ | 364 /* (att3b compiler bug requires do a null comparison this way) */ |
337 while (1) | 365 while (1) |
349 len = NAMLEN (dp); | 377 len = NAMLEN (dp); |
350 | 378 |
351 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) | 379 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) |
352 goto quit; | 380 goto quit; |
353 if (! DIRENTRY_NONEMPTY (dp) | 381 if (! DIRENTRY_NONEMPTY (dp) |
354 || len < XSTRING (file)->size | 382 || len < XSTRING (encoded_file)->size |
355 || 0 <= scmp (dp->d_name, XSTRING (file)->data, | 383 || 0 <= scmp (dp->d_name, XSTRING (encoded_file)->data, |
356 XSTRING (file)->size)) | 384 XSTRING (encoded_file)->size)) |
357 continue; | 385 continue; |
358 | 386 |
359 if (file_name_completion_stat (dirname, dp, &st) < 0) | 387 if (file_name_completion_stat (encoded_dir, dp, &st) < 0) |
360 continue; | 388 continue; |
361 | 389 |
362 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR); | 390 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR); |
363 tem = Qnil; | 391 tem = Qnil; |
364 if (directoryp) | 392 if (directoryp) |
373 } | 401 } |
374 else | 402 else |
375 { | 403 { |
376 /* Compare extensions-to-be-ignored against end of this file name */ | 404 /* Compare extensions-to-be-ignored against end of this file name */ |
377 /* if name is not an exact match against specified string */ | 405 /* if name is not an exact match against specified string */ |
378 if (!passcount && len > XSTRING (file)->size) | 406 if (!passcount && len > XSTRING (encoded_file)->size) |
379 /* and exit this for loop if a match is found */ | 407 /* and exit this for loop if a match is found */ |
380 for (tem = Vcompletion_ignored_extensions; | 408 for (tem = Vcompletion_ignored_extensions; |
381 CONSP (tem); tem = XCONS (tem)->cdr) | 409 CONSP (tem); tem = XCONS (tem)->cdr) |
382 { | 410 { |
383 elt = XCONS (tem)->car; | 411 elt = XCONS (tem)->car; |
430 } | 458 } |
431 else | 459 else |
432 name = make_string (dp->d_name, len); | 460 name = make_string (dp->d_name, len); |
433 if (all_flag) | 461 if (all_flag) |
434 { | 462 { |
463 if (! NILP (Vfile_name_coding_system)) | |
464 name = Fdecode_coding_string (name, | |
465 Vfile_name_coding_system, Qt); | |
435 bestmatch = Fcons (name, bestmatch); | 466 bestmatch = Fcons (name, bestmatch); |
436 } | 467 } |
437 else | 468 else |
438 { | 469 { |
439 bestmatch = name; | 470 bestmatch = name; |
470 either both or neither are exact. */ | 501 either both or neither are exact. */ |
471 (((matchsize == len) | 502 (((matchsize == len) |
472 == | 503 == |
473 (matchsize + !!directoryp | 504 (matchsize + !!directoryp |
474 == XSTRING (bestmatch)->size)) | 505 == XSTRING (bestmatch)->size)) |
475 && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size) | 506 && !bcmp (p2, XSTRING (encoded_file)->data, XSTRING (encoded_file)->size) |
476 && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size))) | 507 && bcmp (p1, XSTRING (encoded_file)->data, XSTRING (encoded_file)->size))) |
477 { | 508 { |
478 bestmatch = make_string (dp->d_name, len); | 509 bestmatch = make_string (dp->d_name, len); |
479 if (directoryp) | 510 if (directoryp) |
480 bestmatch = Ffile_name_as_directory (bestmatch); | 511 bestmatch = Ffile_name_as_directory (bestmatch); |
481 } | 512 } |
496 | 527 |
497 UNGCPRO; | 528 UNGCPRO; |
498 bestmatch = unbind_to (count, bestmatch); | 529 bestmatch = unbind_to (count, bestmatch); |
499 | 530 |
500 if (all_flag || NILP (bestmatch)) | 531 if (all_flag || NILP (bestmatch)) |
501 return bestmatch; | 532 { |
533 if (! NILP (Vfile_name_coding_system) | |
534 && STRINGP (bestmatch)) | |
535 bestmatch = Fdecode_coding_string (bestmatch, | |
536 Vfile_name_coding_system, Qt); | |
537 return bestmatch; | |
538 } | |
502 if (matchcount == 1 && bestmatchsize == XSTRING (file)->size) | 539 if (matchcount == 1 && bestmatchsize == XSTRING (file)->size) |
503 return Qt; | 540 return Qt; |
504 return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize)); | 541 bestmatch = Fsubstring (bestmatch, make_number (0), |
542 make_number (bestmatchsize)); | |
543 /* Now that we got the right initial segment of BESTMATCH, | |
544 decode it from the coding system in use. */ | |
545 if (! NILP (Vfile_name_coding_system)) | |
546 bestmatch = Fdecode_coding_string (bestmatch, | |
547 Vfile_name_coding_system, Qt); | |
548 return bestmatch; | |
549 | |
505 quit: | 550 quit: |
506 if (d) closedir (d); | 551 if (d) closedir (d); |
507 Vquit_flag = Qnil; | 552 Vquit_flag = Qnil; |
508 return Fsignal (Qquit, Qnil); | 553 return Fsignal (Qquit, Qnil); |
509 } | 554 } |
629 (filename) | 674 (filename) |
630 Lisp_Object filename; | 675 Lisp_Object filename; |
631 { | 676 { |
632 Lisp_Object values[12]; | 677 Lisp_Object values[12]; |
633 Lisp_Object dirname; | 678 Lisp_Object dirname; |
679 Lisp_Object encoded; | |
634 struct stat s; | 680 struct stat s; |
635 struct stat sdir; | 681 struct stat sdir; |
636 char modes[10]; | 682 char modes[10]; |
637 Lisp_Object handler; | 683 Lisp_Object handler; |
638 | 684 |
642 call the corresponding file handler. */ | 688 call the corresponding file handler. */ |
643 handler = Ffind_file_name_handler (filename, Qfile_attributes); | 689 handler = Ffind_file_name_handler (filename, Qfile_attributes); |
644 if (!NILP (handler)) | 690 if (!NILP (handler)) |
645 return call2 (handler, Qfile_attributes, filename); | 691 return call2 (handler, Qfile_attributes, filename); |
646 | 692 |
647 if (lstat (XSTRING (filename)->data, &s) < 0) | 693 encoded = ENCODE_FILE (filename); |
694 | |
695 if (lstat (XSTRING (encoded)->data, &s) < 0) | |
648 return Qnil; | 696 return Qnil; |
649 | 697 |
650 switch (s.st_mode & S_IFMT) | 698 switch (s.st_mode & S_IFMT) |
651 { | 699 { |
652 default: | 700 default: |
673 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */ | 721 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */ |
674 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */ | 722 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */ |
675 #endif | 723 #endif |
676 #ifdef BSD4_2 /* file gid will be dir gid */ | 724 #ifdef BSD4_2 /* file gid will be dir gid */ |
677 dirname = Ffile_name_directory (filename); | 725 dirname = Ffile_name_directory (filename); |
678 if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0) | 726 if (! NILP (dirname)) |
727 encoded = ENCODE_FILE (dirname); | |
728 if (! NILP (dirname) && stat (XSTRING (encoded)->data, &sdir) == 0) | |
679 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil; | 729 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil; |
680 else /* if we can't tell, assume worst */ | 730 else /* if we can't tell, assume worst */ |
681 values[9] = Qt; | 731 values[9] = Qt; |
682 #else /* file gid will be egid */ | 732 #else /* file gid will be egid */ |
683 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil; | 733 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil; |