search: make a regex with a beginning-of-word anchor work correctly
The search routine begins searching right after the cursor and behaves as if the line starts there, which means that a beginning-of-word anchor (\< or \b) will match there also when in fact the cursor is sitting in the middle of a word. To prevent finding a false match, verify that for a regex that starts with a BOW anchor the found match is actually the start of a word. This fixes https://savannah.gnu.org/bugs/?45630.master
parent
e36e829ad0
commit
cbf7e57ed0
26
src/search.c
26
src/search.c
|
@ -38,6 +38,8 @@ static bool history_changed = FALSE;
|
|||
#ifdef HAVE_REGEX_H
|
||||
static bool regexp_compiled = FALSE;
|
||||
/* Have we compiled any regular expressions? */
|
||||
static bool bow_anchored = FALSE;
|
||||
/* Whether a regex starts with a beginning-of-word anchor. */
|
||||
|
||||
/* Compile the given regular expression and store it in search_regexp.
|
||||
* Return TRUE if the expression is valid, and FALSE otherwise. */
|
||||
|
@ -60,6 +62,10 @@ bool regexp_init(const char *regexp)
|
|||
|
||||
regexp_compiled = TRUE;
|
||||
|
||||
/* Remember whether the regex starts with a beginning-of-word anchor. */
|
||||
bow_anchored = (strncmp(regexp, "\\<", 2) == 0 ||
|
||||
strncmp(regexp, "\\b", 2) == 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -292,8 +298,24 @@ int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
|
|||
if (found != NULL) {
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* When doing a regex search, compute the length of the match. */
|
||||
if (ISSET(USE_REGEXP))
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
found_len = regmatches[0].rm_eo - regmatches[0].rm_so;
|
||||
|
||||
/* If the regex starts with a BOW anchor, check that the found
|
||||
* match actually is the start of a word. If not, continue. */
|
||||
if (bow_anchored && found != fileptr->data) {
|
||||
size_t before = move_mbleft(fileptr->data, found - fileptr->data);
|
||||
|
||||
/* If a word char is before the match, skip this match. */
|
||||
if (is_word_mbchar(fileptr->data + before, FALSE)) {
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
rev_start = fileptr->data + before;
|
||||
else
|
||||
rev_start = found + move_mbright(found, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
/* When we're spell checking, a match is only a true match when
|
||||
|
@ -304,7 +326,7 @@ int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
|
|||
break;
|
||||
else {
|
||||
/* Maybe there is a whole word in the rest of the line. */
|
||||
rev_start = found + 1;
|
||||
rev_start = found + move_mbright(found, 0);
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
|
|
Loading…
Reference in New Issue