Loading pcbnew/board_undo_redo.cpp +67 −25 Original line number Diff line number Diff line Loading @@ -84,41 +84,75 @@ BOARD_ITEM* DuplicateStruct( BOARD_ITEM* aItem ); * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This function avoids a Pcbnew crash * Before using this function to test existence of items, * it must be called with aItem = NULL to prepare the list * @param aPcb = board to test * @param aItem = item to find * = NULL to build the list of existing items */ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) { static std::vector<BOARD_ITEM*> itemsList; if( aItem == NULL ) // Build list { // Count items to store in itemsList: int icnt = 0; BOARD_ITEM* item; // search in tracks: // Count tracks: for( item = aPcb->m_Track; item != NULL; item = item->Next() ) icnt++; // Count modules: for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) icnt++; // Count drawings for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) icnt++; // Count zones outlines icnt += aPcb->GetAreaCount(); // Count zones segm (now obsolete): for( item = aPcb->m_Zone; item != NULL; item = item->Next() ) icnt++; // Build candidate list: itemsList.clear(); itemsList.reserve(icnt); // Store items in list: // Append tracks: for( item = aPcb->m_Track; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // search in modules: // Append modules: for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Search in drawings // Append drawings for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Search in zones outlines // Append zones outlines for( int ii = 0; ii < aPcb->GetAreaCount(); ii++ ) if( aPcb->GetArea( ii ) == aItem ) return true; itemsList.push_back( aPcb->GetArea( ii ) ); // search in zones segm: // Append zones segm: for( item = aPcb->m_Zone; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Sort list std::sort( itemsList.begin(), itemsList.end() ); return false; } // search in list: return std::binary_search( itemsList.begin(), itemsList.end(), aItem ); } /** * Function SwapData Loading Loading @@ -504,11 +538,19 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed // Undo in the reverse order of list creation: (this can allow stacked changes // like the same item can be changes and deleted in the same complex command TestForExistingItem( GetBoard(), NULL ); // Build list of existing items, for integrity test for( int ii = aList->GetCount()-1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); #if 1 /* Test for existence of item on board. * It could be deleted, and no more on board: * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This test avoids a Pcbnew crash */ if( aList->GetPickedItemStatus( ii ) != UR_DELETED ) { if( !TestForExistingItem( GetBoard(), item ) ) Loading @@ -516,12 +558,12 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed // Remove this non existant item aList->RemovePicker( ii ); ii++; // the current item was removed, ii points now the next item // whe must decrement it because it will be incremented // decrement it because it will be incremented later not_found = true; continue; } } #endif item->m_Flags = 0; // see if we must rebuild ratsnets and pointers lists Loading Loading
pcbnew/board_undo_redo.cpp +67 −25 Original line number Diff line number Diff line Loading @@ -84,41 +84,75 @@ BOARD_ITEM* DuplicateStruct( BOARD_ITEM* aItem ); * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This function avoids a Pcbnew crash * Before using this function to test existence of items, * it must be called with aItem = NULL to prepare the list * @param aPcb = board to test * @param aItem = item to find * = NULL to build the list of existing items */ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) { static std::vector<BOARD_ITEM*> itemsList; if( aItem == NULL ) // Build list { // Count items to store in itemsList: int icnt = 0; BOARD_ITEM* item; // search in tracks: // Count tracks: for( item = aPcb->m_Track; item != NULL; item = item->Next() ) icnt++; // Count modules: for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) icnt++; // Count drawings for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) icnt++; // Count zones outlines icnt += aPcb->GetAreaCount(); // Count zones segm (now obsolete): for( item = aPcb->m_Zone; item != NULL; item = item->Next() ) icnt++; // Build candidate list: itemsList.clear(); itemsList.reserve(icnt); // Store items in list: // Append tracks: for( item = aPcb->m_Track; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // search in modules: // Append modules: for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Search in drawings // Append drawings for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Search in zones outlines // Append zones outlines for( int ii = 0; ii < aPcb->GetAreaCount(); ii++ ) if( aPcb->GetArea( ii ) == aItem ) return true; itemsList.push_back( aPcb->GetArea( ii ) ); // search in zones segm: // Append zones segm: for( item = aPcb->m_Zone; item != NULL; item = item->Next() ) if( item == aItem ) return true; itemsList.push_back( item ); // Sort list std::sort( itemsList.begin(), itemsList.end() ); return false; } // search in list: return std::binary_search( itemsList.begin(), itemsList.end(), aItem ); } /** * Function SwapData Loading Loading @@ -504,11 +538,19 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed // Undo in the reverse order of list creation: (this can allow stacked changes // like the same item can be changes and deleted in the same complex command TestForExistingItem( GetBoard(), NULL ); // Build list of existing items, for integrity test for( int ii = aList->GetCount()-1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); #if 1 /* Test for existence of item on board. * It could be deleted, and no more on board: * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This test avoids a Pcbnew crash */ if( aList->GetPickedItemStatus( ii ) != UR_DELETED ) { if( !TestForExistingItem( GetBoard(), item ) ) Loading @@ -516,12 +558,12 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed // Remove this non existant item aList->RemovePicker( ii ); ii++; // the current item was removed, ii points now the next item // whe must decrement it because it will be incremented // decrement it because it will be incremented later not_found = true; continue; } } #endif item->m_Flags = 0; // see if we must rebuild ratsnets and pointers lists Loading