diff --git complete.c complete.c index e67cfeb..30add90 100644 --- complete.c +++ complete.c @@ -2085,39 +2085,85 @@ complete_fncmp (convfn, convlen, filename, filename_len) int filename_len; { register char *s1, *s2; + char c1, c2; int d, len; - - /* Otherwise, if these match up to the length of filename, then - it is a match. */ +#if defined (HANDLE_MULTIBYTE) + wchar_t wc1, wc2; + mbstate_t ps1, ps2; + int v; +#endif +/* Case-insensitive comparison treating _ and - as equivalent */ if (_rl_completion_case_fold && _rl_completion_case_map) { - /* Case-insensitive comparison treating _ and - as equivalent */ - if (filename_len == 0) - return 1; if (convlen < filename_len) return 0; - s1 = (char *)convfn; - s2 = (char *)filename; - len = filename_len; - do + s1 = (char*)convfn; + s2 = (char*)filename; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented != 0) + goto case_map_byte; + + memset (&ps1, 0, sizeof (mbstate_t)); + memset (&ps2, 0, sizeof (mbstate_t)); + + /* convlen and filename_len in every interation is ok here */ + /* as we believe multibyte sequences are ok */ + while ((v = mbrtowc (&wc1, s1, convlen, &ps1), wc1) && + (mbrtowc (&wc2, s2, filename_len, &ps2), wc2)) + { + s1 += v; + s2 += v; + if ((wc1 == '-' || wc1 == '_') && + (wc2 == '-' || wc2 == '_')) + continue; + if (towlower(wc1) != towlower(wc2)) + return 0; + } + return 1; +#endif +case_map_byte: + while ((c1 = *s1++) && (c2 = *s2++)) { - d = _rl_to_lower (*s1) - _rl_to_lower (*s2); - /* *s1 == [-_] && *s2 == [-_] */ - if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_')) - d = 0; - if (d != 0) + if ((c1 == '-' || c1 == '_') && + (c2 == '-' || c2 == '_')) + continue; + if (_rl_to_lower(c1) != _rl_to_lower(c2)) return 0; - s1++; s2++; /* already checked convlen >= filename_len */ } - while (--len != 0); return 1; } else if (_rl_completion_case_fold) { - if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) && - (convlen >= filename_len) && - (_rl_strnicmp (filename, convfn, filename_len) == 0)) - return 1; + if (convlen < filename_len) + return 0; + s1 = (char*)convfn; + s2 = (char*)filename; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented != 0) + goto case_byte; + + memset (&ps1, 0, sizeof (mbstate_t)); + memset (&ps2, 0, sizeof (mbstate_t)); + + /* convlen and filename_len in every interation is ok here */ + /* as we believe multibyte sequences are ok */ + while ((v = mbrtowc (&wc1, s1, convlen, &ps1), wc1) && + (mbrtowc (&wc2, s2, filename_len, &ps2), wc2)) + { + if (towlower(wc1) != towlower(wc2)) + return 0; + s1 += v; + s2 += v; + } + return 1; +#endif +case_byte: + while ((c1 = *s1++) && (c2 = *s2++)) + { + if (_rl_to_lower(c1) != _rl_to_lower(c2)) + return 0; + } + return 1; } else {