diff --git a/ChangeLog b/ChangeLog
index 853237f6fa37b7ef7a5d55a755d2f54420f1c491..8c779a1ada796fb8d38652af891a11758248928e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-03-30  Benno Schulenberg  <bensberg@justemail.net>
+	* src/search.c (do_replace_loop, go_looking, findnextstr): Report
+	"Cancelled" instead of "Not found" when the user aborts a replace
+	that is taking too long.  This fixes Savannah bug #47439.
+
 2016-03-29  Benno Schulenberg  <bensberg@justemail.net>
 	* src/nano.c (main), src/text.c (do_justify, do_verbatim_input),
 	src/winio.c (parse_escape_sequence): Place the cursor in the edit
diff --git a/src/proto.h b/src/proto.h
index a8bca721aaa9a7d34a016bd68c01df71d27f9101..764634cfab1653c697bd96a734a49fdca735c25e 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -582,7 +582,7 @@ void regexp_cleanup(void);
 void not_found_msg(const char *str);
 void search_replace_abort(void);
 int search_init(bool replacing, bool use_answer);
-bool findnextstr(
+int findnextstr(
 #ifndef DISABLE_SPELLER
 	bool whole_word_only,
 #endif
diff --git a/src/search.c b/src/search.c
index 392183fe157b289e5bc5eaa4aef842bef7b58e84..daa608d953bf33335caefdff2571019bf645a7bf 100644
--- a/src/search.c
+++ b/src/search.c
@@ -248,10 +248,10 @@ int search_init(bool replacing, bool use_answer)
 }
 
 /* Look for needle, starting at (current, current_x).  begin is the line
- * where we first started searching, at column begin_x.  The return
- * value specifies whether we found anything.  If we did, set match_len
- * to the length of the string we found if it isn't NULL. */
-bool findnextstr(
+ * 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(
 #ifndef DISABLE_SPELLER
 	bool whole_word_only,
 #endif
@@ -291,7 +291,7 @@ bool findnextstr(
 
 	    if (input && func_from_key(&input) == do_cancel) {
 		statusbar(_("Cancelled"));
-		return FALSE;
+		return -2;
 	    }
 
 	    if (++feedback > 0)
@@ -310,7 +310,7 @@ bool findnextstr(
 	     * again -- there is no need: we started at x = 0. */
 	    if (whole_word_only && search_last_line) {
 		disable_nodelay();
-		return FALSE;
+		return 0;
 	    }
 #endif
 	    /* Remember the length of the potential match. */
@@ -343,7 +343,7 @@ bool findnextstr(
 	if (search_last_line) {
 	    not_found_msg(needle);
 	    disable_nodelay();
-	    return FALSE;
+	    return 0;
 	}
 
 	/* Move to the previous or next line in the file. */
@@ -402,7 +402,7 @@ bool findnextstr(
     if (feedback > 0)
 	blank_statusbar();
 
-    return TRUE;
+    return 1;
 }
 
 /* Clear the flag indicating that a search reached the last line of the
@@ -492,7 +492,7 @@ void go_looking(void)
     filestruct *was_current = openfile->current;
     size_t was_current_x = openfile->current_x;
     size_t was_pww = openfile->placewewant;
-    bool didfind;
+    int didfind;
 
     findnextstr_wrap_reset();
     didfind = findnextstr(
@@ -503,7 +503,7 @@ void go_looking(void)
 
     /* If we found something, and we're back at the exact same spot
      * where we started searching, then this is the only occurrence. */
-    if (didfind && openfile->current == was_current &&
+    if (didfind == 1 && openfile->current == was_current &&
 		openfile->current_x == was_current_x)
 	statusbar(_("This is the only occurrence"));
 
@@ -643,12 +643,20 @@ ssize_t do_replace_loop(
 #endif /* !NANO_TINY */
 
     findnextstr_wrap_reset();
-    while (findnextstr(
+    while (TRUE) {
+	int i = 0;
+	int result = findnextstr(
 #ifndef DISABLE_SPELLER
-	whole_word_only,
+			whole_word_only,
 #endif
-	real_current, *real_current_x, needle, &match_len)) {
-	int i = 0;
+			real_current, *real_current_x, needle, &match_len);
+
+	/* If nothing more was found, or the user aborted, stop looping. */
+	if (result < 1) {
+	    if (result < 0)
+		numreplaced = -2;  /* It's a Cancel instead of Not found. */
+	    break;
+	}
 
 #ifndef NANO_TINY
 	if (old_mark_set) {
diff --git a/src/text.c b/src/text.c
index fc1f2a18ae7f06a29c1b7e32fd18f41b40d9a74d..2d096a161c6efe906bb3a9f87940dba85f1cb78f 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2419,7 +2419,7 @@ bool do_int_spell_fix(const char *word)
 
     /* Find the first whole occurrence of word. */
     findnextstr_wrap_reset();
-    while (findnextstr(TRUE, openfile->fileage, 0, word, &match_len)) {
+    while (findnextstr(TRUE, openfile->fileage, 0, word, &match_len) == 1) {
 	if (is_whole_word(openfile->current_x, openfile->current->data,
 		word)) {
 	    size_t xpt = xplustabs();