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.
This commit is contained in:
R. Timothy Edwards 2026-02-19 11:40:46 -05:00
parent 751757a02c
commit a5fe69cc8f
8 changed files with 91 additions and 30 deletions

View File

@ -53,6 +53,7 @@ int calmaNonManhattan;
int CalmaFlattenLimit = 10;
int NameConvertErrors = 0;
bool CalmaRewound = FALSE;
bool CalmaRecordPaths = FALSE;
TileTypeBitMask *CalmaMaskHints = NULL;
extern HashTable calmaDefInitHash;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
/*

View File

@ -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

View File

@ -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)
{

View File

@ -182,6 +182,13 @@ Read GDSII input or generate GDSII output.
than to subsplit the internal grid to such a fine value.
The "<B>cif limit</B>" function may also be used to limit
grid subdivision to a minimum value.
<DT> <B>savepaths</B> [<B>yes</B>|<B>no</B>]
<DD> When reading paths from a GDS file, record the centerline of
the path as a property in the cell. The default behavior is
<B>no</B>. If no argument is given, then return the status
of the <B>savepaths</B> option. The first path property is
named "<TT>path</TT>", followed by "<TT>path_0</TT>" and
increasing the suffix index for each individual path read.
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
<DD> When reading a GDS file, this option forces magic to rename
cell definitions in the database when a cell of the same name

View File

@ -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]