magic/database/DBcell.c

200 lines
5.5 KiB
C
Raw Normal View History

/*
* DBcell.c --
*
* Place and Delete subcells
*
* *********************************************************************
* * 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/DBcell.c,v 1.2 2008/12/11 04:20:04 tim Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <stdio.h>
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "database/databaseInt.h"
#include "utils/undo.h"
#include "utils/signals.h"
int placeCellFunc();
int deleteCellFunc();
Tile * clipCellTile();
void dupTileBody();
void cellTileMerge();
bool ctbListMatch();
void freeCTBList();
struct searchArg
{
CellUse * celluse;
Rect * rect;
BPlane * bplane;
};
#define TOPLEFT 10
#define TOPLEFTRIGHT 11
#define TOPBOTTOM 12
#define TOPBOTTOMLEFT 14
#define TOPBOTTOMLEFTRIGHT 15
int dbCellDebug = 0;
void
dbInstanceUnplace(CellUse *use)
{
ASSERT(use != (CellUse *) NULL, "dbInstanceUnplace");
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
* state.
*/
BPDelete(use->cu_parent->cd_cellPlane, use);
}
/*
* ----------------------------------------------------------------------------
*
* DBCellFindDup --
*
* This procedure indicates whether a particular cell is already
* present at a particular point in a particular parent. It is
* used to avoid placing duplicate copies of a cell on top of
* each other.
*
* Results:
* The return value is NULL if there is not already a CellUse in parent
* that is identical to use (same bbox and def). If there is a duplicate
* already in parent, then the return value is a pointer to its CellUse.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
CellUse *
DBCellFindDup(use, parent)
CellUse *use; /* Use that is about to be placed in parent.
* Is it a duplicate?
*/
CellDef *parent; /* Parent definiton: does it already have
* something identical to use?
*/
{
BPEnum bpe;
CellUse *dupUse;
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
"DBCellFindDup");
while (dupUse = BPEnumNext(&bpe))
if (dupUse->cu_def == use->cu_def) break;
BPEnumTerm(&bpe);
return dupUse;
}
/*
* ----------------------------------------------------------------------------
*
* DBPlaceCell --
*
* Add a CellUse to the subcell tile plane of a CellDef.
* Assumes prior check that the new CellUse is not an exact duplicate
* of one already in place.
*
* Results:
* None.
*
* Side effects:
* Modifies the subcell tile plane of the given CellDef.
* Resets the plowing delta of the CellUse to 0. Sets the
* CellDef's parent pointer to point to the parent def.
*
* ----------------------------------------------------------------------------
*/
void
DBPlaceCell (use, def)
CellUse * use; /* new celluse to add to subcell tile plane */
CellDef * def; /* parent cell's definition */
{
Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
struct searchArg arg; /* argument to placeCellFunc() */
ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
ASSERT(def, "DBPlaceCell");
/* To do: Check non-duplicate placement, check non-duplicate ID */
use->cu_parent = def;
/* Be careful not to permit interrupts during this, or the
* database could be left in a trashed state.
*/
SigDisableInterrupts();
BPAdd(def->cd_cellPlane, use);
def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_PLACE);
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
* DBDeleteCell --
*
* Remove a CellUse from the subcell tile plane of a CellDef.
*
* Results:
* None.
*
* Side effects:
* Modifies the subcell tile plane of the CellDef, sets the
* parent pointer of the deleted CellUse to NULL.
* ----------------------------------------------------------------------------
*/
void
DBDeleteCell (use)
CellUse * use;
{
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
* state.
*/
SigDisableInterrupts();
dbInstanceUnplace(use);
use->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_DELETE);
use->cu_parent = (CellDef *) NULL;
SigEnableInterrupts();
}