Corrected the cell delete routine to include removing any elements
related to that cell (since elements are usually temporary and so kept in a separate list, not in the cell). Corrected a major error in the bplane implementation that failed to remove a cell use from the child def's parent list when deleting the use. Can cause magic to go into an infinite loop, especially after selecting and unselecting cells.
This commit is contained in:
parent
028612b70a
commit
fa60cbaaf0
|
|
@ -40,6 +40,7 @@
|
|||
#include "utils/utils.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "database/database.h"
|
||||
#include "textio/textio.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "bplane/bplaneInt.h"
|
||||
|
||||
|
|
@ -180,6 +181,11 @@ void BPDelete(BPlane *bp, void *element)
|
|||
Element *e = element;
|
||||
|
||||
ASSERT(e,"BPDelete");
|
||||
if (bp->bp_count == 0)
|
||||
{
|
||||
TxError("Error: Attempt to delete instance from empty cell!\n");
|
||||
return;
|
||||
}
|
||||
bp->bp_count--;
|
||||
|
||||
/* if element was on edge of bbox, bbox may no longer
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ dbInstanceUnplace(CellUse *use)
|
|||
* or else we could leave the subcell tile plane in a weird
|
||||
* state.
|
||||
*/
|
||||
|
||||
BPDelete(use->cu_parent->cd_cellPlane, use);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "tiles/tile.h"
|
||||
#include "database/database.h"
|
||||
#include "database/databaseInt.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/signals.h"
|
||||
|
||||
/* Forward declarations */
|
||||
|
|
@ -214,6 +215,9 @@ DBCellClearDef(cellDef)
|
|||
/* Remove all defined properties */
|
||||
DBPropClearAll(cellDef);
|
||||
|
||||
/* Remove any elements associated with the cell */
|
||||
DBWElementClearDef(cellDef);
|
||||
|
||||
SigEnableInterrupts();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -811,7 +811,7 @@ DBClearCellPlane(def)
|
|||
/* Do not use BPDelete() inside a BPEnum loop. Use DBSrCellUses */
|
||||
/* to get a linked list of cell instances, then remove each one. */
|
||||
|
||||
DBSrCellUses(def, dbDeleteCellUse, (ClientData)NULL);
|
||||
DBSrCellUses(def, dbDeleteCellUse, (ClientData)def);
|
||||
|
||||
SigEnableInterrupts();
|
||||
}
|
||||
|
|
@ -829,9 +829,32 @@ DBClearCellPlane(def)
|
|||
|
||||
int dbDeleteCellUse(CellUse *use, ClientData arg)
|
||||
{
|
||||
CellDef *def = (CellDef *)arg;
|
||||
CellUse *defuses, *lastuse;
|
||||
|
||||
dbInstanceUnplace(use);
|
||||
|
||||
if (UndoIsEnabled())
|
||||
DBUndoCellUse(use, UNDO_CELL_DELETE);
|
||||
|
||||
/* Remove use from cd_parents of the use's def */
|
||||
lastuse = (CellUse *)NULL;
|
||||
for (defuses = use->cu_def->cd_parents; defuses ; defuses = defuses->cu_nextuse)
|
||||
{
|
||||
if (defuses == use)
|
||||
{
|
||||
if (lastuse)
|
||||
lastuse->cu_nextuse = defuses->cu_nextuse;
|
||||
else
|
||||
use->cu_def->cd_parents = defuses->cu_nextuse;
|
||||
defuses->cu_nextuse = (CellUse *)NULL;
|
||||
break;
|
||||
}
|
||||
lastuse = defuses;
|
||||
}
|
||||
if (use->cu_id) freeMagic(use->cu_id);
|
||||
freeMagic(use);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1239,3 +1239,46 @@ DBWElementPos(MagWindow *w, char *ename, Rect *crect)
|
|||
elem->rootDef->cd_flags |= CDMODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBWElementClearDef --
|
||||
*
|
||||
* Removes all elements associated with the given CellDef.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Elements are removed from the element hash.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DBWElementClearDef(cellDef)
|
||||
CellDef *cellDef;
|
||||
{
|
||||
DBWElement *elem;
|
||||
HashEntry *entry;
|
||||
styleptr stylePtr;
|
||||
HashSearch hs;
|
||||
|
||||
HashStartSearch(&hs);
|
||||
while ((entry = HashNext(&elementTable, &hs)) != NULL)
|
||||
{
|
||||
elem = (DBWElement *) HashGetValue(entry);
|
||||
if (!elem) continue;
|
||||
if (elem->rootDef != cellDef) continue;
|
||||
|
||||
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
|
||||
freeMagic(stylePtr);
|
||||
|
||||
if (elem->type == ELEMENT_TEXT)
|
||||
freeMagic(elem->text);
|
||||
|
||||
HashSetValue(entry, NULL);
|
||||
freeMagic(elem);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ extern void DBWElementAddText();
|
|||
extern void DBWElementDelete();
|
||||
extern void DBWElementNames();
|
||||
extern void DBWElementInbox();
|
||||
extern void DBWElementClearDef();
|
||||
extern void DBWElementParseFlags();
|
||||
extern char *DBWPrintElements();
|
||||
extern void DBWScaleElements();
|
||||
|
|
|
|||
Loading…
Reference in New Issue