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;