From 8f10e364bb3f2a6f0adcc6b320b19593b28c76b9 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@justemail.net>
Date: Fri, 10 Feb 2017 13:51:51 +0100
Subject: [PATCH] replacing: stop searching in a region when edge of buffer is
 reached

Just like when spell-checking, there is no need to wrap around when
doing replacements in a region, because a region cannot straddle the
buffer's edges.

This is the proper fix for https://savannah.gnu.org/bugs/?50158,
and fixes https://savannah.gnu.org/bugs/?50273.
---
 src/proto.h  |  4 ++--
 src/search.c | 21 ++++++++++-----------
 src/text.c   |  2 +-
 3 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/src/proto.h b/src/proto.h
index 65548e3b..3945f073 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -532,8 +532,8 @@ void regexp_cleanup(void);
 void not_found_msg(const char *str);
 void search_replace_abort(void);
 int search_init(bool replacing, bool use_answer);
-int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
-	bool skipone, const filestruct *begin, size_t begin_x);
+int findnextstr(const char *needle, bool whole_word_only, bool have_region,
+	size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
 void do_search(void);
 #ifndef NANO_TINY
 void do_findprevious(void);
diff --git a/src/search.c b/src/search.c
index a6f44663..d932ade0 100644
--- a/src/search.c
+++ b/src/search.c
@@ -231,8 +231,8 @@ int search_init(bool replacing, bool use_answer)
  * where we first started searching, at column begin_x.  Return 1 when we
  * found something, 0 when nothing, and -2 on cancel.  When match_len is
  * not NULL, set it to the length of the found string, if any. */
-int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
-	bool skipone, const filestruct *begin, size_t begin_x)
+int findnextstr(const char *needle, bool whole_word_only, bool have_region,
+	size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x)
 {
     size_t found_len = strlen(needle);
 	/* The length of a match -- will be recomputed for a regex. */
@@ -328,15 +328,14 @@ int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
 	else
 	    line = line->next;
 
-	/* If we've reached the start or end of the buffer, wrap around. */
+	/* If we've reached the start or end of the buffer, wrap around;
+	 * but stop when spell-checking or replacing in a region. */
 	if (line == NULL) {
-#ifndef DISABLE_SPELLER
-	    /* When we're spell-checking, end-of-buffer means we're done. */
-	    if (whole_word_only) {
+	    if (whole_word_only || have_region) {
 		disable_nodelay();
 		return 0;
 	    }
-#endif
+
 	    if (ISSET(BACKWARDS_SEARCH))
 		line = openfile->filebot;
 	    else
@@ -463,7 +462,7 @@ void go_looking(void)
 
     came_full_circle = FALSE;
 
-    didfind = findnextstr(last_search, FALSE, NULL, FALSE,
+    didfind = findnextstr(last_search, FALSE, FALSE, NULL, FALSE,
 				openfile->current, openfile->current_x);
 
     /* If we found something, and we're back at the exact same spot
@@ -609,8 +608,8 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
 
     while (TRUE) {
 	int i = 0;
-	int result = findnextstr(needle, whole_word_only, &match_len, skipone,
-					real_current, *real_current_x);
+	int result = findnextstr(needle, whole_word_only, old_mark_set,
+			&match_len, skipone, real_current, *real_current_x);
 
 	/* If nothing more was found, or the user aborted, stop looping. */
 	if (result < 1) {
@@ -623,7 +622,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
 	if (old_mark_set) {
 	    /* When we've found an occurrence outside of the marked region,
 	     * stop the fanfare. */
-	    if (came_full_circle || openfile->current->lineno > bot->lineno ||
+	    if (openfile->current->lineno > bot->lineno ||
 			openfile->current->lineno < top->lineno ||
 			(openfile->current == bot && openfile->current_x + match_len > bot_x) ||
 			(openfile->current == top && openfile->current_x < top_x))
diff --git a/src/text.c b/src/text.c
index a1acf0a8..161cc1d8 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2656,7 +2656,7 @@ bool do_int_spell_fix(const char *word)
     }
 
     /* Find the first whole occurrence of word. */
-    result = findnextstr(word, TRUE, NULL, FALSE, NULL, 0);
+    result = findnextstr(word, TRUE, TRUE, NULL, FALSE, NULL, 0);
 
     /* If the word isn't found, alert the user; if it is, allow correction. */
     if (result == 0) {
-- 
GitLab