Compare commits

..

No commits in common. "master" and "8.3.617" have entirely different histories.

72 changed files with 850 additions and 2326 deletions

View File

@ -138,8 +138,6 @@ jobs:
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
sudo apt-get update
if [ -n "$BUILD_GCC_VERSION" ]
then
GCCV=$BUILD_GCC_VERSION

View File

@ -33,22 +33,10 @@ jobs:
cd emsdk
./emsdk install latest
./emsdk activate latest
- name: Emscripten Diagnostic
run: |
source ./emsdk/emsdk_env.sh
echo "===== gcc -dM -E - ====="
echo | gcc -dM -E - | sort
echo "===== g++ -dM -E - ====="
echo | g++ -dM -E - | sort
echo "===== emcc -dM -E - ====="
echo | emcc -dM -E - | sort
echo "===== em++ -dM -E - ====="
echo | em++ -dM -E - | sort
- name: Build
run: |
source ./emsdk/emsdk_env.sh
# The --without and --disable in these build options is due to no WASM library being available for that feature
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="

View File

@ -10,6 +10,19 @@ on:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
vezzal:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Pulling the docker image
run: docker pull vezzal/vezzal:v1
- name: Start the container with the docker image
run: docker run -id --name test_magic vezzal/vezzal:v1 bash | exit
- name: Run the testing on the container and send the mail
run: docker exec test_magic /vezzal/test_magic.sh "lankasaicharan123@gmail.com,tim@opencircuitdesign.com" ${{secrets.MAILING_KEY}}
simple_build_linux:
runs-on: ubuntu-22.04
steps:
@ -32,22 +45,10 @@ jobs:
cd emsdk
./emsdk install latest
./emsdk activate latest
- name: Emscripten Diagnostic
run: |
source ./emsdk/emsdk_env.sh
echo "===== gcc -dM -E - ====="
echo | gcc -dM -E - | sort
echo "===== g++ -dM -E - ====="
echo | g++ -dM -E - | sort
echo "===== emcc -dM -E - ====="
echo | emcc -dM -E - | sort
echo "===== em++ -dM -E - ====="
echo | em++ -dM -E - | sort
- name: Build
run: |
source ./emsdk/emsdk_env.sh
# The --without and --disable in these build options is due to no WASM library being available for that feature
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="

View File

@ -1 +1 @@
8.3.637
8.3.617

View File

@ -789,8 +789,8 @@ calmaElementSref(
char *filename)
{
int nbytes, rtype, cols, rows, nref, n, i, savescale;
int xlo, ylo, xhi, yhi, xsep, ysep, angle;
bool madeinst = FALSE, rotated = FALSE;
int xlo, ylo, xhi, yhi, xsep, ysep;
bool madeinst = FALSE;
char *sname = NULL;
bool isArray = FALSE;
bool dolookahead = FALSE;
@ -990,14 +990,6 @@ calmaElementSref(
refarray[2].p_x = refarray[2].p_y = 0;
}
/* If the array is given an angle, then the meaning of rows and
* columns needs to be swapped for the purpose of ignoring
* X or Y values in the case of a 1-row or 1-column entry.
*/
angle = GeoTransAngle(&trans, 0);
if ((angle == 90) || (angle == 270) || (angle == -90) || (angle == -270))
rotated = TRUE;
/* If this is a cell reference, then we scale to magic coordinates
* and place the cell in the magic database. However, if this is
* a cell to be flattened a la "gds flatten", then we keep the GDS
@ -1008,7 +1000,6 @@ calmaElementSref(
* is problematic, and probably incorrect.
*/
for (n = 0; n < nref; n++)
{
savescale = calmaReadScale1;
@ -1020,17 +1011,17 @@ calmaElementSref(
* them as needed.
*/
if ((n > 0) && ((!rotated && (rows == 1)) || (rotated && (cols == 1))))
if ((n > 0) && (rows == 1))
{
calmaReadX(&refarray[n], 1);
calmaSkipBytes(4);
refarray[n].p_y = refarray[0].p_y;
refarray[n].p_y = 0;
}
else if ((n > 0) && ((!rotated && (cols == 1)) || (rotated && (rows == 1))))
else if ((n > 0) && (cols == 1))
{
calmaSkipBytes(4);
calmaReadY(&refarray[n], 1);
refarray[n].p_x = refarray[0].p_x;
refarray[n].p_x = 0;
}
else
calmaReadPoint(&refarray[n], 1);

View File

@ -25,7 +25,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <stdlib.h> /* for abs() */
#include <math.h> /* for ceil() and sqrt() */
#include <ctype.h>
#include <string.h> /* for strcmp() */
#include "utils/magic.h"
#include "utils/geometry.h"
@ -5045,47 +5044,6 @@ cifInteractingRegions(
}
}
/*
* ----------------------------------------------------------------------------
*
* cifCopyPropPlaneFunc --
*
* Copy the contents of a plane saved as a plane-type property into the
* current CIF plane. The property plane is in magic internal
* coordinates, so each tile needs to be scaled and redrawn into the
* current CIF plane.
*
* Results:
* Zero to keep the search going
*
* Side effects:
* Copies translated geometry into the target plane.
*
* ----------------------------------------------------------------------------
*/
int
cifCopyPropPlaneFunc(Tile *tile,
TileType dinfo,
Plane *curPlane)
{
Rect bbox;
TiToRect(tile, &bbox);
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
bbox.r_xbot *= cifScale;
bbox.r_ybot *= cifScale;
bbox.r_xtop *= cifScale;
bbox.r_ytop *= cifScale;
cifScale = 1;
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
CIFPaintTable, (PaintUndoInfo *)NULL);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -5137,13 +5095,12 @@ CIFGenLayer(
CIFSquaresInfo csi;
SearchContext scx;
TileType ttype;
char *netname, *text;
Label *label;
char *netname;
BloatStruct bls;
BridgeStruct brs;
BridgeLimStruct brlims;
BridgeData *bridge;
BloatData *bloats, locbloat;
BloatData *bloats;
bool hstop = FALSE;
PropertyRecord *proprec;
char *propvalue;
@ -5462,12 +5419,9 @@ CIFGenLayer(
(ClientData)NULL);
}
else
{
TTMaskSetMask(&bls.connect, &op->co_paintMask);
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
(ClientData)NULL);
}
break;
@ -5606,108 +5560,6 @@ CIFGenLayer(
}
break;
case CIFOP_TAGGED:
if (hier)
{
hstop = TRUE; /* Stop hierarchical processing */
break;
}
/*
* Find all relevant labels by text matching and then continue
* like CIFOP_BLOATALL. CIFOP_BLOATALL uses a BloatData record
* which is not part of CIFOP_TAGGED. Create a BloatData record
* on the fly for each tagged area based on type, and swap it for
* the text, so that cifBloatAllFunc believes this is actually a
* CIFOP_BLOATALL operation. Note that we don't actually care
* what layer the label is attached to (lab_type). We are looking
* for labels whose lab_rect values overlap the types that are given
* in the rule.
*/
cifPlane = curPlane;
bls.op = op;
bls.def = cellDef;
bls.temps = temps;
text = (char *)op->co_client;
bloats = &locbloat;
if (!TTMaskIsZero(&op->co_cifMask))
{
bloats->bl_plane = -1;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_cifMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
else if (!TTMaskIsZero(&op->co_paintMask))
{
int plane, pmask;
pmask = DBTechTypesToPlanes(&op->co_paintMask);
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
if (PlaneMaskHasPlane(pmask, plane))
break;
bloats->bl_plane = plane;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_paintMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
/* Replace the client data with the bloat record */
op->co_client = (ClientData)bloats;
if (bloats->bl_plane < 0)
{
/* bl_plane == -1 indicates bloating into a CIF templayer, */
/* so the only connecting type should be CIF_SOLIDTYPE. */
TTMaskSetOnlyType(&bls.connect, CIF_SOLIDTYPE);
}
else
{
int i;
TTMaskZero(&bls.connect);
for (i = 0; i < TT_MAXTYPES; i++)
if (bloats->bl_distance[i] != 0)
TTMaskSetType(&bls.connect, i);
}
for (label = cellDef->cd_labels; label; label = label->lab_next)
if (!strcmp(label->lab_text, text))
cifSrTiles(op, &label->lab_rect, cellDef, temps,
cifBloatAllFunc, (ClientData)&bls);
/* Reset marked tiles */
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
{
bls.temps = temps;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++)
if (bloats->bl_distance[ttype] > 0)
(void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect,
&CIFSolidBits, cifProcessResetFunc,
(ClientData)NULL);
}
else
{
TTMaskSetMask(&bls.connect, &op->co_paintMask);
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
(ClientData)NULL);
}
/* Replace the client data */
op->co_client = (ClientData)text;
break;
case CIFOP_BOUNDARY:
if (hier)
{
@ -5794,7 +5646,6 @@ CIFGenLayer(
int n;
char propname[512];
char *layername = (char *)op->co_client;
Tile *t;
snprintf(propname, 512, "MASKHINTS_%s", layername);
@ -5802,11 +5653,30 @@ CIFGenLayer(
proprec = DBPropGet(cellDef, propname, &found);
if (!found) break; /* No mask hints available */
ASSERT (proprec->prop_type == PROPERTY_TYPE_PLANE, "CIFGenLayer");
t = PlaneGetHint(proprec->prop_value.prop_plane);
DBSrPaintArea(t, proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits,
cifCopyPropPlaneFunc, (ClientData)curPlane);
if (proprec->prop_type == PROPERTY_TYPE_DIMENSION)
{
for (n = 0; n < proprec->prop_len; n += 4)
{
if ((n + 3) >= proprec->prop_len) break;
cifPlane = curPlane;
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
bbox.r_xbot = proprec->prop_value.prop_integer[n];
bbox.r_ybot = proprec->prop_value.prop_integer[n + 1];
bbox.r_xtop = proprec->prop_value.prop_integer[n + 2];
bbox.r_ytop = proprec->prop_value.prop_integer[n + 3];
bbox.r_xbot *= cifScale;
bbox.r_ybot *= cifScale;
bbox.r_xtop *= cifScale;
bbox.r_ytop *= cifScale;
cifScale = 1;
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
CIFPaintTable, (PaintUndoInfo *)NULL);
}
}
}
break;

View File

@ -209,52 +209,16 @@ typedef struct _maskHintsData
{
Transform *mh_trans;
CellDef *mh_def;
Plane *mh_plane;
} MaskHintsData;
/*
* ----------------------------------------------------------------------------
*
* cifCopyMaskHintFunc --
*
* Callback function used by cifFlatMaskHints. Transforms a tile
* from the original plane and paints it into the target plane,
* both of which are properties.
*
* Results:
* Zero to keep the search going.
*
* Side effects:
* Paints geometry into the target plane.
*
* ----------------------------------------------------------------------------
*/
int
cifCopyMaskHintFunc(Tile *tile,
TileType dinfo,
ClientData cdata)
{
MaskHintsData *mhd = (MaskHintsData *)cdata;
Rect r, newr;
TiToRect(tile, &r);
/* Transform tile area to coordinates of mhd->mh_plane and paint */
GeoTransRect(mhd->mh_trans, &r, &newr);
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifFlatMaskHints --
*
* Copy a mask hint into a flattened cell by transforming it into the
* coordinate system of the flattened cell, and painting it into the
* property plane of the flattened cell.
* coordinate system of the flattened cell, and adding it to the
* property list of the flattened cell.
*
* Returns:
* 0 to keep the search going.
@ -276,7 +240,6 @@ cifFlatMaskHints(
bool propfound;
int i, lastlen, numvals;
PropertyRecord *newproprec, *oldproprec;
Plane *plane;
if (!strncmp(name, "MASKHINTS_", 10))
{
@ -284,24 +247,53 @@ cifFlatMaskHints(
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
if (propfound)
{
ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE,
"cifFlatMaskHints");
plane = oldproprec->prop_value.prop_plane;
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(oldproprec->prop_len + proprec->prop_len - 2) * sizeof(int));
newproprec->prop_len = oldproprec->prop_len + proprec->prop_len;
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
}
else
{
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
newproprec->prop_len = 0; /* (unused) */
newproprec->prop_type = PROPERTY_TYPE_PLANE;
plane = DBNewPlane((ClientData)TT_SPACE);
newproprec->prop_value.prop_plane = plane;
DBPropPut(mhd->mh_def, name, newproprec);
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proprec->prop_len - 2) * sizeof(int));
newproprec->prop_len = proprec->prop_len;
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
}
mhd->mh_plane = plane;
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits,
cifCopyMaskHintFunc, (ClientData)mhd);
for (i = 0; i < proprec->prop_len; i += 4)
{
/* There should be a multiple of 4 values but avoid an array overrun
* if not.
*/
if ((i + 3) >= proprec->prop_len)
{
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
name + 10, numvals);
break;
}
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
/* Transform rectangle to top level coordinates */
GeoTransRect(mhd->mh_trans, &r, &newr);
newproprec->prop_value.prop_integer[i] = newr.r_xbot;
newproprec->prop_value.prop_integer[i + 1] = newr.r_ybot;
newproprec->prop_value.prop_integer[i + 2] = newr.r_xtop;
newproprec->prop_value.prop_integer[i + 3] = newr.r_ytop;
}
/* If there were existing entries, copy them into the new property */
if (propfound)
{
for (i = 0; i < oldproprec->prop_len; i++)
newproprec->prop_value.prop_integer[i + proprec->prop_len] =
oldproprec->prop_value.prop_integer[i];
}
DBPropPut(mhd->mh_def, name, newproprec);
}
return 0;
}
@ -312,10 +304,9 @@ cifFlatMaskHints(
* CIFCopyMaskHints --
*
* Callback function to copy mask hints from one cell into another.
* (Occasionally called as a standalone function, not as a callback.)
*
* Results:
* Return 0 to keep the search going.
* None.
*
* Side effects:
* May modify properties in the target cell.
@ -323,7 +314,7 @@ cifFlatMaskHints(
* ----------------------------------------------------------------------------
*/
int
void
CIFCopyMaskHints(
SearchContext *scx,
CellDef *targetDef)
@ -333,9 +324,38 @@ CIFCopyMaskHints(
CellDef *sourceDef = scx->scx_use->cu_def;
mhd.mh_trans = &scx->scx_trans;
mhd.mh_def = targetDef;
mhd.mh_plane = (Plane *)NULL;
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
}
/*
* ----------------------------------------------------------------------------
*
* cifHierCopyMaskHints --
*
* Callback function to copy mask hints from a subcell into a flattened
* cell, which is passed in the clientData record.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May modify properties in the flattened cell.
*
* ----------------------------------------------------------------------------
*/
int
cifHierCopyMaskHints(
SearchContext *scx,
ClientData clientData)
{
MaskHintsData mhd;
mhd.mh_trans = &scx->scx_trans;
mhd.mh_def = (CellDef *)clientData;
DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd);
return 0;
}
@ -460,7 +480,7 @@ cifHierCellFunc(
/* Flatten mask hints in the area of interest */
CIFCopyMaskHints(scx, CIFComponentDef);
DBTreeSrCells(&newscx, 0, CIFCopyMaskHints,
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
/* Set CIFErrorDef to NULL to ignore errors here... these will
@ -788,7 +808,7 @@ CIFGenSubcells(
cifHierCopyFunc, (ClientData) CIFTotalDef);
/* Flatten mask hints in the area of interest */
CIFCopyMaskHints(&scx, CIFTotalDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFTotalDef);
CIFErrorDef = def;
@ -966,14 +986,14 @@ cifHierElementFunc(
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFTotalDef);
CIFCopyMaskHints(&scx, CIFTotalDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFTotalDef);
DBCellClearDef(CIFComponentDef);
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
CIFErrorDef = (CellDef *) NULL;

View File

@ -146,7 +146,6 @@ typedef struct cifop
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
* CIFOP_TAGGED - Added 3/11/26---Find geometry attached to the given text label
*/
#define CIFOP_AND 1
@ -175,7 +174,6 @@ typedef struct cifop
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26
#define CIFOP_TAGGED 27
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
@ -340,8 +338,9 @@ extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef
bool hier, ClientData clientdata);
extern void CIFInitCells(void);
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
extern void CIFLoadStyle(char *stylename);
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
/* C99 compat */
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);

View File

@ -613,7 +613,7 @@ CIFPaintCurrent(
CIFOp *op;
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
cifCurReadPlanes, FALSE, (ClientData)NULL);
/* Generate a paint/erase table, then paint from the CIF
@ -718,9 +718,6 @@ CIFPaintCurrent(
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
{
/* (To do: remove the linked Rects and paint directly
* into the plane in cifMaskHintFunc())
*/
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMaskHintFunc,
(ClientData)&lrec);
@ -731,29 +728,30 @@ CIFPaintCurrent(
char *propname, *layername;
int proplen, i, savescale;
bool origfound = FALSE;
Plane *plane;
layername = (char *)op->co_client;
propname = (char *)mallocMagic(11 + strlen(layername));
sprintf(propname, "MASKHINTS_%s", layername);
/* If there is already a mask hint plane for this layer,
* then add to it; otherwise, create a new plane.
/* Turn all linked Rects into a mask-hints property in the
* target cell.
*/
proprec = DBPropGet(cifReadCellDef, layername, &origfound);
if (origfound)
plane = proprec->prop_value.prop_plane;
else
{
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0; /* (unused) */
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
DBPropPut(cifReadCellDef, propname, proprec);
}
proplen = 0;
for (lsrch = lrec; lsrch; lsrch = lsrch->r_next)
proplen += 4;
/* If there is already a mask hint for this layer, then
* prepend to its data.
*/
proporig = DBPropGet(cifReadCellDef, layername, &origfound);
if (origfound) proplen += proporig->prop_len;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
(proplen - 2) * sizeof(int));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = proplen;
proplen = 0;
while (lrec != NULL)
{
lrec->r_r.r_xtop =
@ -789,14 +787,29 @@ CIFPaintCurrent(
(savescale / cifCurReadStyle->crs_scaleFactor);
}
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
(PaintUndoInfo *)NULL);
proprec->prop_value.prop_integer[proplen] =
lrec->r_r.r_xbot;
proprec->prop_value.prop_integer[proplen + 1] =
lrec->r_r.r_ybot;
proprec->prop_value.prop_integer[proplen + 2] =
lrec->r_r.r_xtop;
proprec->prop_value.prop_integer[proplen + 3] =
lrec->r_r.r_ytop;
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
freeMagic1_end(&mm1);
proplen += 4;
}
if (origfound)
for (i = 0; i < proporig->prop_len; i++)
proprec->prop_value.prop_integer[proplen++] =
proporig->prop_value.prop_integer[i];
DBPropPut(cifReadCellDef, propname, proprec);
freeMagic(propname);
}
}
@ -913,9 +926,7 @@ CIFPaintCurrent(
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
/* Scan the resulting plane and generate linked Rect structures for
* each shape found. (To do: Remove the linked Rects and paint
* directly into the plane in cifMaskHintFunc(), which is more
* efficient but not hugely so.)
* each shape found.
*/
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
cifMaskHintFunc, (ClientData)&lrec);
@ -923,45 +934,44 @@ CIFPaintCurrent(
if (lrec != NULL)
{
PropertyRecord *proprec;
bool propfound;
char *propname;
Plane *plane;
int proplen;
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
/* Paint all linked Rects into a mask-hints property plane
* in the target cell.
/* Turn all linked Rects into a mask-hints property in the
* target cell.
*/
proplen = 0;
for (lsrch = lrec; lsrch; lsrch = lsrch->r_next)
proplen += 4;
proprec = DBPropGet(cifReadCellDef, propname, &propfound);
if (!propfound)
{
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0; /* (unused) */
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
DBPropPut(cifReadCellDef, propname, proprec);
}
else
plane = proprec->prop_value.prop_plane;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
(proplen - 2) * sizeof(int));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = proplen;
proplen = 0;
while (lrec != NULL)
{
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
(PaintUndoInfo *)NULL);
proprec->prop_value.prop_integer[proplen] =
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor;
proprec->prop_value.prop_integer[proplen + 1] =
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor;
proprec->prop_value.prop_integer[proplen + 2] =
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor;
proprec->prop_value.prop_integer[proplen + 3] =
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor;
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
freeMagic1_end(&mm1);
proplen += 4;
}
DBPropPut(cifReadCellDef, propname, proprec);
freeMagic(propname);
}
@ -1786,8 +1796,8 @@ CIFReadCellCleanup(
}
/* Do geometrical processing on the top-level cell. */
if (filetype == FILE_CIF) CIFPaintCurrent(filetype);
CIFPaintCurrent(FILE_CIF);
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
DBReComputeBbox(EditCellUse->cu_def);
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,

View File

@ -332,8 +332,7 @@ cifNewReadStyle(void)
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->crl_ops; op != NULL; op = op->co_next)
{
if (op->co_opcode == CIFOP_MASKHINTS ||
op->co_opcode == CIFOP_TAGGED)
if (op->co_opcode == CIFOP_MASKHINTS)
freeMagic((char *)op->co_client);
freeMagic1(&mm1, (char *)op);
}
@ -999,8 +998,6 @@ CIFReadTechLine(
newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "tagged") == 0)
newOp->co_opcode = CIFOP_TAGGED;
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1031,11 +1028,6 @@ CIFReadTechLine(
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break;
case CIFOP_TAGGED:
if (argc != 3) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
break;
}
/* Link the new CIFOp onto the list. */

View File

@ -166,9 +166,9 @@ CIFPaintLayer(
scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount;
@ -287,9 +287,9 @@ CIFSeeLayer(
scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount;
@ -459,9 +459,9 @@ CIFCoverageLayer(
scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,

View File

@ -1107,8 +1107,6 @@ CIFTechLine(
newOp->co_opcode = CIFOP_BBOX;
else if (strcmp(argv[0], "net") == 0)
newOp->co_opcode = CIFOP_NET;
else if (strcmp(argv[0], "tagged") == 0)
newOp->co_opcode = CIFOP_TAGGED;
else if (strcmp(argv[0], "maxrect") == 0)
newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0)
@ -1359,7 +1357,6 @@ bloatCheck:
bloatDone: break;
case CIFOP_NET:
case CIFOP_TAGGED:
if (argc != 3) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
@ -1674,12 +1671,12 @@ cifComputeRadii(
for (op = layer->cl_ops; op != NULL; op = op->co_next)
{
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
/* used hierarchically so ignore any grow/shrink operators that */
/* BBOX, NET, and MASKHINTS operators should never be used */
/* hierarchically so ignore any grow/shrink operators that */
/* come after them. */
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
op->co_opcode == CIFOP_MASKHINTS)
break;
/* If CIF layers are used, switch to the max of current
@ -1991,8 +1988,8 @@ CIFTechFinal(void)
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
/* of the SquaresData pointer from a following operator. */
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
/* CIFOP_TAGGED use it for a string. */
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* uses it for a string. */
else
{
switch (op->co_opcode)
@ -2004,7 +2001,6 @@ CIFTechFinal(void)
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_TAGGED:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
@ -2540,7 +2536,6 @@ CIFTechOutputScale(
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_TAGGED:
case CIFOP_INTERACT:
break;
case CIFOP_BRIDGELIM:
@ -2656,8 +2651,8 @@ CIFTechOutputScale(
default:
/* op->co_opcode in CIFOP_OR is a pointer copy, */
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
/* CIFOP_TAGGED is a string. */
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
/* string. */
break;
}
}

View File

@ -781,82 +781,39 @@ cmdEraseCellsFunc(
* Implement the "expand" command.
*
* Usage:
* expand [selection|surround|overlap|all] [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
* expand
* expand toggle
*
* Results:
* None.
*
* Side effects:
* Expansion state of cells is changed. May read cells in from
* disk, and update bounding boxes that have changed.
* If "toggle" is specified, flips the expanded/unexpanded status
* of all selected cells. Otherwise, aren't any unexpanded cells
* 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
CmdExpand(
MagWindow *w,
TxCommand *cmd)
{
int windowMask, boxMask, d, option;
bool doToggle = FALSE;
const char * const *msg;
int windowMask, boxMask, d;
Rect rootRect;
CellUse *rootBoxUse;
CellDef *rootBoxDef;
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
static const char * const cmdExpandOption[] = {
"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)
if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
&& (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
{
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle",
strlen(cmd->tx_argv[cmd->tx_argc - 1])))
{
doToggle = TRUE;
cmd->tx_argc--;
}
TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
return;
}
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);
if (w == (MagWindow *) NULL)
{
@ -887,95 +844,23 @@ CmdExpand(
WindScale(d, 1);
TxPrintf("expand: rescaled by %d\n", d);
d = DBLambda[1];
if (doToggle) break; /* Don't toggle twice */
if (cmd->tx_argc == 2) break; /* Don't toggle twice */
}
(void) ToolGetBoxWindow(&rootRect, &boxMask);
if (option != EXPAND_SELECTION)
if (cmd->tx_argc == 2)
SelectExpand(windowMask);
else
{
if ((boxMask & windowMask) != windowMask)
{
TxError("The box isn't in the same window as the cursor.\n");
return;
}
}
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;
DBExpandAll(rootBoxUse, &rootRect, windowMask,
TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
}
} 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.

View File

@ -45,8 +45,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/undo.h"
#include "select/select.h"
#include "netmenu/netmenu.h"
/* C99 compat */
#include "cif/cif.h"
#include "cif/CIFint.h"
/* Forward declarations */
@ -517,14 +518,14 @@ CmdLoad(
DBExpandAll(topuse, &(topuse->cu_bbox),
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_EXPAND, keepGoing, NULL);
TRUE, keepGoing, NULL);
DBExpandAll(topuse, &(topuse->cu_bbox),
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_UNEXPAND, keepGoing, NULL);
FALSE, keepGoing, NULL);
DBExpand(topuse,
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_EXPAND);
TRUE);
/* We don't want to save and restore DBLambda, because */
/* loading the file may change their values. Instead, we */
@ -2326,7 +2327,7 @@ CmdDoProperty(
{
PropertyRecord *proprec;
char *value;
bool propfound, dolist;
bool propfound;
int proptype, proplen, propvalue, i;
dlong dvalue;
int locargc = cmd->tx_argc - argstart + 1;
@ -2334,31 +2335,15 @@ CmdDoProperty(
Tcl_Obj *tobj;
#endif
/* Forward declarations */
int printPropertiesFunc();
int printPlanePropFunc();
int printPropertiesFunc(); /* Forward declaration */
/* These should match the property codes in database.h.in, except
* for "compat" which must come at the end.
*/
static const char * const cmdPropertyType[] = {
"string", "integer", "dimension", "double", "plane", "compat", NULL
"string", "integer", "dimension", "double", "compat", NULL
};
/* If the first keyword is "list", then set dolist and increment
* the starting argument position.
*/
dolist = FALSE;
if (locargc > 1)
{
if (!strcmp(cmd->tx_argv[argstart], "list"))
{
dolist = TRUE;
locargc--;
argstart++;
}
}
/* If a property type is given, parse it and then strip it from
* the arguments list.
*/
@ -2408,7 +2393,7 @@ CmdDoProperty(
return;
}
/* Print the value of the indicated property */
/* print the value of the indicated property */
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
if (propfound)
{
@ -2449,14 +2434,6 @@ CmdDoProperty(
Tcl_SetObjResult(magicinterp, tobj);
}
break;
case PROPERTY_TYPE_PLANE:
tobj = Tcl_NewListObj(0, NULL);
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
(ClientData)tobj);
Tcl_SetObjResult(magicinterp, tobj);
break;
case PROPERTY_TYPE_DOUBLE:
if (proprec->prop_len == 1)
Tcl_SetObjResult(magicinterp,
@ -2488,17 +2465,10 @@ CmdDoProperty(
for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%s ", DBWPrintValue(
proprec->prop_value.prop_integer[i], w,
((i % 2) == 0) ? TRUE : FALSE));
((i % 2) == 0) ? TRUE : FALSE);
TxPrintf("\n");
break;
case PROPERTY_TYPE_PLANE:
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
(ClientData)NULL);
TxPrintf("\n");
break;
case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++)
TxPrintf( "%"DLONG_PREFIX"d",
@ -2512,9 +2482,9 @@ CmdDoProperty(
#ifdef MAGIC_WRAPPER
/* If the command was "cellname list property ...", then */
/* just return NULL if the property was not found. */
if (!dolist)
if (strcmp(cmd->tx_argv[1], "list"))
#endif
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[argstart]);
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
}
}
else if (locargc >= 3)
@ -2544,7 +2514,7 @@ CmdDoProperty(
* keyword functions work correctly.
*
* GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE
* MASKHINTS_*: PROPERTY_TYPE_PLANE
* MASKHINTS_*: PROPERTY_TYPE_DIMENSION
* FIXED_BBOX: PROPERTY_TYPE_DIMENSION
*/
if (!strcmp(cmd->tx_argv[argstart], "GDS_START"))
@ -2558,7 +2528,7 @@ CmdDoProperty(
else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX"))
proptype = PROPERTY_TYPE_DIMENSION;
else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10))
proptype = PROPERTY_TYPE_PLANE;
proptype = PROPERTY_TYPE_DIMENSION;
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
DBPropPut(def, cmd->tx_argv[argstart], NULL);
@ -2573,11 +2543,8 @@ CmdDoProperty(
proprec->prop_len = proplen;
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
}
else /* All non-string properties */
else /* PROPERTY_TYPE_INTEGER or PROPERTY_TYPE_DIMENSION */
{
Plane *plane;
Rect r;
/* Two choices: If locargc == 3 then all values are in one
* argument. If locargc > 3, then parse each argument as a
* separate value.
@ -2588,12 +2555,6 @@ CmdDoProperty(
if (proptype == PROPERTY_TYPE_DOUBLE)
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proplen - 1)*sizeof(dlong));
else if (proptype == PROPERTY_TYPE_PLANE)
{
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
}
else
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proplen - 2)*sizeof(int));
@ -2626,28 +2587,6 @@ CmdDoProperty(
proprec->prop_value.prop_double[i - 1] = 0;
}
}
else if (proptype == PROPERTY_TYPE_PLANE)
{
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
switch ((i - 1) % 4)
{
case 0:
r.r_xbot = propvalue;
break;
case 1:
r.r_ybot = propvalue;
break;
case 2:
r.r_xtop = propvalue;
break;
case 3:
r.r_ytop = propvalue;
DBPaintPlane(plane, &r, CIFPaintTable,
(PaintUndoInfo *)NULL);
break;
}
}
else /* PROPERTY_TYPE_DIMENSION */
{
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
@ -2662,32 +2601,23 @@ CmdDoProperty(
* the valid number of arguments, then again to parse the
* values, once the property record has been allocated
*/
if (proptype == PROPERTY_TYPE_PLANE)
value = cmd->tx_argv[argstart + 1];
for (proplen = 0; *value != '\0'; )
{
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
}
else
{
value = cmd->tx_argv[argstart + 1];
for (proplen = 0; *value != '\0'; )
if (isspace(*value) && (*value != '\0')) value++;
if (!isspace(*value))
{
if (isspace(*value) && (*value != '\0')) value++;
if (!isspace(*value))
{
proplen++;
while (!isspace(*value) && (*value != '\0')) value++;
}
proplen++;
while (!isspace(*value) && (*value != '\0')) value++;
}
if (proplen > 0)
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord) +
(proplen - 2) * sizeof(int));
}
proprec->prop_type = proptype;
proprec->prop_len = proplen;
if (proplen > 0)
{
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proplen - 2)*sizeof(int));
proprec->prop_type = proptype;
proprec->prop_len = proplen;
}
/* Second pass */
value = cmd->tx_argv[argstart + 1];
for (proplen = 0; proplen < proprec->prop_len; proplen++)
@ -2727,28 +2657,6 @@ CmdDoProperty(
}
proprec->prop_value.prop_double[proplen] = dvalue;
}
else if (proptype == PROPERTY_TYPE_PLANE)
{
propvalue = cmdParseCoord(w, value, FALSE,
((proplen % 2) == 0) ? TRUE : FALSE);
switch (proplen % 4)
{
case 0:
r.r_xbot = propvalue;
break;
case 1:
r.r_ybot = propvalue;
break;
case 2:
r.r_xtop = propvalue;
break;
case 3:
r.r_ytop = propvalue;
DBPaintPlane(plane, &r, CIFPaintTable,
(PaintUndoInfo *)NULL);
break;
}
}
else /* PROPERTY_TYPE_DIMENSION */
{
propvalue = cmdParseCoord(w, value, FALSE,
@ -2819,59 +2727,6 @@ CmdProperty(
CmdDoProperty(def, w, cmd, 1);
}
/*
* ----------------------------------------------------------------------------
* Callback function for printing values from a Plane property
* ----------------------------------------------------------------------------
*/
#ifdef MAGIC_WRAPPER
int
printPlanePropFunc(
Tile *tile,
TileType dinfo,
Tcl_Obj *lobj)
{
Rect r;
MagWindow *w;
TiToRect(tile, &r);
windCheckOnlyWindow(&w, DBWclientID);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBWPrintValue(r.r_xbot, w, TRUE), -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBWPrintValue(r.r_ybot, w, FALSE), -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBWPrintValue(r.r_xtop, w, TRUE), -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBWPrintValue(r.r_ytop, w, FALSE), -1));
return 0;
}
#else
int
printPlanePropFunc(
Tile *tile,
TileType dinfo,
ClientData cdata) /* (unused) */
{
Rect r;
MagWindow *w;
TiToRect(tile, &r);
windCheckOnlyWindow(&w, DBWclientID);
TxPrintf("%s ", DBWPrintValue(r.r_xbot, w, TRUE));
TxPrintf("%s ", DBWPrintValue(r.r_ybot, w, FALSE));
TxPrintf("%s ", DBWPrintValue(r.r_xtop, w, TRUE));
TxPrintf("%s ", DBWPrintValue(r.r_ytop, w, FALSE));
return 0;
}
#endif
/*
* ----------------------------------------------------------------------------
* Callback function for printing a single property key:value pair
@ -2911,12 +2766,6 @@ printPropertiesFunc(
DBWPrintValue(proprec->prop_value.prop_integer[i],
w, ((i % 2) == 0) ? TRUE : FALSE), -1));
break;
case PROPERTY_TYPE_PLANE:
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
(ClientData)lobj);
break;
case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++)
Tcl_ListObjAppendElement(magicinterp, lobj,
@ -2930,32 +2779,25 @@ printPropertiesFunc(
switch (proprec->prop_type)
{
case PROPERTY_TYPE_STRING:
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_value.prop_string);
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_string);
break;
case PROPERTY_TYPE_INTEGER:
TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
TxPrintf("%d ", proprec->prop_integer[i]);
TxPrintf("\n");
break;
case PROPERTY_TYPE_DIMENSION:
TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%s ", DBWPrintValue(proprec->prop_value.prop_integer[i],
w, ((i % 2) == 0) ? TRUE : FALSE));
w, ((i % 2) == 0) ? TRUE : FALSE);
TxPrintf("\n");
break;
case PROPERTY_TYPE_PLANE:
TxPrintf("%s = ", name);
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
(ClientData)NULL);
TxPrintf("\n");
break;
case PROPERTY_TYPE_DOUBLE:
TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_value.prop_double[i]);
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_double[i]);
TxPrintf("\n");
break;
}

View File

@ -1801,18 +1801,13 @@ cmdLabelSizeFunc(
if (value == NULL)
{
char *labsize;
MagWindow *w;
windCheckOnlyWindow(&w, DBWclientID);
labsize = DBWPrintValue(label->lab_size / 8, w, FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_GetObjResult(magicinterp);
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(labsize, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewDoubleObj((double)label->lab_size / 8.0));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%s\n", labsize);
TxPrintf("%g\n", (double)label->lab_size / 8.0);
#endif
}
else if (label->lab_size != *value)
@ -1957,22 +1952,18 @@ cmdLabelOffsetFunc(
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
lobj = Tcl_GetObjResult(magicinterp);
pobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffy, -1));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewDoubleObj((double)label->lab_offset.p_x / 8.0));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewDoubleObj((double)label->lab_offset.p_y / 8.0));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%s %s\n", laboffx, laboffy);
TxPrintf("%g %g\n", (double)(label->lab_offset.p_x) / 8.0,
(double)(label->lab_offset.p_y) / 8.0);
#endif
}
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
@ -2221,13 +2212,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelTextFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelTextFunc,
(ClientData)cmd->tx_argv[argstart + 1]);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelTextFunc, (locargc == 3) ?
(ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL);
}
break;
@ -2293,12 +2280,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelFontFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelFontFunc, (ClientData)&font);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelFontFunc, (locargc == 3) ?
(ClientData)&font : (ClientData)NULL);
}
}
break;
@ -2326,12 +2310,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelJustFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelJustFunc, (ClientData)&pos);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelJustFunc, (locargc == 3) ?
(ClientData)&pos : (ClientData)NULL);
}
break;
@ -2360,12 +2341,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelSizeFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelSizeFunc, (ClientData)&size);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelSizeFunc, (locargc == 3) ?
(ClientData)&size : (ClientData)NULL);
}
break;
@ -2415,12 +2393,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelOffsetFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelOffsetFunc, (ClientData)&offset);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelOffsetFunc, (locargc != 2) ?
(ClientData)&offset : (ClientData)NULL);
}
break;
@ -2484,12 +2459,10 @@ CmdSetLabel(
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
TRUE, FALSE, 1);
}
if ((locargc == 3) || (locargc == 6))
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRectFunc, (ClientData)&rect);
else
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRectFunc, (ClientData)NULL);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRectFunc,
((locargc == 6) || (locargc == 3)) ?
(ClientData)&rect : (ClientData)NULL);
}
break;
@ -2515,12 +2488,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRotateFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRotateFunc, (ClientData)&rotate);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRotateFunc, (locargc == 3) ?
(ClientData)&rotate : (ClientData)NULL);
}
break;
@ -2552,12 +2522,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelStickyFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelStickyFunc, (ClientData)&flags);
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelStickyFunc, (locargc == 3) ?
(ClientData)&flags : (ClientData)NULL);
}
break;
@ -2596,12 +2563,9 @@ CmdSetLabel(
}
else if (EditCellUse)
{
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelLayerFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelLayerFunc, (ClientData)&ttype);
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelLayerFunc, (locargc == 3) ?
(ClientData)&ttype : (ClientData)NULL);
}
break;

View File

@ -1239,7 +1239,7 @@ cmdExpandOneLevel(
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
/* first, expand this cell use */
DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND);
DBExpand(cu, bitmask, expand);
/* now, unexpand its direct children (ONE LEVEL ONLY) */
if (expand)
@ -1251,7 +1251,7 @@ cmdExpand1func(
CellUse *cu,
ClientData bitmask)
{
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND);
DBExpand(cu, (int)CD2INT(bitmask), FALSE);
return 0;
}

View File

@ -702,62 +702,32 @@ CmdTool(
* Implement the "unexpand" command.
*
* Usage:
* 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
* unexpand
*
* Results:
* None.
*
* Side effects:
* Changes the expansion state of cells.
* Unexpands all cells under the box that don't completely
* contain the box.
*
* ----------------------------------------------------------------------------
*/
#define UNEXPAND_SELECTION 0
#define UNEXPAND_SURROUND 1
#define UNEXPAND_OVERLAP 2
#define UNEXPAND_ALL 3
#define UNEXPAND_HELP 4
void
CmdUnexpand(
MagWindow *w,
TxCommand *cmd)
{
int windowMask, boxMask, option;
const char * const *msg;
int windowMask, boxMask;
Rect rootRect;
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
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)
if (cmd->tx_argc != 1)
{
option = Lookup(cmd->tx_argv[1], cmdUnexpandOption);
if (option < 0) option = UNEXPAND_HELP;
TxError("Usage: %s\n", cmd->tx_argv[0]);
return;
}
else
option = UNEXPAND_SURROUND;
if (option == UNEXPAND_HELP) goto badusage;
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL)
@ -773,42 +743,8 @@ CmdUnexpand(
TxError("The box isn't in the same window as the cursor.\n");
return;
}
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);
DBExpandAll(((CellUse *) w->w_surfaceID), &rootRect, windowMask,
FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask);
}
/* This function is called for each cell whose expansion status changed.

View File

@ -37,8 +37,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "commands/commands.h"
/* C99 compat */
#include "graphics/graphics.h"
#include "cif/CIFint.h"
/*
* The following variable points to the tables currently used for
@ -356,43 +357,10 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
struct propUseDefStruct {
CellDef *puds_source;
CellDef *puds_dest;
Plane *puds_plane; /* Mask hint plane in dest */
Transform *puds_trans; /* Transform from source use to dest */
Rect *puds_area; /* Clip area in source coordinates */
};
/*
*-----------------------------------------------------------------------------
*
* dbCopyMaskHintPlaneFunc --
*
* Translate tiles from a child mask-hint property plane into the
* coordinate system of the parent, and paint the mask-hint area
* into the mask-hint property plane of the parent.
*
*-----------------------------------------------------------------------------
*/
int
dbCopyMaskHintPlaneFunc(Tile *tile,
TileType dinfo,
struct propUseDefStruct *puds)
{
Transform *trans = puds->puds_trans;
Rect *clip = puds->puds_area;
Rect r, rnew;
Plane *plane = puds->puds_plane;
TiToRect(tile, &r);
GeoClip(&r, clip);
if (!GEO_RECTNULL(&r))
{
GeoTransRect(trans, &r, &rnew);
DBPaintPlane(plane, &rnew, CIFPaintTable, (PaintUndoInfo *)NULL);
}
return 0;
}
/*
*-----------------------------------------------------------------------------
*
@ -431,34 +399,56 @@ dbCopyMaskHintsFunc(key, proprec, puds)
{
char *vptr, *lastval;
int lastlen;
Plane *plane;
ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc");
/* Get the existing mask hint plane in the parent cell, and
* create it if it does not already exist.
*/
/* Append to existing mask hint (if any) */
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
if (propfound)
plane = parentproprec->prop_value.prop_plane;
{
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proprec->prop_len + parentproprec->prop_len - 2) *
sizeof(int));
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
newproprec->prop_len = parentproprec->prop_len;
}
else
{
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
newproprec->prop_type = PROPERTY_TYPE_PLANE;
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proprec->prop_len - 2) * sizeof(int));
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
newproprec->prop_len = 0;
plane = DBNewPlane((ClientData)TT_SPACE);
newproprec->prop_value.prop_plane = plane;
DBPropPut(dest, key, newproprec);
}
puds->puds_plane = plane;
/* Copy the properties from child to parent */
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc,
(ClientData)puds);
for (i = 0, j = 0; i < proprec->prop_len; i += 4)
{
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
GeoClip(&r, clip);
if (!GEO_RECTNULL(&r))
{
GeoTransRect(trans, &r, &rnew);
newproprec->prop_value.prop_integer[j] = rnew.r_xbot;
newproprec->prop_value.prop_integer[j + 1] = rnew.r_ybot;
newproprec->prop_value.prop_integer[j + 2] = rnew.r_xtop;
newproprec->prop_value.prop_integer[j + 3] = rnew.r_ytop;
newproprec->prop_len += 4;
j += 4;
}
}
if (propfound)
{
/* Append the original values to the end of the list */
for (i = 0; i < parentproprec->prop_len; i++)
newproprec->prop_value.prop_integer[i + j] =
parentproprec->prop_value.prop_integer[i];
}
DBPropPut(dest, key, newproprec);
}
return 0;
}

View File

@ -588,25 +588,6 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
if (!DBCellRead(def, TRUE, TRUE, NULL))
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)
{
if (SigInterruptPending) break;
@ -659,8 +640,6 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
return (1);
}
if (flags & TF_LABEL_REVERSE_SEARCH) return 0; /* children already searched */
filter.tf_func = func;
filter.tf_arg = cdarg;
filter.tf_mask = mask;
@ -732,16 +711,6 @@ 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. */
result = 0;
@ -763,11 +732,9 @@ dbCellLabelSrFunc(scx, fp)
}
}
/* Now visit each child use recursively, if not doing a reverse search */
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH))
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
result = 1;
/* Now visit each child use recursively */
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
result = 1;
cleanup:
/* Remove the trailing pathname component from the TerminalPath */
@ -1746,7 +1713,7 @@ dbTileMoveFunc(tile, dinfo, mvvals)
if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum),
DBStdPaintTbl(type, mvvals->pnum),
(PaintUndoInfo *)NULL);
return 0;
}
@ -1847,22 +1814,7 @@ int dbScaleProp(name, proprec, cps)
int i, scalen, scaled;
Point p;
/* Only "dimension" and "plane" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData)TT_SPACE);
DBClearPaintPlane(newplane);
/* Plane index is unused; arbitrarily substitute -1 */
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
scalen, scaled, TRUE);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
/* Only "dimension" type properties get scaled */
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
/* Scale numerator held in point X value, */
@ -1905,22 +1857,7 @@ int dbMoveProp(name, proprec, cps)
char *newvalue;
Point p;
/* Only "dimension" and "plane" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane);
/* Use plane index -1 to indicate use of CIFPaintTable */
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
/* Only "dimension" type properties get scaled */
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
origx = cps->cps_point.p_x;

View File

@ -39,7 +39,6 @@ struct expandArg
{
bool ea_deref; /* TRUE if root def dereference flag is set */
int ea_xmask; /* Expand mask. */
int ea_type; /* Expand, unexpand, or toggle */
int (*ea_func)(); /* Function to call for each cell whose
* status is changed.
*/
@ -68,22 +67,15 @@ struct expandArg
*/
void
DBExpand(cellUse, expandMask, expandType)
DBExpand(cellUse, expandMask, expandFlag)
CellUse *cellUse;
int expandMask;
int expandType;
bool expandFlag;
{
CellDef *def;
bool expandFlag, expandTest;
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 (DBDescendSubcell(cellUse, expandMask) == expandFlag)
return;
if (expandFlag)
{
@ -138,17 +130,17 @@ DBExpand(cellUse, expandMask, expandType)
*/
void
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
CellUse *rootUse; /* Root cell use from which search begins */
Rect *rootRect; /* Area to be expanded, in root coordinates */
int expandMask; /* Window mask in which cell is to be expanded */
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */
bool expandFlag; /* TRUE => expand, FALSE => unexpand */
int (*func)(); /* Function to call for each cell whose expansion
* status is modified. NULL means don't call anyone.
*/
ClientData cdarg; /* Argument to pass to func. */
{
int dbExpandFunc();
int dbExpandFunc(), dbUnexpandFunc();
SearchContext scontext;
struct expandArg arg;
@ -156,26 +148,29 @@ DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
/*
* Walk through the area and set the expansion state appropriately.
* Walk through the area and set the expansion state
* appropriately.
*/
arg.ea_xmask = expandMask;
arg.ea_func = func;
arg.ea_arg = cdarg;
arg.ea_type = expandType;
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform;
scontext.scx_area = *rootRect;
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
if (expandFlag)
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
else
DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg);
}
/*
* dbExpandFunc --
*
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
* when cells are being expanded, unexpanded, or toggled.
* when cells are being expanded.
*/
int
@ -189,55 +184,68 @@ dbExpandFunc(scx, arg)
{
CellUse *childUse = scx->scx_use;
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
* client's function if the expansion status has changed.
*/
if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE)))
if (!DBDescendSubcell(childUse, arg->ea_xmask))
{
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
/* If the cell is unavailable, then don't expand it.
*/
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
{
/* If the cell is unavailable, then don't expand it.
*/
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
/* If the parent is dereferenced, then the child should be, too */
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
{
/* If the parent is dereferenced, then the child should be, too */
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
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;
TxError("Cell %s is unavailable. It could not be expanded.\n",
childUse->cu_def->cd_name);
return 2;
}
}
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) ||
(expandType == DB_EXPAND_TOGGLE)))
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
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))
{
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox))
{
childUse->cu_expandMask &= ~arg->ea_xmask;
expandTest = FALSE;
/* Call the client's function, if there is one. */
@ -248,7 +256,11 @@ dbExpandFunc(scx, arg)
}
}
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
/* Don't recursively search things that aren't already expanded. */
else return 2;
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
return 1;
return 2;
}

View File

@ -73,9 +73,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/undo.h"
#include "utils/malloc.h"
#include "utils/signals.h"
/* C99 compat */
#include "dbwind/dbwtech.h"
#include "cif/cif.h"
#include "cif/CIFint.h"
#include "lef/lef.h"
#include "commands/commands.h"
#include "graphics/graphics.h"
@ -2491,24 +2492,10 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
* (2) "integer" (a fixed integer or list of integers)
* (3) "dimension" (an integer that scales with internal units)
* (4) "double" (a fixed double-wide integer or list thereof)
* (5) "plane" (a tile plane structure)
*/
switch (option)
{
case PROPERTY_TYPE_PLANE:
/* Treat this like "string" but make sure property is a
* mask hint. There is currently no method to specify
* a plane property other than to write out the bounding
* box coordinates of all the tiles in a list.
*/
if (strncmp(propertyname, "MASKHINTS_", 10))
{
TxError("Plane type specified for property \"%s\" but "
"property is not a mask hint!\n", propertyname);
break;
}
/* Else drop through */
case PROPERTY_TYPE_STRING:
/* Go ahead and process the vendor GDS property */
if (!strcmp(propertyname, "GDS_FILE"))
@ -2578,64 +2565,69 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
else if (!strncmp(propertyname, "MASKHINTS_", 10))
{
pptr = pvalueptr;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0;
proprec->prop_value.prop_plane = DBNewPlane((ClientData)TT_SPACE);
/* Parse the string and convert sets of four values
* to coordinates and paint into the plane.
/* Do one pass through the string to count the number of
* values and make sure they all parse as integers.
*/
numvals = 0;
while (*pptr != '\0')
{
Rect r;
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
if (!isspace(*pptr))
{
if (sscanf(pptr, "%d", &ival) != 1)
char *endptr;
long result;
/* Check that the value is an integer */
result = strtol(pptr, &endptr, 0);
if (endptr == pptr)
{
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;
/* Unable to parse correctly. Save as a string value */
proplen = strlen(pvalueptr);
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord) - 7 + proplen);
proprec->prop_type = PROPERTY_TYPE_STRING;
proprec->prop_len = proplen;
strcpy(proprec->prop_value.prop_string, pvalueptr);
(void) DBPropPut(cellDef, propertyname, proprec);
break;
}
if (scalen > 1) ival *= scalen;
if (scaled > 1) ival /= scaled;
switch (numvals)
{
case 0:
r.r_xbot = ival;
numvals++;
break;
case 1:
r.r_ybot = ival;
numvals++;
break;
case 2:
r.r_xtop = ival;
numvals++;
break;
case 3:
r.r_ytop = ival;
numvals = 0;
/* Paint this into the plane */
DBPaintPlane(proprec->prop_value.prop_plane,
&r, CIFPaintTable,
(PaintUndoInfo *)NULL);
break;
}
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
numvals++;
}
}
if (numvals != 0)
if (numvals % 4 != 0)
{
TxError("Mask-hint property number of values is not"
" divisible by four. Truncated.\n");
TxError("Cannot read bounding box values in %s property",
propertyname);
/* This does not need to be a fatal error. Extra
* values will be unused.
*/
}
pptr = pvalueptr;
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord) + ((numvals - 2) * sizeof(int)));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = numvals;
/* Do a second pass through the string to convert the values
* to dimensions and save as an integer array.
*/
numvals = 0;
while (*pptr != '\0')
{
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
if (!isspace(*pptr))
{
sscanf(pptr, "%d", &ival);
if (scalen > 1) ival *= scalen;
if (scaled > 1) ival /= scaled;
proprec->prop_value.prop_integer[numvals] = ival;
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
numvals++;
}
}
(void) DBPropPut(cellDef, propertyname, proprec);
}
@ -3489,23 +3481,6 @@ DBCellFindScale(cellDef)
return ggcf;
}
/*
* ----------------------------------------------------------------------------
*
* dbFindGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* in a tile.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int
dbFindGCFFunc(tile, dinfo, ggcf)
Tile *tile;
@ -3528,24 +3503,6 @@ dbFindGCFFunc(tile, dinfo, ggcf)
return (*ggcf == 1) ? 1 : 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbFindCellGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* of a uses bounding box, each component of the use's transform , and
* for arrays, the array pitch.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int
dbFindCellGCFFunc(cellUse, ggcf)
CellUse *cellUse; /* Cell use whose "call" is to be written to a file */
@ -3586,23 +3543,6 @@ dbFindCellGCFFunc(cellUse, ggcf)
return (*ggcf == 1) ? 1 : 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbFindPropGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* of a dimension property, or each point of each tile in a plane property.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int
dbFindPropGCFFunc(key, proprec, ggcf)
char *key;
@ -3611,28 +3551,20 @@ dbFindPropGCFFunc(key, proprec, ggcf)
{
int value, n;
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
/* Only PROPERTY_TYPE_DIMENSION properties get handled */
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
for (n = 0; n < proprec->prop_len; n++)
{
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbFindGCFFunc, (ClientData)ggcf))
return (*ggcf == 1) ? 1 : 0;
value = proprec->prop_value.prop_integer[n];
if (value % (*ggcf) != 0)
*ggcf = FindGCF(value, *ggcf);
}
else if (proprec->prop_type == PROPERTY_TYPE_DIMENSION)
{
for (n = 0; n < proprec->prop_len; n++)
{
value = proprec->prop_value.prop_integer[n];
if (value % (*ggcf) != 0)
*ggcf = FindGCF(value, *ggcf);
}
return (*ggcf == 1) ? 1 : 0;
}
else
/* Only PROPERTY_TYPE_PLANE and PROPERTY_TYPE_DIMENSION get handled */
return 0;
return (*ggcf == 1) ? 1 : 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -3641,12 +3573,6 @@ dbFindPropGCFFunc(key, proprec, ggcf)
* String comparison of two instance names, for the purpose of sorting
* the instances in a .mag file output in a repeatable way.
*
* Results:
* The string comparison, equivalent to the return value of strcmp().
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
@ -3684,9 +3610,6 @@ struct cellUseList {
* Return value:
* Return 0 to keep the search going.
*
* Side effects:
* Adds to the list of cell uses passed as client data.
*
* ----------------------------------------------------------------------------
*/
@ -3712,9 +3635,6 @@ dbGetUseFunc(cellUse, useRec)
* Return value:
* Return 0 to keep the search going.
*
* Side effects:
* Increments the count passed as client data.
*
* ----------------------------------------------------------------------------
*/
@ -3743,12 +3663,6 @@ struct keyValuePair {
* String comparison of two property keys, for the purpose of sorting
* the properties in a .mag file output in a repeatable way.
*
* Results:
* The string comparison, equivalent to the result of strcmp().
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
@ -3784,9 +3698,6 @@ struct cellPropList {
* Return value:
* Return 0 to keep the search going.
*
* Side Effects:
* Adds to the list of property records passed as client data.
*
* ----------------------------------------------------------------------------
*/
@ -3816,9 +3727,6 @@ dbGetPropFunc(key, proprec, propRec)
* Return value:
* Return 0 to keep the search going.
*
* Side Effects:
* Increments the count passed as client data.
*
* ----------------------------------------------------------------------------
*/
@ -4156,52 +4064,6 @@ ioerror:
return (TRUE);
}
/*
* ----------------------------------------------------------------------------
*
* dbWritePropPaintFunc --
*
* Transform tiles in a plane into a set of four coordinate values and output
* them to the file. This turns plane data into a PROP_TYPE_DIMENSION array,
* which is not a very efficient form and may be revisited. For relatively
* simple plane data, it suffices. The property planes are single-bit types.
* Note that there is no support for non-Manhattan geometry in the property
* plane at this time.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePropPaintFunc(Tile *tile,
TileType dinfo,
ClientData cdata)
{
pwfrec *pwf = (pwfrec *)cdata;
FILE *f = pwf->pwf_file;
int reducer = pwf->pwf_reducer;
Rect r;
char newvalue[20];
TiToRect(tile, &r);
snprintf(newvalue, 20, " %d", r.r_xbot / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_ybot / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_xtop / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_ytop / reducer);
FPUTSR(f, newvalue);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -4249,12 +4111,6 @@ dbWritePropFunc(key, proprec, cdata)
case PROPERTY_TYPE_INTEGER:
FPUTSR(f, "integer ");
break;
case PROPERTY_TYPE_PLANE:
/* A mask hint is a plane type property; declare it
* as a dimension, but it's arbitrary anyway since
* the prefix "MASKHINTS_" is detected on read-in and
* the property is parsed as plane data.
*/
case PROPERTY_TYPE_DIMENSION:
FPUTSR(f, "dimension ");
break;
@ -4287,13 +4143,6 @@ dbWritePropFunc(key, proprec, cdata)
FPUTSR(f, newvalue);
}
break;
case PROPERTY_TYPE_PLANE:
/* Scan the plane and output each non-space tile as four values */
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbWritePropPaintFunc,
(ClientData)cdata);
break;
case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++)
{
@ -4418,7 +4267,7 @@ DBCellWriteCommandFile(cellDef, f)
}
else
{
fprintf(f, "label %s %s %d %d %d %d %s %s%s\n",
fprintf(f, "label %s %s %d %d %d %d %s %s\n",
lab->lab_text,
DBFontList[lab->lab_font]->mf_name,
lab->lab_size >> 3,
@ -4426,10 +4275,15 @@ DBCellWriteCommandFile(cellDef, f)
lab->lab_offset.p_x,
lab->lab_offset.p_y,
directionNames[lab->lab_just],
(lab->lab_flags & LABEL_STICKY) ? "-" : "",
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 & LABEL_STICKY))
@ -4541,12 +4395,6 @@ ioerror:
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell layout geometry.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
@ -4612,12 +4460,6 @@ dbWritePaintCommandsFunc(tile, dinfo, cdarg)
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell uses in the layout.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
@ -4637,45 +4479,6 @@ dbWriteUseCommandsFunc(cellUse, cdarg)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbWritePropCommandPaintFunc --
*
* Transform tiles in a plane into a set of four coordinate values and output
* them to the file. This turns plane data into a PROP_TYPE_DIMENSION array,
* which is not a very efficient form and may be revisited. For relatively
* simple plane data, it suffices. The property planes are single-bit types.
* Note that there is no support for non-Manhattan geometry in the property
* plane at this time.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePropCommandPaintFunc(Tile *tile,
TileType dinfo,
FILE *f)
{
Rect r;
MagWindow *w;
TiToRect(tile, &r);
windCheckOnlyWindow(&w, DBWclientID);
fprintf(f, "%s ", DBWPrintValue(r.r_xbot, w, TRUE));
fprintf(f, "%s ", DBWPrintValue(r.r_ybot, w, FALSE));
fprintf(f, "%s ", DBWPrintValue(r.r_xtop, w, TRUE));
fprintf(f, "%s ", DBWPrintValue(r.r_ytop, w, FALSE));
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -4684,12 +4487,6 @@ dbWritePropCommandPaintFunc(Tile *tile,
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to properties in the layout.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
@ -4743,19 +4540,6 @@ dbWritePropCommandsFunc(key, proprec, cdarg)
fprintf(f, "\n");
break;
case PROPERTY_TYPE_PLANE:
/* Plane properties are automatically handled as plane data,
* so the property type does not need to be declared.
* Only mask hints can be plane properties.
*/
fprintf(f, "property %s ", key);
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbWritePropCommandPaintFunc,
(ClientData)f);
fprintf(f, "\n");
break;
case PROPERTY_TYPE_DOUBLE:
fprintf(f, "property double %s ", key);
for (i = 0; i < proprec->prop_len; i++)
@ -4789,6 +4573,7 @@ dbWritePropCommandsFunc(key, proprec, cdarg)
* the file. If successful, rewind the now-expanded file and
* overwrite the beginning of the file, then truncate it.
*
*
* Results:
* TRUE if the cell could be written successfully, FALSE otherwise.
*

View File

@ -106,18 +106,7 @@ DBPropPut(cellDef, name, value)
entry = HashFind(htab, name);
oldvalue = (PropertyRecord *)HashGetValue(entry);
/* All properties are allocated as a single block and can just be freed,
* except for plane properties, which require freeing the plane.
*/
if (oldvalue != NULL)
{
if (oldvalue->prop_type == PROPERTY_TYPE_PLANE)
{
DBFreePaintPlane(oldvalue->prop_value.prop_plane);
TiFreePlane(oldvalue->prop_value.prop_plane);
}
freeMagic((char *)oldvalue);
}
if (oldvalue != NULL) freeMagic((char *)oldvalue);
if (value == (PropertyRecord *)NULL)
HashRemove(htab, name);
else

View File

@ -651,7 +651,6 @@ typedef struct treeFilter
#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_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 */
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
@ -720,7 +719,6 @@ typedef struct
char prop_string[8]; /* For PROPERTY_TYPE_STRING */
int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */
dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */
Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */
} prop_value;
} PropertyRecord;
@ -762,7 +760,6 @@ typedef struct
#define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */
#define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */
#define PROPERTY_TYPE_DOUBLE 3 /* Double-long integer (for file positions) */
#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */
/* -------------------- Exported procedure headers -------------------- */
@ -1062,19 +1059,6 @@ extern unsigned char DBVerbose; /* If 0, don't print any messages */
#define DB_VERBOSE_WARN 2
#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 ------------------- */
/***

View File

@ -131,11 +131,8 @@ DBWAddButtonHandler(
for (i = 0; i < MAXBUTTONHANDLERS; i++)
{
if (dbwButtonHandlers[i] != NULL) continue;
StrDup(&dbwButtonHandlers[i], name);
if (doc != NULL)
StrDup(&dbwButtonDoc[i], doc);
else
dbwButtonDoc[i] = (char *)NULL;
(void) StrDup(&dbwButtonHandlers[i], name);
(void) StrDup(&dbwButtonDoc[i], doc);
dbwButtonProcs[i] = proc;
dbwButtonCursors[i] = cursor;
return;
@ -276,37 +273,6 @@ DBWGetButtonHandler()
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;
}
/*
* ----------------------------------------------------------------------------
*
@ -328,10 +294,7 @@ DBWButtonHandlerIndex(char *toolName)
void
DBWPrintButtonDoc()
{
if (dbwButtonDoc[dbwButtonCurrentIndex])
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
else
TxPrintf("(no usage information)\n");
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
}

View File

@ -421,8 +421,7 @@ DBWredisplay(w, rootArea, clipArea)
/* Set style information beforehand */
GrSetStuff(STYLE_LABEL);
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
(TerminalPath *) NULL,
TF_LABEL_DISPLAY | TF_LABEL_ATTACH | TF_LABEL_REVERSE_SEARCH,
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
GrClipTo(&rootClip);
}

View File

@ -546,12 +546,12 @@ DBWloadWindow(window, name, flags)
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
DBExpand(newEditUse,
((DBWclientRec *)window->w_clientData)->dbw_bitmask, DB_EXPAND);
((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE);
if (expand)
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
DB_UNEXPAND, UnexpandFunc,
FALSE, UnexpandFunc,
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
if (newEdit)

View File

@ -152,7 +152,6 @@ extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandle
int cursor, const char *doc);
extern char *DBWGetButtonHandler();
extern char *DBWChangeButtonHandler();
extern int DBWButtonHandlerIndex();
extern void DBWPrintButtonDoc();
extern void DBWBoxHandler();

View File

@ -71,15 +71,12 @@ Operations on cell definitions.
<DT> <B>rename</B> <I>name newname</I>
<DD> Change the name of the cell definition <I>name</I> to
<I>newname</I>.
<DT> <B>delete</B> <I>name</I> [<B>-noprompt</B>]
<DT> <B>delete</B> <I>name</I>
<DD> Delete the cell definition with name <I>name</I>. If cell
<I>name</I> is a descendent of another cell, the command
will be prohibited. If the cell <I>name</I> is currently
the topmost cell in the window, the window will be loaded
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.
with default cell "(UNNAMED)".
<DT> <B>dereference</B> <I>name</I>
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
first removing any file path associated with the cell, so

View File

@ -26,8 +26,7 @@ expanded/unexpanded cells in the current selection.
<H3>Usage:</H3>
<BLOCKQUOTE>
<B>expand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
[<B>toggle</B>] <BR><BR>
<B>expand</B> [<B>toggle</B>] <BR><BR>
</BLOCKQUOTE>
<H3>Shortcuts:</H3>
@ -39,32 +38,14 @@ expanded/unexpanded cells in the current selection.
<H3>Summary:</H3>
<BLOCKQUOTE>
The <B>expand</B> command expands the view of subcells to
display the contents of the subcells.
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.
display the contents of the subcells. Without arguments,
the <B>expand</B> command expands all unexpanded subcells that
touch or intersect the cursor box in the layout window. <P>
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>
<H3>Implementation Notes:</H3>

View File

@ -87,50 +87,6 @@ Place a label in the layout
to another layer. <P>
</BLOCKQUOTE>
<BLOCKQUOTE>
<B>Attribute labels:</B> <P>
A handful of labels are referred to as "attribute" labels. These
label types are placed on devices and affect how the device is
extracted. <P>
A label that is placed inside a device (e.g., a MOSFET gate) which
ends with the character "<B>^</B>" is a <I>gate attribute</I>. A
gate attribute in the form of "<I>name</I><B>=</B><I>value</I><B>^</B>"
specifies an extra parameter to be passed to the device in addition
to the standard parameters calculated for that device. This is used
to capture parameters which cannot easily be inferred from the layout.
For example, an RF device model might be distinguished from a non-RF
device model by a parameter such as <B>rfmode=1</B>. Whether or not
a device is intended for RF use is not easily guessed from the layout,
and so "tagging" the gate with the parameter allows the correct model
parameters to be used for the device. <P>
A gate attribute that is not in the form of a parameter will be used
as the device's instance index in the netlist; e.g., a label of
"<B>1^</B>" on a MOSFET gate extracted as a MOSFET device would be an
entry "<B>M1</B>" in the netlist. This can be used to better track
device indexes between a schematic and layout. <P>
A label that is placed on the <I>edge</I> a device, specificlly a
MOSFET gate, and which ends with the character "<B>$</B>", is a
<I>terminal attribute</I>. The only terminal attributes recognized
by magic are <B>S$</B> and <B>D$</B>, which specify which side of the
gate is to be considered the source and which is to be considered the
drain. Generally, MOSFET devices are symmetric, and their use in a
simulation does not depend on which side is in the position of the
"source" and which is in the position of the "drain". To the extent
that it matters, the terminal attributes can be used to ensure that
the source and drain connections appear in the netlist in their
intended orientation. <P>
Labels ending with "<B>@</B>" are <I>node attributes</I>. There is
currently no functional application for node attributes. When one
is applied, it will appear in the output netlist in a SPICE comment
line indicating the node and attribute. This could be used, say,
by a post-processing script, but as it is in a comment line, it has
no impact on simulation or LVS.
</BLOCKQUOTE>
<H3>Implementation Notes:</H3>
<BLOCKQUOTE>
<B>label</B> is implemented as a built-in command in <B>magic</B>.

View File

@ -20,64 +20,22 @@
<H2>macro</H2>
<HR>
Define or print a key or button macro binding.
Define or print a macro called char
<HR>
<H3>Usage:</H3>
<BLOCKQUOTE>
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]]
<BR><BR>
<B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
<BLOCKQUOTE>
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
present, <I>window_type</I> must be one of the known valid window
types accepted by the <B>specialopen</B> command (<B>color</B>,
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If
omitted, the layout window is assumed by default, unless the command
has been called from inside a window (using the colon or semicolon
present, <I>window_type</I> must be one of the four window
types accepted by the <B>specialopen</B> command: <B>layout</B>,
<B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If 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
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>
assumed.
</BLOCKQUOTE>
</BLOCKQUOTE>
@ -114,6 +72,7 @@ Define or print a key or button macro binding.
etc., the <B>macro</B> command accepts the abbreviated
forms <B>Button1</B>, and so forth. <P>
Finally, key modifiers may be prepended to the key name.
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
@ -130,7 +89,6 @@ Define or print a key or button macro binding.
<H3>See Also:</H3>
<BLOCKQUOTE>
<A HREF=imacro.html><B>imacro</B></A> <BR>
<A HREF=toolchange.html><B>tool</B></A> (Tcl version) <BR>
</BLOCKQUOTE>
<P><IMG SRC=graphics/line1.gif><P>

View File

@ -25,7 +25,7 @@ Attach a "property" (string key and value pair) to the edit cell
<H3>Usage:</H3>
<BLOCKQUOTE>
<B>property</B> [<I>list</I>] [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
<B>property</B> [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
or
<B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR>
<BLOCKQUOTE>
@ -64,13 +64,6 @@ Attach a "property" (string key and value pair) to the edit cell
.mag file. However, if the user wants to create a property that
is handled differently than a string (namely, to be a dimensional
value that scales), then comptability mode should be turned off. <P>
If the argument <I>list</I> is given as the first argument, and
<I>value</I> is not present, then if the property <I>key</I>
does not exist, then the command will return a NULL object to the
interpreter instead of printing an error message. This is the
"quiet" version of the command preferred for scripts that want to
query whether or not a specific property exists.
</BLOCKQUOTE>
<BLOCKQUOTE>

View File

@ -25,8 +25,7 @@ Unexpand everything inside or touching the cursor box.
<H3>Usage:</H3>
<BLOCKQUOTE>
<B>unexpand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
<BR><BR>
<B>unexpand</B> <BR><BR>
</BLOCKQUOTE>
<H3>Shortcuts:</H3>
@ -38,23 +37,8 @@ Unexpand everything inside or touching the cursor box.
<BLOCKQUOTE>
The <B>unexpand</B> command unexpands the view of subcells to
hide the contents of the subcells and show the bounding box
outline only.
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.
outline only. The <B>unexpand</B> command unexpands all subcells
that touch or intersect the cursor box in the layout window. <P>
</BLOCKQUOTE>
<H3>Implementation Notes:</H3>

View File

@ -27,8 +27,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h>
#include <string.h> // for memcpy()
#include <math.h> // for sqrt() for diagonal check
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
@ -38,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/signals.h"
#include "utils/maxrect.h"
#include "utils/malloc.h"
#include "utils/undo.h"
#include "textio/textio.h"
#include "cif/CIFint.h"
int dbDRCDebug = 0;
@ -66,33 +62,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
/*
*-----------------------------------------------------------------------
*
* drcFoundOneFunc --
*
* Simple callback for a plane search on a mask-hint plane inside
* a DRC check area.
*
* Results:
* Return 1 always, indicating that a tile has been found in the
* DRC search area, and the search can end.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------
*/
int
drcFoundOneFunc(Tile *tile,
TileType dinfo,
ClientData cdata)
{
return 1;
}
/*
*-----------------------------------------------------------------------
*
* drcCifPointToSegment --
* drcCifPointToSegment
*
* Euclidean-distance point-to-segment distance (squared)
* calculation (borrowed from XCircuit)
@ -498,39 +468,12 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
#ifdef MAGIC_WRAPPER
/* Execute pending Tcl events, so the DRC process doesn't block. */
/* WARNING: This code cannot be enabled until some method is
* worked out to determine if any event resulted in a change
* to the DRC check plane which would invalidate the current
* search. If so, the search must end immediately and the
* area being checked must be reinstated. The code was added
* to see how it speeds up the response time of magic when
* some of the DRC rules are compute-intensive. It speeds up
* performance enough that it is worthwhile to implement the
* method just mentioned.
*/
#if 0
UndoEnable();
while (Tcl_DoOneEvent(TCL_DONT_WAIT));
UndoDisable();
#endif
#endif
}
drcCifCheck(&arg);
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
return (errors);
}
/* Expect that keeping around 3 MaxRectsData records should be sufficient
* to avoid recomputing drcCanonicalMaxwidth() multiple times. Note that
* if a PDK sets up multiple rules on an edge which all require running
* drcCanonicalMaxwidth(), then this cache size may need to be revisited.
*/
#define MAXRECTSCACHE 3
/*
* ----------------------------------------------------------------------------
*
@ -568,19 +511,6 @@ drcTile (tile, dinfo, arg)
int triggered;
int cdist, dist, ccdist, result;
/* Keep up to three MaxRectsData records to avoid doing the same
* expensive computation more than once.
*
* mrdcache[0] will be used for the tpleft tile, since it will never
* be reused. mrdcache[1] and mrdcache[2] will be used for the tile
* itself. Note that if more than 2 DRCCookie entries for the same
* edge require drcCanonicalMaxwidth(), then mrdcache[2] will be
* re-used so that at least mrdcache[1] is always a cache hit.
*/
static MaxRectsData *mrdcache[MAXRECTSCACHE] = {NULL, NULL, NULL};
DRCCookie *cptrcache;
arg->dCD_constraint = &errRect;
/*
@ -722,8 +652,6 @@ drcTile (tile, dinfo, arg)
DRCstatEdges++;
}
cptrcache = NULL;
/*
* Check design rules along a vertical boundary between two tiles.
*
@ -800,12 +728,13 @@ drcTile (tile, dinfo, arg)
cptr = cptr->drcc_next)
{
/* Handle rule exceptions and exemptions */
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE)
{
PropertyRecord *proprec;
bool propfound, isinside = FALSE;
char *name;
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
char idx = cptr->drcc_exception;
if (idx < 0) idx = -idx - 1;
name = DRCCurStyle->DRCExceptionList[idx];
/* Is there any exception area defined? */
@ -814,27 +743,35 @@ drcTile (tile, dinfo, arg)
/* If an exception area exists, is the error edge inside? */
if (propfound)
{
Rect redge;
int i;
Rect r, redge;
redge.r_xbot = redge.r_xtop = edgeX;
redge.r_ybot = edgeBot;
redge.r_ytop = edgeTop;
isinside = FALSE;
for (i = 0; i < proprec->prop_len; i += 4)
{
if ((i + 4) > proprec->prop_len) break;
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&redge, &CIFSolidBits, drcFoundOneFunc,
(ClientData)NULL) == 1)
isinside = TRUE;
if (GEO_OVERLAP(&redge, &r))
{
isinside = TRUE;
break;
}
}
}
/* Exemption rules are ignored if the edge is inside
* an exception area. Exception rules are ignored if
* the edge is outside an exception area.
*/
if (!isinside && (!(cptr->drcc_exception & DRC_EXCEPTION_MASK) == 0))
continue;
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
continue;
if (!isinside && (cptr->drcc_exception >= 0)) continue;
if (isinside && (cptr->drcc_exception < 0)) continue;
}
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
@ -879,23 +816,12 @@ drcTile (tile, dinfo, arg)
if (cptr->drcc_flags & DRC_REVERSE)
{
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr,
&mrdcache[0]);
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr);
triggered = 0;
}
else
else if (firsttile)
{
if (cptrcache == NULL)
{
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
&mrdcache[1]);
cptrcache = cptr;
}
else if (cptrcache != cptr)
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
&mrdcache[2]);
else
mrd = mrdcache[1];
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
triggered = 0;
}
if (!trigpending || (DRCCurStyle->DRCFlags
@ -1186,8 +1112,6 @@ drcTile (tile, dinfo, arg)
}
}
cptrcache = NULL;
/*
* Check design rules along a horizontal boundary between two tiles.
*
@ -1260,41 +1184,55 @@ drcTile (tile, dinfo, arg)
cptr = cptr->drcc_next)
{
/* Handle rule exceptions and exemptions */
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE)
{
PropertyRecord *proprec;
bool propfound, isinside = FALSE;
char *name;
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
char idx = cptr->drcc_exception;
if (idx < 0) idx = -idx - 1;
name = DRCCurStyle->DRCExceptionList[idx];
/* Is there any exception area defined? */
proprec = DBPropGet(arg->dCD_celldef, name, &propfound);
/* Quickest case: Rule is an exception but there are no
* exception areas.
*/
if ((!propfound) && (cptr->drcc_exception >= 0))
continue;
/* If an exception area exists, is the error edge inside? */
if (propfound)
{
Rect redge;
int i;
Rect r, redge;
redge.r_ybot = redge.r_ytop = edgeY;
redge.r_xbot = edgeLeft;
redge.r_xtop = edgeRight;
for (i = 0; i < proprec->prop_len; i += 4)
{
if ((i + 4) > proprec->prop_len) break;
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&redge, &CIFSolidBits, drcFoundOneFunc,
(ClientData)NULL) == 1)
isinside = TRUE;
if (GEO_OVERLAP(&redge, &r))
{
isinside = TRUE;
break;
}
}
}
/* Exemption rules are ignored if the edge is inside
* an exception area. Exception rules are ignored if
* the edge is outside an exception area.
*/
if (!isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) == 0))
continue;
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
continue;
if (isinside && (cptr->drcc_exception < 0)) continue;
if (!isinside && (cptr->drcc_exception >= 0)) continue;
}
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
@ -1334,23 +1272,12 @@ drcTile (tile, dinfo, arg)
if (cptr->drcc_flags & DRC_REVERSE)
{
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr,
&mrdcache[0]);
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
triggered = 0;
}
else
else if (firsttile)
{
if (cptrcache == NULL)
{
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
&mrdcache[1]);
cptrcache = cptr;
}
else if (cptrcache != cptr)
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
&mrdcache[2]);
else
mrd = mrdcache[1];
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
triggered = 0;
}
if (!trigpending || (DRCCurStyle->DRCFlags

View File

@ -510,17 +510,16 @@ MaxRectsExclude(
*/
MaxRectsData *
drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr)
drcCanonicalMaxwidth(starttile, dir, arg, cptr)
Tile *starttile;
int dir; /* direction of rule */
struct drcClientData *arg;
DRCCookie *cptr;
MaxRectsData **mrdptr;
{
int s, edgelimit;
Tile *tile,*tp;
TileTypeBitMask wrongtypes;
MaxRectsData *mrd = *mrdptr;
static MaxRectsData *mrd = (MaxRectsData *)NULL;
Rect *boundrect, boundorig;
/* Generate an initial array size of 8 for rlist and swap. */
@ -530,7 +529,6 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr)
mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect));
mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect));
mrd->listdepth = 8;
*mrdptr = mrd;
}
if (starttile == NULL) return mrd;

View File

@ -76,7 +76,7 @@ static int DRCtag = 0;
* while reading the DRC tech file section.
*/
static unsigned char drcCurException = DRC_EXCEPTION_NONE;
static char drcCurException = (char)DRC_EXCEPTION_NONE;
/*
* Forward declarations.
@ -405,9 +405,7 @@ drcWhyCreate(whystring)
* not already exist.
*
* Results:
* The index of the exception (which is an unsigned character containing
* the index in the lower 7 bits and a high bit indicating if the rule
* is an exception (0) or an exemption (1)).
* The index of the exception (which is a signed character).
*
* Side effects:
* Adds to the DRCExceptionList if "name" has not been used before.
@ -416,7 +414,7 @@ drcWhyCreate(whystring)
* ----------------------------------------------------------------------------
*/
unsigned char
char
drcExceptionCreate(name)
char *name;
{
@ -426,14 +424,13 @@ drcExceptionCreate(name)
/* NOTE: DRCExceptionList has "MASKHINTS_" prepended to the names */
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
if (!strcmp(name, DRCCurStyle->DRCExceptionList[i] + 10))
return (unsigned char)i;
return (char)i;
/* Note that i cannot be 127 as this is reserved for DRC_EXCEPTION_NONE */
if (i > 126)
if (i > 127)
{
/* I would be shocked if this code ever got executed. */
TxError("Error: Too many rule exceptions! Limit is 126.\n");
return DRC_EXCEPTION_NONE;
TxError("Error: Too many rule exceptions! Limit is 127.\n");
return (char)DRC_EXCEPTION_NONE;
}
/* Create a new list that is one entry longer than the old list.
@ -451,7 +448,7 @@ drcExceptionCreate(name)
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
freeMagic(DRCCurStyle->DRCExceptionList);
DRCCurStyle->DRCExceptionList = newlist;
return (unsigned char)i;
return (char)i;
}
/*
@ -735,7 +732,7 @@ DRCTechStyleInit()
}
drcCifInit();
drcCurException = DRC_EXCEPTION_NONE;
drcCurException = (char)DRC_EXCEPTION_NONE;
}
/*
@ -3729,10 +3726,9 @@ drcRectangle(argc, argv)
* Returns 0.
*
* Side effects:
* Updates drcCurException. drcCurException contains the index in
* the lower 7 bits, and a flag in the upper bit (0 = exception rule,
* 1 = exemption rule). The index can be recovered by masking off
* the upper bit.
* Updates drcCurException. drcCurException is zero or positive for
* exceptions and negative for exemptions. The index can be
* recovered from a negative value by negating it and subtracting 1.
*
* ----------------------------------------------------------------------------
*/
@ -3749,7 +3745,7 @@ drcException(argc, argv)
/* Assume that argc must be 2 because the parser insists upon it */
if (!strcmp(argv[1], "none"))
drcCurException = DRC_EXCEPTION_NONE;
drcCurException = (char)DRC_EXCEPTION_NONE;
else
drcCurException = drcExceptionCreate(argv[1]);
return (0);
@ -3767,9 +3763,9 @@ drcExemption(argc, argv)
/* Assume that argc must be 2 because the parser insists upon it */
if (!strcmp(argv[1], "none"))
drcCurException = DRC_EXCEPTION_NONE;
drcCurException = (char)DRC_EXCEPTION_NONE;
else
drcCurException = drcExceptionCreate(argv[1]) | DRC_EXCEPTION_MASK;
drcCurException = -(drcExceptionCreate(argv[1])) - 1;
return (0);
}

View File

@ -36,7 +36,7 @@ typedef struct drccookie
TileTypeBitMask drcc_mask; /* Legal types on RHS */
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
unsigned char drcc_exception; /* Index to list of exceptions */
char drcc_exception; /* Index to list of exceptions */
int drcc_edgeplane; /* Plane of edge */
int drcc_plane; /* Index of plane on which to check
* legal types. */
@ -92,10 +92,8 @@ typedef struct drccookie
#define DRC_UNPROCESSED CLIENTDEFAULT
#define DRC_PROCESSED 1
/* drcc_exception defaults to 255 meaning no exceptions/exemptions */
#define DRC_EXCEPTION_NONE ((unsigned char)0xff)
/* The high bit of the value determines if this is an exception or an exemption. */
#define DRC_EXCEPTION_MASK ((unsigned char)0x80)
/* drcc_exception defaults to -128 (0x80) meaning no exceptions/exemptions */
#define DRC_EXCEPTION_NONE (char)0x80
/*
* Background DRC (DRC Idle proc) for Tcl-based Magic

View File

@ -1088,7 +1088,6 @@ spcdevHierVisit(
if (!has_model)
{
fprintf(esSpiceF, " ");
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
}
@ -1139,7 +1138,6 @@ spcdevHierVisit(
if (!has_model)
{
fprintf(esSpiceF, " ");
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
}

View File

@ -3140,7 +3140,6 @@ spcdevVisit(
if (!has_model)
{
fprintf(esSpiceF, " ");
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
}
@ -3187,7 +3186,6 @@ spcdevVisit(
if (!has_model)
{
fprintf(esSpiceF, " ");
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
}

View File

@ -1835,8 +1835,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
ParamList *chkParam;
HashEntry *he;
ResValue resvalue;
LabRegion *node; /* Node connected to gate terminal */
LabelList *ll; /* Gate's label list */
for (chkParam = devptr->exts_deviceParams; chkParam
!= NULL; chkParam = chkParam->pl_next)
@ -1968,34 +1966,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
break;
}
}
/* If there are device attribute labels (labels attached to the device
* type ending with "^") with "=" in them, then treat them as extra
* parameters. Output each one and remove the gate attribute property
* from the label.
*/
node = (LabRegion *)ExtGetRegion(reg->treg_tile, reg->treg_dinfo);
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
{
if (ll->ll_attr == LL_GATEATTR)
{
char cs, *ct, *cp = ll->ll_label->lab_text;
if (strchr(cp, '=') != NULL)
{
/* Since this is an attribute label, it has a special character
* at the end, which needs to be stripped off while printing
* and then put back again.
*/
ct = ll->ll_label->lab_text + strlen(ll->ll_label->lab_text) - 1;
cs = *ct;
*ct = '\0';
fprintf(outFile, " %s", ll->ll_label->lab_text);
ll->ll_attr = LL_NOATTR;
*ct = cs;
}
}
}
}
/* Structures used by extTermAPFunc() for storing area and perimeter data */
@ -2755,56 +2725,6 @@ extOutputDevices(def, transList, outFile)
/* get corrected by extComputeEffectiveLW(). */
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, &ltbox);
GeoInclude(&ltbox, &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;
}
}
/*------------------------------------------------------*/

View File

@ -354,8 +354,8 @@ extHierConnections(ha, cumFlat, oneFlat)
if (!(lab->lab_flags & LABEL_STICKY)) continue;
r = lab->lab_rect;
if (!GEO_TOUCH(&r, &ha->ha_subArea)) continue;
GEOCLIP(&r, &ha->ha_subArea);
if (GEO_RECTNULL(&r)) continue;
cumDef = cumFlat->et_use->cu_def;
connected = &DBConnectTbl[lab->lab_type];

View File

@ -614,7 +614,6 @@ termtop:
termdone:
/* (continue) */
(void)0; /* older compilers need a statement after the label to prevent a compile error */
}
/* Clean up---Put the ClientData entries in the tiles back to

View File

@ -251,17 +251,6 @@ extSubtree(parentUse, reg, f)
if (result == 0) {
/* If result == FALSE then ha.ha_interArea is invalid. */
ha.ha_interArea = rlab;
/* Ensure that the interaction area is not zero */
if (ha.ha_interArea.r_xtop - ha.ha_interArea.r_xbot == 0)
{
ha.ha_interArea.r_xtop++;
ha.ha_interArea.r_xbot--;
}
if (ha.ha_interArea.r_ytop - ha.ha_interArea.r_ybot == 0)
{
ha.ha_interArea.r_ytop++;
ha.ha_interArea.r_ybot--;
}
result = 1;
}
else
@ -790,7 +779,6 @@ extSubtreeFunc(scx, ha)
*/
ha->ha_subArea = use->cu_bbox;
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
hy.hy_area = &ha->ha_subArea;
hy.hy_target = oneFlat->et_use;
hy.hy_prefix = TRUE;

View File

@ -63,6 +63,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <unistd.h>
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "utils/hash.h"

View File

@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include "utils/magsgtty.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "windows/windows.h"

View File

@ -17,6 +17,7 @@
#include <signal.h>
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h"
#include "graphics/graphics.h"
#include "windows/windows.h"

View File

@ -22,6 +22,7 @@
#include <X11/Xlib.h>
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "graphics/graphics.h"

View File

@ -28,6 +28,7 @@
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h"
#include "windows/windows.h"
#include "graphics/graphics.h"

View File

@ -15,6 +15,7 @@
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "windows/windows.h"

View File

@ -26,6 +26,7 @@
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h"
#include "windows/windows.h"
#include "graphics/graphics.h"

View File

@ -13,6 +13,7 @@
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "windows/windows.h"

View File

@ -23,6 +23,7 @@
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h"
#include "windows/windows.h"
#include "graphics/graphics.h"

View File

@ -13,6 +13,7 @@
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "windows/windows.h"

View File

@ -31,6 +31,7 @@
#include <X11/Xutil.h>
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "textio/txcommands.h"

View File

@ -22,6 +22,7 @@
#include <X11/Xlib.h>
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "graphics/graphics.h"

View File

@ -1356,7 +1356,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
}
if (extDev->subs == extNode)
{
if ((layoutDev->rd_nterms >= 4) && ((subs = layoutDev->rd_fet_subs) != NULL))
if ((subs = layoutDev->rd_fet_subs) != NULL)
{
if (subs->rn_name != NULL && notdecremented)
{

View File

@ -386,7 +386,7 @@ ResMoveDevices(node1, node2)
devptr = devptr->te_nextt;
if (device->rd_fet_gate == node1)
device->rd_fet_gate = node2;
else if ((device->rd_nterms >= 4) && (device->rd_fet_subs == node1))
else if (device->rd_fet_subs == node1)
device->rd_fet_subs = node2;
else if (device->rd_fet_source == node1)
device->rd_fet_source = node2;

View File

@ -1216,21 +1216,13 @@ SelectTransform(transform)
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 --
*
* Expand or unexpand all of the selected cells according to
* expandType.
* Expand all of the selected cells that are unexpanded, and
* unexpand all of those that are expanded.
*
* Results:
* None.
@ -1238,166 +1230,58 @@ typedef struct selExpData {
* Side effects:
* The contents of the selected cells will become visible or
* 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
SelectExpand(mask, expandType, rootBox)
SelectExpand(mask)
int mask; /* Bits of this word indicate which
* windows the selected cells will be
* expanded in.
*/
int expandType; /* Operation to perform: Expand,
* unexpand, or expand toggle.
*/
Rect *rootBox; /* Area of root box, if selecting by
* cursor box area.
*/
{
/* Forward references */
extern int selExpandFunc();
extern int selExpandFunc(); /* Forward reference. */
SelExpData sed;
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);
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
selExpandFunc, INT2CD(mask));
}
/* ARGSUSED */
int
selExpandFunc(selUse, use, transform, sed)
selExpandFunc(selUse, use, transform, mask)
CellUse *selUse; /* Use from selection. */
CellUse *use; /* Use to expand (in actual layout). */
Transform *transform; /* Not used. */
SelExpData *sed; /* Information for expansion */
int mask; /* Windows in which to expand. */
{
int expandType = sed->sed_type;
int mask = sed->sed_mask;
Rect *rootBox = sed->sed_box;
/* 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.
/* Don't change expansion status of root cell: screws up
* DBWAreaChanged (need to always have at least top-level
* cell be expanded).
*/
if (rootBox != NULL)
if (use->cu_parent == NULL)
{
if ((expandType & DB_EXPAND_SURROUND_MASK) == DB_EXPAND_OVERLAP)
{
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;
}
TxError("Can't unexpand root cell of window.\n");
return 0;
}
/* If a rootBox was given, then the expansion is being done in the
* 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.
/* 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 ((expandType & DB_EXPAND_MASK) == DB_EXPAND)
if (DBDescendSubcell(use, mask))
{
/* 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_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);
}
DBExpand(selUse, mask, FALSE);
DBExpand(use, mask, FALSE);
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask,
(TileTypeBitMask *) NULL);
}
else if ((expandType & DB_EXPAND_MASK) == DB_UNEXPAND)
else
{
/* 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) && !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);
}
}
DBExpand(selUse, mask, TRUE);
DBExpand(use, mask, TRUE);
DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits);
}
return 0;
}

View File

@ -148,10 +148,6 @@ proc magic::make_texthelper { mgrpath } {
proc magic::analyze_labels {} {
global typedflt typesticky typeport
# Ensure units of microns
set curunits [units]
units microns
# Pick up values from the first entry returned
set tval [lindex [setlabel text] 0]
@ -161,7 +157,6 @@ proc magic::analyze_labels {} {
set oval [lindex [setlabel offset] 0]
set lval [lindex [setlabel layer] 0]
set kval [lindex [setlabel sticky] 0]
set sval [lindex [setlabel size] 0]
set isport [lindex [port exists] 0]
if {$isport} {
set pval [lindex [port index] 0]
@ -169,6 +164,14 @@ proc magic::analyze_labels {} {
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 insert 0 $tval
set jbtn [string map {NORTH N WEST W SOUTH S EAST E CENTER center} $jval]
@ -203,9 +206,6 @@ proc magic::analyze_labels {} {
pack .texthelper.layer.tent -side left -fill x -expand true
pack .texthelper.layer.btn2 -side left
}
# Revert units
units {*}$curunits
}
@ -220,9 +220,6 @@ proc magic::change_label {} {
return
}
set curunits [units]
units microns
set ltext [.texthelper.text.tent get]
set lfont [.texthelper.font.btn cget -text]
set lsize [.texthelper.size.tent get]
@ -250,10 +247,13 @@ proc magic::change_label {} {
}
}
if {$lsize != ""} {
setlabel size $lsize
setlabel size ${lsize}um
}
if {$loff != ""} {
set oldunits [units]
units internal
setlabel offset [join $loff]
units $oldunits
}
if {$lrot != ""} {
setlabel rotate $lrot
@ -274,8 +274,6 @@ proc magic::change_label {} {
port remove
}
}
units {*}$curunits
}
proc magic::make_new_label {} {

View File

@ -12,13 +12,6 @@
# Added spice-to-layout procedure
# March 4, 2026
# Changed to make use of new "units" command
# March 26, 2026
# Added behavior to handle ideal devices (resistor, capacitor,
# 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
# supply a namespace that is the "library name". For each
@ -209,7 +202,7 @@ proc magic::generate_layout_add {subname subpins complist library} {
select cell $inst
delete
}
cellname delete $child -noprompt
cellname delete $child
}
}
}
@ -288,13 +281,8 @@ proc magic::generate_layout_add {subname subpins complist library} {
set paramlist {}
# NOTE: This routine deals with subcircuit calls and devices
# with models. There are two exceptions, for toolkits which
# wish to implement a way to generate unmodeled capacitors,
# resistors, or inductors based on value; for example, metal
# interdigitated capacitors. For those exceptions, the device
# value is recast as a parameter called "value", and the device
# is given a model "capacitor", "resistor", or "inductor",
# respectively.
# with models. It needs to determine when a device is instantiated
# without a model, and ignore such devices.
# Parse SPICE line into pins, device name, and parameters. Make
# sure parameters incorporate quoted expressions as {} or ''.
@ -338,23 +326,6 @@ proc magic::generate_layout_add {subname subpins complist library} {
set devtype [lindex $pinlist end]
set pinlist [lrange $pinlist 0 end-1]
# Ideal device check: "devtype" will start with a digit.
# The instname will begin with "c", "r", or "l".
if {[regexp {^([0-9\.]+.*)} $devtype pval]} {
set comptype [string tolower [string range $instname 0 0]]
if {$comptype == "c"} {
lappend paramlist [list value $pval]
set devtype capacitor
} elseif {$comptype == "r"} {
lappend paramlist [list value $pval]
set devtype resistor
} elseif {$comptype == "l"} {
lappend paramlist [list value $pval]
set devtype inductor
}
}
set mult 1
foreach param $paramlist {
set parmname [lindex $param 0]
@ -366,27 +337,6 @@ proc magic::generate_layout_add {subname subpins complist library} {
}
}
# Check if devtype has routines by looking for ${devtype}_defaults.
# If not found, do a case-insensitive check against all devices
# before deciding that devtype is a subcircuit and not a device.
# If found by case-insensitive check, then change the device name
# to the one used in the library.
if {$library != ""} {
set alldevices [namespace eval ::${library} {info procs}]
} else {
set alldevices [namespace eval ::${PDKNAMESPACE} {info procs}]
}
set devdefault [lsearch $alldevices ${devtype}_defaults]
if {$devdefault == -1} {
set devdefault [lsearch -nocase $alldevices ${devtype}_defaults]
if {$devdefault != -1} {
set devprocname [lindex $alldevices $devdefault]
set devproclist [split $devprocname "_"]
set devtype [lindex $devproclist 0]
}
}
# devtype is assumed to be in library. If not, it will attempt to
# use 'getcell' on devtype. Note that this code depends on the
# PDK setting varible PDKNAMESPACE.
@ -550,7 +500,7 @@ proc magic::netlist_to_layout {netfile library} {
set subname [lindex $ftokens 1]
set subpins [lrange $ftokens 2 end]
set insub true
} elseif {[regexp -nocase {^[xmcrldq]([^ \t]+)[ \t](.*)$} $line \
} elseif {[regexp -nocase {^[xmcrdq]([^ \t]+)[ \t](.*)$} $line \
valid instname rest]} {
lappend toplist $line
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
@ -565,7 +515,7 @@ proc magic::netlist_to_layout {netfile library} {
set subname ""
set subpins ""
set complist {}
} elseif {[regexp -nocase {^[xmcrldq]([^ \t]+)[ \t](.*)$} $line \
} elseif {[regexp -nocase {^[xmcrdq]([^ \t]+)[ \t](.*)$} $line \
valid instname rest]} {
lappend complist $line
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
@ -848,16 +798,11 @@ proc magic::gencell_change {instname gencell_type library parameters} {
set pdefaults [${library}::${gencell_type}_defaults]
# Pull user-entered values from dialog
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]} {
# Setting special parameter "gencell" forces the gencell to change type
set gencell_type [dict get $parameters gencell]
@ -875,20 +820,6 @@ proc magic::gencell_change {instname gencell_type library parameters} {
set gsuffix [magic::get_gencell_hash ${parameters}]
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
# changed as evidenced by the cell suffix not changing, then nothing further
# needs to be done.
@ -924,28 +855,18 @@ proc magic::gencell_change {instname gencell_type library parameters} {
if {$abox != ""} {box values {*}$abox}
set newinstname [getcell $gname $orient]
select cell $newinstname
set origname $newinstname
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
} 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 {[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
cellname delete $old_gname
}
} else {
@ -958,7 +879,6 @@ proc magic::gencell_change {instname gencell_type library parameters} {
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.
@ -973,14 +893,6 @@ proc magic::gencell_change {instname gencell_type library parameters} {
"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
eval "box values $savebox"
@ -1111,47 +1023,38 @@ proc magic::get_gencell_name {gencell_type} {
# gives a result that is repeatable for the same set of
# parameter values with a very low probability of a collision.
#
# The hash function is murmur3 but reduced from 32 to 30 bits
# so that the result can form a 6-character value in base36
# with all characters being valid for a SPICE subcell name
# (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.
# The hash function is similar to elfhash but reduced from 32
# to 30 bits so that the result can form a 6-character value
# in base32 with all characters being valid for a SPICE subcell
# name (e.g., alphanumeric only and case-insensitive).
#----------------------------------------------------------------
proc magic::get_gencell_hash {parameters} {
# Canonicalize: sort by key
set keys [lsort [dict keys $parameters]]
# Build input string (values only, but delimited)
set input ""
foreach k $keys {
set value [magic::normalize_value [dict get $parameters $k]]
append input "${value};"
set hash 0
# Apply hash
dict for {key value} $parameters {
foreach s [split $value {}] {
set hash [expr {($hash << 4) + [scan $s %c]}]
set high [expr {$hash & 0x03c0000000}]
set hash [expr {$hash ^ ($high >> 30)}]
set hash [expr {$hash & (~$high)}]
}
}
# Compute Murmur hash
set hash [magic::murmur3_32 $input]
# Convert to 6-character base32
# Divide hash up into 5 bit values and convert to base32
# using letters A-Z less I and O, and digits 2-9.
set cvals ""
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} {
set bval [expr {$oval + 50}] ;# '2'-'9'
} elseif {$oval < 16} {
set bval [expr {$oval + 57}] ;# 'A'-'H'
} elseif {$oval < 21} {
set bval [expr {$oval + 58}] ;# 'J'-'N'
} else {
set bval [expr {$oval + 59}] ;# 'P'-'Z'
}
append cvals [binary format c* $bval]
set bval [expr {$oval + 50}]
} elseif {$oval < 16} {
set bval [expr {$oval + 57}]
} elseif {$oval < 21} {
set bval [expr {$oval + 58}]
} else {
set bval [expr {$oval + 59}]
}
append cvals [binary format c* $bval]
}
return $cvals
}
@ -1275,7 +1178,17 @@ proc magic::add_entry {pname ptext parameters} {
proc magic::add_check_callbacks {gencell_type library} {
set wlist [winfo children .params.body.area.edits]
foreach w $wlist {
if {[regexp {\.params\.body\.area\.edits\.(.+)_.+} $w valid pname]} {
if {[regexp {\.params\.body\.area\.edits\.(.+)_ent} $w valid pname]} {
# Add callback on enter or focus out
bind $w <Return> \
"magic::update_dialog {} $pname $gencell_type $library"
bind $w <FocusOut> \
"magic::update_dialog {} $pname $gencell_type $library"
}
if {[regexp {\.params\.body\.area\.edits\.(.+)_sel} $w valid pname]} {
magic::add_dependency \{\} $gencell_type $library $pname
}
if {[regexp {\.params\.body\.area\.edits\.(.+)_chk} $w valid pname]} {
magic::add_dependency \{\} $gencell_type $library $pname
}
}
@ -1294,16 +1207,6 @@ proc magic::add_check_callbacks {gencell_type library} {
# dictionary.
#
# Also handle dependencies on checkboxes and selection lists
#
# If dependency callbacks exist, then chain them together.
# A final default dependency will be added to all entries
# to run the "check" procedure for the device. Dependencies
# 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} {
@ -1318,28 +1221,21 @@ proc magic::add_dependency {callback gencell_type library args} {
foreach pname $args {
if {[lsearch $clist .params.body.area.edits.${pname}_ent] >= 0} {
# Add callback on enter or focus out
set oldbind [bind .params.body.area.edits.${pname}_ent <Return>]
set newbind "magic::update_dialog $callback $pname $gencell_type $library"
if {$oldbind != {}} {set newbind "$oldbind ; $newbind"}
bind .params.body.area.edits.${pname}_ent <Return> $newbind
set oldbind [bind .params.body.area.edits.${pname}_ent <FocusOut>]
set newbind "magic::update_dialog $callback $pname $gencell_type $library"
if {$oldbind != {}} {set newbind "$oldbind ; $newbind"}
bind .params.body.area.edits.${pname}_ent <FocusOut> $newbind
bind .params.body.area.edits.${pname}_ent <Return> \
"magic::update_dialog $callback $pname $gencell_type $library"
bind .params.body.area.edits.${pname}_ent <FocusOut> \
"magic::update_dialog $callback $pname $gencell_type $library"
} elseif {[lsearch $clist .params.body.area.edits.${pname}_chk] >= 0} {
# Add callback on checkbox change state
set oldcmd [.params.body.area.edits.${pname}_chk cget -command]
set newcmd "magic::update_dialog $callback $pname $gencell_type $library"
if {$oldcmd != {}} {set newcmd "$oldcmd ; $newcmd"}
.params.body.area.edits.${pname}_chk configure -command $newcmd
.params.body.area.edits.${pname}_chk configure -command \
"magic::update_dialog $callback $pname $gencell_type $library"
} elseif {[lsearch $clist .params.body.area.edits.${pname}_sel] >= 0} {
set smenu .params.body.area.edits.${pname}_sel.menu
set sitems [${smenu} index end]
for {set idx 0} {$idx <= $sitems} {incr idx} {
set oldcmd [${smenu} entrycget $idx -command]
set newcmd "magic::update_dialog $callback $pname $gencell_type $library"
if {$oldcmd != {}} {set newcmd "$oldcmd ; $newcmd"}
${smenu} entryconfigure $idx -command $newcmd
set curcommand [${smenu} entrycget $idx -command]
${smenu} entryconfigure $idx -command "$curcommand ; \
magic::update_dialog $callback $pname $gencell_type $library"
}
}
}
@ -1360,13 +1256,13 @@ proc magic::update_dialog {callback pname gencell_type library} {
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
}
if {$callback != {}} {
set parameters [$callback $pname $parameters]
}
if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \
checkerr]} {
puts stderr $checkerr
}
if {$callback != {}} {
set parameters [$callback $pname $parameters]
}
magic::gencell_setparams $parameters
}
@ -1730,99 +1626,3 @@ 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
}

View File

@ -534,11 +534,8 @@ proc magic::enable_tools {} {
# The user can change these bindings at will by using the
# "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 nettool
magic::macro copy netlist
magic::macro copy pick
magic::tool wiring
@ -552,7 +549,7 @@ proc magic::enable_tools {} {
macro Button4 "wire incr width ; wire show"
macro Button5 "wire decr width ; wire show"
magic::tool nettool
magic::tool netlist
macro Button1 "netlist select"
macro Button2 "netlist join"
macro Button3 "netlist terminal"
@ -707,8 +704,8 @@ proc magic::tool {{type next}} {
if {$type == "next"} {
switch $Opts(tool) {
box { set type wiring }
wiring { set type nettool }
nettool { set type pick }
wiring { set type netlist }
netlist { set type pick }
pick { set type box }
}
}
@ -764,9 +761,9 @@ proc magic::tool {{type next}} {
set Opts(tool) wiring
cursor 19 ;# sets the cursor
}
nettool {
netlist {
puts stdout {Switching to NETLIST tool.}
set Opts(tool) nettool
set Opts(tool) netlist
cursor 18 ;# sets the cursor
}
pick {

View File

@ -25,8 +25,6 @@
#ifndef _MAGIC__TEXTIO__TEXTIO_H
#define _MAGIC__TEXTIO__TEXTIO_H
#include <stdarg.h> /* va_list */
#include "utils/magic.h"
#include "utils/dqueue.h" /* DQueue */

View File

@ -42,6 +42,20 @@ typedef struct {
#define TX_PROMPT '>'
#define TX_CMD_PROMPT ":"
/* all of the state associated with a tty terminal */
#if !defined(SYSV) && !defined(CYGWIN) && !defined(__OpenBSD__) && !defined(EMSCRIPTEN)
#if defined(HAVE_SYS_IOCTL_COMPAT_H) || defined(HAVE_SGTTY_H)
#if defined(HAVE_SYS_IOCTL_COMPAT_H)
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
#elif defined(HAVE_SGTTY_H)
#include <sgtty.h>/* legacy - struct sgttyb{} defn */
#endif
typedef struct {
struct sgttyb tx_i_sgtty;
struct tchars tx_i_tchars;
} txTermState;
#endif /* HAVE_SYS_IOCTL_COMPAT_H || HAVE_SGTTY_H */
#endif /* SYSV */
extern bool TxGetInputEvent(bool block, bool returnOnSigWinch);

View File

@ -39,6 +39,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/t
#endif
#include "tcltk/tclmagic.h"
#include "utils/magsgtty.h"
#include "utils/magic.h"
#include "textio/textio.h"
#include "utils/geometry.h"

View File

@ -32,13 +32,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <dirent.h>
#include "utils/magsgtty.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "utils/main.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "textio/txcommands.h"
#include "textio/textioInt.h"
#include "utils/magsgtty.h" /* txTermState */
#include "utils/dqueue.h"
#include "utils/macros.h"
#include "utils/hash.h"
@ -1224,21 +1225,36 @@ TxGetLine(
* ----------------------------------------------------------------------------
*/
#if defined(SYSV) || defined(CYGWIN)
void
txGetTermState(
struct termio *buf)
{
ioctl( fileno( stdin ), TCGETA, buf);
}
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
void
txGetTermState(
struct termios *buf)
{
(void) tcgetattr(fileno(stdin), buf);
}
#else
void
txGetTermState(
txTermState *buf)
{
#if defined(HAVE_TERMIOS_H)
(void) tcgetattr(fileno(stdin), &buf->termios);
#elif defined(HAVE_TERMIO_H)
ioctl(fileno(stdin), TCGETA, &buf->termio);
#else /* sgtty */
ASSERT(TxStdinIsatty, "txGetTermState");
/* save the current terminal characteristics */
(void) ioctl(fileno(stdin), TIOCGETP, (char *) &buf->tx_i_sgtty);
(void) ioctl(fileno(stdin), TIOCGETC, (char *) &buf->tx_i_tchars);
#endif
(void) ioctl(fileno(stdin), TIOCGETP, (char *) &(buf->tx_i_sgtty) );
(void) ioctl(fileno(stdin), TIOCGETC, (char *) &(buf->tx_i_tchars) );
}
#endif /* SYSV */
/*
@ -1257,17 +1273,24 @@ txGetTermState(
void
txSetTermState(
txTermState *buf)
#if defined(SYSV) || defined(CYGWIN)
struct termio *buf
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
struct termios *buf
#else
txTermState *buf
#endif /* SYSV */
)
{
#if defined(HAVE_TERMIOS_H)
(void) tcsetattr(fileno(stdin), TCSANOW, &buf->termios);
#elif defined(HAVE_TERMIO_H)
ioctl(fileno(stdin), TCSETAF, &buf->termio);
#else /* sgtty */
#if defined(SYSV) || defined(CYGWIN)
ioctl( fileno(stdin), TCSETAF, buf );
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
(void) tcsetattr( fileno(stdin), TCSANOW, buf );
#else
/* set the current terminal characteristics */
(void) ioctl(fileno(stdin), TIOCSETN, (char *) &buf->tx_i_sgtty);
(void) ioctl(fileno(stdin), TIOCSETC, (char *) &buf->tx_i_tchars);
#endif
(void) ioctl(fileno(stdin), TIOCSETN, (char *) &(buf->tx_i_sgtty) );
(void) ioctl(fileno(stdin), TIOCSETC, (char *) &(buf->tx_i_tchars) );
#endif /* SYSV */
}
@ -1290,27 +1313,37 @@ txSetTermState(
void
txInitTermRec(
txTermState *buf)
#if defined(SYSV) || defined(CYGWIN)
struct termio *buf
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
struct termios *buf
#else
txTermState *buf
#endif /* SYSV */
)
{
#if defined(HAVE_TERMIOS_H)
buf->termios.c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
buf->termios.c_cc[ VMIN ] = 1;
buf->termios.c_cc[ VTIME ] = 0;
#elif defined(HAVE_TERMIO_H)
buf->termio.c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
buf->termio.c_cc[ VMIN ] = 1;
buf->termio.c_cc[ VTIME ] = 0;
#else /* sgtty */
#if defined(SYSV) || defined(CYGWIN) || defined(__OpenBSD__) || defined(EMSCRIPTEN)
buf->c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
buf->c_cc[ VMIN ] = 1;
buf->c_cc[ VTIME ] = 0;
#else
/* set things up for us, turn off echo, turn on cbreak, no EOF */
buf->tx_i_sgtty.sg_flags |= CBREAK;
buf->tx_i_sgtty.sg_flags &= ~ECHO;
buf->tx_i_tchars.t_eofc = -1;
#endif
#endif /* SYSV */
}
#if defined(SYSV) || defined(CYGWIN)
struct termio closeTermState;
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
struct termios closeTermState;
#else
static txTermState closeTermState;
#endif /* SYSV */
static bool haveCloseState = FALSE;
@ -1333,21 +1366,21 @@ static bool haveCloseState = FALSE;
void
txSaveTerm(void)
{
#if defined(HAVE_TERMIOS_H)
(void) tcgetattr(fileno(stdin), &closeTermState.termios);
txEraseChar = closeTermState.termios.c_cc[VERASE];
txKillChar = closeTermState.termios.c_cc[VKILL];
TxEOFChar = closeTermState.termios.c_cc[VEOF];
TxInterruptChar = closeTermState.termios.c_cc[VINTR];
#if defined(SYSV) || defined(CYGWIN)
ioctl( fileno( stdin ), TCGETA, &closeTermState);
txEraseChar = closeTermState.c_cc[VERASE];
txKillChar = closeTermState.c_cc[VKILL];
TxEOFChar = closeTermState.c_cc[VEOF];
TxInterruptChar = closeTermState.c_cc[VINTR];
haveCloseState = TRUE;
#elif defined(HAVE_TERMIO_H)
ioctl(fileno(stdin), TCGETA, &closeTermState.termio);
txEraseChar = closeTermState.termio.c_cc[VERASE];
txKillChar = closeTermState.termio.c_cc[VKILL];
TxEOFChar = closeTermState.termio.c_cc[VEOF];
TxInterruptChar = closeTermState.termio.c_cc[VINTR];
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
(void) tcgetattr( fileno( stdin ), &closeTermState);
txEraseChar = closeTermState.c_cc[VERASE];
txKillChar = closeTermState.c_cc[VKILL];
TxEOFChar = closeTermState.c_cc[VEOF];
TxInterruptChar = closeTermState.c_cc[VINTR];
haveCloseState = TRUE;
#else /* sgtty */
#else
struct ltchars lt;
txGetTermState(&closeTermState);
(void) ioctl(fileno(stdin), TIOCGLTC, (char *) &lt);
@ -1360,7 +1393,7 @@ txSaveTerm(void)
TxEOFChar = closeTermState.tx_i_tchars.t_eofc;
TxInterruptChar = closeTermState.tx_i_tchars.t_intrc;
haveCloseState = TRUE;
#endif
#endif /* SYSV */
}
@ -1381,7 +1414,13 @@ txSaveTerm(void)
void
TxSetTerminal(void)
{
#if defined(SYSV) || defined(CYGWIN)
struct termio buf;
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
struct termios buf;
#else
txTermState buf;
#endif /* SYSV */
#ifdef MAGIC_WRAPPER
/* If using Tk console, don't mess with the terminal settings; */

View File

@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <string.h>
#include <unistd.h>
#include "utils/magsgtty.h"
#include "utils/magic.h"
#include "textio/textio.h"
#include "utils/geometry.h"

View File

@ -31,6 +31,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <sys/stat.h>
#include <unistd.h>
#include "utils/magsgtty.h"
#include "utils/magic.h"
#include "textio/textio.h"
#include "utils/geometry.h"

View File

@ -21,54 +21,44 @@
#ifndef _MAGIC__UTILS__MAGSGTTY_H
#define _MAGIC__UTILS__MAGSGTTY_H
/* maybe this can be #ifndef HAVE_TERMIO_H */
#if !defined(SYSV) && !defined(CYGWIN)
#if defined(HAVE_TERMIOS_H)
/* In modern times everything has POSIX */
#include <termios.h>
# ifdef ALPHA
# undef MAX
# undef MIN
# endif
#ifdef HAVE_SYS_IOCTL_H
/* Linux glibx 2.x - present
* FreeBSD 14.3-RELEASE - present
* Solaris 11.4 - present
*/
#include <sys/ioctl.h>
#endif
/* unclear what platform requires this OpenBSD/FreeBSD ? */
# ifndef COMPAT_43TTY
# define COMPAT_43TTY
# endif
#elif defined(HAVE_TERMIO_H)
/* Linux glibx 2.x - present (just includes termios.h & sys/ioctl.h)
* Linux glibc 2.45+ - not present
* FreeBSD 14.3-RELEASE - not present
* Solaris 11.4 - present
*/
#include <termio.h>
#else /* sgtty */
#if defined(HAVE_SYS_IOCTL_COMPAT_H)
/* Linux glibc2.x - not present
* FreeBSD 14.3-RELEASE - not present
* Solaris 11.4 - not present
*/
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
#elif defined(HAVE_SGTTY_H)
/* Linux glibc2.x - present (includes sys/ioctl.h)
* FreeBSD 14.3-RELEASE - not present
* Solaris 11.4 - present
*/
#include <sgtty.h> /* legacy - struct sgttyb{} defn */
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
/* all of the state associated with a tty terminal */
typedef struct {
#if defined(HAVE_TERMIOS_H)
struct termios termios;
#elif defined(HAVE_TERMIO_H)
struct termio termio;
#else /* sgtty */
struct sgttyb tx_i_sgtty;
struct tchars tx_i_tchars;
#include <termios.h>
#elif defined(HAVE_SYS_IOCTL_COMPAT_H)
/* unclear which platform(s) require <sys/ioctl_compat.h> and the structure
* of this file is such that it will try to include it by default, better
* to invert the #if and only select this on the known platforms that need
* it so that <termios.h> goes by default, which exists on MacOSX, Linux, etc..
* many possible solutions to make this work by default:
* HAVE_SYS_IOCTL_COMPAT_H ? HAVE_TERMIOS_H ? !defined(linux) at top (MaxOSX is BSD type)
*/
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
#elif defined(HAVE_SGTTY_H)
#include <sgtty.h> /* legacy - struct sgttyb{} defn */
#endif
} txTermState;
#else
#if defined(HAVE_TERMIO_H)
#include <termio.h>
#endif
#endif /* !SYSV && !CYGWIN */
#endif /* _MAGIC__UTILS__MAGSGTTY_H */

View File

@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/hash.h"
#include "utils/macros.h"
#include "textio/textio.h"

View File

@ -33,6 +33,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "tcltk/tclmagic.h"
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "utils/signals.h"

View File

@ -1056,7 +1056,6 @@ windDoMacro(w, cmd, interactive)
bool do_help = FALSE;
bool do_reverse = FALSE;
char *searchterm = NULL;
char *clientName = NULL;
macrodef *cMacro;
HashTable *clienttable;
HashEntry *h;
@ -1074,25 +1073,9 @@ windDoMacro(w, cmd, interactive)
argstart = 1;
if (cmd->tx_argc == 1)
wc = DBWclientID; /* Default client */
wc = DBWclientID; /* Added by NP 11/15/04 */
else if (cmd->tx_argc > 1)
{
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)
{
@ -1133,15 +1116,6 @@ windDoMacro(w, cmd, interactive)
wc = DBWclientID;
}
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;
}
@ -1173,53 +1147,26 @@ windDoMacro(w, cmd, interactive)
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
{
wc = 0;
argstart++;
return;
}
}
}
/* 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();
else
argstart++;
if (cmd->tx_argc == argstart)
{
if (clientName == NULL)
h = NULL;
else
h = HashLookOnly(&MacroClients, (char *)clientName);
if (h == NULL)
if (wc == (WindClient)0)
{
#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
TxError("No such client.\n");
return;
}
h = HashLookOnly(&MacroClients, (char *)wc);
if (h == NULL)
return;
else
{
clienttable = (HashTable *)HashGetValue(h);

View File

@ -954,7 +954,7 @@ windXviewCmd(w, cmd)
celluse = (CellUse *) (w->w_surfaceID);
DBExpandAll(celluse, &(celluse->cu_bbox),
((DBWclientRec *)w->w_clientData)->dbw_bitmask, DB_UNEXPAND,
((DBWclientRec *)w->w_clientData)->dbw_bitmask, FALSE,
ViewUnexpandFunc,
(ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));