1 /*
2  * ExtYank.c --
3  *
4  * Circuit extraction.
5  * Hierarchical yanking of paint and labels.
6  *
7  *     *********************************************************************
8  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
9  *     * Permission to use, copy, modify, and distribute this              *
10  *     * software and its documentation for any purpose and without        *
11  *     * fee is hereby granted, provided that the above copyright          *
12  *     * notice appear in all copies.  The University of California        *
13  *     * makes no representations about the suitability of this            *
14  *     * software for any purpose.  It is provided "as is" without         *
15  *     * express or implied warranty.  Export of this software outside     *
16  *     * of the United States of America may require an export license.    *
17  *     *********************************************************************
18  */
19 
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtYank.c,v 1.2 2008/06/01 18:37:42 tim Exp $";
22 #endif  /* not lint */
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <math.h>
27 
28 #include "utils/magic.h"
29 #include "utils/geometry.h"
30 #include "utils/geofast.h"
31 #include "tiles/tile.h"
32 #include "utils/hash.h"
33 #include "database/database.h"
34 #include "utils/malloc.h"
35 #include "textio/textio.h"
36 #include "debug/debug.h"
37 #include "utils/styles.h"
38 #include "extract/extract.h"
39 #include "extract/extractInt.h"
40 
41 Rect extSubcellArea;		/* Area of currently processed subcell, clipped
42 				 * to area of interaction, in parent coords.
43 				 */
44 
45 /* Forward declarations of filter functions */
46 int extHierYankFunc();
47 int extHierLabelFunc();
48 
49 /*
50  * ----------------------------------------------------------------------------
51  *
52  * extHierCopyLabels --
53  *
54  * Copy the label list from sourceDef to targetDef, prepending
55  * it to any labels already in targetDef.  Does not change
56  * sourceDef's label list.
57  *
58  * Labels are copied in order, so the first label on sourceDef's
59  * list becomes the first label on targetDef's list.  THIS IS
60  * CRITICAL TO INSURE THAT HIERARCHICAL ADJUSTMENTS CAN BE MADE
61  * PROPERLY; SEE extSubtreeAdjustInit() FOR AN EXPLANATION.
62  *
63  * Results:
64  *	None.
65  *
66  * Side effects:
67  *	See above.
68  *
69  * ----------------------------------------------------------------------------
70  */
71 
72 void
extHierCopyLabels(sourceDef,targetDef)73 extHierCopyLabels(sourceDef, targetDef)
74     CellDef *sourceDef, *targetDef;
75 {
76     Label *lab, *newlab, *firstLab, *lastLab;
77     unsigned n;
78 
79     firstLab = lastLab = (Label *) NULL;
80     for (lab = sourceDef->cd_labels; lab; lab = lab->lab_next)
81     {
82 	n = sizeof (Label) + strlen(lab->lab_text) - sizeof lab->lab_text + 1;
83 	newlab = (Label *) mallocMagic((unsigned) n);
84 	bcopy((char *) lab, (char *) newlab, (int) n);
85 
86 	if (lastLab == NULL) lastLab = firstLab = newlab;
87 	else lastLab->lab_next = newlab, lastLab = newlab;
88     }
89 
90     if (lastLab)
91     {
92 	lastLab->lab_next = targetDef->cd_labels;
93 	targetDef->cd_labels = firstLab;
94     }
95 }
96 
97 /*
98  * ----------------------------------------------------------------------------
99  *
100  * extHierFreeLabels --
101  *
102  * Free all the labels from 'def'.
103  * Leaves the label lis of 'def' pointing to NULL.
104  *
105  * This procedure exists mainly so we can trace the freeing
106  * of labels for debugging.
107  *
108  * Results:
109  *	None.
110  *
111  * Side effects:
112  *	See above.
113  *
114  * ----------------------------------------------------------------------------
115  */
116 
117 void
extHierFreeLabels(def)118 extHierFreeLabels(def)
119     CellDef *def;
120 {
121     Label *lab;
122 
123     for (lab = def->cd_labels; lab; lab = lab->lab_next)
124 	freeMagic((char *) lab);
125     def->cd_labels = (Label *) NULL;
126 }
127 
128 /*
129  * ----------------------------------------------------------------------------
130  *
131  * extHierYankFunc --
132  *
133  * Filter function normally called by DBArraySr to yank hierarchically the
134  * paint and labels from 'use'.  Called for each array element.  Also called
135  * during array extraction.
136  *
137  * Expects hy->hy_area to be the area, in use->cu_parent coordinates,
138  * to be yanked.  What we yank will be transformed to parent coordinates
139  * and placed in the cell hy->hy_target.  If hy->hy_prefix is TRUE, we
140  * will prepend all the labels we yank with the use id of this array
141  * element; otherwise, the labels have no prefix.
142  *
143  * WARNING:
144  *	Only node-name labels are yanked; attributes are not.
145  *	The hierarchical extraction code depends on this fact.
146  *
147  * Results:
148  *	Returns 0 to cause DBArraySr to keep going.
149  *
150  * Side effects:
151  *	Adds paint and new labels to 'hy->hy_target'.
152  *
153  * ----------------------------------------------------------------------------
154  */
155 
156 int
extHierYankFunc(use,trans,x,y,hy)157 extHierYankFunc(use, trans, x, y, hy)
158     CellUse *use;	/* Use that is the root of the subtree being yanked */
159     Transform *trans;	/* Transform from coordinates of use->cu_def to those
160 			 * in use->cu_parent, for the array element (x, y).
161 			 */
162     int x, y;		/* Indices of this array element */
163     HierYank *hy;	/* See comments in procedure header */
164 {
165     char labelBuf[4096];
166     TerminalPath tpath;
167     SearchContext scx;
168     Transform tinv;
169 
170     /*
171      * Want scx.scx_area to be the area in coordinates of use->cu_def
172      * but hy->hy_area is in coordinates of use->cu_parent.
173      */
174     GEOINVERTTRANS(trans, &tinv);
175     GEOTRANSRECT(&tinv, hy->hy_area, &scx.scx_area);
176     GEOCLIP(&scx.scx_area, &use->cu_def->cd_bbox);
177 
178     scx.scx_use = use;
179     scx.scx_trans = *trans;
180     scx.scx_x = x;
181     scx.scx_y = y;
182 
183     /* Yank the paint */
184 //  if (!DBIsSubcircuit(use->cu_def))
185     DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, hy->hy_target);
186 
187     /* Yank the labels */
188     tpath.tp_next = tpath.tp_first = labelBuf;
189     tpath.tp_last = &labelBuf[sizeof labelBuf - 2];
190     if (hy->hy_prefix)
191     {
192 	tpath.tp_next = DBPrintUseId(&scx, labelBuf, sizeof labelBuf - 3, FALSE);
193 	*tpath.tp_next++ = '/';
194     }
195     *tpath.tp_next = '\0';
196     (void) DBTreeSrLabels(&scx, &DBAllButSpaceBits, 0, &tpath, TF_LABEL_ATTACH,
197 		extHierLabelFunc, (ClientData) hy->hy_target->cu_def);
198 
199     return (0);
200 }
201 
202 int
extHierLabelFunc(scx,label,tpath,targetDef)203 extHierLabelFunc(scx, label, tpath, targetDef)
204     SearchContext *scx;
205     Label *label;
206     TerminalPath *tpath;
207     CellDef *targetDef;
208 {
209     char *srcp, *dstp;
210     Label *newlab;
211     int len;
212 
213     /* Reject if the label falls over space */
214     if (label->lab_type == TT_SPACE)
215 	return (0);
216 
217     /* Reject if not a node label */
218     if (!extLabType(label->lab_text, LABTYPE_NAME))
219 	return (0);
220 
221     /* Determine size of new label with hierarchical name */
222     for (srcp = label->lab_text; *srcp++; )
223 	/* Nothing */;
224     len = srcp - label->lab_text;
225     for (srcp = tpath->tp_first; *srcp++; )
226 	/* Nothing */;
227     len += srcp - tpath->tp_first + 1;
228 
229     /* Allocate new label at correct location */
230     newlab = (Label *) mallocMagic((unsigned) (sizeof (Label) + len - 4));
231     GeoTransRect(&scx->scx_trans, &label->lab_rect, &newlab->lab_rect);
232     newlab->lab_just = GeoTransPos(&scx->scx_trans, label->lab_just);
233     newlab->lab_type = label->lab_type;
234     newlab->lab_flags = label->lab_flags;
235     dstp = newlab->lab_text;
236     for (srcp = tpath->tp_first; *dstp++ = *srcp++; )
237 	/* Nothing */;
238     for (--dstp, srcp = label->lab_text; *dstp++ = *srcp++; )
239 	/* Nothing */;
240 
241     newlab->lab_next = targetDef->cd_labels;
242     targetDef->cd_labels = newlab;
243 
244     /* Add paint inside label if this is a subcircuit */
245     /* Caveat:  If label has zero area, it will be extended by 1 unit */
246 
247 //  if (label->lab_flags & PORT_DIR_MASK)
248 //  {
249 //	int pNum;
250 //
251 //	/* Is extending the label area valid in all cases? */
252 //	if (newlab->lab_rect.r_xbot == newlab->lab_rect.r_xtop)
253 //	    newlab->lab_rect.r_xtop++;
254 //	if (newlab->lab_rect.r_ybot == newlab->lab_rect.r_ytop)
255 //	    newlab->lab_rect.r_ytop++;
256 //
257 //	pNum = DBPlane(newlab->lab_type);
258 //	DBPaintPlane(targetDef->cd_planes[pNum], &newlab->lab_rect,
259 //		DBStdPaintTbl(newlab->lab_type, pNum),
260 //		(PaintUndoInfo *) NULL);
261 //  }
262 
263     return (0);
264 }
265