1 /*
2 * DBcell.c --
3 *
4 * Place and Delete subcells
5 *
6 * *********************************************************************
7 * * Copyright (C) 1985, 1990 Regents of the University of California. *
8 * * Permission to use, copy, modify, and distribute this *
9 * * software and its documentation for any purpose and without *
10 * * fee is hereby granted, provided that the above copyright *
11 * * notice appear in all copies. The University of California *
12 * * makes no representations about the suitability of this *
13 * * software for any purpose. It is provided "as is" without *
14 * * express or implied warranty. Export of this software outside *
15 * * of the United States of America may require an export license. *
16 * *********************************************************************
17 */
18
19 #ifndef lint
20 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 $";
21 #endif /* not lint */
22
23 #include <sys/types.h>
24 #include <stdio.h>
25
26 #include "utils/magic.h"
27 #include "utils/malloc.h"
28 #include "utils/geometry.h"
29 #include "tiles/tile.h"
30 #include "utils/hash.h"
31 #include "database/database.h"
32 #include "database/databaseInt.h"
33 #include "utils/undo.h"
34 #include "utils/signals.h"
35
36 int placeCellFunc();
37 int deleteCellFunc();
38 Tile * clipCellTile();
39 void dupTileBody();
40 void cellTileMerge();
41 bool ctbListMatch();
42 void freeCTBList();
43
44 struct searchArg
45 {
46 CellUse * celluse;
47 Rect * rect;
48 BPlane * bplane;
49 };
50
51 #define TOPLEFT 10
52 #define TOPLEFTRIGHT 11
53 #define TOPBOTTOM 12
54 #define TOPBOTTOMLEFT 14
55 #define TOPBOTTOMLEFTRIGHT 15
56
57 int dbCellDebug = 0;
58
59 void
dbInstanceUnplace(CellUse * use)60 dbInstanceUnplace(CellUse *use)
61 {
62 ASSERT(use != (CellUse *) NULL, "dbInstanceUnplace");
63
64 /* It's important that this code run with interrupts disabled,
65 * or else we could leave the subcell tile plane in a weird
66 * state.
67 */
68
69 BPDelete(use->cu_parent->cd_cellPlane, use);
70 }
71
72
73
74 /*
75 * ----------------------------------------------------------------------------
76 *
77 * DBCellFindDup --
78 *
79 * This procedure indicates whether a particular cell is already
80 * present at a particular point in a particular parent. It is
81 * used to avoid placing duplicate copies of a cell on top of
82 * each other.
83 *
84 * Results:
85 * The return value is NULL if there is not already a CellUse in parent
86 * that is identical to use (same bbox and def). If there is a duplicate
87 * already in parent, then the return value is a pointer to its CellUse.
88 *
89 * Side effects:
90 * None.
91 *
92 * ----------------------------------------------------------------------------
93 */
94
95 CellUse *
DBCellFindDup(use,parent)96 DBCellFindDup(use, parent)
97 CellUse *use; /* Use that is about to be placed in parent.
98 * Is it a duplicate?
99 */
100 CellDef *parent; /* Parent definiton: does it already have
101 * something identical to use?
102 */
103 {
104 BPEnum bpe;
105 CellUse *dupUse;
106
107 BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
108 "DBCellFindDup");
109 while (dupUse = BPEnumNext(&bpe))
110 if (dupUse->cu_def == use->cu_def) break;
111
112 BPEnumTerm(&bpe);
113 return dupUse;
114 }
115
116
117 /*
118 * ----------------------------------------------------------------------------
119 *
120 * DBPlaceCell --
121 * DBPlaceCellNoModify --
122 *
123 * Add a CellUse to the subcell tile plane of a CellDef.
124 * Assumes prior check that the new CellUse is not an exact duplicate
125 * of one already in place.
126 *
127 * Results:
128 * None.
129 *
130 * Side effects:
131 * Modifies the subcell tile plane of the given CellDef.
132 * Resets the plowing delta of the CellUse to 0. Sets the
133 * CellDef's parent pointer to point to the parent def.
134 *
135 * ----------------------------------------------------------------------------
136 */
137
138 void
DBPlaceCell(use,def)139 DBPlaceCell (use, def)
140 CellUse * use; /* new celluse to add to subcell tile plane */
141 CellDef * def; /* parent cell's definition */
142 {
143 Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
144 BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
145 struct searchArg arg; /* argument to placeCellFunc() */
146
147 ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
148 ASSERT(def, "DBPlaceCell");
149
150 /* To do: Check non-duplicate placement, check non-duplicate ID */
151
152 use->cu_parent = def;
153
154 /* Be careful not to permit interrupts during this, or the
155 * database could be left in a trashed state.
156 */
157
158 SigDisableInterrupts();
159 BPAdd(def->cd_cellPlane, use);
160 def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
161 if (UndoIsEnabled())
162 DBUndoCellUse(use, UNDO_CELL_PLACE);
163 SigEnableInterrupts();
164 }
165
166 /* Like DBPlaceCell(), but don't change the flags of the parent cell. */
167 /* This is needed by the bounding box recalculation routine, which may */
168 /* cause the cell to be deleted and replaced for the purpose of */
169 /* capturing the bounding box information in the BPlane structure, but */
170 /* this does not mean that anything in the parent cell has changed. */
171
172 void
DBPlaceCellNoModify(use,def)173 DBPlaceCellNoModify (use, def)
174 CellUse * use; /* new celluse to add to subcell tile plane */
175 CellDef * def; /* parent cell's definition */
176 {
177 Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
178 BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
179 struct searchArg arg; /* argument to placeCellFunc() */
180
181 ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
182 ASSERT(def, "DBPlaceCell");
183
184 /* To do: Check non-duplicate placement, check non-duplicate ID */
185
186 use->cu_parent = def;
187
188 /* Be careful not to permit interrupts during this, or the
189 * database could be left in a trashed state.
190 */
191
192 SigDisableInterrupts();
193 BPAdd(def->cd_cellPlane, use);
194 if (UndoIsEnabled())
195 DBUndoCellUse(use, UNDO_CELL_PLACE);
196 SigEnableInterrupts();
197 }
198
199 /*
200 * ----------------------------------------------------------------------------
201 * DBDeleteCell --
202 *
203 * Remove a CellUse from the subcell tile plane of a CellDef.
204 * If "nomodify" is TRUE, then don't set the parent cell's CDMODIFIED flag.
205 * This is needed when recomputing the bounding box, which should not by
206 * itself change the modified state.
207 *
208 * Results:
209 * None.
210 *
211 * Side effects:
212 * Modifies the subcell tile plane of the CellDef, sets the
213 * parent pointer of the deleted CellUse to NULL.
214 * ----------------------------------------------------------------------------
215 */
216
217 void
DBDeleteCell(use)218 DBDeleteCell (use)
219 CellUse * use;
220 {
221 ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
222
223 /* It's important that this code run with interrupts disabled,
224 * or else we could leave the subcell tile plane in a weird
225 * state.
226 */
227
228 SigDisableInterrupts();
229 dbInstanceUnplace(use);
230 use->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
231 if (UndoIsEnabled())
232 DBUndoCellUse(use, UNDO_CELL_DELETE);
233 use->cu_parent = (CellDef *) NULL;
234 SigEnableInterrupts();
235 }
236
237 /*
238 * ----------------------------------------------------------------------------
239 * DBDeleteCellNoModify --
240 *
241 * Remove a CellUse from the subcell tile plane of a CellDef, as above,
242 * but don't set the parent cell's CDMODIFIED flag. This is needed when
243 * recomputing the bounding box, which should not by itself change the
244 * modified state.
245 *
246 * Results:
247 * None.
248 *
249 * Side effects:
250 * Modifies the subcell tile plane of the CellDef, sets the
251 * parent pointer of the deleted CellUse to NULL.
252 * ----------------------------------------------------------------------------
253 */
254
255 void
DBDeleteCellNoModify(use)256 DBDeleteCellNoModify (use)
257 CellUse * use;
258 {
259 ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
260
261 /* It's important that this code run with interrupts disabled,
262 * or else we could leave the subcell tile plane in a weird
263 * state.
264 */
265
266 SigDisableInterrupts();
267 dbInstanceUnplace(use);
268 if (UndoIsEnabled())
269 DBUndoCellUse(use, UNDO_CELL_DELETE);
270 use->cu_parent = (CellDef *) NULL;
271 SigEnableInterrupts();
272 }
273