From 3497666a216d87a890b2d57282d672682c036ae3 Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Sat, 9 Oct 2004 16:26:32 +0000
Subject: [PATCH] in do_replace_loop(), if the mark is on when we start, skip
 over all matches not found inside the marked text; this makes marked spell
 checking when using the internal spell checker work as expected, and also
 allows replacing only marked text when the mark is on

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1978 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog    |  6 ++++++
 TODO         |  3 ++-
 src/proto.h  |  4 ++--
 src/search.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
 4 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 12de2a77..e90a5fd8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -154,6 +154,12 @@ CVS code -
 	  current_x to current_x_save, only turn the mark off and call
 	  edit_refresh() if the mark was originally on, and make
 	  length_change a ssize_t. (DLR)
+	- If the mark is on when we start, skip over all matches not
+	  found inside the marked text.  This makes marked spell
+	  checking when using the internal spell checker work as
+	  expected (found by Rocco Corsi), and also allows replacing
+	  only marked text when the mark is on (suggested by Joseph
+	  Birthisel). (DLR)
   findnextstr()
 	- Take the no_sameline parameter after can_display_wrap and
 	  wholewords, not after all other parameters. (DLR)
diff --git a/TODO b/TODO
index d8169416..8ea816f6 100644
--- a/TODO
+++ b/TODO
@@ -10,7 +10,8 @@ For version 1.4:
 - Rebindable keys?
 - Keystroke to implement "Add next sequence as raw" like vi's ^V.
   [DONE for edit window, needs to be done for statusbar prompt]
-- Spell check selected text only. [DONE]
+- Spell check selected text only. [DONE for internal spell checker,
+  partially done for external spell checker]
 - Make "To Line" (^W^T) and "Read from Command" (^R^X) reenter their
   parent menu when their keystroke is entered a second time (^W^T^T and
   (^R^X^X) (requires figuring out when to keep cursor position and when
diff --git a/src/proto.h b/src/proto.h
index a4061761..864feb19 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -417,8 +417,8 @@ void replace_abort(void);
 int replace_regexp(char *string, bool create_flag);
 #endif
 char *replace_line(const char *needle);
-int do_replace_loop(const char *needle, const filestruct *real_current,
-	size_t *real_current_x, bool wholewords);
+int do_replace_loop(const char *needle, filestruct *real_current, size_t
+	*real_current_x, bool wholewords);
 void do_replace(void);
 void do_gotoline(int line, bool save_pos);
 void do_gotoline_void(void);
diff --git a/src/search.c b/src/search.c
index 57613f7c..b8e33048 100644
--- a/src/search.c
+++ b/src/search.c
@@ -610,8 +610,8 @@ 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. */
-int do_replace_loop(const char *needle, const filestruct *real_current,
-	size_t *real_current_x, bool wholewords)
+int do_replace_loop(const char *needle, filestruct *real_current, size_t
+	*real_current_x, bool wholewords)
 {
     int numreplaced = -1;
     size_t old_pww = placewewant, current_x_save = *real_current_x;
@@ -623,8 +623,13 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
 #endif
 #ifndef NANO_SMALL
     bool old_mark_set = ISSET(MARK_ISSET);
+    const filestruct *top, *bot;
+    size_t top_x, bot_x;
 
     if (old_mark_set) {
+	/* Save the locations where the mark begins and ends. */
+	mark_order(&top, &top_x, &bot, &bot_x);
+
 	UNSET(MARK_ISSET);
 	edit_refresh();
     }
@@ -643,7 +648,25 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
 	, current_save, current_x_save, needle)) {
 
 	int i = 0;
-	size_t match_len;
+	size_t match_len =
+#ifdef HAVE_REGEX_H
+		ISSET(USE_REGEXP) ?
+		regmatches[0].rm_eo - regmatches[0].rm_so :
+#endif
+		strlen(needle);
+
+#ifndef NANO_SMALL
+	/* If we've found a match outside the marked text, skip over it
+	 * and search for another one. */
+	if (old_mark_set) {
+	    if (current->lineno < top->lineno
+		|| current->lineno > bot->lineno
+		|| (current == top && current_x < top_x)
+		|| (current == bot && (current_x > bot_x ||
+		current_x + match_len > bot_x)))
+		continue;
+	}
+#endif
 
 #ifdef HAVE_REGEX_H
 	/* If the bol_or_eol flag is set, we've found a match on the
@@ -668,13 +691,6 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
 	    old_pww = placewewant;
 	}
 
-#ifdef HAVE_REGEX_H
-	if (ISSET(USE_REGEXP))
-	    match_len = regmatches[0].rm_eo - regmatches[0].rm_so;
-	else
-#endif
-	    match_len = strlen(needle);
-
 	/* Record for the return value that we found the search string. */
 	if (numreplaced == -1)
 	    numreplaced = 0;
@@ -734,6 +750,22 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
 		*real_current_x += length_change;
 	    }
 
+#ifndef NANO_SMALL
+	    /* Since the locations where the mark begins and ends may
+	     * have changed, keep our saved locations in sync with
+	     * them. */
+	    if (old_mark_set) {
+		filestruct *old_current = current;
+		size_t old_current_x = current_x;
+
+		current = real_current;
+		current_x = *real_current_x;
+		mark_order(&top, &top_x, &bot, &bot_x);
+		current = old_current;
+		current_x = old_current_x;
+	    }
+#endif
+
 	    /* Set the cursor at the last character of the replacement
 	     * text, so searching will resume after the replacement
 	     * text.  Note that current_x might be set to -1 here. */
-- 
GitLab