Reworked the way that magic displays measurement values (both linear

and area) so that they are consistent across commands.  The default
behavior remains the same, for backwards compatibility.  However, a
new "units" command has been added, so that "units microns" results
in measurements always being displayed in microns, with choice of
that or "internal", "lambda", or "grid".  The units themselves may
be printed (for interactive use) or not (for scripted use).  The
use of "units" is independent of "snap", after overriding the
default behavior, so that units parsed on the command line are
interpreted according to "units", not to "snap".
This commit is contained in:
R. Timothy Edwards
2026-01-24 16:19:12 -05:00
parent 8822f8dce2
commit 81436b75ed
17 changed files with 894 additions and 234 deletions
+97 -49
View File
@@ -338,14 +338,17 @@ CmdArray(
case ARRAY_WIDTH:
if (locargc == 2)
{
char *xsepvalue;
for (la = lahead; la != NULL; la = la->ar_next)
{
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_NewStringObj(xsepvalue, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@@ -355,7 +358,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
TxPrintf("x separation %s\n", xsepvalue);
#ifdef MAGIC_WRAPPER
}
#endif
@@ -374,14 +377,17 @@ CmdArray(
case ARRAY_HEIGHT:
if (locargc == 2)
{
char *ysepvalue;
for (la = lahead; la != NULL; la = la->ar_next)
{
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_NewStringObj(ysepvalue, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@@ -391,7 +397,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
TxPrintf("y separation %s\n", ysepvalue);
#ifdef MAGIC_WRAPPER
}
#endif
@@ -410,16 +416,21 @@ CmdArray(
case ARRAY_PITCH:
if (locargc == 2)
{
char *xpitch, *ypitch;
for (la = lahead; la != NULL; la = la->ar_next)
{
xpitch = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
ypitch = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_NewStringObj(xpitch, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_NewStringObj(ypitch, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@@ -429,8 +440,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
TxPrintf("x separation %s ", xpitch);
TxPrintf("y separation %s\n", ypitch);
#ifdef MAGIC_WRAPPER
}
#endif
@@ -450,16 +461,21 @@ CmdArray(
case ARRAY_POSITION:
if (locargc == 2)
{
char *xpos, *ypos;
for (la = lahead; la != NULL; la = la->ar_next)
{
xpos = DBWPrintValue(la->cellUse->cu_bbox.r_xbot,
w, TRUE);
ypos = DBWPrintValue(la->cellUse->cu_bbox.r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
Tcl_NewStringObj(xpos, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
Tcl_NewStringObj(ypos, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@@ -469,8 +485,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
TxPrintf("x=%s ", xpos);
TxPrintf("y=%s\n", ypos);
#ifdef MAGIC_WRAPPER
}
#endif
@@ -874,13 +890,16 @@ CmdBox(
TxRebuildCommand(cmd);
return;
}
else if (DBWSnapToGrid != DBW_SNAP_USER)
else if (DBWUnits != DBW_UNITS_USER)
{
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
distancey = distancex;
}
else
{
/* For user units, the distance may be different in the X and Y
* directions for a given value.
*/
switch (direction)
{
case GEO_EAST: case GEO_WEST:
@@ -908,15 +927,14 @@ CmdBox(
case BOX_WIDTH:
if (argc == 2)
{
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
w, TRUE);
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_xtop - boxptr->r_xbot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
#else
TxPrintf("%s box width is %d\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xtop - boxptr->r_xbot);
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root",
boxvalues);
#endif
return;
}
@@ -928,15 +946,14 @@ CmdBox(
case BOX_HEIGHT:
if (argc == 2)
{
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_ytop - boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
#else
TxPrintf("%s box height is %d\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_ytop - boxptr->r_ybot);
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root",
boxvalues);
#endif
return;
}
@@ -949,16 +966,24 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d",
boxptr->r_xtop - boxptr->r_xbot,
boxptr->r_ytop - boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluex, *boxvaluey;
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
w, TRUE);
boxvaluey = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box size is %d x %d\n",
TxPrintf("%s box size is %s x %s\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xtop - boxptr->r_xbot,
boxptr->r_ytop - boxptr->r_ybot);
boxvaluex, boxvaluey);
#endif
return;
}
@@ -973,14 +998,22 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d",
boxptr->r_xbot, boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluex, *boxvaluey;
boxvaluex = DBWPrintValue(boxptr->r_xbot, w, TRUE);
boxvaluey = DBWPrintValue(boxptr->r_ybot, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box lower-left corner at (%d, %d)\n",
TxPrintf("%s box lower-left corner at (%s, %s)\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xbot, boxptr->r_ybot);
boxvaluex, boxvaluey);
#endif
return;
}
@@ -1012,16 +1045,31 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d %d %d",
boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluellx, *boxvaluelly;
char *boxvalueurx, *boxvalueury;
boxvaluellx = DBWPrintValue(boxptr->r_xbot, w, TRUE);
boxvaluelly = DBWPrintValue(boxptr->r_ybot, w, FALSE);
boxvalueurx = DBWPrintValue(boxptr->r_xtop, w, TRUE);
boxvalueury = DBWPrintValue(boxptr->r_ytop, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluellx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluelly, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueurx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueury, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury);
#endif
return;
}
+9 -8
View File
@@ -1122,12 +1122,13 @@ CmdExtract(
}
else if (argc == 2)
{
char *halodisp;
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
Tcl_SetObjResult(magicinterp, tobj);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
#else
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
TxPrintf("Side overlap halo is %s\n", halodisp);
#endif
return;
}
@@ -1152,12 +1153,12 @@ CmdExtract(
}
else if (argc == 2)
{
char *stepdisp;
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
Tcl_SetObjResult(magicinterp, tobj);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
#else
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
TxPrintf("Extraction step size is %s\n", stepdisp);
#endif
return;
}
+50 -36
View File
@@ -1084,25 +1084,33 @@ CmdSelect(
*/
case SEL_BBOX:
{
char *selllx, *sellly, *selurx, *selury;
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
selllx = DBWPrintValue(selarea.r_xbot, w, TRUE);
sellly = DBWPrintValue(selarea.r_ybot, w, FALSE);
selurx = DBWPrintValue(selarea.r_xtop, w, TRUE);
selury = DBWPrintValue(selarea.r_ytop, w, FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_xbot));
Tcl_NewStringObj(selllx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_ybot));
Tcl_NewStringObj(sellly, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_xtop));
Tcl_NewStringObj(selurx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_ytop));
Tcl_NewStringObj(selury, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Select bounding box: %d %d %d %d\n",
selarea.r_xbot, selarea.r_ybot,
selarea.r_xtop, selarea.r_ytop);
TxPrintf("Select bounding box: %s %s %s %s\n",
selllx, sellly, selurx, selury);
#endif
return;
}
/*--------------------------------------------------------------------
* Make a copy of the selection at its present loction but do not
@@ -1985,23 +1993,25 @@ cmdLabelRectFunc(
if (rect == NULL)
{
char *labllx, *lablly, *laburx, *labury;
/* Note: Ideally, the MagWindow pointer should be passed to this function */
labllx = DBWPrintValue(label->lab_rect.r_xbot, (MagWindow *)NULL, TRUE);
lablly = DBWPrintValue(label->lab_rect.r_ybot, (MagWindow *)NULL, FALSE);
laburx = DBWPrintValue(label->lab_rect.r_xtop, (MagWindow *)NULL, TRUE);
labury = DBWPrintValue(label->lab_rect.r_ytop, (MagWindow *)NULL, FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_GetObjResult(magicinterp);
pobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_xbot));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_ybot));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_xtop));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_ytop));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labllx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(lablly, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laburx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labury, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%d %d %d %d\n",
label->lab_rect.r_xbot, label->lab_rect.r_ybot,
label->lab_rect.r_xtop, label->lab_rect.r_ytop);
TxPrintf("%s %s %s %s\n", labllx, lablly, laburx,labury);
#endif
}
else if (!GEO_SAMERECT(label->lab_rect, *rect))
@@ -2317,11 +2327,13 @@ CmdSetLabel(
{
if (locargc == 2)
{
char *labsize;
labsize = DBWPrintValue(DefaultLabel->lab_size, w, FALSE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp,
Tcl_NewIntObj(DefaultLabel->lab_size));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(labsize, -1));
#else
TxPrintf("%d\n", DefaultLabel->lab_size);
TxPrintf("%s\n", labsize);
#endif
}
else
@@ -2360,16 +2372,20 @@ CmdSetLabel(
{
if (locargc == 2)
{
char *laboffx, *laboffy;
laboffx = DBWPrintValue(DefaultLabel->lab_offset.p_x, w,
TRUE);
laboffy = DBWPrintValue(DefaultLabel->lab_offset.p_y, w,
FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(DefaultLabel->lab_offset.p_x));
Tcl_NewStringObj(laboffx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(DefaultLabel->lab_offset.p_y));
Tcl_NewStringObj(laboffy, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%d %d\n", DefaultLabel->lab_offset.p_x,
DefaultLabel->lab_offset.p_y);
TxPrintf("%s %s\n", laboffx, laboffy);
#endif
}
else
@@ -2887,13 +2903,13 @@ CmdSnap(
switch (n)
{
case SNAP_OFF: case SNAP_INTERNAL:
DBWSnapToGrid = DBW_SNAP_INTERNAL;
DBWSnapToGrid = DBW_UNITS_INTERNAL;
return;
case SNAP_LAMBDA:
DBWSnapToGrid = DBW_SNAP_LAMBDA;
DBWSnapToGrid = DBW_UNITS_LAMBDA;
return;
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
DBWSnapToGrid = DBW_SNAP_USER;
DBWSnapToGrid = DBW_UNITS_USER;
return;
}
@@ -2901,21 +2917,19 @@ printit:
if (n == SNAP_LIST) /* list */
#ifdef MAGIC_WRAPPER
Tcl_SetResult(magicinterp,
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"),
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"),
TCL_VOLATILE);
#else
TxPrintf("%s\n", (DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
TxPrintf("%s\n", (DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
#endif
else
TxPrintf("Box is aligned to %s grid\n",
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
}
/*
* ----------------------------------------------------------------------------
*
+19 -5
View File
@@ -109,7 +109,7 @@ cmdScaleCoord(
{
char *endptr;
double dval = 0;
int mscale = 1;
int mscale = 1, curunits;
DBWclientRec *crec;
if (*arg == '{') arg++;
@@ -125,8 +125,18 @@ cmdScaleCoord(
return 0;
}
else if ((*endptr == 'l')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
/* Original behavior was to accept un-suffixed values according to the
* "snap" setting. This behavior remains in effect until the "units"
* command is used, in which case units follow the selected units
* value indepedendently of the snap setting.
*/
if (DBWUnits == DBW_UNITS_DEFAULT)
curunits = DBWSnapToGrid;
else
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
if ((*endptr == 'l')
|| ((*endptr == '\0') && (curunits == DBW_UNITS_LAMBDA)))
{
/* lambda or default units */
dval *= (double)DBLambda[1];
@@ -134,13 +144,13 @@ cmdScaleCoord(
return round(dval);
}
else if ((*endptr == 'i')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
|| ((*endptr == '\0') && (curunits == DBW_UNITS_INTERNAL)))
{
/* internal units */
return round(dval);
}
else if ((*endptr == 'g')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
|| ((*endptr == '\0') && (curunits == DBW_UNITS_USER)))
{
/* grid units */
if (w == (MagWindow *)NULL)
@@ -166,6 +176,10 @@ cmdScaleCoord(
}
return round(dval);
}
else if (*endptr == '\0' && (curunits == DBW_UNITS_MICRONS))
{
mscale = 1000;
}
else
{
/* natural units referred to the current cifoutput style */
+202 -13
View File
@@ -455,15 +455,18 @@ CmdTech(
}
if (!strncmp(cmd->tx_argv[2], "width", 5))
{
char *techwidth;
tresult = DRCGetDefaultLayerWidth(t1);
techwidth = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techwidth, -1));
#else
TxPrintf("Minimum width is %d\n", tresult);
TxPrintf("Minimum width is %s\n", techwidth);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
{
char *techspace;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@@ -475,14 +478,16 @@ CmdTech(
else
t2 = t1;
tresult = DRCGetDefaultLayerSpacing(t1, t2);
techspace = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techspace, -1));
#else
TxPrintf("Minimum spacing is %d\n", tresult);
TxPrintf("Minimum spacing is %s\n", techspace);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
{
char *techsurround;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@@ -498,14 +503,17 @@ CmdTech(
}
tresult = DRCGetDefaultLayerSurround(t1, t2);
techsurround = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techsurround, -1));
#else
TxPrintf("Minimum surround is %d\n", tresult);
TxPrintf("Minimum surround is %s\n", techsurround);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
{
char *techdirec;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@@ -521,10 +529,11 @@ CmdTech(
}
tresult = DRCGetDirectionalLayerSurround(t1, t2);
techdirec = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techdirec, -1));
#else
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
TxPrintf("Minimum surround (in one orientation) is %s\n", techdirec);
#endif
}
}
@@ -754,6 +763,182 @@ cmdUnexpandFunc(
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* CmdUnits --
*
* Implement the "units" command.
*
* Usage:
* units [value] [print|noprint]
*
* where "value" may be one of "default", "internal", "lambda",
* "user" (equivalently "grid"), or "microns".
*
* Results:
* None.
*
* Side effects:
* The global variable DBWUnits may be changed, which changes the
* behavior of magic when interpreting un-suffixed values or
* displaying values.
*
* Notes:
* The units behavior was previously dependent on what command was
* issued, with results usually being given in internal units, and
* with un-suffixed values following the snap behavior. Backwards-
* compatible behavior is used on startup or at any time by setting
* the units to "default". Otherwise, unit display follows the
* given "units" setting.
*
* ----------------------------------------------------------------------------
*/
#define UNITS_DEFAULT 0
#define UNITS_INTERNAL 1
#define UNITS_LAMBDA 2
#define UNITS_GRID 3
#define UNITS_USER 4
#define UNITS_MICRONS 5
#define UNITS_LIST 6
#define UNITS_PRINT 7
#define UNITS_NOPRINT 8
void
CmdUnits(
MagWindow *w,
TxCommand *cmd)
{
static const char * const names[] = { "default", "internal", "lambda",
"grid", "user", "microns", "list", "print", "noprint", 0 };
int idx, n = UNITS_LIST, n2, saveflag;
DBWclientRec *crec;
if (cmd->tx_argc >= 2)
{
n = Lookup(cmd->tx_argv[1], names);
if (n < 0)
{
TxPrintf("Usage: units [default | internal | lambda | microns"
" | user] [print]\n");
return;
}
if (DBWUnits != DBW_UNITS_DEFAULT)
saveflag = DBWUnits & DBW_UNITS_PRINT_FLAG;
else
saveflag = -1;
switch (n)
{
case UNITS_DEFAULT:
DBWUnits = DBW_UNITS_DEFAULT;
break;
case UNITS_INTERNAL:
DBWUnits = DBW_UNITS_INTERNAL;
break;
case UNITS_LAMBDA:
DBWUnits = DBW_UNITS_LAMBDA;
break;
case UNITS_USER:
case UNITS_GRID:
DBWUnits = DBW_UNITS_USER;
break;
case UNITS_MICRONS:
DBWUnits = DBW_UNITS_MICRONS;
break;
case UNITS_PRINT:
saveflag = DBW_UNITS_PRINT_FLAG;
break;
case UNITS_NOPRINT:
saveflag = 0;
break;
}
if (n < 0)
{
TxError("Unrecognized units option %s\n.", cmd->tx_argv[1]);
return;
}
if (n != UNITS_LIST)
{
if ((cmd->tx_argc == 3) && (n != UNITS_DEFAULT))
{
n2 = Lookup(cmd->tx_argv[2], names);
switch (n2)
{
case UNITS_PRINT:
DBWUnits |= DBW_UNITS_PRINT_FLAG;
break;
case UNITS_NOPRINT:
DBWUnits &= DBW_UNITS_TYPE_MASK;
break;
default:
TxError("Unrecognized units option %s\n.", cmd->tx_argv[2]);
break;
}
}
else if ((n != UNITS_DEFAULT) && (saveflag != -1))
{
/* Preserve the previous value of the print/noprint flag */
DBWUnits &= DBW_UNITS_TYPE_MASK;
DBWUnits |= saveflag;
}
return;
}
}
if (DBWUnits == DBW_UNITS_DEFAULT)
idx = UNITS_DEFAULT;
else
switch (DBWUnits & DBW_UNITS_TYPE_MASK)
{
case DBW_UNITS_INTERNAL:
idx = UNITS_INTERNAL;
break;
case DBW_UNITS_LAMBDA:
idx = UNITS_LAMBDA;
break;
case DBW_UNITS_USER:
idx = UNITS_USER;
break;
case DBW_UNITS_MICRONS:
idx = UNITS_MICRONS;
break;
}
if (n == UNITS_LIST) /* list */
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj((char *)names[idx], -1));
if (idx != UNITS_DEFAULT)
{
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj("print", 5));
else
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj("noprint", 7));
}
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s", names[idx]);
if (idx != UNITS_DEFAULT)
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
TxPrintf(" print");
TxPrintf("\n");
#endif
}
else if (idx == UNITS_DEFAULT)
TxPrintf("Reported units follow the snap setting.\n");
else if (DBWUnits & DBW_UNITS_PRINT_FLAG)
TxPrintf("Values are reported as %s, along with the units.\n", names[idx]);
else
TxPrintf("Values are reported as %s\n", names[idx]);
}
/*
* ----------------------------------------------------------------------------
*
@@ -1696,18 +1881,20 @@ CmdWire(
case VALUES:
if (locargc == 2)
{
char *wdisp;
width = WireGetWidth();
type = WireGetType();
wdisp = DBWPrintValue(width, w, TRUE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(width));
Tcl_NewStringObj(wdisp, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Wire layer %s, width %d\n",
DBTypeLongNameTbl[type], width);
TxPrintf("Wire layer %s, width %s\n",
DBTypeLongNameTbl[type], wdisp);
#endif
}
break;
@@ -1732,12 +1919,14 @@ CmdWire(
case WIDTH:
if (locargc == 2)
{
char *wdisp;
width = WireGetWidth();
wdisp = DBWPrintValue(width, w, TRUE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewIntObj(width);
lobj = Tcl_NewStringObj(wdisp, -1);
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Wire width is %d\n", width);
TxPrintf("Wire width is %s\n", wdisp);
#endif
}
else if (locargc != 3)