diff --git a/ChangeLog b/ChangeLog index eaaf9b1f..d3fd88dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -98,21 +98,21 @@ CVS code - is_blank_wchar(), is_cntrl_mbchar(), is_cntrl_wchar(), control_mbrep(), control_wrep(), mbwidth(), mb_cur_max(), make_mbchar(), mbstrnlen(), mbstrcasecmp(), mbstrncasecmp(), - and mbstrcasestr(); changes to is_byte() (moved to chars.c), - is_blank_char() (moved to chars.c), is_cntrl_char() (moved to - chars.c), nstricmp() (renamed nstrcasecmp() and moved to - chars.c), nstrnicmp() (renamed nstrncasecmp() and moved to - chars.c), nstristr() (renamed nstrcasestr() and moved to - chars.c), revstrstr() (moved to chars.c), revstristr() - (renamed revstrcasestr() and moved to chars.c), nstrnlen() - (moved to chars.c), parse_char() (renamed parse_mbchar() and - moved to chars.c), move_left() (renamed move_mbleft() and - moved to chars.c), move_right() (renamed move_mbright() and - moved to chars.c), do_home(), do_verbatim_input(), - do_delete(), do_tab(), do_next_word(), do_prev_word(), - do_input(), do_output(), strstrwrapper(), get_buffer(), - unget_input(), unget_kbinput(), get_input(), parse_kbinput(), - unparse_kbinput(), parse_verbatim_kbinput(), + mbstrcasestr(), and mbrevstrcasestr(); changes to is_byte() + (moved to chars.c), is_blank_char() (moved to chars.c), + is_cntrl_char() (moved to chars.c), nstricmp() (renamed + nstrcasecmp() and moved to chars.c), nstrnicmp() (renamed + nstrncasecmp() and moved to chars.c), nstristr() (renamed + nstrcasestr() and moved to chars.c), revstrstr() (moved to + chars.c), revstristr() (renamed revstrcasestr() and moved to + chars.c), nstrnlen() (moved to chars.c), parse_char() + (renamed parse_mbchar() and moved to chars.c), move_left() + (renamed move_mbleft() and moved to chars.c), move_right() + (renamed move_mbright() and moved to chars.c), do_home(), + do_verbatim_input(), do_delete(), do_tab(), do_next_word(), + do_prev_word(), do_input(), do_output(), strstrwrapper(), + get_buffer(), unget_input(), unget_kbinput(), get_input(), + parse_kbinput(), unparse_kbinput(), parse_verbatim_kbinput(), do_statusbar_input(), do_statusbar_home(), do_statusbar_verbatim_kbinput(), do_statusbar_output(), and display_string(); removal of buffer_to_keys() and diff --git a/src/chars.c b/src/chars.c index ccd0d7e3..8c92908e 100644 --- a/src/chars.c +++ b/src/chars.c @@ -692,6 +692,68 @@ const char *revstrcasestr(const char *haystack, const char *needle, return NULL; } + +/* This function is equivalent to strcasestr() for multibyte strings, + * except in that it scans the string in reverse, starting at + * rev_start. */ +const char *mbrevstrcasestr(const char *haystack, const char *needle, + const char *rev_start) +{ +#ifdef NANO_WIDE + if (!ISSET(NO_UTF8)) { + char *r_mb = charalloc(MB_CUR_MAX); + char *q_mb = charalloc(MB_CUR_MAX); + wchar_t wr, wq; + bool begin_line = FALSE, found_needle = FALSE; + + assert(haystack != NULL && needle != NULL && rev_start != NULL); + + while (!begin_line) { + const char *r = rev_start, *q = needle; + int r_mb_len, q_mb_len; + + while (*q != '\0') { + r_mb_len = parse_mbchar(r, r_mb, NULL, NULL); + + if (mbtowc(&wr, r_mb, r_mb_len) <= 0) { + mbtowc(NULL, NULL, 0); + wr = (unsigned char)*r; + } + + q_mb_len = parse_mbchar(q, q_mb, NULL, NULL); + + if (mbtowc(&wq, q_mb, q_mb_len) <= 0) { + mbtowc(NULL, NULL, 0); + wq = (unsigned char)*q; + } + + if (towlower(wr) != towlower(wq)) + break; + + r += r_mb_len; + q += q_mb_len; + } + + if (*q == '\0') { + found_needle = TRUE; + break; + } + + if (rev_start == haystack) + begin_line = TRUE; + else + rev_start = haystack + move_mbleft(haystack, rev_start - + haystack); + } + + free(r_mb); + free(q_mb); + + return found_needle ? rev_start : NULL; + } else +#endif + return revstrcasestr(haystack, needle, rev_start); +} #endif #ifndef HAVE_STRNLEN diff --git a/src/proto.h b/src/proto.h index 3d1e7649..668d1002 100644 --- a/src/proto.h +++ b/src/proto.h @@ -199,6 +199,8 @@ const char *revstrstr(const char *haystack, const char *needle, const char *rev_start); const char *revstrcasestr(const char *haystack, const char *needle, const char *rev_start); +const char *mbrevstrcasestr(const char *haystack, const char *needle, + const char *rev_start); #endif #ifndef HAVE_STRNLEN size_t nstrnlen(const char *s, size_t maxlen); diff --git a/src/utils.c b/src/utils.c index 601ee296..64064098 100644 --- a/src/utils.c +++ b/src/utils.c @@ -243,7 +243,7 @@ const char *strstrwrapper(const char *haystack, const char *needle, #endif /* !DISABLE_SPELLER || !NANO_SMALL */ #ifndef NANO_SMALL else if (ISSET(REVERSE_SEARCH)) - return revstrcasestr(haystack, needle, start); + return mbrevstrcasestr(haystack, needle, start); #endif return mbstrcasestr(start, needle); }