From 4a0ad456270b27f5ed7924fd80eb00fa1e5281cb Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 20 Mar 2020 13:40:16 -0400 Subject: [PATCH 1/3] Added a "move" command option "move origin" which will move the coordinate system origin to the specified (current) location. This is a much more efficient method than selecting everything in a layout and moving it, especially for very large layouts where selection and moving becomes prohibitive. --- VERSION | 2 +- commands/CmdCD.c | 8 -- commands/CmdLQ.c | 68 ++++++++-- database/DBcellsrch.c | 288 +++++++++++++++++++++++++++++++++++++++++- database/DBio.c | 7 + windows/windView.c | 41 ++++++ 6 files changed, 388 insertions(+), 26 deletions(-) diff --git a/VERSION b/VERSION index 5bcff72f..ff0ca913 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.198 +8.2.199 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index dc817c6f..86a258c5 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3714,14 +3714,6 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) if ((clen > 4) && !strcmp(cellnameptr + clen - 4, ".mag")) *(cellnameptr + clen - 4) = '\0'; - /* However, if this is a full path, then the full path name must have .mag */ - if (fullpathname != NULL) - { - clen = strlen(fullpathname); - if ((clen <= 4) || strcmp(fullpathname + clen - 4, ".mag")) - strcat(cellnameptr, ".mag"); - } - /* Check for illegal characters in the cellname */ if (CmdIllegalChars(cellnameptr, "", "Cell name")) { diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 8427fb8d..53f7b928 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -480,8 +480,8 @@ keepGoing(use, clientdata) * Implement the "move" command. * * Usage: - * move [direction [amount]] - * move to x y + * move [origin] [direction [amount]] + * move [origin] to x y * * Results: * None. @@ -502,12 +502,13 @@ CmdMove(w, cmd) Point rootPoint, editPoint; CellDef *rootDef; int argpos; + bool doOrigin = FALSE; if (cmd->tx_argc > 4) { badUsage: - TxError("Usage: %s [direction [amount]]\n", cmd->tx_argv[0]); - TxError(" or: %s to x y\n", cmd->tx_argv[0]); + TxError("Usage: %s [origin] [direction [amount]]\n", cmd->tx_argv[0]); + TxError(" or: %s [origin] to x y\n", cmd->tx_argv[0]); return; } @@ -518,18 +519,26 @@ CmdMove(w, cmd) if (!ToolGetEditBox((Rect *)NULL)) return; - if (strcmp(cmd->tx_argv[1], "to") == 0) + argpos = 1; + + if (strcmp(cmd->tx_argv[1], "origin") == 0) + { + doOrigin = TRUE; + argpos++; + } + + if (strcmp(cmd->tx_argv[argpos], "to") == 0) { if (cmd->tx_argc != 4) goto badUsage; - editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE); - editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE); + editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[argpos + 1], FALSE, TRUE); + editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[argpos + 2], FALSE, FALSE); GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint); goto moveToPoint; } - indx = GeoNameToPos(cmd->tx_argv[1], FALSE, FALSE); - argpos = (indx < 0) ? 1 : 2; + indx = GeoNameToPos(cmd->tx_argv[argpos], FALSE, FALSE); + if (indx >= 0) argpos++; if (cmd->tx_argc >= 3) { @@ -605,8 +614,9 @@ CmdMove(w, cmd) * but is retained for backward compatibility. */ - if (ToolGetBox(&rootDef, &rootBox) && ((rootDef == SelectRootDef) - || (SelectRootDef == NULL))) + if (ToolGetBox(&rootDef, &rootBox) && + ((rootDef == SelectRootDef) || (SelectRootDef == NULL)) + && (doOrigin == FALSE)) { GeoTransRect(&t, &rootBox, &newBox); DBWSetBox(rootDef, &newBox); @@ -640,11 +650,41 @@ moveToPoint: } GeoTransTranslate(rootPoint.p_x - rootBox.r_xbot, rootPoint.p_y - rootBox.r_ybot, &GeoIdentityTransform, &t); - GeoTransRect(&t, &rootBox, &newBox); - DBWSetBox(rootDef, &newBox); + if (doOrigin == FALSE) + { + GeoTransRect(&t, &rootBox, &newBox); + DBWSetBox(rootDef, &newBox); + } } - SelectTransform(&t); + if (doOrigin) + { + DBMoveCell(rootDef, t.t_c, t.t_f); + + /* Adjust box to maintain relative position */ + + if (ToolGetBox(&rootDef, &rootBox) && + ((rootDef == SelectRootDef) || (SelectRootDef == NULL))) + { + t.t_c = -t.t_c; + t.t_f = -t.t_f; + GeoTransRect(&t, &rootBox, &newBox); + DBWSetBox(rootDef, &newBox); + t.t_c = -t.t_c; + t.t_f = -t.t_f; + } + + /* Adjust all window viewing positions and redraw */ + + WindTranslate(t.t_c, t.t_f); + + /* This is harsh. Might work to change all distance measures */ + /* in the undo record, but this is simple and direct. */ + + UndoFlush(); + } + else + SelectTransform(&t); } /* diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index d3eaa667..7e65fdbc 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -1386,6 +1386,42 @@ typedef struct LCU1 /* A linked celluse record */ struct LCU1 *cu_next; /* Pointer to another linked celluse record */ } LinkedCellUse; +/* + * ---------------------------------------------------------------------------- + * + * DBMovePoint --- + * + * Move a point by a position (origx, origy). Ignore positions which + * are marked as (M)INFINITY. + * + * Results: + * TRUE if the point was moved (point position was not infinite) + * + * Side effects: + * Point structure pointed to by the first argument is repositioned. + * + * ---------------------------------------------------------------------------- + */ + +bool +DBMovePoint(p, origx, origy) + Point *p; + int origx, origy; +{ + int result = FALSE; + if ((p->p_x < (INFINITY - 2)) && (p->p_x > (MINFINITY + 2))) + { + p->p_x -= origx; + result = TRUE; + } + if ((p->p_y < (INFINITY + 2)) && (p->p_y > (MINFINITY + 2))) + { + p->p_y -= origy; + result = TRUE; + } + return result; +} + /* * ---------------------------------------------------------------------------- * @@ -1538,6 +1574,14 @@ struct scaleArg { bool modified; }; +struct moveArg { + int origx; + int origy; + int pnum; + Plane *ptarget; + bool modified; +}; + /* * ---------------------------------------------------------------------------- * @@ -1619,6 +1663,74 @@ dbTileScaleFunc(tile, scvals) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * dbMovePlane -- + * + * Relocation procedure called on a single plane. Copies paint into the + * new plane at a delta position (-origx, -origy) + * + * ---------------------------------------------------------------------------- + */ + +bool +dbMovePlane(oldplane, newplane, pnum, origx, origy) + Plane *oldplane, *newplane; + int pnum; + int origx, origy; +{ + int dbTileMoveFunc(); /* forward declaration */ + struct moveArg arg; + + arg.origx = origx; + arg.origy = origy; + arg.ptarget = newplane; + arg.pnum = pnum; + arg.modified = FALSE; + (void) DBSrPaintArea((Tile *) NULL, oldplane, &TiPlaneRect, + &DBAllButSpaceBits, dbTileMoveFunc, (ClientData) &arg); + + return arg.modified; +} + +/* + * ---------------------------------------------------------------------------- + * + * dbTileMoveFunc -- + * + * Repositioning procedure called on each tile being copied from one plane + * to another. Delta position (-origx, -origy) is stored inside the struct + * moveArg before calling. + * + * ---------------------------------------------------------------------------- + */ + +int +dbTileMoveFunc(tile, mvvals) + Tile *tile; + struct moveArg *mvvals; +{ + TileType type; + Rect targetRect; + TileType exact; + + TiToRect(tile, &targetRect); + + mvvals->modified = TRUE; + DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy); + DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy); + + type = TiGetTypeExact(tile); + exact = type; + if (IsSplit(tile)) + type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + DBNMPaintPlane(mvvals->ptarget, exact, &targetRect, + DBStdPaintTbl(type, mvvals->pnum), + (PaintUndoInfo *)NULL); + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -1804,9 +1916,6 @@ dbScaleCell(cellDef, scalen, scaled) cellDef->cd_planes[pNum] = newplane; } - /* Check consistency of several global pointers */ - /* WARNING: This list may not be complete! */ - /* Also scale the position of all labels. */ /* If labels are the rendered-font type, scale the size as well */ @@ -1949,3 +2058,176 @@ dbCellUseEnumFunc(cellUse, arg) return 0; } + +/* + * ---------------------------------------------------------------------------- + * + * DBMoveCell -- + * + * Reposition a cell to a different origin. This routine is equivalent to + * unexpanding all contents of a cell, selecting everything, and issuing a + * move command. However, for very large layouts this becomes memory- and + * compute- intensive. The process of reorienting an entire layout to a + * new position can be done much more efficiently. This routine is + * essentially a copy of dbScaleCell() but changes only position and not + * scale. + * + * ---------------------------------------------------------------------------- + */ + +int +DBMoveCell(cellDef, origx, origy) + CellDef *cellDef; /* Pointer to CellDef to be saved. This def might + * be an internal buffer; if so, we ignore it. + */ + int origx, origy; /* Internal unit coordinates which will become the new origin */ +{ + int dbCellTileEnumFunc(), dbCellUseEnumFunc(); + Label *lab; + int pNum; + LinkedTile *lhead, *lt; + LinkedCellUse *luhead, *lu; + Plane *newplane; + + /* Unlike dbScaleCell(), this routine is only run on valid edit defs */ + + cellDef->cd_flags |= CDBOXESCHANGED; + + /* Enumerate all unique cell uses, and move their position in the */ + /* bounding box and transform. */ + + luhead = NULL; + + (void) DBCellEnum(cellDef, dbCellUseEnumFunc, (ClientData) &luhead); + + lu = luhead; + while (lu != NULL) + { + CellUse *use; + Rect *bbox; + + use = lu->cellUse; + bbox = &use->cu_bbox; + + /* TxPrintf("CellUse: BBox is ll (%d, %d), transform [%d %d %d %d %d %d]\n", + bbox->r_xbot, bbox->r_ybot, + use->cu_transform.t_a, use->cu_transform.t_b, use->cu_transform.t_c, + use->cu_transform.t_d, use->cu_transform.t_e, use->cu_transform.t_f); */ + + DBMovePoint(&bbox->r_ll, origx, origy); + DBMovePoint(&bbox->r_ur, origx, origy); + + bbox = &use->cu_extended; + DBMovePoint(&bbox->r_ll, origx, origy); + DBMovePoint(&bbox->r_ur, origx, origy); + + use->cu_transform.t_c -= origx; + use->cu_transform.t_f -= origy; + + lu = lu->cu_next; + } + + /* Free this linked cellUse structure */ + lu = luhead; + while (lu != NULL) + { + freeMagic((char *)lu); + lu = lu->cu_next; + } + + /* Move the position of all subcell uses. Count all of the tiles in the */ + /* subcell plane, and move those without reference to the actual cells (so */ + /* we don't count the cells multiple times). */ + + lhead = NULL; + (void) TiSrArea((Tile *)NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect, + dbCellTileEnumFunc, (ClientData) &lhead); + + /* Move each of the tiles in the linked list by (-x, -y) */ + /* Don't move (M)INFINITY on boundary tiles! */ + + lt = lhead; + while (lt != NULL) + { + DBMovePoint(<->tile->ti_ll, origx, origy); + lt = lt->t_next; + } + + /* Free this linked tile structure */ + lt = lhead; + while (lt != NULL) + { + freeMagic((char *)lt); + lt = lt->t_next; + } + + /* Move all of the paint tiles in this cell by creating a new plane */ + /* and copying all tiles into the new plane at the new position. */ + + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + { + if (cellDef->cd_planes[pNum] == NULL) continue; + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + if (dbMovePlane(cellDef->cd_planes[pNum], newplane, pNum, + origx, origy, FALSE)) + cellDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP); + DBFreePaintPlane(cellDef->cd_planes[pNum]); + TiFreePlane(cellDef->cd_planes[pNum]); + cellDef->cd_planes[pNum] = newplane; + } + + /* Also move the position of all labels. */ + + if (cellDef->cd_labels) + { + for (lab = cellDef->cd_labels; lab; lab = lab->lab_next) + { + DBMovePoint(&lab->lab_rect.r_ll, origx, origy); + DBMovePoint(&lab->lab_rect.r_ur, origx, origy); + + if (lab->lab_font >= 0) + { + DBMovePoint(&lab->lab_bbox.r_ll, origx, origy); + DBMovePoint(&lab->lab_bbox.r_ur, origx, origy); + } + } + } + +donecell: + + /* The cellDef bounding box gets moved to match the new position. */ + + DBMovePoint(&cellDef->cd_bbox.r_ll, origx, origy); + DBMovePoint(&cellDef->cd_bbox.r_ur, origx, origy); + DBMovePoint(&cellDef->cd_extended.r_ll, origx, origy); + DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy); + + /* If the cell is an abstract view with a fixed bounding box, then */ + /* adjust the bounding box property to match the new scale. */ + + if ((cellDef->cd_flags & CDFIXEDBBOX) != 0) + { + Rect r; + bool found; + char *propval; + + propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found); + if (found) + { + if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot, + &r.r_xtop, &r.r_ytop) == 4) + { + DBMovePoint(&r.r_ll, origx, origy); + DBMovePoint(&r.r_ur, origx, origy); + + propval = (char *)mallocMagic(40); + sprintf(propval, "%d %d %d %d", r.r_xbot, r.r_ybot, + r.r_xtop, r.r_ytop); + DBPropPut(cellDef, "FIXED_BBOX", propval); + } + } + } + return 0; +} + diff --git a/database/DBio.c b/database/DBio.c index 0b74ef67..77c6ed5b 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -1133,7 +1133,14 @@ dbReadOpen(cellDef, name, setFileName, errptr) cellDef->cd_flags &= ~CDNOTFOUND; #endif if (setFileName) + { + /* Remove any ".mag" file extension */ + char *pptr = strrchr(filename, '.'); + if (pptr != NULL) + if (!strcmp(pptr, DBSuffix)) *pptr = '\0'; + (void) StrDup(&cellDef->cd_file, filename); + } cellDef->cd_flags |= CDAVAILABLE; return (f); } diff --git a/windows/windView.c b/windows/windView.c index eefff34e..eb87d6b9 100644 --- a/windows/windView.c +++ b/windows/windView.c @@ -289,6 +289,47 @@ WindScale(scalen, scaled) } } +/* + * ---------------------------------------------------------------------------- + * + * WindTranslate -- + * + * Move the viewing windows by the given delta position. Because + * this is done in conjunction with repositioning the geometry + * ("move origin" command), we don't preserve the center position + * like WindZoom() does. The net effect is that the image in the + * window doesn't appear to change. + * + * Results: + * None. + * + * Side effects: + * All windows will be now view a different portion of the client's area. + * + * ---------------------------------------------------------------------------- + */ + +void +WindTranslate(origx, origy) + int origx, origy; +{ + extern void DBMovePoint(); + MagWindow *w2; + Rect newArea; + + for (w2 = windTopWindow; w2 != NULL; w2 = w2->w_nextWindow) + { + newArea.r_xbot = w2->w_surfaceArea.r_xbot; + newArea.r_xtop = w2->w_surfaceArea.r_xtop; + newArea.r_ybot = w2->w_surfaceArea.r_ybot; + newArea.r_ytop = w2->w_surfaceArea.r_ytop; + DBMovePoint(&newArea.r_ll, origx, origy); + DBMovePoint(&newArea.r_ur, origx, origy); + WindMove(w2, &newArea); + } +} + + /* * ---------------------------------------------------------------------------- From ad13e48a07253e32e967fa7edae949fc82454bfe Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 20 Mar 2020 14:50:56 -0400 Subject: [PATCH 2/3] Corrected ext2spice for the case where a port has been given more than one name, because in that case one of the port records ends up with a null pointer to a node, and causes a crash condition. This can happen inadvertently, as when a connected node is not specifically designated a port, but is forced to be a port because of the connection. --- ext2spice/ext2hier.c | 2 +- ext2spice/ext2spice.c | 6 +++--- extflat/EFbuild.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index fc010154..64578469 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1619,7 +1619,7 @@ esMakePorts(hc, cdata) nn = (EFNodeName *) HashGetValue(he); } - if (!(nn->efnn_node->efnode_flags & EF_PORT)) + if (nn->efnn_node && !(nn->efnn_node->efnode_flags & EF_PORT)) { nn->efnn_node->efnode_flags |= EF_PORT; nn->efnn_port = -1; // Will be sorted later diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 94b2eb53..221483a6 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1668,7 +1668,7 @@ topVisit(def, doStub) sname = (EFNodeName *) HashGetValue(he); if (sname == NULL) continue; snode = sname->efnn_node; - if (!(snode->efnode_flags & EF_PORT)) continue; + if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue; for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next) { portorder = nodeName->efnn_port; @@ -1729,7 +1729,7 @@ topVisit(def, doStub) if (sname == NULL) continue; /* Should not happen */ snode = sname->efnn_node; - if (!(snode->efnode_flags & EF_PORT)) continue; + if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue; for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next) { @@ -1787,7 +1787,7 @@ topVisit(def, doStub) if (sname == NULL) continue; snode = sname->efnn_node; - if (snode->efnode_flags & EF_SUBS_PORT) + if (snode && (snode->efnode_flags & EF_SUBS_PORT)) { if (snode->efnode_name->efnn_port < 0) { diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index f4ba250b..33e43bc6 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -466,6 +466,8 @@ efBuildEquiv(def, nodeName1, nodeName2) if (efWarn) efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2); efNodeMerge(&nn1->efnn_node, &nn2->efnn_node); + if (nn1->efnn_port > 0) nn2->efnn_port = nn1->efnn_port; + else if (nn2->efnn_port > 0) nn1->efnn_port = nn2->efnn_port; } return; } From a1ee1720f1211e1703f1b7336a2489f6791767e1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 20 Mar 2020 21:29:29 -0400 Subject: [PATCH 3/3] Corrected the "lef write -hide" method to keep a list of the areas of the pin port geometry and using those areas to create the spacing between them and the obstruction layer. Otherwise, the existing method used different databases (source vs. flattened) to find the pin area, and they did not always agree on the exact dimensions, leading to spacing errors within the LEF view. --- lef/lefWrite.c | 64 ++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index af0cbffd..ad1cab85 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -618,6 +618,14 @@ MakeLegalLEFSyntax(text) return rstr; } +/* Linked list structure for holding PIN PORT geometry areas */ + +typedef struct _labelLinkedList { + Label *lll_label; + Rect lll_area; + struct _labelLinkedList *lll_next; +} labelLinkedList; + /* * ---------------------------------------------------------------------------- * @@ -657,6 +665,7 @@ lefWriteMacro(def, f, scale, hide) char *LEFtext; HashSearch hs; HashEntry *he; + labelLinkedList *lll = NULL; extern CellDef *SelectDef; @@ -959,7 +968,11 @@ lefWriteMacro(def, f, scale, hide) if (hide) { - SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE); + Rect carea; + labelLinkedList *newlll; + + SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE); + if (GEO_RECTNULL(&carea)) carea = lab->lab_rect; /* Note that a sticky label could be placed over multiple */ /* tile types, which would cause SelectChunk to fail. So */ @@ -967,8 +980,15 @@ lefWriteMacro(def, f, scale, hide) /* SelectDef. */ pNum = DBPlane(lab->lab_type); - DBPaintPlane(SelectDef->cd_planes[pNum], &lab->lab_rect, + DBPaintPlane(SelectDef->cd_planes[pNum], &carea, DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL); + + /* Remember this area since it's going to get erased */ + newlll = (labelLinkedList *)mallocMagic(sizeof(labelLinkedList)); + newlll->lll_label = lab; + newlll->lll_area = carea; + newlll->lll_next = lll; + lll = newlll; } else SelectNet(&scx, lab->lab_type, 0, NULL, FALSE); @@ -1064,6 +1084,7 @@ lefWriteMacro(def, f, scale, hide) /* cell. Otherwise, this routine can block internal pins. */ Rect layerBound; + labelLinkedList *thislll; for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) if (TTMaskHasType(&lmask, ttype)) @@ -1080,39 +1101,20 @@ lefWriteMacro(def, f, scale, hide) DBPaint(lc.lefYank, &layerBound, ttype); } - scx.scx_use = &lefSourceUse; - for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next) + for (thislll = lll; thislll; thislll = thislll->lll_next) { - Rect carea; int lspace; - labr = lab->lab_rect; + lab = thislll->lll_label; - /* Force label area to be non-degenerate */ - if (labr.r_xbot >= labr.r_xtop) - { - labr.r_xbot--; - labr.r_xtop++; - } - if (labr.r_ybot >= labr.r_ytop) - { - labr.r_ybot--; - labr.r_ytop++; - } - - if (lab->lab_flags & PORT_DIR_MASK) - { - scx.scx_area = labr; - SelectClear(); - SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE); - if (GEO_RECTNULL(&carea)) carea = lab->lab_rect; - lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); - carea.r_xbot -= lspace; - carea.r_ybot -= lspace; - carea.r_xtop += lspace; - carea.r_ytop += lspace; - DBErase(lc.lefYank, &carea, lab->lab_type); - } + lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); + thislll->lll_area.r_xbot -= lspace; + thislll->lll_area.r_ybot -= lspace; + thislll->lll_area.r_xtop += lspace; + thislll->lll_area.r_ytop += lspace; + DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type); + + freeMagic(thislll); } } else