From 345260c624d1447c44716e69fc21b3d077559c62 Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Mon, 24 Jan 2005 01:14:17 +0000
Subject: [PATCH] add multibyte version of revstrcasestr()

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2296 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog   | 30 +++++++++++++-------------
 src/chars.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/proto.h |  2 ++
 src/utils.c |  2 +-
 4 files changed, 80 insertions(+), 16 deletions(-)

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);
 }
-- 
GitLab