function IsWordChar(ch: WideChar): Boolean;
begin
// Letters and digits are word characters. Include '_' if you want underscore to count as part of words.
Result := TCharacter.IsLetterOrDigit(ch) or (ch = '_');
end;
function PosWholeWordInsensitive(const Sub, S: unicodestring; StartPos: Integer = 1): Integer;
var
i, LSub, LStr: Integer;
Hay, Needle: unicodestring;
beforeOK, afterOK: Boolean;
begin
Result := 0;
if (Sub = '') or (S = '') then Exit;
if StartPos < 1 then StartPos := 1;
LSub := Length(Sub);
LStr := Length(S);
if StartPos > LStr - LSub + 1 then Exit;
// Use Unicode-aware case folding; UpperCase is OK for many RTLs. Replace with proper casefold if available.
Hay := ToUpper(S);
Needle := ToUpper(Sub);
i := StartPos;
while i <= LStr - LSub + 1 do
begin
if Copy(Hay, i, LSub) = Needle then
begin
// check char before match (if any)
if i = 1 then
beforeOK := True
else
beforeOK := not IsWordChar(S[i - 1]);
// check char after match (if any)
if i + LSub - 1 = LStr then
afterOK := True
else
afterOK := not IsWordChar(S[i + LSub]);
if beforeOK and afterOK then
begin
Result := i;
Exit;
end;
end;
Inc(i);
end;
end;
function strSearchReplaceWholeAll(const strText, strToReplace, strReplaceWith : unicodestring) : string;
var
ps : Integer;
a : Integer;
rtn : unicodestring;
txtBefore, txtAfter : unicodestring;
begin
rtn := strText;
if (trim(rtn)<>'') and (trim(strToReplace)<>'') then
begin
try
ps := posWholeWordInsensitive(strToReplace, rtn, ps);
while ps>0 do
begin
txtBefore := Copy(rtn, 1, ps-1);
txtAfter := Copy(rtn, (ps + length(strToReplace)), length(rtn));
if (rtn[ps-1]=#10) then
rtn := #10 + txtBefore + strReplaceWith + txtAfter
else if (rtn[ps-1]=#13) then
rtn := #13 + txtBefore + strReplaceWith + txtAfter
else if (rtn[ps-1]=#13) then
rtn := #13 + txtBefore + strReplaceWith + txtAfter
else if (rtn[ps-1]=#9) then
rtn := #9 + txtBefore + strReplaceWith + txtAfter;
if (rtn[ps+length(strToReplace)]=#10) then
rtn := txtBefore + strReplaceWith + #10 + txtAfter
else if (rtn[ps+length(strToReplace)]=#13) then
rtn := txtBefore + strReplaceWith + #13 + txtAfter
else if (rtn[ps+length(strToReplace)]=#9) then
rtn := txtBefore + strReplaceWith + #9 + txtAfter
else
rtn := txtBefore + strReplaceWith + txtAfter;
ps := ps + length(strReplaceWith);
ps := posWholeWordInsensitive(strToReplace, rtn, ps);
if (ps>=length(rtn)) or (ps<=0) then break;
end;
except
//
end;
end;
result := string(rtn);
end;