diff --git a/src/proto.h b/src/proto.h
index 6eaafeb92cfe1c209bcd7acca1d65e60aa008292..0712942669efb6709d8666dacd388aec2e3933e8 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 dce899683378a80da5063b131babee5655c6a1de..6f4f3e0359ecff3407aba6be0d41bc581cb5b810 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 7f1d8c9be21dd49baaf14f5f362b73a2e7a9e20c..d3ae76ccc6106652b0227e3f7235f208f4c0b527 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;
 }