/*
 * database.h --
 *
 * Definitions for the database module.
 * This file defines everything that is visible to clients
 * outside the database module.
 *
 *     ********************************************************************* 
 *     * 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.    * 
 *     *********************************************************************
 *
 * Needs to include: magic.h, tile.h
 *
 * rcsid "$Header: /usr/cvsroot/magic-8.0/database/database.h.in,v 1.8 2010/08/25 17:33:55 tim Exp $"
 */

#ifndef _MAGIC__DATABASE__DATABASE_H
#define _MAGIC__DATABASE__DATABASE_H

#ifndef _MAGIC__TILES__TILE_H
#include "tiles/tile.h"
#endif

#ifndef _MAGIC__UTILS__HASH_H
#include "utils/hash.h"
#endif

#ifndef _MAGIC__UTILS__STACK_H
#include "utils/stack.h"
#endif

#ifndef _MAGIC__BPLANE__BPLANE_H
#include "bplane/bplane.h"
#endif

/* ----------------------- Tunable constants -------------------------- */

#define	MAXPLANES	64	/* Maximum number of planes per cell */

    /*
     * The "unnamed" cell.
     * This is visible only within Magic, and just determines the
     * name by which the initial cell-without-a-name appears.
     */
#define	UNNAMED	"(UNNAMED)"

/* --------------------- Tile types and masks ------------------------- */

typedef int TileType;

/*
 * Tile types are small integers (currently from 0 to TT_MAXTYPES-1).
 * They are used in constructing TileTypeBitMask bitmasks with the
 * operators defined below.  A TileTypeBitMask contains one bit for
 * each possible TileType.
 *
 * A negative value of TileType implies an error condition when received
 * from a routine returning a TileType.  Care should be taken to ensure
 * that a negative TileType is never used to index an array!
 *
 * The last TT_RESERVEDTYPES tile types are reserved for use by clients.
 * Because unsigned chars are used to hold tile types (PaintResultType),
 * this number should not be increased without changing the definition
 * of PaintResultType later in this file.
 *
 * (Magic v.7.1) Macros are generated by script scripts/makedbh,
 * with each macro appropriately constructed for the value of
 * TT_MAXTYPES.
 *
 * Each addition of a word to the bitmask increases computation
 * time on all plane operations in magic!  Choose the smallest number
 * required for the technology files used.  The obvious reasonable values
 * to choose are 96, 192, 256, or 512, corresponding to word array sizes
 * of 3, 6, 8, and 16, respectively.
 */

#define	TT_MAXTYPES		256			/* See above! */
#define	TT_RESERVEDTYPES	2			/* See above! */

/*
 * Note that the value of 5 for TT_WORDSHIFT effectively requires that
 * bits-per-word equal 32 or havoc is likely to result.
 */

#define	TT_BPW		(8 * sizeof (unsigned int))
#define	TT_WORDMASK	(TT_BPW - 1)
#define	TT_WORDSHIFT	5			/* LOG2(TT_BPW) */
#define	TT_MASKWORDS	((TT_MAXTYPES + TT_BPW - 1) / TT_BPW)

typedef struct
{
    unsigned int	tt_words[TT_MASKWORDS];
} TileTypeBitMask;

/*
 * Here's a brief note about how to interpret TileTypeBitMasks:
 * The default TT_MAXTYPES = 256 translates to 8 words.  As an
 * example, to examine TileTypeBitMask DBConnectTbl[65]
 * (in this example DBTypeLongNameTbl[65]="metal1").  In gdb,
 * use "print /x DBConnectTbl[65]" to get:
 *
 * $2 = {tt_words = {0x59800000, 0xc8cc22a6, 0x8000003b, 0xff800008, \
 *	0x38f, 0x0, 0x0, 0x0}}
 *
 * The first word represents types 0-31 (lsb to msb, respectively),
 * the second work represents types 32-63, and so forth.  From this
 * result we see that metal1 (type 65) connects to types 23, 24, 27,
 * 28, and 30 (from the 1st word), 33, 34, 37, 39, 41, and so on.
 * A quick check of DBTypeLongNameTbl[] shows that these types are
 * ndc, pdc, psc, nsc, and so forth.
 */

/*
 * Although some tile types are assigned on a technology-specific basis,
 * certain types are independent of the technology used, and are
 * defined below:
 */
#define	TT_SPACE	0	/* Space tile */
#define	TT_PAINTBASE	1	/* First non-space type */
#define TT_CHECKPAINT   1       /* DRC -- paint has changed */
#define TT_CHECKSUBCELL 2	/* DRC -- subcells have changed */
#define TT_ERROR_P      3       /* DRC -- paint error */
#define TT_ERROR_S      4       /* DRC -- subcell error */
#define TT_ERROR_PS     5       /* DRC --             */
#define TT_MAGNET	6	/* magnet for interactive router */
#define TT_FENCE	7	/* fence for interactive router */
#define TT_ROTATE	8	/* rotate for interactive router */
#define TT_SELECTBASE 	TT_MAGNET /* First selectable type */
#define	TT_TECHDEPBASE	9	/* First technology-dependent type */

#define TT_DIAGONAL	0x40000000	/* Bit set for non-manhattan tiles */
#define TT_SIDE		0x20000000	/* Temporary bit set: 1 = right */
#define TT_DIRECTION	0x10000000	/* Bit set for tile split direction */
#define TT_LEFTMASK	0x00003fff	/* Type for left side of split  */
#define TT_RIGHTMASK	0x0fffc000	/* Type for right side of split */

/* Pseudo type signifying unexpanded subcells.  Never painted.  -  Only
   used in a few places, e.g.  TouchingTypes() and mzrouter spacing arrays.
 */
#define TT_SUBCELL	TT_MAXTYPES  

/* The following type is used in the paint result tables to save space. */
#if TT_MAXTYPES > 256
typedef unsigned short PaintResultType;
#else
typedef unsigned char PaintResultType;
#endif

/* Which word in a mask contains the bit for type 't'? */
#define	ttWord(t)	((t) >> TT_WORDSHIFT)

/* Which bit in the above word is for type 't'? */
#define	ttBit(t)	((t) & TT_WORDMASK)

/* Mask for above word with only bit 't' set */
#define	ttMask(t)	((unsigned int)1 << ttBit(t))

/* Operations for manipulating TileTypeBitMasks */
#define TTMaskSetType(m, t)	((m)->tt_words[ttWord(t)] |= ttMask(t))
#define	TTMaskClearType(m, t)	((m)->tt_words[ttWord(t)] &= ~ttMask(t))
#define	TTMaskHasType(m, t)	(((m)->tt_words[ttWord(t)] & ttMask(t)) != 0)
#define	TTMaskSetOnlyType(m, t)	(TTMaskZero(m), TTMaskSetType(m, t))

/* ---------------------- Planes and masks ---------------------------- */
/*
 * Plane numbers are also small integers.  Certain planes are
 * technology-specific, but others are always present independent
 * of the technology used.
 *
 * Note that the CELL plane and the DRC_CHECK plane are invisible
 * as far as normal painting operations are concerned, but that the
 * DRC_CHECK plane does get written out to the .cad file.
 *
 * The following macros are used for converting between plane numbers
 * and masks of same.
 */
#if (MAXPLANES <= 32)
  #define PlaneMask		int
#else
  #define PlaneMask		dlong
#endif

#define	PlaneNumToMaskBit(p)	((PlaneMask)1 << (p))
#define	PlaneMaskHasPlane(m, p)	(((m) & PlaneNumToMaskBit(p)) != 0)


#define	PL_MAXTYPES	MAXPLANES	/* Maximum number of planes per cell */
#define	PL_ROUTER	0		/* Used by the router and plow modules */
#define PL_DRC_CHECK	1		/* DRC plane for CHECK tiles */
#define PL_DRC_ERROR	2		/* DRC plane for ERROR tiles */
#define PL_M_HINT	3		/* magnet hints for irouter */
#define PL_F_HINT       4		/* fence hints for irouter */
#define PL_R_HINT	5		/* rotate hints for irouter */
#define PL_SELECTBASE	PL_M_HINT	/* First plane with selectable types */
#define	PL_TECHDEPBASE	6		/* First technology-dependent plane */
#define PL_PAINTBASE	1		/* Base of paint planes */

/* --------------------------- Labels --------------------------------- */

/*
 * The body of a tile may have a list of labels associated with it.
 * Each label contains a location that indicates the point at which the
 * label is supposed to appear attached.  This location must be within
 * the tile on whose list the label appears.
 *
 * Note that structure parts lab_size, lab_rotate, lab_bbox,
 * and lab_offset are all used only by the outline fonts, when 
 * the value of lab_font is not -1.
 */

typedef struct label
{
    TileType        lab_type;		/* Type of material to which this label
					 * is attached.  This material, or
					 * other materials that connect it,
					 * must be present everywhere under
					 * the area of the label (Magic
					 * enforces this).  If there isn't
					 * any such material, lab_type is
					 * TT_SPACE.
					 */
    Rect            lab_rect;		/* Area of paint to which label is
					 * attached.
					 */
    Point	    lab_corners[4];	/* The four corners of the label.  Values
					 * are in (database units / 8), and
					 * indicate the relative distance from
					 * the center of lab_rect.
					 */ 
    Rect	    lab_bbox;		/* Area of the label itself, in surface
					 * coordinates (if font is not -1).  This
					 * is derived from lab_corners[] and
				 	 * cached in lab_bbox;
					 */
    int		    lab_just;		/* Justification (GEO_NORTH, etc.) */
    signed char	    lab_font;		/* Font used for label. -1 is the default
					 * X11 font; other values are indexes into
					 * the font tables.
					 */
    int		    lab_size;		/* Scale of font relative to database,
					 * in (database units / 8)
					 */
    short	    lab_rotate;		/* Rotation of label, in degrees */
    Point	    lab_offset;		/* Offset relative to origin point, in
					 * units of (database units / 8)
					 */
    unsigned short  lab_flags;		/* Information, especially for
					 * marking port labels
					 */
    unsigned int    lab_port;		/* Port number, if label is a port */
    struct label   *lab_next;      	/* Next label in list */
    char            lab_text[];   	/* Actual text of label. This
                                     * MUST be the last field in the
                                     * structure.
                                     */
} Label;

/*
 * Size of a Label big enough to hold a string containing
 * n bytes (not including the NULL byte).
 */
#define labelSize(n) (sizeof(Label) + n + 1)

/*
 * Label flags bit fields
 */

#define PORT_DIR_MASK	0x00000f	/* Mask of all port directions 	   */
#define PORT_DIR_NORTH	0x000001	/* Port allows connection to north */
#define PORT_DIR_EAST	0x000002	/* Port allows connection to east  */
#define PORT_DIR_SOUTH	0x000004	/* Port allows connection to south */
#define PORT_DIR_WEST	0x000008	/* Port allows connection to west  */

#define PORT_CLASS_MASK		 0x070 /* Mask of all port classes	*/
#define PORT_CLASS_DEFAULT	 0x000 /* Port takes default class	*/
#define PORT_CLASS_INPUT	 0x010 /* Port is a digital input	*/
#define PORT_CLASS_OUTPUT	 0x020 /* Port is a digital output	*/
#define PORT_CLASS_TRISTATE	 0x030 /* Port is a tri-state output	*/
#define PORT_CLASS_BIDIRECTIONAL 0x040 /* Port is analog or digital	*/
				       /*   bidirectional		*/
#define PORT_CLASS_FEEDTHROUGH	 0x050 /* Port touches no active	*/
				       /*   devices			*/

#define PORT_USE_MASK	   0x0780	/* Mask of all port uses	*/
#define PORT_USE_DEFAULT   0x0000	/* Port takes default use	*/
#define PORT_USE_SIGNAL	   0x0080	/* Port is a digital signal	*/
#define PORT_USE_ANALOG	   0x0100	/* Port is an analog signal	*/
#define PORT_USE_POWER	   0x0180	/* Port is a power rail		*/
#define PORT_USE_GROUND    0x0200	/* Port is a ground rail	*/
#define PORT_USE_CLOCK     0x0280	/* Port is a digital clock	*/
#define PORT_USE_RESET	   0x0300	/* Port is a digital reset	*/
#define PORT_USE_SCAN	   0x0380	/* Port is a digital scan	*/
#define PORT_USE_TIEOFF	   0x0400	/* Port is a tie-off		*/

#define PORT_SHAPE_MASK	   0x1800	/* Mask of all port shapes	*/
#define PORT_SHAPE_DEFAULT 0x0000	/* Port takes default shape	*/
#define PORT_SHAPE_ABUT	   0x0800	/* Port is an abutment shape	*/
#define PORT_SHAPE_RING	   0x1000	/* Port is a ring shape		*/
#define PORT_SHAPE_THRU	   0x1800	/* Port is a feedthrough shape	*/

#define LABEL_STICKY	   0x2000	/* Label does not change layers	*/
#define LABEL_UNIQUE	   0x4000	/* Temporary unique label	*/

/* The last two flags are never used at the same time and so can share
 * a flag bit.
 */
#define PORT_VISITED	   0x8000	/* Bit for checking if a port	*/
					/* has been previously visited.	*/
#define LABEL_GENERATE	   0x8000	/* Auto-generated label		*/

/*
 * Macros for dealing with label rectangles.
 */

#define	LABELTOUCHPOINT(p, r) \
			((p)->p_x >= (r)->r_xbot && (p)->p_x <= (r)->r_xtop \
		      && (p)->p_y >= (r)->r_ybot && (p)->p_y <= (r)->r_ytop)

/* ------------------- Cell definitions and uses ---------------------- */

/*
 * There are two structures used for cells:
 *
 *	CellDef -- one for the definition of the cell
 *	CellUse -- one for each instantiation of the cell.
 *
 * The CellDef is shared by all of the CellUses of that cell.
 */

typedef struct celldef
{
    unsigned int	 cd_flags;	/* See definitions below */
    Rect		 cd_bbox;	/* Bounding box for cell */
    Rect		 cd_extended;	/* Bounding box, including labels */
    char		*cd_file;	/* File containing cell definition */
#ifdef FILE_LOCKS
    int			cd_fd;		/* File descriptor for obtaining and
					 * holding advisory locks.
					 */
#endif
    char		*cd_name;	/* Name of cell */
    struct celluse	*cd_parents;	/* NULL-terminated list of all uses */
    BPlane		*cd_cellPlane;	/* Instance locations */
    Plane		*cd_planes[MAXPLANES];	/* Tiles */
    ClientData		 cd_client;	/* This space for rent */
    int			 cd_timestamp;	/* Unique integer identifying last
					 * time that paint, labels, or subcell
					 * placements changed in this def.
					 */
    Label		*cd_labels;	/* Label list for this cell */
    Label		*cd_lastLabel; 	/* Last label in list for this cell. */
    char		*cd_technology;	/* Name of technology for this cell 
					 * (Not yet used.)
					 */
    ClientData		 cd_props;	/* Private data used to maintain
					 * lists of properties.  Properties
					 * are name-value pairs and provide
					 * a flexible way of extending the
					 * data that is stored in a CellDef.
					 */
    ClientData		 cd_filler;	/* UNUSED */
    HashTable		 cd_idHash;	/* Maps cell use ids to cell uses.
					 * Indexed by cell use id; value
					 * is a pointer to the CellUse.
					 */
    TileTypeBitMask	 cd_types;	/* Types of tiles in the cell */
} CellDef;

/*
 * Cell definition flags:
 *	CDAVAILABLE means cell has been loaded from disk into main store.
 *	CDMODIFIED means cell has been changed since last write to disk.
 *	    This bit applies only to the real contents of the cell (paint,
 *	    labels, and subcell placements), and not to hint information
 *	    like child bounding box guesses and child timestamps.
 *	CDNOTFOUND means we failed to find the cell on disk once, so
 *	    don't give any more error messages about it.
 *	CDINTERNAL means that this cell is used internally by Magic (e.g.
 *	    for DRC checking or channel decomposition or selection) and
 *	    has nothing to do with the user's layout.  Many things don't
 *	    apply to internal cells (such as design-rule checking).
 *	CDGETNEWSTAMP means the cell has been modified since the
 *	    last time a timestamp was assigned to it, so it needs
 *	    to have a new stamp assigned.
 *	CDSTAMPSCHANGED means that a timestamp has changed in one or
 *	    more children of this cell.
 *	CDBOXESCHANGED means that bounding boxes of one or more children
 *	    have changed.
 *	CDFIXEDBBOX means that this cell has been declared to be a
 *	    pre-extracted subcircuit, so the bounding box should not
 *	    be altered.
 *	CDNOEDIT means that the cell cannot be edited because its file
 *	    is read-only or (if FILE_LOCKS enabled) locked by another user.
 *	CDPROCESSED means that the cell bounding box has been calculated
 *	    and should not be calculated again.
 *	CDFLATGDS is set when the "calma flatten" option is chosen and
 *	    a cell is small and does not call any instances itself.
 *	    The flag is used to identify the cell and remove it after GDS
 *	    input processing.
 *	CDFLATTENED is set when a cell marked CDFLATGDS is used.  Cells
 *	    that are never used are not removed after processing.
 *	CDPROCESSEDGDS is set when the cell read from the GDS stream file
 *	    is added to the magic database.  The flag is used to identify
 *	    whether the cell has been processed when forcing the GDS
 *	    stream data to be read in post-order.
 *	CDPRELOADED is similar to CDPROCESSEDGDS but is used in cases
 *	    other than forced post-order reading, such as flattening
 *	    or flatten-by-name.
 *	CDVENDORGDS indicates that the cell was read from a GDS stream
 *	    with the option "gds readonly true".
 *	CDVISITED indicates that at least one instance of the cell was
 *	    already output during a file write.
 *	CDDEREFERENCE is a flag indicating that when loading or expanding
 *	    children of a cell, the path should be ignored and the cell
 *	    path should be searched for the location.
 *	CDFIXEDSTAMP is a flag indicating that the cell has a fixed
 *	    timestamp that should not be modified.  This should be used
 *	    with caution as it messes with the usual timestamp tracking,
 *	    but is useful for preparing libraries all cells of which have
 *	    the same timestamp value.
 *	CDNOEXTRACT is used by incremental extraction to flag cells that
 *	    are up-to-date and do not need to be re-extracted.
 *	CDDONTUSE is used during extraction to flag cells that have no
 *	    contents and should be ignored.
 */

#define	CDAVAILABLE	 0x00001
#define	CDMODIFIED	 0x00002
#define	CDNOTFOUND	 0x00004
#define CDINTERNAL	 0x00008
#define CDGETNEWSTAMP	 0x00010
#define CDSTAMPSCHANGED	 0x00020
#define CDBOXESCHANGED	 0x00040
#define CDFIXEDBBOX	 0x00080
#define CDNOEDIT	 0x00100
#define CDPROCESSED	 0x00200
#define CDFLATGDS	 0x00400
#define CDFLATTENED	 0x00800
#define CDPROCESSEDGDS	 0x01000
#define CDPRELOADED	 0x02000
#define CDVENDORGDS	 0x04000
#define CDVISITED	 0x08000
#define CDDEREFERENCE	 0x10000
#define CDFIXEDSTAMP	 0x20000
#define CDNOEXTRACT	 0x40000
#define CDDONTUSE	 0x80000

#include "database/arrayinfo.h" /* ArrayInfo */

/*
 * Since a cell may be used in an orientation different from that
 * in which it was defined, each cell use contains a transform
 * that will generate coordinates in the world of the parent from
 * the coordinates in the world of the child.  Cells may also be
 * arrayed.  Note:  arraying occurs before the transformation, then
 * the entire array is transformed.
 */

typedef struct celluse
{
    /* Binning plane element struct header---must go first! */
    void		*cu_bpLinks[BP_NUM_LINKS];	/* link fields */
    Rect		 cu_bbox;	/* Bounding box of this use, with
					 * arraying taken into account, in
					 * coordinates of the parent def.
					 */
    /* End of BPlane header */

    Rect		 cu_extended;	/* Bounding box of this use, including
					 * the area of rendered text labels.
					 */
    unsigned int	 cu_expandMask;	/* Mask of windows in which this use
					 * is expanded.
					 */
    unsigned char	 cu_flags;	/* See definitions below */
    Transform		 cu_transform;	/* Transform to parent coordinates */
    char		*cu_id;		/* Unique identifier of this use */
    ArrayInfo		 cu_array;	/* Arraying information */
    CellDef		*cu_def;	/* The definition of the cell */
    struct celluse	*cu_nextuse;	/* Next in list of uses of our def,
					 * or NULL for end of list.
					 */
    CellDef		*cu_parent;	/* Cell def containing this use */
    ClientData		 cu_client;	/* This space for rent */
} CellUse;

/* CellUse flags */
/* CU_LOCKED	means that the cell use is locked, and cannot be
 *		moved, copied, edited, rotated, etc.
 */
#define CU_LOCKED	0x01
/* CU_SELECT_*	are used only with the select cell def.  They indicate
 *		that the selection has been made via a "select chunk"
 *		or "select net" command, and should be treated accordingly.
 */  
#define CU_SELECT_NET	0x02
#define CU_SELECT_CHUNK	0x04
/* CU_SUB_EXTRACTED is a temporary flag indicating that the substrate
 *		    of the use has been extracted and the extraction
 *		    does not need to be repeated for this use.
 */
#define CU_SUB_EXTRACTED 0x08

/* Character prefix used to denote a locked cell use in a .mag file */
#define CULOCKCHAR	'*'

#define	cu_xlo	cu_array.ar_xlo
#define	cu_ylo	cu_array.ar_ylo
#define	cu_xhi	cu_array.ar_xhi
#define	cu_yhi	cu_array.ar_yhi
#define	cu_xsep	cu_array.ar_xsep
#define	cu_ysep	cu_array.ar_ysep

/*
 * xMask special values.  Note that the usual form of xMask specifies
 * a single-bit value (1, 2, 4, etc.) representing one window from
 * which a command originated.  Any number that is not a power of 2
 * may be used to define a special criterion for determining whether
 * or not to descend into a cell during a tree search, in routine
 * DBDescendSubcell().
 */

#define CU_DESCEND_ALL		0	/* Descend all subcells */
#define CU_DESCEND_SPECIAL	0x0003	/* Descend marked subcells only */
#define CU_DESCEND_NO_SUBCKT	0x0005	/* Descend no subcircuits */
#define CU_DESCEND_NO_VENDOR	0x0006	/* Descend no vendor-GDS subcells */
#define CU_DESCEND_NO_LOCK	0x0007	/* Descend unlocked subcells only */
#define CU_DESCEND_NONE		0x0009	/* Descend no subcells */
#define CU_DESCEND_PROP_FLAT	0x000a	/* Descend by property string "flatten" */

/*
 * Declare tile type structure for non-manhattan geometry
 */

typedef struct diagonaltilebody
{
    TileType  type_l;
    TileType  type_r;
    unsigned char split_dir;    /* (0 = /, 1 = \) */
} DiagonalTileBody;

/*
 * Structure containing painting information to be passed to the paint  
 * procedure when a diagonal tile is encountered.
 */

typedef struct diag_info
{
   const PaintResultType *resultTbl;
   bool dir;
   bool side;
} DiagInfo;

/* Where search functions need to return a Tile pointer and tile split	*/
/* information, use this structure.  Contains a pointer to its own	*/
/* structure type so that it may also be used to create a linked list	*/
/* of tiles including split side information.				*/

typedef struct tile_and_dinfo
{
    struct tile_and_dinfo *tad_next;
    Tile     *tad_tile;
    TileType  tad_dinfo;
} TileAndDinfo;

/* This would normally go in geometry.h except that it uses TileType.	*/
/* Used in selOps.c but also passed back to CmdRS.c for select command.	*/

typedef struct extRectList
{
   TileType r_type;
   Rect r_r;
   struct extRectList *r_next;
} ExtRectList;

/* Structure similar to the above, but adding a pointer to a cell use ID
 * and a client data record which can be used to hold a region pointer.
 */

typedef struct extConnList
{
   char *r_useid;		/* Cell Use being connected to */
   TileType r_type;		/* Connecting tile type in the parent */
   Rect r_r;			/* Area of connection */
   ClientData r_upnode;		/* Parent node making the connection */
   ClientData r_downnode;	/* Child node making the connection */
   struct extConnList *r_next;	/* Next item in the linked list */
} ExtConnList;

/* -------------------- Search context information -------------------- */

/* Search contexts are used in hierarchical searches */
typedef struct
{
    CellUse	*scx_use;	/* Pointer to cell use currently searched */
    int		 scx_x, scx_y;	/* X and Y array elementS if scx_use is array */
    Rect	 scx_area;	/* Area searched in scx_use->cu_def coords */
    Transform	 scx_trans;	/* Composite transform from coordinates
				 * of the cell use (scx_use) all the way
				 * back to those of the "root" of the
				 * search.
				 */
} SearchContext;

/* ------------------- Pathname of a terminal (label) ----------------- */

/* The following structure is used to build hierarchical label names */
typedef struct
{
    char	*tp_first;	/* Pointer to first character in pathname */
    char	*tp_next;	/* Pointer to next character to be filled in */
    char	*tp_last;	/* Pointer to last available character slot
				 * in pathname.
				 */
} TerminalPath;

/* --------------- Contexts for hierarchical tile searches ------------ */

/*
 * The TreeContext is the glue which holds together the SearchContext
 * of a given search (which varies depending on where in the search we
 * happen to be) and the TreeFilter (see below) which does not.
 */
typedef struct treeContext
{
    SearchContext *tc_scx;		/* Search context (varies) */
    int tc_plane;			/* Current plane of search */
    struct treeFilter *tc_filter;	/* Constant search criteria */
} TreeContext;

/*
 * The TreeFilter is that portion of the argument to the
 * filter procedures associated with tree searches that does
 * not change during the entire search, but serves mainly to
 * pass the search criteria down to the filter functions.
 */
typedef struct treeFilter
{
    int (*tf_func)();		/* Client's filter function */
    ClientData tf_arg;		/* Client's argument to pass to filter */
    const TileTypeBitMask *tf_mask;	/* Only process tiles with these types */
    int tf_xmask;		/* Expand mask */
    PlaneMask tf_planes;	/* Mask of planes which will be visited */
    TileType tf_dinfo;		/* Info for processing triangular areas */
    unsigned char tf_flags;	/* Flags to apply to search (see below)	*/
    TerminalPath *tf_tpath;	/* Buffer to hold hierarchical label names */
} TreeFilter;

/* Definition of tf_flags values */

#define TF_LABEL_DISPLAY	0x01	/* Search for labels using the area
					 * of the label itself
					 */
#define TF_LABEL_ATTACH		0x02	/* Search for labels using the area
					 * of paint to which the label is
					 * attached
					 */
#define TF_LABEL_ATTACH_NOT_NE	0x04	/* Same as above, ignore tile NE corner */
#define TF_LABEL_ATTACH_NOT_NW	0x08	/* Same as above, ignore tile NW corner */
#define TF_LABEL_ATTACH_NOT_SE	0x10	/* Same as above, ignore tile SE corner */
#define TF_LABEL_ATTACH_NOT_SW	0x20	/* Same as above, ignore tile SW corner */
#define TF_LABEL_ATTACH_CORNER	0x3C	/* Mask of the four types above */
#define TF_LABEL_REVERSE_SEARCH 0x40	/* Search children before parent */

/* To do:  Make the tpath entries dynamically allocated */
#define FLATTERMSIZE 4096		/* Used for generating flattened labels */

/* ------------ Information used in connectivity searches --------------*/

/* The following structure is used to hold several pieces of information
 * that must be passed through multiple levels of search function.  This
 * structure is used by DBSrConnect, DBTreeCopyConnect, SimTreeCopyConnect,
 * and DBTreeCopyConnectDCS.
 */

struct conSrArg
{
    CellDef *csa_def;                   /* Definition being searched. */
    int csa_pNum;			/* Index of plane being searched */
    const TileTypeBitMask *csa_connect; /* Table indicating what connects
                                         * to what.
                                         */
    int (*csa_clientFunc)();            /* Client function to call. */
    ClientData csa_clientData;          /* Argument for clientFunc. */
    ClientData csa_clientDefault;       /* Value to reset tiles' ClientData to. */
    bool csa_clear;                     /* FALSE means pass 1, TRUE
                                         * means pass 2.
                                         */
    Rect csa_bounds;                    /* Area that limits search. */
};

typedef struct
{
    Rect                area;           /* Area to process */
    const TileTypeBitMask *connectMask; /* Connection mask for search */
    TileType            dinfo;          /* Info about triangular search areas */
} conSrArea;

struct conSrArg2
{
    CellUse             *csa2_use;      /* Destination use */
    const TileTypeBitMask *csa2_connect;/* Table indicating what connects
                                         * to what.
                                         */
    SearchContext       *csa2_topscx;   /* Original top-level search context */
    int                  csa2_xMask;    /* Cell window mask for search */
    const Rect          *csa2_bounds;   /* Area that limits the search */

    Stack               *csa2_stack;    /* Stack of full csa2_list entries */
    conSrArea           *csa2_list;     /* List of areas to process */
    int                 csa2_top;       /* Index of next area to process */
    int                 csa2_lasttop;   /* Previous top index */
};

#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 {
        Plane *prop_plane;	/* For PROPERTY_TYPE_PLANE */
        FLEX_UNION_MEMBER(int prop_integer[], 0);	/* For PROPERTY_TYPE_INTEGER or _DIMENSION */
        FLEX_UNION_MEMBER(dlong prop_double[], 1);	/* For PROPERTY_TYPE_DOUBLE */
        FLEX_UNION_MEMBER(char  prop_string[], 2);	/* For PROPERTY_TYPE_STRING, must be last in
                                * struct and union */
    } prop_value;
} PropertyRecord;

#define intPropertyRecordSize(n) ( \
    sizeof(PropertyRecord) + n * sizeof(int) \
    - sizeof(((PropertyRecord *) 0)->prop_value))
#define dlongPropertyRecordSize(n) ( \
    sizeof(PropertyRecord) + n * sizeof(dlong) \
    - sizeof(((PropertyRecord *) 0)->prop_value))
#define strPropertyRecordSize(n) ( \
    sizeof(PropertyRecord) + n + 1 - \
    sizeof(((PropertyRecord *) 0)->prop_value))

/* -------------- Undo information passed to DBPaintPlane ------------- */

typedef struct
{
    CellDef *pu_def;	/* Cell definition being modified */
    int pu_pNum;	/* Index of plane within cell def */
} PaintUndoInfo;

/* ---------------------- Codes for paint/erase ----------------------- */

    /* The following are obsolete and will go away */
#define	ERASE	0	/* Erase type from existing tiles */
#define	PAINT	1	/* Paint type over existing tiles */
#define	WRITE	2	/* Write type unconditionally */

/* ---------------------- Codes for cell printing ---------------------- */

#define SELF	  0
#define PARENTS   1
#define CHILDREN  2
#define CHILDINST 3
#define ALLCELLS  4
#define TOPCELLS  5
#define MODIFIED  6
#define OTHER	  7

/* -------------------- More codes for painting ------------------------*/

#define PAINT_NORMAL	0	/* Normal paint procedure */
#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) */
#define PROPERTY_TYPE_PLANE	4	/* A tile plane structure */

/* -------------------- Exported procedure headers -------------------- */

    /* Painting/erasing */
extern void DBPaint();
extern void DBErase();
extern int  DBSrPaintArea();
extern int  DBPaintPlane0();
extern int  DBPaintPlaneActive();
extern int  DBPaintPlaneWrapper();
extern int  DBPaintPlaneMark();
extern int  DBPaintPlaneXor();
extern int  DBPaintPlaneByProc();
extern int  DBPaintPlaneMergeOnce();
extern void DBPaintMask();
extern void DBEraseMask();
extern void DBClearPaintPlane();
extern void DBLockContact();
extern void DBUnlockContact();

#define DBPaintPlane(a, b, c, d)  DBPaintPlane0(a, b, c, d, PAINT_NORMAL)
#define DBMergeNMTiles(a, b, c)      DBMergeNMTiles0(a, b, c, FALSE)

extern int DBNMPaintPlane0();
#define DBNMPaintPlane(a, b, c, d, e)  DBNMPaintPlane0(a, b, c, d, e, PAINT_NORMAL)

    /* I/O */
extern bool DBCellRead();
extern bool DBTestOpen();
extern char *DBGetTech();
extern bool DBCellWrite();
extern CellDef *DBCellReadArea();
extern void DBFileRecovery();
extern bool DBWriteBackup();
extern bool DBReadBackup();
extern void DBRemoveBackup();
extern void DBPathSubstitute();

    /* Labels */
extern Label *DBPutLabel();
extern Label *DBPutFontLabel();
extern void DBFontLabelSetBBox();
extern bool DBEraseGlobLabel();
extern bool DBEraseLabel();
extern void DBEraseLabelAll();
extern void DBEraseLabelsByContent();
extern void DBRemoveLabel();
extern void DBReOrientLabel();
extern void DBAdjustLabels();

    /* Technology initialization */
extern void DBTechInit();
extern bool DBTechSetTech();
extern void DBTechInitVersion();
extern bool DBTechSetVersion();
extern bool DBTechAddPlane(const char *sectionName, int argc, char *argv[]);
extern bool DBTechAddType();
extern bool DBTechAddAlias();
extern void DBTechFinalType();
extern bool DBTechAddConnect();
extern bool DBTechAddContact();
extern bool DBTechAddCompose();
extern TileType DBTechNameType(), DBTechNoisyNameType();
extern int DBTechNamePlane(), DBTechNoisyNamePlane();
extern PlaneMask DBTechNameMask(), DBTechNoisyNameMask();
extern PlaneMask DBTechTypesToPlanes();
extern bool DBTechTypesOnPlane();
extern void DBTechInitPlane(void);
extern void DBTypeInit();
extern void DBTechInitType();
extern void DBTechInitCompose();
extern void DBTechFinalCompose();
extern void DBTechInitContact();
extern void DBTechFinalContact();
extern void DBTechFinalConnect();
extern void DBTechInitConnect();

    /* Cell symbol table */
extern void DBCellInit();
extern void DBCellPrint();
extern void DBUsePrint();
extern void DBTopPrint();
extern CellDef *DBCellLookDef();
extern CellDef *DBCellNewDef();
extern CellDef *DBCellDefAlloc();
extern bool DBCellRenameDef();
extern bool DBCellDeleteDef();
extern void DBCellDefFree();
extern int DBCellSrDefs();
extern CellUse *DBCellNewUse();
extern bool DBCellDeleteUse();
extern CellUse *DBCellFindDup();
extern void DBLockUse();
extern void DBUnlockUse();
extern void DBOrientUse();
extern void DBAbutmentUse();

    /* Cell selection */
extern CellUse *DBSelectCell();
extern CellUse *DBFindUse();

    /* Insertion/deletion of cell uses into the cell tile plane of a parent */
extern void DBPlaceCell();
extern void DBPlaceCellNoModify();
extern void DBDeleteCell();
extern void DBDeleteCellNoModify();
extern void DBClearCellPlane();

    /* Insertion/deletion of cell uses into the name space of a parent */
extern bool DBLinkCell();
extern void DBUnLinkCell();

    /* Deletion of cell defs */
extern void DBUndoReset();

    /* Bounding boxes and arrays */
extern bool DBBoundPlane();
extern void DBComputeUseBbox();
extern void DBReComputeBbox();
extern void DBReComputeBboxVert();
extern void DBMakeArray();
extern void DBSetArray();
extern void DBSetTrans();
extern void DBArrayOverlap();
extern void DBComputeArrayArea();
extern Transform *DBGetArrayTransform();
extern char *DBPrintUseId(SearchContext *scx, char *name, int size, bool display_only);

    /* Massive copying */
extern void DBCellCopyPaint();
extern void DBCellCopyAllPaint();
extern void DBCellCheckCopyAllPaint();
extern void DBCellCopyLabels();
extern void DBCellCopyAllLabels();
extern void DBCellCopyGlobLabels();
extern void DBCellCopyCells();
extern void DBCellCopyAllCells();
extern void DBFlatCopyMaskHints();
extern Plane *DBCellGenerateSubstrate();
extern Plane *DBCellGenerateSimpleSubstrate();

    /* Contact image handling */
extern TileType DBPlaneToResidue();
extern TileType DBTechFindStacking();
extern bool DBIsContact();
extern PlaneMask DBLayerPlanes();

extern TileTypeBitMask *DBResidueMask();
extern void DBFullResidueMask();

    /* Miscellaneous */
extern void DBCellClearDef();
extern void DBCellCopyDefBody();
extern void DBExpandAll(), DBExpand();
extern bool DBIsAncestor();
extern void DBCellSetAvail();
extern void DBCellClearAvail();
extern bool DBCellGetModified();
extern void DBCellSetModified();
extern void DBFixMismatch();
extern void DBTreeCopyConnect();
extern void DBSeeTypesAll();
extern void DBUpdateStamps();
extern void DBEnumerateTypes();
extern Plane *DBNewPlane();
extern bool DBDescendSubcell();
extern void DBCellCopyMaskHints();
extern void DBFlattenInPlace();
extern void DBCellFlattenAllCells();

extern PaintResultType (*DBNewPaintTable())[TT_MAXTYPES][TT_MAXTYPES];
typedef int (*IntProc)();
IntProc DBNewPaintPlane();

    /* Diagnostic */
extern void DBTechPrintTypes();
extern void DBTechPrintCanonicalType();

    /* Deallocation */
extern void DBClearCellPlane();
extern void DBClearPaintPlane();
extern void DBFreeCellPlane();
extern void DBFreePaintPlane();

    /* Cell properties */
extern void DBPropPut();
extern PropertyRecord *DBPropGet();
extern char *DBPropGetString();
extern dlong DBPropGetDouble();
extern int DBPropEnum();
extern void DBPropClearAll();

    /* Searching */
extern int DBTreeSrTiles();
extern int DBTreeSrUniqueTiles();
extern int DBNoTreeSrTiles();
extern int DBTreeSrLabels();
extern int DBTreeSrCells();
extern int DBSrRoots();
extern int DBCellEnum();
extern int DBArraySr();
extern bool DBNearestLabel();
extern int DBSrLabelLoc();
extern TileType DBTransformDiagonal();
extern bool DBTestNMInteract(Rect *rect1, TileType tt1, Tile *t2, TileType di2, bool overlap_only);
extern int dbcUnconnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (notused) */
extern int dbSrConnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /*  (struct conSrArg *csa) */
extern int dbSrConnectStartFunc(Tile *tile, TileType dinfo, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */

/* C99 compat */
extern void DBEraseValid();
extern void DBPaintValid();
extern void DBTreeCountPaint();
extern void DBOpenOnly();
extern int  DBLoadFont();
extern int  DBNameToFont();
extern int  DBFontChar();
extern void DBFontInitCurves();
extern void DBUndoEraseLabel();
extern void DBUndoPutLabel();
extern bool DBCellRename();
extern bool DBCellDelete();
extern int  DBCellSrArea();
extern int  DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg);
extern int  DBMoveCell();
extern bool DBReLinkCell();
extern int  DBBoundCellPlane();
extern Label *DBCheckLabelsByContent();
extern void DBMaskAddStacking();
extern bool DBIsChild();
extern void DBScaleEverything();
extern bool DBScalePoint();
extern int  DBScaleCell();
extern TileType DBTechNameTypes();
extern void DBTreeFindUse();
extern void DBGenerateUniqueIds();
extern void DBSelectionUniqueIds();
extern TileType DBInvTransformDiagonal();
extern bool DBIsSubcircuit();
extern int  DBSrPaintNMArea();
extern int  DBTreeSrNMTiles();
extern void DRCOffGridError();
extern int  dbCellUsePrintFunc();
extern int  dbTechContactResidues();
extern TileType dbTechNewStackedType();
extern void dbUndoEdit();
extern void DBSplitTile();
extern int  DBSrCellUses();
extern TileType DBTechNameTypeExact();
extern void dbInstanceUnplace();
extern int  dbIsPrimary();
extern void dbTechMatchResidues();
extern void DBUndoInit();
extern void DBResetTilePlane();
extern void DBResetTilePlaneSpecial();
extern void DBNewYank();
extern int  DBSrPaintClient();
extern int  DBSrConnect();
extern char *dbFgets();
extern void DBAdjustLabelsNew();
extern bool DBScaleValue();
extern int  DBMergeNMTiles0();
extern int  DBSearchLabel();
extern int  dbCellUniqueTileSrFunc();
extern void DBWDrawFontLabel();
extern void DBCellCopyManhattanPaint();
extern bool dbScalePlane();
extern int  DBPaintPlaneVert();

/* -------------------------- Layer locking ------------------------------*/

extern TileTypeBitMask DBActiveLayerBits; /* Layers that are locked */
extern TileTypeBitMask DBTechActiveLayerBits; /* Layers that are marked as
					       * locked in the techfile
					       */

#define LOCKLAYERCHAR '-'   /* Layer names beginning with this are locked */
#define LockedLayer(tiletype)  (!TTMaskHasType(&DBActiveLayerBits, tiletype)) 

/* ---------- Internal units to Lambda conversion factor ---------------- */

extern int DBLambda[2];

/* -------------------- Exported magic file suffix -------------------- */

extern char *DBSuffix;		/* Suffix appended to all Magic cell names */
extern bool DBPropCompat;	/* Backwards-compatible properties */

/* -------------------- User Interface Stuff -------------------------- */

extern unsigned char DBVerbose;	/* If 0, don't print any messages	*/
				/* If 1, print only error messages	*/
				/* If 2, print errors and warnings	*/
				/* If > 2, print all messages		*/
#define DB_VERBOSE_NONE	0
#define DB_VERBOSE_ERR	1
#define DB_VERBOSE_WARN	2
#define DB_VERBOSE_ALL	3

/* ---------- Definitions for expanding/unexpanding cells --------------*/

/* Selection expansion flags */
#define DB_EXPAND_MASK	 	3	/* 1 = expand, 0 = unexpand, 2 = toggle */
#define DB_EXPAND_SURROUND_MASK	4	/* 1 = surround, 0 = touch */

/* Selection expansion values */
#define DB_EXPAND      	   0
#define DB_UNEXPAND        1
#define DB_EXPAND_TOGGLE   2
#define DB_EXPAND_SURROUND 4
#define DB_EXPAND_OVERLAP  0

/* ------------------ Exported technology variables ------------------- */

/***
 *** The following variables should be considered
 *** read-only to all clients of the database module.
 ***/

    /* Name, version, and description of the current technology */
extern char *DBTechName;
extern char *DBTechVersion;
extern char *DBTechDescription;

    /*
     * Predefined masks of tile types.
     * The number of built-in types is just TT_TECHDEPBASE.
     */
extern TileTypeBitMask DBZeroTypeBits;		/* All zeroes */
extern TileTypeBitMask DBAllTypeBits;		/* All ones */
extern TileTypeBitMask DBBuiltinLayerBits;	/* All built-in types */
extern TileTypeBitMask DBAllButSpaceBits;	/* All but space */
extern TileTypeBitMask DBAllButSpaceAndDRCBits;	/* All but space and drc */
extern TileTypeBitMask DBSpaceBits;		/* Space only */

    /*
     * Number of tile types, including those specied by the technology
     * file and those built-in to Magic, but not including those automatically
     * generated to represent contact images.  Also, a mask of those
     * types contained in the technology file.
     */
extern int DBNumUserLayers;
extern TileTypeBitMask DBUserLayerBits;		/* Including space */

    /* Total number of Magic tile types in this technology */
extern int DBNumTypes;

    /* Total number of tile planes */
extern int DBNumPlanes;

/* Abbreviations */
#define	NT	TT_MAXTYPES
#define	NP	PL_MAXTYPES

    /* Alias names for groups of types defined in the tech file */
extern HashTable	DBTypeAliasTable;

    /* Gives the official long name of each plane: */
extern const char	*DBPlaneLongNameTbl[NP];

    /* Gives a short name for each plane: */
extern const char	*DBPlaneShortName();

    /* Gives for each plane a mask of all tile types stored in that plane: */
extern TileTypeBitMask	DBPlaneTypes[NP];

    /* Similar to DBPlaneTypes[], but no type appears on more than one plane.
     * Effectively, the reverse lookup of DBPlane(type) (DBTypePlaneTbl[type]).
     */
extern TileTypeBitMask  DBHomePlaneTypes[NP];

    /* Gives a TileTypeBitMask for everything that connects to a type.
     * Bit x is set in mask DBConnectTbl[y] if any image of x connects
     * to any image of y.
     */
extern TileTypeBitMask	DBConnectTbl[NT];

    /* Complement of above: everything not connected to a type */
extern TileTypeBitMask	DBNotConnectTbl[NT];

    /*
     * Gives a TileTypeBitMask of all types that correspond to a given
     * layer.  Used for contacts that have images in more than one
     * plane.
     */
extern TileTypeBitMask	DBLayerTypeMaskTbl[NT];

    /*
     * Gives a plane mask of all planes that have tiles that connect to
     * tiles of a given type.  This is only used for contacts; it tells
     * which other planes contain images of the contact.  A tile's own
     * plane is never included in its plane mask.  Non-contact types
     * always have 0 DBConnPlanes entries.
     */
extern PlaneMask DBConnPlanes[NT];

    /*
     * Similar to DBConnPlanes[], but this time it is non-zero
     * for those planes to which each type connects, exclusive
     * of its home plane and those planes to which it connects as a
     * contact.  These planes needn't be adjacent.  For example, a
     * p-well is connected to p-substrate diffusion that overlaps it;
     * also, p well contacts connect to a p-well.  This information
     * is currently used only in the circuit extractor.
     */
extern PlaneMask DBAllConnPlanes[NT];

    /*
     * Each TileType has a home plane.  The TileType only appears on
     * its home plane.  The only exception is TT_SPACE, which can appear
     * on any plane.  (For debugging, there may be other cases).
     *
     * DBTypePlaneTbl gives the home plane for a given TileType,
     * and DBTypePlaneMaskTbl gives a mask of the planes on which
     * it appears (all planes for TT_SPACE, one plane for others).
     */
extern int		DBTypePlaneTbl[TT_MAXTYPES];
extern PlaneMask	DBTypePlaneMaskTbl[TT_MAXTYPES];

    /* Gives the long name for each tile type: */
extern const char	*DBTypeLongNameTbl[TT_MAXTYPES];

    /* Gives a short name for a tile type: */
extern const char	*DBTypeShortName(TileType type);

    /*
     * The following give masks of all planes that may be affected
     * when material of a given type is painted/erased:
     */
extern PlaneMask	DBTypePaintPlanesTbl[TT_MAXTYPES];
extern PlaneMask	DBTypeErasePlanesTbl[TT_MAXTYPES];

    /*
     * Gives the resulting tile type when one tile type is painted over
     * another in a given plane:
     *
     *	newType = DBPaintResult[pNum][paintType][oldType]
     */
extern PaintResultType	DBPaintResultTbl[NP][NT][NT];

    /*
     * Gives the resulting tile type when one tile type is erased over
     * another in a given plane:
     *
     *	newType = DBEraseResult[pNum][paintType][oldType]
     */
extern PaintResultType	DBEraseResultTbl[NP][NT][NT];

    /*
     * A simple table using TT_CHECKPAINT, which does not exist on
     * paintable planes, to force a paint result that is always a
     * tiletype that does not exist on the plane.  Used for generating
     * non-Manhattan geometry.
     */
extern PaintResultType	DBSpecialResultTbl[NT];

    /*
     * Gives the resulting tile type when one tile type is 'written'
     * over a given plane.  This corresponds to the case where the
     * written type replaces the old tile without regard to the type
     * of the old tile.
     *
     *	paintType = DBWriteResultTbl[paintType][oldType]
     */
extern PaintResultType	DBWriteResultTbl[NT][NT];

/* --------------------- Exported macros ------------------------------ */

    /*
     * Macros for reading the paint/erase tables:
     *	resultType = DBStdPaintEntry(oldType, paintType, planeNum)
     *	resultType = DBStdEraseEntry(oldType, paintType, planeNum)
     */
#define	DBStdPaintEntry(h,t,p) 	(DBPaintResultTbl[p][t][h])
#define	DBStdEraseEntry(h,t,p)	(DBEraseResultTbl[p][t][h])

    /*
     * Macros for constructing the pointer to pass to DBPaintPlane
     * as the result table.
     */
#define	DBStdPaintTbl(t,p)	(&DBPaintResultTbl[p][t][0])
#define	DBStdEraseTbl(t,p)	(&DBEraseResultTbl[p][t][0])
#define DBStdWriteTbl(t)	(&DBWriteResultTbl[t][0])
#define DBSpecialPaintTbl	(&DBSpecialResultTbl[0])

    /*
     * int DBPlane(type) TileType type;
     * Returns the home plane of 'type'.
     */
#define	DBPlane(type)		(DBTypePlaneTbl[type])

    /*
     * char *DBTypeLongName(type) TileType type;
     * Returns the long name of 'type'.
     */
#define	DBTypeLongName(type)	(DBTypeLongNameTbl[type])

    /*
     * char *DBPlaneLongName(p) int p;
     * Returns the long name of plane 'plane'.
     */
#define	DBPlaneLongName(p)	(DBPlaneLongNameTbl[p])

    /*
     * bool DBConnectsTo(t1, t2) TileType t1, t2;
     * Returns TRUE if types 't1' and 't2' are electrically connected.
     */
#define	DBConnectsTo(t1, t2)	(TTMaskHasType(&DBConnectTbl[t1], t2))

    /*
     * bool DBTypesOnSamePlane(t1, t2) TileType t1, t2;
     * Returns TRUE if types 't1' and 't2' exist on the same plane.
     */
#define DBTypesOnSamePlane(t1, t2) \
			(DBTypePlaneMaskTbl[t1] & DBTypePlaneMaskTbl[t2])

    /*
     * bool DBPaintOnPlane(t, p) TileType t; int p;
     * bool DBEraseOnPlane(t, p) TileType t; int p;
     *
     * Return TRUE if tile type 't' has any effect on plane 'p'
     * when being painted/erased.
     */
#define	DBPaintOnPlane(t, p)	(PlaneMaskHasPlane(DBTypePaintPlanesTbl[t], p))
#define	DBEraseOnPlane(t, p)	(PlaneMaskHasPlane(DBTypeErasePlanesTbl[t], p))

    /*
     * bool DBPaintOnTypePlanes(t1, t2) TileType t1, t2;
     * bool DBEraseOnTypePlanes(t1, t2) TileType t1, t2;
     *
     * Return TRUE if tile type 't1' has any effect on planes defined
     * for type 't2' when being painted/erased.
     */
#define	DBPaintOnTypePlanes(t1, t2) \
			(DBTypePaintPlanesTbl[t1] & DBTypePlaneMaskTbl[t2])
#define	DBEraseOnTypePlanes(t1, t2) \
			(DBTypePaintPlanesTbl[t1] & DBTypePlaneMaskTbl[t2])

    /*
     * bool DBTypeOnPlane(t, p) TileType t; int p;
     * Returns TRUE if tile type 't' exists on plane 'p'.
     */
#define DBTypeOnPlane(t, p)	(PlaneMaskHasPlane(DBTypePlaneMaskTbl[t], p))

/* --------- Tile types and masks (auto-generated by makedbh) ------------ */

