diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 101 |
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++))) |