From 5a4c66368283cb03b4cd99acb35edd2399dab5ce Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Wed, 30 Sep 2015 14:02:31 -0400 Subject: [PATCH] Eeschema: fix infinite loop in replace all caused by previous find fix. * Only check for search cache update on close dialog event instead of every update of the find/replace view which caused an infinite loop when replace all was called. * Check for dirty search cache for each find/replace event. * Add code to save and restore last replace index on cache refresh. --- eeschema/find.cpp | 53 ++++++++++++++++++++++++++++----------- eeschema/sch_collectors.h | 10 ++++++-- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/eeschema/find.cpp b/eeschema/find.cpp index 59ce3783ad..fc7aeb45bf 100644 --- a/eeschema/find.cpp +++ b/eeschema/find.cpp @@ -321,6 +321,20 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) { if( m_foundItems.GetCount() == 0 ) return; + + // Refresh the search cache in case something has changed. This prevents any stale + // pointers from crashing Eeschema when the wxEVT_FIND_CLOSE event is handled. + if( IsSearchCacheObsolete( searchCriteria ) ) + { + if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 ) + { + m_foundItems.Collect( searchCriteria, m_CurrentSheet ); + } + else + { + m_foundItems.Collect( searchCriteria ); + } + } } else if( IsSearchCacheObsolete( searchCriteria ) ) { @@ -349,10 +363,32 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent ) { + static int nextFoundIndex = 0; SCH_ITEM* item; SCH_SHEET_PATH* sheet; SCH_SHEET_LIST schematic; SCH_FIND_COLLECTOR_DATA data; + SCH_FIND_REPLACE_DATA searchCriteria; + + searchCriteria.SetFlags( aEvent.GetFlags() ); + searchCriteria.SetFindString( aEvent.GetFindString() ); + searchCriteria.SetReplaceString( aEvent.GetReplaceString() ); + + if( IsSearchCacheObsolete( searchCriteria ) ) + { + if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 ) + { + m_foundItems.Collect( searchCriteria, m_CurrentSheet ); + } + else + { + m_foundItems.Collect( searchCriteria ); + } + + // Restore the next found index on cache refresh. Prevents single replace events + // from starting back at the beginning of the cache. + m_foundItems.SetFoundIndex( nextFoundIndex ); + } if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL ) { @@ -385,7 +421,7 @@ void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent ) } else { - SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data ); + item = (SCH_ITEM*) m_foundItems.GetItem( data ); wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) ); @@ -408,6 +444,7 @@ void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent ) } m_foundItems.IncrementIndex(); + nextFoundIndex = m_foundItems.GetFoundIndex(); } // End the replace if we are at the end if the list. This prevents an infinite loop if @@ -430,20 +467,6 @@ void SCH_EDIT_FRAME::updateFindReplaceView( wxFindDialogEvent& aEvent ) searchCriteria.SetFindString( aEvent.GetFindString() ); searchCriteria.SetReplaceString( aEvent.GetReplaceString() ); - // Refresh the search cache in case something has changed. This prevents any stale - // pointers. - if( IsSearchCacheObsolete( searchCriteria ) ) - { - if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 ) - { - m_foundItems.Collect( searchCriteria, m_CurrentSheet ); - } - else - { - m_foundItems.Collect( searchCriteria ); - } - } - if( m_foundItems.GetItem( data ) != NULL ) { wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() ); diff --git a/eeschema/sch_collectors.h b/eeschema/sch_collectors.h index e427a17808..a564521491 100644 --- a/eeschema/sch_collectors.h +++ b/eeschema/sch_collectors.h @@ -272,8 +272,14 @@ public: void SetForceSearch( bool doSearch = true ) { m_forceSearch = doSearch; } - int GetLibHash() const { return m_lib_hash; } - void SetLibHash( int aHash ) { m_lib_hash = aHash; } + int GetLibHash() const { return m_lib_hash; } + void SetLibHash( int aHash ) { m_lib_hash = aHash; } + + int GetFoundIndex() const { return m_foundIndex; } + void SetFoundIndex( int aIndex ) + { + m_foundIndex = ( (unsigned) aIndex < m_data.size() ) ? aIndex : 0; + } /** * Function PassedEnd