1 /*
2  * DBcellcopy.c --
3  *
4  * Cell copying (yank and stuff)
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/DBcellcopy.c,v 1.13 2010/06/24 12:37:15 tim Exp $";
21 #endif  /* not lint */
22 
23 #include <stdio.h>
24 #include "utils/magic.h"
25 #include "utils/geometry.h"
26 #include "utils/geofast.h"
27 #include "utils/malloc.h"
28 #include "tiles/tile.h"
29 #include "utils/hash.h"
30 #include "utils/utils.h"
31 #include "database/database.h"
32 #include "database/databaseInt.h"
33 #include "textio/textio.h"
34 #include "windows/windows.h"
35 #include "dbwind/dbwind.h"
36 #include "commands/commands.h"
37 
38 /*
39  * The following variable points to the tables currently used for
40  * painting.  The paint tables are occasionally switched, by clients
41  * like the design-rule checker, by calling DBNewPaintTable.  This
42  * paint table applies only to the routine in this module.
43  */
44 static PaintResultType (*dbCurPaintTbl)[NT][NT] = DBPaintResultTbl;
45 
46 /*
47  * The following variable points to the version of DBPaintPlane used
48  * for painting during yanks.  This is occasionally switched by clients
49  * such as the design-rule checker that need to use, for example,
50  * DBPaintPlaneMark instead of the standard version.
51  */
52 static int (*dbCurPaintPlane)() = DBPaintPlaneWrapper;
53 
54     /* Structure passed to DBTreeSrTiles() */
55 struct copyAllArg
56 {
57     TileTypeBitMask	*caa_mask;	/* Mask of tile types to be copied */
58     Rect		 caa_rect;	/* Clipping rect in target coords */
59     CellUse		*caa_targetUse;	/* Use to which tiles are copied */
60     void		(*caa_func)();	/* Callback function for off-grid points */
61     Rect		*caa_bbox;	/* Bbox of material copied (in
62 					 * targetUse coords).  Used only when
63 					 * copying cells.
64 					 */
65 };
66 
67     /* Structure passed to DBSrPaintArea() */
68 struct copyArg
69 {
70     TileTypeBitMask	*ca_mask;	/* Mask of tile types to be copied */
71     Rect		 ca_rect;	/* Clipping rect in source coords */
72     CellUse		*ca_targetUse;	/* Use to which tiles are copied */
73     Transform		*ca_trans;	/* Transform to target */
74 };
75 
76     /* Structure passed to DBTreeSrLabels to hold information about
77      * copying labels.
78      */
79 
80 struct copyLabelArg
81 {
82     CellUse *cla_targetUse;		/* Use to which labels are copied. */
83     Rect *cla_bbox;			/* If non-NULL, points to rectangle
84 					 * to be filled in with total area of
85 					 * all labels copied.
86 					 */
87     char *cla_glob;			/* If non-NULL, used for glob-style
88 					 * matching of labels during copy.
89 					 */
90 };
91 
92 /*
93  * ----------------------------------------------------------------------------
94  *
95  * DBPaintPlaneWrapper --
96  *
97  *    Simple wrapper to DBPaintPlane.
98  *    Note that this function is passed as a pointer on occasion, so
99  *    it cannot be replaced with a macro!
100  *
101  * ----------------------------------------------------------------------------
102  */
103 
104 int
DBPaintPlaneWrapper(def,pNum,type,area,undo)105 DBPaintPlaneWrapper(def, pNum, type, area, undo)
106     CellDef *def;
107     int pNum;
108     TileType type;
109     Rect *area;
110     PaintUndoInfo *undo;
111 {
112     TileType loctype = type & TT_LEFTMASK;
113     Rect expand;
114     int result;
115 
116     undo->pu_pNum = pNum;
117     result = DBNMPaintPlane(def->cd_planes[pNum], type, area,
118 		dbCurPaintTbl[pNum][loctype], undo);
119     GEO_EXPAND(area, 1, &expand);
120     DBMergeNMTiles(def->cd_planes[pNum], &expand, undo);
121     return result;
122 }
123 
124 /*
125  * ----------------------------------------------------------------------------
126  *
127  * DBPaintPlaneMark --
128  *
129  *    Another wrapper function to DBPaintPlane.  This one is used for
130  *    hierarchical DRC, and ensures that tiles are never painted twice
131  *    on the same pass, so as not to cause false overlap errors.
132  *
133  * ----------------------------------------------------------------------------
134  */
135 
136 int
DBPaintPlaneMark(def,pNum,type,area,undo)137 DBPaintPlaneMark(def, pNum, type, area, undo)
138     CellDef *def;
139     int pNum;
140     TileType type;
141     Rect *area;
142     PaintUndoInfo *undo;
143 {
144     TileType loctype = type & TT_LEFTMASK;
145 
146     undo->pu_pNum = pNum;
147     return DBNMPaintPlane0(def->cd_planes[pNum], type, area,
148 		dbCurPaintTbl[pNum][loctype], undo, (unsigned char)PAINT_MARK);
149 }
150 
151 /*
152  * ----------------------------------------------------------------------------
153  *
154  * ----------------------------------------------------------------------------
155  */
156 
157 int
DBPaintPlaneXor(def,pNum,type,area,undo)158 DBPaintPlaneXor(def, pNum, type, area, undo)
159     CellDef *def;
160     int pNum;
161     TileType type;
162     Rect *area;
163     PaintUndoInfo *undo;
164 {
165     TileType loctype = type & TT_LEFTMASK;
166 
167     undo->pu_pNum = pNum;
168     return DBNMPaintPlane0(def->cd_planes[pNum], type, area,
169 		dbCurPaintTbl[pNum][loctype], undo, (unsigned char)PAINT_XOR);
170 }
171 
172 /*
173  * ----------------------------------------------------------------------------
174  *
175  * DBPaintPlaneActive ---
176  *
177  *    This function calls DBPaintPlane, but first checks if the type
178  *    being painted is an active layer.  If the type is a contact,
179  *    then the residues are checked to see if they are active layers.
180  *    Painting proceeds accordingly.
181  *
182  * ----------------------------------------------------------------------------
183  */
184 
185 int
DBPaintPlaneActive(def,pNum,type,area,undo)186 DBPaintPlaneActive(def, pNum, type, area, undo)
187     CellDef *def;
188     int pNum;
189     TileType type;
190     Rect *area;
191     PaintUndoInfo *undo;
192 {
193     TileType loctype = type & TT_LEFTMASK;
194     TileType t;
195 
196     if (DBIsContact(loctype))
197     {
198 	TileTypeBitMask tmask, *rMask;
199 
200 	rMask = DBResidueMask(loctype);
201 	TTMaskAndMask3(&tmask, rMask, &DBActiveLayerBits);
202 	if (!TTMaskEqual(&tmask, rMask))
203 	{
204 	    if (!TTMaskIsZero(&tmask))
205 		for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
206 		    if (TTMaskHasType(&tmask, t))
207 			DBPaintPlaneWrapper(def, pNum, t | (type &
208 				(TT_SIDE | TT_DIRECTION | TT_DIAGONAL)),
209 				area, undo);
210 	    return 0;
211 	}
212     }
213     if (TTMaskHasType(&DBActiveLayerBits, loctype))
214 	return DBPaintPlaneWrapper(def, pNum, type, area, undo);
215     else
216 	return 0;
217 }
218 
219 /*
220  *-----------------------------------------------------------------------------
221  *
222  * DBCellCopyManhattanPaint --
223  *
224  * Copy paint from the tree rooted at scx->scx_use to the paint planes
225  * of targetUse, transforming according to the transform in scx.
226  * Only the types specified by typeMask are copied, and only Manhattan
227  * geometry is copied.
228  *
229  * Results:
230  *	None.
231  *
232  * Side effects:
233  *	Updates the paint planes in targetUse.
234  *
235  *-----------------------------------------------------------------------------
236  */
237 
238 void
DBCellCopyManhattanPaint(scx,mask,xMask,targetUse)239 DBCellCopyManhattanPaint(scx, mask, xMask, targetUse)
240     SearchContext *scx;		/* Describes root cell to search, area to
241 				 * copy, transform from root cell to coords
242 				 * of targetUse.
243 				 */
244     TileTypeBitMask *mask;	/* Types of tiles to be yanked/stuffed */
245     int xMask;			/* Expansion state mask to be used in search */
246     CellUse *targetUse;		/* Cell into which material is to be stuffed */
247 {
248     struct copyAllArg arg;
249     int dbCopyManhattanPaint();
250 
251     arg.caa_mask = mask;
252     arg.caa_targetUse = targetUse;
253     arg.caa_func = NULL;
254     GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
255 
256     (void) DBTreeSrTiles(scx, mask, xMask, dbCopyManhattanPaint, (ClientData) &arg);
257 }
258 
259 
260 /*
261  *-----------------------------------------------------------------------------
262  *
263  * DBCellCopyAllPaint --
264  *
265  * Copy paint from the tree rooted at scx->scx_use to the paint planes
266  * of targetUse, transforming according to the transform in scx.
267  * Only the types specified by typeMask are copied.
268  *
269  * Results:
270  *	None.
271  *
272  * Side effects:
273  *	Updates the paint planes in targetUse.
274  *
275  *-----------------------------------------------------------------------------
276  */
277 
278 void
DBCellCopyAllPaint(scx,mask,xMask,targetUse)279 DBCellCopyAllPaint(scx, mask, xMask, targetUse)
280     SearchContext *scx;		/* Describes root cell to search, area to
281 				 * copy, transform from root cell to coords
282 				 * of targetUse.
283 				 */
284     TileTypeBitMask *mask;	/* Types of tiles to be yanked/stuffed */
285     int xMask;			/* Expansion state mask to be used in search */
286     CellUse *targetUse;		/* Cell into which material is to be stuffed */
287 {
288     TileTypeBitMask locMask;
289     struct copyAllArg arg;
290     int dbCopyAllPaint();
291 
292     arg.caa_mask = mask;
293     arg.caa_targetUse = targetUse;
294     arg.caa_func = NULL;
295     GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
296 
297     /* Add any stacking types for the search (but not to mask passed as arg!) */
298     locMask = *mask;
299     DBMaskAddStacking(&locMask);
300 
301     DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg);
302 }
303 
304 /*
305  *-----------------------------------------------------------------------------
306  *
307  * DBCellCheckCopyAllPaint --
308  *
309  * Copy paint from the tree rooted at scx->scx_use to the paint planes
310  * of targetUse, transforming according to the transform in scx.
311  * Only the types specified by typeMask are copied.
312  *
313  * Results:
314  *	None.
315  *
316  * Side effects:
317  *	Updates the paint planes in targetUse.
318  *
319  *-----------------------------------------------------------------------------
320  */
321 
322 void
DBCellCheckCopyAllPaint(scx,mask,xMask,targetUse,func)323 DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
324     SearchContext *scx;		/* Describes root cell to search, area to
325 				 * copy, transform from root cell to coords
326 				 * of targetUse.
327 				 */
328     TileTypeBitMask *mask;	/* Types of tiles to be yanked/stuffed */
329     int xMask;			/* Expansion state mask to be used in search */
330     CellUse *targetUse;		/* Cell into which material is to be stuffed */
331     void (*func)();		/* Function to call on tile split error */
332 {
333     TileTypeBitMask locMask;
334     struct copyAllArg arg;
335     int dbCopyAllPaint();
336 
337     arg.caa_mask = mask;
338     arg.caa_targetUse = targetUse;
339     arg.caa_func = func;
340     GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
341 
342     /* Add any stacking types for the search (but not to mask passed as arg!) */
343     locMask = *mask;
344     DBMaskAddStacking(&locMask);
345 
346     DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg);
347 }
348 
349 /* Client data structure used by DBCellGenerateSubstrate() */
350 
351 struct dbCopySubData {
352     Plane *csd_plane;
353     TileType csd_subtype;
354     int csd_pNum;
355     bool csd_modified;
356 };
357 
358 /*
359  *-----------------------------------------------------------------------------
360  *
361  * DBCellGenerateSubstrate --
362  *
363  * This function is used by the extraction code in ExtSubtree.c.
364  * Paint substrate into the target use.  Similar to DBCellCopyAllPaint(),
365  * but it finds space tiles on the substrate plane and converts them to
366  * a substrate type in the target, clipped to the cell boundary.  This
367  * allows the extraction to find and record all substrate regions, both
368  * common (global substrate) and local (isolated substrate), without
369  * requiring a physical substrate type to be drawn into all cells.
370  *
371  * Unlike normal paint copying, this can only be done by painting the
372  * substrate type over the entire cell area and then erasing all areas
373  * belonging to not-substrate types in the source.
374  *
375  * Returns:
376  *	Nothing.
377  *
378  * Side Effects:
379  *	Paints into the targetUse's CellDef.  This only happens if two
380  *	conditions are met:
381  *	(1) The techfile has defined "substrate"
382  *	(2) The techfile defines a type corresponding to the substrate
383  *
384  * ----------------------------------------------------------------------------
385  */
386 
387 Plane *
DBCellGenerateSubstrate(scx,subType,notSubMask,subShieldMask,targetDef)388 DBCellGenerateSubstrate(scx, subType, notSubMask, subShieldMask, targetDef)
389     SearchContext *scx;
390     TileType subType;			/* Substrate paint type */
391     TileTypeBitMask *notSubMask;	/* Mask of types that are not substrate */
392     TileTypeBitMask *subShieldMask;	/* Mask of types that shield substrate */
393     CellDef *targetDef;
394 {
395     struct dbCopySubData csd;
396     Plane *tempPlane;
397     int plane;
398     Rect rect;
399     int dbPaintSubFunc();
400     int dbEraseNonSub();
401     int dbCopySubFunc();
402 
403     GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &rect);
404 
405     /* Clip to bounding box of the top level cell */
406     GEOCLIP(&rect, &scx->scx_use->cu_def->cd_bbox);
407 
408     plane = DBPlane(subType);
409 
410     tempPlane = DBNewPlane((ClientData) TT_SPACE);
411     DBClearPaintPlane(tempPlane);
412 
413     csd.csd_subtype = subType;
414     csd.csd_plane = tempPlane;
415     csd.csd_pNum = plane;
416     csd.csd_modified = FALSE;
417 
418     /* First paint the substrate type in the temporary plane over the	*/
419     /* area of all substrate shield types.				*/
420     /* Note: xMask is always zero, as this is only called from extract routines */
421     DBTreeSrTiles(scx, subShieldMask, 0, dbPaintSubFunc, (ClientData)&csd);
422     if (csd.csd_modified == FALSE) return NULL;
423 
424     /* Now erase all areas that are non-substrate types in the source */
425     DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSub, (ClientData)&csd);
426 
427     /* Finally, copy the destination plane contents onto tempPlane */
428     DBSrPaintArea((Tile *)NULL, targetDef->cd_planes[plane], &TiPlaneRect,
429 		&DBAllButSpaceBits, dbCopySubFunc, (ClientData)&csd);
430 
431     return tempPlane;
432 }
433 
434 /*
435  * Callback function for DBCellGenerateSubstrate()
436  * Finds tiles in the source def that belong to the list of types that
437  * shield the substrate (e.g., deep nwell), and paint the substrate type
438  * into the target plane over the same area.
439  */
440 
441 int
dbPaintSubFunc(tile,cxp)442 dbPaintSubFunc(tile, cxp)
443     Tile *tile;			/* Pointer to source tile with shield type */
444     TreeContext *cxp;		/* Context from DBTreeSrTiles */
445 {
446     SearchContext *scx;
447     Rect sourceRect, targetRect;
448     int pNum;
449     TileType type, loctype, subType;
450     Plane *plane;
451     struct dbCopySubData *csd;	/* Client data */
452 
453     scx = cxp->tc_scx;
454     csd = (struct dbCopySubData *)cxp->tc_filter->tf_arg;
455     plane = csd->csd_plane;
456     pNum = csd->csd_pNum;
457     subType = csd->csd_subtype;
458     type = TiGetTypeExact(tile);
459     if (IsSplit(tile))
460     {
461 	loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
462 	if (loctype == TT_SPACE) return 0;
463     }
464 
465     /* Construct the rect for the tile */
466     TITORECT(tile, &sourceRect);
467 
468     /* Transform to target coordinates */
469     GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
470 
471     csd->csd_modified = TRUE;
472 
473     return DBNMPaintPlane(plane, type, &targetRect, DBStdPaintTbl(subType, pNum),
474 		(PaintUndoInfo *)NULL);
475 }
476 
477 /*
478  * Callback function for DBCellGenerateSubstrate()
479  * Finds tiles on the substrate plane in the source def that are not the
480  * substrate type, and erases those areas from the target.  This reduces
481  * the geometry in the target plane to areas that form isolated substrate
482  * regions.  Regions belonging to the common global substrate are ignored.
483  */
484 
485 int
dbEraseNonSub(tile,cxp)486 dbEraseNonSub(tile, cxp)
487     Tile *tile;			/* Pointer to tile to erase from target */
488     TreeContext *cxp;		/* Context from DBTreeSrTiles */
489 {
490     SearchContext *scx;
491     Rect sourceRect, targetRect;
492     Plane *plane;		/* Plane of target data */
493     TileType type, loctype, subType;
494     struct dbCopySubData *csd;
495     int pNum;
496 
497     csd = (struct dbCopySubData *)cxp->tc_filter->tf_arg;
498     plane = csd->csd_plane;
499     subType = csd->csd_subtype;
500     pNum = csd->csd_pNum;
501 
502     scx = cxp->tc_scx;
503 
504     type = TiGetTypeExact(tile);
505     if (IsSplit(tile))
506     {
507 	loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
508 	if (loctype == TT_SPACE) return 0;
509     }
510 
511     /* Construct the rect for the tile */
512     TITORECT(tile, &sourceRect);
513 
514     /* Transform to target coordinates */
515     GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
516 
517     /* Erase the substrate type from the area of this tile in the target plane. */
518     return DBNMPaintPlane(plane, type, &targetRect, DBStdEraseTbl(subType, pNum),
519 		(PaintUndoInfo *)NULL);
520 }
521 
522 /*
523  * Callback function for DBCellGenerateSubstrate()
524  * Simple paint function to copy all paint from the substrate plane of the
525  * source def into the target plane containing the isolated substrate
526  * regions.
527  */
528 
529 int
dbCopySubFunc(tile,csd)530 dbCopySubFunc(tile, csd)
531     Tile *tile;			/* Pointer to tile to erase from target */
532     struct dbCopySubData *csd;	/* Client data */
533 {
534     Rect rect;
535     int pNum;
536     TileType type, loctype;
537     Plane *plane;
538 
539     plane = csd->csd_plane;
540     pNum = csd->csd_pNum;
541     type = TiGetTypeExact(tile);
542     if (IsSplit(tile))
543     {
544 	loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
545 	if (loctype == TT_SPACE) return 0;
546     }
547     else
548 	loctype = type;
549 
550     /* Construct the rect for the tile */
551     TITORECT(tile, &rect);
552 
553     return DBNMPaintPlane(plane, type, &rect, DBStdPaintTbl(loctype, pNum),
554 		(PaintUndoInfo *)NULL);
555 }
556 
557 /*
558  *-----------------------------------------------------------------------------
559  *
560  * DBCellCopyAllLabels --
561  *
562  * Copy labels from the tree rooted at scx->scx_use to targetUse,
563  * transforming according to the transform in scx.  Only labels
564  * attached to layers of the types specified by mask are copied.
565  * The area to be copied is determined by GEO_LABEL_IN_AREA.
566  *
567  * Results:
568  *	None.
569  *
570  * Side effects:
571  *	Copies labels to targetUse, clipping against scx->scx_area.
572  *	If pArea is given, store in it the bounding box of all the
573  *	labels copied.
574  *
575  *-----------------------------------------------------------------------------
576  */
577 
578 void
DBCellCopyAllLabels(scx,mask,xMask,targetUse,pArea)579 DBCellCopyAllLabels(scx, mask, xMask, targetUse, pArea)
580     SearchContext *scx;		/* Describes root cell to search, area to
581 				 * copy, transform from root cell to coords
582 				 * of targetUse.
583 				 */
584     TileTypeBitMask *mask;	/* Only labels of these types are copied */
585     int xMask;			/* Expansion state mask to be used in search */
586     CellUse *targetUse;		/* Cell into which labels are to be stuffed */
587     Rect *pArea;		/* If non-NULL, points to a box that will be
588 				 * filled in with bbox (in targetUse coords)
589 				 * of all labels copied.  Will be degenerate
590 				 * if nothing was copied.
591 				 */
592 {
593     int dbCopyAllLabels();
594     struct copyLabelArg arg;
595 
596     /* DBTeeSrLabels finds all the labels that we want plus some more.
597      * We'll filter out the ones that we don't need.
598      */
599 
600     arg.cla_targetUse = targetUse;
601     arg.cla_bbox = pArea;
602     arg.cla_glob = NULL;
603     if (pArea != NULL)
604     {
605 	pArea->r_xbot = 0;
606 	pArea->r_xtop = -1;
607     }
608     (void) DBTreeSrLabels(scx, mask, xMask, (TerminalPath *) 0,
609 			TF_LABEL_ATTACH, dbCopyAllLabels,
610 			(ClientData) &arg);
611 }
612 
613     /*ARGSUSED*/
614 int
dbCopyAllLabels(scx,lab,tpath,arg)615 dbCopyAllLabels(scx, lab, tpath, arg)
616     SearchContext *scx;
617     Label *lab;
618     TerminalPath *tpath;
619     struct copyLabelArg *arg;
620 {
621     Rect labTargetRect;
622     Point labOffset;
623     int targetPos, labRotate;
624     CellDef *def;
625 
626     def = arg->cla_targetUse->cu_def;
627     if (arg->cla_glob != NULL)
628 	if (!Match(arg->cla_glob, lab->lab_text))
629 	    return 0;
630     if (!GEO_LABEL_IN_AREA(&lab->lab_rect, &(scx->scx_area))) return 0;
631     GeoTransRect(&scx->scx_trans, &lab->lab_rect, &labTargetRect);
632     targetPos = GeoTransPos(&scx->scx_trans, lab->lab_just);
633     GeoTransPointDelta(&scx->scx_trans, &lab->lab_offset, &labOffset);
634     labRotate = GeoTransAngle(&scx->scx_trans, lab->lab_rotate);
635 
636     /* Eliminate duplicate labels.  Don't pay any attention to layers
637      * in deciding on duplicates:  if text and position match, it's a
638      * duplicate.
639      */
640 
641     DBEraseLabelsByContent(def, &labTargetRect, -1, lab->lab_text);
642     DBPutFontLabel(def, &labTargetRect, lab->lab_font,
643 		lab->lab_size, labRotate, &labOffset, targetPos,
644 		lab->lab_text, lab->lab_type, lab->lab_flags, lab->lab_port);
645     if (arg->cla_bbox != NULL)
646     {
647 	GeoIncludeAll(&labTargetRect, arg->cla_bbox);
648 
649 	/* Rendered font labels include the bounding box of the text itself */
650 	if (lab->lab_font >= 0)
651 	{
652 	    GeoTransRect(&scx->scx_trans, &lab->lab_bbox, &labTargetRect);
653 	    GeoIncludeAll(&labTargetRect, arg->cla_bbox);
654 	}
655     }
656     return 0;
657 }
658 
659 /*
660  *-----------------------------------------------------------------------------
661  *
662  * DBCellCopyGlobLabels --
663  *
664  * Copy labels from the tree rooted at scx->scx_use to targetUse,
665  * transforming according to the transform in scx.  Only labels
666  * attached to layers of the types specified by mask and which
667  * match the string "globmatch" by glob-style matching are copied.
668  * The area to be copied is determined by GEO_LABEL_IN_AREA.
669  *
670  * Results:
671  *	None.
672  *
673  * Side effects:
674  *	Copies labels to targetUse, clipping against scx->scx_area.
675  *	If pArea is given, store in it the bounding box of all the
676  *	labels copied.
677  *
678  *-----------------------------------------------------------------------------
679  */
680 
681 void
DBCellCopyGlobLabels(scx,mask,xMask,targetUse,pArea,globmatch)682 DBCellCopyGlobLabels(scx, mask, xMask, targetUse, pArea, globmatch)
683     SearchContext *scx;		/* Describes root cell to search, area to
684 				 * copy, transform from root cell to coords
685 				 * of targetUse.
686 				 */
687     TileTypeBitMask *mask;	/* Only labels of these types are copied */
688     int xMask;			/* Expansion state mask to be used in search */
689     CellUse *targetUse;		/* Cell into which labels are to be stuffed */
690     Rect *pArea;		/* If non-NULL, points to a box that will be
691 				 * filled in with bbox (in targetUse coords)
692 				 * of all labels copied.  Will be degenerate
693 				 * if nothing was copied.
694 				 */
695     char *globmatch;		/* If non-NULL, only labels matching this
696 				 * string by glob-style matching are copied.
697 				 */
698 {
699     int dbCopyAllLabels();
700     struct copyLabelArg arg;
701 
702     /* DBTeeSrLabels finds all the labels that we want plus some more.
703      * We'll filter out the ones that we don't need.
704      */
705 
706     arg.cla_targetUse = targetUse;
707     arg.cla_bbox = pArea;
708     arg.cla_glob = globmatch;
709     if (pArea != NULL)
710     {
711 	pArea->r_xbot = 0;
712 	pArea->r_xtop = -1;
713     }
714     (void) DBTreeSrLabels(scx, mask, xMask, (TerminalPath *) 0,
715 			TF_LABEL_ATTACH, dbCopyAllLabels,
716 			(ClientData) &arg);
717 }
718 
719 /*
720  *-----------------------------------------------------------------------------
721  *
722  * DBCellCopyPaint --
723  *
724  * Copy paint from the paint planes of scx->scx_use to the paint planes
725  * of targetUse, transforming according to the transform in scx.
726  * Only the types specified by typeMask are copied.
727  *
728  * Results:
729  *	None.
730  *
731  * Side effects:
732  *	Updates the paint planes in targetUse.
733  *
734  *-----------------------------------------------------------------------------
735  */
736 
737 void
DBCellCopyPaint(scx,mask,xMask,targetUse)738 DBCellCopyPaint(scx, mask, xMask, targetUse)
739     SearchContext *scx;		/* Describes cell to search, area to
740 				 * copy, transform from cell to coords
741 				 * of targetUse.
742 				 */
743     TileTypeBitMask *mask;	/* Types of tiles to be yanked/stuffed */
744     int xMask;			/* Expansion state mask to be used in search */
745     CellUse *targetUse;		/* Cell into which material is to be stuffed */
746 {
747     int pNum;
748     PlaneMask planeMask;
749     TreeContext cxp;
750     TreeFilter filter;
751     struct copyAllArg arg;
752     int dbCopyAllPaint();
753 
754     if (!DBDescendSubcell(scx->scx_use, xMask))
755 	return;
756 
757     arg.caa_mask = mask;
758     arg.caa_targetUse = targetUse;
759     arg.caa_func = NULL;
760     GeoTransRect(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
761 
762     /* Build dummy TreeContext */
763     cxp.tc_scx = scx;
764     cxp.tc_filter = &filter;
765     filter.tf_arg = (ClientData) &arg;
766 
767     /* tf_func, tf_mask, tf_xmask, tf_planes, and tf_tpath are unneeded */
768 
769     planeMask = DBTechTypesToPlanes(mask);
770     for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
771 	if (PlaneMaskHasPlane(planeMask, pNum))
772 	{
773 	    cxp.tc_plane = pNum;
774 	    (void) DBSrPaintArea((Tile *) NULL,
775 		scx->scx_use->cu_def->cd_planes[pNum], &scx->scx_area,
776 		mask, dbCopyAllPaint, (ClientData) &cxp);
777 	}
778 }
779 
780 /*
781  *-----------------------------------------------------------------------------
782  *
783  * DBCellCopyLabels --
784  *
785  * Copy labels from scx->scx_use to targetUse, transforming according to
786  * the transform in scx.  Only labels attached to layers of the types
787  * specified by mask are copied.  If mask contains the L_LABEL bit, then
788  * all labels are copied regardless of their layer.  The area copied is
789  * determined by GEO_LABEL_IN_AREA.
790  *
791  * Results:
792  *	None.
793  *
794  * Side effects:
795  *	Updates the labels in targetUse.  If pArea is given, it will
796  *	be filled in with the bounding box of all labels copied.
797  *
798  *-----------------------------------------------------------------------------
799  */
800 
801 void
DBCellCopyLabels(scx,mask,xMask,targetUse,pArea)802 DBCellCopyLabels(scx, mask, xMask, targetUse, pArea)
803     SearchContext *scx;		/* Describes root cell to search, area to
804 				 * copy, transform from root cell to coords
805 				 * of targetUse.
806 				 */
807     TileTypeBitMask *mask;	/* Only labels of these types are copied */
808     int xMask;			/* Expansion state mask to be used in search */
809     CellUse *targetUse;		/* Cell into which labels are to be stuffed */
810     Rect *pArea;		/* If non-NULL, points to rectangle to be
811 				 * filled in with bbox (in targetUse coords)
812 				 * of all labels copied.  Will be degenerate
813 				 * if no labels are copied.
814 				 */
815 {
816     Label *lab;
817     CellDef *def = targetUse->cu_def;
818     Rect labTargetRect;
819     Rect *rect = &scx->scx_area;
820     int targetPos, labRotate;
821     Point labOffset;
822     CellUse *sourceUse = scx->scx_use;
823 
824     if (pArea != NULL)
825     {
826 	pArea->r_xbot = 0;
827 	pArea->r_xtop = -1;
828     }
829 
830     if (!DBDescendSubcell(sourceUse, xMask))
831 	return;
832 
833     for (lab = sourceUse->cu_def->cd_labels; lab; lab = lab->lab_next)
834 	if (GEO_LABEL_IN_AREA(&lab->lab_rect, rect) &&
835 		(TTMaskHasType(mask, lab->lab_type)
836 		|| TTMaskHasType(mask, L_LABEL)))
837 	{
838 	    GeoTransRect(&scx->scx_trans, &lab->lab_rect, &labTargetRect);
839 	    targetPos = GeoTransPos(&scx->scx_trans, lab->lab_just);
840 	    GeoTransPointDelta(&scx->scx_trans, &lab->lab_offset, &labOffset);
841 	    labRotate = GeoTransAngle(&scx->scx_trans, lab->lab_rotate);
842 
843 
844 	    /* Eliminate duplicate labels.  Don't pay any attention to
845 	     * type when deciding on duplicates, since types can change
846 	     * later and then we'd have a duplicate.
847 	     */
848 
849 	    DBEraseLabelsByContent(def, &labTargetRect, -1, lab->lab_text);
850 	    DBPutFontLabel(def, &labTargetRect, lab->lab_font,
851 			lab->lab_size, labRotate, &labOffset, targetPos,
852 			lab->lab_text, lab->lab_type, lab->lab_flags,
853 			lab->lab_port);
854 	    if (pArea != NULL)
855 		(void) GeoIncludeAll(&labTargetRect, pArea);
856 	}
857 }
858 
859 /***
860  *** Filter function for paint: Ignores diagonal (split) tiles for
861  *** purposes of selection searches.
862  ***/
863 
864 int
dbCopyManhattanPaint(tile,cxp)865 dbCopyManhattanPaint(tile, cxp)
866     Tile *tile;	/* Pointer to tile to copy */
867     TreeContext *cxp;		/* Context from DBTreeSrTiles */
868 {
869     SearchContext *scx = cxp->tc_scx;
870     struct copyAllArg *arg;
871     Rect sourceRect, targetRect;
872     PaintUndoInfo ui;
873     CellDef *def;
874     TileType type;
875     int pNum = cxp->tc_plane;
876 
877     /*
878      * Don't copy space tiles -- this copy is additive.
879      * We should never get passed a space tile, though, because
880      * the caller will be using DBSrPaintArea, so this is just
881      * a sanity check.
882      */
883 
884     type = TiGetTypeExact(tile);
885     if (type == TT_SPACE || (type & TT_DIAGONAL))
886 	return 0;
887 
888     arg = (struct copyAllArg *) cxp->tc_filter->tf_arg;
889 
890     /* Construct the rect for the tile in source coordinates */
891     TITORECT(tile, &sourceRect);
892 
893     /* Transform to target coordinates */
894     GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
895 
896     ui.pu_def = def = arg->caa_targetUse->cu_def;
897     def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
898 
899     /* Clip against the target area */
900     GEOCLIP(&targetRect, &arg->caa_rect);
901 
902     (*dbCurPaintPlane)(def, pNum, type, &targetRect, &ui);
903     return (0);
904 }
905 
906 
907 /***
908  *** Filter function for paint
909  ***/
910 
911 int
dbCopyAllPaint(tile,cxp)912 dbCopyAllPaint(tile, cxp)
913     Tile *tile;	/* Pointer to tile to copy */
914     TreeContext *cxp;		/* Context from DBTreeSrTiles */
915 {
916     SearchContext *scx = cxp->tc_scx;
917     struct copyAllArg *arg;
918     Rect sourceRect, targetRect;
919     PaintUndoInfo ui;
920     CellDef *def;
921     TileType type = TiGetTypeExact(tile);
922     int pNum = cxp->tc_plane;
923     int result;
924     TileTypeBitMask *typeMask;
925 
926     /*
927      * Don't copy space tiles -- this copy is additive.
928      * We should never get passed a space tile, though, because
929      * the caller will be using DBSrPaintArea, so this is just
930      * a sanity check.
931      */
932 
933     bool splittile = FALSE;
934     TileType dinfo = 0;
935 
936     if (IsSplit(tile))
937     {
938 	splittile = TRUE;
939 	dinfo = DBTransformDiagonal(type, &scx->scx_trans);
940 	type = (SplitSide(tile)) ? SplitRightType(tile) :
941 			SplitLeftType(tile);
942     }
943 
944     if (type == TT_SPACE)
945 	return 0;
946 
947     arg = (struct copyAllArg *) cxp->tc_filter->tf_arg;
948     typeMask = arg->caa_mask;
949 
950     /* Resolve what type we're going to paint, based on the type and mask */
951     if (!TTMaskHasType(typeMask, type))
952     {
953 	TileTypeBitMask rMask, *tmask;
954 
955 	/* Simple case---typeMask has a residue of type on pNum */
956 	tmask = DBResidueMask(type);
957 	TTMaskAndMask3(&rMask, typeMask, tmask);
958 	TTMaskAndMask(&rMask, &DBPlaneTypes[pNum]);
959 	if (!TTMaskIsZero(&rMask))
960 	{
961 	    for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
962 		if (TTMaskHasType(&rMask, type))
963 		    break;
964 	    if (type == DBNumUserLayers) return 0;	/* shouldn't happen */
965 
966 	    /* Hopefully there's always just one type here---sanity check */
967 	    TTMaskClearType(&rMask, type);
968 	    if (!TTMaskIsZero(&rMask))
969 	    {
970 		/* Diagnostic */
971 		TxError("Bad assumption:  Multiple types to paint!  Fix me!\n");
972 	    }
973 	}
974 	else
975 	{
976 	    type = DBPlaneToResidue(type, pNum);
977 	    if (!TTMaskHasType(typeMask, type)) return 0;
978 	}
979     }
980 
981     /* Construct the rect for the tile in source coordinates */
982     TITORECT(tile, &sourceRect);
983 
984     /* Transform to target coordinates */
985     GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
986 
987     ui.pu_def = def = arg->caa_targetUse->cu_def;
988 
989     def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
990 
991     /* Nonmanhattan geometry requires slightly different handling. */
992     /* Paint the whole tile and clip by erasing areas outside the  */
993     /* clipping rectangle.					   */
994     if (splittile)
995     {
996 	Point points[5];
997 	Rect rrect, orect;
998 	int np, i, j;
999 
1000 	GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, dinfo, points, &np);
1001 
1002 	if (np == 0)
1003 	   return(0);
1004 
1005 	if (np >= 3)
1006 	{
1007 	    for (i = 0; i < np; i++)
1008 	    {
1009 		j = (i + 1) % np;
1010 		if (points[i].p_x != points[j].p_x && points[i].p_y !=
1011 				points[j].p_y)
1012 		{
1013 		    /* Break out the triangle */
1014 		    rrect.r_xbot = points[i].p_x;
1015 		    rrect.r_xtop = points[j].p_x;
1016 		    rrect.r_ybot = points[i].p_y;
1017 		    rrect.r_ytop = points[j].p_y;
1018 		    GeoCanonicalRect(&rrect, &targetRect);
1019 		    break;
1020 		}
1021 	    }
1022 	    if (i == np)  /* Exactly one Manhattan rectangle */
1023 	    {
1024 		rrect.r_xbot = points[0].p_x;
1025 		rrect.r_xtop = points[2].p_x;
1026 		rrect.r_ybot = points[0].p_y;
1027 		rrect.r_ytop = points[2].p_y;
1028 		GeoCanonicalRect(&rrect, &targetRect);
1029 		dinfo = 0;
1030 	    }
1031 	    else if (np >= 4) /* Process extra rectangles in the area */
1032 	    {
1033 		/* "orect" is the bounding box of the polygon returned	*/
1034 		/* by ClipTriangle.					*/
1035 
1036 		orect.r_xtop = orect.r_xbot = points[0].p_x;
1037 		orect.r_ytop = orect.r_ybot = points[0].p_y;
1038 		for (i = 0; i < np; i++)
1039 		    GeoIncludePoint(&points[i], &orect);
1040 
1041 		/* Rectangle to left or right */
1042 		rrect.r_ybot = orect.r_ybot;
1043 		rrect.r_ytop = orect.r_ytop;
1044 		if (targetRect.r_xbot > orect.r_xbot)
1045 		{
1046 		    rrect.r_xbot = orect.r_xbot;
1047 		    rrect.r_xtop = targetRect.r_xbot;
1048 		}
1049 		else if (targetRect.r_xtop < orect.r_xtop)
1050 		{
1051 		    rrect.r_xtop = orect.r_xtop;
1052 		    rrect.r_xbot = targetRect.r_xtop;
1053 		}
1054 		else
1055 		    goto topbottom;
1056 
1057 		(*dbCurPaintPlane)(def, pNum, type, &rrect, &ui);
1058 
1059 topbottom:
1060 		/* Rectangle to top or bottom */
1061 		rrect.r_xbot = targetRect.r_xbot;
1062 		rrect.r_xtop = targetRect.r_xtop;
1063 		if (targetRect.r_ybot > orect.r_ybot)
1064 		{
1065 		    rrect.r_ybot = orect.r_ybot;
1066 		    rrect.r_ytop = targetRect.r_ybot;
1067 		}
1068 		else if (targetRect.r_ytop < orect.r_ytop)
1069 		{
1070 		    rrect.r_ytop = orect.r_ytop;
1071 		    rrect.r_ybot = targetRect.r_ytop;
1072 		}
1073 		else
1074 		    goto splitdone;
1075 
1076 		(*dbCurPaintPlane)(def, pNum, type, &rrect, &ui);
1077 	    }
1078 	}
1079     }
1080     else
1081 	/* Clip against the target area */
1082 	GEOCLIP(&targetRect, &arg->caa_rect);
1083 
1084 splitdone:
1085 
1086     result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
1087     if ((result != 0) && (arg->caa_func != NULL))
1088     {
1089 	/* result == 1 used exclusively for DRC off-grid error flagging */
1090 	DRCOffGridError(&targetRect);
1091     }
1092 
1093     return (0);
1094 }
1095 
1096 /*
1097  *-----------------------------------------------------------------------------
1098  *
1099  * DBCellCopyAllCells --
1100  *
1101  * Copy unexpanded subcells from the tree rooted at scx->scx_use
1102  * to the subcell plane of targetUse, transforming according to
1103  * the transform in scx.
1104  *
1105  * This effectively "flattens" a cell hierarchy in the sense that
1106  * all unexpanded subcells in a region (which would appear in the
1107  * display as bounding boxes) are copied into targetUse without
1108  * regard for their original location in the hierarchy of scx->scx_use.
1109  * If an array is unexpanded, it is copied as an array, not as a
1110  * collection of individual cells.
1111  *
1112  * Results:
1113  *	None.
1114  *
1115  * Side effects:
1116  *	Updates the cell plane in targetUse.  If pArea is given, it
1117  *	will be filled in with the total area of all cells copied.
1118  *
1119  *-----------------------------------------------------------------------------
1120  */
1121 
1122 void
DBCellCopyAllCells(scx,xMask,targetUse,pArea)1123 DBCellCopyAllCells(scx, xMask, targetUse, pArea)
1124     SearchContext *scx;		/* Describes root cell to search, area to
1125 				 * copy, transform from root cell to coords
1126 				 * of targetUse.
1127 				 */
1128     CellUse *targetUse;		/* Cell into which material is to be stuffed */
1129     int xMask;			/* Expansion state mask to be used in
1130 				 * searching.  Cells not expanded according
1131 				 * to this mask are copied.  To copy everything
1132 				 * in the subtree under scx->scx_use without
1133 				 * regard to expansion, pass a mask of 0.
1134 				 */
1135     Rect *pArea;		/* If non-NULL, points to a rectangle to be
1136 				 * filled in with bbox (in targetUse coords)
1137 				 * of all cells copied.  Will be degenerate
1138 				 * if nothing was copied.
1139 				 */
1140 {
1141     struct copyAllArg arg;
1142     int dbCellCopyCellsFunc();
1143 
1144     arg.caa_targetUse = targetUse;
1145     arg.caa_bbox = pArea;
1146     if (pArea != NULL)
1147     {
1148 	pArea->r_xbot = 0;		/* Make bounding box empty initially. */
1149 	pArea->r_xtop = -1;
1150     }
1151     GeoTransRect(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
1152 
1153     (void) DBTreeSrCells(scx, xMask, dbCellCopyCellsFunc, (ClientData) &arg);
1154 }
1155 
1156 /*
1157  *-----------------------------------------------------------------------------
1158  *
1159  * DBCellCopyCells --
1160  *
1161  * Copy all subcells that are immediate children of scx->scx_use->cu_def
1162  * into the subcell plane of targetUse, transforming according to
1163  * the transform in scx.  Arrays are copied as arrays, not as a
1164  * collection of individual cells.  If a cell is already present in
1165  * targetUse that would be exactly duplicated by a new cell, the new
1166  * cell isn't copied.
1167  *
1168  * Results:
1169  *	None.
1170  *
1171  * Side effects:
1172  *	Updates the cell plane in targetUse.  If pArea is given, it will
1173  *	be filled in with the bounding box of all cells copied.
1174  *
1175  *-----------------------------------------------------------------------------
1176  */
1177 
1178 void
DBCellCopyCells(scx,targetUse,pArea)1179 DBCellCopyCells(scx, targetUse, pArea)
1180     SearchContext *scx;		/* Describes root cell to search, area to
1181 				 * copy, transform from coords of
1182 				 * scx->scx_use->cu_def to coords of targetUse.
1183 				 */
1184     CellUse *targetUse;		/* Cell into which material is to be stuffed */
1185     Rect *pArea;		/* If non-NULL, points to rectangle to be
1186 				 * filled in with bbox (in targetUse coords)
1187 				 * of all cells copied.  Will be degenerate
1188 				 * if nothing was copied.
1189 				 */
1190 {
1191     struct copyAllArg arg;
1192     int dbCellCopyCellsFunc();
1193 
1194     arg.caa_targetUse = targetUse;
1195     arg.caa_bbox = pArea;
1196     if (pArea != NULL)
1197     {
1198 	pArea->r_xbot = 0;
1199 	pArea->r_xtop = -1;
1200     }
1201     GeoTransRect(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
1202 
1203     (void) DBCellSrArea(scx, dbCellCopyCellsFunc, (ClientData) &arg);
1204 }
1205 
1206 /*
1207  *-----------------------------------------------------------------------------
1208  *
1209  * dbCellCopyCellsFunc --
1210  *
1211  * Do the actual work of yanking cells for DBCellCopyAllCells() and
1212  * DBCellCopyCells() above.
1213  *
1214  * Results:
1215  *	Always return 2.
1216  *
1217  * Side effects:
1218  *	Updates the cell plane in arg->caa_targetUse->cu_def.
1219  *
1220  *-----------------------------------------------------------------------------
1221  */
1222 
1223 int
dbCellCopyCellsFunc(scx,arg)1224 dbCellCopyCellsFunc(scx, arg)
1225     SearchContext *scx;	/* Pointer to search context containing
1226 					 * ptr to cell use to be copied,
1227 					 * and transform to the target def.
1228 					 */
1229     struct copyAllArg *arg;	/* Client data from caller */
1230 {
1231     CellUse *use, *newUse;
1232     CellDef *def;
1233     int xsep, ysep, xbase, ybase;
1234     Transform newTrans;
1235 
1236     use = scx->scx_use;
1237     def = use->cu_def;
1238 
1239     /* Don't allow circular structures! */
1240 
1241     if (DBIsAncestor(def, arg->caa_targetUse->cu_def))
1242     {
1243 	TxPrintf("Copying %s would create a circularity in the",
1244 	    def->cd_name);
1245 	TxPrintf(" cell hierarchy \n(%s is already its ancestor)",
1246 	    arg->caa_targetUse->cu_def->cd_name);
1247 	TxPrintf(" so cell not copied.\n");
1248 	return 2;
1249     }
1250 
1251     /* When creating a new use, try to re-use the id from the old
1252      * one.  Only create a new one if the old id can't be used.
1253      */
1254 
1255     newUse = DBCellNewUse(def, (char *) use->cu_id);
1256     if (!DBLinkCell(newUse, arg->caa_targetUse->cu_def))
1257     {
1258 	freeMagic((char *) newUse->cu_id);
1259 	newUse->cu_id = NULL;
1260 	(void) DBLinkCell(newUse, arg->caa_targetUse->cu_def);
1261     }
1262     newUse->cu_expandMask = use->cu_expandMask;
1263     newUse->cu_flags = use->cu_flags;
1264 
1265     /* The translation stuff is funny, since we got one element of
1266      * the array, but not necessarily the lower-left element.  To
1267      * get the transform for the array as a whole, subtract off fo
1268      * the index of the element.  The easiest way to see how this
1269      * works is to look at the code in dbCellSrFunc;  the stuff here
1270      * is the opposite.
1271      */
1272 
1273     if (use->cu_xlo > use->cu_xhi) xsep = -use->cu_xsep;
1274     else xsep = use->cu_xsep;
1275     if (use->cu_ylo > use->cu_yhi) ysep = -use->cu_ysep;
1276     else ysep = use->cu_ysep;
1277     xbase = xsep * (scx->scx_x - use->cu_xlo);
1278     ybase = ysep * (scx->scx_y - use->cu_ylo);
1279     GeoTransTranslate(-xbase, -ybase, &scx->scx_trans, &newTrans);
1280     DBSetArray(use, newUse);
1281     DBSetTrans(newUse, &newTrans);
1282     if (DBCellFindDup(newUse, arg->caa_targetUse->cu_def) != NULL)
1283     {
1284 	if (!(arg->caa_targetUse->cu_def->cd_flags & CDINTERNAL))
1285 	{
1286 	    TxError("Cell \"%s\" would end up on top of an identical copy\n",
1287 		newUse->cu_id);
1288 	    TxError("    of itself.  I'm going to forget about the");
1289 	    TxError(" new copy.\n");
1290 	}
1291 	DBUnLinkCell(newUse, arg->caa_targetUse->cu_def);
1292 	(void) DBCellDeleteUse(newUse);
1293     }
1294     else
1295     {
1296 	DBPlaceCell(newUse, arg->caa_targetUse->cu_def);
1297 	if (arg->caa_bbox != NULL)
1298 	    (void) GeoIncludeAll(&newUse->cu_bbox, arg->caa_bbox);
1299     }
1300     return 2;
1301 }
1302 
1303 /*
1304  * ----------------------------------------------------------------------------
1305  *
1306  * DBNewPaintTable --
1307  *
1308  * 	This procedure changes the paint table to be used by the
1309  *	DBCellCopyPaint and DBCellCopyAllPaint procedures.
1310  *
1311  * Results:
1312  *	The return value is the address of the paint table that used
1313  *	to be in effect.  It is up to the client to restore this
1314  *	value with another call to this procedure.
1315  *
1316  * Side effects:
1317  *	A new paint table takes effect.  However, if newTable is NULL,
1318  *	then the old paint table remains active.  This allows one to
1319  *	get a pointer to the active paint table without altering it.
1320  *
1321  * ----------------------------------------------------------------------------
1322  */
1323 
1324 PaintResultType (*
1325 DBNewPaintTable(newTable))[NT][NT]
1326     PaintResultType (*newTable)[NT][NT];  /* Address of new paint table. */
1327 {
1328     PaintResultType (*oldTable)[NT][NT] = dbCurPaintTbl;
1329     if (newTable) dbCurPaintTbl = newTable;
1330     return oldTable;
1331 }
1332 
1333 /*
1334  * ----------------------------------------------------------------------------
1335  *
1336  * DBNewPaintPlane --
1337  *
1338  * 	This procedure changes the painting procedure to be used by the
1339  *	DBCellCopyPaint and DBCellCopyAllPaint procedures.
1340  *
1341  * Results:
1342  *	The return value is the address of the paint procedure that
1343  *	used to be in effect.  It is up to the client to restore this
1344  *	value with another call to this procedure.
1345  *
1346  * Side effects:
1347  *	A new paint procedure takes effect.
1348  *
1349  * ----------------------------------------------------------------------------
1350  */
1351 
1352 IntProc
1353 DBNewPaintPlane(newProc)
1354     int (*newProc)();		/* Address of new procedure */
1355 {
1356     int (*oldProc)() = dbCurPaintPlane;
1357     dbCurPaintPlane = newProc;
1358     return (oldProc);
1359 }
1360