#ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResUtils.c,v 1.3 2010/06/24 12:37:56 tim Exp $"; #endif /* not lint */ #include #include #include #include #include "utils/magic.h" #include "utils/geometry.h" #include "utils/geofast.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/malloc.h" #include "textio/textio.h" #include "extract/extract.h" #include "extract/extractInt.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/stack.h" #include "utils/tech.h" #include "textio/txcommands.h" #include "resis/resis.h" /* * --------------------------------------------------------------------------- * * ResFirst -- Checks to see if tile is a contact. If it is, allocate a * contact structure. * * * Results: Always returns NULL (in the form of a Region pointer) * * Side effects: * Memory is allocated by ResFirst. * We cons the newly allocated region onto the front of the existing * region list. * * * ------------------------------------------------------------------------- */ ExtRegion * ResFirst(tile, dinfo, arg) Tile *tile; TileType dinfo; FindRegion *arg; { ResContactPoint *reg; TileType t; int i; if (IsSplit(tile)) { t = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); } else t = TiGetType(tile); if (DBIsContact(t)) { reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint))); reg->cp_center.p_x = (LEFT(tile) + RIGHT(tile)) >> 1; reg->cp_center.p_y = (TOP(tile) + BOTTOM(tile)) >> 1; reg->cp_status = FALSE; reg->cp_type = t; reg->cp_width = RIGHT(tile) - LEFT(tile); reg->cp_height = TOP(tile) - BOTTOM(tile); for (i = 0; i < LAYERS_PER_CONTACT; i++) { reg->cp_tile[i] = (Tile *) NULL; reg->cp_cnode[i] = (resNode *) NULL; } reg->cp_currentcontact = 0; reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x; reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y; reg->cp_rect.r_ur.p_x = RIGHT(tile); reg->cp_rect.r_ur.p_y = TOP(tile); reg->cp_contactTile = tile; /* Prepend it to the region list */ reg->cp_nextcontact = (ResContactPoint *) arg->fra_region; arg->fra_region = (ExtRegion *) reg; } return((ExtRegion *) NULL); } /* *-------------------------------------------------------------------------- * * resMultiPlaneTerm -- * * Callback function to set a resInfo field * *-------------------------------------------------------------------------- */ int resMultiPlaneTerm( Tile *tile, TileType dinfo, // Unused (but should be handled) resInfo *rinfo2) { resInfo *Info; Info = resAddField(tile); Info->ri_status |= RES_TILE_SD; rinfo2->sourceEdge |= OTHERPLANE; return 0; } /* *-------------------------------------------------------------------------- * * resSubstrateTerm -- * * Callback function to set a resInfo field * *-------------------------------------------------------------------------- */ int resSubstrateTerm( Tile *tile, TileType dinfo, ClientData clientdata) /* (unused) */ { resInfo *Info; Info = resAddField(tile); Info->ri_status |= RES_TILE_SUBS; return 0; } /* *-------------------------------------------------------------------------- * * ResEach-- * * ResEach calls ResFirst unless this is the first contact, in which case it * has alreay been processed * * results: returns 0 * * Side Effects: see ResFirst * * ------------------------------------------------------------------------- */ int ResEach(tile, dinfo, pNum, arg) Tile *tile; TileType dinfo; int pNum; FindRegion *arg; { if (((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile) { ResFirst(tile, dinfo, arg); } return(0); } /* *------------------------------------------------------------------------- * * ResAddTerminalPlumbing -- * * Called from ResAddDevPlumbing(). When a tile has been found adjacent to * a device tile that is a terminal type, walk through all of the tiles * belonging to the terminal and mark them all with resInfo structures * and set a status of RES_TILE_SD. * * Results: None. * * Side effects: See above. * *------------------------------------------------------------------------- */ void ResAddTerminalPlumbing( Tile *tile, ExtDevice *devptr, int sourceTerm) { static Stack *resSDStack = NULL; Tile *tp1, *tp2; TileType t1; if (resSDStack == NULL) resSDStack = StackNew(64); STACKPUSH(PTR2CD(tile), resSDStack); while (!StackEmpty(resSDStack)) { /* Find and mark all tiles belonging to the same source */ tp1 = (Tile *) STACKPOP(resSDStack); if (IsSplit(tp1)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetRightType(tp1))) t1 = SplitRightType(tp1); else t1 = SplitLeftType(tp1); } else t1 = TiGetTypeExact(tp1); /* Top */ for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { resInfo *re = resAddField(tp2); if ((re->ri_status & RES_TILE_SD) == 0) { re->ri_status |= RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Bottom */ for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetTopType(tp2))) { resInfo *re = resAddField(tp2); if ((re->ri_status & RES_TILE_SD) == 0) { re->ri_status |= RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Right */ for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetLeftType(tp2))) { resInfo *re = resAddField(tp2); if ((re->ri_status & RES_TILE_SD) == 0) { re->ri_status |= RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Left */ for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetRightType(tp2))) { resInfo *re = resAddField(tp2); if ((re->ri_status & RES_TILE_SD) == 0) { re->ri_status |= RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } } } /* *------------------------------------------------------------------------- * * ResUnmarkTerminal -- * * After adding structures to all tiles of a device, remove the RES_TILE_SD * status from all tiles. * * Results: None * * Side effects: Tile status changes * *------------------------------------------------------------------------- */ void ResUnmarkTerminal( Tile *tile, ExtDevice *devptr, int sourceTerm) { static Stack *resSDStack = NULL; resInfo *re, *re2; Tile *tp1, *tp2; TileType t1; if (resSDStack == NULL) resSDStack = StackNew(64); re = (resInfo *)TiGetClientPTR(tile); STACKPUSH(PTR2CD(tile), resSDStack); re->ri_status &= ~RES_TILE_SD; while (!StackEmpty(resSDStack)) { tp1 = (Tile *) STACKPOP(resSDStack); if (IsSplit(tp1)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetRightType(tp1))) t1 = SplitRightType(tp1); else t1 = SplitLeftType(tp1); } else t1 = TiGetTypeExact(tp1); /* Top */ for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) { re2 = (resInfo *) TiGetClientPTR(tp2); if ((re2 != (resInfo *)CLIENTDEFAULT) && (re2->ri_status & RES_TILE_SD)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { re2->ri_status &= ~RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Bottom */ for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) { re2 = (resInfo *) TiGetClientPTR(tp2); if ((re2 != (resInfo *)CLIENTDEFAULT) && (re2->ri_status & RES_TILE_SD)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetTopType(tp2))) { re2->ri_status &= ~RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Right */ for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) { re2 = (resInfo *) TiGetClientPTR(tp2); if ((re2 != (resInfo *)CLIENTDEFAULT) && (re2->ri_status & RES_TILE_SD)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetLeftType(tp2))) { re2->ri_status &= ~RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } /* Left */ for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) { re2 = (resInfo *) TiGetClientPTR(tp2); if ((re2 != (resInfo *)CLIENTDEFAULT) && (re2->ri_status & RES_TILE_SD)) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetRightType(tp2))) { re2->ri_status &= ~RES_TILE_SD; STACKPUSH(PTR2CD(tp2), resSDStack); } } } } } /* *------------------------------------------------------------------------- * * ResAddlumbing -- * * Each tile has a resInfo structure associated with it to keep track of * various things used by the extractor. ResAddDevPlumbing adds this structure * and sets the tile's ClientData field to point to it. * * Results: Always return 0 to keep the search going. * * Side Effects: See above * *------------------------------------------------------------------------- */ int ResAddPlumbing( Tile *tile, TileType dinfo, /* (unused) */ ClientData clientdata) /* (unused) */ { if (TiGetClient(tile) == CLIENTDEFAULT) resAddField(tile); return 0; } /* *------------------------------------------------------------------------- * * ResAddDevPlumbing -- * * Each tile has a resInfo structure associated with it to keep track of * various things used by the extractor. ResAddDevPlumbing adds this structure * to tiles associated with devices and sets the tile's ClientData field to * point to it. A device structure is also added; all connected device * tiles are enumerated and their deviceList fields set to the new structure. * * Results: None. * * Side Effects: See above * *------------------------------------------------------------------------- */ void ResAddDevPlumbing( ResDevTile *thisDev, /* Pointer to device from .ext file */ resDevice **resDevListPtr) /* Add to this list */ { resInfo *Info, *rinfo2; static Stack *resDevStack = NULL; Tile *tile, *tp1, *tp2, *sourceTile = NULL; TileType ttype, loctype, t1; TileTypeBitMask locDevSubsMask; int i, pNum, nterms; Plane *plane; Rect r; resDevice *resDev; ExtDevice *devptr; int srcidx, sourceTerm = -1; if (resDevStack == NULL) resDevStack = StackNew(64); ttype = thisDev->type; pNum = DBPlane(ttype); plane = ResDef->cd_planes[pNum]; devptr = thisDev->devptr; /* Add 2 to # terminals to include the device node and the substrate */ nterms = devptr->exts_deviceSDCount + 2; /* Find the tile in the location of the device on the device's plane. * Note that GOTOPOINT() is used because the actual tile will have * changed after dissolving contacts and re-forming the entire database * with ResFract(). */ tile = PlaneGetHint(plane); GOTOPOINT(tile, &(thisDev->area.r_ll)); PlaneSetHint(plane, tile); if (IsSplit(tile)) { loctype = SplitRightType(tile); if (!TTMaskHasType(&ExtCurStyle->exts_deviceConn[ttype], loctype)) loctype = SplitLeftType(tile); } else loctype = TiGetTypeExact(tile); /* Create a record for the device type and add it to tile */ resDev = (resDevice *)mallocMagic((unsigned)(sizeof(resDevice))); resDev->rd_nterms = nterms; resDev->rd_terminals = (resNode **)mallocMagic(nterms * sizeof(resNode *)); for (i = 0; i != nterms; i++) resDev->rd_terminals[i] = (resNode *) NULL; resDev->rd_tile = tile; resDev->rd_inside.r_ll.p_x = LEFT(tile); resDev->rd_inside.r_ll.p_y = BOTTOM(tile); resDev->rd_inside.r_ur.p_x = RIGHT(tile); resDev->rd_inside.r_ur.p_y = TOP(tile); resDev->rd_devtype = loctype; resDev->rd_tiles = 0; resDev->rd_length = 0; resDev->rd_width = 0; resDev->rd_perim = 0; resDev->rd_area = 0; resDev->rd_status = 0; resDev->rd_nextDev = (resDevice *)*resDevListPtr; *resDevListPtr = (ClientData)resDev; /* Add a record to the initial tile */ rinfo2 = resAddField(tile); rinfo2->deviceList = resDev; rinfo2->ri_status |= RES_TILE_DEV; /* Walk the area of the device, adding records to the tiles and * looking for terminals. When a terminal is found, walk the * area of the terminal, adding records to the tiles. Mark * terminal tiles adjacent to the device with the relative * position. */ STACKPUSH(PTR2CD(tile), resDevStack); while (!StackEmpty(resDevStack)) { resInfo *re0; tp1 = (Tile *)STACKPOP(resDevStack); if (IsSplit(tp1)) { t1 = SplitRightType(tp1); if (!TTMaskHasType(&ExtCurStyle->exts_deviceConn[ttype], t1)) t1 = SplitLeftType(tp1); } else t1 = TiGetTypeExact(tp1); re0 = (resInfo *) TiGetClientPTR(tp1); /* Top */ for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) { if (TTMaskHasType(&ExtCurStyle->exts_deviceConn[t1], TiGetBottomType(tp2)) && (TiGetClient(tp2) == CLIENTDEFAULT)) { STACKPUSH(PTR2CD(tp2), resDevStack); Info = resAddField(tp2); Info->deviceList = resDev; Info->ri_status |= RES_TILE_DEV; /* Update device position to point to the lower-leftmost tile */ if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) { resDev->rd_inside.r_ll.p_x = LEFT(tp2); resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); resDev->rd_inside.r_ur.p_x = RIGHT(tp2); resDev->rd_inside.r_ur.p_y = TOP(tp2); } } else { if (sourceTerm < 0) { for (srcidx = 0; srcidx < (nterms - 2); srcidx++) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[srcidx]), TiGetBottomType(tp2))) { sourceTile = tp2; sourceTerm = srcidx; ResAddTerminalPlumbing(tp2, devptr, srcidx); break; } } } if (sourceTerm >= 0) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { Info = resAddField(tp2); if (Info->ri_status & RES_TILE_SD) re0->sourceEdge |= TOPEDGE; } } } } /* Bottom */ for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) { if (TTMaskHasType(&ExtCurStyle->exts_deviceConn[t1], TiGetTopType(tp2)) && (TiGetClient(tp2) == CLIENTDEFAULT)) { STACKPUSH(PTR2CD(tp2), resDevStack); Info = resAddField(tp2); Info->deviceList = resDev; Info->ri_status |= RES_TILE_DEV; /* Update device position to point to the lower-leftmost tile */ if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) { resDev->rd_inside.r_ll.p_x = LEFT(tp2); resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); resDev->rd_inside.r_ur.p_x = RIGHT(tp2); resDev->rd_inside.r_ur.p_y = TOP(tp2); } } else { if (sourceTerm < 0) { for (srcidx = 0; srcidx < (nterms - 2); srcidx++) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[srcidx]), TiGetBottomType(tp2))) { sourceTile = tp2; sourceTerm = srcidx; ResAddTerminalPlumbing(tp2, devptr, srcidx); break; } } } if (sourceTerm >= 0) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { Info = resAddField(tp2); if (Info->ri_status & RES_TILE_SD) re0->sourceEdge |= BOTTOMEDGE; } } } } /* Right */ for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) { if (TTMaskHasType(&ExtCurStyle->exts_deviceConn[t1], TiGetLeftType(tp2)) && (TiGetClient(tp2) == CLIENTDEFAULT)) { STACKPUSH(PTR2CD(tp2), resDevStack); Info = resAddField(tp2); Info->deviceList = resDev; Info->ri_status |= RES_TILE_DEV; /* Update device position to point to the lower-leftmost tile */ if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) { resDev->rd_inside.r_ll.p_x = LEFT(tp2); resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); resDev->rd_inside.r_ur.p_x = RIGHT(tp2); resDev->rd_inside.r_ur.p_y = TOP(tp2); } } else { if (sourceTerm < 0) { for (srcidx = 0; srcidx < (nterms - 2); srcidx++) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[srcidx]), TiGetBottomType(tp2))) { sourceTile = tp2; sourceTerm = srcidx; ResAddTerminalPlumbing(tp2, devptr, srcidx); break; } } } if (sourceTerm >= 0) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { Info = resAddField(tp2); if (Info->ri_status & RES_TILE_SD) re0->sourceEdge |= RIGHTEDGE; } } } } /* Left */ for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) { if (TTMaskHasType(&ExtCurStyle->exts_deviceConn[t1], TiGetRightType(tp2)) && (TiGetClient(tp2) == CLIENTDEFAULT)) { STACKPUSH(PTR2CD(tp2), resDevStack); Info = resAddField(tp2); Info->deviceList = resDev; Info->ri_status |= RES_TILE_DEV; /* Update device position to point to the lower-leftmost tile */ if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) { resDev->rd_inside.r_ll.p_x = LEFT(tp2); resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); resDev->rd_inside.r_ur.p_x = RIGHT(tp2); resDev->rd_inside.r_ur.p_y = TOP(tp2); } } else { if (sourceTerm < 0) { for (srcidx = 0; srcidx < (nterms - 2); srcidx++) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[srcidx]), TiGetBottomType(tp2))) { sourceTile = tp2; sourceTerm = srcidx; ResAddTerminalPlumbing(tp2, devptr, srcidx); break; } } } if (sourceTerm >= 0) { if (TTMaskHasType(&(devptr->exts_deviceSDTypes[sourceTerm]), TiGetBottomType(tp2))) { Info = resAddField(tp2); if (Info->ri_status & RES_TILE_SD) re0->sourceEdge |= LEFTEDGE; } } } } } TiToRect(tile, &r); /* Check other planes for terminals */ if (sourceTile == NULL) { for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { for (srcidx = 0; srcidx < (nterms - 2); srcidx++) { if (TTMaskIntersect(&DBPlaneTypes[pNum], &(devptr->exts_deviceSDTypes[srcidx]))) DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum], &r, &(devptr->exts_deviceSDTypes[srcidx]), resMultiPlaneTerm, (ClientData)rinfo2); } } } /* Find device substrate */ TTMaskZero(&locDevSubsMask); TTMaskSetMask(&locDevSubsMask, &(devptr->exts_deviceSubstrateTypes)); TTMaskClearType(&locDevSubsMask, TT_SPACE); for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { if (TTMaskIntersect(&DBPlaneTypes[pNum], &locDevSubsMask)) DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum], &r, &locDevSubsMask, resSubstrateTerm, (ClientData)NULL); } if (sourceTile) ResUnmarkTerminal(sourceTile, devptr, srcidx); } /* *------------------------------------------------------------------------- * * ResRemovePlumbing-- Removes and deallocates all the resInfo fields. * * Results: returns 0 * * Side Effects: frees up memory; resets tile->ti_client fields to CLIENTDEFAULT * *------------------------------------------------------------------------- */ int ResRemovePlumbing(tile, dinfo, arg) Tile *tile; TileType dinfo; // Unused, but should be handled. ClientData *arg; { ClientData ticlient = TiGetClient(tile); if (ticlient != CLIENTDEFAULT) { freeMagic((char *)CD2PTR(ticlient)); TiSetClient(tile, CLIENTDEFAULT); } return(0); } /* *------------------------------------------------------------------------- * * ResPreProcessDevices-- Given a list of all the device tiles and * a list of all the devices, this procedure calculates the width and * length. The width is set equal to the sum of all edges that touch * diffusion divided by 2. The length is the remaining perimeter divided by * 2*tiles. The perimeter and area fields of device structures are also * fixed. * * Results: none * * Side Effects: sets length and width of devices. "ResDevTile" * structures are freed. * *------------------------------------------------------------------------- */ void ResPreProcessDevices(TileList, DeviceList, Def) ResDevTile *TileList; resDevice *DeviceList; CellDef *Def; { Tile *tile; ResDevTile *oldTile; resInfo *tstruct; TileType tt, residue; int pNum; while (TileList != (ResDevTile *) NULL) { tt = TileList->type; if (DBIsContact(tt)) { /* Find which residue of the contact is a device. */ TileTypeBitMask ttresidues; DBFullResidueMask(tt, &ttresidues); for (residue = TT_TECHDEPBASE; residue < DBNumUserLayers; residue++) { if (TTMaskHasType(&ttresidues, residue)) { if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, residue)) { pNum = DBPlane(residue); break; } } } } else pNum = DBPlane(tt); /* always correct for non-contact types */ tile = PlaneGetHint(Def->cd_planes[pNum]); GOTOPOINT(tile, &(TileList->area.r_ll)); PlaneSetHint(Def->cd_planes[pNum], tile); tt = TiGetType(tile); tstruct = (resInfo *) TiGetClientPTR(tile); if ((tstruct == (resInfo *)CLIENTDEFAULT) || (tstruct->deviceList == NULL) || !TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt)) { TxError("Bad Device Location at %d,%d\n", TileList->area.r_ll.p_x, TileList->area.r_ll.p_y); } else if ((tstruct->ri_status & RES_TILE_MARK) == 0) { resDevice *rd = tstruct->deviceList; tstruct->ri_status |= RES_TILE_MARK; rd->rd_perim += TileList->perim; rd->rd_length += TileList->overlap; rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot) * (TileList->area.r_ytop - TileList->area.r_ybot); rd->rd_tiles++; } oldTile = TileList; TileList = TileList->nextDev; freeMagic((char *)oldTile); } for (; DeviceList != NULL; DeviceList = DeviceList->rd_nextDev) { int width = DeviceList->rd_perim; int length = DeviceList->rd_length; if (DeviceList->rd_tiles != 0) { if (length) { DeviceList->rd_length = (float) length / ((float)((DeviceList->rd_tiles) << 1)); DeviceList->rd_width = (width-length) >> 1; } else { double perimeter = DeviceList->rd_perim; double area = DeviceList->rd_area; perimeter /= 4.0; DeviceList->rd_width = perimeter + sqrt(perimeter * perimeter-area); DeviceList->rd_length = (DeviceList->rd_perim - 2 * DeviceList->rd_width) >> 1; } } } } /* *------------------------------------------------------------------------- * * ResAddToQueue-- adds new nodes to list of nodes requiring processing. * * Side Effects: nodes are added to list (i.e they have their linked list * pointers modified.) * *------------------------------------------------------------------------- */ void ResAddToQueue(node, list) resNode *node, **list; { node->rn_more = *list; node->rn_less = NULL; if (*list) (*list)->rn_less = node; *list = node; } /* *------------------------------------------------------------------------- * * ResRemoveFromQueue-- removes node from queue. Complains if it notices * that the node isn't in the supplied list. * * Results: none * * Side Effects: modifies nodelist * *------------------------------------------------------------------------- */ void ResRemoveFromQueue(node, list) resNode *node, **list; { if (node->rn_less != NULL) { node->rn_less->rn_more = node->rn_more; } else { if (node != (*list)) { TxError("Error: Attempt to remove node from wrong list\n"); } else { *list = node->rn_more; } } if (node->rn_more != NULL) { node->rn_more->rn_less = node->rn_less; } node->rn_more = NULL; node->rn_less = NULL; } resInfo * resAddField(tile) Tile *tile; { ClientData ticlient = TiGetClient(tile); resInfo *Info = (resInfo *)CD2PTR(ticlient); if (ticlient == CLIENTDEFAULT) { Info = (resInfo *) mallocMagic((unsigned) (sizeof(resInfo))); ResInfoInit(Info); TiSetClientPTR(tile, Info); } return Info; }