diff options
| author | Richard M. Stallman | 1997-09-08 10:09:15 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-09-08 10:09:15 +0000 |
| commit | 24c2a54f4ca12a428d0402ab76f926bfb1723261 (patch) | |
| tree | 1cc54096ab8bba0d7c817f62867cd77d724be70a /src | |
| parent | fe487a71280026a7ca47b6bf425aae4c67889a76 (diff) | |
| download | emacs-24c2a54f4ca12a428d0402ab76f926bfb1723261.tar.gz emacs-24c2a54f4ca12a428d0402ab76f926bfb1723261.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 84 |
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 (); | |||
| 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 | ||
| @@ -95,6 +103,7 @@ extern struct re_pattern_buffer *compile_pattern (); | |||
| 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; |
| @@ -117,6 +126,7 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\ | |||
| 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 | ||
| @@ -164,6 +174,10 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\ | |||
| 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 | ||
| @@ -176,7 +190,7 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\ | |||
| 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 */ |
| @@ -201,12 +215,12 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\ | |||
| 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; |
| @@ -215,6 +229,9 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\ | |||
| 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 | } |
| @@ -290,11 +307,13 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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 (); |
| @@ -316,9 +335,17 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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); |
| 321 | 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); | ||
| 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, |
| @@ -329,7 +356,8 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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 */ |
| @@ -351,12 +379,12 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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); |
| @@ -375,7 +403,7 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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) |
| @@ -432,6 +460,9 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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 |
| @@ -472,8 +503,8 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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) |
| @@ -498,10 +529,24 @@ file_name_completion (file, dirname, all_flag, ver_flag) | |||
| 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; |
| @@ -631,6 +676,7 @@ If file does not exist, returns nil.") | |||
| 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]; |
| @@ -644,7 +690,9 @@ If file does not exist, returns nil.") | |||
| 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) |
| @@ -675,7 +723,9 @@ If file does not exist, returns nil.") | |||
| 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; |