Extended the "property" command and modified the way that properties
are handled. Properties were previously only character strings, which had become cumbersome because properties were being used for mask hints and bounding boxes, with the necessity of constantly converting values from string to integer and back, which can cause a performance impact as well as just being messy. The main difference to the command is the addition of an optional first keyword argument for the property type, which can be "string", "integer", "dimension", or "double". All types except "string" can consist of multiple values. Multiple values can be specified as separate arguments on the command line, so that, for example, values of FIXED_BBOX or MASKHINTS_* no longer need to be quoted. In addition, this completes the handling of "units" implemented recently, as all properties of the type "dimension" can be entered in the current units, will display in the current units, and will scale with the database.
This commit is contained in:
parent
7e9b6fb61e
commit
cb30ac369b
|
|
@ -505,28 +505,33 @@ calmaParseStructure(
|
|||
|
||||
if (CalmaReadOnly || predefined)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
char cstring[1024];
|
||||
|
||||
/* Writing the file position into a string is slow, but */
|
||||
/* it prevents requiring special handling when printing */
|
||||
/* out the properties. */
|
||||
|
||||
char *fpcopy = (char *)mallocMagic(20);
|
||||
char *fncopy;
|
||||
|
||||
/* Substitute variable for PDK path or ~ for home directory */
|
||||
/* the same way that cell references are handled in .mag files. */
|
||||
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
||||
fncopy = StrDup(NULL, cstring);
|
||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
|
||||
|
||||
fpcopy = (char *)mallocMagic(20);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||
proprec->prop_len = 1;
|
||||
proprec->prop_value.prop_double[0] = filepos;
|
||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)proprec);
|
||||
|
||||
filepos = FTELL(calmaInputFile);
|
||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
|
||||
|
||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||
proprec->prop_len = 1;
|
||||
proprec->prop_value.prop_double[0] = filepos;
|
||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)proprec);
|
||||
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) - 7 +
|
||||
strlen(cstring));
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = 1;
|
||||
strcpy(proprec->prop_value.prop_string, cstring);
|
||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)proprec);
|
||||
|
||||
if (predefined)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ calmaDumpStructure(
|
|||
|
||||
/* Is view abstract? */
|
||||
DBPropGet(edef, "LEFview", &isAbstract);
|
||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||
|
||||
if (isAbstract && isReadOnly)
|
||||
{
|
||||
|
|
@ -738,7 +738,7 @@ calmaFullDump(
|
|||
* names in the GDS file do not shadow any names in the database.
|
||||
*/
|
||||
|
||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||
{
|
||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||
|
|
@ -918,7 +918,7 @@ calmaProcessDef(
|
|||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||
DBPropGet(def, "CIFhier", &needHier);
|
||||
|
||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||
|
||||
/* When used with "calma addendum true", don't output the read-only */
|
||||
/* cells. This makes the library incomplete and dependent on the */
|
||||
|
|
@ -1033,13 +1033,12 @@ calmaProcessDef(
|
|||
}
|
||||
else
|
||||
{
|
||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||
cellend = (off_t)cval;
|
||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
|
@ -1056,7 +1055,6 @@ calmaProcessDef(
|
|||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellstart = (off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
|
|
@ -1263,7 +1261,7 @@ calmaOutFunc(
|
|||
int dbunits;
|
||||
calmaOutputStruct cos;
|
||||
bool propfound;
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
|
||||
cos.f = f;
|
||||
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
||||
|
|
@ -1323,14 +1321,20 @@ calmaOutFunc(
|
|||
|
||||
/* Include any fixed bounding box as part of the area to process, */
|
||||
/* in case the fixed bounding box is larger than the geometry. */
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
Rect bbox;
|
||||
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
GeoInclude(&bbox, &bigArea);
|
||||
}
|
||||
}
|
||||
|
||||
CIFErrorDef = def;
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ calmaDumpStructureZ(
|
|||
|
||||
/* Is view abstract? */
|
||||
DBPropGet(edef, "LEFview", &isAbstract);
|
||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||
|
||||
if (isAbstract && isReadOnly)
|
||||
{
|
||||
|
|
@ -716,7 +716,7 @@ calmaFullDumpZ(
|
|||
* names in the GDS file do not shadow any names in the database.
|
||||
*/
|
||||
|
||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||
{
|
||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||
|
|
@ -870,7 +870,7 @@ calmaProcessDefZ(
|
|||
DBPropGet(def, "GDS_START", &hasContent);
|
||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||
DBPropGet(def, "CIFhier", &needHier);
|
||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||
|
||||
/* When used with "calma addendum true", don't output the read-only */
|
||||
/* cells. This makes the library incomplete and dependent on the */
|
||||
|
|
@ -985,13 +985,12 @@ calmaProcessDefZ(
|
|||
}
|
||||
else
|
||||
{
|
||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||
cellend = (z_off_t)cval;
|
||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
|
@ -1008,7 +1007,6 @@ calmaProcessDefZ(
|
|||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellstart = (z_off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
|
|
@ -1186,6 +1184,7 @@ calmaOutFuncZ(
|
|||
int dbunits;
|
||||
calmaOutputStructZ cos;
|
||||
bool propfound;
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
extern int compport(const void *one, const void *two); /* Forward declaration */
|
||||
|
||||
|
|
@ -1247,14 +1246,20 @@ calmaOutFuncZ(
|
|||
|
||||
/* Include any fixed bounding box as part of the area to process, */
|
||||
/* in case the fixed bounding box is larger than the geometry. */
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
Rect bbox;
|
||||
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
GeoInclude(&bbox, &bigArea);
|
||||
}
|
||||
}
|
||||
|
||||
CIFErrorDef = def;
|
||||
|
|
|
|||
69
cif/CIFgen.c
69
cif/CIFgen.c
|
|
@ -4998,6 +4998,7 @@ CIFGenLayer(
|
|||
BridgeData *bridge;
|
||||
BloatData *bloats;
|
||||
bool hstop = FALSE;
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
bool found;
|
||||
|
||||
|
|
@ -5454,10 +5455,17 @@ CIFGenLayer(
|
|||
|
||||
if (origDef && (origDef->cd_flags & CDFIXEDBBOX))
|
||||
{
|
||||
propvalue = (char *)DBPropGet(origDef, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(origDef, "FIXED_BBOX", &found);
|
||||
if (!found) break;
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) != 4) break;
|
||||
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
}
|
||||
|
||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||
bbox.r_xbot *= cifScale;
|
||||
|
|
@ -5519,44 +5527,37 @@ CIFGenLayer(
|
|||
|
||||
case CIFOP_MASKHINTS:
|
||||
{
|
||||
int j, numfound;
|
||||
int n;
|
||||
char propname[512];
|
||||
char *propptr;
|
||||
char *layername = (char *)op->co_client;
|
||||
|
||||
sprintf(propname, "MASKHINTS_%s", layername);
|
||||
snprintf(propname, 512, "MASKHINTS_%s", layername);
|
||||
|
||||
propvalue = (char *)DBPropGet(cellDef, propname, &found);
|
||||
proprec = DBPropGet(cellDef, propname, &found);
|
||||
if (!found) break; /* No mask hints available */
|
||||
propptr = propvalue;
|
||||
while (*propptr)
|
||||
{
|
||||
numfound = sscanf(propptr, "%d %d %d %d",
|
||||
&bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop);
|
||||
|
||||
if (numfound != 4)
|
||||
if (proprec->prop_type == PROPERTY_TYPE_DIMENSION)
|
||||
{
|
||||
for (n = 0; n < proprec->prop_len; n += 4)
|
||||
{
|
||||
/* To do: Allow keyword "rect", "tri", or "poly"
|
||||
* at the start of the list and parse accordingly.
|
||||
* For now, this only flags an error.
|
||||
*/
|
||||
TxError("%s: Cannot read rectangle values.\n", propname);
|
||||
break;
|
||||
}
|
||||
cifPlane = curPlane;
|
||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||
bbox.r_xbot *= cifScale;
|
||||
bbox.r_xtop *= cifScale;
|
||||
bbox.r_ybot *= cifScale;
|
||||
bbox.r_ytop *= cifScale;
|
||||
cifScale = 1;
|
||||
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
|
||||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
while (*propptr && isspace(*propptr)) propptr++;
|
||||
while (*propptr && !isspace(*propptr)) propptr++;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
130
cif/CIFhier.c
130
cif/CIFhier.c
|
|
@ -211,53 +211,6 @@ typedef struct _maskHintsData
|
|||
CellDef *mh_def;
|
||||
} MaskHintsData;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* cifMaskHints --
|
||||
*
|
||||
* Copy a mask hint into a target cell by adding it to the
|
||||
* property list of the target cell. If the target cell already
|
||||
* has the same mask hint key, then the mask hint value is
|
||||
* appended to the property in the target cell def.
|
||||
*
|
||||
* Returns:
|
||||
* 0 to keep the search going.
|
||||
*
|
||||
* Side effects:
|
||||
* Modifies properties of the target cell def.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* DEPRECATED */
|
||||
int
|
||||
cifMaskHints(
|
||||
char *name,
|
||||
char *value,
|
||||
CellDef *targetDef)
|
||||
{
|
||||
char *propvalue, *newval;
|
||||
bool propfound;
|
||||
|
||||
if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
/* Check if name exists already in the flattened cell */
|
||||
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
/* Append value to the property */
|
||||
newval = mallocMagic(strlen(value) + strlen(propvalue) + 2);
|
||||
sprintf(newval, "%s %s", propvalue, value);
|
||||
}
|
||||
else
|
||||
newval = StrDup((char **)NULL, value);
|
||||
|
||||
DBPropPut(targetDef, name, newval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -279,67 +232,68 @@ cifMaskHints(
|
|||
int
|
||||
cifFlatMaskHints(
|
||||
char *name,
|
||||
char *value,
|
||||
PropertyRecord *proprec,
|
||||
MaskHintsData *mhd)
|
||||
{
|
||||
Rect r, newr;
|
||||
char *vptr, *newval, *lastval, *propvalue;
|
||||
bool propfound;
|
||||
int lastlen, numvals;
|
||||
int i, lastlen, numvals;
|
||||
PropertyRecord *newproprec, *oldproprec;
|
||||
|
||||
if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
newval = (char *)NULL;
|
||||
vptr = value;
|
||||
while (*vptr != '\0')
|
||||
/* Check if name exists already in the flattened cell */
|
||||
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
numvals = sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop);
|
||||
if (numvals == 4)
|
||||
{
|
||||
/* Transform rectangle to top level coordinates */
|
||||
GeoTransRect(mhd->mh_trans, &r, &newr);
|
||||
lastval = newval;
|
||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
||||
newval = mallocMagic(40 + lastlen);
|
||||
if (lastval)
|
||||
strcpy(newval, lastval);
|
||||
else
|
||||
*newval = '\0';
|
||||
sprintf(newval + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
||||
newr.r_xbot, newr.r_ybot, newr.r_xtop, newr.r_ytop);
|
||||
if (lastval) freeMagic(lastval);
|
||||
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) +
|
||||
(proprec->prop_len - 2) * sizeof(int));
|
||||
newproprec->prop_len = proprec->prop_len;
|
||||
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
}
|
||||
|
||||
/* Parse through the four values and check if there's more */
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check if name exists already in the flattened cell */
|
||||
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||
/* If there were existing entries, copy them into the new property */
|
||||
if (propfound)
|
||||
{
|
||||
/* Append newval to the property */
|
||||
lastval = newval;
|
||||
newval = mallocMagic(strlen(lastval) + strlen(propvalue) + 2);
|
||||
sprintf(newval, "%s %s", propvalue, lastval);
|
||||
freeMagic(lastval);
|
||||
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, newval);
|
||||
DBPropPut(mhd->mh_def, name, newproprec);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -824,46 +824,43 @@ CIFPaintCurrent(
|
|||
|
||||
if (lrec != NULL)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
char *propname;
|
||||
int proplen;
|
||||
|
||||
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
||||
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
||||
|
||||
propstr = (char *)NULL;
|
||||
|
||||
/* Turn all linked Rects into a mask-hints property in the
|
||||
* target cell.
|
||||
*/
|
||||
proplen = 0;
|
||||
while (lrec != NULL) proplen += 4;
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
|
||||
(proplen - 2) * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = proplen;
|
||||
|
||||
proplen = 0;
|
||||
while (lrec != NULL)
|
||||
{
|
||||
char *newstr;
|
||||
sprintf(locstr, "%d %d %d %d",
|
||||
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);
|
||||
if (propstr == NULL)
|
||||
{
|
||||
newstr = (char *)mallocMagic(strlen(locstr) + 1);
|
||||
sprintf(newstr, "%s", locstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
newstr = (char *)mallocMagic(strlen(locstr)
|
||||
+ strlen(propstr) + 2);
|
||||
sprintf(newstr, "%s %s", propstr, locstr);
|
||||
freeMagic(propstr);
|
||||
}
|
||||
propstr = newstr;
|
||||
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;
|
||||
}
|
||||
/* NOTE: propstr is transferred to the CellDef and should
|
||||
* not be free'd here.
|
||||
*/
|
||||
DBPropPut(cifReadCellDef, propname, propstr);
|
||||
DBPropPut(cifReadCellDef, propname, proprec);
|
||||
freeMagic(propname);
|
||||
}
|
||||
|
||||
|
|
@ -902,6 +899,7 @@ cifMakeBoundaryFunc(
|
|||
/* If there are multiple rectangles defined with the boundary */
|
||||
/* layer, then the last one defines the FIXED_BBOX property. */
|
||||
|
||||
PropertyRecord *proprec;
|
||||
Rect area;
|
||||
char propertyvalue[128], *storedvalue;
|
||||
int savescale;
|
||||
|
|
@ -933,19 +931,24 @@ cifMakeBoundaryFunc(
|
|||
|
||||
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
/* Only flag a warning if the redefined boundary was */
|
||||
/* different from the original. */
|
||||
|
||||
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
Rect bbox;
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
|
||||
if ((bbox.r_xbot != area.r_xbot) ||
|
||||
(bbox.r_ybot != area.r_ybot) ||
|
||||
(bbox.r_xtop != area.r_xtop) ||
|
||||
|
|
@ -962,10 +965,15 @@ cifMakeBoundaryFunc(
|
|||
}
|
||||
}
|
||||
|
||||
sprintf(propertyvalue, "%d %d %d %d",
|
||||
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
||||
storedvalue = StrDup((char **)NULL, propertyvalue);
|
||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = area.r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = area.r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = area.r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = area.r_ytop;
|
||||
|
||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", proprec);
|
||||
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -504,10 +504,10 @@ CIFCoverageLayer(
|
|||
}
|
||||
else
|
||||
{
|
||||
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
|
||||
TxPrintf("%s Area = %"DLONG_PREFIX"d CIF units^2\n", doBox ? "Cursor Box" :
|
||||
"Cell", btotal);
|
||||
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
||||
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
||||
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal);
|
||||
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage);
|
||||
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
||||
"cell", 100.0 * fcover);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1300,7 +1300,7 @@ CmdCellname(
|
|||
if (cellDef == (CellDef *) NULL)
|
||||
TxError("Unknown cell %s\n", cellname);
|
||||
else
|
||||
CmdDoProperty(cellDef, cmd, 3 + ((dolist) ? 1 : 0));
|
||||
CmdDoProperty(cellDef, w, cmd, 3 + ((dolist) ? 1 : 0));
|
||||
break;
|
||||
|
||||
case IDX_DELETE:
|
||||
|
|
@ -4991,15 +4991,20 @@ cmdDumpParseArgs(
|
|||
bbox = def->cd_bbox;
|
||||
if (def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
||||
bbox = def->cd_bbox;
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
362
commands/CmdLQ.c
362
commands/CmdLQ.c
|
|
@ -2319,30 +2319,145 @@ parsepositions:
|
|||
void
|
||||
CmdDoProperty(
|
||||
CellDef *def,
|
||||
MagWindow *w,
|
||||
TxCommand *cmd,
|
||||
int argstart)
|
||||
{
|
||||
int printPropertiesFunc();
|
||||
PropertyRecord *proprec;
|
||||
char *value;
|
||||
bool propfound;
|
||||
int proptype, proplen, propvalue, i;
|
||||
dlong dvalue;
|
||||
int locargc = cmd->tx_argc - argstart + 1;
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj;
|
||||
#endif
|
||||
|
||||
int printPropertiesFunc(); /* Forward declaration */
|
||||
|
||||
/* These should match the property codes in database.h.in */
|
||||
static const char * const cmdPropertyType[] = {
|
||||
"string", "integer", "dimension", "double", NULL
|
||||
};
|
||||
|
||||
/* If a property type is given, parse it and then strip it from
|
||||
* the arguments list.
|
||||
*/
|
||||
if (locargc > 1)
|
||||
{
|
||||
proptype = Lookup(cmd->tx_argv[argstart], cmdPropertyType);
|
||||
if (proptype >= 0)
|
||||
{
|
||||
locargc--;
|
||||
argstart++;
|
||||
}
|
||||
else
|
||||
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||
}
|
||||
else
|
||||
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||
|
||||
if (locargc == 1)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj;
|
||||
/* Create an empty list for the interpreter result; the
|
||||
* printPropertiesFunc() function will append values to it.
|
||||
*/
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
#endif
|
||||
/* print all properties and their values */
|
||||
DBPropEnum(def, printPropertiesFunc, NULL);
|
||||
DBPropEnum(def, printPropertiesFunc, (ClientData)w);
|
||||
}
|
||||
|
||||
else if (locargc == 2)
|
||||
{
|
||||
/* print the value of the indicated property */
|
||||
value = (char *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
proptype = proprec->prop_type;
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetResult(magicinterp, value, NULL);
|
||||
switch (proptype)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
Tcl_SetResult(magicinterp, proprec->prop_value.prop_string, NULL);
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
if (proprec->prop_len == 1)
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewIntObj(proprec->prop_value.prop_integer[0]));
|
||||
else
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewIntObj(
|
||||
proprec->prop_value.prop_integer[i]));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
if (proprec->prop_len == 1)
|
||||
Tcl_SetResult(magicinterp,
|
||||
DBWPrintValue(proprec->prop_value.prop_integer[0],
|
||||
w, TRUE), NULL);
|
||||
else
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(DBWPrintValue(
|
||||
proprec->prop_value.prop_integer[i], w,
|
||||
((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
if (proprec->prop_len == 1)
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||
proprec->prop_value.prop_double[0]));
|
||||
else
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||
proprec->prop_value.prop_double[i]));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#else
|
||||
TxPrintf("%s", value);
|
||||
switch (proptype)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
TxPrintf("%s\n", proprec->prop_value.prop_string);
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
TxPrintf("%s ", DBWPrintValue(
|
||||
proprec->prop_value.prop_integer[i], w,
|
||||
((i % 2) == 0) ? TRUE : FALSE);
|
||||
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
TxPrintf( "%"DLONG_PREFIX"d",
|
||||
proprec->prop_value.prop_double[i]);
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef MAGIC_WRAPPER
|
||||
/* If the command was "cellname list property ...", then */
|
||||
|
|
@ -2352,14 +2467,159 @@ CmdDoProperty(
|
|||
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
|
||||
}
|
||||
}
|
||||
else if (locargc == 3)
|
||||
else if (locargc >= 3)
|
||||
{
|
||||
/* Catch the following known reserved keywords and cast them to the
|
||||
* expected property type. If any property type was already given
|
||||
* to the command, it is overridden. This ensures that the reserved
|
||||
* keyword functions work correctly.
|
||||
*
|
||||
* GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE
|
||||
* MASKHINTS_*: PROPERTY_TYPE_DIMENSION
|
||||
* FIXED_BBOX: PROPERTY_TYPE_DIMENSION
|
||||
*/
|
||||
if (!strcmp(cmd->tx_argv[argstart], "GDS_START"))
|
||||
proptype = PROPERTY_TYPE_DOUBLE;
|
||||
else if (!strcmp(cmd->tx_argv[argstart], "GDS_END"))
|
||||
proptype = PROPERTY_TYPE_DOUBLE;
|
||||
else if (!strcmp(cmd->tx_argv[argstart], "GDS_FILE"))
|
||||
proptype = PROPERTY_TYPE_STRING;
|
||||
else if (!strcmp(cmd->tx_argv[argstart], "FIXED_BBOX"))
|
||||
proptype = PROPERTY_TYPE_DIMENSION;
|
||||
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_DIMENSION;
|
||||
|
||||
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
||||
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
||||
else
|
||||
{
|
||||
value = StrDup((char **)NULL, cmd->tx_argv[argstart + 1]);
|
||||
DBPropPut(def, cmd->tx_argv[argstart], value);
|
||||
if (proptype == PROPERTY_TYPE_STRING)
|
||||
{
|
||||
proplen = strlen(cmd->tx_argv[argstart + 1]);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) -
|
||||
7 + proplen);
|
||||
proprec->prop_type = proptype;
|
||||
proprec->prop_len = proplen;
|
||||
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
|
||||
}
|
||||
else /* PROPERTY_TYPE_INTEGER or PROPERTY_TYPE_DIMENSION */
|
||||
{
|
||||
/* Two choices: If locargc == 3 then all values are in one
|
||||
* argument. If locargc > 3, then parse each argument as a
|
||||
* separate value.
|
||||
*/
|
||||
if (locargc > 3)
|
||||
{
|
||||
proplen = locargc - 2;
|
||||
if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(proplen - 1)*sizeof(dlong));
|
||||
else
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(proplen - 2)*sizeof(int));
|
||||
proprec->prop_type = proptype;
|
||||
proprec->prop_len = proplen;
|
||||
|
||||
for (i = 1; i < locargc - 1; i++)
|
||||
{
|
||||
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||
{
|
||||
if (sscanf(cmd->tx_argv[argstart + i], "%d",
|
||||
&propvalue) == 1)
|
||||
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||
else
|
||||
{
|
||||
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||
cmd->tx_argv[argstart + i]);
|
||||
proprec->prop_value.prop_integer[i - 1] = 0;
|
||||
}
|
||||
}
|
||||
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||
{
|
||||
if (sscanf(cmd->tx_argv[argstart + i], "%"DLONG_PREFIX"d",
|
||||
&dvalue) == 1)
|
||||
proprec->prop_value.prop_double[i - 1] = dvalue;
|
||||
else
|
||||
{
|
||||
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||
cmd->tx_argv[argstart + i]);
|
||||
proprec->prop_value.prop_double[i - 1] = 0;
|
||||
}
|
||||
}
|
||||
else /* PROPERTY_TYPE_DIMENSION */
|
||||
{
|
||||
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
||||
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
||||
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make two passes through the argument string, once to get
|
||||
* the valid number of arguments, then again to parse the
|
||||
* values, once the property record has been allocated
|
||||
*/
|
||||
value = cmd->tx_argv[argstart + 1];
|
||||
for (proplen = 0; *value != '\0'; )
|
||||
{
|
||||
if (isspace(*value) && (*value != '\0')) value++;
|
||||
if (!isspace(*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;
|
||||
}
|
||||
/* Second pass */
|
||||
value = cmd->tx_argv[argstart + 1];
|
||||
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
||||
{
|
||||
if (isspace(*value) && (*value != '\0')) value++;
|
||||
if (!isspace(*value))
|
||||
{
|
||||
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||
{
|
||||
if (sscanf(value, "%d", &propvalue) != 1)
|
||||
{
|
||||
TxError("Unable to parse integer "
|
||||
"value from \"%s\"\n",
|
||||
value);
|
||||
propvalue = 0;
|
||||
}
|
||||
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||
}
|
||||
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||
{
|
||||
if (sscanf(value, "%"DLONG_PREFIX"d", &dvalue) != 1)
|
||||
{
|
||||
TxError("Unable to parse integer "
|
||||
"value from \"%s\"\n",
|
||||
value);
|
||||
propvalue = 0;
|
||||
}
|
||||
proprec->prop_value.prop_double[proplen] = dvalue;
|
||||
}
|
||||
else /* PROPERTY_TYPE_DIMENSION */
|
||||
{
|
||||
propvalue = cmdParseCoord(w, value, FALSE,
|
||||
((proplen % 2) == 0) ? TRUE : FALSE);
|
||||
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||
}
|
||||
while (!isspace(*value) && (*value != '\0')) value++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DBPropPut(def, cmd->tx_argv[argstart], proprec);
|
||||
}
|
||||
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||
}
|
||||
|
|
@ -2380,10 +2640,14 @@ CmdDoProperty(
|
|||
* defined in database/DBprop.c.
|
||||
*
|
||||
* Usage:
|
||||
* property [name] [value]
|
||||
* property [string|integer|dimension] [name] [value]
|
||||
*
|
||||
* "name" is a unique string tag for the property, and "value" is its
|
||||
* string value.
|
||||
* If the first argument is present, it must be one of the known
|
||||
* keywords, and determines the form in which "value" is interpreted and
|
||||
* stored. "name" is a unique string tag for the property. "value" is
|
||||
* the value of the property, which is either a string, integer, or a
|
||||
* list of integers. The difference between an "integer" and a "dimension"
|
||||
* is that all values which are dimensions are scaled with internal units.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
|
|
@ -2410,7 +2674,7 @@ CmdProperty(
|
|||
else
|
||||
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
||||
|
||||
CmdDoProperty(def, cmd, 1);
|
||||
CmdDoProperty(def, w, cmd, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2422,27 +2686,71 @@ CmdProperty(
|
|||
int
|
||||
printPropertiesFunc(
|
||||
const char *name,
|
||||
ClientData value,
|
||||
ClientData cdata) /* not used */
|
||||
PropertyRecord *proprec,
|
||||
MagWindow *w)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
char *keyvalue;
|
||||
int i;
|
||||
|
||||
if (value == NULL)
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj, *lobj;
|
||||
|
||||
tobj = Tcl_GetObjResult(magicinterp);
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(name, -1));
|
||||
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
keyvalue = (char *)mallocMagic(strlen(name) + 4);
|
||||
sprintf(keyvalue, "%s {}", name);
|
||||
case PROPERTY_TYPE_STRING:
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(proprec->prop_value.prop_string, -1));
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewIntObj(proprec->prop_value.prop_integer[i]));
|
||||
break;
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(
|
||||
DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||
w, ((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewWideIntObj(proprec->prop_value.prop_double[i]));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyvalue = (char *)mallocMagic(strlen(name) + strlen((const char *)value) + 2);
|
||||
sprintf(keyvalue, "%s %s", name, (const char *)value);
|
||||
}
|
||||
Tcl_AppendElement(magicinterp, keyvalue);
|
||||
freeMagic(keyvalue);
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj, lobj);
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
|
||||
#else
|
||||
TxPrintf("%s = %s\n", name, (const char *)value);
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
case PROPERTY_TYPE_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_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);
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
TxPrintf("%s = ", name);
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_double[i]);
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0; /* keep the search alive */
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ extern int cmdParseCoord(MagWindow *w, char *arg, bool is_relative, bool is_x);
|
|||
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
||||
extern void CmdInit(void);
|
||||
|
||||
extern void CmdDoProperty(CellDef *def, TxCommand *cmd, int argstart);
|
||||
extern void CmdDoProperty(CellDef *def, MagWindow *w, TxCommand *cmd, int argstart);
|
||||
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
||||
|
||||
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
||||
|
|
|
|||
|
|
@ -380,17 +380,18 @@ struct propUseDefStruct {
|
|||
*/
|
||||
|
||||
int
|
||||
dbCopyMaskHintsFunc(key, value, puds)
|
||||
dbCopyMaskHintsFunc(key, proprec, puds)
|
||||
char *key;
|
||||
ClientData value;
|
||||
PropertyRecord *proprec;
|
||||
struct propUseDefStruct *puds;
|
||||
{
|
||||
CellDef *dest = puds->puds_dest;
|
||||
Transform *trans = puds->puds_trans;
|
||||
char *propstr = (char *)value;
|
||||
PropertyRecord *parentproprec, *newproprec;
|
||||
char *parentprop, *newvalue, *vptr;
|
||||
Rect r, rnew;
|
||||
bool propfound;
|
||||
int i;
|
||||
|
||||
if (!strncmp(key, "MASKHINTS_", 10))
|
||||
{
|
||||
|
|
@ -398,43 +399,48 @@ dbCopyMaskHintsFunc(key, value, puds)
|
|||
int lastlen;
|
||||
|
||||
/* Append to existing mask hint (if any) */
|
||||
parentprop = (char *)DBPropGet(dest, key, &propfound);
|
||||
newvalue = (propfound) ? StrDup((char **)NULL, parentprop) : (char *)NULL;
|
||||
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
|
||||
|
||||
vptr = propstr;
|
||||
while (*vptr != '\0')
|
||||
if (propfound)
|
||||
{
|
||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
GeoTransRect(trans, &r, &rnew);
|
||||
|
||||
lastval = newvalue;
|
||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
||||
newvalue = mallocMagic(40 + lastlen);
|
||||
|
||||
if (lastval)
|
||||
strcpy(newvalue, lastval);
|
||||
else
|
||||
*newvalue = '\0';
|
||||
|
||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
||||
rnew.r_xbot, rnew.r_ybot, rnew.r_xtop, rnew.r_ytop);
|
||||
if (lastval) freeMagic(lastval);
|
||||
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
}
|
||||
else break;
|
||||
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(proprec->prop_len + parentproprec->prop_len - 2) *
|
||||
sizeof(int));
|
||||
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
newproprec->prop_len = proprec->prop_len + parentproprec->prop_len;
|
||||
}
|
||||
if (newvalue)
|
||||
DBPropPut(dest, key, newvalue);
|
||||
else
|
||||
{
|
||||
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(proprec->prop_len - 2) * sizeof(int));
|
||||
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
newproprec->prop_len = proprec->prop_len;
|
||||
}
|
||||
|
||||
for (i = 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];
|
||||
|
||||
GeoTransRect(trans, &r, &rnew);
|
||||
|
||||
newproprec->prop_value.prop_integer[i] = rnew.r_xbot;
|
||||
newproprec->prop_value.prop_integer[i + 1] = rnew.r_ybot;
|
||||
newproprec->prop_value.prop_integer[i + 2] = rnew.r_xtop;
|
||||
newproprec->prop_value.prop_integer[i + 3] = rnew.r_ytop;
|
||||
}
|
||||
|
||||
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 + proprec->prop_len] =
|
||||
parentproprec->prop_value.prop_integer[i];
|
||||
}
|
||||
|
||||
DBPropPut(dest, key, newproprec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -152,10 +152,9 @@ DBCellRename(cellname, newname, doforce)
|
|||
|
||||
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
||||
{
|
||||
char *chkgdsfile;
|
||||
bool isReadOnly;
|
||||
|
||||
chkgdsfile = (char *)DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
||||
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1806,84 +1806,33 @@ typedef struct _cellpropstruct {
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbScaleProp(name, value, cps)
|
||||
int dbScaleProp(name, proprec, cps)
|
||||
char *name;
|
||||
char *value;
|
||||
PropertyRecord *proprec;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int scalen, scaled;
|
||||
char *newvalue, *vptr;
|
||||
Rect r;
|
||||
int i, scalen, scaled;
|
||||
Point p;
|
||||
|
||||
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||
/* Only "dimension" type properties get scaled */
|
||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||
|
||||
/* Scale numerator held in point X value, */
|
||||
/* scale denominator held in point Y value */
|
||||
scalen = cps->cps_point.p_x;
|
||||
scaled = cps->cps_point.p_y;
|
||||
|
||||
for (i = 0; i < proprec->prop_len; i += 2)
|
||||
{
|
||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
/* Scale numerator held in point X value, */
|
||||
/* scale denominator held in point Y value */
|
||||
if ((i + 1) >= proprec->prop_len) break;
|
||||
|
||||
scalen = cps->cps_point.p_x;
|
||||
scaled = cps->cps_point.p_y;
|
||||
|
||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
||||
|
||||
newvalue = (char *)mallocMagic(40);
|
||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||
r.r_xtop, r.r_ytop);
|
||||
DBPropPut(cps->cps_def, name, newvalue);
|
||||
}
|
||||
p.p_x = proprec->prop_value.prop_integer[i];
|
||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||
DBScalePoint(&p, scalen, scaled);
|
||||
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||
}
|
||||
else if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
char *vptr, *lastval;
|
||||
int lastlen;
|
||||
|
||||
newvalue = (char *)NULL;
|
||||
vptr = value;
|
||||
while (*vptr != '\0')
|
||||
{
|
||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
/* Scale numerator held in point X value, */
|
||||
/* scale denominator held in point Y value */
|
||||
|
||||
scalen = cps->cps_point.p_x;
|
||||
scaled = cps->cps_point.p_y;
|
||||
|
||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
||||
|
||||
lastval = newvalue;
|
||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
||||
newvalue = mallocMagic(40 + lastlen);
|
||||
|
||||
if (lastval)
|
||||
strcpy(newvalue, lastval);
|
||||
else
|
||||
*newvalue = '\0';
|
||||
|
||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
||||
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
|
||||
if (lastval) freeMagic(lastval);
|
||||
|
||||
/* Parse through the four values and check if there's more */
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
while (*vptr && !isspace(*vptr)) vptr++;
|
||||
while (*vptr && isspace(*vptr)) vptr++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
if (newvalue)
|
||||
DBPropPut(cps->cps_def, name, newvalue);
|
||||
}
|
||||
return 0; /* Keep enumerating through properties */
|
||||
}
|
||||
|
||||
|
|
@ -1899,33 +1848,32 @@ int dbScaleProp(name, value, cps)
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbMoveProp(name, value, cps)
|
||||
int dbMoveProp(name, proprec, cps)
|
||||
char *name;
|
||||
char *value;
|
||||
PropertyRecord *proprec;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int origx, origy;
|
||||
int i, origx, origy;
|
||||
char *newvalue;
|
||||
Rect r;
|
||||
Point p;
|
||||
|
||||
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||
|| !strncmp(name, "MASKHINTS_", 10))
|
||||
/* Only "dimension" type properties get scaled */
|
||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||
|
||||
origx = cps->cps_point.p_x;
|
||||
origy = cps->cps_point.p_y;
|
||||
|
||||
for (i = 0; i < proprec->prop_len; i += 2)
|
||||
{
|
||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
origx = cps->cps_point.p_x;
|
||||
origy = cps->cps_point.p_y;
|
||||
if ((i + 1) >= proprec->prop_len) break;
|
||||
|
||||
DBMovePoint(&r.r_ll, origx, origy);
|
||||
DBMovePoint(&r.r_ur, origx, origy);
|
||||
|
||||
newvalue = (char *)mallocMagic(40);
|
||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||
r.r_xtop, r.r_ytop);
|
||||
DBPropPut(cps->cps_def, name, newvalue);
|
||||
}
|
||||
p.p_x = proprec->prop_value.prop_integer[i];
|
||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||
DBMovePoint(&p, origx, origy);
|
||||
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||
}
|
||||
|
||||
return 0; /* Keep enumerating through properties */
|
||||
}
|
||||
|
||||
|
|
|
|||
813
database/DBio.c
813
database/DBio.c
|
|
@ -2375,7 +2375,6 @@ nextLine:
|
|||
return (dbFgets(line, len, f) != NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -2398,23 +2397,32 @@ nextLine:
|
|||
|
||||
bool
|
||||
dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
||||
CellDef *cellDef; /* Cell whose elements are being read */
|
||||
char *line; /* Line containing << elements >> */
|
||||
CellDef *cellDef; /* Cell whose properties are being read */
|
||||
char *line; /* Line containing << properties >> */
|
||||
int len; /* Size of buffer pointed to by line */
|
||||
FILETYPE f; /* Input file */
|
||||
int scalen; /* Scale up by this factor */
|
||||
int scaled; /* Scale down by this factor */
|
||||
{
|
||||
char propertyname[128], propertyvalue[2049], *storedvalue;
|
||||
char *pvalueptr;
|
||||
int ntok;
|
||||
char propertytype[32], propertyname[128], propertyvalue[2049];
|
||||
PropertyRecord *proprec;
|
||||
char *storedvalue, *pvalueptr;
|
||||
int ntok, option, proplen;
|
||||
unsigned int noeditflag;
|
||||
char *pptr;
|
||||
int numvals, ival;
|
||||
dlong dval;
|
||||
|
||||
/* These type indexes must align with the property codes in database.h.in */
|
||||
static const char * const propType[] = {
|
||||
"string", "integer", "dimension", "double", 0
|
||||
};
|
||||
|
||||
/* Save CDNOEDIT flag if set, and clear it */
|
||||
noeditflag = cellDef->cd_flags & CDNOEDIT;
|
||||
cellDef->cd_flags &= ~CDNOEDIT;
|
||||
|
||||
/* Get first element line */
|
||||
/* Get first property line */
|
||||
line[len - 1] = 'X';
|
||||
if (dbFgets(line, len, f) == NULL) return (FALSE);
|
||||
|
||||
|
|
@ -2428,139 +2436,102 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
|||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Stop when at end of properties section (currently, only "string"
|
||||
* is defined)
|
||||
*/
|
||||
if (line[0] != 's') break;
|
||||
/* Tokenize the input line */
|
||||
ntok = sscanf(line, "%31s %127s %2048[^\n]",
|
||||
propertytype, propertyname, propertyvalue);
|
||||
|
||||
/*
|
||||
* Properties may only be "string", for now. This may be the only
|
||||
* property type ever needed. Handle possible string buffer
|
||||
* overflows.
|
||||
*/
|
||||
if (line[0] == 's')
|
||||
if (ntok > 0)
|
||||
{
|
||||
pvalueptr = &propertyvalue[0];
|
||||
option = Lookup(propertytype, propType);
|
||||
|
||||
if ((ntok = sscanf(line, "string %127s %2048[^\n]",
|
||||
propertyname, propertyvalue)) != 2)
|
||||
/* Stop when at end of properties section */
|
||||
if (option < 0) break;
|
||||
}
|
||||
if (ntok != 3)
|
||||
{
|
||||
TxError("Skipping bad property line: %s", line);
|
||||
goto nextproperty;
|
||||
}
|
||||
|
||||
/* Read the string value from the file, accounting for overflow */
|
||||
pvalueptr = &propertyvalue[0];
|
||||
|
||||
/* Handle string overflows in property values */
|
||||
if (line[len - 1] == '\0')
|
||||
{
|
||||
int pvlen = strlen(pvalueptr);
|
||||
*(pvalueptr + pvlen - 1) = '\0';
|
||||
|
||||
while (*(pvalueptr + pvlen - 1) == '\0')
|
||||
{
|
||||
TxError("Skipping bad property line: %s", line);
|
||||
goto nextproperty;
|
||||
}
|
||||
char *newpvalue;
|
||||
|
||||
/* Handle string overflows in property values */
|
||||
if (line[len - 1] == '\0')
|
||||
{
|
||||
int pvlen = strlen(pvalueptr);
|
||||
*(pvalueptr + pvlen - 1) = '\0';
|
||||
|
||||
while (*(pvalueptr + pvlen - 1) == '\0')
|
||||
pvlen += 2048;
|
||||
newpvalue = (char *)mallocMagic(pvlen);
|
||||
strcpy(newpvalue, pvalueptr);
|
||||
if (pvalueptr != &propertyvalue[0])
|
||||
freeMagic(pvalueptr);
|
||||
pvalueptr = newpvalue;
|
||||
*(pvalueptr + pvlen - 1) = 'X';
|
||||
if (dbFgets(newpvalue + pvlen - 2048, 2048, f) == NULL)
|
||||
{
|
||||
char *newpvalue;
|
||||
|
||||
pvlen += 2048;
|
||||
newpvalue = (char *)mallocMagic(pvlen);
|
||||
strcpy(newpvalue, pvalueptr);
|
||||
if (pvalueptr != &propertyvalue[0])
|
||||
freeMagic(pvalueptr);
|
||||
pvalueptr = newpvalue;
|
||||
*(pvalueptr + pvlen - 1) = 'X';
|
||||
if (dbFgets(newpvalue + pvlen - 2048, 2048, f) == NULL)
|
||||
{
|
||||
freeMagic(pvalueptr);
|
||||
cellDef->cd_flags |= noeditflag;
|
||||
return (TRUE);
|
||||
}
|
||||
/* Oops, hit end-of-file in the middle of a property */
|
||||
freeMagic(pvalueptr);
|
||||
cellDef->cd_flags |= noeditflag;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Go ahead and process the vendor GDS property */
|
||||
if (!strcmp(propertyname, "GDS_FILE"))
|
||||
cellDef->cd_flags |= CDVENDORGDS;
|
||||
/* "pvalueptr" now points to a string containing the complete
|
||||
* property value.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Also process FIXED_BBOX property, as units must match, */
|
||||
/* and ditto for MASKHINTS_*. */
|
||||
/* Handle properties by type. Property types are:
|
||||
* (1) "string" (the default)
|
||||
* (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)
|
||||
*/
|
||||
|
||||
if (!strcmp(propertyname, "FIXED_BBOX"))
|
||||
{
|
||||
Rect locbbox;
|
||||
switch (option)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
/* Go ahead and process the vendor GDS property */
|
||||
if (!strcmp(propertyname, "GDS_FILE"))
|
||||
cellDef->cd_flags |= CDVENDORGDS;
|
||||
|
||||
if (sscanf(pvalueptr, "%d %d %d %d",
|
||||
&(locbbox.r_xbot),
|
||||
&(locbbox.r_ybot),
|
||||
&(locbbox.r_xtop),
|
||||
&(locbbox.r_ytop)) != 4)
|
||||
/* Also process FIXED_BBOX property, as units must */
|
||||
/* match, and ditto for MASKHINTS_*. This is */
|
||||
/* backwards-compatibility handling for files that have */
|
||||
/* either property as a string. The property is best */
|
||||
/* handled as a dimension to avoid parsing the string */
|
||||
/* value every time the coordinates are needed. */
|
||||
|
||||
if (!strcmp(propertyname, "FIXED_BBOX"))
|
||||
{
|
||||
TxError("Cannot read bounding box values in %s property",
|
||||
propertyname);
|
||||
storedvalue = StrDup((char **)NULL, pvalueptr);
|
||||
(void) DBPropPut(cellDef, propertyname, storedvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scalen > 1)
|
||||
{
|
||||
locbbox.r_xbot *= scalen;
|
||||
locbbox.r_ybot *= scalen;
|
||||
locbbox.r_xtop *= scalen;
|
||||
locbbox.r_ytop *= scalen;
|
||||
}
|
||||
if (scaled > 1)
|
||||
{
|
||||
locbbox.r_xbot /= scaled;
|
||||
locbbox.r_ybot /= scaled;
|
||||
locbbox.r_xtop /= scaled;
|
||||
locbbox.r_ytop /= scaled;
|
||||
}
|
||||
cellDef->cd_flags |= CDFIXEDBBOX;
|
||||
storedvalue = (char *)mallocMagic(40);
|
||||
sprintf(storedvalue, "%d %d %d %d",
|
||||
locbbox.r_xbot, locbbox.r_ybot,
|
||||
locbbox.r_xtop, locbbox.r_ytop);
|
||||
(void) DBPropPut(cellDef, propertyname, storedvalue);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(propertyname, "MASKHINTS_", 10))
|
||||
{
|
||||
Rect locbbox;
|
||||
char *pptr = pvalueptr;
|
||||
int numvals, numrects = 0, slen, n;
|
||||
Rect locbbox;
|
||||
|
||||
while (*pptr != '\0')
|
||||
{
|
||||
numvals = sscanf(pptr, "%d %d %d %d",
|
||||
if (sscanf(pvalueptr, "%d %d %d %d",
|
||||
&(locbbox.r_xbot),
|
||||
&(locbbox.r_ybot),
|
||||
&(locbbox.r_xtop),
|
||||
&(locbbox.r_ytop));
|
||||
if (numvals <= 0)
|
||||
break;
|
||||
else if (numvals != 4)
|
||||
&(locbbox.r_ytop)) != 4)
|
||||
{
|
||||
TxError("Cannot read bounding box values in %s property",
|
||||
propertyname);
|
||||
/* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numrects == 0)
|
||||
{
|
||||
storedvalue = (char *)mallocMagic(40);
|
||||
*storedvalue = '\0';
|
||||
slen = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *newvalue;
|
||||
slen = strlen(storedvalue);
|
||||
newvalue = (char *)mallocMagic(40 + slen);
|
||||
sprintf(newvalue, "%s ", storedvalue);
|
||||
freeMagic(storedvalue);
|
||||
storedvalue = newvalue;
|
||||
}
|
||||
numrects++;
|
||||
|
||||
if (scalen > 1)
|
||||
{
|
||||
locbbox.r_xbot *= scalen;
|
||||
|
|
@ -2575,27 +2546,308 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
|||
locbbox.r_xtop /= scaled;
|
||||
locbbox.r_ytop /= scaled;
|
||||
}
|
||||
sprintf(storedvalue + slen + 1, "%d %d %d %d",
|
||||
locbbox.r_xbot, locbbox.r_ybot,
|
||||
locbbox.r_xtop, locbbox.r_ytop);
|
||||
cellDef->cd_flags |= CDFIXEDBBOX;
|
||||
|
||||
/* Skip forward four values in pvalueptr */
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
while ((*pptr != '\0') && !isspace(*pptr)) pptr++;
|
||||
while ((*pptr != '\0') && isspace(*pptr)) pptr++;
|
||||
}
|
||||
proprec = (PropertyRecord *)mallocMagic(
|
||||
sizeof(PropertyRecord) + 2 * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = locbbox.r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = locbbox.r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = locbbox.r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = locbbox.r_ytop;
|
||||
|
||||
(void) DBPropPut(cellDef, propertyname, proprec);
|
||||
}
|
||||
}
|
||||
(void) DBPropPut(cellDef, propertyname, storedvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
storedvalue = StrDup((char **)NULL, pvalueptr);
|
||||
(void) DBPropPut(cellDef, propertyname, storedvalue);
|
||||
}
|
||||
if (pvalueptr != &propertyvalue[0])
|
||||
freeMagic(pvalueptr);
|
||||
else if (!strncmp(propertyname, "MASKHINTS_", 10))
|
||||
{
|
||||
pptr = pvalueptr;
|
||||
|
||||
/* 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')
|
||||
{
|
||||
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
if (!isspace(*pptr))
|
||||
{
|
||||
char *endptr;
|
||||
long result;
|
||||
|
||||
/* Check that the value is an integer */
|
||||
result = strtol(pptr, &endptr, 0);
|
||||
if (endptr == pptr)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
if (numvals % 4 != 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if ((!strncmp(propertyname, "GDS_START", 9)) ||
|
||||
(!strncmp(propertyname, "GDS_BEGIN", 9)) ||
|
||||
(!strncmp(propertyname, "GDS_END", 7)))
|
||||
{
|
||||
if (sscanf(pvalueptr, "%"DLONG_PREFIX"d", &dval) == 1)
|
||||
{
|
||||
TxError("Cannot read file offset value in %s property",
|
||||
propertyname);
|
||||
/* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||
proprec->prop_len = 1;
|
||||
proprec->prop_value.prop_double[0] = dval;
|
||||
(void) DBPropPut(cellDef, propertyname, proprec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (pvalueptr != &propertyvalue[0])
|
||||
freeMagic(pvalueptr);
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
pptr = pvalueptr;
|
||||
|
||||
/* 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')
|
||||
{
|
||||
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
if (!isspace(*pptr))
|
||||
{
|
||||
char *endptr;
|
||||
long result;
|
||||
|
||||
/* Check that the value is an integer */
|
||||
result = strtol(pptr, &endptr, 0);
|
||||
if (endptr == pptr)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
|
||||
pptr = pvalueptr;
|
||||
proprec = (PropertyRecord *)mallocMagic(
|
||||
sizeof(PropertyRecord) + ((numvals - 2) * sizeof(int)));
|
||||
proprec->prop_type = PROPERTY_TYPE_INTEGER;
|
||||
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);
|
||||
proprec->prop_value.prop_integer[numvals] = ival;
|
||||
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
(void) DBPropPut(cellDef, propertyname, proprec);
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
pptr = pvalueptr;
|
||||
|
||||
/* 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')
|
||||
{
|
||||
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
if (!isspace(*pptr))
|
||||
{
|
||||
char *endptr;
|
||||
dlong result;
|
||||
|
||||
/* Check that the value is an integer */
|
||||
result = strtoll(pptr, &endptr, 0);
|
||||
if (endptr == pptr)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
|
||||
pptr = pvalueptr;
|
||||
proprec = (PropertyRecord *)mallocMagic(
|
||||
sizeof(PropertyRecord) + ((numvals - 1) * sizeof(dlong)));
|
||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||
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, "%"DLONG_PREFIX"d", &dval);
|
||||
proprec->prop_value.prop_double[numvals] = dval;
|
||||
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
(void) DBPropPut(cellDef, propertyname, proprec);
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
pptr = pvalueptr;
|
||||
|
||||
/* 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')
|
||||
{
|
||||
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
if (!isspace(*pptr))
|
||||
{
|
||||
char *endptr;
|
||||
long result;
|
||||
|
||||
/* Check that the value is an integer */
|
||||
result = strtol(pptr, &endptr, 0);
|
||||
if (endptr == pptr)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
|
||||
numvals++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
nextproperty:
|
||||
|
|
@ -3290,68 +3542,23 @@ dbFindCellGCFFunc(cellUse, ggcf)
|
|||
}
|
||||
|
||||
int
|
||||
dbFindPropGCFFunc(key, value, ggcf)
|
||||
dbFindPropGCFFunc(key, proprec, ggcf)
|
||||
char *key;
|
||||
ClientData value;
|
||||
PropertyRecord *proprec;
|
||||
int *ggcf; /* Client data */
|
||||
{
|
||||
Rect bbox;
|
||||
char *vptr = value, *sptr;
|
||||
int numvals, n;
|
||||
int value, n;
|
||||
|
||||
if (!strcmp(key, "FIXED_BBOX"))
|
||||
{
|
||||
if (sscanf(value, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
{
|
||||
/* Check bounding box */
|
||||
if (bbox.r_xtop % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_xtop, *ggcf);
|
||||
if (bbox.r_xbot % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_xbot, *ggcf);
|
||||
if (bbox.r_ytop % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_ytop, *ggcf);
|
||||
if (bbox.r_ybot % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_ybot, *ggcf);
|
||||
}
|
||||
else
|
||||
TxError("Error: Cannot parse FIXED_BBOX property value!\n");
|
||||
}
|
||||
else if (!strncmp(key, "MASKHINTS_", 10))
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
numvals = sscanf(vptr, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop);
|
||||
if (numvals <= 0)
|
||||
break;
|
||||
else if (numvals != 4)
|
||||
{
|
||||
TxError("Error: Cannot parse %s property value at \"%s\"!\n",
|
||||
key, vptr);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check bounding box */
|
||||
if (bbox.r_xtop % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_xtop, *ggcf);
|
||||
if (bbox.r_xbot % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_xbot, *ggcf);
|
||||
if (bbox.r_ytop % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_ytop, *ggcf);
|
||||
if (bbox.r_ybot % (*ggcf) != 0)
|
||||
*ggcf = FindGCF(bbox.r_ybot, *ggcf);
|
||||
}
|
||||
/* Only PROPERTY_TYPE_DIMENSION properties get handled */
|
||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||
|
||||
/* Skip forward four values in value */
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
while (!isspace(*vptr) && (*vptr != '\0')) vptr++;
|
||||
while (isspace(*vptr) && (*vptr != '\0')) vptr++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -3443,7 +3650,7 @@ dbCountUseFunc(cellUse, count)
|
|||
|
||||
struct keyValuePair {
|
||||
char *key;
|
||||
char *value;
|
||||
PropertyRecord *value;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3493,15 +3700,15 @@ struct cellPropList {
|
|||
*/
|
||||
|
||||
int
|
||||
dbGetPropFunc(key, value, propRec)
|
||||
dbGetPropFunc(key, proprec, propRec)
|
||||
char *key;
|
||||
ClientData value;
|
||||
PropertyRecord *proprec;
|
||||
struct cellPropList *propRec;
|
||||
{
|
||||
propRec->keyValueList[propRec->idx] =
|
||||
(struct keyValuePair *)mallocMagic(sizeof(struct keyValuePair));
|
||||
propRec->keyValueList[propRec->idx]->key = key;
|
||||
propRec->keyValueList[propRec->idx]->value = (char *)value;
|
||||
propRec->keyValueList[propRec->idx]->value = proprec;
|
||||
propRec->idx++;
|
||||
|
||||
return 0;
|
||||
|
|
@ -3522,9 +3729,9 @@ dbGetPropFunc(key, value, propRec)
|
|||
*/
|
||||
|
||||
int
|
||||
dbCountPropFunc(key, value, count)
|
||||
dbCountPropFunc(key, proprec, count)
|
||||
char *key;
|
||||
ClientData value;
|
||||
PropertyRecord *proprec;
|
||||
int *count; /* Client data */
|
||||
{
|
||||
(*count)++;
|
||||
|
|
@ -3868,120 +4075,70 @@ ioerror:
|
|||
* Side effects:
|
||||
* Writes to the disk file.
|
||||
*
|
||||
* Warnings:
|
||||
* This function assumes that all property values are strings!
|
||||
* This is currently true; if it changes in the future, this
|
||||
* function will have to check each property against a list of
|
||||
* expected property strings and output the value based on the
|
||||
* known format of what it points to.
|
||||
*
|
||||
* Also, this function assumes that properties FIXED_BBOX and
|
||||
* MASKHINTS_* are in internal units, and converts them by
|
||||
* dividing by the reducer value passed in cdata. No other
|
||||
* properties are altered.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
dbWritePropFunc(key, value, cdata)
|
||||
dbWritePropFunc(key, proprec, cdata)
|
||||
char *key;
|
||||
char *value;
|
||||
PropertyRecord *proprec;
|
||||
ClientData cdata;
|
||||
{
|
||||
pwfrec *pwf = (pwfrec *)cdata;
|
||||
FILE *f = pwf->pwf_file;
|
||||
int reducer = pwf->pwf_reducer;
|
||||
char *newvalue = value;
|
||||
int i;
|
||||
char newvalue[20];
|
||||
|
||||
/* NOTE: FIXED_BBOX is treated specially; values are database */
|
||||
/* values and should be divided by reducer. Easiest to do it */
|
||||
/* here and revert values after. Ditto for MASKHINTS_*. */
|
||||
|
||||
if (!strcmp(key, "FIXED_BBOX"))
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
Rect scalebox, bbox;
|
||||
|
||||
if (sscanf(value, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
{
|
||||
scalebox.r_xbot = bbox.r_xbot / reducer;
|
||||
scalebox.r_xtop = bbox.r_xtop / reducer;
|
||||
scalebox.r_ybot = bbox.r_ybot / reducer;
|
||||
scalebox.r_ytop = bbox.r_ytop / reducer;
|
||||
|
||||
newvalue = mallocMagic(strlen(value) + 5);
|
||||
sprintf(newvalue, "%d %d %d %d",
|
||||
scalebox.r_xbot, scalebox.r_ybot,
|
||||
scalebox.r_xtop, scalebox.r_ytop);
|
||||
}
|
||||
else
|
||||
TxError("Error: Cannot parse FIXED_BBOX property value!\n");
|
||||
|
||||
case PROPERTY_TYPE_STRING:
|
||||
FPUTSR(f, "string ");
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
FPUTSR(f, "integer ");
|
||||
break;
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
FPUTSR(f, "dimension ");
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
FPUTSR(f, "double ");
|
||||
break;
|
||||
}
|
||||
else if (!strncmp(key, "MASKHINTS_", 10))
|
||||
{
|
||||
Rect scalebox, bbox;
|
||||
char *vptr = value, *sptr;
|
||||
int numvals, numrects = 0, n;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
numvals = sscanf(vptr, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop);
|
||||
if (numvals <= 0)
|
||||
break;
|
||||
else if (numvals != 4)
|
||||
{
|
||||
TxError("Error: Cannot parse %s property value!\n", key);
|
||||
/* Revert property value to original string */
|
||||
if (newvalue != value) freeMagic(newvalue);
|
||||
newvalue = value;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
scalebox.r_xbot = bbox.r_xbot / reducer;
|
||||
scalebox.r_xtop = bbox.r_xtop / reducer;
|
||||
scalebox.r_ybot = bbox.r_ybot / reducer;
|
||||
scalebox.r_ytop = bbox.r_ytop / reducer;
|
||||
if (numrects == 0)
|
||||
{
|
||||
newvalue = mallocMagic(40);
|
||||
sptr = newvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *tempvalue;
|
||||
tempvalue = mallocMagic(strlen(newvalue) + 40);
|
||||
sprintf(tempvalue, "%s ", newvalue);
|
||||
sptr = tempvalue + strlen(newvalue) + 1;
|
||||
freeMagic(newvalue);
|
||||
newvalue = tempvalue;
|
||||
}
|
||||
sprintf(sptr, "%d %d %d %d",
|
||||
scalebox.r_xbot, scalebox.r_ybot,
|
||||
scalebox.r_xtop, scalebox.r_ytop);
|
||||
numrects++;
|
||||
}
|
||||
|
||||
/* Skip forward four values in value */
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
while (!isspace(*vptr)) vptr++;
|
||||
while (isspace(*vptr) && (*vptr != '\0')) vptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FPUTSR(f, "string ");
|
||||
FPUTSR(f, key);
|
||||
FPUTSR(f, " ");
|
||||
FPUTSR(f, newvalue);
|
||||
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
FPUTSR(f, proprec->prop_value.prop_string);
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
{
|
||||
snprintf(newvalue, 20, " %d", proprec->prop_value.prop_integer[i]);
|
||||
FPUTSR(f, newvalue);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
/* Dimensions scale by the reducer */
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
{
|
||||
snprintf(newvalue, 20, " %d", proprec->prop_value.prop_integer[i]
|
||||
/ reducer);
|
||||
FPUTSR(f, newvalue);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
{
|
||||
snprintf(newvalue, 20, " %"DLONG_PREFIX"d",
|
||||
proprec->prop_value.prop_double[i]);
|
||||
FPUTSR(f, newvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
FPUTSR(f, "\n");
|
||||
|
||||
if (newvalue != value) freeMagic(newvalue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4311,32 +4468,62 @@ dbWriteUseCommandsFunc(cellUse, cdarg)
|
|||
*/
|
||||
|
||||
int
|
||||
dbWritePropCommandsFunc(key, value, cdarg)
|
||||
dbWritePropCommandsFunc(key, proprec, cdarg)
|
||||
char *key;
|
||||
char *value;
|
||||
PropertyRecord *proprec;
|
||||
ClientData cdarg;
|
||||
{
|
||||
struct writeArg *arg = (struct writeArg *) cdarg;
|
||||
char *escstr, *p, *v;
|
||||
int vallen;
|
||||
char *escstr, *p, *v, *value;
|
||||
int i, vallen;
|
||||
FILE *f = arg->wa_file;
|
||||
MagWindow *w;
|
||||
|
||||
/* Probably need to escape more than just quotes here. */
|
||||
vallen = strlen(value) + 1;
|
||||
for (v = value; *v != '\0'; v++)
|
||||
if (*v == '"') vallen++;
|
||||
|
||||
escstr = (char *)mallocMagic(vallen);
|
||||
p = escstr;
|
||||
for (v = value; *v != '\0'; v++)
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
if (*v == '"')
|
||||
*p++ = '\\';
|
||||
*p++ = *v;
|
||||
case PROPERTY_TYPE_STRING:
|
||||
/* Probably need to escape more than just quotes here. */
|
||||
value = proprec->prop_value.prop_string;
|
||||
vallen = strlen(value) + 1;
|
||||
for (v = value; *v != '\0'; v++)
|
||||
if (*v == '"') vallen++;
|
||||
|
||||
escstr = (char *)mallocMagic(vallen);
|
||||
p = escstr;
|
||||
for (v = value; *v != '\0'; v++)
|
||||
{
|
||||
if (*v == '"')
|
||||
*p++ = '\\';
|
||||
*p++ = *v;
|
||||
}
|
||||
*p = '\0';
|
||||
fprintf(f, "property string %s \"%s\"\n", key, escstr);
|
||||
freeMagic(escstr);
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
fprintf(f, "property integer ");
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
fprintf(f, "%d ", proprec->prop_value.prop_integer[i]);
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_DIMENSION:
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
fprintf(f, "property dimension ");
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
fprintf(f, "%d ", DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||
w, ((i % 2) == 0) ? TRUE : FALSE));
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE_DOUBLE:
|
||||
fprintf(f, "property double ");
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
fprintf(f, "%"DLONG_PREFIX"d ", proprec->prop_value.prop_double[i]);
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
}
|
||||
*p = '\0';
|
||||
fprintf(f, "property %s \"%s\"\n", key, escstr);
|
||||
freeMagic(escstr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,16 +47,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
|
||||
void
|
||||
DBPropPut(cellDef, name, value)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
ClientData value; /* MUST point to a malloc'ed structure, or NULL.
|
||||
* This will be freed when the CellDef is freed.
|
||||
*/
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL.
|
||||
* This will be freed when the CellDef is freed.
|
||||
*/
|
||||
|
||||
{
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
char *oldvalue;
|
||||
PropertyRecord *oldvalue;
|
||||
|
||||
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
||||
/* the value would be saved in the hash table, so if it is not */
|
||||
|
|
@ -95,12 +95,12 @@ DBPropPut(cellDef, name, value)
|
|||
}
|
||||
|
||||
entry = HashFind(htab, name);
|
||||
oldvalue = (char *)HashGetValue(entry);
|
||||
if (oldvalue != NULL) freeMagic(oldvalue);
|
||||
if (value == (ClientData)NULL)
|
||||
oldvalue = (PropertyRecord *)HashGetValue(entry);
|
||||
if (oldvalue != NULL) freeMagic((char *)oldvalue);
|
||||
if (value == (PropertyRecord *)NULL)
|
||||
HashRemove(htab, name);
|
||||
else
|
||||
HashSetValue(entry, value);
|
||||
HashSetValue(entry, PTR2CD(value));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
|
@ -110,13 +110,13 @@ DBPropPut(cellDef, name, value)
|
|||
* Get a property from a celldef.
|
||||
*
|
||||
* Results:
|
||||
* NULL if the property didn't exist, or if the property value was NULL.
|
||||
* Otherwise, ClientData that represents the property.
|
||||
* NULL if the property didn't exist, or if the property record was NULL.
|
||||
* Otherwise, returns a pointer to the property record.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
ClientData
|
||||
PropertyRecord *
|
||||
DBPropGet(cellDef, name, found)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
|
|
@ -124,12 +124,12 @@ DBPropGet(cellDef, name, found)
|
|||
* exists.
|
||||
*/
|
||||
{
|
||||
ClientData result;
|
||||
PropertyRecord *result;
|
||||
bool haveit;
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
|
||||
result = (ClientData) NULL;
|
||||
result = (PropertyRecord *)NULL;
|
||||
haveit = FALSE;
|
||||
htab = (HashTable *) cellDef->cd_props;
|
||||
if (htab == (HashTable *) NULL) goto done;
|
||||
|
|
@ -138,7 +138,7 @@ DBPropGet(cellDef, name, found)
|
|||
if (entry != NULL)
|
||||
{
|
||||
haveit = TRUE;
|
||||
result = (ClientData) HashGetValue(entry);
|
||||
result = (PropertyRecord *)HashGetValue(entry);
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -146,6 +146,109 @@ done:
|
|||
return result;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBPropGetString --
|
||||
*
|
||||
* Get a string property from a celldef.
|
||||
*
|
||||
* Results:
|
||||
* NULL if the property didn't exist, or if the property record was NULL.
|
||||
* Otherwise, returns a pointer to the property's string record.
|
||||
*
|
||||
* Notes:
|
||||
* This is basically the original DBPropGet(), when properties were only
|
||||
* allowed to be strings.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
DBPropGetString(cellDef, name, found)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||
* exists.
|
||||
*/
|
||||
{
|
||||
char *result = NULL;
|
||||
PropertyRecord *proprec;
|
||||
bool haveit;
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
|
||||
haveit = FALSE;
|
||||
htab = (HashTable *) cellDef->cd_props;
|
||||
if (htab == (HashTable *) NULL) goto pdone;
|
||||
|
||||
entry = HashLookOnly(htab, name);
|
||||
if (entry != NULL)
|
||||
{
|
||||
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||
if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||
{
|
||||
haveit = TRUE;
|
||||
result = proprec->prop_value.prop_string;
|
||||
}
|
||||
}
|
||||
|
||||
pdone:
|
||||
if (found != (bool *) NULL) *found = haveit;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBPropGetDouble --
|
||||
*
|
||||
* Get a single double-long integer property from a celldef.
|
||||
*
|
||||
* Results:
|
||||
* NULL if the property didn't exist, or if the property record was NULL.
|
||||
* Otherwise, returns a pointer to the property's value record.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
dlong
|
||||
DBPropGetDouble(cellDef, name, found)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||
* exists.
|
||||
*/
|
||||
{
|
||||
dlong result = 0;
|
||||
PropertyRecord *proprec;
|
||||
bool haveit;
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
|
||||
haveit = FALSE;
|
||||
htab = (HashTable *) cellDef->cd_props;
|
||||
if (htab == (HashTable *) NULL) goto ddone;
|
||||
|
||||
entry = HashLookOnly(htab, name);
|
||||
if (entry != NULL)
|
||||
{
|
||||
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||
if (proprec->prop_type == PROPERTY_TYPE_DOUBLE)
|
||||
{
|
||||
haveit = TRUE;
|
||||
result = proprec->prop_value.prop_double[0];
|
||||
}
|
||||
else if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||
{
|
||||
haveit = TRUE;
|
||||
sscanf(proprec->prop_value.prop_string, "%"DLONG_PREFIX"d", &result);
|
||||
}
|
||||
}
|
||||
|
||||
ddone:
|
||||
if (found != (bool *) NULL) *found = haveit;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBPropEnum --
|
||||
|
|
@ -168,7 +271,7 @@ DBPropEnum(cellDef, func, cdata)
|
|||
*
|
||||
* int foo(name, value, cdata)
|
||||
* char *name;
|
||||
* ClientData value;
|
||||
* PropertyRecord *value;
|
||||
* ClientData cdata;
|
||||
* {
|
||||
* -- return 0 to continue,
|
||||
|
|
@ -189,7 +292,7 @@ DBPropEnum(cellDef, func, cdata)
|
|||
HashStartSearch(&hs);
|
||||
while ((entry = HashNext(htab, &hs)) != NULL)
|
||||
{
|
||||
res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
|
||||
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata);
|
||||
if (res != 0) return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -704,6 +704,24 @@ struct conSrArg2
|
|||
|
||||
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
||||
|
||||
/* ------------------------ Properties ------------------------------ */
|
||||
|
||||
/* Note that the property record is a single allocated block large enough
|
||||
* to hold the string or integer list, and can be freed as a single block.
|
||||
* The array bounds, like those of lab_text for labels, are placeholders.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int prop_type; /* See codes below; e.g., PROPERTY_TYPE_STRING */
|
||||
int prop_len; /* String length or number of values */
|
||||
union {
|
||||
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 */
|
||||
} prop_value;
|
||||
} PropertyRecord;
|
||||
|
||||
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
||||
|
||||
typedef struct
|
||||
|
|
@ -736,6 +754,13 @@ typedef struct
|
|||
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
||||
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
||||
|
||||
/* ---------------------- Codes for properties -------------------------*/
|
||||
|
||||
#define PROPERTY_TYPE_STRING 0 /* ASCII string property */
|
||||
#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) */
|
||||
|
||||
/* -------------------- Exported procedure headers -------------------- */
|
||||
|
||||
/* Painting/erasing */
|
||||
|
|
@ -921,7 +946,9 @@ extern void DBFreePaintPlane();
|
|||
|
||||
/* Cell properties */
|
||||
extern void DBPropPut();
|
||||
extern ClientData DBPropGet();
|
||||
extern PropertyRecord *DBPropGet();
|
||||
extern char *DBPropGetString();
|
||||
extern dlong DBPropGetDouble();
|
||||
extern int DBPropEnum();
|
||||
extern void DBPropClearAll();
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,11 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<B>property</B> [<I>key</I> [<I>value</I>]] <BR><BR>
|
||||
<B>property</B> [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
|
||||
<BLOCKQUOTE>
|
||||
where <I>key</I> and <I>value</I> are any text strings.
|
||||
where <I>key</I> and <I>value</I> are any text strings. <BR>
|
||||
<I>type</I> may be one of <B>string</B>, <B>integer</B>,
|
||||
<B>dimension</B>, or <B>double</B>.
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
@ -45,11 +47,48 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
with the key is returned. With both arguments, the string
|
||||
<I>value</I> is associated with the string <I>key</I> as a
|
||||
property of the cell. If <I>key</I> is an existing key, then
|
||||
its original value will be overwritten.
|
||||
its original value will be overwritten. <P>
|
||||
|
||||
By default, properties are interpreted as verbatim string values,
|
||||
with exceptions for the reserved types (see below). To force the
|
||||
values of the property to be interpreted as a specific type, use
|
||||
the <I>type</I> option.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Property names reserved by and used by magic:
|
||||
Types are interpreted as follows:
|
||||
<DL>
|
||||
<DT> <B>string</B> type:
|
||||
<DD> The property value is a character string. Character strings
|
||||
may contain spaces, but if so, then the string should be quoted
|
||||
or in braces, per Tcl syntax.
|
||||
<DT> <B>integer</I> type:
|
||||
<DD> The property value is an integer value or a list of integer
|
||||
values. The values are not considered to be measurements and
|
||||
do not scale. Multiple values may be passed on the command
|
||||
line as additional arguments, or the set of values may be
|
||||
given as a list.
|
||||
<DT> <B>dimension</I> type:
|
||||
<DD> The property value is an integer value or a list of integer
|
||||
values. The values are considered to be (linear) dimensional
|
||||
measurements and therefore scale with the database internal
|
||||
units. They are interpreted as having the values currently
|
||||
specified for <B>units</B>, and display back in the same
|
||||
units. Multiple values may be passed on the command line as
|
||||
additional arguments, or the set of values may be given as a
|
||||
list.
|
||||
<DT> <B>double</I> type:
|
||||
<DD> The property value is a double-wide (64-bit) integer value or
|
||||
a list of double-wide integer values. The values are not
|
||||
considered to be measurements and do not scale. Multiple
|
||||
values may be passed on the command line as additional arguments,
|
||||
or the set of values may be given as a list.
|
||||
</DL>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Property names reserved by and used by magic (types are <B>string</B>
|
||||
unless otherwise noted):
|
||||
<DL>
|
||||
<DT> <B>GDS_FILE</B>
|
||||
<DD> The value is the name of a GDS file which contains the mask
|
||||
|
|
@ -60,12 +99,14 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||
byte position of the start of mask data for this cell definition
|
||||
in the file. If set to value <B>0</B>, then the file will be
|
||||
searched for the data bounds.
|
||||
searched for the data bounds. This property is always of type
|
||||
<B>double</B>.
|
||||
<DT> <B>GDS_END</B>
|
||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||
byte position of the end of mask data for this cell definition
|
||||
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
||||
property may be omitted.
|
||||
property may be omitted. This property is always of type
|
||||
<B>double</B>.
|
||||
<DT> <B>LEFview</B>
|
||||
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
||||
obtained from a LEF macro, and should not be used for extraction
|
||||
|
|
@ -97,6 +138,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
corresponding to the abutment box of the cell, in magic's internal
|
||||
units. The abutment box is automatically read from LEF files, but
|
||||
may be defined for any file and can be used for placement alignment.
|
||||
This property is always of type <B>dimension</B> and must contain
|
||||
exactly four values.
|
||||
<DT> <B>OBS_BBOX</B>
|
||||
<DD> This property value is a space-sparated list of four integer values
|
||||
corresponding to a bounding box to be used when generating a LEF
|
||||
|
|
@ -104,7 +147,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
will be entirely covered in obstruction layers (unless cut-outs
|
||||
are required to accommodate pins). Any set-back applied by the
|
||||
"lef write -hide <value>" option will be applied to this obstruction
|
||||
box.
|
||||
box. This property is always of type <B>dimension</B> and must
|
||||
contain exactly four values.
|
||||
<DT> <B>flatten</B>
|
||||
<DD> This property is used in conjunction with the "flatten -doproperty"
|
||||
command option and marks the cell for flattening. Cells without
|
||||
|
|
@ -146,7 +190,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
always generate mask layer <I>type</I> in the specified rectangle
|
||||
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
||||
such that <I>type</I> could be defined as the absence of a mask layer,
|
||||
for example.
|
||||
for example. This property is always of type <B>dimension</B> and
|
||||
must have a multiple of four values.
|
||||
</DL>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
@ -157,6 +202,11 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
the cell definition structure.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>See Also:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF=units.html><B>units</B></A> <BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><IMG SRC=graphics/line1.gif><P>
|
||||
<TABLE BORDER=0>
|
||||
<TR>
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ extBasic(def, outFile)
|
|||
}
|
||||
|
||||
/* Check for "device", as it modifies handling of parasitics */
|
||||
propptr = (char *)DBPropGet(def, "device", &propfound);
|
||||
propptr = DBPropGetString(def, "device", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
/* Remove parasitics from local nodes */
|
||||
|
|
@ -1702,7 +1702,7 @@ extOutputParameters(def, transList, outFile)
|
|||
* and device name, and if detected, add the type corresponding to the
|
||||
* device name to the mask so it gets handled, too.
|
||||
*/
|
||||
propptr = DBPropGet(def, "device", &propfound);
|
||||
propptr = DBPropGetString(def, "device", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
char *devname;
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ extHeader(def, f)
|
|||
/* are to be passed to instances of the cell */
|
||||
/* (created by defining property "parameter") */
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "parameter", &propfound);
|
||||
propvalue = DBPropGetString(def, "parameter", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
// Use device parameter table to store the cell def parameters,
|
||||
|
|
|
|||
|
|
@ -1359,15 +1359,21 @@ DefReadLocation(
|
|||
|
||||
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propval;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
propval = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
r = ▭
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2453,7 +2459,7 @@ DefRead(
|
|||
FILE *f;
|
||||
char *filename;
|
||||
const char *token;
|
||||
char *bboxstr;
|
||||
PropertyRecord *proprec;
|
||||
int keyword, dscale, total;
|
||||
float oscale;
|
||||
Rect *dierect;
|
||||
|
|
@ -2605,14 +2611,17 @@ DefRead(
|
|||
break;
|
||||
case DEF_DIEAREA:
|
||||
dierect = LefReadRect(f, 0, oscale);
|
||||
bboxstr = mallocMagic(40);
|
||||
sprintf(bboxstr, "%d %d %d %d",
|
||||
dierect->r_xbot,
|
||||
dierect->r_ybot,
|
||||
dierect->r_xtop,
|
||||
dierect->r_ytop);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
2 * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = dierect->r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = dierect->r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = dierect->r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = dierect->r_ytop;
|
||||
if (rootDef == NULL) rootDef = DefNewCell(inName);
|
||||
DBPropPut(rootDef, "FIXED_BBOX", bboxstr);
|
||||
DBPropPut(rootDef, "FIXED_BBOX", proprec);
|
||||
|
||||
LefEndStatement(f);
|
||||
break;
|
||||
case DEF_PROPERTYDEFINITIONS:
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ defWriteHeader(
|
|||
float oscale,
|
||||
int units) /* Units for UNITS; could be derived from oscale */
|
||||
{
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
bool propfound;
|
||||
|
||||
TxPrintf("Diagnostic: Write DEF header for cell %s\n", def->cd_name);
|
||||
|
|
@ -141,15 +141,20 @@ defWriteHeader(
|
|||
/* For DIEAREA, use the FIXED_BBOX property if present. Otherwise, */
|
||||
/* use the extents of geometry (CellDef bounding box) */
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
Rect bbox;
|
||||
|
||||
/* Die area, taken from the declared FIXED_BBOX. */
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
{
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
|
||||
fprintf(f, " DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n",
|
||||
(float)bbox.r_xbot * oscale,
|
||||
(float)bbox.r_ybot * oscale,
|
||||
|
|
@ -2786,15 +2791,21 @@ arrayDefFunc(
|
|||
|
||||
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propval;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
propval = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
r = ▭
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2844,15 +2855,20 @@ defComponentFunc(
|
|||
xoff = yoff = 0;
|
||||
if (cellUse->cu_def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propval;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
propval = (char *)DBPropGet(cellUse->cu_def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(cellUse->cu_def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
|
||||
r = ▭
|
||||
GeoTransRect(&cellUse->cu_transform, &rect, &bbrect);
|
||||
GeoTransRect(&cellUse->cu_transform, &cellUse->cu_def->cd_bbox, &defrect);
|
||||
|
|
|
|||
101
lef/lefRead.c
101
lef/lefRead.c
|
|
@ -2150,6 +2150,7 @@ LefReadMacro(
|
|||
int keyword, pinNum, propsize, result;
|
||||
float x, y;
|
||||
bool has_size, is_imported = FALSE, propfound;
|
||||
PropertyRecord *proprec;
|
||||
Rect lefBBox;
|
||||
Point gdsOffset; /* Difference between GDS and LEF coordinates */
|
||||
|
||||
|
|
@ -2250,7 +2251,12 @@ LefReadMacro(
|
|||
sprintf(tsave + strlen(tsave), " %s", token);
|
||||
token = LefNextToken(f, TRUE);
|
||||
}
|
||||
DBPropPut(lefMacro, "LEFclass", StrDup((char **)NULL, tsave + 1));
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
strlen(tsave + 1) - 7);
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = strlen(tsave + 1);
|
||||
strcpy(proprec->prop_value.prop_string, tsave + 1);
|
||||
DBPropPut(lefMacro, "LEFclass", proprec);
|
||||
break;
|
||||
case LEF_SIZE:
|
||||
token = LefNextToken(f, TRUE);
|
||||
|
|
@ -2294,7 +2300,12 @@ origin_error:
|
|||
sprintf(tsave + strlen(tsave), " %s", token);
|
||||
token = LefNextToken(f, TRUE);
|
||||
}
|
||||
DBPropPut(lefMacro, "LEFsymmetry", StrDup((char **)NULL, tsave + 1));
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
strlen(tsave + 1) - 7);
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = strlen(tsave + 1);
|
||||
strcpy(proprec->prop_value.prop_string, tsave + 1);
|
||||
DBPropPut(lefMacro, "LEFsymmetry", proprec);
|
||||
break;
|
||||
case LEF_SOURCE:
|
||||
token = LefNextToken(f, TRUE);
|
||||
|
|
@ -2305,12 +2316,19 @@ origin_error:
|
|||
case LEF_SITE:
|
||||
token = LefNextToken(f, TRUE);
|
||||
if (*token != '\n')
|
||||
DBPropPut(lefMacro, "LEFsite", StrDup((char **)NULL, token));
|
||||
{
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
strlen(token) - 7);
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = strlen(token);
|
||||
strcpy(proprec->prop_value.prop_string, token);
|
||||
DBPropPut(lefMacro, "LEFsite", proprec);
|
||||
}
|
||||
LefEndStatement(f);
|
||||
break;
|
||||
case LEF_PROPERTY:
|
||||
/* Append property key:value pairs to the cell property LEFproperties */
|
||||
propval = (char *)DBPropGet(lefMacro, "LEFproperties", &propfound);
|
||||
propval = DBPropGetString(lefMacro, "LEFproperties", &propfound);
|
||||
if (propfound)
|
||||
propsize = strlen(propval);
|
||||
else
|
||||
|
|
@ -2322,14 +2340,19 @@ origin_error:
|
|||
char *propext;
|
||||
sprintf(tsave, "%.127s", token);
|
||||
token = LefNextToken(f, TRUE);
|
||||
propext = (char *)mallocMagic(propsize + strlen(tsave) +
|
||||
strlen(token) + 4);
|
||||
if (propsize > 0)
|
||||
sprintf(propext, "%s %s %s", propval, tsave, token);
|
||||
else
|
||||
sprintf(propext, "%s %s", tsave, token);
|
||||
|
||||
DBPropPut(lefMacro, "LEFproperties", StrDup((char **)NULL, propext));
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
propsize + strlen(tsave) + strlen(token) - 3);
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = propsize + strlen(tsave) + strlen(token) + 4;
|
||||
|
||||
if (propsize > 0)
|
||||
sprintf(proprec->prop_value.prop_string, "%s %s %s",
|
||||
propval, tsave, token);
|
||||
else
|
||||
sprintf(proprec->prop_value.prop_string, "%s %s", tsave, token);
|
||||
|
||||
DBPropPut(lefMacro, "LEFproperties", proprec);
|
||||
}
|
||||
LefEndStatement(f);
|
||||
break;
|
||||
|
|
@ -2405,11 +2428,16 @@ foreign_error:
|
|||
if (has_size)
|
||||
{
|
||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||
propval = (char *)mallocMagic(40);
|
||||
sprintf(propval, "%d %d %d %d",
|
||||
lefBBox.r_xbot, lefBBox.r_ybot,
|
||||
lefBBox.r_xtop, lefBBox.r_ytop);
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(2 * sizeof(int)));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = lefBBox.r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = lefBBox.r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = lefBBox.r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = lefBBox.r_ytop;
|
||||
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2419,11 +2447,16 @@ foreign_error:
|
|||
if (has_size)
|
||||
{
|
||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||
propval = (char *)mallocMagic(40);
|
||||
sprintf(propval, "%d %d %d %d",
|
||||
lefBBox.r_xbot, lefBBox.r_ybot,
|
||||
lefBBox.r_xtop, lefBBox.r_ytop);
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(2 * sizeof(int)));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = lefBBox.r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = lefBBox.r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = lefBBox.r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = lefBBox.r_ytop;
|
||||
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2432,13 +2465,17 @@ foreign_error:
|
|||
|
||||
/* Set the placement bounding box property to the current bounding box */
|
||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||
propval = (char *)mallocMagic(40);
|
||||
sprintf(propval, "%d %d %d %d",
|
||||
lefMacro->cd_bbox.r_xbot,
|
||||
lefMacro->cd_bbox.r_ybot,
|
||||
lefMacro->cd_bbox.r_xtop,
|
||||
lefMacro->cd_bbox.r_ytop);
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
(2 * sizeof(int)));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
proprec->prop_value.prop_integer[0] = lefMacro->cd_bbox.r_xbot;
|
||||
proprec->prop_value.prop_integer[1] = lefMacro->cd_bbox.r_ybot;
|
||||
proprec->prop_value.prop_integer[2] = lefMacro->cd_bbox.r_xtop;
|
||||
proprec->prop_value.prop_integer[3] = lefMacro->cd_bbox.r_ytop;
|
||||
|
||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
||||
DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox);
|
||||
}
|
||||
}
|
||||
|
|
@ -2453,7 +2490,13 @@ foreign_error:
|
|||
/* i.e., setting it to "FALSE" would be ineffective. */
|
||||
|
||||
if (!is_imported)
|
||||
DBPropPut(lefMacro, "LEFview", StrDup((char **)NULL, "TRUE"));
|
||||
{
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||
proprec->prop_len = 4;
|
||||
strcpy(proprec->prop_value.prop_string, "TRUE");
|
||||
DBPropPut(lefMacro, "LEFview", proprec);
|
||||
}
|
||||
|
||||
DBWAreaChanged(lefMacro, &lefMacro->cd_bbox, DBW_ALLWINDOWS,
|
||||
&DBAllButSpaceBits);
|
||||
|
|
|
|||
|
|
@ -328,14 +328,14 @@ lefWriteHeader(
|
|||
{
|
||||
fprintf(f, "SITE %s\n", siteDef->cd_name);
|
||||
|
||||
propvalue = (char *)DBPropGet(siteDef, "LEFsymmetry", &propfound);
|
||||
propvalue = DBPropGetString(siteDef, "LEFsymmetry", &propfound);
|
||||
if (propfound)
|
||||
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
||||
else
|
||||
/* Usually core cells have symmetry Y only. */
|
||||
fprintf(f, IN0 "SYMMETRY Y ;\n");
|
||||
|
||||
propvalue = (char *)DBPropGet(siteDef, "LEFclass", &propfound);
|
||||
propvalue = DBPropGetString(siteDef, "LEFclass", &propfound);
|
||||
if (propfound)
|
||||
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
||||
else
|
||||
|
|
@ -345,10 +345,20 @@ lefWriteHeader(
|
|||
boundary = siteDef->cd_bbox;
|
||||
if (siteDef->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
PropertyRecord *proprec;
|
||||
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
|
||||
&boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
|
||||
{
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
boundary.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
boundary.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
boundary.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
boundary.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scale = CIFGetOutputScale(1000); /* conversion to microns */
|
||||
|
|
@ -1288,7 +1298,7 @@ lefWriteMacro(
|
|||
/* default values are optional, so in this case we will leave those */
|
||||
/* entries blank. */
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFclass", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFclass", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
||||
|
|
@ -1324,13 +1334,21 @@ lefWriteMacro(
|
|||
|
||||
if (def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
bool found;
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
|
||||
&boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
|
||||
{
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
boundary.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
boundary.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
boundary.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
boundary.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if (boundry less setback) is degenerate. If so, then */
|
||||
|
|
@ -1358,11 +1376,11 @@ lefWriteMacro(
|
|||
lc.origin.p_x = 0;
|
||||
lc.origin.p_y = 0;
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFsymmetry", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFsymmetry", &propfound);
|
||||
if (propfound)
|
||||
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFsite", &propfound);
|
||||
if (propfound)
|
||||
fprintf(f, IN0 "SITE %s ;\n", propvalue);
|
||||
|
||||
|
|
@ -1821,20 +1839,24 @@ lefWriteMacro(
|
|||
Rect layerBound, manualBound;
|
||||
labelLinkedList *thislll;
|
||||
bool propfound;
|
||||
char *propvalue;
|
||||
PropertyRecord *proprec;
|
||||
|
||||
/* If there is a property OBS_BBOX, then use the value of the */
|
||||
/* defined box to set the minimum hidden area. This will still */
|
||||
/* get clipped to the setback. */
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "OBS_BBOX", &propfound);
|
||||
proprec = DBPropGet(def, "OBS_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
if (sscanf(propvalue, "%d %d %d %d",
|
||||
&(manualBound.r_xbot),
|
||||
&(manualBound.r_ybot),
|
||||
&(manualBound.r_xtop),
|
||||
&(manualBound.r_ytop)) != 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
manualBound.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
manualBound.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
manualBound.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
manualBound.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Improper values for obstruction bounding box "
|
||||
"OBS_BBOX property");
|
||||
|
|
@ -2016,7 +2038,7 @@ lefWriteMacro(
|
|||
|
||||
/* If there are any properties saved in LEFproperties, write them out */
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFproperties", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
char *delim;
|
||||
|
|
@ -2094,7 +2116,7 @@ lefGetSites(
|
|||
bool propfound;
|
||||
char *propvalue;
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFsite", &propfound);
|
||||
if (propfound)
|
||||
he = HashFind(lefSiteTbl, propvalue); /* FIXME return value not used from call to function with no side-effects (reevaluate this entire func purpose?) */
|
||||
|
||||
|
|
@ -2124,7 +2146,7 @@ lefGetProperties(
|
|||
bool propfound;
|
||||
char *propvalue;
|
||||
|
||||
propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
|
||||
propvalue = DBPropGetString(def, "LEFproperties", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
char *key;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ MAGIC_8.0 {
|
|||
DBPlaneTypes;
|
||||
DBPrintUseId;
|
||||
DBPropGet;
|
||||
DBPropGetString;
|
||||
DBPropGetDouble;
|
||||
DBPutLabel;
|
||||
DBReComputeBbox;
|
||||
DBSeeTypesAll;
|
||||
|
|
|
|||
|
|
@ -321,14 +321,20 @@ selRedisplayCellFunc(scx, window)
|
|||
if (scx->scx_use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
bool found;
|
||||
char *propval;
|
||||
PropertyRecord *proprec;
|
||||
|
||||
propval = (char *)DBPropGet(scx->scx_use->cu_def, "FIXED_BBOX", &found);
|
||||
proprec = DBPropGet(scx->scx_use->cu_def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propval, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
{
|
||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||
GeoTransRect(&scx->scx_trans, &bbox, &tmp);
|
||||
}
|
||||
else
|
||||
found = FALSE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue