From 75f7e803f6f22065923a422a4b78c4a6d4bb0f42 Mon Sep 17 00:00:00 2001 From: Nick Gammon Date: Thu, 11 Nov 2010 15:46:50 +1100 Subject: [PATCH] Implemented find on same line for backwards searches --- Finding.cpp | 95 +++++++++++++++++++++++-- dialogs/world_prefs/genpropertypage.cpp | 2 +- doc.cpp | 6 ++ sendvw.cpp | 4 +- stdafx.h | 3 + 5 files changed, 100 insertions(+), 10 deletions(-) diff --git a/Finding.cpp b/Finding.cpp index 17ee42cc..eea726c0 100644 --- a/Finding.cpp +++ b/Finding.cpp @@ -54,6 +54,8 @@ 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 @@ -72,6 +74,8 @@ 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 (); @@ -118,7 +122,7 @@ CFindDlg dlg (FindInfo.m_strFindStringList); else { if (FindInfo.m_bRepeatOnSameLine) - FindInfo.m_iStartColumn++; // skip previous match + FindInfo.m_iStartColumn = FindInfo.m_iEndColumn; // skip previous match else FindInfo.m_iStartColumn = -1; // return consistent column number @@ -150,10 +154,6 @@ CFindDlg dlg (FindInfo.m_strFindStringList); return NotFound (FindInfo); } - // re-initiate the search - this will set up the POSITION parameter, if it wants to - -// (*pInitiateSearch) (pObject, FindInfo); - // loop until end of text, or text found CString strLine; @@ -217,6 +217,87 @@ 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 + + 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 + + // 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 + else + { + // nothing found, try previous line + FindInfo.m_nCurrentLine--; + continue; // skip other testing + } // end if not found + + } // end of searching backwards with repeat on same line + // if text found on this line, then we have done it! if (FindInfo.m_bRegexp ) @@ -233,14 +314,14 @@ CString strStatus = TFormat ("Finding: %s", (LPCTSTR) FindInfo.m_strFindStringLi } // end of regular expression 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) { // work out ending column - FindInfo.m_iEndColumn = FindInfo.m_iStartColumn + - FindInfo.m_strFindStringList.GetHead ().GetLength (); + FindInfo.m_iEndColumn = FindInfo.m_iStartColumn + strFindString.GetLength (); WrapUpFind (FindInfo); return true; // found it! } // end of found diff --git a/dialogs/world_prefs/genpropertypage.cpp b/dialogs/world_prefs/genpropertypage.cpp index 75f3b7a9..152fb43e 100644 --- a/dialogs/world_prefs/genpropertypage.cpp +++ b/dialogs/world_prefs/genpropertypage.cpp @@ -1058,7 +1058,7 @@ void CGenPropertyPage::LoadList (void) m_cTreeCtrl.DeleteAllItems (); // since all is deleted, we don't have any groups any more - m_GroupsMap.erase (m_GroupsMap.begin (), m_GroupsMap.end ()); + m_GroupsMap.clear (); CString strObjectName; diff --git a/doc.cpp b/doc.cpp index 5a98c083..4cde2854 100644 --- a/doc.cpp +++ b/doc.cpp @@ -4373,9 +4373,15 @@ 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 ba56f57f..1a016af8 100644 --- a/sendvw.cpp +++ b/sendvw.cpp @@ -1362,8 +1362,8 @@ ASSERT_VALID(pDoc); pDoc->m_DisplayFindInfo.m_bAgain = bAgain; -// if finding forwards, we can find multiple instances on the same line -pDoc->m_DisplayFindInfo.m_bRepeatOnSameLine = pDoc->m_DisplayFindInfo.m_bForwards; +// we can find multiple instances on the same line +pDoc->m_DisplayFindInfo.m_bRepeatOnSameLine = true; bool found = FindRoutine (pDoc, // passed back to callback routines pDoc->m_DisplayFindInfo, // finding structure diff --git a/stdafx.h b/stdafx.h index 86429f5a..9c3e561c 100644 --- a/stdafx.h +++ b/stdafx.h @@ -260,6 +260,7 @@ class CFindInfo : public CObject m_iControlColumns = 0; m_regexp = NULL; m_bRepeatOnSameLine = false; + m_iLastLineSearched = -1; }; // constructor ~CFindInfo () { delete m_regexp; }; @@ -281,6 +282,8 @@ 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 }; // prototype for "get next line" callback for find routine