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;
}