From: David Lawrence Ramsey Date: Thu, 21 Oct 2004 15:32:11 +0000 (+0000) Subject: fix infinite loop when we're doing a replace of marked text and the only X-Git-Tag: v1.3.5~116 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=9819ed031b4602f26f0de43f13db21c8f82e26ec;p=nano.git fix infinite loop when we're doing a replace of marked text and the only matches found are outside the marked text git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2004 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/ChangeLog b/ChangeLog index 273e6b53..7771c656 100644 --- 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 diff --git a/src/nano.c b/src/nano.c index 0567c2f3..62414cac 100644 --- a/src/nano.c +++ b/src/nano.c @@ -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(); diff --git a/src/proto.h b/src/proto.h index 3c28bc95..1449be89 100644 --- a/src/proto.h +++ b/src/proto.h @@ -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); diff --git a/src/search.c b/src/search.c index 627d9069..6ab859f4 100644 --- a/src/search.c +++ b/src/search.c @@ -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++;