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