Here's how to find a substring into a text, forward and backward, with Case Sensitive and Match Whole Word options (the main function is RichEditFind). If bMatchCase is false, it changes the text case to lower so that we can find a case insensitive match (if it is true, it doesn't alter the text). If bWholeWord is true, it is trying to find a match for which the previous and the next characters are separators. Separators are any characters that are not alphanumerical letters (a-z, A-Z, 0-9). If bWholeWord is false, the previous and next characters are ignored (can be alphanumerical). nPosition specifies the start position for finding a substring in the text. When bReverse is false, CString's Find function is used to find a substring in the text, otherwise the ReverseFind function is used (because the CString class can only search characters in a string).
BOOL IsSeparator(CString strRichEdit, CString strFindText, int nPosition)
{
int lenSub = strFindText.GetLength();
int len = strRichEdit.GetLength();
int nPrevChar = nPosition - 1;
int nNextChar = nPosition + lenSub;
if (nPosition > 0)
{
if ((strRichEdit.GetAt(nPrevChar) >= _T('A')) &&
(strRichEdit.GetAt(nPrevChar) <= _T('Z')))
{
return FALSE;
}
if ((strRichEdit.GetAt(nPrevChar) >= _T('a')) &&
(strRichEdit.GetAt(nPrevChar) <= _T('z')))
{
return FALSE;
}
if ((strRichEdit.GetAt(nPrevChar) >= _T('0')) &&
(strRichEdit.GetAt(nPrevChar) <= _T('9')))
{
return FALSE;
}
}
if (nNextChar < len)
{
if ((strRichEdit.GetAt(nNextChar) >= _T('A')) &&
(strRichEdit.GetAt(nNextChar) <= _T('Z')))
{
return FALSE;
}
if ((strRichEdit.GetAt(nNextChar) >= _T('a')) &&
(strRichEdit.GetAt(nNextChar) <= _T('z')))
{
return FALSE;
}
if ((strRichEdit.GetAt(nNextChar) >= _T('0')) &&
(strRichEdit.GetAt(nNextChar) <= _T('9')))
{
return FALSE;
}
}
return TRUE; }
int ReverseFind(LPCTSTR lpszData, LPCTSTR lpszSub, int startpos)
{
int lenSub = lstrlen( lpszSub );
int len = lstrlen( lpszData );
if (0 < lenSub && 0 < len)
{
if (startpos == -1 || startpos >= len) startpos = len - 1;
for (LPCTSTR lpszReverse = lpszData + startpos;
lpszReverse != lpszData; --lpszReverse)
if (_tcsncmp(lpszSub, lpszReverse, lenSub ) == 0)
return (lpszReverse - lpszData);
}
return -1;
}
int RichEditFind(CString strRichEdit, CString strFindText,
int nPosition, BOOL bReverse, BOOL bMatchCase, BOOL bWholeWord)
{
if (nPosition < 0)
nPosition = strRichEdit.GetLength() - 1;
if (bReverse) {
if (bMatchCase) {
if (bWholeWord) {
int nRetVal = ReverseFind(strRichEdit, strFindText, nPosition);
while (nRetVal != -1)
{
if (IsSeparator(strRichEdit, strFindText, nRetVal))
return nRetVal;
nRetVal = ReverseFind(strRichEdit, strFindText, --nRetVal);
}
}
else
{
return ReverseFind(strRichEdit, strFindText, nPosition);
}
}
else
{
strRichEdit.MakeLower();
strFindText.MakeLower();
if (bWholeWord) {
int nRetVal = ReverseFind(strRichEdit, strFindText, nPosition);
while (nRetVal != -1)
{
if (IsSeparator(strRichEdit, strFindText, nRetVal))
return nRetVal;
nRetVal = ReverseFind(strRichEdit, strFindText, --nRetVal);
}
}
else
{
return ReverseFind(strRichEdit, strFindText, nPosition);
}
}
}
else {
if (bMatchCase) {
if (bWholeWord) {
int nRetVal = strRichEdit.Find(strFindText, nPosition);
while (nRetVal != -1)
{
if (IsSeparator(strRichEdit, strFindText, nRetVal))
return nRetVal;
nRetVal = strRichEdit.Find(strFindText, ++nRetVal);
}
}
else
{
return strRichEdit.Find(strFindText, nPosition);
}
}
else
{
strRichEdit.MakeLower();
strFindText.MakeLower();
if (bWholeWord) {
int nRetVal = strRichEdit.Find(strFindText, nPosition);
while (nRetVal != -1)
{
if (IsSeparator(strRichEdit, strFindText, nRetVal))
return nRetVal;
nRetVal = strRichEdit.Find(strFindText, ++nRetVal);
}
}
else
{
return strRichEdit.Find(strFindText, nPosition);
}
}
}
return -1;
}