aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dired.c101
1 files changed, 66 insertions, 35 deletions
diff --git a/src/dired.c b/src/dired.c
index 3768b6dbb7c..0e1c88f03ce 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -481,18 +481,32 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
481 record_unwind_protect_ptr (directory_files_internal_unwind, d); 481 record_unwind_protect_ptr (directory_files_internal_unwind, d);
482 482
483 /* Loop reading directory entries. */ 483 /* Loop reading directory entries. */
484 Lisp_Object zero = make_fixnum (0);
485 ptrdiff_t enc_file_len = SCHARS (encoded_file);
486 Lisp_Object file_len = make_fixnum (SCHARS (file));
484 for (struct dirent *dp; (dp = read_dirent (d, dirname)); ) 487 for (struct dirent *dp; (dp = read_dirent (d, dirname)); )
485 { 488 {
486 ptrdiff_t len = dirent_namelen (dp); 489 ptrdiff_t len = dirent_namelen (dp);
487 bool canexclude = 0; 490 bool canexclude = 0;
488 491
489 maybe_quit (); 492 maybe_quit ();
490 if (len < SCHARS (encoded_file) 493
491 || (scmp (dp->d_name, SSDATA (encoded_file), 494 if (len < enc_file_len
492 SCHARS (encoded_file)) 495 /* scmp cannot reliably compare non-ASCII strings while
493 >= 0)) 496 ignoring letter-case. */
497 || (!completion_ignore_case
498 && scmp (dp->d_name, SSDATA (encoded_file), enc_file_len) >= 0))
494 continue; 499 continue;
495 500
501 name = make_unibyte_string (dp->d_name, len);
502 name = DECODE_FILE (name);
503 ptrdiff_t name_blen = SBYTES (name), name_len = SCHARS (name);
504 if (completion_ignore_case
505 && !EQ (Fcompare_strings (name, zero, file_len, file, zero, file_len,
506 Qt),
507 Qt))
508 continue;
509
496 switch (dirent_type (dp)) 510 switch (dirent_type (dp))
497 { 511 {
498 case DT_DIR: 512 case DT_DIR:
@@ -515,6 +529,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
515 if (!all_flag) 529 if (!all_flag)
516 { 530 {
517 ptrdiff_t skip; 531 ptrdiff_t skip;
532 Lisp_Object cmp_len = make_fixnum (name_len);
518 533
519#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */ 534#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */
520 /* If this entry matches the current bestmatch, the only 535 /* If this entry matches the current bestmatch, the only
@@ -538,7 +553,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
538 actually in the way in a directory with only one file. */ 553 actually in the way in a directory with only one file. */
539 if (TRIVIAL_DIRECTORY_ENTRY (dp->d_name)) 554 if (TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
540 canexclude = 1; 555 canexclude = 1;
541 else if (len > SCHARS (encoded_file)) 556 else if (len > enc_file_len)
542 /* Ignore directories if they match an element of 557 /* Ignore directories if they match an element of
543 completion-ignored-extensions which ends in a slash. */ 558 completion-ignored-extensions which ends in a slash. */
544 for (tem = Vcompletion_ignored_extensions; 559 for (tem = Vcompletion_ignored_extensions;
@@ -550,21 +565,31 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
550 elt = XCAR (tem); 565 elt = XCAR (tem);
551 if (!STRINGP (elt)) 566 if (!STRINGP (elt))
552 continue; 567 continue;
553 /* Need to encode ELT, since scmp compares unibyte 568 elt_len = SBYTES (elt) - 1; /* -1 for trailing / */
554 strings only. */
555 elt = ENCODE_FILE (elt);
556 elt_len = SCHARS (elt) - 1; /* -1 for trailing / */
557 if (elt_len <= 0) 569 if (elt_len <= 0)
558 continue; 570 continue;
559 p1 = SSDATA (elt); 571 p1 = SSDATA (elt);
560 if (p1[elt_len] != '/') 572 if (p1[elt_len] != '/')
561 continue; 573 continue;
562 skip = len - elt_len; 574 skip = name_blen - elt_len;
563 if (skip < 0) 575 if (skip < 0)
564 continue; 576 continue;
565 577
566 if (scmp (dp->d_name + skip, p1, elt_len) >= 0) 578 if (!completion_ignore_case
579 && scmp (SSDATA (name) + skip, p1, elt_len) >= 0)
567 continue; 580 continue;
581 if (completion_ignore_case)
582 {
583 elt_len = SCHARS (elt) - 1;
584 skip = name_len - elt_len;
585 cmp_len = make_fixnum (elt_len);
586 if (skip < 0
587 || !EQ (Fcompare_strings (name, make_fixnum (skip),
588 cmp_len,
589 elt, zero, cmp_len, Qt),
590 Qt))
591 continue;
592 }
568 break; 593 break;
569 } 594 }
570 } 595 }
@@ -572,22 +597,33 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
572 { 597 {
573 /* Compare extensions-to-be-ignored against end of this file name */ 598 /* Compare extensions-to-be-ignored against end of this file name */
574 /* if name is not an exact match against specified string */ 599 /* if name is not an exact match against specified string */
575 if (len > SCHARS (encoded_file)) 600 if (len > enc_file_len)
576 /* and exit this for loop if a match is found */ 601 /* and exit this for loop if a match is found */
577 for (tem = Vcompletion_ignored_extensions; 602 for (tem = Vcompletion_ignored_extensions;
578 CONSP (tem); tem = XCDR (tem)) 603 CONSP (tem); tem = XCDR (tem))
579 { 604 {
580 elt = XCAR (tem); 605 elt = XCAR (tem);
581 if (!STRINGP (elt)) continue; 606 if (!STRINGP (elt)) continue;
582 /* Need to encode ELT, since scmp compares unibyte 607 ptrdiff_t elt_len = SBYTES (elt);
583 strings only. */ 608 skip = len - elt_len;
584 elt = ENCODE_FILE (elt);
585 skip = len - SCHARS (elt);
586 if (skip < 0) continue; 609 if (skip < 0) continue;
587 610
588 if (scmp (dp->d_name + skip, SSDATA (elt), SCHARS (elt)) 611 if (!completion_ignore_case
589 >= 0) 612 && (scmp (SSDATA (name) + skip, SSDATA (elt), elt_len)
613 >= 0))
590 continue; 614 continue;
615 if (completion_ignore_case)
616 {
617 elt_len = SCHARS (elt);
618 skip = name_len - elt_len;
619 cmp_len = make_fixnum (elt_len);
620 if (skip < 0
621 || !EQ (Fcompare_strings (name, make_fixnum (skip),
622 cmp_len,
623 elt, zero, cmp_len, Qt),
624 Qt))
625 continue;
626 }
591 break; 627 break;
592 } 628 }
593 } 629 }
@@ -611,24 +647,18 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
611 matchcount = 0; 647 matchcount = 0;
612 } 648 }
613 } 649 }
614 /* FIXME: If we move this `decode' earlier we can eliminate
615 the repeated ENCODE_FILE on Vcompletion_ignored_extensions. */
616 name = make_unibyte_string (dp->d_name, len);
617 name = DECODE_FILE (name);
618 650
619 { 651 Lisp_Object regexps, table = (completion_ignore_case
620 Lisp_Object regexps, table = (completion_ignore_case 652 ? Vascii_canon_table : Qnil);
621 ? Vascii_canon_table : Qnil);
622 653
623 /* Ignore this element if it fails to match all the regexps. */ 654 /* Ignore this element if it fails to match all the regexps. */
624 for (regexps = Vcompletion_regexp_list; CONSP (regexps); 655 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
625 regexps = XCDR (regexps)) 656 regexps = XCDR (regexps))
626 if (fast_string_match_internal (XCAR (regexps), name, table) < 0) 657 if (fast_string_match_internal (XCAR (regexps), name, table) < 0)
627 break; 658 break;
628 659
629 if (CONSP (regexps)) 660 if (CONSP (regexps))
630 continue; 661 continue;
631 }
632 662
633 /* This is a possible completion */ 663 /* This is a possible completion */
634 if (directoryp) 664 if (directoryp)
@@ -642,8 +672,6 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
642 /* Reject entries where the encoded strings match, but the 672 /* Reject entries where the encoded strings match, but the
643 decoded don't. For example, "a" should not match "a-ring" on 673 decoded don't. For example, "a" should not match "a-ring" on
644 file systems that store decomposed characters. */ 674 file systems that store decomposed characters. */
645 Lisp_Object zero = make_fixnum (0);
646
647 if (check_decoded && SCHARS (file) <= SCHARS (name)) 675 if (check_decoded && SCHARS (file) <= SCHARS (name))
648 { 676 {
649 /* FIXME: This is a copy of the code below. */ 677 /* FIXME: This is a copy of the code below. */
@@ -757,6 +785,9 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
757 785
758 if (completion_ignore_case) 786 if (completion_ignore_case)
759 { 787 {
788 /* WARNING: This only works for pure ASCII strings, as we
789 compare bytes, not characters! Use Fcompare_strings for
790 comparing non-ASCII strings case-insensitively. */
760 while (l 791 while (l
761 && (downcase ((unsigned char) *s1++) 792 && (downcase ((unsigned char) *s1++)
762 == downcase ((unsigned char) *s2++))) 793 == downcase ((unsigned char) *s2++)))