Compare commits
11 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
67c6ed9395 | |
|
|
f15f0dabbb | |
|
|
ae6d26578e | |
|
|
cb1653b157 | |
|
|
a3f5e665d1 | |
|
|
2eea849c06 | |
|
|
6e295d030e | |
|
|
ceba050a21 | |
|
|
f7cceed5e3 | |
|
|
5d35ae38b5 | |
|
|
05561b90f3 |
|
|
@ -5462,9 +5462,12 @@ CIFGenLayer(
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
TTMaskSetMask(&bls.connect, &op->co_paintMask);
|
||||||
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
||||||
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -5693,9 +5696,12 @@ CIFGenLayer(
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
TTMaskSetMask(&bls.connect, &op->co_paintMask);
|
||||||
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
||||||
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Replace the client data */
|
/* Replace the client data */
|
||||||
op->co_client = (ClientData)text;
|
op->co_client = (ClientData)text;
|
||||||
|
|
|
||||||
149
commands/CmdE.c
149
commands/CmdE.c
|
|
@ -781,39 +781,82 @@ cmdEraseCellsFunc(
|
||||||
* Implement the "expand" command.
|
* Implement the "expand" command.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* expand
|
* expand [selection|surround|overlap|all] [toggle]
|
||||||
* expand toggle
|
*
|
||||||
|
* "selection" expands cells in the selection. All other options
|
||||||
|
* expand cells in the layout. "all" expands all cells in the
|
||||||
|
* layout. "surround" expands cells which the cursor box
|
||||||
|
* surrounds completely, and "overlap" expands cells which the
|
||||||
|
* cursor box overlaps.
|
||||||
|
*
|
||||||
|
* If "toggle" is specified, flips the expanded/unexpanded status.
|
||||||
|
* Cells which were expanded are unexpanded, and cells which were
|
||||||
|
* unexpanded are expanded.
|
||||||
|
*
|
||||||
|
* For backwards compatibility:
|
||||||
|
* "expand" alone implements "expand overlap".
|
||||||
|
* "expand toggle" implements "expand selection toggle".
|
||||||
|
*
|
||||||
|
* Also see: CmdUnexpand
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* If "toggle" is specified, flips the expanded/unexpanded status
|
* Expansion state of cells is changed. May read cells in from
|
||||||
* of all selected cells. Otherwise, aren't any unexpanded cells
|
* disk, and update bounding boxes that have changed.
|
||||||
* left under the box. May read cells in from disk, and updates
|
|
||||||
* bounding boxes that have changed.
|
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define EXPAND_SELECTION 0
|
||||||
|
#define EXPAND_SURROUND 1
|
||||||
|
#define EXPAND_OVERLAP 2
|
||||||
|
#define EXPAND_ALL 3
|
||||||
|
#define EXPAND_HELP 4
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdExpand(
|
CmdExpand(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int windowMask, boxMask, d;
|
int windowMask, boxMask, d, option;
|
||||||
|
bool doToggle = FALSE;
|
||||||
|
const char * const *msg;
|
||||||
Rect rootRect;
|
Rect rootRect;
|
||||||
CellUse *rootBoxUse;
|
CellUse *rootBoxUse;
|
||||||
CellDef *rootBoxDef;
|
CellDef *rootBoxDef;
|
||||||
|
|
||||||
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||||
|
|
||||||
if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
|
static const char * const cmdExpandOption[] = {
|
||||||
&& (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
|
"selection expand cell instances in the selection",
|
||||||
|
"surround expand cell instances which the cursor box surrounds",
|
||||||
|
"overlap expand cell instances which the cursor box overlaps",
|
||||||
|
"all expand all cell instances",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
|
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle",
|
||||||
return;
|
strlen(cmd->tx_argv[cmd->tx_argc - 1])))
|
||||||
|
{
|
||||||
|
doToggle = TRUE;
|
||||||
|
cmd->tx_argc--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
|
{
|
||||||
|
option = Lookup(cmd->tx_argv[1], cmdExpandOption);
|
||||||
|
if (option < 0) option = EXPAND_HELP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
option = EXPAND_OVERLAP;
|
||||||
|
|
||||||
|
if (option == EXPAND_HELP) goto badusage;
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *) NULL)
|
if (w == (MagWindow *) NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -844,23 +887,95 @@ CmdExpand(
|
||||||
WindScale(d, 1);
|
WindScale(d, 1);
|
||||||
TxPrintf("expand: rescaled by %d\n", d);
|
TxPrintf("expand: rescaled by %d\n", d);
|
||||||
d = DBLambda[1];
|
d = DBLambda[1];
|
||||||
if (cmd->tx_argc == 2) break; /* Don't toggle twice */
|
if (doToggle) break; /* Don't toggle twice */
|
||||||
}
|
}
|
||||||
(void) ToolGetBoxWindow(&rootRect, &boxMask);
|
(void) ToolGetBoxWindow(&rootRect, &boxMask);
|
||||||
|
|
||||||
if (cmd->tx_argc == 2)
|
if (option != EXPAND_SELECTION)
|
||||||
SelectExpand(windowMask);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if ((boxMask & windowMask) != windowMask)
|
if ((boxMask & windowMask) != windowMask)
|
||||||
{
|
{
|
||||||
TxError("The box isn't in the same window as the cursor.\n");
|
TxError("The box isn't in the same window as the cursor.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
}
|
||||||
TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case EXPAND_SELECTION:
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
(doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
break;
|
||||||
|
case EXPAND_OVERLAP:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXPAND_SURROUND:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXPAND_ALL:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while (d != DBLambda[1]);
|
} while (d != DBLambda[1]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
badusage:
|
||||||
|
for (msg = &(cmdExpandOption[0]); *msg != NULL; msg++)
|
||||||
|
TxPrintf(" %s\n", *msg);
|
||||||
|
TxPrintf(" toggle Toggle the visibility of cell instances.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called for each cell whose expansion status changed.
|
/* This function is called for each cell whose expansion status changed.
|
||||||
|
|
|
||||||
|
|
@ -517,14 +517,14 @@ CmdLoad(
|
||||||
|
|
||||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
TRUE, keepGoing, NULL);
|
DB_EXPAND, keepGoing, NULL);
|
||||||
|
|
||||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
FALSE, keepGoing, NULL);
|
DB_UNEXPAND, keepGoing, NULL);
|
||||||
DBExpand(topuse,
|
DBExpand(topuse,
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
TRUE);
|
DB_EXPAND);
|
||||||
|
|
||||||
/* We don't want to save and restore DBLambda, because */
|
/* We don't want to save and restore DBLambda, because */
|
||||||
/* loading the file may change their values. Instead, we */
|
/* loading the file may change their values. Instead, we */
|
||||||
|
|
@ -2681,14 +2681,13 @@ CmdDoProperty(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (proplen > 0)
|
if (proplen > 0)
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(
|
proprec = (PropertyRecord *)mallocMagic(
|
||||||
sizeof(PropertyRecord) +
|
sizeof(PropertyRecord) +
|
||||||
(proplen - 2) * sizeof(int));
|
(proplen - 2) * sizeof(int));
|
||||||
proprec->prop_type = proptype;
|
|
||||||
proprec->prop_len = proplen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
|
||||||
/* Second pass */
|
/* Second pass */
|
||||||
value = cmd->tx_argv[argstart + 1];
|
value = cmd->tx_argv[argstart + 1];
|
||||||
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
||||||
|
|
|
||||||
110
commands/CmdRS.c
110
commands/CmdRS.c
|
|
@ -1801,13 +1801,18 @@ cmdLabelSizeFunc(
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
{
|
{
|
||||||
|
char *labsize;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
labsize = DBWPrintValue(label->lab_size / 8, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(labsize, -1));
|
||||||
Tcl_NewDoubleObj((double)label->lab_size / 8.0));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%g\n", (double)label->lab_size / 8.0);
|
TxPrintf("%s\n", labsize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (label->lab_size != *value)
|
else if (label->lab_size != *value)
|
||||||
|
|
@ -1952,18 +1957,22 @@ cmdLabelOffsetFunc(
|
||||||
|
|
||||||
if (point == NULL)
|
if (point == NULL)
|
||||||
{
|
{
|
||||||
|
char *laboffx, *laboffy;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
laboffx = DBWPrintValue(label->lab_offset.p_x / 8, w, TRUE);
|
||||||
|
laboffy = DBWPrintValue(label->lab_offset.p_x / 8, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffx, -1));
|
||||||
Tcl_NewDoubleObj((double)label->lab_offset.p_x / 8.0));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffy, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewDoubleObj((double)label->lab_offset.p_y / 8.0));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%g %g\n", (double)(label->lab_offset.p_x) / 8.0,
|
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||||
(double)(label->lab_offset.p_y) / 8.0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
|
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
|
||||||
|
|
@ -2212,9 +2221,13 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelTextFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL);
|
cmdLabelTextFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelTextFunc,
|
||||||
|
(ClientData)cmd->tx_argv[argstart + 1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2280,9 +2293,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelFontFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&font : (ClientData)NULL);
|
cmdLabelFontFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelFontFunc, (ClientData)&font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2310,9 +2326,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelJustFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&pos : (ClientData)NULL);
|
cmdLabelJustFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelJustFunc, (ClientData)&pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2341,9 +2360,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelSizeFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&size : (ClientData)NULL);
|
cmdLabelSizeFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelSizeFunc, (ClientData)&size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2393,9 +2415,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelOffsetFunc, (locargc != 2) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&offset : (ClientData)NULL);
|
cmdLabelOffsetFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelOffsetFunc, (ClientData)&offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2459,10 +2484,12 @@ CmdSetLabel(
|
||||||
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
|
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
|
||||||
TRUE, FALSE, 1);
|
TRUE, FALSE, 1);
|
||||||
}
|
}
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if ((locargc == 3) || (locargc == 6))
|
||||||
cmdLabelRectFunc,
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
((locargc == 6) || (locargc == 3)) ?
|
cmdLabelRectFunc, (ClientData)&rect);
|
||||||
(ClientData)&rect : (ClientData)NULL);
|
else
|
||||||
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelRectFunc, (ClientData)NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2488,9 +2515,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelRotateFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&rotate : (ClientData)NULL);
|
cmdLabelRotateFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelRotateFunc, (ClientData)&rotate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2522,9 +2552,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelStickyFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&flags : (ClientData)NULL);
|
cmdLabelStickyFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelStickyFunc, (ClientData)&flags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2563,9 +2596,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelLayerFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&ttype : (ClientData)NULL);
|
cmdLabelLayerFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelLayerFunc, (ClientData)&ttype);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1239,7 +1239,7 @@ cmdExpandOneLevel(
|
||||||
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
|
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
|
||||||
|
|
||||||
/* first, expand this cell use */
|
/* first, expand this cell use */
|
||||||
DBExpand(cu, bitmask, expand);
|
DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND);
|
||||||
|
|
||||||
/* now, unexpand its direct children (ONE LEVEL ONLY) */
|
/* now, unexpand its direct children (ONE LEVEL ONLY) */
|
||||||
if (expand)
|
if (expand)
|
||||||
|
|
@ -1251,7 +1251,7 @@ cmdExpand1func(
|
||||||
CellUse *cu,
|
CellUse *cu,
|
||||||
ClientData bitmask)
|
ClientData bitmask)
|
||||||
{
|
{
|
||||||
DBExpand(cu, (int)CD2INT(bitmask), FALSE);
|
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -702,32 +702,62 @@ CmdTool(
|
||||||
* Implement the "unexpand" command.
|
* Implement the "unexpand" command.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* unexpand
|
* unexpand [selection|surround|overlap|all]
|
||||||
|
*
|
||||||
|
* "selection" unexpands (hides) cells in the selection. All
|
||||||
|
* other options unexpand cells in the layout. "all" unexpands
|
||||||
|
* all cells in the layout. "surround" unexpannds cells which
|
||||||
|
* the cursor box surrounds completely, and "overlap" unexpands
|
||||||
|
* cells which the cursor box overlaps.
|
||||||
|
*
|
||||||
|
* For backwards compatibility:
|
||||||
|
* "unexpand" alone implements "unexpand surround".
|
||||||
|
*
|
||||||
|
* Also see: CmdExpand
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Unexpands all cells under the box that don't completely
|
* Changes the expansion state of cells.
|
||||||
* contain the box.
|
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define UNEXPAND_SELECTION 0
|
||||||
|
#define UNEXPAND_SURROUND 1
|
||||||
|
#define UNEXPAND_OVERLAP 2
|
||||||
|
#define UNEXPAND_ALL 3
|
||||||
|
#define UNEXPAND_HELP 4
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdUnexpand(
|
CmdUnexpand(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int windowMask, boxMask;
|
int windowMask, boxMask, option;
|
||||||
|
const char * const *msg;
|
||||||
Rect rootRect;
|
Rect rootRect;
|
||||||
|
|
||||||
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||||
|
|
||||||
if (cmd->tx_argc != 1)
|
static const char * const cmdUnexpandOption[] = {
|
||||||
|
"selection expand cell instances in the selection",
|
||||||
|
"surround expand cell instances which the cursor box surrounds",
|
||||||
|
"overlap expand cell instances which the cursor box overlaps",
|
||||||
|
"all expand all cell instances",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s\n", cmd->tx_argv[0]);
|
option = Lookup(cmd->tx_argv[1], cmdUnexpandOption);
|
||||||
return;
|
if (option < 0) option = UNEXPAND_HELP;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
option = UNEXPAND_SURROUND;
|
||||||
|
|
||||||
|
if (option == UNEXPAND_HELP) goto badusage;
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *) NULL)
|
if (w == (MagWindow *) NULL)
|
||||||
|
|
@ -743,8 +773,42 @@ CmdUnexpand(
|
||||||
TxError("The box isn't in the same window as the cursor.\n");
|
TxError("The box isn't in the same window as the cursor.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DBExpandAll(((CellUse *) w->w_surfaceID), &rootRect, windowMask,
|
|
||||||
FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask);
|
switch (option)
|
||||||
|
{
|
||||||
|
case UNEXPAND_SELECTION:
|
||||||
|
SelectExpand(windowMask, DB_UNEXPAND, (Rect *)NULL, FALSE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_OVERLAP:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_SURROUND:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_ALL:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &TiPlaneRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
badusage:
|
||||||
|
for (msg = &(cmdUnexpandOption[0]); *msg != NULL; msg++)
|
||||||
|
TxPrintf(" %s\n", *msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called for each cell whose expansion status changed.
|
/* This function is called for each cell whose expansion status changed.
|
||||||
|
|
|
||||||
|
|
@ -588,6 +588,25 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (flags & TF_LABEL_REVERSE_SEARCH)
|
||||||
|
{
|
||||||
|
/* Search children first */
|
||||||
|
filter.tf_func = func;
|
||||||
|
filter.tf_arg = cdarg;
|
||||||
|
filter.tf_mask = mask;
|
||||||
|
filter.tf_xmask = xMask;
|
||||||
|
filter.tf_tpath = tpath;
|
||||||
|
filter.tf_flags = flags;
|
||||||
|
|
||||||
|
scx2 = *scx;
|
||||||
|
if (scx2.scx_area.r_xbot > TiPlaneRect.r_xbot) scx2.scx_area.r_xbot -= 1;
|
||||||
|
if (scx2.scx_area.r_ybot > TiPlaneRect.r_ybot) scx2.scx_area.r_ybot -= 1;
|
||||||
|
if (scx2.scx_area.r_xtop < TiPlaneRect.r_xtop) scx2.scx_area.r_xtop += 1;
|
||||||
|
if (scx2.scx_area.r_ytop < TiPlaneRect.r_ytop) scx2.scx_area.r_ytop += 1;
|
||||||
|
if (DBCellSrArea(&scx2, dbCellLabelSrFunc, (ClientData) &filter))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||||
{
|
{
|
||||||
if (SigInterruptPending) break;
|
if (SigInterruptPending) break;
|
||||||
|
|
@ -640,6 +659,8 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & TF_LABEL_REVERSE_SEARCH) return 0; /* children already searched */
|
||||||
|
|
||||||
filter.tf_func = func;
|
filter.tf_func = func;
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
filter.tf_mask = mask;
|
filter.tf_mask = mask;
|
||||||
|
|
@ -711,6 +732,16 @@ dbCellLabelSrFunc(scx, fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If fp->tf_flags has TF_LABEL_REVERSE_SEARCH, then search child
|
||||||
|
* uses first, then the parent. This is for display, so that if
|
||||||
|
* a child cell and parent cell have overlapping labels, the parent
|
||||||
|
* label is the one on top.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fp->tf_flags & TF_LABEL_REVERSE_SEARCH)
|
||||||
|
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||||
|
result = 1;
|
||||||
|
|
||||||
/* Apply the function first to any of the labels in this def. */
|
/* Apply the function first to any of the labels in this def. */
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
@ -732,9 +763,11 @@ dbCellLabelSrFunc(scx, fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now visit each child use recursively */
|
/* Now visit each child use recursively, if not doing a reverse search */
|
||||||
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
|
||||||
result = 1;
|
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH))
|
||||||
|
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||||
|
result = 1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
/* Remove the trailing pathname component from the TerminalPath */
|
/* Remove the trailing pathname component from the TerminalPath */
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ struct expandArg
|
||||||
{
|
{
|
||||||
bool ea_deref; /* TRUE if root def dereference flag is set */
|
bool ea_deref; /* TRUE if root def dereference flag is set */
|
||||||
int ea_xmask; /* Expand mask. */
|
int ea_xmask; /* Expand mask. */
|
||||||
|
int ea_type; /* Expand, unexpand, or toggle */
|
||||||
int (*ea_func)(); /* Function to call for each cell whose
|
int (*ea_func)(); /* Function to call for each cell whose
|
||||||
* status is changed.
|
* status is changed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -67,15 +68,22 @@ struct expandArg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBExpand(cellUse, expandMask, expandFlag)
|
DBExpand(cellUse, expandMask, expandType)
|
||||||
CellUse *cellUse;
|
CellUse *cellUse;
|
||||||
int expandMask;
|
int expandMask;
|
||||||
bool expandFlag;
|
int expandType;
|
||||||
{
|
{
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
bool expandFlag, expandTest;
|
||||||
if (DBDescendSubcell(cellUse, expandMask) == expandFlag)
|
|
||||||
return;
|
expandTest = DBDescendSubcell(cellUse, expandMask);
|
||||||
|
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE)
|
||||||
|
expandFlag = expandTest;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE;
|
||||||
|
if (expandFlag == expandTest) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (expandFlag)
|
if (expandFlag)
|
||||||
{
|
{
|
||||||
|
|
@ -130,17 +138,17 @@ DBExpand(cellUse, expandMask, expandFlag)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
|
||||||
CellUse *rootUse; /* Root cell use from which search begins */
|
CellUse *rootUse; /* Root cell use from which search begins */
|
||||||
Rect *rootRect; /* Area to be expanded, in root coordinates */
|
Rect *rootRect; /* Area to be expanded, in root coordinates */
|
||||||
int expandMask; /* Window mask in which cell is to be expanded */
|
int expandMask; /* Window mask in which cell is to be expanded */
|
||||||
bool expandFlag; /* TRUE => expand, FALSE => unexpand */
|
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */
|
||||||
int (*func)(); /* Function to call for each cell whose expansion
|
int (*func)(); /* Function to call for each cell whose expansion
|
||||||
* status is modified. NULL means don't call anyone.
|
* status is modified. NULL means don't call anyone.
|
||||||
*/
|
*/
|
||||||
ClientData cdarg; /* Argument to pass to func. */
|
ClientData cdarg; /* Argument to pass to func. */
|
||||||
{
|
{
|
||||||
int dbExpandFunc(), dbUnexpandFunc();
|
int dbExpandFunc();
|
||||||
SearchContext scontext;
|
SearchContext scontext;
|
||||||
struct expandArg arg;
|
struct expandArg arg;
|
||||||
|
|
||||||
|
|
@ -148,29 +156,26 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
||||||
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
|
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Walk through the area and set the expansion state
|
* Walk through the area and set the expansion state appropriately.
|
||||||
* appropriately.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
arg.ea_xmask = expandMask;
|
arg.ea_xmask = expandMask;
|
||||||
arg.ea_func = func;
|
arg.ea_func = func;
|
||||||
arg.ea_arg = cdarg;
|
arg.ea_arg = cdarg;
|
||||||
|
arg.ea_type = expandType;
|
||||||
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
||||||
|
|
||||||
scontext.scx_use = rootUse;
|
scontext.scx_use = rootUse;
|
||||||
scontext.scx_trans = GeoIdentityTransform;
|
scontext.scx_trans = GeoIdentityTransform;
|
||||||
scontext.scx_area = *rootRect;
|
scontext.scx_area = *rootRect;
|
||||||
if (expandFlag)
|
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
||||||
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
|
||||||
else
|
|
||||||
DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dbExpandFunc --
|
* dbExpandFunc --
|
||||||
*
|
*
|
||||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
||||||
* when cells are being expanded.
|
* when cells are being expanded, unexpanded, or toggled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -184,68 +189,55 @@ dbExpandFunc(scx, arg)
|
||||||
{
|
{
|
||||||
CellUse *childUse = scx->scx_use;
|
CellUse *childUse = scx->scx_use;
|
||||||
int n = DBLambda[1];
|
int n = DBLambda[1];
|
||||||
|
int expandTest;
|
||||||
|
int expandType = (arg->ea_type & DB_EXPAND_MASK);
|
||||||
|
int expandSurround = (arg->ea_type & DB_EXPAND_SURROUND_MASK);
|
||||||
|
bool surround;
|
||||||
|
|
||||||
|
expandTest = DBDescendSubcell(childUse, arg->ea_xmask);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change the expansion status of this cell if necessary. Call the
|
* Change the expansion status of this cell if necessary. Call the
|
||||||
* client's function if the expansion status has changed.
|
* client's function if the expansion status has changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!DBDescendSubcell(childUse, arg->ea_xmask))
|
if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE)))
|
||||||
{
|
{
|
||||||
/* If the cell is unavailable, then don't expand it.
|
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||||
*/
|
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||||
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||||
{
|
{
|
||||||
/* If the parent is dereferenced, then the child should be, too */
|
/* If the cell is unavailable, then don't expand it.
|
||||||
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
*/
|
||||||
if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
||||||
{
|
{
|
||||||
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
/* If the parent is dereferenced, then the child should be, too */
|
||||||
childUse->cu_def->cd_name);
|
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
||||||
return 2;
|
if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
||||||
|
{
|
||||||
|
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
||||||
|
childUse->cu_def->cd_name);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
childUse->cu_expandMask |= arg->ea_xmask;
|
||||||
|
expandTest = TRUE;
|
||||||
|
if (arg->ea_func != NULL)
|
||||||
|
{
|
||||||
|
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
childUse->cu_expandMask |= arg->ea_xmask;
|
|
||||||
if (arg->ea_func != NULL)
|
|
||||||
{
|
|
||||||
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (expandTest && ((expandType == DB_UNEXPAND) ||
|
||||||
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
(expandType == DB_EXPAND_TOGGLE)))
|
||||||
return 1;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dbUnexpandFunc --
|
|
||||||
*
|
|
||||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
|
||||||
* when cells are being unexpanded.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
dbUnexpandFunc(scx, arg)
|
|
||||||
SearchContext *scx; /* Pointer to search context containing
|
|
||||||
* child use, search area in coor-
|
|
||||||
* dinates of the child use, and
|
|
||||||
* transform back to "root".
|
|
||||||
*/
|
|
||||||
struct expandArg *arg; /* Client data from caller */
|
|
||||||
{
|
|
||||||
CellUse *childUse = scx->scx_use;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Change the expansion status of this cell if necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (DBDescendSubcell(childUse, arg->ea_xmask))
|
|
||||||
{
|
{
|
||||||
if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||||
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox))
|
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||||
|
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||||
{
|
{
|
||||||
childUse->cu_expandMask &= ~arg->ea_xmask;
|
childUse->cu_expandMask &= ~arg->ea_xmask;
|
||||||
|
expandTest = FALSE;
|
||||||
|
|
||||||
/* Call the client's function, if there is one. */
|
/* Call the client's function, if there is one. */
|
||||||
|
|
||||||
|
|
@ -256,11 +248,7 @@ dbUnexpandFunc(scx, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't recursively search things that aren't already expanded. */
|
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
||||||
|
|
||||||
else return 2;
|
|
||||||
|
|
||||||
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
|
|
||||||
return 1;
|
return 1;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2594,7 +2594,16 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
||||||
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||||
if (!isspace(*pptr))
|
if (!isspace(*pptr))
|
||||||
{
|
{
|
||||||
sscanf(pptr, "%d", &ival);
|
if (sscanf(pptr, "%d", &ival) != 1)
|
||||||
|
{
|
||||||
|
TxError("Mask-hint \"%s\" has non-integer values!",
|
||||||
|
pptr);
|
||||||
|
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
||||||
|
TiFreePlane(proprec->prop_value.prop_plane);
|
||||||
|
freeMagic((char *)proprec);
|
||||||
|
proprec = (PropertyRecord *)NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (scalen > 1) ival *= scalen;
|
if (scalen > 1) ival *= scalen;
|
||||||
if (scaled > 1) ival /= scaled;
|
if (scaled > 1) ival /= scaled;
|
||||||
switch (numvals)
|
switch (numvals)
|
||||||
|
|
@ -2622,11 +2631,11 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
||||||
}
|
}
|
||||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||||
}
|
}
|
||||||
if (numvals == 0)
|
}
|
||||||
{
|
if (numvals != 0)
|
||||||
TxError("Mask-hint property number of values is not"
|
{
|
||||||
|
TxError("Mask-hint property number of values is not"
|
||||||
" divisible by four. Truncated.\n");
|
" divisible by four. Truncated.\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(void) DBPropPut(cellDef, propertyname, proprec);
|
(void) DBPropPut(cellDef, propertyname, proprec);
|
||||||
}
|
}
|
||||||
|
|
@ -4409,7 +4418,7 @@ DBCellWriteCommandFile(cellDef, f)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(f, "label %s %s %d %d %d %d %s %s\n",
|
fprintf(f, "label %s %s %d %d %d %d %s %s%s\n",
|
||||||
lab->lab_text,
|
lab->lab_text,
|
||||||
DBFontList[lab->lab_font]->mf_name,
|
DBFontList[lab->lab_font]->mf_name,
|
||||||
lab->lab_size >> 3,
|
lab->lab_size >> 3,
|
||||||
|
|
@ -4417,15 +4426,10 @@ DBCellWriteCommandFile(cellDef, f)
|
||||||
lab->lab_offset.p_x,
|
lab->lab_offset.p_x,
|
||||||
lab->lab_offset.p_y,
|
lab->lab_offset.p_y,
|
||||||
directionNames[lab->lab_just],
|
directionNames[lab->lab_just],
|
||||||
|
(lab->lab_flags & LABEL_STICKY) ? "-" : "",
|
||||||
DBTypeLongName(lab->lab_type));
|
DBTypeLongName(lab->lab_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lab->lab_flags & LABEL_STICKY)
|
|
||||||
{
|
|
||||||
fprintf(f, "select area label\n");
|
|
||||||
fprintf(f, "setlabel sticky true\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lab->lab_flags & PORT_DIR_MASK)
|
if (lab->lab_flags & PORT_DIR_MASK)
|
||||||
{
|
{
|
||||||
if (!(lab->lab_flags & LABEL_STICKY))
|
if (!(lab->lab_flags & LABEL_STICKY))
|
||||||
|
|
|
||||||
|
|
@ -651,6 +651,7 @@ typedef struct treeFilter
|
||||||
#define TF_LABEL_ATTACH_NOT_SE 0x10 /* Same as above, ignore tile SE corner */
|
#define TF_LABEL_ATTACH_NOT_SE 0x10 /* Same as above, ignore tile SE corner */
|
||||||
#define TF_LABEL_ATTACH_NOT_SW 0x20 /* Same as above, ignore tile SW corner */
|
#define TF_LABEL_ATTACH_NOT_SW 0x20 /* Same as above, ignore tile SW corner */
|
||||||
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
|
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
|
||||||
|
#define TF_LABEL_REVERSE_SEARCH 0x40 /* Search children before parent */
|
||||||
|
|
||||||
/* To do: Make the tpath entries dynamically allocated */
|
/* To do: Make the tpath entries dynamically allocated */
|
||||||
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
|
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
|
||||||
|
|
@ -1061,6 +1062,19 @@ extern unsigned char DBVerbose; /* If 0, don't print any messages */
|
||||||
#define DB_VERBOSE_WARN 2
|
#define DB_VERBOSE_WARN 2
|
||||||
#define DB_VERBOSE_ALL 3
|
#define DB_VERBOSE_ALL 3
|
||||||
|
|
||||||
|
/* ---------- Definitions for expanding/unexpanding cells --------------*/
|
||||||
|
|
||||||
|
/* Selection expansion flags */
|
||||||
|
#define DB_EXPAND_MASK 3 /* 1 = expand, 0 = unexpand, 2 = toggle */
|
||||||
|
#define DB_EXPAND_SURROUND_MASK 4 /* 1 = surround, 0 = touch */
|
||||||
|
|
||||||
|
/* Selection expansion values */
|
||||||
|
#define DB_EXPAND 0
|
||||||
|
#define DB_UNEXPAND 1
|
||||||
|
#define DB_EXPAND_TOGGLE 2
|
||||||
|
#define DB_EXPAND_SURROUND 4
|
||||||
|
#define DB_EXPAND_OVERLAP 0
|
||||||
|
|
||||||
/* ------------------ Exported technology variables ------------------- */
|
/* ------------------ Exported technology variables ------------------- */
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,11 @@ DBWAddButtonHandler(
|
||||||
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||||
{
|
{
|
||||||
if (dbwButtonHandlers[i] != NULL) continue;
|
if (dbwButtonHandlers[i] != NULL) continue;
|
||||||
(void) StrDup(&dbwButtonHandlers[i], name);
|
StrDup(&dbwButtonHandlers[i], name);
|
||||||
(void) StrDup(&dbwButtonDoc[i], doc);
|
if (doc != NULL)
|
||||||
|
StrDup(&dbwButtonDoc[i], doc);
|
||||||
|
else
|
||||||
|
dbwButtonDoc[i] = (char *)NULL;
|
||||||
dbwButtonProcs[i] = proc;
|
dbwButtonProcs[i] = proc;
|
||||||
dbwButtonCursors[i] = cursor;
|
dbwButtonCursors[i] = cursor;
|
||||||
return;
|
return;
|
||||||
|
|
@ -273,6 +276,37 @@ DBWGetButtonHandler()
|
||||||
return dbwButtonHandlers[dbwButtonCurrentIndex];
|
return dbwButtonHandlers[dbwButtonCurrentIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBWButtonHandlerIndex()
|
||||||
|
*
|
||||||
|
* Given a string, return the index of the button handler. If the
|
||||||
|
* string does not correspond to any button handler name, then
|
||||||
|
* return -1.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Index of button handler, if it exists; -1 otherwise.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
DBWButtonHandlerIndex(char *toolName)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||||
|
{
|
||||||
|
if (dbwButtonHandlers[i] == NULL) return -1;
|
||||||
|
else if (!strcmp(toolName, dbwButtonHandlers[i])) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -294,7 +328,10 @@ DBWGetButtonHandler()
|
||||||
void
|
void
|
||||||
DBWPrintButtonDoc()
|
DBWPrintButtonDoc()
|
||||||
{
|
{
|
||||||
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
if (dbwButtonDoc[dbwButtonCurrentIndex])
|
||||||
|
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
||||||
|
else
|
||||||
|
TxPrintf("(no usage information)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,8 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
/* Set style information beforehand */
|
/* Set style information beforehand */
|
||||||
GrSetStuff(STYLE_LABEL);
|
GrSetStuff(STYLE_LABEL);
|
||||||
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
||||||
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
|
(TerminalPath *) NULL,
|
||||||
|
TF_LABEL_DISPLAY | TF_LABEL_ATTACH | TF_LABEL_REVERSE_SEARCH,
|
||||||
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
|
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
|
||||||
GrClipTo(&rootClip);
|
GrClipTo(&rootClip);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -546,12 +546,12 @@ DBWloadWindow(window, name, flags)
|
||||||
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
|
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
|
||||||
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
|
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
|
||||||
DBExpand(newEditUse,
|
DBExpand(newEditUse,
|
||||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE);
|
((DBWclientRec *)window->w_clientData)->dbw_bitmask, DB_EXPAND);
|
||||||
|
|
||||||
if (expand)
|
if (expand)
|
||||||
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
|
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
|
||||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
|
||||||
FALSE, UnexpandFunc,
|
DB_UNEXPAND, UnexpandFunc,
|
||||||
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
|
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
|
||||||
|
|
||||||
if (newEdit)
|
if (newEdit)
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandle
|
||||||
int cursor, const char *doc);
|
int cursor, const char *doc);
|
||||||
extern char *DBWGetButtonHandler();
|
extern char *DBWGetButtonHandler();
|
||||||
extern char *DBWChangeButtonHandler();
|
extern char *DBWChangeButtonHandler();
|
||||||
|
extern int DBWButtonHandlerIndex();
|
||||||
extern void DBWPrintButtonDoc();
|
extern void DBWPrintButtonDoc();
|
||||||
extern void DBWBoxHandler();
|
extern void DBWBoxHandler();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,15 @@ Operations on cell definitions.
|
||||||
<DT> <B>rename</B> <I>name newname</I>
|
<DT> <B>rename</B> <I>name newname</I>
|
||||||
<DD> Change the name of the cell definition <I>name</I> to
|
<DD> Change the name of the cell definition <I>name</I> to
|
||||||
<I>newname</I>.
|
<I>newname</I>.
|
||||||
<DT> <B>delete</B> <I>name</I>
|
<DT> <B>delete</B> <I>name</I> [<B>-noprompt</B>]
|
||||||
<DD> Delete the cell definition with name <I>name</I>. If cell
|
<DD> Delete the cell definition with name <I>name</I>. If cell
|
||||||
<I>name</I> is a descendent of another cell, the command
|
<I>name</I> is a descendent of another cell, the command
|
||||||
will be prohibited. If the cell <I>name</I> is currently
|
will be prohibited. If the cell <I>name</I> is currently
|
||||||
the topmost cell in the window, the window will be loaded
|
the topmost cell in the window, the window will be loaded
|
||||||
with default cell "(UNNAMED)".
|
with default cell "(UNNAMED)". If option <B>-noprompt</B>
|
||||||
|
is specified, then the actions specified above happen
|
||||||
|
immediately. Otherwise, a dialog box will be raised
|
||||||
|
asking for confirmation to delete the cell.
|
||||||
<DT> <B>dereference</B> <I>name</I>
|
<DT> <B>dereference</B> <I>name</I>
|
||||||
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
|
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
|
||||||
first removing any file path associated with the cell, so
|
first removing any file path associated with the cell, so
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ expanded/unexpanded cells in the current selection.
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>expand</B> [<B>toggle</B>] <BR><BR>
|
<B>expand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||||
|
[<B>toggle</B>] <BR><BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Shortcuts:</H3>
|
<H3>Shortcuts:</H3>
|
||||||
|
|
@ -38,14 +39,32 @@ expanded/unexpanded cells in the current selection.
|
||||||
<H3>Summary:</H3>
|
<H3>Summary:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
The <B>expand</B> command expands the view of subcells to
|
The <B>expand</B> command expands the view of subcells to
|
||||||
display the contents of the subcells. Without arguments,
|
display the contents of the subcells.
|
||||||
the <B>expand</B> command expands all unexpanded subcells that
|
|
||||||
touch or intersect the cursor box in the layout window. <P>
|
Option <B>overlap</B> expands all unexpanded subcells that
|
||||||
|
overlap with the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>surround</B> expands all unexpanded subcells that
|
||||||
|
are completely surrounded by the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>all</B> expands all subcells in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>selection</B> operates on the current selection, not
|
||||||
|
relative to the cursor box, expanding all selected cells. <P>
|
||||||
|
|
||||||
|
Option <B>toggle</B> will expand a selected cell that is
|
||||||
|
unexpanded, or unexpand a cell that is already expanded.
|
||||||
|
<B>toggle</B> may be given as an additional option to any
|
||||||
|
of the other options above; however, the <B>toggle</B> option
|
||||||
|
must be the last option given to the command.<P>
|
||||||
|
|
||||||
|
With no arguments, the <B>expand</B> command behaves like
|
||||||
|
<B>expand overlap</B>, and the <B>expand toggle</B> command
|
||||||
|
with no additonal arguments behaves like
|
||||||
|
<B>expand selection toggle</B>, for backwards-compatible
|
||||||
|
behavior with earlier versions of magic which offered only
|
||||||
|
the <B>toggle</B> option.
|
||||||
|
|
||||||
Option <B>expand toggle</B> operates on the current selection,
|
|
||||||
not relative to the cursor box, and will expand a selected
|
|
||||||
cell that is unexpanded, or unexpand a cell that is already
|
|
||||||
expanded.
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -20,22 +20,64 @@
|
||||||
|
|
||||||
<H2>macro</H2>
|
<H2>macro</H2>
|
||||||
<HR>
|
<HR>
|
||||||
Define or print a macro called char
|
Define or print a key or button macro binding.
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
|
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]]
|
||||||
|
<BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>key</I> is the name of a valid key (see below), and
|
where <I>key</I> is the name of a valid key (see below), and
|
||||||
<I>value</I> is a <B>magic</B> command-line command. If
|
<I>value</I> is a <B>magic</B> command-line command. If
|
||||||
present, <I>window_type</I> must be one of the four window
|
present, <I>window_type</I> must be one of the known valid window
|
||||||
types accepted by the <B>specialopen</B> command: <B>layout</B>,
|
types accepted by the <B>specialopen</B> command (<B>color</B>,
|
||||||
<B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If omitted,
|
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool
|
||||||
the layout window is assumed by default, unless the command has
|
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If
|
||||||
been called from inside a window (using the colon or semicolon
|
omitted, the layout window is assumed by default, unless the command
|
||||||
|
has been called from inside a window (using the colon or semicolon
|
||||||
escape to the command-line), in which case that window type is
|
escape to the command-line), in which case that window type is
|
||||||
assumed.
|
assumed. <P>
|
||||||
|
|
||||||
|
In the non-Tcl version of magic, the <I>window_type</I> must be
|
||||||
|
one of the three valid window types listed above, or <B>layout</B>.
|
||||||
|
Tool button bindings are hard-coded, fixed, and unknown to the
|
||||||
|
macro handler. <P>
|
||||||
|
|
||||||
|
In the Tcl version of magic, tool types are generated by
|
||||||
|
procedure and can be modified or overridden. The four tools
|
||||||
|
listed above are the default tools known to magic. If no window
|
||||||
|
or tool type is given, then the current tool in the current
|
||||||
|
active layout window is assumed.<P>
|
||||||
|
|
||||||
|
<I>option</I> may be one of the following:
|
||||||
|
<DL>
|
||||||
|
<DT> <B>list</B> [<B>-reverse</B>]
|
||||||
|
<DD> The key bindings are returned in the form of a Tcl list
|
||||||
|
(Tcl version of magic only). The returned value is a
|
||||||
|
single list with alternating entries of the macro key and
|
||||||
|
the macro binding. In Tcl, this list can be treated as a
|
||||||
|
dictionary type of key:value pairs. With the <B>-reverse</B>
|
||||||
|
option, the keys and values are reversed, resulting in a
|
||||||
|
dictionary that can be searched or listed by function.
|
||||||
|
<DT> <B>help</B>
|
||||||
|
<DD> Curently, <B>macro help</B> is equivalent to <B>macro</B>
|
||||||
|
without arguments, and returns a full list of macro names
|
||||||
|
and their bindings.
|
||||||
|
<DT> <B>search</B> <I>text</I>
|
||||||
|
<DD> Return only results which match (all or in part) the string
|
||||||
|
<I>text</I>. For example, <B>macro search grid</B> will
|
||||||
|
return all key bindings that include the command <B>grid</B>.
|
||||||
|
<DT> <B>copy</B> <I>tool_name</I>
|
||||||
|
<DD> This is a method introduced to allow the interactive creation
|
||||||
|
of new tools, in the Tcl version of magic. Each tool is defined
|
||||||
|
specifically by its unique button and key bindings. Because
|
||||||
|
tools generally keep most of the same default bindings, the
|
||||||
|
<B>copy</B> option will copy all the existing bindings to the
|
||||||
|
new tool from the current tool. This can be followed by
|
||||||
|
switching to the new tool and replacing macros with ones
|
||||||
|
unique to the tool.
|
||||||
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -72,7 +114,6 @@ Define or print a macro called char
|
||||||
etc., the <B>macro</B> command accepts the abbreviated
|
etc., the <B>macro</B> command accepts the abbreviated
|
||||||
forms <B>Button1</B>, and so forth. <P>
|
forms <B>Button1</B>, and so forth. <P>
|
||||||
|
|
||||||
|
|
||||||
Finally, key modifiers may be prepended to the key name.
|
Finally, key modifiers may be prepended to the key name.
|
||||||
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
|
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
|
||||||
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
|
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
|
||||||
|
|
@ -89,6 +130,7 @@ Define or print a macro called char
|
||||||
<H3>See Also:</H3>
|
<H3>See Also:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<A HREF=imacro.html><B>imacro</B></A> <BR>
|
<A HREF=imacro.html><B>imacro</B></A> <BR>
|
||||||
|
<A HREF=toolchange.html><B>tool</B></A> (Tcl version) <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ Unexpand everything inside or touching the cursor box.
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>unexpand</B> <BR><BR>
|
<B>unexpand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||||
|
<BR><BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Shortcuts:</H3>
|
<H3>Shortcuts:</H3>
|
||||||
|
|
@ -37,8 +38,23 @@ Unexpand everything inside or touching the cursor box.
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
The <B>unexpand</B> command unexpands the view of subcells to
|
The <B>unexpand</B> command unexpands the view of subcells to
|
||||||
hide the contents of the subcells and show the bounding box
|
hide the contents of the subcells and show the bounding box
|
||||||
outline only. The <B>unexpand</B> command unexpands all subcells
|
outline only.
|
||||||
that touch or intersect the cursor box in the layout window. <P>
|
|
||||||
|
Option <B>overlap</B> unexpands all expanded subcells that
|
||||||
|
overlap with the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>surround</B> unexpands all expanded subcells that
|
||||||
|
are completely surrounded by the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>all</B> unexpands all subcells in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>selection</B> operates on the current selection, not
|
||||||
|
relative to the cursor box, unexpanding all selected cells. <P>
|
||||||
|
|
||||||
|
With no arguments, the <B>unexpand</B> command behaves like
|
||||||
|
<B>unexpand surround</B>, for backwards-compatible behavior with
|
||||||
|
earlier versions of magic which did not offer the options.
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -2755,6 +2755,56 @@ extOutputDevices(def, transList, outFile)
|
||||||
/* get corrected by extComputeEffectiveLW(). */
|
/* get corrected by extComputeEffectiveLW(). */
|
||||||
length = (extTransRec.tr_gatelen - width) / 2;
|
length = (extTransRec.tr_gatelen - width) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((n == 1) && (length == 0) && (extTransRec.tr_gatelen == 0))
|
||||||
|
{
|
||||||
|
/* If a one-terminal device has not recorded any
|
||||||
|
* gate length, then get W and L from the bounding
|
||||||
|
* box of the device. This routine could be much
|
||||||
|
* better optimized but it is probably not worth
|
||||||
|
* the effort. Just reusing the code from above
|
||||||
|
* for creating extSpecialDevice, a list of device
|
||||||
|
* tiles. Note that W and L are not distinguishable
|
||||||
|
* and hopefully the PDK defines the device by area
|
||||||
|
* and perimeter.
|
||||||
|
*/
|
||||||
|
LinkedTile *lt;
|
||||||
|
Rect devbbox, ltbox;
|
||||||
|
|
||||||
|
extSpecialDevice = (LinkedTile *)NULL;
|
||||||
|
|
||||||
|
arg.fra_uninit = (ClientData)extTransRec.tr_gatenode;
|
||||||
|
arg.fra_region = (ExtRegion *)reg;
|
||||||
|
arg.fra_each = extSDTileFunc;
|
||||||
|
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
|
||||||
|
arg.fra_pNum, &arg);
|
||||||
|
|
||||||
|
arg.fra_uninit = (ClientData) reg;
|
||||||
|
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
|
||||||
|
arg.fra_each = (int (*)()) NULL;
|
||||||
|
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
|
||||||
|
arg.fra_pNum, &arg);
|
||||||
|
|
||||||
|
lt = extSpecialDevice;
|
||||||
|
if (lt)
|
||||||
|
{
|
||||||
|
TiToRect(lt->t, &devbbox);
|
||||||
|
for (; lt; lt = lt->t_next)
|
||||||
|
{
|
||||||
|
TiToRect(lt->t, <box);
|
||||||
|
GeoInclude(<box, &devbbox);
|
||||||
|
}
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
for (lt = extSpecialDevice; lt; lt = lt->t_next)
|
||||||
|
freeMagic1(&mm1, (char *)lt);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
|
length = devbbox.r_xtop - devbbox.r_xbot;
|
||||||
|
/* Width was likely a perimeter value and will
|
||||||
|
* be recalculated as the actual device width.
|
||||||
|
*/
|
||||||
|
width = devbbox.r_ytop - devbbox.r_ybot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------*/
|
/*------------------------------------------------------*/
|
||||||
|
|
|
||||||
|
|
@ -1356,7 +1356,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
}
|
}
|
||||||
if (extDev->subs == extNode)
|
if (extDev->subs == extNode)
|
||||||
{
|
{
|
||||||
if ((subs = layoutDev->rd_fet_subs) != NULL)
|
if ((layoutDev->rd_nterms >= 4) && ((subs = layoutDev->rd_fet_subs) != NULL))
|
||||||
{
|
{
|
||||||
if (subs->rn_name != NULL && notdecremented)
|
if (subs->rn_name != NULL && notdecremented)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,7 @@ ResMoveDevices(node1, node2)
|
||||||
devptr = devptr->te_nextt;
|
devptr = devptr->te_nextt;
|
||||||
if (device->rd_fet_gate == node1)
|
if (device->rd_fet_gate == node1)
|
||||||
device->rd_fet_gate = node2;
|
device->rd_fet_gate = node2;
|
||||||
else if (device->rd_fet_subs == node1)
|
else if ((device->rd_nterms >= 4) && (device->rd_fet_subs == node1))
|
||||||
device->rd_fet_subs = node2;
|
device->rd_fet_subs = node2;
|
||||||
else if (device->rd_fet_source == node1)
|
else if (device->rd_fet_source == node1)
|
||||||
device->rd_fet_source = node2;
|
device->rd_fet_source = node2;
|
||||||
|
|
|
||||||
170
select/selOps.c
170
select/selOps.c
|
|
@ -1216,13 +1216,21 @@ SelectTransform(transform)
|
||||||
SelectAndCopy2(EditRootDef);
|
SelectAndCopy2(EditRootDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Client data used by SelectExpand */
|
||||||
|
|
||||||
|
typedef struct selExpData {
|
||||||
|
int sed_mask; /* window mask */
|
||||||
|
int sed_type; /* DB_EXPAND, etc. */
|
||||||
|
Rect *sed_box; /* selection box if used, or NULL */
|
||||||
|
} SelExpData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* SelectExpand --
|
* SelectExpand --
|
||||||
*
|
*
|
||||||
* Expand all of the selected cells that are unexpanded, and
|
* Expand or unexpand all of the selected cells according to
|
||||||
* unexpand all of those that are expanded.
|
* expandType.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -1230,58 +1238,166 @@ SelectTransform(transform)
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* The contents of the selected cells will become visible or
|
* The contents of the selected cells will become visible or
|
||||||
* invisible on the display in the indicated window(s).
|
* invisible on the display in the indicated window(s).
|
||||||
|
* Both the cell in the layout and the selection are updated
|
||||||
|
* so that they are synchonized with respect to the state of
|
||||||
|
* visibility.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
SelectExpand(mask)
|
SelectExpand(mask, expandType, rootBox)
|
||||||
int mask; /* Bits of this word indicate which
|
int mask; /* Bits of this word indicate which
|
||||||
* windows the selected cells will be
|
* windows the selected cells will be
|
||||||
* expanded in.
|
* expanded in.
|
||||||
*/
|
*/
|
||||||
|
int expandType; /* Operation to perform: Expand,
|
||||||
|
* unexpand, or expand toggle.
|
||||||
|
*/
|
||||||
|
Rect *rootBox; /* Area of root box, if selecting by
|
||||||
|
* cursor box area.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
extern int selExpandFunc(); /* Forward reference. */
|
/* Forward references */
|
||||||
|
extern int selExpandFunc();
|
||||||
|
|
||||||
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
|
SelExpData sed;
|
||||||
selExpandFunc, INT2CD(mask));
|
|
||||||
|
sed.sed_type = expandType;
|
||||||
|
sed.sed_box = rootBox;
|
||||||
|
sed.sed_mask = mask;
|
||||||
|
|
||||||
|
if (rootBox != NULL)
|
||||||
|
{
|
||||||
|
SearchContext scx;
|
||||||
|
|
||||||
|
scx.scx_use = SelectUse;
|
||||||
|
scx.scx_area = *rootBox;
|
||||||
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
||||||
|
SelEnumCells(FALSE, (bool *) NULL, &scx, selExpandFunc, &sed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelEnumCells(FALSE, (bool *) NULL, (SearchContext *)NULL,
|
||||||
|
selExpandFunc, &sed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
selExpandFunc(selUse, use, transform, mask)
|
selExpandFunc(selUse, use, transform, sed)
|
||||||
CellUse *selUse; /* Use from selection. */
|
CellUse *selUse; /* Use from selection. */
|
||||||
CellUse *use; /* Use to expand (in actual layout). */
|
CellUse *use; /* Use to expand (in actual layout). */
|
||||||
Transform *transform; /* Not used. */
|
Transform *transform; /* Not used. */
|
||||||
int mask; /* Windows in which to expand. */
|
SelExpData *sed; /* Information for expansion */
|
||||||
{
|
{
|
||||||
/* Don't change expansion status of root cell: screws up
|
int expandType = sed->sed_type;
|
||||||
* DBWAreaChanged (need to always have at least top-level
|
int mask = sed->sed_mask;
|
||||||
* cell be expanded).
|
Rect *rootBox = sed->sed_box;
|
||||||
*/
|
|
||||||
|
|
||||||
if (use->cu_parent == NULL)
|
/* If a rootBox is provided, then we are here trying to sync the
|
||||||
|
* cells in the selection to those in the edit cell. Need to
|
||||||
|
* follow the policy of expandType: If DB_EXPAND_SURROUND, then
|
||||||
|
* selUse must be inside the rootBox. If DB_EXPAND_OVERLAP, then
|
||||||
|
* selUse must ovelap the rootBox.
|
||||||
|
*/
|
||||||
|
if (rootBox != NULL)
|
||||||
{
|
{
|
||||||
TxError("Can't unexpand root cell of window.\n");
|
if ((expandType & DB_EXPAND_SURROUND_MASK) == DB_EXPAND_OVERLAP)
|
||||||
return 0;
|
{
|
||||||
|
if (!GEO_OVERLAP(rootBox, &selUse->cu_bbox))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else /* (expandType & DB_EXPAND_SURROUND_MASK) == DB_EXPAND_SURROUND */
|
||||||
|
{
|
||||||
|
if (!GEO_SURROUND(rootBox, &selUse->cu_bbox))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Be sure to modify the expansion bit in the selection as well as
|
/* If a rootBox was given, then the expansion is being done in the
|
||||||
* the one in the layout in order to keep them consistent.
|
* edit cell, and the selection is being updated to reflect any
|
||||||
|
* changes there, so only handle the selection. Otherwise, we
|
||||||
|
* have to sync the corresponding cells in the edit def here.
|
||||||
*/
|
*/
|
||||||
|
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND)
|
||||||
if (DBDescendSubcell(use, mask))
|
|
||||||
{
|
{
|
||||||
DBExpand(selUse, mask, FALSE);
|
/* Be sure to modify the expansion bit in the selection as well as
|
||||||
DBExpand(use, mask, FALSE);
|
* the one in the layout in order to keep them consistent.
|
||||||
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask,
|
*/
|
||||||
(TileTypeBitMask *) NULL);
|
DBExpand(selUse, mask, DB_EXPAND);
|
||||||
|
if (!rootBox)
|
||||||
|
{
|
||||||
|
DBExpand(use, mask, DB_EXPAND);
|
||||||
|
if (use->cu_parent == NULL)
|
||||||
|
DBWAreaChanged(use->cu_def, &use->cu_bbox, mask, &DBAllButSpaceBits);
|
||||||
|
else
|
||||||
|
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if ((expandType & DB_EXPAND_MASK) == DB_UNEXPAND)
|
||||||
{
|
{
|
||||||
DBExpand(selUse, mask, TRUE);
|
/* Don't change expansion status of root cell: screws up
|
||||||
DBExpand(use, mask, TRUE);
|
* DBWAreaChanged (need to always have at least top-level
|
||||||
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits);
|
* cell be expanded).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((use->cu_parent == NULL) && !rootBox)
|
||||||
|
{
|
||||||
|
TxError("Can't unexpand root cell of window.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use->cu_parent != NULL)
|
||||||
|
{
|
||||||
|
/* Be sure to modify the expansion bit in the selection as well as
|
||||||
|
* the one in the layout in order to keep them consistent.
|
||||||
|
*/
|
||||||
|
DBExpand(selUse, mask, DB_UNEXPAND);
|
||||||
|
if (!rootBox)
|
||||||
|
{
|
||||||
|
DBExpand(use, mask, DB_UNEXPAND);
|
||||||
|
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask,
|
||||||
|
(TileTypeBitMask *) NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* (expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE */
|
||||||
|
{
|
||||||
|
/* Don't change expansion status of root cell: screws up
|
||||||
|
* DBWAreaChanged (need to always have at least top-level
|
||||||
|
* cell be expanded).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (use->cu_parent == NULL)
|
||||||
|
{
|
||||||
|
if (!rootBox) TxError("Can't unexpand root cell of window.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Be sure to modify the expansion bit in the selection as well as
|
||||||
|
* the one in the layout in order to keep them consistent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (DBDescendSubcell(selUse, mask))
|
||||||
|
{
|
||||||
|
DBExpand(selUse, mask, DB_UNEXPAND);
|
||||||
|
if (!rootBox)
|
||||||
|
{
|
||||||
|
DBExpand(use, mask, DB_UNEXPAND);
|
||||||
|
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask,
|
||||||
|
(TileTypeBitMask *) NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpand(selUse, mask, DB_EXPAND);
|
||||||
|
if (!rootBox)
|
||||||
|
{
|
||||||
|
DBExpand(use, mask, DB_EXPAND);
|
||||||
|
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,10 @@ proc magic::make_texthelper { mgrpath } {
|
||||||
proc magic::analyze_labels {} {
|
proc magic::analyze_labels {} {
|
||||||
global typedflt typesticky typeport
|
global typedflt typesticky typeport
|
||||||
|
|
||||||
|
# Ensure units of microns
|
||||||
|
set curunits [units]
|
||||||
|
units microns
|
||||||
|
|
||||||
# Pick up values from the first entry returned
|
# Pick up values from the first entry returned
|
||||||
|
|
||||||
set tval [lindex [setlabel text] 0]
|
set tval [lindex [setlabel text] 0]
|
||||||
|
|
@ -157,6 +161,7 @@ proc magic::analyze_labels {} {
|
||||||
set oval [lindex [setlabel offset] 0]
|
set oval [lindex [setlabel offset] 0]
|
||||||
set lval [lindex [setlabel layer] 0]
|
set lval [lindex [setlabel layer] 0]
|
||||||
set kval [lindex [setlabel sticky] 0]
|
set kval [lindex [setlabel sticky] 0]
|
||||||
|
set sval [lindex [setlabel size] 0]
|
||||||
set isport [lindex [port exists] 0]
|
set isport [lindex [port exists] 0]
|
||||||
if {$isport} {
|
if {$isport} {
|
||||||
set pval [lindex [port index] 0]
|
set pval [lindex [port index] 0]
|
||||||
|
|
@ -164,14 +169,6 @@ proc magic::analyze_labels {} {
|
||||||
set pval -1
|
set pval -1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Rescale internal units to microns
|
|
||||||
set sval [lindex [setlabel size] 0]
|
|
||||||
set sscale [cif scale out]
|
|
||||||
set tmp_pre $::tcl_precision
|
|
||||||
set ::tcl_precision 3
|
|
||||||
set sval [expr $sscale * $sval]
|
|
||||||
set ::tcl_precision $tmp_pre
|
|
||||||
|
|
||||||
.texthelper.text.tent delete 0 end
|
.texthelper.text.tent delete 0 end
|
||||||
.texthelper.text.tent insert 0 $tval
|
.texthelper.text.tent insert 0 $tval
|
||||||
set jbtn [string map {NORTH N WEST W SOUTH S EAST E CENTER center} $jval]
|
set jbtn [string map {NORTH N WEST W SOUTH S EAST E CENTER center} $jval]
|
||||||
|
|
@ -206,6 +203,9 @@ proc magic::analyze_labels {} {
|
||||||
pack .texthelper.layer.tent -side left -fill x -expand true
|
pack .texthelper.layer.tent -side left -fill x -expand true
|
||||||
pack .texthelper.layer.btn2 -side left
|
pack .texthelper.layer.btn2 -side left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Revert units
|
||||||
|
units {*}$curunits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -220,6 +220,9 @@ proc magic::change_label {} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set curunits [units]
|
||||||
|
units microns
|
||||||
|
|
||||||
set ltext [.texthelper.text.tent get]
|
set ltext [.texthelper.text.tent get]
|
||||||
set lfont [.texthelper.font.btn cget -text]
|
set lfont [.texthelper.font.btn cget -text]
|
||||||
set lsize [.texthelper.size.tent get]
|
set lsize [.texthelper.size.tent get]
|
||||||
|
|
@ -247,13 +250,10 @@ proc magic::change_label {} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if {$lsize != ""} {
|
if {$lsize != ""} {
|
||||||
setlabel size ${lsize}um
|
setlabel size $lsize
|
||||||
}
|
}
|
||||||
if {$loff != ""} {
|
if {$loff != ""} {
|
||||||
set oldunits [units]
|
|
||||||
units internal
|
|
||||||
setlabel offset [join $loff]
|
setlabel offset [join $loff]
|
||||||
units $oldunits
|
|
||||||
}
|
}
|
||||||
if {$lrot != ""} {
|
if {$lrot != ""} {
|
||||||
setlabel rotate $lrot
|
setlabel rotate $lrot
|
||||||
|
|
@ -274,6 +274,8 @@ proc magic::change_label {} {
|
||||||
port remove
|
port remove
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
units {*}$curunits
|
||||||
}
|
}
|
||||||
|
|
||||||
proc magic::make_new_label {} {
|
proc magic::make_new_label {} {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@
|
||||||
# March 26, 2026
|
# March 26, 2026
|
||||||
# Added behavior to handle ideal devices (resistor, capacitor,
|
# Added behavior to handle ideal devices (resistor, capacitor,
|
||||||
# inductor)
|
# inductor)
|
||||||
|
# April 2, 2026
|
||||||
|
# Changed the hash to MurmurHash3, as the existing hash
|
||||||
|
# is prone to creating name collisions (rare, but not rare
|
||||||
|
# enough).
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
# Sets up the environment for a toolkit. The toolkit must
|
# Sets up the environment for a toolkit. The toolkit must
|
||||||
# supply a namespace that is the "library name". For each
|
# supply a namespace that is the "library name". For each
|
||||||
|
|
@ -205,7 +209,7 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
select cell $inst
|
select cell $inst
|
||||||
delete
|
delete
|
||||||
}
|
}
|
||||||
cellname delete $child
|
cellname delete $child -noprompt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -844,11 +848,16 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
set pdefaults [${library}::${gencell_type}_defaults]
|
set pdefaults [${library}::${gencell_type}_defaults]
|
||||||
# Pull user-entered values from dialog
|
# Pull user-entered values from dialog
|
||||||
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
|
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
|
||||||
set newinstname [.params.title.ient get]
|
|
||||||
if {$newinstname == "(default)"} {set newinstname $instname}
|
|
||||||
if {$newinstname == $instname} {set newinstname $instname}
|
|
||||||
if {[instance list exists $newinstname] != ""} {set newinstname $instname}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Attempt to set the new instance name as specified in the dialog.
|
||||||
|
# If the entry is "(default)" or if there is a name collision,
|
||||||
|
# revert the name to the original name.
|
||||||
|
|
||||||
|
set newinstname [.params.title.ient get]
|
||||||
|
if {$newinstname == "(default)"} {set newinstname $instname}
|
||||||
|
if {[instance list exists $newinstname] != ""} {set newinstname $instname}
|
||||||
|
|
||||||
if {[dict exists $parameters gencell]} {
|
if {[dict exists $parameters gencell]} {
|
||||||
# Setting special parameter "gencell" forces the gencell to change type
|
# Setting special parameter "gencell" forces the gencell to change type
|
||||||
set gencell_type [dict get $parameters gencell]
|
set gencell_type [dict get $parameters gencell]
|
||||||
|
|
@ -866,6 +875,20 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
set gsuffix [magic::get_gencell_hash ${parameters}]
|
set gsuffix [magic::get_gencell_hash ${parameters}]
|
||||||
set gname ${gencell_type}_${gsuffix}
|
set gname ${gencell_type}_${gsuffix}
|
||||||
|
|
||||||
|
# Handle instance name changing first. If no parameters changed, then
|
||||||
|
# we're done.
|
||||||
|
if {$newinstname != $instname} {
|
||||||
|
identify $newinstname
|
||||||
|
# The buttons "Apply" and "Okay" need to be changed for the new
|
||||||
|
# instance name
|
||||||
|
catch {.params.buttons.apply config -command \
|
||||||
|
"magic::gencell_change $newinstname $gencell_type $library {}"}
|
||||||
|
catch {.params.buttons.okay config -command \
|
||||||
|
"magic::gencell_change $newinstname $gencell_type $library {} ;\
|
||||||
|
destroy .params"}
|
||||||
|
set instname $newinstname
|
||||||
|
}
|
||||||
|
|
||||||
# Guard against instance having been deleted. Also, if parameters have not
|
# Guard against instance having been deleted. Also, if parameters have not
|
||||||
# changed as evidenced by the cell suffix not changing, then nothing further
|
# changed as evidenced by the cell suffix not changing, then nothing further
|
||||||
# needs to be done.
|
# needs to be done.
|
||||||
|
|
@ -901,31 +924,9 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
if {$abox != ""} {box values {*}$abox}
|
if {$abox != ""} {box values {*}$abox}
|
||||||
set newinstname [getcell $gname $orient]
|
set newinstname [getcell $gname $orient]
|
||||||
select cell $newinstname
|
select cell $newinstname
|
||||||
|
set origname $newinstname
|
||||||
expand
|
expand
|
||||||
|
|
||||||
# If the old instance name was not formed from the old cell name,
|
|
||||||
# then keep the old instance name.
|
|
||||||
if {[string first $old_gname $instname] != 0} {
|
|
||||||
set newinstname $instname
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[cellname list parents $old_gname] == []} {
|
|
||||||
# If the original cell has no intances left, delete it. It can
|
|
||||||
# be regenerated if and when necessary.
|
|
||||||
cellname delete $old_gname
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
select cell $instname
|
|
||||||
set orient [instance list orientation]
|
|
||||||
set abox [instance list abutment]
|
|
||||||
delete
|
|
||||||
|
|
||||||
# There is no cell of this name, so generate one and instantiate it.
|
|
||||||
if {$abox != ""} {box values {*}$abox}
|
|
||||||
set newinstname [magic::gencell_create $gencell_type $library $parameters $orient]
|
|
||||||
select cell $newinstname
|
|
||||||
|
|
||||||
# If the old instance name was not formed from the old cell name,
|
# If the old instance name was not formed from the old cell name,
|
||||||
# then keep the old instance name.
|
# then keep the old instance name.
|
||||||
if {[string first $old_gname $instname] != 0} {
|
if {[string first $old_gname $instname] != 0} {
|
||||||
|
|
@ -939,6 +940,47 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
"magic::gencell_change $newinstname $gencell_type $library {} ;\
|
"magic::gencell_change $newinstname $gencell_type $library {} ;\
|
||||||
destroy .params"}
|
destroy .params"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if {[cellname list parents $old_gname] == []} {
|
||||||
|
# If the original cell has no intances left, delete it. It can
|
||||||
|
# be regenerated if and when necessary.
|
||||||
|
cellname delete $old_gname -noprompt
|
||||||
|
select cell $origname
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
select cell $instname
|
||||||
|
set orient [instance list orientation]
|
||||||
|
set abox [instance list abutment]
|
||||||
|
delete
|
||||||
|
|
||||||
|
# There is no cell of this name, so generate one and instantiate it.
|
||||||
|
if {$abox != ""} {box values {*}$abox}
|
||||||
|
set newinstname [magic::gencell_create $gencell_type $library $parameters $orient]
|
||||||
|
select cell $newinstname
|
||||||
|
set origname $newinstname
|
||||||
|
|
||||||
|
# If the old instance name was not formed from the old cell name,
|
||||||
|
# then keep the old instance name.
|
||||||
|
if {[string first $old_gname $instname] != 0} {
|
||||||
|
set newinstname $instname
|
||||||
|
} else {
|
||||||
|
# The buttons "Apply" and "Okay" need to be changed for the new
|
||||||
|
# instance name
|
||||||
|
catch {.params.buttons.apply config -command \
|
||||||
|
"magic::gencell_change $newinstname $gencell_type $library {}"}
|
||||||
|
catch {.params.buttons.okay config -command \
|
||||||
|
"magic::gencell_change $newinstname $gencell_type $library {} ;\
|
||||||
|
destroy .params"}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If the old cell is not used anywhere, delete it
|
||||||
|
if {[cellname list parents $old_gname] == []} {
|
||||||
|
# If the original cell has no intances left, delete it. It can
|
||||||
|
# be regenerated if and when necessary.
|
||||||
|
cellname delete $old_gname -noprompt
|
||||||
|
select cell $origname
|
||||||
|
}
|
||||||
}
|
}
|
||||||
identify $newinstname
|
identify $newinstname
|
||||||
eval "box values $savebox"
|
eval "box values $savebox"
|
||||||
|
|
@ -1069,38 +1111,47 @@ proc magic::get_gencell_name {gencell_type} {
|
||||||
# gives a result that is repeatable for the same set of
|
# gives a result that is repeatable for the same set of
|
||||||
# parameter values with a very low probability of a collision.
|
# parameter values with a very low probability of a collision.
|
||||||
#
|
#
|
||||||
# The hash function is similar to elfhash but reduced from 32
|
# The hash function is murmur3 but reduced from 32 to 30 bits
|
||||||
# to 30 bits so that the result can form a 6-character value
|
# so that the result can form a 6-character value in base36
|
||||||
# in base32 with all characters being valid for a SPICE subcell
|
# with all characters being valid for a SPICE subcell name
|
||||||
# name (e.g., alphanumeric only and case-insensitive).
|
# (e.g., alphanumeric only and case-insensitive). This
|
||||||
|
# reduces the space from ~4 billion unique suffixes to ~1
|
||||||
|
# billion; however, even a complex mixed-signal chip design
|
||||||
|
# is unlikely to have more than a few hundred unique parameter
|
||||||
|
# sets for any given device.
|
||||||
|
#
|
||||||
|
# Code courtesy of ChatGPT, derived from my implementation.
|
||||||
#----------------------------------------------------------------
|
#----------------------------------------------------------------
|
||||||
|
|
||||||
proc magic::get_gencell_hash {parameters} {
|
proc magic::get_gencell_hash {parameters} {
|
||||||
set hash 0
|
# Canonicalize: sort by key
|
||||||
# Apply hash
|
set keys [lsort [dict keys $parameters]]
|
||||||
dict for {key value} $parameters {
|
|
||||||
foreach s [split $value {}] {
|
# Build input string (values only, but delimited)
|
||||||
set hash [expr {($hash << 4) + [scan $s %c]}]
|
set input ""
|
||||||
set high [expr {$hash & 0x03c0000000}]
|
foreach k $keys {
|
||||||
set hash [expr {$hash ^ ($high >> 30)}]
|
set value [magic::normalize_value [dict get $parameters $k]]
|
||||||
set hash [expr {$hash & (~$high)}]
|
append input "${value};"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
# Divide hash up into 5 bit values and convert to base32
|
|
||||||
# using letters A-Z less I and O, and digits 2-9.
|
# Compute Murmur hash
|
||||||
|
set hash [magic::murmur3_32 $input]
|
||||||
|
|
||||||
|
# Convert to 6-character base32
|
||||||
set cvals ""
|
set cvals ""
|
||||||
for {set i 0} {$i < 6} {incr i} {
|
for {set i 0} {$i < 6} {incr i} {
|
||||||
set oval [expr {($hash >> ($i * 5)) & 0x1f}]
|
set oval [expr {($hash >> ($i * 5)) & 0x1f}]
|
||||||
|
|
||||||
if {$oval < 8} {
|
if {$oval < 8} {
|
||||||
set bval [expr {$oval + 50}]
|
set bval [expr {$oval + 50}] ;# '2'-'9'
|
||||||
} elseif {$oval < 16} {
|
} elseif {$oval < 16} {
|
||||||
set bval [expr {$oval + 57}]
|
set bval [expr {$oval + 57}] ;# 'A'-'H'
|
||||||
} elseif {$oval < 21} {
|
} elseif {$oval < 21} {
|
||||||
set bval [expr {$oval + 58}]
|
set bval [expr {$oval + 58}] ;# 'J'-'N'
|
||||||
} else {
|
} else {
|
||||||
set bval [expr {$oval + 59}]
|
set bval [expr {$oval + 59}] ;# 'P'-'Z'
|
||||||
}
|
}
|
||||||
append cvals [binary format c* $bval]
|
append cvals [binary format c* $bval]
|
||||||
}
|
}
|
||||||
return $cvals
|
return $cvals
|
||||||
}
|
}
|
||||||
|
|
@ -1248,6 +1299,11 @@ proc magic::add_check_callbacks {gencell_type library} {
|
||||||
# A final default dependency will be added to all entries
|
# A final default dependency will be added to all entries
|
||||||
# to run the "check" procedure for the device. Dependencies
|
# to run the "check" procedure for the device. Dependencies
|
||||||
# that are more targeted get run first.
|
# that are more targeted get run first.
|
||||||
|
#
|
||||||
|
# NOTE: The "check" procedure must be the first in the
|
||||||
|
# list, as otherwise, any invalid entry that is corrected
|
||||||
|
# by the check callback will have been used to evaluate
|
||||||
|
# dependent values.
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
||||||
proc magic::add_dependency {callback gencell_type library args} {
|
proc magic::add_dependency {callback gencell_type library args} {
|
||||||
|
|
@ -1304,13 +1360,13 @@ proc magic::update_dialog {callback pname gencell_type library} {
|
||||||
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
|
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
|
||||||
}
|
}
|
||||||
|
|
||||||
if {$callback != {}} {
|
|
||||||
set parameters [$callback $pname $parameters]
|
|
||||||
}
|
|
||||||
if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \
|
if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \
|
||||||
checkerr]} {
|
checkerr]} {
|
||||||
puts stderr $checkerr
|
puts stderr $checkerr
|
||||||
}
|
}
|
||||||
|
if {$callback != {}} {
|
||||||
|
set parameters [$callback $pname $parameters]
|
||||||
|
}
|
||||||
magic::gencell_setparams $parameters
|
magic::gencell_setparams $parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1674,3 +1730,99 @@ proc magic::gencell_dialog {instname gencell_type library parameters} {
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------
|
#-------------------------------------------------------------
|
||||||
|
# Implementation of murmur3 hash, 32 bits
|
||||||
|
# Code courtesy of ChatGPT.
|
||||||
|
#-------------------------------------------------------------
|
||||||
|
|
||||||
|
proc magic::murmur3_32 {key {seed 0}} {
|
||||||
|
set length [string length $key]
|
||||||
|
|
||||||
|
set c1 0xcc9e2d51
|
||||||
|
set c2 0x1b873593
|
||||||
|
|
||||||
|
set h1 $seed
|
||||||
|
|
||||||
|
# Body (process 4 bytes at a time)
|
||||||
|
set nblocks [expr {$length / 4}]
|
||||||
|
for {set i 0} {$i < $nblocks} {incr i} {
|
||||||
|
binary scan [string range $key [expr {$i*4}] [expr {$i*4+3}]] i k1
|
||||||
|
|
||||||
|
set k1 [expr {($k1 * $c1) & 0xffffffff}]
|
||||||
|
set k1 [expr {(($k1 << 15) | (($k1 & 0xffffffff) >> 17)) & 0xffffffff}]
|
||||||
|
set k1 [expr {($k1 * $c2) & 0xffffffff}]
|
||||||
|
|
||||||
|
set h1 [expr {$h1 ^ $k1}]
|
||||||
|
set h1 [expr {(($h1 << 13) | (($h1 & 0xffffffff) >> 19)) & 0xffffffff}]
|
||||||
|
set h1 [expr {(($h1 * 5) + 0xe6546b64) & 0xffffffff}]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tail
|
||||||
|
set k1 0
|
||||||
|
set tail_index [expr {$nblocks * 4}]
|
||||||
|
set tail [string range $key $tail_index end]
|
||||||
|
set remaining [string length $tail]
|
||||||
|
|
||||||
|
if {$remaining >= 3} {
|
||||||
|
binary scan [string index $tail 2] c b
|
||||||
|
set k1 [expr {$k1 ^ (($b & 0xff) << 16)}]
|
||||||
|
}
|
||||||
|
if {$remaining >= 2} {
|
||||||
|
binary scan [string index $tail 1] c b
|
||||||
|
set k1 [expr {$k1 ^ (($b & 0xff) << 8)}]
|
||||||
|
}
|
||||||
|
if {$remaining >= 1} {
|
||||||
|
binary scan [string index $tail 0] c b
|
||||||
|
set k1 [expr {$k1 ^ ($b & 0xff)}]
|
||||||
|
set k1 [expr {($k1 * $c1) & 0xffffffff}]
|
||||||
|
set k1 [expr {(($k1 << 15) | (($k1 & 0xffffffff) >> 17)) & 0xffffffff}]
|
||||||
|
set k1 [expr {($k1 * $c2) & 0xffffffff}]
|
||||||
|
set h1 [expr {$h1 ^ $k1}]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Finalization (fmix)
|
||||||
|
set h1 [expr {$h1 ^ $length}]
|
||||||
|
set h1 [expr {$h1 ^ (($h1 & 0xffffffff) >> 16)}]
|
||||||
|
set h1 [expr {($h1 * 0x85ebca6b) & 0xffffffff}]
|
||||||
|
set h1 [expr {$h1 ^ (($h1 & 0xffffffff) >> 13)}]
|
||||||
|
set h1 [expr {($h1 * 0xc2b2ae35) & 0xffffffff}]
|
||||||
|
set h1 [expr {$h1 ^ (($h1 & 0xffffffff) >> 16)}]
|
||||||
|
|
||||||
|
return $h1
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------
|
||||||
|
# Numerical normalization: Avoid having different suffixes
|
||||||
|
# for cells with the same parameter values due to Tcl handling
|
||||||
|
# numerical values as strings, which makes "2", "2.0", and "2e0"
|
||||||
|
# all separate values. If hashed on the verbatim values, then
|
||||||
|
# the same device with the same parameters can have many
|
||||||
|
# different cell names, even though the layout is exactly the
|
||||||
|
# same. Avoid this by detecting when a parameter value is
|
||||||
|
# numeric and enforcing a consistent format (fixed precision,
|
||||||
|
# four decimal places).
|
||||||
|
#
|
||||||
|
# Code courtesy of ChatGPT
|
||||||
|
#-------------------------------------------------------------
|
||||||
|
|
||||||
|
proc magic::normalize_value {value} {
|
||||||
|
# Detect if value is numeric
|
||||||
|
if {[string is double -strict $value]} {
|
||||||
|
set num [expr {double($value)}]
|
||||||
|
|
||||||
|
# Check if effectively integer
|
||||||
|
if {abs($num - round($num)) < 1e-9} {
|
||||||
|
return [format "%d" [expr {int(round($num))}]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Otherwise, format to fixed precision (3 decimal places)
|
||||||
|
set str [format "%.3f" $num]
|
||||||
|
|
||||||
|
# Strip trailing zeros
|
||||||
|
regsub {\.?0+$} $str "" str
|
||||||
|
|
||||||
|
return $str
|
||||||
|
}
|
||||||
|
|
||||||
|
# Non-numeric: return as-is
|
||||||
|
return $value
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -534,8 +534,11 @@ proc magic::enable_tools {} {
|
||||||
# The user can change these bindings at will by using the
|
# The user can change these bindings at will by using the
|
||||||
# "macro" command when the tool is active.
|
# "macro" command when the tool is active.
|
||||||
|
|
||||||
|
# NOTE: Do not name a tool "netlist" because it will get
|
||||||
|
# confused with the "netlist" window.
|
||||||
|
|
||||||
magic::macro copy wiring
|
magic::macro copy wiring
|
||||||
magic::macro copy netlist
|
magic::macro copy nettool
|
||||||
magic::macro copy pick
|
magic::macro copy pick
|
||||||
|
|
||||||
magic::tool wiring
|
magic::tool wiring
|
||||||
|
|
@ -549,7 +552,7 @@ proc magic::enable_tools {} {
|
||||||
macro Button4 "wire incr width ; wire show"
|
macro Button4 "wire incr width ; wire show"
|
||||||
macro Button5 "wire decr width ; wire show"
|
macro Button5 "wire decr width ; wire show"
|
||||||
|
|
||||||
magic::tool netlist
|
magic::tool nettool
|
||||||
macro Button1 "netlist select"
|
macro Button1 "netlist select"
|
||||||
macro Button2 "netlist join"
|
macro Button2 "netlist join"
|
||||||
macro Button3 "netlist terminal"
|
macro Button3 "netlist terminal"
|
||||||
|
|
@ -704,8 +707,8 @@ proc magic::tool {{type next}} {
|
||||||
if {$type == "next"} {
|
if {$type == "next"} {
|
||||||
switch $Opts(tool) {
|
switch $Opts(tool) {
|
||||||
box { set type wiring }
|
box { set type wiring }
|
||||||
wiring { set type netlist }
|
wiring { set type nettool }
|
||||||
netlist { set type pick }
|
nettool { set type pick }
|
||||||
pick { set type box }
|
pick { set type box }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -761,9 +764,9 @@ proc magic::tool {{type next}} {
|
||||||
set Opts(tool) wiring
|
set Opts(tool) wiring
|
||||||
cursor 19 ;# sets the cursor
|
cursor 19 ;# sets the cursor
|
||||||
}
|
}
|
||||||
netlist {
|
nettool {
|
||||||
puts stdout {Switching to NETLIST tool.}
|
puts stdout {Switching to NETLIST tool.}
|
||||||
set Opts(tool) netlist
|
set Opts(tool) nettool
|
||||||
cursor 18 ;# sets the cursor
|
cursor 18 ;# sets the cursor
|
||||||
}
|
}
|
||||||
pick {
|
pick {
|
||||||
|
|
|
||||||
|
|
@ -1056,6 +1056,7 @@ windDoMacro(w, cmd, interactive)
|
||||||
bool do_help = FALSE;
|
bool do_help = FALSE;
|
||||||
bool do_reverse = FALSE;
|
bool do_reverse = FALSE;
|
||||||
char *searchterm = NULL;
|
char *searchterm = NULL;
|
||||||
|
char *clientName = NULL;
|
||||||
macrodef *cMacro;
|
macrodef *cMacro;
|
||||||
HashTable *clienttable;
|
HashTable *clienttable;
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
|
|
@ -1073,9 +1074,25 @@ windDoMacro(w, cmd, interactive)
|
||||||
|
|
||||||
argstart = 1;
|
argstart = 1;
|
||||||
if (cmd->tx_argc == 1)
|
if (cmd->tx_argc == 1)
|
||||||
wc = DBWclientID; /* Added by NP 11/15/04 */
|
wc = DBWclientID; /* Default client */
|
||||||
else if (cmd->tx_argc > 1)
|
else if (cmd->tx_argc > 1)
|
||||||
|
{
|
||||||
wc = WindGetClient(cmd->tx_argv[1], TRUE);
|
wc = WindGetClient(cmd->tx_argv[1], TRUE);
|
||||||
|
if (wc != NULL)
|
||||||
|
{
|
||||||
|
clientName = cmd->tx_argv[1];
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check if argument is a known layout button handler */
|
||||||
|
if (DBWButtonHandlerIndex(cmd->tx_argv[1]) != -1)
|
||||||
|
{
|
||||||
|
clientName = cmd->tx_argv[1];
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (cmd->tx_argc > argstart)
|
while (cmd->tx_argc > argstart)
|
||||||
{
|
{
|
||||||
|
|
@ -1116,6 +1133,15 @@ windDoMacro(w, cmd, interactive)
|
||||||
wc = DBWclientID;
|
wc = DBWclientID;
|
||||||
}
|
}
|
||||||
MacroCopy(wc, cmd->tx_argv[argstart]);
|
MacroCopy(wc, cmd->tx_argv[argstart]);
|
||||||
|
|
||||||
|
/* If tool name did not previously exist, then add
|
||||||
|
* it to the list of known tool names, so that it
|
||||||
|
* can be found later by the "macro" command.
|
||||||
|
*/
|
||||||
|
if (DBWButtonHandlerIndex(cmd->tx_argv[argstart]) == -1)
|
||||||
|
DBWAddButtonHandler(cmd->tx_argv[argstart],
|
||||||
|
(const cb_database_buttonhandler_t)NULL,
|
||||||
|
0, (const char *)NULL);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1147,26 +1173,53 @@ windDoMacro(w, cmd, interactive)
|
||||||
|
|
||||||
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
|
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
|
||||||
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
|
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
|
||||||
{
|
|
||||||
wc = 0;
|
|
||||||
argstart++;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
argstart++;
|
/* If a clientName wasn't given, but wc is DBWclientID, then get
|
||||||
|
* the clientName from the default button handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((clientName == NULL) && (wc == DBWclientID))
|
||||||
|
clientName = DBWGetButtonHandler();
|
||||||
|
|
||||||
if (cmd->tx_argc == argstart)
|
if (cmd->tx_argc == argstart)
|
||||||
{
|
{
|
||||||
if (wc == (WindClient)0)
|
if (clientName == NULL)
|
||||||
|
h = NULL;
|
||||||
|
else
|
||||||
|
h = HashLookOnly(&MacroClients, (char *)clientName);
|
||||||
|
|
||||||
|
if (h == NULL)
|
||||||
{
|
{
|
||||||
TxError("No such client.\n");
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *lobj;
|
||||||
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
#endif
|
||||||
|
TxError("Cannot get macro list from current window.\n");
|
||||||
|
#ifndef MAGIC_WRAPPER
|
||||||
|
TxError("List of known macro clients:\n");
|
||||||
|
#endif
|
||||||
|
/* If clientName was not in MacroClients, then what is? */
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while ((h = HashNext(&MacroClients, &hs)) != NULL)
|
||||||
|
{
|
||||||
|
char *clientName = h->h_key.h_name;
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(clientName, -1));
|
||||||
|
#else
|
||||||
|
TxError("%s ", clientName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
|
#else
|
||||||
|
TxError("\n");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
h = HashLookOnly(&MacroClients, (char *)wc);
|
|
||||||
if (h == NULL)
|
|
||||||
return;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clienttable = (HashTable *)HashGetValue(h);
|
clienttable = (HashTable *)HashGetValue(h);
|
||||||
|
|
|
||||||
|
|
@ -954,7 +954,7 @@ windXviewCmd(w, cmd)
|
||||||
|
|
||||||
celluse = (CellUse *) (w->w_surfaceID);
|
celluse = (CellUse *) (w->w_surfaceID);
|
||||||
DBExpandAll(celluse, &(celluse->cu_bbox),
|
DBExpandAll(celluse, &(celluse->cu_bbox),
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask, FALSE,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask, DB_UNEXPAND,
|
||||||
ViewUnexpandFunc,
|
ViewUnexpandFunc,
|
||||||
(ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));
|
(ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue