diff --git a/src/proto.h b/src/proto.h index 6eaafeb9..07129426 100644 --- a/src/proto.h +++ b/src/proto.h @@ -721,7 +721,7 @@ ssize_t ngetdelim(char **lineptr, size_t *n, int delim, FILE *stream); const char *fixbounds(const char *r); #endif #ifndef DISABLE_SPELLER -bool is_whole_word(size_t pos, const char *buf, const char *word); +bool is_separate_word(size_t position, size_t length, const char *buf); #endif const char *strstrwrapper(const char *haystack, const char *needle, const char *start); diff --git a/src/search.c b/src/search.c index dce89968..6f4f3e03 100644 --- a/src/search.c +++ b/src/search.c @@ -305,10 +305,6 @@ int findnextstr( found = strstrwrapper(fileptr->data, needle, rev_start); if (found != NULL) { -#ifndef DISABLE_SPELLER - bool found_whole = FALSE; - /* Is this potential match a whole word? */ -#endif /* Remember the length of the potential match. */ found_len = #ifdef HAVE_REGEX_H @@ -318,19 +314,13 @@ int findnextstr( strlen(needle); #ifndef DISABLE_SPELLER - /* If we're searching for whole words, see if it is. */ + /* When we're spell checking, a match is only a true match when + * it is a separate word. */ if (whole_word_only) { - char *word = mallocstrncpy(NULL, found, found_len + 1); - word[found_len] = '\0'; - - found_whole = is_whole_word(found - fileptr->data, - fileptr->data, word); - free(word); - } - - /* If we're searching for whole words and this potential - * match isn't a whole word, continue searching. */ - if (!whole_word_only || found_whole) + if (is_separate_word(found - fileptr->data, found_len, + fileptr->data)) + break; + } else #endif break; } diff --git a/src/utils.c b/src/utils.c index 7f1d8c9b..d3ae76cc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -278,27 +278,29 @@ const char *fixbounds(const char *r) #endif /* HAVE_REGEX_H */ #ifndef DISABLE_SPELLER -/* Is the word starting at position pos in buf a whole word? */ -bool is_whole_word(size_t pos, const char *buf, const char *word) +/* Is the word starting at the given position in buf and of the given length + * a separate word? That is: is it not part of a longer word?*/ +bool is_separate_word(size_t position, size_t length, const char *buf) { - char *p = charalloc(mb_cur_max()), *r = charalloc(mb_cur_max()); - size_t word_end = pos + strlen(word); + char *before = charalloc(mb_cur_max()), *after = charalloc(mb_cur_max()); + size_t word_end = position + length; bool retval; - assert(buf != NULL && pos <= strlen(buf) && word != NULL); + assert(buf != NULL && position < strlen(buf) && position + length <= strlen(buf)); - parse_mbchar(buf + move_mbleft(buf, pos), p, NULL); - parse_mbchar(buf + word_end, r, NULL); + /* Get the characters before and after the word, if any. */ + parse_mbchar(buf + move_mbleft(buf, position), before, NULL); + parse_mbchar(buf + word_end, after, NULL); /* If we're at the beginning of the line or the character before the * word isn't a non-punctuation "word" character, and if we're at * the end of the line or the character after the word isn't a * non-punctuation "word" character, we have a whole word. */ - retval = (pos == 0 || !is_word_mbchar(p, FALSE)) && - (word_end == strlen(buf) || !is_word_mbchar(r, FALSE)); + retval = (position == 0 || !is_word_mbchar(before, FALSE)) && + (word_end == strlen(buf) || !is_word_mbchar(after, FALSE)); - free(p); - free(r); + free(before); + free(after); return retval; }