From 9f901d5ea8ea9f1c92971d91b793b98cf838efd4 Mon Sep 17 00:00:00 2001 From: Nick Gammon Date: Fri, 6 May 2011 14:19:07 +1000 Subject: [PATCH] Fixed bugs in generic Find routine --- Finding.cpp | 201 +++++++++++++++++++++------------------------------- doc.cpp | 5 -- sendvw.cpp | 2 +- stdafx.h | 4 +- 4 files changed, 84 insertions(+), 128 deletions(-) diff --git a/Finding.cpp b/Finding.cpp index a0840eba..9e89d25c 100644 --- a/Finding.cpp +++ b/Finding.cpp @@ -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 @@ -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 (); @@ -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; @@ -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 @@ -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 @@ -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 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)) @@ -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 (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 (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 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 (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 (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 diff --git a/doc.cpp b/doc.cpp index c13aac0e..3d7adee7 100644 --- a/doc.cpp +++ b/doc.cpp @@ -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 diff --git a/sendvw.cpp b/sendvw.cpp index 1a016af8..3ea83268 100644 --- a/sendvw.cpp +++ b/sendvw.cpp @@ -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) diff --git a/stdafx.h b/stdafx.h index 8477c8fa..fcc97ff6 100644 --- a/stdafx.h +++ b/stdafx.h @@ -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; }; @@ -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 > m_MatchesOnLine; // list of matches on this line (for reverse searching) - int m_iLastLineSearched; // last line searched to populate m_MatchesOnLine + list > m_MatchesOnLine; // list of matches on this line }; // prototype for "get next line" callback for find routine