Modified the behavior of SelectCopy() so that it surveys cell

instance names in both the selection and in the root edit CellDef,
and then wipes duplicate names from the selection and regenerates
unique IDs.  This avoids the unexpected behavior displayed by
magic in which a "copy" function renames the *original* instance
and gives the original name to the copied instance.  This is not
only unexpected, but causes an error in which "undo" after
multiple copies fails to remove earlier copies because the name
change was not recorded, and the instance can no longer be found
by name.
This commit is contained in:
R. Timothy Edwards 2025-03-26 14:45:46 -04:00
parent 705b4da105
commit dde7144966
4 changed files with 56 additions and 2 deletions

View File

@ -1 +1 @@
8.3.522
8.3.523

View File

@ -2380,6 +2380,50 @@ DBGenerateUniqueIds(def, warn)
HashKill(&dbUniqueNameTable);
}
/*
* ----------------------------------------------------------------------------
*
* DBSelectionUniqueIds --
*
* This is similar to DBGenerateUniqueIds(), but the purpose is to make
* sure that cell IDs in the selection do not collide with IDs in the
* definition. This is done before copying from Select2Def back to the
* root edit CellDef. Otherwise, any copied cell takes the name of the
* original, and the original gets renamed, which is unexpected behavior.
* Called only from SelectCopy().
*
* Results:
* None.
*
* Side effects:
* May modify the use-id's of the cells in the cell plane of 'selDef'.
*
* ----------------------------------------------------------------------------
*/
void
DBSelectionUniqueIds(selDef, rootDef)
CellDef *selDef; /* Should be Select2Def */
CellDef *rootDef; /* Should be EditRootDef */
{
int dbFindNamesFunc();
int dbGenerateUniqueIdsFunc();
dbWarnUniqueIds = FALSE;
HashInit(&dbUniqueDefTable, 32, 1); /* Indexed by (CellDef *) */
HashInit(&dbUniqueNameTable, 32, 0); /* Indexed by use-id */
/* Build up tables of names */
DBCellEnum(rootDef, dbFindNamesFunc, (ClientData) rootDef);
DBCellEnum(selDef, dbFindNamesFunc, (ClientData) selDef);
/* Assign unique use-ids to all cells in the selection */
DBCellEnum(selDef, dbGenerateUniqueIdsFunc, (ClientData) selDef);
HashKill(&dbUniqueDefTable);
HashKill(&dbUniqueNameTable);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -983,6 +983,7 @@ extern int DBScaleCell();
extern TileType DBTechNameTypes();
extern void DBTreeFindUse();
extern void DBGenerateUniqueIds();
extern void DBSelectionUniqueIds();
extern TileType DBInvTransformDiagonal();
extern bool DBIsSubcircuit();
extern int DBSrPaintNMArea();

View File

@ -311,9 +311,18 @@ SelectCopy(transform)
(void) DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_NO_LOCK, Select2Use,
(Rect *) NULL);
(void) DBCellCopyAllCells(&scx, CU_DESCEND_NO_LOCK, Select2Use, (Rect *) NULL);
/* The selection now has the same instance names as the cell def. If
* copies are made, then there will be name conflicts, and the original
* instance may be the one renamed. The sensible thing to do is to make
* sure that all conflicts are resolved within the select CellDef before
* the copy is made.
*/
DBSelectionUniqueIds(Select2Def, EditRootDef);
DBReComputeBbox(Select2Def);
UndoEnable();
SelectClear();
SelectAndCopy2(EditRootDef);
}