]> git.wh0rd.org Git - nano.git/commitdiff
fix infinite loop when we're doing a replace of marked text and the only
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Thu, 21 Oct 2004 15:32:11 +0000 (15:32 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Thu, 21 Oct 2004 15:32:11 +0000 (15:32 +0000)
matches found are outside the marked text

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2004 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
src/nano.c
src/proto.h
src/search.c

index 273e6b53196fbbeb53d170acba62e2f5e88bcc4b..7771c6564efe0f7ce01ca84bd977d3ee086c89c0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -187,9 +187,10 @@ CVS code -
          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 allows replacing
-         only marked text when the mark is on. (DLR, suggested by
-         Joseph Birthisel)
+         found inside the marked text, and break out if the only
+         matches found are outside the marked text.  This allows
+         replacing only marked text when the mark is on. (DLR,
+         suggested by Joseph Birthisel)
        - Return ssize_t instead of int. (DLR)
   findnextstr()
        - Take the no_sameline parameter after can_display_wrap and
@@ -198,8 +199,9 @@ CVS code -
          that smooth scrolling works correctly. (DLR)
        - Fix handling of the wholewords flag so that it works with
          regular expressions and in conjunction with the no_sameline
-         flag, and add a new parameter needle_len to return the length
-         of the match in. (DLR)
+         flag, and add new parameters wrapped (used to return the value
+         of search_last_line) and needle_len (used to return the length
+         of the match). (DLR)
 - utils.c:
   regexp_bol_or_eol()
        - Don't assume any longer that string will be found if
index 0567c2f3d902554d71cec2c998b7fe6c2dfa35ff..62414cac09f42965f5969a33799760630244626a 100644 (file)
@@ -1468,7 +1468,8 @@ bool do_int_spell_fix(const char *word)
     current_x = -1;
 
     /* Find the first whole-word occurrence of word. */
-    while (findnextstr(TRUE, TRUE, FALSE, fileage, 0, word, NULL)) {
+    while (findnextstr(TRUE, TRUE, FALSE, fileage, 0, word, NULL,
+       NULL)) {
        if (is_whole_word(current_x, current->data, word)) {
            edit_refresh();
 
index 3c28bc952dd1f071e9eeb2ff2333677d679e71b2..1449be89e2440d8568aea553d7d87bd2074c9bfd 100644 (file)
@@ -405,7 +405,7 @@ bool is_whole_word(int curr_pos, const char *datastr, const char
        *searchword);
 bool findnextstr(bool can_display_wrap, bool wholeword, bool
        no_sameline, const filestruct *begin, size_t beginx, const char
-       *needle, size_t *needle_len);
+       *needle, bool *wrapped, size_t *needle_len);
 void do_search(void);
 #ifndef NANO_SMALL
 void do_research(void);
index 627d90698e901605a1303a2ec11d6ba60da1c84e..6ab859f441c736dff867d0e56db6a0988eb6f4f2 100644 (file)
@@ -266,13 +266,13 @@ bool is_whole_word(int curr_pos, const char *datastr, const char
 /* Look for needle, starting at current, column 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 beginx.  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, and needle_len isn't NULL, set it to the
- * length of the string we found. */
+ * can_display_wrap is TRUE, we put messages on the statusbar, wrap
+ * around the file boundaries, and set wrapped to TRUE if it isn't NULL.
+ * 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 beginx, const char
-       *needle, size_t *needle_len)
+       *needle, bool *wrapped, size_t *needle_len)
 {
     filestruct *fileptr = current;
     const char *rev_start = NULL, *found = NULL;
@@ -284,6 +284,10 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
     bool search_last_line = FALSE;
        /* Have we gone past the last line while searching? */
 
+    /* wrapped holds the value of search_last_line. */
+    if (wrapped != NULL)
+       *wrapped = FALSE;
+
     /* rev_start might end up 1 character before the start or after the
      * end of the line.  This won't be a problem because strstrwrapper()
      * will return immediately and say that no match was found, and
@@ -374,8 +378,11 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
        }
 
        /* Original start line reached. */
-       if (fileptr == begin)
+       if (fileptr == begin) {
            search_last_line = TRUE;
+           if (wrapped != NULL)
+               *wrapped = TRUE;
+       }
        rev_start = fileptr->data;
 #ifndef NANO_SMALL
        if (ISSET(REVERSE_SEARCH))
@@ -405,6 +412,8 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
     current = fileptr;
     current_x = current_x_find;
     current_y = current_y_find;
+
+    /* needle_len holds the length of needle. */
     if (needle_len != NULL)
        *needle_len = found_len;
 
@@ -452,7 +461,7 @@ void do_search(void)
 #endif
 
     didfind = findnextstr(TRUE, FALSE, FALSE, current, current_x,
-       answer, NULL);
+       answer, NULL, NULL);
 
     /* Check to see if there's only one occurrence of the string and
      * we're on it now. */
@@ -466,7 +475,7 @@ void do_search(void)
        if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
                last_search)) {
            didfind = findnextstr(TRUE, FALSE, TRUE, current, current_x,
-               answer, NULL);
+               answer, NULL, NULL);
            if (fileptr == current && fileptr_x == current_x && !didfind)
                statusbar(_("This is the only occurrence"));
        } else {
@@ -505,7 +514,7 @@ void do_research(void)
 #endif
 
        didfind = findnextstr(TRUE, FALSE, FALSE, current, current_x,
-               last_search, NULL);
+               last_search, NULL, NULL);
 
        /* Check to see if there's only one occurrence of the string and
         * we're on it now. */
@@ -519,7 +528,7 @@ void do_research(void)
            if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
                last_search)) {
                didfind = findnextstr(TRUE, FALSE, TRUE, current,
-                       current_x, answer, NULL);
+                       current_x, answer, NULL, NULL);
                if (fileptr == current && fileptr_x == current_x && !didfind)
                    statusbar(_("This is the only occurrence"));
            } else {
@@ -656,9 +665,10 @@ ssize_t do_replace_loop(const char *needle, filestruct *real_current,
     bool begin_line = FALSE, bol_or_eol = FALSE;
 #endif
 #ifndef NANO_SMALL
-    bool old_mark_set = ISSET(MARK_ISSET);
+    bool old_mark_set = ISSET(MARK_ISSET), wrapped;
     const filestruct *top, *bot;
     size_t top_x, bot_x;
+    int wraps = 0;
 
     if (old_mark_set) {
        /* Save the locations where the mark begins and ends. */
@@ -686,7 +696,16 @@ ssize_t do_replace_loop(const char *needle, filestruct *real_current,
 #else
        FALSE
 #endif
-       , current_save, current_x_save, needle, &match_len)) {
+       , current_save, current_x_save, needle,
+#ifndef NANO_SMALL
+       /* If we're replacing marked text, we should take note of when
+        * the search wraps.  If the wrapped flag is set, it means that
+        * we've wrapped since the last search. */
+       &wrapped
+#else
+       NULL
+#endif
+       , &match_len)) {
 
        int i = 0;
 
@@ -697,8 +716,18 @@ ssize_t do_replace_loop(const char *needle, filestruct *real_current,
            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)))
+               match_len > bot_x))) {
+               /* Keep track of how many times the search has wrapped.
+                * If it's wrapped more than once, it means that the
+                * only matches left are those outside the marked text,
+                * so we're done. */
+               if (wrapped) {
+                   wraps++;
+                   if (wraps > 1)
+                       break;
+               }
                continue;
+           }
        }
 #endif
 
@@ -1056,7 +1085,7 @@ void do_find_bracket(void)
 
     while (TRUE) {
        if (findnextstr(FALSE, FALSE, FALSE, current, current_x,
-               regexp_pat, NULL)) {
+               regexp_pat, NULL, NULL)) {
            /* Found identical bracket. */
            if (current->data[current_x] == ch_under_cursor)
                count++;