I like the Sertac idea of removing parenthesized strings and finding the string after that. Here is a sample code, extended by searching for whole words and case sensitivity:
function ContainsWord(const AText, AWord: string; AWholeWord: Boolean = True; ACaseSensitive: Boolean = False): Boolean; var S: string; BracketEnd: Integer; BracketStart: Integer; SearchOptions: TStringSearchOptions; begin S := AText; BracketEnd := Pos(']', S); BracketStart := Pos('[', S); while (BracketStart > 0) and (BracketEnd > 0) do begin Delete(S, BracketStart, BracketEnd - BracketStart + 1); BracketEnd := Pos(']', S); BracketStart := Pos('[', S); end; SearchOptions := [soDown]; if AWholeWord then Include(SearchOptions, soWholeWord); if ACaseSensitive then Include(SearchOptions, soMatchCase); Result := Assigned(SearchBuf(PChar(S), StrLen(PChar(S)), 0, 0, AWord, SearchOptions)); end;
Here is an optimized version of a function that uses iteration of a char pointer without string manipulation. Compared to the previous version, this handles the case when you have a line with a missing closing bracket, for example, My [favorite color is . Such a string evaluates to True because of this missing bracket.
The principle is to go through the whole string char to char, and when you find the open bracket, see if this bracket has a closing pair for itself. If yes, then check if the substring is from the saved position until the opening bracket contains the search word. If yes, exit the function. If not, move the saved position to the closing bracket. If the opening bracket does not have its own closing pair, find the word from the saved position to the end of the entire line and exit the function.
For a commented version of this code, follow this link .
function ContainsWord(const AText, AWord: string; AWholeWord: Boolean = True; ACaseSensitive: Boolean = False): Boolean; var CurrChr: PChar; TokenChr: PChar; TokenLen: Integer; SubstrChr: PChar; SubstrLen: Integer; SearchOptions: TStringSearchOptions; begin Result := False; if (Length(AText) = 0) or (Length(AWord) = 0) then Exit; SearchOptions := [soDown]; if AWholeWord then Include(SearchOptions, soWholeWord); if ACaseSensitive then Include(SearchOptions, soMatchCase); CurrChr := PChar(AText); SubstrChr := CurrChr; SubstrLen := 0; while CurrChr^ <> #0 do begin if CurrChr^ = '[' then begin TokenChr := CurrChr; TokenLen := 0; while (TokenChr^ <> #0) and (TokenChr^ <> ']') do begin Inc(TokenChr); Inc(TokenLen); end; if TokenChr^ = #0 then SubstrLen := SubstrLen + TokenLen; Result := Assigned(SearchBuf(SubstrChr, SubstrLen, 0, 0, AWord, SearchOptions)); if Result or (TokenChr^ = #0) then Exit; CurrChr := TokenChr; SubstrChr := CurrChr; SubstrLen := 0; end else begin Inc(CurrChr); Inc(SubstrLen); end; end; Result := Assigned(SearchBuf(SubstrChr, SubstrLen, 0, 0, AWord, SearchOptions)); end;