diff --git a/ChangeLog b/ChangeLog
index 323a1a4593a3759a50a1a38810dcf3cd4f5a880b..a3521b1ce27b3d43dba650736fedb8d370225820 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -101,6 +101,10 @@ CVS code -
 	  nano is built with --disable-nls.  Changes to Makefile.am and
 	  doc/man/Makefile.am. (Mike Frysinger)
 	- Rename the NANO_SMALL #define to NANO_TINY. (DLR)
+	- Overhaul the bracket searching code so that it no longer
+	  requires regex support to work.  New functions revstrpbrk()
+	  and find_bracket_match(); changes to sc_init_one() and
+	  do_find_bracket(). (DLR)
 - chars.c:
   mbwidth()
 	- If wcwidth() returns -1 for the character passed in, treat the
@@ -132,6 +136,15 @@ CVS code -
 - rcfile.c:
   do_rcfile()
 	- Remove unneeded assert. (DLR)
+- search.c:
+  findnextstr()
+	- Remove parameter can_display_wrap, as it's always set to TRUE
+	  now, and rename parameter wholeword to whole_word for
+	  consistency. (DLR)
+  do_replace_loop()
+	- Change order of parameters to more closely match those of
+	  findnextstr(), and rename parameter wholewords to whole_word
+	  for consistency. (DLR)
 - text.c:
   begpar()
 	- Return FALSE if foo is NULL, as inpar() does. (DLR)
diff --git a/src/chars.c b/src/chars.c
index 90808a91a3f2b24d24165c1767bd4d17c4cfc23a..09b2b9b1352ba4936cdaf64a725cd0fe2aeb1985 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -814,6 +814,26 @@ size_t mbstrnlen(const char *s, size_t maxlen)
 	return strnlen(s, maxlen);
 }
 
+#ifndef NANO_TINY
+/* This function is equivalent to strpbrk(), except in that it scans the
+ * string in reverse, starting at rev_start. */
+char *revstrpbrk(const char *s, const char *accept, const char
+	*rev_start)
+{
+    assert(s != NULL && accept != NULL && rev_start != NULL);
+
+    for (; rev_start >= s; rev_start--) {
+	const char *q = (*rev_start == '\0') ? NULL : strchr(accept,
+		*rev_start);
+
+	if (q != NULL)
+	    return (char *)rev_start;
+    }
+
+    return NULL;
+}
+#endif /* !NANO_TINY */
+
 #ifndef DISABLE_JUSTIFY
 /* This function is equivalent to strchr() for multibyte strings. */
 char *mbstrchr(const char *s, char *c)
diff --git a/src/global.c b/src/global.c
index 960112eae0c42a268d9214b4c944593ba146828e..984c13a4aec0333d1e30e744c1983706c2a2471c 100644
--- a/src/global.c
+++ b/src/global.c
@@ -313,7 +313,7 @@ void shortcut_init(bool unjustify)
 #ifndef DISABLE_JUSTIFY
     const char *nano_fulljustify_msg = N_("Justify the entire file");
 #endif
-#if !defined(NANO_TINY) && defined(HAVE_REGEX_H)
+#ifndef NANO_TINY
     const char *nano_bracket_msg = N_("Find other bracket");
 #endif
     const char *nano_cancel_msg = N_("Cancel the current function");
@@ -594,7 +594,7 @@ void shortcut_init(bool unjustify)
 	NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_full_justify);
 #endif
 
-#if !defined(NANO_TINY) && defined(HAVE_REGEX_H)
+#ifndef NANO_TINY
     sc_init_one(&main_list, NANO_NO_KEY, N_("Find Other Bracket"),
 	IFHELP(nano_bracket_msg, NANO_BRACKET_KEY), NANO_NO_KEY,
 	NANO_NO_KEY, VIEW, do_find_bracket);
diff --git a/src/proto.h b/src/proto.h
index e9872176f10f35be2124044abe5a0370c4b50830..8e93bdc091c1815c0cb3a4812ca38030fbbc3a89 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -196,6 +196,10 @@ size_t mbstrlen(const char *s);
 size_t nstrnlen(const char *s, size_t maxlen);
 #endif
 size_t mbstrnlen(const char *s, size_t maxlen);
+#ifndef NANO_TINY
+char *revstrpbrk(const char *s, const char *accept, const char
+	*rev_start);
+#endif
 #ifndef DISABLE_JUSTIFY
 char *mbstrchr(const char *s, char *c);
 #ifdef ENABLE_NANORC
@@ -489,9 +493,8 @@ void not_found_msg(const char *str);
 void search_abort(void);
 void search_init_globals(void);
 int search_init(bool replacing, bool use_answer);
-bool findnextstr(bool can_display_wrap, bool wholeword, bool
-	no_sameline, const filestruct *begin, size_t begin_x, const char
-	*needle, size_t *needle_len);
+bool findnextstr(bool whole_word, bool no_sameline, const filestruct
+	*begin, size_t begin_x, const char *needle, size_t *needle_len);
 void findnextstr_wrap_reset(void);
 void do_search(void);
 #ifndef NANO_TINY
@@ -502,9 +505,9 @@ void replace_abort(void);
 int replace_regexp(char *string, bool create);
 #endif
 char *replace_line(const char *needle);
-ssize_t do_replace_loop(const char *needle, const filestruct
-	*real_current, size_t *real_current_x, bool wholewords, bool
-	*canceled);
+ssize_t do_replace_loop(bool whole_word, bool *canceled, const
+	filestruct *real_current, size_t *real_current_x, const char
+	*needle);
 void do_replace(void);
 void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
 	bool interactive, bool save_pos, bool allow_update);
@@ -514,9 +517,8 @@ void do_gotopos(ssize_t line, size_t pos_x, ssize_t pos_y, size_t
 	pos_pww);
 #endif
 #ifndef NANO_TINY
-#ifdef HAVE_REGEX_H
+bool find_bracket_match(bool reverse, const char *bracket_set);
 void do_find_bracket(void);
-#endif
 #ifdef ENABLE_NANORC
 bool history_has_changed(void);
 #endif
diff --git a/src/search.c b/src/search.c
index 3ee62e625215d2e67dd1ff0510e834b81bd71ee2..8b49bd33f55d5147391cc4819e0921bf516df576 100644
--- a/src/search.c
+++ b/src/search.c
@@ -256,21 +256,18 @@ int search_init(bool replacing, bool use_answer)
 
 /* Look for needle, starting at (current, current_x).  If no_sameline is
  * TRUE, skip over begin when looking for needle.  begin is the line
- * where we first started searching, at column begin_x.  If
- * can_display_wrap is TRUE, we put messages on the statusbar and wrap
- * around the file boundaries.  The return value specifies whether we
- * found anything.  If we did, set needle_len to the length of the
- * string we found if it isn't NULL. */
-bool findnextstr(bool can_display_wrap, bool wholeword, bool
-	no_sameline, const filestruct *begin, size_t begin_x, const char
-	*needle, size_t *needle_len)
+ * where we first started searching, at column begin_x.  The return
+ * value specifies whether we found anything.  If we did, set needle_len
+ * to the length of the string we found if it isn't NULL. */
+bool findnextstr(bool whole_word, bool no_sameline, const filestruct
+	*begin, size_t begin_x, const char *needle, size_t *needle_len)
 {
     filestruct *fileptr = openfile->current;
     const char *rev_start = NULL, *found = NULL;
     size_t found_len;
 	/* The length of the match we found. */
     size_t current_x_find = 0;
-	/* The location of the match we found. */
+	/* The location in the current line of the match we found. */
     ssize_t current_y_find = openfile->current_y;
 
     /* rev_start might end up 1 character before the start or after the
@@ -304,7 +301,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
 
 	    /* If we're searching for whole words, see if this potential
 	     * match is a whole word. */
-	    if (wholeword) {
+	    if (whole_word) {
 		char *word = mallocstrncpy(NULL, found, found_len + 1);
 		word[found_len] = '\0';
 
@@ -317,15 +314,14 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
 	     * match isn't a whole word, or if we're not allowed to find
 	     * a match on the same line we started on and this potential
 	     * match is on that line, continue searching. */
-	    if ((!wholeword || found_whole) && (!no_sameline ||
+	    if ((!whole_word || found_whole) && (!no_sameline ||
 		fileptr != openfile->current))
 		break;
 	}
 
 	/* We've finished processing the file, so get out. */
 	if (search_last_line) {
-	    if (can_display_wrap)
-		not_found_msg(needle);
+	    not_found_msg(needle);
 	    return FALSE;
 	}
 
@@ -343,9 +339,6 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
 
 	/* Start or end of buffer reached, so wrap around. */
 	if (fileptr == NULL) {
-	    if (!can_display_wrap)
-		return FALSE;
-
 #ifndef NANO_TINY
 	    if (ISSET(BACKWARDS_SEARCH)) {
 		fileptr = openfile->filebot;
@@ -358,8 +351,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
 	    }
 #endif
 
-	    if (can_display_wrap)
-		statusbar(_("Search Wrapped"));
+	    statusbar(_("Search Wrapped"));
 	}
 
 	/* Original start line reached. */
@@ -385,8 +377,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
 	current_x_find > begin_x
 #endif
 	) {
-	if (can_display_wrap)
-	    not_found_msg(needle);
+	not_found_msg(needle);
 	return FALSE;
     }
 
@@ -450,7 +441,7 @@ void do_search(void)
 #endif
 
     findnextstr_wrap_reset();
-    didfind = findnextstr(TRUE, FALSE, FALSE, openfile->current,
+    didfind = findnextstr(FALSE, FALSE, openfile->current,
 	openfile->current_x, answer, NULL);
 
     /* Check to see if there's only one occurrence of the string and
@@ -465,7 +456,7 @@ void do_search(void)
 	 * which case it's the only occurrence. */
 	if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
 		last_search)) {
-	    didfind = findnextstr(TRUE, FALSE, TRUE, openfile->current,
+	    didfind = findnextstr(FALSE, TRUE, openfile->current,
 		openfile->current_x, answer, NULL);
 	    if (fileptr == openfile->current && fileptr_x ==
 		openfile->current_x && !didfind)
@@ -506,7 +497,7 @@ void do_research(void)
 #endif
 
 	findnextstr_wrap_reset();
-	didfind = findnextstr(TRUE, FALSE, FALSE, openfile->current,
+	didfind = findnextstr(FALSE, FALSE, openfile->current,
 		openfile->current_x, last_search, NULL);
 
 	/* Check to see if there's only one occurrence of the string and
@@ -521,9 +512,8 @@ void do_research(void)
 	     * found again, in which case it's the only occurrence. */
 	    if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
 		last_search)) {
-		didfind = findnextstr(TRUE, FALSE, TRUE,
-			openfile->current, openfile->current_x, answer,
-			NULL);
+		didfind = findnextstr(FALSE, TRUE, openfile->current,
+			openfile->current_x, answer, NULL);
 		if (fileptr == openfile->current && fileptr_x ==
 			openfile->current_x && !didfind)
 		    statusbar(_("This is the only occurrence"));
@@ -649,9 +639,9 @@ char *replace_line(const char *needle)
  * needle is the string to seek.  We replace it with answer.  Return -1
  * if needle isn't found, else the number of replacements performed.  If
  * canceled isn't NULL, set it to TRUE if we canceled. */
-ssize_t do_replace_loop(const char *needle, const filestruct
-	*real_current, size_t *real_current_x, bool wholewords, bool
-	*canceled)
+ssize_t do_replace_loop(bool whole_word, bool *canceled, const
+	filestruct *real_current, size_t *real_current_x, const char
+	*needle)
 {
     ssize_t numreplaced = -1;
     size_t match_len;
@@ -685,7 +675,7 @@ ssize_t do_replace_loop(const char *needle, const filestruct
 	*canceled = FALSE;
 
     findnextstr_wrap_reset();
-    while (findnextstr(TRUE, wholewords,
+    while (findnextstr(whole_word,
 #ifdef HAVE_REGEX_H
 	/* We should find a bol and/or eol regex only once per line.  If
 	 * the bol_or_eol flag is set, it means that the last search
@@ -922,8 +912,8 @@ void do_replace(void)
     begin_x = openfile->current_x;
     pww_save = openfile->placewewant;
 
-    numreplaced = do_replace_loop(last_search, begin, &begin_x, FALSE,
-	NULL);
+    numreplaced = do_replace_loop(FALSE, NULL, begin, &begin_x,
+	last_search);
 
     /* Restore where we were. */
     openfile->edittop = edittop_save;
@@ -1034,22 +1024,95 @@ void do_gotopos(ssize_t line, size_t pos_x, ssize_t pos_y, size_t
 #endif
 
 #ifndef NANO_TINY
-#ifdef HAVE_REGEX_H
+/* Search for a match to one of the two characters in bracket_set.  If
+ * reverse is TRUE, search backwards.  Otherwise, search forwards. */
+bool find_bracket_match(bool reverse, const char *bracket_set)
+{
+    filestruct *fileptr = openfile->current;
+    const char *rev_start = NULL, *found = NULL;
+    size_t current_x_find = 0;
+	/* The location in the current line of the match we found. */
+    ssize_t current_y_find = openfile->current_y;
+
+    assert(strlen(bracket_set) == 2);
+
+    /* rev_start might end up 1 character before the start or after the
+     * end of the line.  This won't be a problem because we'll skip over
+     * it below in that case, and rev_start will be properly set when
+     * the search continues on the previous or next line. */
+    rev_start = reverse ? fileptr->data + (openfile->current_x - 1) :
+	fileptr->data + (openfile->current_x + 1);
+
+    /* Look for either of the two characters in bracket_set.  rev_start
+     * can be 1 character before the start or after the end of the line.
+     * In either case, just act as though no match is found. */
+    while (TRUE) {
+	found = ((rev_start > fileptr->data && *(rev_start - 1) ==
+		'\0') || rev_start < fileptr->data) ? NULL : (reverse ?
+		revstrpbrk(fileptr->data, bracket_set, rev_start) :
+		strpbrk(rev_start, bracket_set));
+
+	/* We've found a potential match. */
+	if (found != NULL)
+	    break;
+
+	if (reverse) {
+	    fileptr = fileptr->prev;
+	    current_y_find--;
+	} else {
+	    fileptr = fileptr->next;
+	    current_y_find++;
+	}
+
+	/* Start or end of buffer reached, so get out. */
+	if (fileptr == NULL)
+	    return FALSE;
+
+	rev_start = fileptr->data;
+	if (reverse)
+	    rev_start += strlen(fileptr->data);
+    }
+
+    /* We found an instance. */
+    current_x_find = found - fileptr->data;
+
+    /* We've definitely found something. */
+    openfile->current = fileptr;
+    openfile->current_x = current_x_find;
+    openfile->placewewant = xplustabs();
+    openfile->current_y = current_y_find;
+
+    return TRUE;
+}
+
+/* Search for a match to the bracket at the current cursor position, if
+ * there is one. */
 void do_find_bracket(void)
 {
-    const char *bracket_pat = "()<>[]{}", *pos;
-    char regex_pat[] = "[  ]", ch, wanted_ch;
     filestruct *current_save;
     size_t current_x_save, pww_save;
-    bool regexp_set = ISSET(USE_REGEXP);
-    bool backwards_search_set = ISSET(BACKWARDS_SEARCH);
-    int count = 1;
-
-    assert(strlen(bracket_pat) % 2 == 0);
+    const char *bracket_list = "()<>[]{}";
+	/* The list of brackets we can find matches to. */
+    const char *pos;
+	/* The location in bracket_list of the bracket at the current
+	 * cursor position. */
+    char ch;
+	/* The bracket at the current cursor position. */
+    char wanted_ch;
+	/* The bracket complementing the bracket at the current cursor
+	 * position. */
+    char bracket_set[3];
+	/* The pair of characters in ch and wanted_ch. */
+    size_t count = 1;
+	/* The initial bracket count. */
+    bool reverse;
+	/* The direction we search. */
+
+    assert(strlen(bracket_list) % 2 == 0);
 
     ch = openfile->current->data[openfile->current_x];
 
-    if (ch == '\0' || (pos = strchr(bracket_pat, ch)) == NULL) {
+    if (ch == '\0' || (pos = strchr(bracket_list, ch)) == NULL) {
 	statusbar(_("Not a bracket"));
 	return;
     }
@@ -1059,40 +1122,17 @@ void do_find_bracket(void)
     current_x_save = openfile->current_x;
     pww_save = openfile->placewewant;
 
-    /* Turn regular expression searches on. */
-    SET(USE_REGEXP);
-
     /* If we're on an opening bracket, we want to search forwards for a
      * closing bracket, and if we're on a closing bracket, we want to
-     * search backwards for an opening bracket.
-     *
-     * We replace the spaces in regex_pat with the opening and closing
-     * brackets, and then do a regular expression search using it.  We
-     * have to put the closing bracket first when we do the latter,
-     * since "[[]]" won't work properly, but "[][]" will. */
-    if ((pos - bracket_pat) % 2 == 0) {
-	wanted_ch = *(pos + 1);
-	regex_pat[1] = wanted_ch;
-	regex_pat[2] = ch;
-	UNSET(BACKWARDS_SEARCH);
-    } else {
-	wanted_ch = *(pos - 1);
-	regex_pat[1] = ch;
-	regex_pat[2] = wanted_ch;
-	SET(BACKWARDS_SEARCH);
-    }
-
-    /* Compile the regular expression in regex_pat. */
-    regexp_init(regex_pat);
-
-    /* The regular expression in regex_pat should always be valid. */
-    assert(regexp_compiled);
-
-    findnextstr_wrap_reset();
+     * search backwards for an opening bracket. */
+    reverse = ((pos - bracket_list) % 2 != 0);
+    wanted_ch = reverse ? *(pos - 1) : *(pos + 1);
+    bracket_set[0] = ch;
+    bracket_set[1] = wanted_ch;
+    bracket_set[2] = '\0';
 
     while (TRUE) {
-	if (findnextstr(FALSE, FALSE, FALSE, openfile->current,
-		openfile->current_x, regex_pat, NULL)) {
+	if (find_bracket_match(reverse, bracket_set)) {
 	    /* If we found an identical bracket, increment count.  If we
 	     * found a complementary bracket, decrement it. */
 	    count += (openfile->current->data[openfile->current_x] ==
@@ -1114,21 +1154,7 @@ void do_find_bracket(void)
 	    break;
 	}
     }
-
-    /* Decompile the regular expression in regex_pat. */
-    regexp_cleanup();
-
-    /* Restore search/replace direction. */
-    if (backwards_search_set)
-	SET(BACKWARDS_SEARCH);
-    else
-	UNSET(BACKWARDS_SEARCH);
-
-    /* Restore regular expression usage setting. */
-    if (!regexp_set)
-	UNSET(USE_REGEXP);
 }
-#endif /* HAVE_REGEX_H */
 
 #ifdef ENABLE_NANORC
 /* Indicate whether any of the history lists have changed. */
diff --git a/src/text.c b/src/text.c
index 031357751254bcd5385ecefc1a477f413653b3d9..6724ea176961de78ed35bf2b0e2ac40acb464bb3 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1589,9 +1589,9 @@ bool do_int_spell_fix(const char *word)
     openfile->current_x = (size_t)-1;
     openfile->placewewant = 0;
 
-    /* Find the first whole-word occurrence of word. */
+    /* Find the first whole occurrence of word. */
     findnextstr_wrap_reset();
-    while (findnextstr(TRUE, TRUE, FALSE, openfile->fileage, 0, word,
+    while (findnextstr(TRUE, FALSE, openfile->fileage, 0, word,
 	&match_len)) {
 	if (is_whole_word(openfile->current_x, openfile->current->data,
 		word)) {
@@ -1617,8 +1617,8 @@ bool do_int_spell_fix(const char *word)
 
 	    if (!canceled && strcmp(word, answer) != 0) {
 		openfile->current_x--;
-		do_replace_loop(word, openfile->current,
-			&openfile->current_x, TRUE, &canceled);
+		do_replace_loop(TRUE, &canceled, openfile->current,
+			&openfile->current_x, word);
 	    }
 
 	    break;