From 95baea1c22777d1cdca3d6befaf7e2376e4d46a2 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Thu, 19 Feb 2026 11:40:46 -0500 Subject: [PATCH] Corrected another place where the property handling had not been converted to the new PropertyRecord type. Since this was in the CIFPropRecordPath() subroutine, which has always been problematic and generally useless, I took the opportunity to make that function dependent on an option set by "gds savepaths true", with the option set to "false" by default, so "path" properties will no longer be created from GDS input unless the option is manually set to "true". Also: Found that the returned boolean from "box exists" is sometimes getting overwritten with a NULL result, causing a spurious Tcl error messages to pop up. I could not find where this overwriting happens (probably in a tag callback), so I just took the hack approach of converting a NULL result to "false", which is always safe to do. --- calma/CalmaRdcl.c | 1 + calma/CalmaRdpt.c | 7 +++++- calma/calma.h | 1 + cif/CIFrdpt.c | 61 +++++++++++++++++++++++++++++++---------------- commands/CmdAB.c | 4 ++-- commands/CmdCD.c | 35 ++++++++++++++++++++++----- doc/html/gds.html | 7 ++++++ tcltk/wrapper.tcl | 5 +++- 8 files changed, 91 insertions(+), 30 deletions(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index cd331a86..b036bd26 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -53,6 +53,7 @@ int calmaNonManhattan; int CalmaFlattenLimit = 10; int NameConvertErrors = 0; bool CalmaRewound = FALSE; +bool CalmaRecordPaths = FALSE; TileTypeBitMask *CalmaMaskHints = NULL; extern HashTable calmaDefInitHash; diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index 4d58ede2..ef0cf396 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -692,7 +692,12 @@ calmaElementPath(void) } } - CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path"); + /* If requested by command option, record the path centerline as a + * property of the cell def. + */ + if (CalmaRecordPaths) + CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path"); + CIFPaintWirePath(pathheadp, width, (pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ? FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL); diff --git a/calma/calma.h b/calma/calma.h index a2730b80..f745e1d6 100644 --- a/calma/calma.h +++ b/calma/calma.h @@ -38,6 +38,7 @@ extern TileTypeBitMask *CalmaMaskHints; extern bool CalmaMergeTiles; extern bool CalmaFlattenArrays; extern bool CalmaNoDRCCheck; +extern bool CalmaRecordPaths; extern bool CalmaFlattenUses; extern int CalmaFlattenLimit; extern float CalmaMagScale; diff --git a/cif/CIFrdpt.c b/cif/CIFrdpt.c index 35adc0b0..dee267d9 100644 --- a/cif/CIFrdpt.c +++ b/cif/CIFrdpt.c @@ -244,40 +244,61 @@ CIFPropRecordPath( { extern float CIFGetOutputScale(int convert); CIFPath *pathp; - char *pathstr, *sptr; - int components; - float x, y, oscale, mult; + char *namestr = NULL; + int components, i, x, y, mult, pathnum; + PropertyRecord *proprec; + bool propfound; - oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */ - if (oscale == 0.0) oscale = 1.0; - mult = (iswire == TRUE) ? 0.5 : 1.0; + /* If "name" is a property, then append a suffix to it to ensure uniqueness */ + DBPropGet(def, propname, &propfound); + if (propfound) + { + pathnum = 0; + namestr = mallocMagic(strlen(propname) + 10); + while (propfound) + { + sprintf(namestr, "%s_%d", propname, pathnum); + DBPropGet(def, namestr, &propfound); + pathnum++; + } + } - pathp = pathheadp; - components = 0; + mult = (iswire == TRUE) ? 1 : 0; /* Count the number of components in the path */ + pathp = pathheadp; + components = 0; while (pathp != NULL) { - pathp = pathp->cifp_next; components++; + pathp = pathp->cifp_next; } - /* Allocate enough space to hold 2 * N points at "infinity" */ - pathstr = (char *)mallocMagic(components * 40); + /* Allocate enough space to hold 2 * N points. */ + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + + ((components - 1) * 2) * sizeof(int)); + proprec->prop_type = PROPERTY_TYPE_DIMENSION; + proprec->prop_len = components * 2; pathp = pathheadp; - sptr = pathstr; + i = 0; while (pathp != NULL) { - x = (float)pathp->cifp_x * oscale * mult; - y = (float)pathp->cifp_y * oscale * mult; - sprintf(sptr, "%.3f %.3f ", x, y); - sptr = sptr + strlen(sptr); + x = pathp->cifp_x >> mult; + y = pathp->cifp_y >> mult; + + proprec->prop_value.prop_integer[i] = x; + proprec->prop_value.prop_integer[i + 1] = y; + + i += 2; pathp = pathp->cifp_next; } - - /* Reallocate pathstr to be no larger than needed to hold the path contents */ - StrDup(&pathstr, pathstr); - DBPropPut(def, propname, (ClientData)pathstr); + if (namestr) + { + DBPropPut(def, namestr, proprec); + freeMagic(namestr); + } + else + DBPropPut(def, propname, proprec); } /* diff --git a/commands/CmdAB.c b/commands/CmdAB.c index 375ac307..472aea1c 100644 --- a/commands/CmdAB.c +++ b/commands/CmdAB.c @@ -779,8 +779,8 @@ CmdBox( break; case BOX_EXISTS: #ifdef MAGIC_WRAPPER - Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0", - NULL); + Tcl_SetObjResult(magicinterp, + Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE)); #else TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False"); #endif diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 7e2ac203..c9315378 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -117,12 +117,13 @@ bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dumm #define CALMA_READ 19 #define CALMA_READONLY 20 #define CALMA_RESCALE 21 -#define CALMA_WARNING 22 -#define CALMA_WRITE 23 -#define CALMA_POLYS 24 -#define CALMA_PATHS 25 -#define CALMA_UNDEFINED 26 -#define CALMA_UNIQUE 27 +#define CALMA_SAVEPATHS 22 +#define CALMA_WARNING 23 +#define CALMA_WRITE 24 +#define CALMA_POLYS 25 +#define CALMA_PATHS 26 +#define CALMA_UNDEFINED 27 +#define CALMA_UNIQUE 28 #define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */ @@ -175,6 +176,7 @@ CmdCalma( " into edit cell", "readonly [yes|no] set cell as read-only and generate output from GDS file", "rescale [yes|no] allow or disallow internal grid subdivision", + "savepaths [yes|no] save path centerlines as cell properties", "warning [option] set warning information level", "write file output Calma GDS-II format to \"file\"\n" " for the window's root cell", @@ -738,6 +740,27 @@ CmdCalma( CalmaSubcellPolygons = (unsigned char)option; return; + case CALMA_SAVEPATHS: + if (cmd->tx_argc == 2) + { +#ifdef MAGIC_WRAPPER + Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaRecordPaths)); +#else + TxPrintf("Paths in GDS cells read from input file are%s recorded" + " as cell properties.\n", + (CalmaRecordPaths) ? " " : " not"); +#endif + return; + } + else if (cmd->tx_argc != 3) + goto wrongNumArgs; + + option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo); + if (option < 0) + goto wrongNumArgs; + CalmaRecordPaths = (option < 4) ? FALSE : TRUE; + return; + case CALMA_NO_DUP: if (cmd->tx_argc == 2) { diff --git a/doc/html/gds.html b/doc/html/gds.html index 3a0de05a..0a259921 100644 --- a/doc/html/gds.html +++ b/doc/html/gds.html @@ -182,6 +182,13 @@ Read GDSII input or generate GDSII output. than to subsplit the internal grid to such a fine value. The "cif limit" function may also be used to limit grid subdivision to a minimum value. +
savepaths [yes|no] +
When reading paths from a GDS file, record the centerline of + the path as a property in the cell. The default behavior is + no. If no argument is given, then return the status + of the savepaths option. The first path property is + named "path", followed by "path_0" and + increasing the suffix index for each individual path read.
unique [yes|no]
When reading a GDS file, this option forces magic to rename cell definitions in the database when a cell of the same name diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index a9d0e82e..db08aa0a 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -684,7 +684,10 @@ proc magic::cursorview {win} { *bypass crosshair ${olstx}um ${olsty}um } - if {[${win} box exists]} { + # I do not know why the T/F result gets lost or overridden sometimes + set gotbox [${win} box exists] + if {$gotbox == {}} {set gotbox false} + if {$gotbox} { set curunits [${win} units list] ${win} units microns noprint set dlst [${win} box position]