Skip to content

Commit

Permalink
Fixed bugs in generic Find routine
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed May 6, 2011
1 parent d33099e commit 9f901d5
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 128 deletions.
201 changes: 82 additions & 119 deletions Finding.cpp
Expand Up @@ -54,7 +54,6 @@ bool NotFound (CFindInfo & FindInfo)
FindInfo.m_bAgain ? " again." : " .");
::UMessageBox (strMsg, MB_ICONINFORMATION);
FindInfo.m_iStartColumn = -1;
FindInfo.m_iLastLineSearched = -1;
FindInfo.m_MatchesOnLine.clear ();
return false;
} // end of NotFound
Expand All @@ -74,8 +73,6 @@ CFindDlg dlg (FindInfo.m_strFindStringList);
if (!FindInfo.m_bAgain || FindInfo.m_strFindStringList.IsEmpty ())
{
FindInfo.m_iStartColumn = -1; // return consistent column number
FindInfo.m_iLastLineSearched = -1;
FindInfo.m_MatchesOnLine.clear ();

if (!FindInfo.m_strFindStringList.IsEmpty ())
dlg.m_strFindText = FindInfo.m_strFindStringList.GetHead ();
Expand Down Expand Up @@ -109,6 +106,7 @@ CFindDlg dlg (FindInfo.m_strFindStringList);
FindInfo.m_nCurrentLine = FindInfo.m_nTotalLines - 1;

FindInfo.m_bAgain = false;
FindInfo.m_MatchesOnLine.clear ();

delete FindInfo.m_regexp; // get rid of earlier regular expression
FindInfo.m_regexp = NULL;
Expand All @@ -118,23 +116,18 @@ CFindDlg dlg (FindInfo.m_strFindStringList);
FindInfo.m_regexp = regcomp (FindInfo.m_strFindStringList.GetHead (),
(FindInfo.m_bMatchCase ? 0 : PCRE_CASELESS) | (FindInfo.m_bUTF8 ? PCRE_UTF8 : 0));

} // end of not repeating the last find
} // end of not starting a new find
else
{
if (FindInfo.m_bRepeatOnSameLine)
FindInfo.m_iStartColumn = FindInfo.m_iEndColumn; // skip previous match
else
FindInfo.m_iStartColumn = -1; // return consistent column number
{ // finding again

// doing a "find again" - step past the line we were on

if (!FindInfo.m_bRepeatOnSameLine)
// this line dealt with? move onto next one
if (FindInfo.m_MatchesOnLine.empty ())
{
if (FindInfo.m_bForwards)
FindInfo.m_nCurrentLine++;
else
FindInfo.m_nCurrentLine--;
} // end of not repeating on same line
}

// re-initiate the search - this will set up the POSITION parameter, if it wants to

Expand All @@ -152,7 +145,7 @@ CFindDlg dlg (FindInfo.m_strFindStringList);
else
FindInfo.m_nCurrentLine = FindInfo.m_nTotalLines - 1;
return NotFound (FindInfo);
}
} // end of if off end of buffewr

// loop until end of text, or text found

Expand Down Expand Up @@ -189,9 +182,42 @@ CString strStatus = TFormat ("Finding: %s", (LPCTSTR) FindInfo.m_strFindStringLi
{
int iMilestone = 0;

while (true)
while (true) // until match
{

// if m_MatchesOnLine is not empty we had a match (last time)
if (!FindInfo.m_MatchesOnLine.empty ())
{
pair<int, int> result;

if (FindInfo.m_bForwards)
{
// get first match
result = FindInfo.m_MatchesOnLine.front ();
// don't want it any more
FindInfo.m_MatchesOnLine.pop_front ();
}
else
{
// get last match
result = FindInfo.m_MatchesOnLine.back ();
// don't want it any more
FindInfo.m_MatchesOnLine.pop_back ();
}

// copy first and last column
FindInfo.m_iStartColumn = result.first;
FindInfo.m_iEndColumn = result.second;

// only want one? throw others away
if (!FindInfo.m_bRepeatOnSameLine)
FindInfo.m_MatchesOnLine.clear ();

// all done!
WrapUpFind (FindInfo);
return true; // found it!
} // end if found

// get the next line, return "not found" if end of text

if ((*pGetNextLine) (pObject, FindInfo, strLine))
Expand All @@ -217,125 +243,62 @@ CString strStatus = TFormat ("Finding: %s", (LPCTSTR) FindInfo.m_strFindStringLi
}
} // end of having a progress control

// if searching backwards, and doing more than one, find all matches on this line
// find all matches on this line

if (!FindInfo.m_bForwards && FindInfo.m_bRepeatOnSameLine)
{

if (FindInfo.m_nCurrentLine != FindInfo.m_iLastLineSearched)
{
FindInfo.m_iLastLineSearched = FindInfo.m_nCurrentLine;
FindInfo.m_MatchesOnLine.clear (); // no matches yet
int iStartCol = 0; // start at start of line
FindInfo.m_MatchesOnLine.clear (); // no matches yet
int iStartCol = 0; // start at start of line

// if case-insensitive search wanted, force this line to lower case
if (!FindInfo.m_bMatchCase && !FindInfo.m_bRegexp )
strLine.MakeLower ();
// if case-insensitive search wanted, force this line to lower case
if (!FindInfo.m_bMatchCase && !FindInfo.m_bRegexp )
strLine.MakeLower ();

// loop until we run out of matches
while (true)
{

if (FindInfo.m_bRegexp )
{
if (regexec (FindInfo.m_regexp, strLine, iStartCol))
{
FindInfo.m_MatchesOnLine.push_back (
pair <int, int> (FindInfo.m_regexp->m_vOffsets [0],
FindInfo.m_regexp->m_vOffsets [1]));
iStartCol = FindInfo.m_regexp->m_vOffsets [1];
if (iStartCol >= strLine.GetLength ())
break;
} // end of regexp matched
else
break; // no match, done searching

} // end regexp
else
{
if ((iStartCol = strLine.Find (strFindString, iStartCol)) != -1)
{
// work out ending column
int iEndCol = iStartCol + strFindString.GetLength ();
FindInfo.m_MatchesOnLine.push_back (pair <int, int> (iStartCol, iEndCol));
iStartCol = iEndCol;
if (iStartCol >= strLine.GetLength ())
break;
} // end of found
else
break; // no match, done searching

} // end not regexp


} // end of while we found something


} // end of different line to last time


// if m_MatchesOnLine is not empty we had a match (either this time or last time)

if (!FindInfo.m_MatchesOnLine.empty ())
{
// get last match
pair<int, int> result = FindInfo.m_MatchesOnLine.back ();
// don't want it any more
FindInfo.m_MatchesOnLine.pop_back ();
// copy first and last column
FindInfo.m_iStartColumn = result.first;
FindInfo.m_iEndColumn = result.second;
// all done!
WrapUpFind (FindInfo);
return true; // found it!
} // end if found

// nothing found, try previous line
FindInfo.m_nCurrentLine--;
continue; // skip other testing

} // end of searching backwards with repeat on same line

// if text found on this line, then we have done it!

if (maximum (FindInfo.m_iStartColumn, 0) < strLine.GetLength ())
// loop until we run out of matches
while (true)
{

if (FindInfo.m_bRegexp )
{

if (regexec (FindInfo.m_regexp, strLine, maximum (FindInfo.m_iStartColumn, 0)))
if (regexec (FindInfo.m_regexp, strLine, iStartCol))
{
// work out what column it must have been at
FindInfo.m_iStartColumn = FindInfo.m_regexp->m_vOffsets [0];
FindInfo.m_iEndColumn = FindInfo.m_regexp->m_vOffsets [1];
WrapUpFind (FindInfo);
return true; // found it!
}
} // end of regular expression
FindInfo.m_MatchesOnLine.push_back (
pair <int, int> (FindInfo.m_regexp->m_vOffsets [0],
FindInfo.m_regexp->m_vOffsets [1]));
iStartCol = FindInfo.m_regexp->m_vOffsets [1];
if (iStartCol >= strLine.GetLength ())
break;
} // end of regexp matched
else
break; // no match, done searching

} // end regexp
else
{ // not regular expression

// if case-insensitive search wanted, force this line to lower case
if (!FindInfo.m_bMatchCase)
strLine.MakeLower ();
if ((FindInfo.m_iStartColumn = strLine.Find (strFindString, maximum (FindInfo.m_iStartColumn, 0))) != -1)
{
if ((iStartCol = strLine.Find (strFindString, iStartCol)) != -1)
{
// work out ending column
FindInfo.m_iEndColumn = FindInfo.m_iStartColumn + strFindString.GetLength ();
WrapUpFind (FindInfo);
return true; // found it!
int iEndCol = iStartCol + strFindString.GetLength ();
FindInfo.m_MatchesOnLine.push_back (pair <int, int> (iStartCol, iEndCol));
iStartCol = iEndCol;
if (iStartCol >= strLine.GetLength ())
break;
} // end of found
} // end of not regular expression
} // end of start column being inside the line
else
break; // no match, done searching

// keep track of line count
} // end not regexp

FindInfo.m_iStartColumn = -1; // back to start for next line
} // end of while we found something

if (FindInfo.m_bForwards)
FindInfo.m_nCurrentLine++;
else
FindInfo.m_nCurrentLine--;

// no saved matches from that line, move onto next one
if (FindInfo.m_MatchesOnLine.empty ())
{
if (FindInfo.m_bForwards)
FindInfo.m_nCurrentLine++;
else
FindInfo.m_nCurrentLine--;
} // end if no matches

} // end of looping through each line

Expand Down
5 changes: 0 additions & 5 deletions doc.cpp
Expand Up @@ -4376,15 +4376,10 @@ long CMUSHclientDoc::GetLastLine (void)
// our "last found" line needs adjusting

m_DisplayFindInfo.m_nCurrentLine -= JUMP_SIZE;
m_DisplayFindInfo.m_iLastLineSearched -= JUMP_SIZE;

// has last found line has disappeared off the front of the buffer?
if (m_DisplayFindInfo.m_nCurrentLine < 0)
{
m_DisplayFindInfo.m_nCurrentLine = 0;
m_DisplayFindInfo.m_iLastLineSearched = -1;
}


} // end of CMUSHclientDoc::RemoveChunk

Expand Down
2 changes: 1 addition & 1 deletion sendvw.cpp
Expand Up @@ -1476,7 +1476,7 @@ CLine * pLine;
POSITION prevpos = NULL;

if (FindInfo.m_pFindPosition == NULL)
return true;
return true; // no more lines

// if doing backwards, we must go back a whole *line* (ie. the one after a hard return)
if (!FindInfo.m_bForwards)
Expand Down
4 changes: 1 addition & 3 deletions stdafx.h
Expand Up @@ -271,7 +271,6 @@ class CFindInfo : public CObject
m_iControlColumns = 0;
m_regexp = NULL;
m_bRepeatOnSameLine = false;
m_iLastLineSearched = -1;
}; // constructor

~CFindInfo () { delete m_regexp; };
Expand All @@ -293,8 +292,7 @@ class CFindInfo : public CObject
t_regexp * m_regexp; // compiled regular expression
CStringList m_strFindStringList; // previous things we found
bool m_bRepeatOnSameLine; // keep trying to match on same line
list<pair<int, int> > m_MatchesOnLine; // list of matches on this line (for reverse searching)
int m_iLastLineSearched; // last line searched to populate m_MatchesOnLine
list<pair<int, int> > m_MatchesOnLine; // list of matches on this line
};

// prototype for "get next line" callback for find routine
Expand Down

0 comments on commit 9f901d5

Please sign in to comment.