/* * DBprop.c -- * * Implement properties on database cells. Properties are name-value pairs * and provide a flexible way of extending the data that is stored in a * CellDef. Maybe in the future properties will be added to other database * objects. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBprop.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; #endif /* not lint */ #include #include #include "utils/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/malloc.h" /* ---------------------------------------------------------------------------- * * DBPropPut -- * * Put a property onto a celldef. * * Results: * None. * * ---------------------------------------------------------------------------- */ void DBPropPut(cellDef, name, value) 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; 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 */ /* being used, then it must be freed here. */ if (cellDef->cd_flags & CDNOEDIT) { if (value != (ClientData)NULL) freeMagic((char *)value); return; } if (cellDef->cd_props == (ClientData) NULL) { cellDef->cd_props = (ClientData) mallocMagic(sizeof(HashTable)); HashInit( (HashTable *) cellDef->cd_props, 8, 0); } htab = (HashTable *) cellDef->cd_props; /* Special handling of FIXED_BBOX, which uses CDFIXEDBBOX as a quick lookup */ if (!strcmp(name, "FIXED_BBOX")) { if (value == (ClientData)NULL) cellDef->cd_flags &= ~CDFIXEDBBOX; else cellDef->cd_flags |= CDFIXEDBBOX; } /* Special handling of GDS_FILE, which uses CDVENDORGDS as a quick lookup */ if (!strcmp(name, "GDS_FILE")) { if (value == (ClientData)NULL) cellDef->cd_flags &= ~CDVENDORGDS; else cellDef->cd_flags |= CDVENDORGDS; } entry = HashFind(htab, name); oldvalue = (PropertyRecord *)HashGetValue(entry); if (oldvalue != NULL) freeMagic((char *)oldvalue); if (value == (PropertyRecord *)NULL) HashRemove(htab, name); else HashSetValue(entry, PTR2CD(value)); } /* ---------------------------------------------------------------------------- * * DBPropGet -- * * Get a 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 record. * * ---------------------------------------------------------------------------- */ PropertyRecord * DBPropGet(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. */ { PropertyRecord *result; bool haveit; HashTable *htab; HashEntry *entry; result = (PropertyRecord *)NULL; haveit = FALSE; htab = (HashTable *) cellDef->cd_props; if (htab == (HashTable *) NULL) goto done; entry = HashLookOnly(htab, name); if (entry != NULL) { haveit = TRUE; result = (PropertyRecord *)HashGetValue(entry); } done: if (found != (bool *) NULL) *found = haveit; 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 -- * * Enumerate all the properties on a cell. * * Results: * 0 if the search completed, else whatever value was returned by the * called proc. * * Side effects: * Depends on the called proc. * ---------------------------------------------------------------------------- */ int DBPropEnum(cellDef, func, cdata) CellDef *cellDef; /* Pointer to definition of cell. */ int (*func)(); /* Function of the form: * * int foo(name, value, cdata) * char *name; * PropertyRecord *value; * ClientData cdata; * { * -- return 0 to continue, * -- nonzero to abort. * return result; * } */ ClientData cdata; { HashTable *htab; HashSearch hs; HashEntry *entry; int res; if (cellDef->cd_props == (ClientData) NULL) return 0; htab = (HashTable *) cellDef->cd_props; HashStartSearch(&hs); while ((entry = HashNext(htab, &hs)) != NULL) { res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata); if (res != 0) return res; } return 0; } /* ---------------------------------------------------------------------------- * * DBPropClearAll -- * * Free up all properties and associated storage for a CellDef. * * Results: * none. * * Side effects: * Frees up storage, even for the property table itself. * ---------------------------------------------------------------------------- */ void DBPropClearAll(cellDef) CellDef *cellDef; /* Pointer to definition of cell. */ { HashTable *htab; HashSearch hs; HashEntry *entry; if (cellDef->cd_props == (ClientData) NULL) return; htab = (HashTable *) cellDef->cd_props; HashStartSearch(&hs); while ((entry = HashNext(htab, &hs)) != NULL) { if (entry->h_pointer != NULL) freeMagic((char *) entry->h_pointer); HashSetValue(entry, NULL); } HashKill(htab); freeMagic((char *) htab); cellDef->cd_props = (ClientData) NULL; /* Since CDFIXEDBBOX requires a FIXED_BBOX property, clearing all */ /* properties necessarily means this flag must be clear. */ cellDef->cd_flags &= ~CDFIXEDBBOX; }