1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usredtecc.c
6 * User interface technology editor: interactive technology library editing
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "global.h"
33 #include "egraphics.h"
34 #include "efunction.h"
35 #include "edialogs.h"
36 #include "usr.h"
37 #include "drc.h"
38 #include "tecgen.h"
39 #include "tecart.h"
40 #include "usredtec.h"
41 #include "usrdiacom.h"
42
43 #define MAXNAMELEN 25 /* max chars in a new name */
44
45 INTBIG us_teceddrclayers = 0;
46 CHAR **us_teceddrclayernames = 0;
47
48 /* the known technology variables */
49 TECHVAR us_knownvars[] =
50 {
51 {x_("DRC_ecad_deck"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING|VISARRAY,
52 x_("Dracula design-rule deck")},
53 {x_("IO_cif_polypoints"), NOTECHVAR, 0, 0, 0.0, x_(""), VINTEGER,
54 x_("Maximum points in a CIF polygon")},
55 {x_("IO_cif_resolution"), NOTECHVAR, 0, 0, 0.0, x_(""), VINTEGER,
56 x_("Minimum resolution of CIF coordinates")},
57 {x_("IO_gds_polypoints"), NOTECHVAR, 0, 0, 0.0, x_(""), VINTEGER,
58 x_("Maximum points in a GDS-II polygon")},
59 {x_("SIM_spice_min_resistance"), NOTECHVAR, 0, 0, 0.0, x_(""), VFLOAT,
60 x_("Minimum resistance of SPICE elements")},
61 {x_("SIM_spice_min_capacitance"), NOTECHVAR, 0, 0, 0.0, x_(""), VFLOAT,
62 x_("Minimum capacitance of SPICE elements")},
63 {x_("SIM_spice_mask_scale"), NOTECHVAR, 0, 0, 0.0, x_(""), VFLOAT,
64 x_("Scaling factor for SPICE decks")},
65 {x_("SIM_spice_header_level1"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING|VISARRAY,
66 x_("Level 1 header for SPICE decks")},
67 {x_("SIM_spice_header_level2"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING|VISARRAY,
68 x_("Level 2 header for SPICE decks")},
69 {x_("SIM_spice_header_level3"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING|VISARRAY,
70 x_("Level 3 header for SPICE decks")},
71 {x_("SIM_spice_model_file"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING,
72 x_("Disk file with SPICE header cards")},
73 {x_("SIM_spice_trailer_file"), NOTECHVAR, 0, 0, 0.0, x_(""), VSTRING,
74 x_("Disk file with SPICE trailer cards")},
75 {NULL, NULL,0, 0, 0.0, NULL, 0, NULL} /* 0 */
76 };
77
78 /* these must correspond to the layer functions in "efunction.h" */
79 LIST us_teclayer_functions[] =
80 {
81 {x_("unknown"), x_("LFUNKNOWN"), LFUNKNOWN},
82 {x_("metal-1"), x_("LFMETAL1"), LFMETAL1},
83 {x_("metal-2"), x_("LFMETAL2"), LFMETAL2},
84 {x_("metal-3"), x_("LFMETAL3"), LFMETAL3},
85 {x_("metal-4"), x_("LFMETAL4"), LFMETAL4},
86 {x_("metal-5"), x_("LFMETAL5"), LFMETAL5},
87 {x_("metal-6"), x_("LFMETAL6"), LFMETAL6},
88 {x_("metal-7"), x_("LFMETAL7"), LFMETAL7},
89 {x_("metal-8"), x_("LFMETAL8"), LFMETAL8},
90 {x_("metal-9"), x_("LFMETAL9"), LFMETAL9},
91 {x_("metal-10"), x_("LFMETAL10"), LFMETAL10},
92 {x_("metal-11"), x_("LFMETAL11"), LFMETAL11},
93 {x_("metal-12"), x_("LFMETAL12"), LFMETAL12},
94 {x_("poly-1"), x_("LFPOLY1"), LFPOLY1},
95 {x_("poly-2"), x_("LFPOLY2"), LFPOLY2},
96 {x_("poly-3"), x_("LFPOLY3"), LFPOLY3},
97 {x_("gate"), x_("LFGATE"), LFGATE},
98 {x_("diffusion"), x_("LFDIFF"), LFDIFF},
99 {x_("implant"), x_("LFIMPLANT"), LFIMPLANT},
100 {x_("contact-1"), x_("LFCONTACT1"), LFCONTACT1},
101 {x_("contact-2"), x_("LFCONTACT2"), LFCONTACT2},
102 {x_("contact-3"), x_("LFCONTACT3"), LFCONTACT3},
103 {x_("contact-4"), x_("LFCONTACT4"), LFCONTACT4},
104 {x_("contact-5"), x_("LFCONTACT5"), LFCONTACT5},
105 {x_("contact-6"), x_("LFCONTACT6"), LFCONTACT6},
106 {x_("contact-7"), x_("LFCONTACT7"), LFCONTACT7},
107 {x_("contact-8"), x_("LFCONTACT8"), LFCONTACT8},
108 {x_("contact-9"), x_("LFCONTACT9"), LFCONTACT9},
109 {x_("contact-10"), x_("LFCONTACT10"), LFCONTACT10},
110 {x_("contact-11"), x_("LFCONTACT11"), LFCONTACT11},
111 {x_("contact-12"), x_("LFCONTACT12"), LFCONTACT12},
112 {x_("plug"), x_("LFPLUG"), LFPLUG},
113 {x_("overglass"), x_("LFOVERGLASS"), LFOVERGLASS},
114 {x_("resistor"), x_("LFRESISTOR"), LFRESISTOR},
115 {x_("capacitor"), x_("LFCAP"), LFCAP},
116 {x_("transistor"), x_("LFTRANSISTOR"), LFTRANSISTOR},
117 {x_("emitter"), x_("LFEMITTER"), LFEMITTER},
118 {x_("base"), x_("LFBASE"), LFBASE},
119 {x_("collector"), x_("LFCOLLECTOR"), LFCOLLECTOR},
120 {x_("substrate"), x_("LFSUBSTRATE"), LFSUBSTRATE},
121 {x_("well"), x_("LFWELL"), LFWELL},
122 {x_("guard"), x_("LFGUARD"), LFGUARD},
123 {x_("isolation"), x_("LFISOLATION"), LFISOLATION},
124 {x_("bus"), x_("LFBUS"), LFBUS},
125 {x_("art"), x_("LFART"), LFART},
126 {x_("control"), x_("LFCONTROL"), LFCONTROL},
127
128 {x_("p-type"), x_("LFPTYPE"), LFPTYPE},
129 {x_("n-type"), x_("LFNTYPE"), LFNTYPE},
130 {x_("depletion"), x_("LFDEPLETION"), LFDEPLETION},
131 {x_("enhancement"), x_("LFENHANCEMENT"), LFENHANCEMENT},
132 {x_("light"), x_("LFLIGHT"), LFLIGHT},
133 {x_("heavy"), x_("LFHEAVY"), LFHEAVY},
134 {x_("pseudo"), x_("LFPSEUDO"), LFPSEUDO},
135 {x_("nonelectrical"), x_("LFNONELEC"), LFNONELEC},
136 {x_("connects-metal"), x_("LFCONMETAL"), LFCONMETAL},
137 {x_("connects-poly"), x_("LFCONPOLY"), LFCONPOLY},
138 {x_("connects-diff"), x_("LFCONDIFF"), LFCONDIFF},
139 {x_("inside-transistor"), x_("LFINTRANS"), LFINTRANS},
140 {NULL, NULL, 0}
141 };
142
143 /* these must correspond to the layer functions in "efunction.h" */
144 LIST us_tecarc_functions[] =
145 {
146 {x_("unknown"), x_("APUNKNOWN"), APUNKNOWN},
147 {x_("metal-1"), x_("APMETAL1"), APMETAL1},
148 {x_("metal-2"), x_("APMETAL2"), APMETAL2},
149 {x_("metal-3"), x_("APMETAL3"), APMETAL3},
150 {x_("metal-4"), x_("APMETAL4"), APMETAL4},
151 {x_("metal-5"), x_("APMETAL5"), APMETAL5},
152 {x_("metal-6"), x_("APMETAL6"), APMETAL6},
153 {x_("metal-7"), x_("APMETAL7"), APMETAL7},
154 {x_("metal-8"), x_("APMETAL8"), APMETAL8},
155 {x_("metal-9"), x_("APMETAL9"), APMETAL9},
156 {x_("metal-10"), x_("APMETAL10"), APMETAL10},
157 {x_("metal-11"), x_("APMETAL11"), APMETAL11},
158 {x_("metal-12"), x_("APMETAL12"), APMETAL12},
159 {x_("polysilicon-1"), x_("APPOLY1"), APPOLY1},
160 {x_("polysilicon-2"), x_("APPOLY2"), APPOLY2},
161 {x_("polysilicon-3"), x_("APPOLY3"), APPOLY3},
162 {x_("diffusion"), x_("APDIFF"), APDIFF},
163 {x_("p-Diffusion"), x_("APDIFFP"), APDIFFP},
164 {x_("n-Diffusion"), x_("APDIFFN"), APDIFFN},
165 {x_("substrate-Diffusion"), x_("APDIFFS"), APDIFFS},
166 {x_("well-Diffusion"), x_("APDIFFW"), APDIFFW},
167 {x_("bus"), x_("APBUS"), APBUS},
168 {x_("unrouted"), x_("APUNROUTED"), APUNROUTED},
169 {x_("nonelectrical"), x_("APNONELEC"), APNONELEC},
170 {NULL, NULL, 0}
171 };
172
173 static GRAPHICS us_edtechigh = {LAYERH, HIGHLIT, SOLIDC, SOLIDC,
174 {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
175 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
176
177 /* prototypes for local routines */
178 static void us_teceditdrc(void);
179 static void us_teceditcolormap(void);
180 static void us_teceditcreat(INTBIG, CHAR*[]);
181 static void us_teceditidentify(BOOLEAN);
182 static void us_teceditinquire(void);
183 static void us_teceditmodobject(INTBIG, CHAR*[]);
184 static void us_tecedlayer3dheight(NODEINST*, INTBIG, CHAR*[]);
185 static void us_tecedlayer3dthick(NODEINST*, INTBIG, CHAR*[]);
186 static void us_tecedlayerprintcol(NODEINST*, INTBIG, CHAR*[]);
187 static void us_tecedlayercolor(NODEINST*, INTBIG, CHAR*[]);
188 static void us_tecedlayerdrcminwid(NODEINST*, INTBIG, CHAR*[]);
189 static void us_tecedlayerstyle(NODEINST*, INTBIG, CHAR*[]);
190 static void us_tecedlayercif(NODEINST*, INTBIG, CHAR*[]);
191 static void us_tecedlayerdxf(NODEINST*, INTBIG, CHAR*[]);
192 static void us_tecedlayergds(NODEINST*, INTBIG, CHAR*[]);
193 static void us_tecedlayerspires(NODEINST*, INTBIG, CHAR*[]);
194 static void us_tecedlayerspicap(NODEINST*, INTBIG, CHAR*[]);
195 static void us_tecedlayerspiecap(NODEINST*, INTBIG, CHAR*[]);
196 static void us_tecedlayerfunction(NODEINST*, INTBIG, CHAR*[]);
197 static void us_tecedlayerletters(NODEINST*, INTBIG, CHAR*[]);
198 static void us_tecedlayerpatterncontrol(NODEINST*, INTBIG, CHAR*[]);
199 static void us_tecedlayerpattern(NODEINST*);
200 static void us_tecedlayertype(NODEINST*, INTBIG, CHAR*[]);
201 static void us_tecedmodport(NODEINST*, INTBIG, CHAR*[]);
202 static void us_tecedarcfunction(NODEINST*, INTBIG, CHAR*[]);
203 static void us_tecedarcfixang(NODEINST*, INTBIG, CHAR*[]);
204 static void us_tecedarcwipes(NODEINST*, INTBIG, CHAR*[]);
205 static void us_tecedarcnoextend(NODEINST*, INTBIG, CHAR*[]);
206 static void us_tecedarcinc(NODEINST*, INTBIG, CHAR*[]);
207 static void us_tecednodefunction(NODEINST*, INTBIG, CHAR*[]);
208 static void us_tecednodeserpentine(NODEINST*, INTBIG, CHAR*[]);
209 static void us_tecednodesquare(NODEINST*, INTBIG, CHAR*[]);
210 static void us_tecednodewipes(NODEINST*, INTBIG, CHAR*[]);
211 static void us_tecednodelockable(NODEINST*, INTBIG, CHAR*[]);
212 static void us_tecednodemulticut(NODEINST*, INTBIG, CHAR*[]);
213 static void us_tecedinfolambda(NODEINST*, INTBIG, CHAR*[]);
214 static void us_tecedinfodescript(NODEINST*, INTBIG, CHAR*[]);
215 static void us_tecedsetnode(NODEINST*, CHAR*);
216 static NODEPROTO *us_tecedentercell(CHAR*);
217 static void us_tecedredolayergraphics(NODEPROTO*);
218 static void us_tecedloadlibmap(LIBRARY*);
219 static INTBIG us_teceditparsefun(CHAR*);
220 static BOOLEAN us_tecedgetdrc(CHAR *str, BOOLEAN *connected, BOOLEAN *wide, BOOLEAN *multi,
221 INTBIG *widrule, BOOLEAN *edge, INTBIG *amt, INTBIG *layer1, INTBIG *layer2,
222 CHAR **rule, INTBIG maxlayers, CHAR **layernames);
223 static void us_tecedrenamesequence(CHAR *varname, CHAR *oldname, CHAR *newname);
224 static void us_reorderprimdlog(CHAR *type, CHAR *prefix, CHAR *varname);
225 static NODEINST *us_tecedlayersetpattern(NODEINST *ni, INTSML color);
226 static INTSML us_tecedlayergetpattern(NODEINST *ni);
227 static void us_teceditsetlayerpattern(NODEPROTO *np, GRAPHICS *desc);
228
229 /*
230 * the entry routine for all technology editing
231 */
us_tecedentry(INTBIG count,CHAR * par[])232 void us_tecedentry(INTBIG count, CHAR *par[])
233 {
234 REGISTER TECHNOLOGY *tech;
235 REGISTER LIBRARY *lib;
236 LIBRARY **dependentlibs;
237 NODEPROTO **sequence;
238 REGISTER CHAR *pp, **dependentlist;
239 CHAR *cellname, *newpar[2];
240 UINTSML stip[16];
241 REGISTER INTBIG i, l;
242 REGISTER INTBIG dependentlibcount;
243 REGISTER NODEPROTO *np;
244 REGISTER VARIABLE *var;
245 REGISTER void *infstr;
246
247 if (count == 0)
248 {
249 ttyputusage(x_("technology edit OPTION"));
250 return;
251 }
252
253 l = estrlen(pp = par[0]);
254 if (namesamen(pp, x_("library-to-tech-and-c"), l) == 0 && l >= 21)
255 {
256 if (count <= 1) pp = 0; else
257 pp = par[1];
258 us_tecfromlibinit(el_curlib, pp, 1);
259 return;
260 }
261 if (namesamen(pp, x_("library-to-tech-and-java"), l) == 0 && l >= 21)
262 {
263 if (count <= 1) pp = 0; else
264 pp = par[1];
265 us_tecfromlibinit(el_curlib, pp, -1);
266 return;
267 }
268 if (namesamen(pp, x_("library-to-tech"), l) == 0)
269 {
270 if (count <= 1) pp = 0; else
271 pp = par[1];
272 us_tecfromlibinit(el_curlib, pp, 0);
273 return;
274 }
275 if (namesamen(pp, x_("tech-to-library"), l) == 0)
276 {
277 if (count == 1) tech = el_curtech; else
278 {
279 tech = gettechnology(par[1]);
280 if (tech == NOTECHNOLOGY)
281 {
282 us_abortcommand(_("Technology '%s' unknown"), par[1]);
283 return;
284 }
285 }
286 if ((tech->userbits&NONSTANDARD) != 0)
287 {
288 us_abortcommand(_("Cannot convert technology '%s', it is nonstandard"), tech->techname);
289 return;
290 }
291
292 /* see if there is already such a library */
293 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
294 if (namesame(lib->libname, tech->techname) == 0) break;
295 if (lib != NOLIBRARY)
296 ttyputmsg(_("Already a library called %s, using that"), lib->libname); else
297 lib = us_tecedmakelibfromtech(tech);
298 if (lib != NOLIBRARY)
299 {
300 newpar[0] = x_("use");
301 newpar[1] = lib->libname;
302 us_library(2, newpar);
303 us_tecedloadlibmap(lib);
304 }
305 return;
306 }
307 if (namesamen(pp, x_("reorder-arcs"), l) == 0 && l >= 9)
308 {
309 us_reorderprimdlog(_("Arcs"), x_("arc-"), x_("EDTEC_arcsequence"));
310 return;
311 }
312 if (namesamen(pp, x_("reorder-nodes"), l) == 0 && l >= 9)
313 {
314 us_reorderprimdlog(_("Nodes"), x_("node-"), x_("EDTEC_nodesequence"));
315 return;
316 }
317 if (namesamen(pp, x_("reorder-layers"), l) == 0 && l >= 9)
318 {
319 us_reorderprimdlog(_("Layers"), x_("layer-"), x_("EDTEC_layersequence"));
320 return;
321 }
322 if (namesamen(pp, x_("inquire-layer"), l) == 0 && l >= 2)
323 {
324 us_teceditinquire();
325 return;
326 }
327 if (namesamen(pp, x_("place-layer"), l) == 0)
328 {
329 if (count < 2)
330 {
331 ttyputusage(x_("technology edit place-layer SHAPE"));
332 return;
333 }
334
335 us_teceditcreat(count-1, &par[1]);
336 return;
337 }
338 if (namesamen(pp, x_("change"), l) == 0 && l >= 2)
339 {
340 /* in outline edit, create a point */
341 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
342 {
343 newpar[0] = x_("trace");
344 newpar[1] = x_("add-point");
345 us_node(2, newpar);
346 return;
347 }
348
349 us_teceditmodobject(count-1, &par[1]);
350 return;
351 }
352 if (namesamen(pp, x_("edit-node"), l) == 0 && l >= 6)
353 {
354 if (count < 2)
355 {
356 ttyputusage(x_("technology edit edit-node NODENAME"));
357 return;
358 }
359 infstr = initinfstr();
360 addstringtoinfstr(infstr, x_("node-"));
361 addstringtoinfstr(infstr, par[1]);
362 (void)allocstring(&cellname, returninfstr(infstr), el_tempcluster);
363
364 /* first make sure all fields exist */
365 np = getnodeproto(cellname);
366 if (np != NONODEPROTO)
367 {
368 us_tecedmakenode(np, NPUNKNOWN, FALSE, FALSE, FALSE, FALSE, 0);
369 (*el_curconstraint->solve)(np);
370 }
371
372 np = us_tecedentercell(cellname);
373 efree(cellname);
374 if (np == NONODEPROTO) return;
375 us_tecedmakenode(np, NPUNKNOWN, FALSE, FALSE, FALSE, FALSE, 0);
376 (*el_curconstraint->solve)(np);
377 np->userbits |= TECEDITCELL;
378 (void)us_tecedentercell(describenodeproto(np));
379 return;
380 }
381 if (namesamen(pp, x_("edit-arc"), l) == 0 && l >= 6)
382 {
383 if (count < 2)
384 {
385 ttyputusage(x_("technology edit edit-arc ARCNAME"));
386 return;
387 }
388 infstr = initinfstr();
389 addstringtoinfstr(infstr, x_("arc-"));
390 addstringtoinfstr(infstr, par[1]);
391 (void)allocstring(&cellname, returninfstr(infstr), el_tempcluster);
392 np = us_tecedentercell(cellname);
393 efree(cellname);
394 if (np == NONODEPROTO) return;
395 us_tecedmakearc(np, APUNKNOWN, 1, 1, 0, 90);
396 (*el_curconstraint->solve)(np);
397 np->userbits |= TECEDITCELL;
398 (void)us_tecedentercell(describenodeproto(np));
399 return;
400 }
401 if (namesamen(pp, x_("edit-layer"), l) == 0 && l >= 6)
402 {
403 if (count < 2)
404 {
405 ttyputusage(x_("technology edit edit-layer LAYERNAME"));
406 return;
407 }
408 infstr = initinfstr();
409 addstringtoinfstr(infstr, x_("layer-"));
410 addstringtoinfstr(infstr, par[1]);
411 (void)allocstring(&cellname, returninfstr(infstr), el_tempcluster);
412
413 /* first make sure all fields exist */
414 for(i=0; i<16; i++) stip[i] = 0;
415 np = getnodeproto(cellname);
416 if (np != NONODEPROTO)
417 {
418 us_tecedmakelayer(np, COLORT1, stip, SOLIDC, x_("XX"), LFUNKNOWN, x_("x"), x_(""),
419 x_(""), 0.0, 0.0, 0.0, 0, 0, 0);
420 (*el_curconstraint->solve)(np);
421 }
422
423 np = us_tecedentercell(cellname);
424 efree(cellname);
425 if (np == NONODEPROTO) return;
426 us_tecedmakelayer(np, COLORT1, stip, SOLIDC, x_("XX"), LFUNKNOWN, x_("x"), x_(""),
427 x_(""), 0.0, 0.0, 0.0, 0, 0, 0);
428 (*el_curconstraint->solve)(np);
429 np->userbits |= TECEDITCELL;
430 (void)us_tecedentercell(describenodeproto(np));
431 return;
432 }
433 if (namesamen(pp, x_("edit-subsequent"), l) == 0 && l >= 6)
434 {
435 np = us_needcell();
436 if (np == NONODEPROTO) return;
437 if (namesamen(np->protoname, x_("node-"), 5) == 0)
438 {
439 dependentlibcount = us_teceditgetdependents(el_curlib, &dependentlibs);
440 i = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("node-"),
441 x_("EDTEC_nodesequence"), &sequence);
442 if (i == 0) return;
443 for(l=0; l<i; l++) if (sequence[l] == np)
444 {
445 if (l == i-1) np = sequence[0]; else np = sequence[l+1];
446 (void)us_tecedentercell(describenodeproto(np));
447 break;
448 }
449 efree((CHAR *)sequence);
450 return;
451 }
452 if (namesamen(np->protoname, x_("arc-"), 4) == 0)
453 {
454 dependentlibcount = us_teceditgetdependents(el_curlib, &dependentlibs);
455 i = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("arc-"),
456 x_("EDTEC_arcsequence"), &sequence);
457 if (i == 0) return;
458 for(l=0; l<i; l++) if (sequence[l] == np)
459 {
460 if (l == i-1) np = sequence[0]; else np = sequence[l+1];
461 (void)us_tecedentercell(describenodeproto(np));
462 break;
463 }
464 efree((CHAR *)sequence);
465 return;
466 }
467 if (namesamen(np->protoname, x_("layer-"), 6) == 0)
468 {
469 dependentlibcount = us_teceditgetdependents(el_curlib, &dependentlibs);
470 i = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("layer-"),
471 x_("EDTEC_layersequence"), &sequence);
472 if (i == 0) return;
473 for(l=0; l<i; l++) if (sequence[l] == np)
474 {
475 if (l == i-1) np = sequence[0]; else np = sequence[l+1];
476 (void)us_tecedentercell(describenodeproto(np));
477 break;
478 }
479 efree((CHAR *)sequence);
480 return;
481 }
482 ttyputerr(_("Must be editing a layer, node, or arc to advance to the next"));
483 return;
484 }
485 if (namesamen(pp, x_("edit-colors"), l) == 0 && l >= 6)
486 {
487 us_teceditcolormap();
488 return;
489 }
490 if (namesamen(pp, x_("edit-design-rules"), l) == 0 && l >= 6)
491 {
492 us_teceditdrc();
493 return;
494 }
495 if (namesamen(pp, x_("edit-misc-information"), l) == 0 && l >= 6)
496 {
497 /* first make sure all fields exist */
498 np = getnodeproto(x_("factors"));
499 if (np != NONODEPROTO)
500 {
501 us_tecedmakeinfo(np, 2000, el_curlib->libname);
502 (*el_curconstraint->solve)(np);
503 }
504
505 /* now edit the cell */
506 np = us_tecedentercell(x_("factors"));
507 if (np == NONODEPROTO) return;
508 us_tecedmakeinfo(np, 2000, el_curlib->libname);
509 (*el_curconstraint->solve)(np);
510 (void)us_tecedentercell(describenodeproto(np));
511 return;
512 }
513 if (namesamen(pp, x_("identify-layers"), l) == 0 && l >= 10)
514 {
515 us_teceditidentify(FALSE);
516 return;
517 }
518 if (namesamen(pp, x_("identify-ports"), l) == 0 && l >= 10)
519 {
520 us_teceditidentify(TRUE);
521 return;
522 }
523 if (namesamen(pp, x_("dependent-libraries"), l) == 0 && l >= 2)
524 {
525 if (count < 2)
526 {
527 /* display dependent library names */
528 var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_dependent_libraries"));
529 if (var == NOVARIABLE) ttyputmsg(_("There are no dependent libraries")); else
530 {
531 i = getlength(var);
532 ttyputmsg(_("%ld dependent %s:"), i, makeplural(x_("library"), i));
533 for(l=0; l<i; l++)
534 {
535 pp = ((CHAR **)var->addr)[l];
536 lib = getlibrary(pp);
537 ttyputmsg(x_(" %s%s"), pp, (lib == NOLIBRARY ? _(" (not read in)") : x_("")));
538 }
539 }
540 return;
541 }
542
543 /* clear list if just "-" is given */
544 if (count == 2 && estrcmp(par[1], x_("-")) == 0)
545 {
546 var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_dependent_libraries"));
547 if (var != NOVARIABLE)
548 (void)delval((INTBIG)el_curlib, VLIBRARY, x_("EDTEC_dependent_libraries"));
549 return;
550 }
551
552 /* create a list */
553 dependentlist = (CHAR **)emalloc((count-1) * (sizeof (CHAR *)), el_tempcluster);
554 if (dependentlist == 0) return;
555 for(i=1; i<count; i++) dependentlist[i-1] = par[i];
556 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("EDTEC_dependent_libraries"), (INTBIG)dependentlist,
557 VSTRING|VISARRAY|((count-1)<<VLENGTHSH));
558 efree((CHAR *)dependentlist);
559 return;
560 }
561 if (namesamen(pp, x_("compact-current-cell"), l) == 0 && l >= 2)
562 {
563 if (el_curwindowpart == NOWINDOWPART) np = NONODEPROTO; else
564 np = el_curwindowpart->curnodeproto;
565 if (np != NONODEPROTO) us_tecedcompact(np); else
566 ttyputmsg(_("No current cell to compact"));
567 return;
568 }
569 ttyputbadusage(x_("technology edit"));
570 }
571
572 /*
573 * Routine to compact the current technology-edit cell
574 */
us_tecedcompact(NODEPROTO * cell)575 void us_tecedcompact(NODEPROTO *cell)
576 {
577 REGISTER EXAMPLE *nelist, *ne;
578 REGISTER SAMPLE *ns;
579 REGISTER BOOLEAN first;
580 REGISTER INTBIG i, numexamples, xoff, yoff, examplenum, leftheight, height,
581 lx, hx, ly, hy, topy, separation;
582 REGISTER NODEINST *ni;
583
584 if (namesame(cell->protoname, x_("factors")) == 0)
585 {
586 /* save highlighting */
587 us_pushhighlight();
588 us_clearhighlightcount();
589
590 /* move the option text */
591 us_tecedfindspecialtext(cell, us_tecedmisctexttable);
592 for(i=0; us_tecedmisctexttable[i].funct != 0; i++)
593 {
594 ni = us_tecedmisctexttable[i].ni;
595 if (ni == NONODEINST) continue;
596 xoff = us_tecedmisctexttable[i].x - (ni->lowx + ni->highx) / 2;
597 yoff = us_tecedmisctexttable[i].y - (ni->lowy + ni->highy) / 2;
598 if (xoff == 0 && yoff == 0) continue;
599 startobjectchange((INTBIG)ni, VNODEINST);
600 modifynodeinst(ni, xoff, yoff, xoff, yoff, 0, 0);
601 endobjectchange((INTBIG)ni, VNODEINST);
602 }
603 us_pophighlight(FALSE);
604 return;
605 }
606 if (namesamen(cell->protoname, x_("layer-"), 6) == 0)
607 {
608 ttyputmsg("Cannot compact technology-edit layer cells");
609 return;
610 }
611 if (namesamen(cell->protoname, x_("arc-"), 4) == 0)
612 {
613 /* save highlighting */
614 us_pushhighlight();
615 us_clearhighlightcount();
616
617 /* move the option text */
618 us_tecedfindspecialtext(cell, us_tecedarctexttable);
619 for(i=0; us_tecedarctexttable[i].funct != 0; i++)
620 {
621 ni = us_tecedarctexttable[i].ni;
622 if (ni == NONODEINST) continue;
623 xoff = us_tecedarctexttable[i].x - (ni->lowx + ni->highx) / 2;
624 yoff = us_tecedarctexttable[i].y - (ni->lowy + ni->highy) / 2;
625 if (xoff == 0 && yoff == 0) continue;
626 startobjectchange((INTBIG)ni, VNODEINST);
627 modifynodeinst(ni, xoff, yoff, xoff, yoff, 0, 0);
628 endobjectchange((INTBIG)ni, VNODEINST);
629 }
630
631 /* compute bounds of arc contents */
632 first = TRUE;
633 for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
634 {
635 /* ignore the special text nodes */
636 for(i=0; us_tecedarctexttable[i].funct != 0; i++)
637 if (us_tecedarctexttable[i].ni == ni) break;
638 if (us_tecedarctexttable[i].funct != 0) continue;
639
640 if (first)
641 {
642 first = FALSE;
643 lx = ni->lowx; hx = ni->highx;
644 ly = ni->lowy; hy = ni->highy;
645 } else
646 {
647 if (ni->lowx < lx) lx = ni->lowx;
648 if (ni->highx > hx) hx = ni->highx;
649 if (ni->lowy < ly) ly = ni->lowy;
650 if (ni->highy > hy) hy = ni->highy;
651 }
652 }
653
654 /* now rearrange the geometry */
655 if (!first)
656 {
657 xoff = -(lx + hx) / 2;
658 yoff = -hy;
659 if (xoff != 0 || yoff != 0)
660 {
661 for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
662 {
663 /* ignore the special text nodes */
664 for(i=0; us_tecedarctexttable[i].funct != 0; i++)
665 if (us_tecedarctexttable[i].ni == ni) break;
666 if (us_tecedarctexttable[i].funct != 0) continue;
667
668 startobjectchange((INTBIG)ni, VNODEINST);
669 modifynodeinst(ni, xoff, yoff, xoff, yoff, 0, 0);
670 endobjectchange((INTBIG)ni, VNODEINST);
671 }
672 }
673 }
674 us_pophighlight(FALSE);
675 return;
676 }
677 if (namesamen(cell->protoname, x_("node-"), 5) == 0)
678 {
679 /* save highlighting */
680 us_pushhighlight();
681 us_clearhighlightcount();
682
683 /* move the option text */
684 us_tecedfindspecialtext(cell, us_tecednodetexttable);
685 for(i=0; us_tecednodetexttable[i].funct != 0; i++)
686 {
687 ni = us_tecednodetexttable[i].ni;
688 if (ni == NONODEINST) continue;
689 xoff = us_tecednodetexttable[i].x - (ni->lowx + ni->highx) / 2;
690 yoff = us_tecednodetexttable[i].y - (ni->lowy + ni->highy) / 2;
691 if (xoff == 0 && yoff == 0) continue;
692 startobjectchange((INTBIG)ni, VNODEINST);
693 modifynodeinst(ni, xoff, yoff, xoff, yoff, 0, 0);
694 endobjectchange((INTBIG)ni, VNODEINST);
695 }
696
697 /* move the examples */
698 nelist = us_tecedgetexamples(cell, TRUE);
699 if (nelist == NOEXAMPLE) return;
700 numexamples = 0;
701 for(ne = nelist; ne != NOEXAMPLE; ne = ne->nextexample) numexamples++;
702 examplenum = 0;
703 topy = 0;
704 separation = mini(nelist->hx - nelist->lx, nelist->hy - nelist->ly);
705 for(ne = nelist; ne != NOEXAMPLE; ne = ne->nextexample)
706 {
707 /* handle left or right side */
708 yoff = topy - ne->hy;
709 if ((examplenum&1) == 0)
710 {
711 /* do left side */
712 if (examplenum == numexamples-1)
713 {
714 /* last one is centered */
715 xoff = -(ne->lx + ne->hx) / 2;
716 } else
717 {
718 xoff = -ne->hx - separation/2;
719 }
720 leftheight = ne->hy - ne->ly;
721 } else
722 {
723 /* do right side */
724 xoff = -ne->lx + separation/2;
725 height = ne->hy - ne->ly;
726 if (leftheight > height) height = leftheight;
727 topy -= height + separation;
728 }
729 examplenum++;
730
731 /* adjust every node in the example */
732 if (xoff == 0 && yoff == 0) continue;
733 for(ns = ne->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
734 {
735 ni = ns->node;
736 startobjectchange((INTBIG)ni, VNODEINST);
737 modifynodeinst(ni, xoff, yoff, xoff, yoff, 0, 0);
738 endobjectchange((INTBIG)ni, VNODEINST);
739 }
740 }
741 us_tecedfreeexamples(nelist);
742 us_pophighlight(FALSE);
743 return;
744 }
745 ttyputmsg(_("Cannot compact technology-edit cell %s: unknown type"),
746 describenodeproto(cell));
747 }
748
749 /*
750 * Routine for editing the DRC tables.
751 */
us_teceditdrc(void)752 void us_teceditdrc(void)
753 {
754 REGISTER INTBIG i, changed, nodecount;
755 NODEPROTO **nodesequence;
756 LIBRARY *liblist[1];
757 REGISTER VARIABLE *var;
758 REGISTER DRCRULES *rules;
759
760 /* get the current list of layer and node names */
761 us_tecedgetlayernamelist();
762 liblist[0] = el_curlib;
763 nodecount = us_teceditfindsequence(liblist, 1, x_("node-"), x_("EDTEC_nodesequence"), &nodesequence);
764
765 /* create a RULES structure */
766 rules = dr_allocaterules(us_teceddrclayers, nodecount, x_("EDITED TECHNOLOGY"));
767 if (rules == NODRCRULES) return;
768 for(i=0; i<us_teceddrclayers; i++)
769 (void)allocstring(&rules->layernames[i], us_teceddrclayernames[i], el_tempcluster);
770 for(i=0; i<nodecount; i++)
771 (void)allocstring(&rules->nodenames[i], &nodesequence[i]->protoname[5], el_tempcluster);
772 if (nodecount > 0) efree((CHAR *)nodesequence);
773
774 /* get the text-list of design rules and convert them into arrays */
775 var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_DRC"));
776 us_teceditgetdrcarrays(var, rules);
777
778 /* edit the design-rule arrays */
779 changed = dr_rulesdlog(NOTECHNOLOGY, rules);
780
781 /* if changes were made, convert the arrays back into a text-list */
782 if (changed != 0)
783 {
784 us_tecedloaddrcmessage(rules, el_curlib);
785 }
786
787 /* free the arrays */
788 dr_freerules(rules);
789 }
790
791 /*
792 * Routine to update tables to reflect that cell "oldname" is now called "newname".
793 * If "newname" is not valid, any rule that refers to "oldname" is removed.
794 *
795 */
us_tecedrenamecell(CHAR * oldname,CHAR * newname)796 void us_tecedrenamecell(CHAR *oldname, CHAR *newname)
797 {
798 REGISTER VARIABLE *var;
799 REGISTER INTBIG i, len;
800 REGISTER BOOLEAN valid;
801 INTBIG count;
802 REGISTER CHAR *origstr, *firstkeyword, *keyword;
803 CHAR *str, **strings;
804 REGISTER void *infstr, *sa;
805
806 /* if this is a layer, rename the layer sequence array */
807 if (namesamen(oldname, x_("layer-"), 6) == 0 && namesamen(newname, x_("layer-"), 6) == 0)
808 {
809 us_tecedrenamesequence(x_("EDTEC_layersequence"), &oldname[6], &newname[6]);
810 }
811
812 /* if this is an arc, rename the arc sequence array */
813 if (namesamen(oldname, x_("arc-"), 4) == 0 && namesamen(newname, x_("arc-"), 4) == 0)
814 {
815 us_tecedrenamesequence(x_("EDTEC_arcsequence"), &oldname[4], &newname[4]);
816 }
817
818 /* if this is a node, rename the node sequence array */
819 if (namesamen(oldname, x_("node-"), 5) == 0 && namesamen(newname, x_("node-"), 5) == 0)
820 {
821 us_tecedrenamesequence(x_("EDTEC_nodesequence"), &oldname[5], &newname[5]);
822 }
823
824 /* see if there are design rules in the current library */
825 var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_DRC"));
826 if (var == NOVARIABLE) return;
827
828 /* examine the rules and convert the name */
829 len = getlength(var);
830 sa = newstringarray(us_tool->cluster);
831 for(i=0; i<len; i++)
832 {
833 /* parse the DRC rule */
834 str = ((CHAR **)var->addr)[i];
835 origstr = str;
836 firstkeyword = getkeyword(&str, x_(" "));
837 if (firstkeyword == NOSTRING) return;
838
839 /* pass wide wire limitation through */
840 if (*firstkeyword == 'l')
841 {
842 addtostringarray(sa, origstr);
843 continue;
844 }
845
846 /* rename nodes in the minimum node size rule */
847 if (*firstkeyword == 'n')
848 {
849 if (namesamen(oldname, x_("node-"), 5) == 0 &&
850 namesame(&oldname[5], &firstkeyword[1]) == 0)
851 {
852 /* substitute the new name */
853 if (namesamen(newname, x_("node-"), 5) == 0)
854 {
855 infstr = initinfstr();
856 addstringtoinfstr(infstr, x_("n"));
857 addstringtoinfstr(infstr, &newname[5]);
858 addstringtoinfstr(infstr, str);
859 addtostringarray(sa, returninfstr(infstr));
860 }
861 continue;
862 }
863 addtostringarray(sa, origstr);
864 continue;
865 }
866
867 /* rename layers in the minimum layer size rule */
868 if (*firstkeyword == 's')
869 {
870 valid = TRUE;
871 infstr = initinfstr();
872 formatinfstr(infstr, x_("%s "), firstkeyword);
873 keyword = getkeyword(&str, x_(" "));
874 if (keyword == NOSTRING) return;
875 if (namesamen(oldname, x_("layer-"), 6) == 0 &&
876 namesame(&oldname[6], keyword) == 0)
877 {
878 if (namesamen(newname, x_("layer-"), 6) != 0) valid = FALSE; else
879 addstringtoinfstr(infstr, &newname[6]);
880 } else
881 addstringtoinfstr(infstr, keyword);
882 addstringtoinfstr(infstr, str);
883 str = returninfstr(infstr);
884 if (valid) addtostringarray(sa, str);
885 continue;
886 }
887
888 /* layer width rule: substitute layer names */
889 infstr = initinfstr();
890 formatinfstr(infstr, x_("%s "), firstkeyword);
891 valid = TRUE;
892
893 /* get the first layer name and convert it */
894 keyword = getkeyword(&str, x_(" "));
895 if (keyword == NOSTRING) return;
896 if (namesamen(oldname, x_("layer-"), 6) == 0 &&
897 namesame(&oldname[6], keyword) == 0)
898 {
899 /* substitute the new name */
900 if (namesamen(newname, x_("layer-"), 6) != 0) valid = FALSE; else
901 addstringtoinfstr(infstr, &newname[6]);
902 } else
903 addstringtoinfstr(infstr, keyword);
904 addtoinfstr(infstr, ' ');
905
906 /* get the second layer name and convert it */
907 keyword = getkeyword(&str, x_(" "));
908 if (keyword == NOSTRING) return;
909 if (namesamen(oldname, x_("layer-"), 6) == 0 &&
910 namesame(&oldname[6], keyword) == 0)
911 {
912 /* substitute the new name */
913 if (namesamen(newname, x_("layer-"), 6) != 0) valid = FALSE; else
914 addstringtoinfstr(infstr, &newname[6]);
915 } else
916 addstringtoinfstr(infstr, keyword);
917
918 addstringtoinfstr(infstr, str);
919 str = returninfstr(infstr);
920 if (valid) addtostringarray(sa, str);
921 }
922 strings = getstringarray(sa, &count);
923 setval((INTBIG)el_curlib, VLIBRARY, x_("EDTEC_DRC"), (INTBIG)strings,
924 VSTRING|VISARRAY|(count<<VLENGTHSH));
925 killstringarray(sa);
926 }
927
928 /*
929 * Routine to rename the layer/arc/node sequence arrays to account for a name change.
930 * The sequence array is in variable "varname", and the item has changed from "oldname" to
931 * "newname".
932 */
us_tecedrenamesequence(CHAR * varname,CHAR * oldname,CHAR * newname)933 void us_tecedrenamesequence(CHAR *varname, CHAR *oldname, CHAR *newname)
934 {
935 REGISTER VARIABLE *var;
936 CHAR **strings;
937 REGISTER INTBIG i, len;
938 INTBIG count;
939 void *sa;
940
941 var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, varname);
942 if (var == NOVARIABLE) return;
943
944 strings = (CHAR **)var->addr;
945 len = getlength(var);
946 sa = newstringarray(us_tool->cluster);
947 for(i=0; i<len; i++)
948 {
949 if (namesame(strings[i], oldname) == 0)
950 addtostringarray(sa, newname); else
951 addtostringarray(sa, strings[i]);
952 }
953 strings = getstringarray(sa, &count);
954 setval((INTBIG)el_curlib, VLIBRARY, varname, (INTBIG)strings,
955 VSTRING|VISARRAY|(count<<VLENGTHSH));
956 killstringarray(sa);
957 }
958
us_tecedgetlayernamelist(void)959 void us_tecedgetlayernamelist(void)
960 {
961 REGISTER INTBIG i, dependentlibcount;
962 REGISTER NODEPROTO *np;
963 NODEPROTO **sequence;
964 LIBRARY **dependentlibs;
965
966 /* free any former layer name information */
967 if (us_teceddrclayernames != 0)
968 {
969 for(i=0; i<us_teceddrclayers; i++) efree(us_teceddrclayernames[i]);
970 efree((CHAR *)us_teceddrclayernames);
971 us_teceddrclayernames = 0;
972 }
973
974 dependentlibcount = us_teceditgetdependents(el_curlib, &dependentlibs);
975 us_teceddrclayers = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("layer-"),
976 x_("EDTEC_layersequence"), &sequence);
977
978 /* build and fill array of layers for DRC parsing */
979 us_teceddrclayernames = (CHAR **)emalloc(us_teceddrclayers * (sizeof (CHAR *)), us_tool->cluster);
980 if (us_teceddrclayernames == 0) return;
981 for(i = 0; i<us_teceddrclayers; i++)
982 {
983 np = sequence[i];
984 (void)allocstring(&us_teceddrclayernames[i], &np->protoname[6], us_tool->cluster);
985 }
986 }
987
988 /*
989 * Routine to create arrays describing the design rules in the variable "var" (which is
990 * from "EDTEC_DRC" on a library). The arrays are stored in "rules".
991 */
us_teceditgetdrcarrays(VARIABLE * var,DRCRULES * rules)992 void us_teceditgetdrcarrays(VARIABLE *var, DRCRULES *rules)
993 {
994 REGISTER INTBIG i, l;
995 INTBIG amt;
996 BOOLEAN connected, wide, multi, edge;
997 INTBIG widrule, layer1, layer2, j;
998 REGISTER CHAR *str, *pt;
999 CHAR *rule;
1000
1001 /* get the design rules */
1002 if (var == NOVARIABLE) return;
1003
1004 l = getlength(var);
1005 for(i=0; i<l; i++)
1006 {
1007 /* parse the DRC rule */
1008 str = ((CHAR **)var->addr)[i];
1009 while (*str == ' ') str++;
1010 if (*str == 0) continue;
1011
1012 /* special case for node minimum size rule */
1013 if (*str == 'n')
1014 {
1015 str++;
1016 for(pt = str; *pt != 0; pt++) if (*pt == ' ') break;
1017 if (*pt == 0)
1018 {
1019 ttyputmsg(_("Bad node size rule (line %ld): %s"), i+1, str);
1020 continue;
1021 }
1022 *pt = 0;
1023 for(j=0; j<rules->numnodes; j++)
1024 if (namesame(str, rules->nodenames[j]) == 0) break;
1025 *pt = ' ';
1026 if (j >= rules->numnodes)
1027 {
1028 ttyputmsg(_("Unknown node (line %ld): %s"), i+1, str);
1029 continue;
1030 }
1031 while (*pt == ' ') pt++;
1032 rules->minnodesize[j*2] = atofr(pt);
1033 while (*pt != 0 && *pt != ' ') pt++;
1034 while (*pt == ' ') pt++;
1035 rules->minnodesize[j*2+1] = atofr(pt);
1036 while (*pt != 0 && *pt != ' ') pt++;
1037 while (*pt == ' ') pt++;
1038 if (*pt != 0) reallocstring(&rules->minnodesizeR[j], pt, el_tempcluster);
1039 continue;
1040 }
1041
1042 /* parse the layer rule */
1043 if (us_tecedgetdrc(str, &connected, &wide, &multi, &widrule, &edge,
1044 &amt, &layer1, &layer2, &rule, rules->numlayers, rules->layernames))
1045 {
1046 ttyputmsg(_("DRC line %ld is: %s"), i+1, str);
1047 continue;
1048 }
1049
1050 /* set the layer spacing */
1051 if (widrule == 1)
1052 {
1053 rules->minwidth[layer1] = amt;
1054 if (*rule != 0)
1055 (void)reallocstring(&rules->minwidthR[layer1], rule, el_tempcluster);
1056 } else if (widrule == 2)
1057 {
1058 rules->widelimit = amt;
1059 } else
1060 {
1061 if (layer1 > layer2) { j = layer1; layer1 = layer2; layer2 = j; }
1062 j = (layer1+1) * (layer1/2) + (layer1&1) * ((layer1+1)/2);
1063 j = layer2 + rules->numlayers * layer1 - j;
1064 if (edge)
1065 {
1066 rules->edgelist[j] = amt;
1067 if (*rule != 0)
1068 (void)reallocstring(&rules->edgelistR[j], rule, el_tempcluster);
1069 } else if (wide)
1070 {
1071 if (connected)
1072 {
1073 rules->conlistW[j] = amt;
1074 if (*rule != 0)
1075 (void)reallocstring(&rules->conlistWR[j], rule, el_tempcluster);
1076 } else
1077 {
1078 rules->unconlistW[j] = amt;
1079 if (*rule != 0)
1080 (void)reallocstring(&rules->unconlistWR[j], rule, el_tempcluster);
1081 }
1082 } else if (multi)
1083 {
1084 if (connected)
1085 {
1086 rules->conlistM[j] = amt;
1087 if (*rule != 0)
1088 (void)reallocstring(&rules->conlistMR[j], rule, el_tempcluster);
1089 } else
1090 {
1091 rules->unconlistM[j] = amt;
1092 if (*rule != 0)
1093 (void)reallocstring(&rules->unconlistMR[j], rule, el_tempcluster);
1094 }
1095 } else
1096 {
1097 if (connected)
1098 {
1099 rules->conlist[j] = amt;
1100 if (*rule != 0)
1101 (void)reallocstring(&rules->conlistR[j], rule, el_tempcluster);
1102 } else
1103 {
1104 rules->unconlist[j] = amt;
1105 if (*rule != 0)
1106 (void)reallocstring(&rules->unconlistR[j], rule, el_tempcluster);
1107 }
1108 }
1109 }
1110 }
1111 }
1112
1113 /*
1114 * routine to parse DRC line "str" and fill the factors "connected" (set nonzero
1115 * if rule is for connected layers), "amt" (rule distance), "layer1" and "layer2"
1116 * (the layers). Presumes that there are "maxlayers" layer names in the
1117 * array "layernames". Returns true on error.
1118 */
us_tecedgetdrc(CHAR * str,BOOLEAN * connected,BOOLEAN * wide,BOOLEAN * multi,INTBIG * widrule,BOOLEAN * edge,INTBIG * amt,INTBIG * layer1,INTBIG * layer2,CHAR ** rule,INTBIG maxlayers,CHAR ** layernames)1119 BOOLEAN us_tecedgetdrc(CHAR *str, BOOLEAN *connected, BOOLEAN *wide, BOOLEAN *multi, INTBIG *widrule,
1120 BOOLEAN *edge, INTBIG *amt, INTBIG *layer1, INTBIG *layer2, CHAR **rule, INTBIG maxlayers,
1121 CHAR **layernames)
1122 {
1123 REGISTER CHAR *pt;
1124 REGISTER INTBIG save;
1125
1126 *connected = *wide = *multi = *edge = FALSE;
1127 for( ; *str != 0; str++)
1128 {
1129 if (tolower(*str) == 'c')
1130 {
1131 *connected = TRUE;
1132 continue;
1133 }
1134 if (tolower(*str) == 'w')
1135 {
1136 *wide = TRUE;
1137 continue;
1138 }
1139 if (tolower(*str) == 'm')
1140 {
1141 *multi = TRUE;
1142 continue;
1143 }
1144 if (tolower(*str) == 'e')
1145 {
1146 *edge = TRUE;
1147 continue;
1148 }
1149 break;
1150 }
1151 *widrule = 0;
1152 if (tolower(*str) == 's')
1153 {
1154 *widrule = 1;
1155 str++;
1156 } else if (tolower(*str) == 'l')
1157 {
1158 *widrule = 2;
1159 str++;
1160 }
1161
1162 /* get the distance */
1163 pt = str;
1164 while (*pt != 0 && *pt != ' ' && *pt != '\t') pt++;
1165 while (*pt == ' ' || *pt == '\t') pt++;
1166 *amt = atofr(str);
1167
1168 /* get the first layer */
1169 if (*widrule != 2)
1170 {
1171 str = pt;
1172 if (*str == 0)
1173 {
1174 ttyputerr(_("Cannot find layer names on DRC line"));
1175 return(TRUE);
1176 }
1177 while (*pt != 0 && *pt != ' ' && *pt != '\t') pt++;
1178 if (*pt == 0)
1179 {
1180 ttyputerr(_("Cannot find layer name on DRC line"));
1181 return(TRUE);
1182 }
1183 save = *pt;
1184 *pt = 0;
1185 for(*layer1 = 0; *layer1 < maxlayers; (*layer1)++)
1186 if (namesame(str, layernames[*layer1]) == 0) break;
1187 *pt++ = (CHAR)save;
1188 if (*layer1 >= maxlayers)
1189 {
1190 ttyputerr(_("First DRC layer name unknown"));
1191 return(TRUE);
1192 }
1193 while (*pt == ' ' || *pt == '\t') pt++;
1194 }
1195
1196 /* get the second layer */
1197 if (*widrule == 0)
1198 {
1199 str = pt;
1200 while (*pt != 0 && *pt != ' ' && *pt != '\t') pt++;
1201 save = *pt;
1202 *pt = 0;
1203 for(*layer2 = 0; *layer2 < maxlayers; (*layer2)++)
1204 if (namesame(str, layernames[*layer2]) == 0) break;
1205 *pt = (CHAR)save;
1206 if (*layer2 >= maxlayers)
1207 {
1208 ttyputerr(_("Second DRC layer name unknown"));
1209 return(TRUE);
1210 }
1211 }
1212
1213 while (*pt == ' ' || *pt == '\t') pt++;
1214 *rule = pt;
1215 return(FALSE);
1216 }
1217
1218 /*
1219 * Helper routine to examine the arrays describing the design rules and create
1220 * the variable "EDTEC_DRC" on library "lib".
1221 */
us_tecedloaddrcmessage(DRCRULES * rules,LIBRARY * lib)1222 void us_tecedloaddrcmessage(DRCRULES *rules, LIBRARY *lib)
1223 {
1224 REGISTER INTBIG drccount, drcindex, i, k, j;
1225 REGISTER CHAR **drclist;
1226 REGISTER void *infstr;
1227
1228 /* determine the number of lines in the text-version of the design rules */
1229 drccount = 0;
1230 for(i=0; i<rules->utsize; i++)
1231 {
1232 if (rules->conlist[i] >= 0) drccount++;
1233 if (rules->unconlist[i] >= 0) drccount++;
1234 if (rules->conlistW[i] >= 0) drccount++;
1235 if (rules->unconlistW[i] >= 0) drccount++;
1236 if (rules->conlistM[i] >= 0) drccount++;
1237 if (rules->unconlistM[i] >= 0) drccount++;
1238 if (rules->edgelist[i] >= 0) drccount++;
1239 }
1240 for(i=0; i<rules->numlayers; i++)
1241 {
1242 if (rules->minwidth[i] >= 0) drccount++;
1243 }
1244 for(i=0; i<rules->numnodes; i++)
1245 {
1246 if (rules->minnodesize[i*2] > 0 || rules->minnodesize[i*2+1] > 0) drccount++;
1247 }
1248
1249 /* load the arrays */
1250 if (drccount != 0)
1251 {
1252 drccount++;
1253 drclist = (CHAR **)emalloc((drccount * (sizeof (CHAR *))), el_tempcluster);
1254 if (drclist == 0) return;
1255 drcindex = 0;
1256
1257 /* write the width limit */
1258 infstr = initinfstr();
1259 formatinfstr(infstr, x_("l%s"), frtoa(rules->widelimit));
1260 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1261
1262 /* write the minimum width for each layer */
1263 for(i=0; i<rules->numlayers; i++)
1264 {
1265 if (rules->minwidth[i] >= 0)
1266 {
1267 infstr = initinfstr();
1268 formatinfstr(infstr, x_("s%s %s %s"), frtoa(rules->minwidth[i]),
1269 rules->layernames[i], rules->minwidthR[i]);
1270 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1271 }
1272 }
1273
1274 /* write the minimum size for each node */
1275 for(i=0; i<rules->numnodes; i++)
1276 {
1277 if (rules->minnodesize[i*2] <= 0 && rules->minnodesize[i*2+1] <= 0) continue;
1278 {
1279 infstr = initinfstr();
1280 formatinfstr(infstr, x_("n%s %s %s %s"), rules->nodenames[i],
1281 frtoa(rules->minnodesize[i*2]), frtoa(rules->minnodesize[i*2+1]),
1282 rules->minnodesizeR[i]);
1283 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1284 }
1285 }
1286
1287 /* now do the distance rules */
1288 k = 0;
1289 for(i=0; i<rules->numlayers; i++) for(j=i; j<rules->numlayers; j++)
1290 {
1291 if (rules->conlist[k] >= 0)
1292 {
1293 infstr = initinfstr();
1294 formatinfstr(infstr, x_("c%s %s %s %s"), frtoa(rules->conlist[k]),
1295 rules->layernames[i], rules->layernames[j],
1296 rules->conlistR[k]);
1297 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1298 }
1299 if (rules->unconlist[k] >= 0)
1300 {
1301 infstr = initinfstr();
1302 formatinfstr(infstr, x_("%s %s %s %s"), frtoa(rules->unconlist[k]),
1303 rules->layernames[i], rules->layernames[j],
1304 rules->unconlistR[k]);
1305 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1306 }
1307 if (rules->conlistW[k] >= 0)
1308 {
1309 infstr = initinfstr();
1310 formatinfstr(infstr, x_("cw%s %s %s %s"), frtoa(rules->conlistW[k]),
1311 rules->layernames[i], rules->layernames[j],
1312 rules->conlistWR[k]);
1313 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1314 }
1315 if (rules->unconlistW[k] >= 0)
1316 {
1317 infstr = initinfstr();
1318 formatinfstr(infstr, x_("w%s %s %s %s"), frtoa(rules->unconlistW[k]),
1319 rules->layernames[i], rules->layernames[j],
1320 rules->unconlistWR[k]);
1321 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1322 }
1323 if (rules->conlistM[k] >= 0)
1324 {
1325 infstr = initinfstr();
1326 formatinfstr(infstr, x_("cm%s %s %s %s"), frtoa(rules->conlistM[k]),
1327 rules->layernames[i], rules->layernames[j],
1328 rules->conlistMR[k]);
1329 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1330 }
1331 if (rules->unconlistM[k] >= 0)
1332 {
1333 infstr = initinfstr();
1334 formatinfstr(infstr, x_("m%s %s %s %s"), frtoa(rules->unconlistM[k]),
1335 rules->layernames[i], rules->layernames[j],
1336 rules->unconlistMR[k]);
1337 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1338 }
1339 if (rules->edgelist[k] >= 0)
1340 {
1341 infstr = initinfstr();
1342 formatinfstr(infstr, x_("e%s %s %s %s"), frtoa(rules->edgelist[k]),
1343 rules->layernames[i], rules->layernames[j],
1344 rules->edgelistR[k]);
1345 (void)allocstring(&drclist[drcindex++], returninfstr(infstr), el_tempcluster);
1346 }
1347 k++;
1348 }
1349
1350 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_DRC"), (INTBIG)drclist,
1351 VSTRING|VISARRAY|(drccount<<VLENGTHSH));
1352 for(i=0; i<drccount; i++) efree(drclist[i]);
1353 efree((CHAR *)drclist);
1354 } else
1355 {
1356 /* no rules: remove the variable */
1357 if (getval((INTBIG)lib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_DRC")) != NOVARIABLE)
1358 (void)delval((INTBIG)lib, VLIBRARY, x_("EDTEC_DRC"));
1359 }
1360 }
1361
1362 /*
1363 * routine for manipulating color maps
1364 */
us_teceditcolormap(void)1365 void us_teceditcolormap(void)
1366 {
1367 REGISTER INTBIG i, k, total, dependentlibcount, *printcolors;
1368 INTBIG func, drcminwid, height3d, thick3d, printcol[5];
1369 CHAR *layerlabel[5], *layerabbrev[5], *cif, *gds, *layerletters, *dxf, **layernames, line[50];
1370 LIBRARY **dependentlibs;
1371 GRAPHICS desc;
1372 NODEPROTO **sequence;
1373 REGISTER NODEINST *ni;
1374 REGISTER NODEPROTO *np;
1375 REGISTER VARIABLE *var;
1376 float spires, spicap, spiecap;
1377 REGISTER INTBIG *mapptr, *newmap;
1378 REGISTER VARIABLE *varred, *vargreen, *varblue;
1379
1380 if (us_needwindow()) return;
1381
1382 /* load the color map of the technology */
1383 us_tecedloadlibmap(el_curlib);
1384
1385 dependentlibcount = us_teceditgetdependents(el_curlib, &dependentlibs);
1386 total = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("layer-"),
1387 x_("EDTEC_layersequence"), &sequence);
1388 printcolors = (INTBIG *)emalloc(total*5*SIZEOFINTBIG, us_tool->cluster);
1389 if (printcolors == 0) return;
1390 layernames = (CHAR **)emalloc(total * (sizeof (CHAR *)), us_tool->cluster);
1391 if (layernames == 0) return;
1392
1393 /* now fill in real layer names if known */
1394 for(i=0; i<5; i++) layerlabel[i] = 0;
1395 for(i=0; i<total; i++)
1396 {
1397 np = sequence[i];
1398 cif = layerletters = gds = 0;
1399 if (us_teceditgetlayerinfo(np, &desc, &cif, &func, &layerletters,
1400 &dxf, &gds, &spires, &spicap, &spiecap, &drcminwid, &height3d,
1401 &thick3d, printcol)) return;
1402 for(k=0; k<5; k++) printcolors[i*5+k] = printcol[k];
1403 layernames[i] = &np->protoname[6];
1404 switch (desc.bits)
1405 {
1406 case LAYERT1: k = 0; break;
1407 case LAYERT2: k = 1; break;
1408 case LAYERT3: k = 2; break;
1409 case LAYERT4: k = 3; break;
1410 case LAYERT5: k = 4; break;
1411 default: k = -1; break;
1412 }
1413 if (k >= 0)
1414 {
1415 if (layerlabel[k] == 0)
1416 {
1417 layerlabel[k] = &np->protoname[6];
1418 layerabbrev[k] = (CHAR *)emalloc(2 * SIZEOFCHAR, el_tempcluster);
1419 layerabbrev[k][0] = *layerletters;
1420 layerabbrev[k][1] = 0;
1421 }
1422 }
1423 if (gds != 0) efree(gds);
1424 if (cif != 0) efree(cif);
1425 if (layerletters != 0) efree(layerletters);
1426 }
1427
1428 /* set defaults */
1429 if (layerlabel[0] == 0)
1430 {
1431 layerlabel[0] = _("Ovrlap 1");
1432 (void)allocstring(&layerabbrev[0], x_("1"), el_tempcluster);
1433 }
1434 if (layerlabel[1] == 0)
1435 {
1436 layerlabel[1] = _("Ovrlap 2");
1437 (void)allocstring(&layerabbrev[1], x_("2"), el_tempcluster);
1438 }
1439 if (layerlabel[2] == 0)
1440 {
1441 layerlabel[2] = _("Ovrlap 3");
1442 (void)allocstring(&layerabbrev[2], x_("3"), el_tempcluster);
1443 }
1444 if (layerlabel[3] == 0)
1445 {
1446 layerlabel[3] = _("Ovrlap 4");
1447 (void)allocstring(&layerabbrev[3], x_("4"), el_tempcluster);
1448 }
1449 if (layerlabel[4] == 0)
1450 {
1451 layerlabel[4] = _("Ovrlap 5");
1452 (void)allocstring(&layerabbrev[4], x_("5"), el_tempcluster);
1453 }
1454
1455 /* run the color mixing palette */
1456 if (us_colormixdlog(layerlabel, total, layernames, printcolors))
1457 {
1458 /* update all of the layer cells */
1459 for(i=0; i<total; i++)
1460 {
1461 np = sequence[i];
1462 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1463 {
1464 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
1465 if (var == NOVARIABLE) continue;
1466 if (var->addr != LAYERPRINTCOL) continue;
1467 (void)esnprintf(line, 50, x_("%s%ld,%ld,%ld, %ld,%s"), TECEDNODETEXTPRINTCOL,
1468 printcolors[i*5], printcolors[i*5+1], printcolors[i*5+2],
1469 printcolors[i*5+3], (printcolors[i*5+4]==0 ? x_("off") : x_("on")));
1470 startobjectchange((INTBIG)ni, VNODEINST);
1471 (void)setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)line,
1472 VSTRING|VDISPLAY);
1473 endobjectchange((INTBIG)ni, VNODEINST);
1474 }
1475 }
1476 }
1477 for(i=0; i<5; i++) efree(layerabbrev[i]);
1478
1479 /* save the map on the library */
1480 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
1481 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
1482 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
1483 if (varred != NOVARIABLE && vargreen != NOVARIABLE && varblue != NOVARIABLE)
1484 {
1485 newmap = emalloc(256*3*SIZEOFINTBIG, el_tempcluster);
1486 mapptr = newmap;
1487 for(i=0; i<256; i++)
1488 {
1489 *mapptr++ = ((INTBIG *)varred->addr)[i];
1490 *mapptr++ = ((INTBIG *)vargreen->addr)[i];
1491 *mapptr++ = ((INTBIG *)varblue->addr)[i];
1492 }
1493 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("EDTEC_colormap"), (INTBIG)newmap,
1494 VINTEGER|VISARRAY|((256*3)<<VLENGTHSH));
1495 efree((CHAR *)newmap);
1496 }
1497 efree((CHAR *)layernames);
1498 efree((CHAR *)printcolors);
1499 }
1500
1501 /*
1502 * routine for creating a new layer with shape "pp"
1503 */
us_teceditcreat(INTBIG count,CHAR * par[])1504 void us_teceditcreat(INTBIG count, CHAR *par[])
1505 {
1506 REGISTER INTBIG l;
1507 REGISTER CHAR *name, *pp;
1508 CHAR *subpar[3];
1509 REGISTER NODEINST *ni;
1510 REGISTER NODEPROTO *np, *savenp, *cell;
1511 HIGHLIGHT high;
1512 REGISTER VARIABLE *var;
1513
1514 l = estrlen(pp = par[0]);
1515 np = NONODEPROTO;
1516 if (namesamen(pp, x_("port"), l) == 0 && l >= 1) np = gen_portprim;
1517 if (namesamen(pp, x_("highlight"), l) == 0 && l >= 1) np = art_boxprim;
1518 if (namesamen(pp, x_("rectangle-filled"), l) == 0 && l >= 11) np = art_filledboxprim;
1519 if (namesamen(pp, x_("rectangle-outline"), l) == 0 && l >= 11) np = art_boxprim;
1520 if (namesamen(pp, x_("rectangle-crossed"), l) == 0 && l >= 11) np = art_crossedboxprim;
1521 if (namesamen(pp, x_("polygon-filled"), l) == 0 && l >= 9) np = art_filledpolygonprim;
1522 if (namesamen(pp, x_("polygon-outline"), l) == 0 && l >= 9) np = art_closedpolygonprim;
1523 if (namesamen(pp, x_("lines-solid"), l) == 0 && l >= 7) np = art_openedpolygonprim;
1524 if (namesamen(pp, x_("lines-dotted"), l) == 0 && l >= 8) np = art_openeddottedpolygonprim;
1525 if (namesamen(pp, x_("lines-dashed"), l) == 0 && l >= 8) np = art_openeddashedpolygonprim;
1526 if (namesamen(pp, x_("lines-thicker"), l) == 0 && l >= 7) np = art_openedthickerpolygonprim;
1527 if (namesamen(pp, x_("circle-outline"), l) == 0 && l >= 8) np = art_circleprim;
1528 if (namesamen(pp, x_("circle-filled"), l) == 0 && l >= 8) np = art_filledcircleprim;
1529 if (namesamen(pp, x_("circle-half"), l) == 0 && l >= 8) np = art_circleprim;
1530 if (namesamen(pp, x_("circle-arc"), l) == 0 && l >= 8) np = art_circleprim;
1531 if (namesamen(pp, x_("text"), l) == 0 && l >= 1) np = gen_invispinprim;
1532
1533 if (np == NONODEPROTO)
1534 {
1535 ttyputerr(_("Unrecoginzed shape: '%s'"), pp);
1536 return;
1537 }
1538
1539 /* make sure the cell is right */
1540 cell = us_needcell();
1541 if (cell == NONODEPROTO) return;
1542 if (namesamen(cell->protoname, x_("node-"), 5) != 0 &&
1543 namesamen(cell->protoname, x_("arc-"), 4) != 0)
1544 {
1545 us_abortcommand(_("Must be editing a node or arc to place geometry"));
1546 if ((us_tool->toolstate&NODETAILS) == 0)
1547 ttyputmsg(_("Use 'edit-node' or 'edit-arc' options"));
1548 return;
1549 }
1550 if (np == gen_portprim &&
1551 namesamen(cell->protoname, x_("node-"), 5) != 0)
1552 {
1553 us_abortcommand(_("Can only place ports in node descriptions"));
1554 if ((us_tool->toolstate&NODETAILS) == 0)
1555 ttyputmsg(_("Use the 'edit-node' options"));
1556 return;
1557 }
1558
1559 /* create the node */
1560 us_clearhighlightcount();
1561 savenp = us_curnodeproto;
1562 us_curnodeproto = np;
1563 subpar[0] = x_("wait-for-down");
1564 us_create(1, subpar);
1565 us_curnodeproto = savenp;
1566
1567 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1568 if (var == NOVARIABLE) return;
1569 (void)us_makehighlight(((CHAR **)var->addr)[0], &high);
1570 if (high.fromgeom == NOGEOM) return;
1571 if (!high.fromgeom->entryisnode) return;
1572 ni = high.fromgeom->entryaddr.ni;
1573 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
1574
1575 /* postprocessing on the nodes */
1576 if (namesamen(pp, x_("port"), l) == 0 && l >= 1)
1577 {
1578 /* a port layer */
1579 if (count == 1)
1580 {
1581 name = ttygetline(M_("Port name: "));
1582 if (name == 0 || name[0] == 0)
1583 {
1584 us_abortedmsg();
1585 return;
1586 }
1587 } else name = par[1];
1588 var = setval((INTBIG)ni, VNODEINST, x_("EDTEC_portname"), (INTBIG)name, VSTRING|VDISPLAY);
1589 if (var != NOVARIABLE) defaulttextdescript(var->textdescript, ni->geom);
1590 if ((us_tool->toolstate&NODETAILS) == 0)
1591 ttyputmsg(_("Use 'change' option to set arc connectivity and port angle"));
1592 }
1593 if (namesamen(pp, x_("highlight"), l) == 0 && l >= 1)
1594 {
1595 /* a highlight layer */
1596 us_teceditsetpatch(ni, &us_edtechigh);
1597 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"), (INTBIG)NONODEPROTO, VNODEPROTO);
1598 ttyputmsg(_("Keep highlight a constant distance from the example edge"));
1599 }
1600 if (namesamen(pp, x_("circle-half"), l) == 0 && l >= 8)
1601 setarcdegrees(ni, 0.0, 180.0*EPI/180.0);
1602 if ((us_tool->toolstate&NODETAILS) == 0)
1603 {
1604 if (namesamen(pp, x_("rectangle-"), 10) == 0)
1605 ttyputmsg(_("Use 'change' option to set a layer for this shape"));
1606 if (namesamen(pp, x_("polygon-"), 8) == 0)
1607 {
1608 ttyputmsg(_("Use 'change' option to set a layer for this shape"));
1609 ttyputmsg(_("Use 'outline edit' to describe polygonal shape"));
1610 }
1611 if (namesamen(pp, x_("lines-"), 6) == 0)
1612 ttyputmsg(_("Use 'change' option to set a layer for this line"));
1613 if (namesamen(pp, x_("circle-"), 7) == 0)
1614 ttyputmsg(_("Use 'change' option to set a layer for this circle"));
1615 if (namesamen(pp, x_("text"), l) == 0 && l >= 1)
1616 {
1617 ttyputmsg(_("Use 'change' option to set a layer for this text"));
1618 ttyputmsg(_("Use 'var textedit ~.ART_message' command to set text"));
1619 ttyputmsg(_("Then use 'var change ~.ART_message display' command"));
1620 }
1621 }
1622 if (namesamen(pp, x_("circle-arc"), l) == 0 && l >= 8)
1623 {
1624 setarcdegrees(ni, 0.0, 45.0*EPI/180.0);
1625 if ((us_tool->toolstate&NODETAILS) == 0)
1626 ttyputmsg(_("Use 'setarc' command to set portion of circle"));
1627 }
1628 if ((ni->proto->userbits&HOLDSTRACE) != 0)
1629 {
1630 /* give it real points if it holds an outline */
1631 subpar[0] = x_("trace");
1632 subpar[1] = x_("init-points");
1633 us_node(2, subpar);
1634 }
1635 }
1636
1637 /*
1638 * routine to highlight information about all layers (or ports if "doports" is true)
1639 */
us_teceditidentify(BOOLEAN doports)1640 void us_teceditidentify(BOOLEAN doports)
1641 {
1642 REGISTER NODEPROTO *np;
1643 REGISTER INTBIG total, qtotal, i, j, bestrot, indent;
1644 REGISTER INTBIG xsep, ysep, *xpos, *ypos, dist, bestdist, *style;
1645 INTBIG lx, hx, ly, hy;
1646 REGISTER EXAMPLE *nelist;
1647 REGISTER SAMPLE *ns, **whichsam;
1648 static POLYGON *poly = NOPOLYGON;
1649 extern GRAPHICS us_hbox;
1650
1651 np = us_needcell();
1652 if (np == NONODEPROTO) return;
1653
1654 if (doports)
1655 {
1656 if (namesamen(np->protoname, x_("node-"), 5) != 0)
1657 {
1658 us_abortcommand(_("Must be editing a node to identify ports"));
1659 if ((us_tool->toolstate&NODETAILS) == 0)
1660 ttyputmsg(M_("Use the 'edit-node' option"));
1661 return;
1662 }
1663 } else
1664 {
1665 if (namesamen(np->protoname, x_("node-"), 5) != 0 &&
1666 namesamen(np->protoname, x_("arc-"), 4) != 0)
1667 {
1668 us_abortcommand(_("Must be editing a node or arc to identify layers"));
1669 if ((us_tool->toolstate&NODETAILS) == 0)
1670 ttyputmsg(M_("Use 'edit-node' or 'edit-arc' options"));
1671 return;
1672 }
1673 }
1674
1675 /* get examples */
1676 if (namesamen(np->protoname, x_("node-"), 5) == 0)
1677 nelist = us_tecedgetexamples(np, TRUE); else
1678 nelist = us_tecedgetexamples(np, FALSE);
1679 if (nelist == NOEXAMPLE) return;
1680
1681 /* count the number of appropriate samples in the main example */
1682 total = 0;
1683 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1684 {
1685 if (!doports)
1686 {
1687 if (ns->layer != gen_portprim) total++;
1688 } else
1689 {
1690 if (ns->layer == gen_portprim) total++;
1691 }
1692 }
1693 if (total == 0)
1694 {
1695 us_tecedfreeexamples(nelist);
1696 us_abortcommand(_("There are no %s to identify"), (!doports ? _("layers") : _("ports")));
1697 return;
1698 }
1699
1700 /* make arrays for position and association */
1701 xpos = (INTBIG *)emalloc(total * SIZEOFINTBIG, el_tempcluster);
1702 if (xpos == 0) return;
1703 ypos = (INTBIG *)emalloc(total * SIZEOFINTBIG, el_tempcluster);
1704 if (ypos == 0) return;
1705 style = (INTBIG *)emalloc(total * SIZEOFINTBIG, el_tempcluster);
1706 if (style == 0) return;
1707 whichsam = (SAMPLE **)emalloc(total * (sizeof (SAMPLE *)), el_tempcluster);
1708 if (whichsam == 0) return;
1709
1710 /* fill in label positions */
1711 qtotal = (total+3) / 4;
1712 ysep = (el_curwindowpart->screenhy-el_curwindowpart->screenly) / qtotal;
1713 xsep = (el_curwindowpart->screenhx-el_curwindowpart->screenlx) / qtotal;
1714 indent = (el_curwindowpart->screenhy-el_curwindowpart->screenly) / 15;
1715 for(i=0; i<qtotal; i++)
1716 {
1717 /* label on the left side */
1718 xpos[i] = el_curwindowpart->screenlx + indent;
1719 ypos[i] = el_curwindowpart->screenly + ysep * i + ysep/2;
1720 style[i] = TEXTLEFT;
1721 if (i+qtotal < total)
1722 {
1723 /* label on the top side */
1724 xpos[i+qtotal] = el_curwindowpart->screenlx + xsep * i + xsep/2;
1725 ypos[i+qtotal] = el_curwindowpart->screenhy - indent;
1726 style[i+qtotal] = TEXTTOP;
1727 }
1728 if (i+qtotal*2 < total)
1729 {
1730 /* label on the right side */
1731 xpos[i+qtotal*2] = el_curwindowpart->screenhx - indent;
1732 ypos[i+qtotal*2] = el_curwindowpart->screenly + ysep * i + ysep/2;
1733 style[i+qtotal*2] = TEXTRIGHT;
1734 }
1735 if (i+qtotal*3 < total)
1736 {
1737 /* label on the bottom side */
1738 xpos[i+qtotal*3] = el_curwindowpart->screenlx + xsep * i + xsep/2;
1739 ypos[i+qtotal*3] = el_curwindowpart->screenly + indent;
1740 style[i+qtotal*3] = TEXTBOT;
1741 }
1742 }
1743
1744 /* fill in sample associations */
1745 i = 0;
1746 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1747 {
1748 if (!doports)
1749 {
1750 if (ns->layer != gen_portprim) whichsam[i++] = ns;
1751 } else
1752 {
1753 if (ns->layer == gen_portprim) whichsam[i++] = ns;
1754 }
1755 }
1756
1757 /* rotate through all configurations, finding least distance */
1758 bestdist = MAXINTBIG;
1759 for(i=0; i<total; i++)
1760 {
1761 /* find distance from each label to its sample center */
1762 dist = 0;
1763 for(j=0; j<total; j++)
1764 dist += computedistance(xpos[j], ypos[j], whichsam[j]->xpos, whichsam[j]->ypos);
1765 if (dist < bestdist)
1766 {
1767 bestdist = dist;
1768 bestrot = i;
1769 }
1770
1771 /* rotate the samples */
1772 ns = whichsam[0];
1773 for(j=1; j<total; j++) whichsam[j-1] = whichsam[j];
1774 whichsam[total-1] = ns;
1775 }
1776
1777 /* rotate back to the best orientation */
1778 for(i=0; i<bestrot; i++)
1779 {
1780 ns = whichsam[0];
1781 for(j=1; j<total; j++) whichsam[j-1] = whichsam[j];
1782 whichsam[total-1] = ns;
1783 }
1784
1785 /* get polygon */
1786 (void)needstaticpolygon(&poly, 2, us_tool->cluster);
1787
1788 /* draw the highlighting */
1789 us_clearhighlightcount();
1790 for(i=0; i<total; i++)
1791 {
1792 ns = whichsam[i];
1793 poly->xv[0] = xpos[i];
1794 poly->yv[0] = ypos[i];
1795 poly->count = 1;
1796 if (ns->layer == NONODEPROTO)
1797 {
1798 poly->string = x_("HIGHLIGHT");
1799 } else if (ns->layer == gen_cellcenterprim)
1800 {
1801 poly->string = x_("GRAB");
1802 } else if (ns->layer == gen_portprim)
1803 {
1804 poly->string = us_tecedgetportname(ns->node);
1805 if (poly->string == 0) poly->string = x_("?");
1806 } else poly->string = &ns->layer->protoname[6];
1807 poly->desc = &us_hbox;
1808 poly->style = style[i];
1809 TDCLEAR(poly->textdescript);
1810 TDSETSIZE(poly->textdescript, TXTSETQLAMBDA(4));
1811 poly->tech = el_curtech;
1812 us_hbox.col = HIGHLIT;
1813
1814 nodesizeoffset(ns->node, &lx, &ly, &hx, &hy);
1815 switch (poly->style)
1816 {
1817 case TEXTLEFT:
1818 poly->xv[1] = ns->node->lowx+lx;
1819 poly->yv[1] = (ns->node->lowy + ns->node->highy) / 2;
1820 poly->style = TEXTBOTLEFT;
1821 break;
1822 case TEXTRIGHT:
1823 poly->xv[1] = ns->node->highx-hx;
1824 poly->yv[1] = (ns->node->lowy + ns->node->highy) / 2;
1825 poly->style = TEXTBOTRIGHT;
1826 break;
1827 case TEXTTOP:
1828 poly->xv[1] = (ns->node->lowx + ns->node->highx) / 2;
1829 poly->yv[1] = ns->node->highy-hy;
1830 poly->style = TEXTTOPLEFT;
1831 break;
1832 case TEXTBOT:
1833 poly->xv[1] = (ns->node->lowx + ns->node->highx) / 2;
1834 poly->yv[1] = ns->node->lowy+ly;
1835 poly->style = TEXTBOTLEFT;
1836 break;
1837 }
1838 us_showpoly(poly, el_curwindowpart);
1839
1840 /* now draw the vector polygon */
1841 poly->count = 2;
1842 poly->style = VECTORS;
1843 us_showpoly(poly, el_curwindowpart);
1844 }
1845
1846 /* free rotation arrays */
1847 efree((CHAR *)xpos);
1848 efree((CHAR *)ypos);
1849 efree((CHAR *)style);
1850 efree((CHAR *)whichsam);
1851
1852 /* free all examples */
1853 us_tecedfreeexamples(nelist);
1854 }
1855
1856 /*
1857 * routine to print information about selected object
1858 */
us_teceditinquire(void)1859 void us_teceditinquire(void)
1860 {
1861 REGISTER NODEINST *ni;
1862 REGISTER ARCINST *ai;
1863 REGISTER NODEPROTO *np;
1864 REGISTER CHAR *pt1, *pt2, *pt;
1865 REGISTER VARIABLE *var;
1866 REGISTER INTBIG opt;
1867 REGISTER HIGHLIGHT *high;
1868
1869 high = us_getonehighlight();
1870 if ((high->status&HIGHTYPE) != HIGHTEXT && (high->status&HIGHTYPE) != HIGHFROM)
1871 {
1872 us_abortcommand(_("Must select a single object for inquiry"));
1873 return;
1874 }
1875 if ((high->status&HIGHTYPE) == HIGHFROM && !high->fromgeom->entryisnode)
1876 {
1877 /* describe currently highlighted arc */
1878 ai = high->fromgeom->entryaddr.ai;
1879 if (ai->proto != gen_universalarc)
1880 {
1881 ttyputmsg(_("This is an unimportant %s arc"), describearcproto(ai->proto));
1882 return;
1883 }
1884 if (ai->end[0].nodeinst->proto != gen_portprim ||
1885 ai->end[1].nodeinst->proto != gen_portprim)
1886 {
1887 ttyputmsg(_("This arc makes an unimportant connection"));
1888 return;
1889 }
1890 pt1 = us_tecedgetportname(ai->end[0].nodeinst);
1891 pt2 = us_tecedgetportname(ai->end[1].nodeinst);
1892 if (pt1 == 0 || pt2 == 0)
1893 ttyputmsg(_("This arc connects two port objects")); else
1894 ttyputmsg(_("This arc connects ports '%s' and '%s'"), pt1, pt2);
1895 return;
1896 }
1897 ni = high->fromgeom->entryaddr.ni;
1898 np = ni->parent;
1899 opt = us_tecedgetoption(ni);
1900 if (opt < 0)
1901 {
1902 ttyputmsg(_("This object has no relevance to technology editing"));
1903 return;
1904 }
1905
1906 switch (opt)
1907 {
1908 case ARCFIXANG:
1909 ttyputmsg(_("This object defines the fixed-angle factor of %s"), describenodeproto(np));
1910 break;
1911 case ARCFUNCTION:
1912 ttyputmsg(_("This object defines the function of %s"), describenodeproto(np));
1913 break;
1914 case ARCINC:
1915 ttyputmsg(_("This object defines the prefered angle increment of %s"), describenodeproto(np));
1916 break;
1917 case ARCNOEXTEND:
1918 ttyputmsg(_("This object defines the arc extension of %s"), describenodeproto(np));
1919 break;
1920 case ARCWIPESPINS:
1921 ttyputmsg(_("This object defines the arc coverage of %s"), describenodeproto(np));
1922 break;
1923 case CENTEROBJ:
1924 ttyputmsg(_("This object identifies the grab point of %s"), describenodeproto(np));
1925 break;
1926 case LAYER3DHEIGHT:
1927 ttyputmsg(_("This object defines the 3D height of %s"), describenodeproto(np));
1928 break;
1929 case LAYER3DTHICK:
1930 ttyputmsg(_("This object defines the 3D thickness of %s"), describenodeproto(np));
1931 break;
1932 case LAYERPRINTCOL:
1933 ttyputmsg(_("This object defines the print colors of %s"), describenodeproto(np));
1934 break;
1935 case LAYERCIF:
1936 ttyputmsg(_("This object defines the CIF name of %s"), describenodeproto(np));
1937 break;
1938 case LAYERCOLOR:
1939 ttyputmsg(_("This object defines the color of %s"), describenodeproto(np));
1940 break;
1941 case LAYERDXF:
1942 ttyputmsg(_("This object defines the DXF name(s) of %s"), describenodeproto(np));
1943 break;
1944 case LAYERDRCMINWID:
1945 ttyputmsg(_("This object defines the minimum DRC width of %s (OBSOLETE)"), describenodeproto(np));
1946 break;
1947 case LAYERFUNCTION:
1948 ttyputmsg(_("This object defines the function of %s"), describenodeproto(np));
1949 break;
1950 case LAYERGDS:
1951 ttyputmsg(_("This object defines the Calma GDS-II number of %s"), describenodeproto(np));
1952 break;
1953 case LAYERLETTERS:
1954 ttyputmsg(_("This object defines the letters to use for %s"), describenodeproto(np));
1955 break;
1956 case LAYERPATCONT:
1957 ttyputmsg(_("This object provides control of the stipple pattern in %s"), describenodeproto(np));
1958 break;
1959 case LAYERPATTERN:
1960 ttyputmsg(_("This is one of the bitmap squares in %s"), describenodeproto(np));
1961 break;
1962 case LAYERSPICAP:
1963 ttyputmsg(_("This object defines the SPICE capacitance of %s"), describenodeproto(np));
1964 break;
1965 case LAYERSPIECAP:
1966 ttyputmsg(_("This object defines the SPICE edge capacitance of %s"), describenodeproto(np));
1967 break;
1968 case LAYERSPIRES:
1969 ttyputmsg(_("This object defines the SPICE resistance of %s"), describenodeproto(np));
1970 break;
1971 case LAYERSTYLE:
1972 ttyputmsg(_("This object defines the style of %s"), describenodeproto(np));
1973 break;
1974 case LAYERPATCH:
1975 case HIGHLIGHTOBJ:
1976 np = us_tecedgetlayer(ni);
1977 if (np == 0)
1978 ttyputerr(_("This is an object with no valid layer!")); else
1979 {
1980 if (np == NONODEPROTO) ttyputmsg(_("This is a highlight box")); else
1981 ttyputmsg(_("This is a '%s' layer"), &np->protoname[6]);
1982 var = getval((INTBIG)ni, VNODEINST, VSTRING, x_("EDTEC_minbox"));
1983 if (var != NOVARIABLE)
1984 ttyputmsg(_(" It is at minimum size"));
1985 }
1986 break;
1987 case NODEFUNCTION:
1988 ttyputmsg(_("This object defines the function of %s"), describenodeproto(np));
1989 break;
1990 case NODELOCKABLE:
1991 ttyputmsg(_("This object tells if %s can be locked (used in array technologies)"),
1992 describenodeproto(np));
1993 break;
1994 case NODEMULTICUT:
1995 ttyputmsg(_("This object tells the separation between multiple contact cuts in %s"),
1996 describenodeproto(np));
1997 break;
1998 case NODESERPENTINE:
1999 ttyputmsg(_("This object tells if %s is a serpentine transistor"), describenodeproto(np));
2000 break;
2001 case NODESQUARE:
2002 ttyputmsg(_("This object tells if %s is square"), describenodeproto(np));
2003 break;
2004 case NODEWIPES:
2005 ttyputmsg(_("This object tells if %s disappears when conencted to one or two arcs"),
2006 describenodeproto(np));
2007 break;
2008 case PORTOBJ:
2009 pt = us_tecedgetportname(ni);
2010 if (pt == 0) ttyputmsg(_("This is a port object")); else
2011 ttyputmsg(_("This is port '%s'"), pt);
2012 break;
2013 case TECHDESCRIPT:
2014 ttyputmsg(_("This object contains the technology description"));
2015 break;
2016 case TECHLAMBDA:
2017 ttyputmsg(_("This object defines the value of lambda"));
2018 break;
2019 default:
2020 ttyputerr(_("This object has unknown information"));
2021 break;
2022 }
2023 }
2024
2025 /*
2026 * Routine to return a brief description of node "ni" for use in the status area.
2027 */
us_teceddescribenode(NODEINST * ni)2028 CHAR *us_teceddescribenode(NODEINST *ni)
2029 {
2030 REGISTER INTBIG opt;
2031 REGISTER NODEPROTO *np;
2032 REGISTER void *infstr;
2033 REGISTER CHAR *pt;
2034
2035 opt = us_tecedgetoption(ni);
2036 if (opt < 0) return(0);
2037 switch (opt)
2038 {
2039 case ARCFIXANG: return(_("Arc fixed-angle factor"));
2040 case ARCFUNCTION: return(_("Arc function"));
2041 case ARCINC: return(_("Arc angle increment"));
2042 case ARCNOEXTEND: return(_("Arc extension"));
2043 case ARCWIPESPINS: return(_("Arc coverage"));
2044 case CENTEROBJ: return(_("Grab point"));
2045 case LAYER3DHEIGHT: return(_("3D height"));
2046 case LAYER3DTHICK: return(_("3D thickness"));
2047 case LAYERPRINTCOL: return(_("Print colors"));
2048 case LAYERCIF: return(_("CIF names"));
2049 case LAYERCOLOR: return(_("Layer color"));
2050 case LAYERDXF: return(_("DXF name(s)"));
2051 case LAYERFUNCTION: return(_("Layer function"));
2052 case LAYERGDS: return(_("GDS-II number(s)"));
2053 case LAYERLETTERS: return(_("Layer letters"));
2054 case LAYERPATCONT: return(_("Pattern control"));
2055 case LAYERPATTERN: return(_("Stipple pattern element"));
2056 case LAYERSPICAP: return(_("Spice capacitance"));
2057 case LAYERSPIECAP: return(_("Spice edge capacitance"));
2058 case LAYERSPIRES: return(_("Spice resistance"));
2059 case LAYERSTYLE: return(_("Srawing style"));
2060 case LAYERPATCH:
2061 case HIGHLIGHTOBJ:
2062 np = us_tecedgetlayer(ni);
2063 if (np == 0) return(_("Unknown layer"));
2064 if (np == NONODEPROTO) return(_("Highlight box"));
2065 infstr = initinfstr();
2066 formatinfstr(infstr, _("Layer %s"), &np->protoname[6]);
2067 return(returninfstr(infstr));
2068 case NODEFUNCTION: return(_("Node function"));
2069 case NODELOCKABLE: return(_("Node lockability"));
2070 case NODEMULTICUT: return(_("Multicut separation"));
2071 case NODESERPENTINE: return(_("Serpentine transistor"));
2072 case NODESQUARE: return(_("Square node"));
2073 case NODEWIPES: return(_("Disappearing pin"));
2074 case PORTOBJ:
2075 pt = us_tecedgetportname(ni);
2076 if (pt == 0) return(_("Unnamed export"));
2077 infstr = initinfstr();
2078 formatinfstr(infstr, _("Export %s"), pt);
2079 return(returninfstr(infstr));
2080 case TECHDESCRIPT: return(_("Technology description"));
2081 case TECHLAMBDA: return(_("Lambda value"));
2082 }
2083 return(0);
2084 }
2085
2086 /*
2087 * routine for modifying the selected object. If two are selected, connect them.
2088 */
us_teceditmodobject(INTBIG count,CHAR * par[])2089 void us_teceditmodobject(INTBIG count, CHAR *par[])
2090 {
2091 REGISTER NODEINST *ni;
2092 GEOM *fromgeom, *togeom, **list;
2093 PORTPROTO *fromport, *toport;
2094 INTBIG opt, textcount, i, found;
2095 REGISTER HIGHLIGHT *high;
2096 HIGHLIGHT newhigh;
2097 CHAR *newpar[2], **textinfo;
2098
2099 /* special case for pattern changes */
2100 list = us_gethighlighted(WANTNODEINST|WANTARCINST, &textcount, &textinfo);
2101 if (textcount == 0)
2102 {
2103 found = 0;
2104 for(i=0; list[i] != NOGEOM; i++)
2105 {
2106 if (!list[i]->entryisnode) continue;
2107 ni = list[i]->entryaddr.ni;
2108 opt = us_tecedgetoption(ni);
2109 if (opt == LAYERPATTERN) found++;
2110 }
2111 if (found > 0)
2112 {
2113 /* change them */
2114 us_clearhighlightcount();
2115 for(i=0; list[i] != NOGEOM; i++)
2116 {
2117 if (!list[i]->entryisnode) continue;
2118 ni = list[i]->entryaddr.ni;
2119 opt = us_tecedgetoption(ni);
2120 if (opt == LAYERPATTERN)
2121 us_tecedlayerpattern(ni);
2122 }
2123 return;
2124 }
2125 }
2126
2127 /* if two are highlighted, connect them */
2128 if (!us_gettwoobjects(&fromgeom, &fromport, &togeom, &toport))
2129 {
2130 newpar[0] = x_("angle"); newpar[1] = x_("0");
2131 us_create(2, newpar);
2132 return;
2133 }
2134
2135 /* make sure something is highlighted */
2136 high = us_getonehighlight();
2137 if (high == NOHIGHLIGHT) return;
2138
2139 /* must be one node highlighted */
2140 ni = (NODEINST *)us_getobject(VNODEINST, TRUE);
2141 if (ni == NONODEINST) return;
2142
2143 /* determine technology editor relevance */
2144 opt = us_tecedgetoption(ni);
2145
2146 /* special case for port modification: reset highlighting by hand */
2147 if (opt == PORTOBJ)
2148 {
2149 /* pick up old highlight values and then remove highlighting */
2150 newhigh = *high;
2151 us_clearhighlightcount();
2152
2153 /* modify the port */
2154 us_tecedmodport(ni, count, par);
2155
2156 /* set new highlighting variable */
2157 newhigh.fromvar = getval((INTBIG)ni, VNODEINST, VSTRING, x_("EDTEC_portname"));
2158 if (newhigh.fromvar == NOVARIABLE)
2159 newhigh.fromvar = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
2160 us_addhighlight(&newhigh);
2161 return;
2162 }
2163
2164 /* ignore if no parameter given */
2165 if (count <= 0) return;
2166
2167 /* handle other cases */
2168 us_pushhighlight();
2169 us_clearhighlightcount();
2170 switch (opt)
2171 {
2172 case ARCFIXANG: us_tecedarcfixang(ni, count, par); break;
2173 case ARCFUNCTION: us_tecedarcfunction(ni, count, par); break;
2174 case ARCINC: us_tecedarcinc(ni, count, par); break;
2175 case ARCNOEXTEND: us_tecedarcnoextend(ni, count, par); break;
2176 case ARCWIPESPINS: us_tecedarcwipes(ni, count, par); break;
2177 case LAYER3DHEIGHT: us_tecedlayer3dheight(ni, count, par); break;
2178 case LAYER3DTHICK: us_tecedlayer3dthick(ni, count, par); break;
2179 case LAYERPRINTCOL: us_tecedlayerprintcol(ni, count, par); break;
2180 case LAYERCIF: us_tecedlayercif(ni, count, par); break;
2181 case LAYERCOLOR: us_tecedlayercolor(ni, count, par); break;
2182 case LAYERDXF: us_tecedlayerdxf(ni, count, par); break;
2183 case LAYERDRCMINWID: us_tecedlayerdrcminwid(ni, count, par); break;
2184 case LAYERFUNCTION: us_tecedlayerfunction(ni, count, par); break;
2185 case LAYERGDS: us_tecedlayergds(ni, count, par); break;
2186 case LAYERLETTERS: us_tecedlayerletters(ni, count, par); break;
2187 case LAYERPATCONT: us_tecedlayerpatterncontrol(ni, count, par); break;
2188 case LAYERPATCH: us_tecedlayertype(ni, count, par); break;
2189 case LAYERSPICAP: us_tecedlayerspicap(ni, count, par); break;
2190 case LAYERSPIECAP: us_tecedlayerspiecap(ni, count, par); break;
2191 case LAYERSPIRES: us_tecedlayerspires(ni, count, par); break;
2192 case LAYERSTYLE: us_tecedlayerstyle(ni, count, par); break;
2193 case NODEFUNCTION: us_tecednodefunction(ni, count, par); break;
2194 case NODELOCKABLE: us_tecednodelockable(ni, count, par); break;
2195 case NODEMULTICUT: us_tecednodemulticut(ni, count, par); break;
2196 case NODESERPENTINE: us_tecednodeserpentine(ni, count, par); break;
2197 case NODESQUARE: us_tecednodesquare(ni, count, par); break;
2198 case NODEWIPES: us_tecednodewipes(ni, count, par); break;
2199 case TECHDESCRIPT: us_tecedinfodescript(ni, count, par); break;
2200 case TECHLAMBDA: us_tecedinfolambda(ni, count, par); break;
2201 default: us_abortcommand(_("Cannot modify this object")); break;
2202 }
2203 us_pophighlight(FALSE);
2204 }
2205
2206 /***************************** OBJECT MODIFICATION *****************************/
2207
us_tecedlayer3dheight(NODEINST * ni,INTBIG count,CHAR * par[])2208 void us_tecedlayer3dheight(NODEINST *ni, INTBIG count, CHAR *par[])
2209 {
2210 REGISTER void *infstr;
2211
2212 if (par[0][0] == 0)
2213 {
2214 us_abortcommand(_("Enter the height of the layer when viewed in 3D"));
2215 return;
2216 }
2217 infstr = initinfstr();
2218 addstringtoinfstr(infstr, TECEDNODETEXT3DHEIGHT);
2219 addstringtoinfstr(infstr, par[0]);
2220 us_tecedsetnode(ni, returninfstr(infstr));
2221 }
2222
us_tecedlayer3dthick(NODEINST * ni,INTBIG count,CHAR * par[])2223 void us_tecedlayer3dthick(NODEINST *ni, INTBIG count, CHAR *par[])
2224 {
2225 REGISTER void *infstr;
2226
2227 if (par[0][0] == 0)
2228 {
2229 us_abortcommand(_("Enter the thickness of the layer when viewed in 3D"));
2230 return;
2231 }
2232 infstr = initinfstr();
2233 addstringtoinfstr(infstr, TECEDNODETEXT3DTHICK);
2234 addstringtoinfstr(infstr, par[0]);
2235 us_tecedsetnode(ni, returninfstr(infstr));
2236 }
2237
us_tecedlayerprintcol(NODEINST * ni,INTBIG count,CHAR * par[])2238 void us_tecedlayerprintcol(NODEINST *ni, INTBIG count, CHAR *par[])
2239 {
2240 REGISTER void *infstr;
2241 INTBIG len, r, g, b, o, f;
2242 REGISTER VARIABLE *var;
2243
2244 if (count < 2)
2245 {
2246 ttyputverbose(_("Enter the print colors of the layer"));
2247 return;
2248 }
2249 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
2250 us_teceditgetprintcol(var, &r, &g, &b, &o, &f);
2251 len = estrlen(par[0]);
2252 if (namesamen(par[0], x_("red"), len) == 0) r = myatoi(par[1]); else
2253 if (namesamen(par[0], x_("green"), len) == 0) g = myatoi(par[1]); else
2254 if (namesamen(par[0], x_("blue"), len) == 0) b = myatoi(par[1]); else
2255 if (namesamen(par[0], x_("opacity"), len) == 0) o = myatoi(par[1]); else
2256 if (namesamen(par[0], x_("foreground"), len) == 0)
2257 {
2258 if (namesame(par[1], x_("on")) == 0) f = 1; else
2259 if (namesame(par[1], x_("off")) == 0) f = 0; else
2260 f = myatoi(par[1]);
2261 }
2262 infstr = initinfstr();
2263 addstringtoinfstr(infstr, TECEDNODETEXTPRINTCOL);
2264 formatinfstr(infstr, x_("%ld,%ld,%ld, %ld,%s"), r, g, b, o, (f==0 ? x_("off") : x_("on")));
2265 us_tecedsetnode(ni, returninfstr(infstr));
2266 }
2267
us_tecedlayerdrcminwid(NODEINST * ni,INTBIG count,CHAR * par[])2268 void us_tecedlayerdrcminwid(NODEINST *ni, INTBIG count, CHAR *par[])
2269 {
2270 REGISTER void *infstr;
2271
2272 if (par[0][0] == 0)
2273 {
2274 us_abortcommand(_("Enter the minimum DRC width (negative for none)"));
2275 return;
2276 }
2277 infstr = initinfstr();
2278 addstringtoinfstr(infstr, TECEDNODETEXTDRCMINWID);
2279 addstringtoinfstr(infstr, par[0]);
2280 us_tecedsetnode(ni, returninfstr(infstr));
2281 }
2282
us_tecedlayercolor(NODEINST * ni,INTBIG count,CHAR * par[])2283 void us_tecedlayercolor(NODEINST *ni, INTBIG count, CHAR *par[])
2284 {
2285 REGISTER void *infstr;
2286
2287 if (par[0][0] == 0)
2288 {
2289 us_abortcommand(_("New color required"));
2290 return;
2291 }
2292 infstr = initinfstr();
2293 addstringtoinfstr(infstr, TECEDNODETEXTCOLOR);
2294 addstringtoinfstr(infstr, par[0]);
2295 us_tecedsetnode(ni, returninfstr(infstr));
2296
2297 /* redraw the demo layer in this cell */
2298 us_tecedredolayergraphics(ni->parent);
2299 }
2300
us_tecedlayerstyle(NODEINST * ni,INTBIG count,CHAR * par[])2301 void us_tecedlayerstyle(NODEINST *ni, INTBIG count, CHAR *par[])
2302 {
2303 REGISTER void *infstr;
2304
2305 if (par[0][0] == 0)
2306 {
2307 us_abortcommand(_("Layer style required"));
2308 return;
2309 }
2310 infstr = initinfstr();
2311 addstringtoinfstr(infstr, TECEDNODETEXTSTYLE);
2312 addstringtoinfstr(infstr, par[0]);
2313 us_tecedsetnode(ni, returninfstr(infstr));
2314
2315 /* redraw the demo layer in this cell */
2316 us_tecedredolayergraphics(ni->parent);
2317 }
2318
us_tecedlayercif(NODEINST * ni,INTBIG count,CHAR * par[])2319 void us_tecedlayercif(NODEINST *ni, INTBIG count, CHAR *par[])
2320 {
2321 REGISTER void *infstr;
2322
2323 infstr = initinfstr();
2324 addstringtoinfstr(infstr, TECEDNODETEXTCIF);
2325 addstringtoinfstr(infstr, par[0]);
2326 us_tecedsetnode(ni, returninfstr(infstr));
2327 }
2328
us_tecedlayerdxf(NODEINST * ni,INTBIG count,CHAR * par[])2329 void us_tecedlayerdxf(NODEINST *ni, INTBIG count, CHAR *par[])
2330 {
2331 REGISTER void *infstr;
2332
2333 infstr = initinfstr();
2334 addstringtoinfstr(infstr, TECEDNODETEXTDXF);
2335 addstringtoinfstr(infstr, par[0]);
2336 us_tecedsetnode(ni, returninfstr(infstr));
2337 }
2338
us_tecedlayergds(NODEINST * ni,INTBIG count,CHAR * par[])2339 void us_tecedlayergds(NODEINST *ni, INTBIG count, CHAR *par[])
2340 {
2341 REGISTER void *infstr;
2342
2343 infstr = initinfstr();
2344 addstringtoinfstr(infstr, TECEDNODETEXTGDS);
2345 addstringtoinfstr(infstr, par[0]);
2346 us_tecedsetnode(ni, returninfstr(infstr));
2347 }
2348
us_tecedlayerspires(NODEINST * ni,INTBIG count,CHAR * par[])2349 void us_tecedlayerspires(NODEINST *ni, INTBIG count, CHAR *par[])
2350 {
2351 REGISTER void *infstr;
2352
2353 if (par[0][0] == 0)
2354 {
2355 us_abortcommand(_("Enter the SPICE layer resistance"));
2356 return;
2357 }
2358 infstr = initinfstr();
2359 addstringtoinfstr(infstr, TECEDNODETEXTSPICERES);
2360 addstringtoinfstr(infstr, par[0]);
2361 us_tecedsetnode(ni, returninfstr(infstr));
2362 }
2363
us_tecedlayerspicap(NODEINST * ni,INTBIG count,CHAR * par[])2364 void us_tecedlayerspicap(NODEINST *ni, INTBIG count, CHAR *par[])
2365 {
2366 REGISTER void *infstr;
2367
2368 if (par[0][0] == 0)
2369 {
2370 us_abortcommand(_("Enter the SPICE layer capacitance"));
2371 return;
2372 }
2373 infstr = initinfstr();
2374 addstringtoinfstr(infstr, TECEDNODETEXTSPICECAP);
2375 addstringtoinfstr(infstr, par[0]);
2376 us_tecedsetnode(ni, returninfstr(infstr));
2377 }
2378
us_tecedlayerspiecap(NODEINST * ni,INTBIG count,CHAR * par[])2379 void us_tecedlayerspiecap(NODEINST *ni, INTBIG count, CHAR *par[])
2380 {
2381 REGISTER void *infstr;
2382
2383 if (par[0][0] == 0)
2384 {
2385 us_abortcommand(_("Enter the SPICE layer edge capacitance"));
2386 return;
2387 }
2388 infstr = initinfstr();
2389 addstringtoinfstr(infstr, TECEDNODETEXTSPICEECAP);
2390 addstringtoinfstr(infstr, par[0]);
2391 us_tecedsetnode(ni, returninfstr(infstr));
2392 }
2393
us_tecedlayerfunction(NODEINST * ni,INTBIG count,CHAR * par[])2394 void us_tecedlayerfunction(NODEINST *ni, INTBIG count, CHAR *par[])
2395 {
2396 REGISTER INTBIG func, newfunc;
2397 REGISTER CHAR *str;
2398 REGISTER VARIABLE *var;
2399 REGISTER void *infstr;
2400
2401 if (par[0][0] == 0)
2402 {
2403 us_abortcommand(_("Layer function required"));
2404 return;
2405 }
2406
2407 /* get the existing function */
2408 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
2409 func = 0;
2410 if (var != NOVARIABLE)
2411 {
2412 str = (CHAR *)var->addr;
2413 while (*str != 0 && *str != ':') str++;
2414 if (*str == ':') str++;
2415 while (*str == ' ') str++;
2416 if (*str != 0) func = us_teceditparsefun(str);
2417 }
2418
2419 /* add in the new function */
2420 newfunc = us_teceditparsefun(par[0]);
2421 if (newfunc <= LFTYPE) func = newfunc; else func |= newfunc;
2422
2423 /* build the string corresponding to this function */
2424 infstr = initinfstr();
2425 addstringtoinfstr(infstr, TECEDNODETEXTFUNCTION);
2426 us_tecedaddfunstring(infstr, func);
2427
2428 /* rewrite the node with the new function */
2429 us_tecedsetnode(ni, returninfstr(infstr));
2430 }
2431
us_tecedlayerletters(NODEINST * ni,INTBIG count,CHAR * par[])2432 void us_tecedlayerletters(NODEINST *ni, INTBIG count, CHAR *par[])
2433 {
2434 REGISTER NODEPROTO *np;
2435 REGISTER CHAR *pt;
2436 REGISTER INTBIG i;
2437 CHAR *cif, *layerletters, *dxf, *gds;
2438 GRAPHICS desc;
2439 float spires, spicap, spiecap;
2440 INTBIG func, drcminwid, height3d, thick3d, printcol[5];
2441 REGISTER void *infstr;
2442
2443 if (par[0][0] == 0)
2444 {
2445 us_abortcommand(_("Layer letter(s) required"));
2446 return;
2447 }
2448
2449 /* check layer letters for uniqueness */
2450 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2451 {
2452 if (namesamen(np->protoname, x_("layer-"), 6) != 0) continue;
2453 cif = layerletters = gds = 0;
2454 if (us_teceditgetlayerinfo(np, &desc, &cif, &func, &layerletters,
2455 &dxf, &gds, &spires, &spicap, &spiecap, &drcminwid, &height3d,
2456 &thick3d, printcol)) return;
2457 if (gds != 0) efree(gds);
2458 if (cif != 0) efree(cif);
2459 if (layerletters == 0) continue;
2460
2461 /* check these layer letters for uniqueness */
2462 for(pt = layerletters; *pt != 0; pt++)
2463 {
2464 for(i=0; par[0][i] != 0; i++) if (par[0][i] == *pt)
2465 {
2466 us_abortcommand(_("Cannot use letter '%c', it is in %s"), *pt, describenodeproto(np));
2467 efree(layerletters);
2468 return;
2469 }
2470 }
2471 efree(layerletters);
2472 }
2473
2474 infstr = initinfstr();
2475 addstringtoinfstr(infstr, TECEDNODETEXTLETTERS);
2476 addstringtoinfstr(infstr, par[0]);
2477 us_tecedsetnode(ni, returninfstr(infstr));
2478 }
2479
us_tecedlayerpatterncontrol(NODEINST * ni,INTBIG count,CHAR * par[])2480 void us_tecedlayerpatterncontrol(NODEINST *ni, INTBIG count, CHAR *par[])
2481 {
2482 REGISTER INTBIG len;
2483 REGISTER NODEINST *pni;
2484 REGISTER INTBIG opt;
2485 UINTSML color;
2486 static GRAPHICS desc;
2487 static BOOLEAN didcopy = FALSE;
2488 CHAR *cif, *layerletters, *gds, *dxf;
2489 INTBIG func, drcminwid, height3d, thick3d, printcol[5];
2490 float spires, spicap, spiecap;
2491
2492 len = estrlen(par[0]);
2493 if (namesamen(par[0], x_("Clear Pattern"), len) == 0 && len > 2)
2494 {
2495 us_clearhighlightcount();
2496 for(pni = ni->parent->firstnodeinst; pni != NONODEINST; pni = pni->nextnodeinst)
2497 {
2498 opt = us_tecedgetoption(pni);
2499 if (opt != LAYERPATTERN) continue;
2500 color = us_tecedlayergetpattern(pni);
2501 if (color != 0)
2502 us_tecedlayersetpattern(pni, 0);
2503 }
2504
2505 /* redraw the demo layer in this cell */
2506 us_tecedredolayergraphics(ni->parent);
2507 return;
2508 }
2509 if (namesamen(par[0], x_("Invert Pattern"), len) == 0 && len > 1)
2510 {
2511 us_clearhighlightcount();
2512 for(pni = ni->parent->firstnodeinst; pni != NONODEINST; pni = pni->nextnodeinst)
2513 {
2514 opt = us_tecedgetoption(pni);
2515 if (opt != LAYERPATTERN) continue;
2516 color = us_tecedlayergetpattern(pni);
2517 us_tecedlayersetpattern(pni, (INTSML)(~color));
2518 }
2519
2520 /* redraw the demo layer in this cell */
2521 us_tecedredolayergraphics(ni->parent);
2522 return;
2523 }
2524 if (namesamen(par[0], x_("Copy Pattern"), len) == 0 && len > 2)
2525 {
2526 us_clearhighlightcount();
2527 if (us_teceditgetlayerinfo(ni->parent, &desc, &cif, &func, &layerletters, &dxf,
2528 &gds, &spires, &spicap, &spiecap, &drcminwid, &height3d, &thick3d, printcol)) return;
2529 didcopy = TRUE;
2530 return;
2531 }
2532 if (namesamen(par[0], x_("Paste Pattern"), len) == 0 && len > 1)
2533 {
2534 us_clearhighlightcount();
2535 us_teceditsetlayerpattern(ni->parent, &desc);
2536
2537 /* redraw the demo layer in this cell */
2538 us_tecedredolayergraphics(ni->parent);
2539 return;
2540 }
2541 }
2542
2543 /*
2544 * Routine to return the color in layer-pattern node "ni" (off is 0, on is 0xFFFF).
2545 */
us_tecedlayergetpattern(NODEINST * ni)2546 INTSML us_tecedlayergetpattern(NODEINST *ni)
2547 {
2548 REGISTER VARIABLE *var;
2549 REGISTER INTSML color;
2550
2551 if (ni->proto == art_boxprim) return(0);
2552 if (ni->proto == art_filledboxprim)
2553 {
2554 var = getvalkey((INTBIG)ni, VNODEINST, VSHORT|VISARRAY, art_patternkey);
2555 if (var == NOVARIABLE) color = (INTSML)0xFFFF; else color = ((INTSML *)var->addr)[0];
2556 return(color);
2557 }
2558 return(0);
2559 }
2560
2561 /*
2562 * Routine to set layer-pattern node "ni" to be color "color" (off is 0, on is 0xFFFF).
2563 * Returns the address of the node (may be different than "ni" if it had to be replaced).
2564 */
us_tecedlayersetpattern(NODEINST * ni,INTSML color)2565 NODEINST *us_tecedlayersetpattern(NODEINST *ni, INTSML color)
2566 {
2567 REGISTER NODEINST *newni;
2568 INTBIG i;
2569 UINTSML col[16];
2570
2571 if (ni->proto == art_boxprim)
2572 {
2573 if (color == 0) return(ni);
2574 startobjectchange((INTBIG)ni, VNODEINST);
2575 newni = replacenodeinst(ni, art_filledboxprim, FALSE, FALSE);
2576 if (newni == NONODEINST) return(ni);
2577 endobjectchange((INTBIG)newni, VNODEINST);
2578 ni = newni;
2579 } else if (ni->proto == art_filledboxprim)
2580 {
2581 startobjectchange((INTBIG)ni, VNODEINST);
2582 for(i=0; i<16; i++) col[i] = color;
2583 (void)setvalkey((INTBIG)ni, VNODEINST, art_patternkey, (INTBIG)col,
2584 VSHORT|VISARRAY|(16<<VLENGTHSH));
2585 endobjectchange((INTBIG)ni, VNODEINST);
2586 }
2587 return(ni);
2588 }
2589
2590 /*
2591 * Routine to toggle the color of layer-pattern node "ni" (called when the user does a
2592 * "technology edit" click on the node).
2593 */
us_tecedlayerpattern(NODEINST * ni)2594 void us_tecedlayerpattern(NODEINST *ni)
2595 {
2596 HIGHLIGHT high;
2597 UINTSML color;
2598
2599 color = us_tecedlayergetpattern(ni);
2600 ni = us_tecedlayersetpattern(ni, (INTSML)(~color));
2601
2602 high.status = HIGHFROM;
2603 high.cell = ni->parent;
2604 high.fromgeom = ni->geom;
2605 high.fromport = NOPORTPROTO;
2606 high.frompoint = 0;
2607 high.fromvar = NOVARIABLE;
2608 high.fromvarnoeval = NOVARIABLE;
2609 us_addhighlight(&high);
2610
2611 /* redraw the demo layer in this cell */
2612 us_tecedredolayergraphics(ni->parent);
2613 }
2614
2615 /*
2616 * routine to modify the layer information in node "ni".
2617 */
us_tecedlayertype(NODEINST * ni,INTBIG count,CHAR * par[])2618 void us_tecedlayertype(NODEINST *ni, INTBIG count, CHAR *par[])
2619 {
2620 REGISTER NODEPROTO *np;
2621 CHAR *cif, *layerletters, *dxf, *gds;
2622 REGISTER CHAR *name;
2623 GRAPHICS desc;
2624 float spires, spicap, spiecap;
2625 INTBIG func, drcminwid, height3d, thick3d, printcol[5];
2626 REGISTER void *infstr;
2627
2628 if (par[0][0] == 0)
2629 {
2630 us_abortcommand(_("Requires a layer name"));
2631 return;
2632 }
2633
2634 np = us_needcell();
2635 if (np == NONODEPROTO) return;
2636 if (namesame(par[0], x_("SET-MINIMUM-SIZE")) == 0)
2637 {
2638 if (namesamen(np->protoname, x_("node-"), 5) != 0)
2639 {
2640 us_abortcommand(_("Can only set minimum size in node descriptions"));
2641 if ((us_tool->toolstate&NODETAILS) == 0) ttyputmsg(_("Use 'edit-node' option"));
2642 return;
2643 }
2644 startobjectchange((INTBIG)ni, VNODEINST);
2645 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_minbox"), (INTBIG)x_("MIN"), VSTRING|VDISPLAY);
2646 endobjectchange((INTBIG)ni, VNODEINST);
2647 return;
2648 }
2649
2650 if (namesame(par[0], x_("CLEAR-MINIMUM-SIZE")) == 0)
2651 {
2652 if (getval((INTBIG)ni, VNODEINST, VSTRING, x_("EDTEC_minbox")) == NOVARIABLE)
2653 {
2654 ttyputmsg(_("Minimum size is not set on this layer"));
2655 return;
2656 }
2657 startobjectchange((INTBIG)ni, VNODEINST);
2658 (void)delval((INTBIG)ni, VNODEINST, x_("EDTEC_minbox"));
2659 endobjectchange((INTBIG)ni, VNODEINST);
2660 return;
2661 }
2662
2663 /* find the actual cell with that layer specification */
2664 infstr = initinfstr();
2665 addstringtoinfstr(infstr, x_("layer-"));
2666 addstringtoinfstr(infstr, par[0]);
2667 name = returninfstr(infstr);
2668 np = getnodeproto(name);
2669 if (np == NONODEPROTO)
2670 {
2671 ttyputerr(_("Cannot find layer primitive %s"), name);
2672 return;
2673 }
2674
2675 /* get the characteristics of that layer */
2676 cif = layerletters = gds = 0;
2677 if (us_teceditgetlayerinfo(np, &desc, &cif, &func, &layerletters,
2678 &dxf, &gds, &spires, &spicap, &spiecap, &drcminwid, &height3d,
2679 &thick3d, printcol)) return;
2680 if (gds != 0) efree(gds);
2681 if (cif != 0) efree(cif);
2682 if (layerletters != 0) efree(layerletters);
2683
2684 startobjectchange((INTBIG)ni, VNODEINST);
2685 us_teceditsetpatch(ni, &desc);
2686 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"), (INTBIG)np, VNODEPROTO);
2687 endobjectchange((INTBIG)ni, VNODEINST);
2688 }
2689
2690 /*
2691 * routine to modify port characteristics
2692 */
us_tecedmodport(NODEINST * ni,INTBIG count,CHAR * par[])2693 void us_tecedmodport(NODEINST *ni, INTBIG count, CHAR *par[])
2694 {
2695 REGISTER INTBIG total, i, len, j, yes;
2696 BOOLEAN changed;
2697 REGISTER BOOLEAN *yesno;
2698 REGISTER NODEPROTO *np, **conlist;
2699 REGISTER VARIABLE *var;
2700
2701 /* build an array of arc connections */
2702 for(total = 0, np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2703 if (namesamen(np->protoname, x_("arc-"), 4) == 0) total++;
2704 conlist = (NODEPROTO **)emalloc(total * (sizeof (NODEPROTO *)), el_tempcluster);
2705 if (conlist == 0) return;
2706 for(total = 0, np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2707 if (namesamen(np->protoname, x_("arc-"), 4) == 0) conlist[total++] = np;
2708 yesno = (BOOLEAN *)emalloc(total * (sizeof (BOOLEAN)), el_tempcluster);
2709 if (yesno == 0) return;
2710 for(i=0; i<total; i++) yesno[i] = FALSE;
2711
2712 /* put current list into the array */
2713 var = getval((INTBIG)ni, VNODEINST, VNODEPROTO|VISARRAY, x_("EDTEC_connects"));
2714 if (var != NOVARIABLE)
2715 {
2716 len = getlength(var);
2717 for(j=0; j<len; j++)
2718 {
2719 for(i=0; i<total; i++)
2720 if (conlist[i] == ((NODEPROTO **)var->addr)[j]) break;
2721 if (i < total) yesno[i] = TRUE;
2722 }
2723 }
2724
2725 /* parse the command parameters */
2726 changed = FALSE;
2727 for(i=0; i<count-1; i += 2)
2728 {
2729 /* search for an arc name */
2730 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2731 if (namesamen(np->protoname, x_("arc-"), 4) == 0 &&
2732 namesame(&np->protoname[4], par[i]) == 0) break;
2733 if (np != NONODEPROTO)
2734 {
2735 for(j=0; j<total; j++) if (conlist[j] == np)
2736 {
2737 if (*par[i+1] == 'y' || *par[i+1] == 'Y') yesno[j] = TRUE; else
2738 yesno[j] = FALSE;
2739 changed = TRUE;
2740 break;
2741 }
2742 continue;
2743 }
2744
2745 if (namesame(par[i], x_("PORT-ANGLE")) == 0)
2746 {
2747 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_portangle"), myatoi(par[i+1]), VINTEGER);
2748 continue;
2749 }
2750 if (namesame(par[i], x_("PORT-ANGLE-RANGE")) == 0)
2751 {
2752 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_portrange"), myatoi(par[i+1]), VINTEGER);
2753 continue;
2754 }
2755 }
2756
2757 /* store list back if it was changed */
2758 if (changed)
2759 {
2760 yes = 0;
2761 for(i=0; i<total; i++)
2762 {
2763 if (!yesno[i]) continue;
2764 conlist[yes++] = conlist[i];
2765 }
2766 if (yes == 0 && var != NOVARIABLE)
2767 (void)delval((INTBIG)ni, VNODEINST, x_("EDTEC_connects")); else
2768 {
2769 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_connects"), (INTBIG)conlist,
2770 VNODEPROTO|VISARRAY|(yes<<VLENGTHSH));
2771 }
2772 }
2773 efree((CHAR *)conlist);
2774 efree((CHAR *)yesno);
2775 }
2776
us_tecedarcfunction(NODEINST * ni,INTBIG count,CHAR * par[])2777 void us_tecedarcfunction(NODEINST *ni, INTBIG count, CHAR *par[])
2778 {
2779 REGISTER void *infstr;
2780
2781 if (par[0][0] == 0)
2782 {
2783 us_abortcommand(_("Requires a layer function"));
2784 return;
2785 }
2786 infstr = initinfstr();
2787 addstringtoinfstr(infstr, TECEDNODETEXTFUNCTION);
2788 addstringtoinfstr(infstr, par[0]);
2789 us_tecedsetnode(ni, returninfstr(infstr));
2790 }
2791
us_tecedarcfixang(NODEINST * ni,INTBIG count,CHAR * par[])2792 void us_tecedarcfixang(NODEINST *ni, INTBIG count, CHAR *par[])
2793 {
2794 REGISTER void *infstr;
2795
2796 if (par[0][0] == 0)
2797 {
2798 us_abortcommand(_("Requires a yes or no"));
2799 return;
2800 }
2801 infstr = initinfstr();
2802 addstringtoinfstr(infstr, x_("Fixed-angle: "));
2803 addstringtoinfstr(infstr, par[0]);
2804 us_tecedsetnode(ni, returninfstr(infstr));
2805 }
2806
us_tecedarcwipes(NODEINST * ni,INTBIG count,CHAR * par[])2807 void us_tecedarcwipes(NODEINST *ni, INTBIG count, CHAR *par[])
2808 {
2809 REGISTER void *infstr;
2810
2811 if (par[0][0] == 0)
2812 {
2813 us_abortcommand(_("Requires a yes or no"));
2814 return;
2815 }
2816 infstr = initinfstr();
2817 addstringtoinfstr(infstr, x_("Wipes pins: "));
2818 addstringtoinfstr(infstr, par[0]);
2819 us_tecedsetnode(ni, returninfstr(infstr));
2820 }
2821
us_tecedarcnoextend(NODEINST * ni,INTBIG count,CHAR * par[])2822 void us_tecedarcnoextend(NODEINST *ni, INTBIG count, CHAR *par[])
2823 {
2824 REGISTER void *infstr;
2825
2826 if (par[0][0] == 0)
2827 {
2828 us_abortcommand(_("Requires a yes or no"));
2829 return;
2830 }
2831 infstr = initinfstr();
2832 addstringtoinfstr(infstr, x_("Extend arcs: "));
2833 addstringtoinfstr(infstr, par[0]);
2834 us_tecedsetnode(ni, returninfstr(infstr));
2835 }
2836
us_tecedarcinc(NODEINST * ni,INTBIG count,CHAR * par[])2837 void us_tecedarcinc(NODEINST *ni, INTBIG count, CHAR *par[])
2838 {
2839 REGISTER void *infstr;
2840
2841 if (par[0][0] == 0)
2842 {
2843 us_abortcommand(_("Requires an angle increment in degrees"));
2844 return;
2845 }
2846 infstr = initinfstr();
2847 addstringtoinfstr(infstr, x_("Angle increment: "));
2848 addstringtoinfstr(infstr, par[0]);
2849 us_tecedsetnode(ni, returninfstr(infstr));
2850 }
2851
us_tecednodefunction(NODEINST * ni,INTBIG count,CHAR * par[])2852 void us_tecednodefunction(NODEINST *ni, INTBIG count, CHAR *par[])
2853 {
2854 REGISTER void *infstr;
2855
2856 if (par[0][0] == 0)
2857 {
2858 us_abortcommand(_("Requires a node function"));
2859 return;
2860 }
2861 infstr = initinfstr();
2862 addstringtoinfstr(infstr, TECEDNODETEXTFUNCTION);
2863 addstringtoinfstr(infstr, par[0]);
2864 us_tecedsetnode(ni, returninfstr(infstr));
2865 }
2866
us_tecednodeserpentine(NODEINST * ni,INTBIG count,CHAR * par[])2867 void us_tecednodeserpentine(NODEINST *ni, INTBIG count, CHAR *par[])
2868 {
2869 REGISTER void *infstr;
2870
2871 if (par[0][0] == 0)
2872 {
2873 us_abortcommand(_("Requires a yes or no"));
2874 return;
2875 }
2876 infstr = initinfstr();
2877 addstringtoinfstr(infstr, x_("Serpentine transistor: "));
2878 addstringtoinfstr(infstr, par[0]);
2879 us_tecedsetnode(ni, returninfstr(infstr));
2880 }
2881
us_tecednodesquare(NODEINST * ni,INTBIG count,CHAR * par[])2882 void us_tecednodesquare(NODEINST *ni, INTBIG count, CHAR *par[])
2883 {
2884 REGISTER void *infstr;
2885
2886 if (par[0][0] == 0)
2887 {
2888 us_abortcommand(_("Requires a yes or no"));
2889 return;
2890 }
2891 infstr = initinfstr();
2892 addstringtoinfstr(infstr, x_("Square node: "));
2893 addstringtoinfstr(infstr, par[0]);
2894 us_tecedsetnode(ni, returninfstr(infstr));
2895 }
2896
us_tecednodewipes(NODEINST * ni,INTBIG count,CHAR * par[])2897 void us_tecednodewipes(NODEINST *ni, INTBIG count, CHAR *par[])
2898 {
2899 REGISTER void *infstr;
2900
2901 if (par[0][0] == 0)
2902 {
2903 us_abortcommand(_("Requires a yes or no"));
2904 return;
2905 }
2906 infstr = initinfstr();
2907 addstringtoinfstr(infstr, x_("Invisible with 1 or 2 arcs: "));
2908 addstringtoinfstr(infstr, par[0]);
2909 us_tecedsetnode(ni, returninfstr(infstr));
2910 }
2911
us_tecednodelockable(NODEINST * ni,INTBIG count,CHAR * par[])2912 void us_tecednodelockable(NODEINST *ni, INTBIG count, CHAR *par[])
2913 {
2914 REGISTER void *infstr;
2915
2916 if (par[0][0] == 0)
2917 {
2918 us_abortcommand(_("Requires a yes or no"));
2919 return;
2920 }
2921 infstr = initinfstr();
2922 addstringtoinfstr(infstr, x_("Lockable: "));
2923 addstringtoinfstr(infstr, par[0]);
2924 us_tecedsetnode(ni, returninfstr(infstr));
2925 }
2926
us_tecednodemulticut(NODEINST * ni,INTBIG count,CHAR * par[])2927 void us_tecednodemulticut(NODEINST *ni, INTBIG count, CHAR *par[])
2928 {
2929 REGISTER void *infstr;
2930
2931 if (par[0][0] == 0)
2932 {
2933 us_abortcommand(_("Requires a separation distance (0 for none)"));
2934 return;
2935 }
2936 infstr = initinfstr();
2937 addstringtoinfstr(infstr, x_("Multicut separation: "));
2938 addstringtoinfstr(infstr, par[0]);
2939 us_tecedsetnode(ni, returninfstr(infstr));
2940 }
2941
us_tecedinfolambda(NODEINST * ni,INTBIG count,CHAR * par[])2942 void us_tecedinfolambda(NODEINST *ni, INTBIG count, CHAR *par[])
2943 {
2944 REGISTER void *infstr;
2945
2946 if (par[0][0] == 0)
2947 {
2948 us_abortcommand(_("Requires a value of lambda"));
2949 return;
2950 }
2951 infstr = initinfstr();
2952 addstringtoinfstr(infstr, x_("Lambda: "));
2953 addstringtoinfstr(infstr, par[0]);
2954 us_tecedsetnode(ni, returninfstr(infstr));
2955 }
2956
us_tecedinfodescript(NODEINST * ni,INTBIG count,CHAR * par[])2957 void us_tecedinfodescript(NODEINST *ni, INTBIG count, CHAR *par[])
2958 {
2959 REGISTER void *infstr;
2960
2961 if (par[0][0] == 0)
2962 {
2963 us_abortcommand(_("Requires a technology description"));
2964 return;
2965 }
2966 infstr = initinfstr();
2967 addstringtoinfstr(infstr, x_("Description: "));
2968 addstringtoinfstr(infstr, par[0]);
2969 us_tecedsetnode(ni, returninfstr(infstr));
2970 }
2971
2972 /****************************** UTILITIES ******************************/
2973
us_tecedsetnode(NODEINST * ni,CHAR * chr)2974 void us_tecedsetnode(NODEINST *ni, CHAR *chr)
2975 {
2976 UINTBIG descript[TEXTDESCRIPTSIZE];
2977 REGISTER VARIABLE *var;
2978 CHAR *newmsg;
2979
2980 allocstring(&newmsg, chr, el_tempcluster);
2981 startobjectchange((INTBIG)ni, VNODEINST);
2982 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
2983 if (var == NOVARIABLE) TDCLEAR(descript); else TDCOPY(descript, var->textdescript);
2984 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)newmsg, VSTRING|VDISPLAY);
2985 if (var != NOVARIABLE) modifydescript((INTBIG)ni, VNODEINST, var, descript);
2986 endobjectchange((INTBIG)ni, VNODEINST);
2987 efree((CHAR *)newmsg);
2988 }
2989
2990 /*
2991 * routine to call up the cell "cellname" (either create it or reedit it)
2992 * returns NONODEPROTO if there is an error or the cell exists
2993 */
us_tecedentercell(CHAR * cellname)2994 NODEPROTO *us_tecedentercell(CHAR *cellname)
2995 {
2996 REGISTER NODEPROTO *np;
2997 CHAR *newpar[2];
2998
2999 np = getnodeproto(cellname);
3000 if (np != NONODEPROTO && np->primindex == 0)
3001 {
3002 newpar[0] = x_("editcell");
3003 newpar[1] = cellname;
3004 telltool(us_tool, 2, newpar);
3005 return(NONODEPROTO);
3006 }
3007
3008 /* create the cell */
3009 np = newnodeproto(cellname, el_curlib);
3010 if (np == NONODEPROTO) return(NONODEPROTO);
3011
3012 /* now edit the cell */
3013 newpar[0] = x_("editcell");
3014 newpar[1] = cellname;
3015 telltool(us_tool, 2, newpar);
3016 return(np);
3017 }
3018
3019 /*
3020 * routine to redraw the demo layer in "layer" cell "np"
3021 */
us_tecedredolayergraphics(NODEPROTO * np)3022 void us_tecedredolayergraphics(NODEPROTO *np)
3023 {
3024 REGISTER VARIABLE *var;
3025 REGISTER NODEINST *ni;
3026 GRAPHICS desc;
3027 REGISTER NODEPROTO *onp;
3028 CHAR *cif, *layerletters, *dxf, *gds;
3029 INTBIG func, drcminwid, height3d, thick3d, printcol[5];
3030 float spires, spicap, spiecap;
3031
3032 /* find the demo patch in this cell */
3033 var = getval((INTBIG)np, VNODEPROTO, VNODEINST, x_("EDTEC_colornode"));
3034 if (var == NOVARIABLE) return;
3035 ni = (NODEINST *)var->addr;
3036
3037 /* get the current description of this layer */
3038 cif = layerletters = gds = 0;
3039 if (us_teceditgetlayerinfo(np, &desc, &cif, &func, &layerletters,
3040 &dxf, &gds, &spires, &spicap, &spiecap, &drcminwid, &height3d,
3041 &thick3d, printcol)) return;
3042 if (gds != 0) efree(gds);
3043 if (cif != 0) efree(cif);
3044 if (layerletters != 0) efree(layerletters);
3045
3046 /* modify the demo patch to reflect the color and pattern */
3047 startobjectchange((INTBIG)ni, VNODEINST);
3048 us_teceditsetpatch(ni, &desc);
3049 endobjectchange((INTBIG)ni, VNODEINST);
3050
3051 /* now do this to all layers in all cells! */
3052 for(onp = el_curlib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
3053 {
3054 if (namesamen(onp->protoname, x_("arc-"), 4) != 0 &&
3055 namesamen(onp->protoname, x_("node-"), 5) != 0) continue;
3056 for(ni = onp->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3057 {
3058 if (us_tecedgetoption(ni) != LAYERPATCH) continue;
3059 var = getval((INTBIG)ni, VNODEINST, VNODEPROTO, x_("EDTEC_layer"));
3060 if (var == NOVARIABLE) continue;
3061 if ((NODEPROTO *)var->addr != np) continue;
3062 us_teceditsetpatch(ni, &desc);
3063 }
3064 }
3065 }
3066
us_teceditsetpatch(NODEINST * ni,GRAPHICS * desc)3067 void us_teceditsetpatch(NODEINST *ni, GRAPHICS *desc)
3068 {
3069 REGISTER INTBIG i;
3070 UINTBIG pattern[16];
3071 UINTSML spattern[16];
3072
3073 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, desc->col, VINTEGER);
3074 if ((desc->colstyle&NATURE) == PATTERNED)
3075 {
3076 if ((desc->colstyle&OUTLINEPAT) == 0)
3077 {
3078 for(i=0; i<16; i++) pattern[i] = desc->raster[i];
3079 (void)setvalkey((INTBIG)ni, VNODEINST, art_patternkey, (INTBIG)pattern,
3080 VINTEGER|VISARRAY|(16<<VLENGTHSH));
3081 } else
3082 {
3083 for(i=0; i<16; i++) spattern[i] = desc->raster[i];
3084 (void)setvalkey((INTBIG)ni, VNODEINST, art_patternkey, (INTBIG)spattern,
3085 VSHORT|VISARRAY|(16<<VLENGTHSH));
3086 }
3087 } else
3088 {
3089 if (getvalkey((INTBIG)ni, VNODEINST, -1, art_patternkey) != NOVARIABLE)
3090 (void)delvalkey((INTBIG)ni, VNODEINST, art_patternkey);
3091 }
3092 }
3093
3094 /*
3095 * routine to load the color map associated with library "lib"
3096 */
us_tecedloadlibmap(LIBRARY * lib)3097 void us_tecedloadlibmap(LIBRARY *lib)
3098 {
3099 REGISTER VARIABLE *var;
3100 REGISTER INTBIG i;
3101 REGISTER INTBIG *mapptr;
3102 INTBIG redmap[256], greenmap[256], bluemap[256];
3103
3104 var = getval((INTBIG)lib, VLIBRARY, VINTEGER|VISARRAY, x_("EDTEC_colormap"));
3105 if (var != NOVARIABLE)
3106 {
3107 mapptr = (INTBIG *)var->addr;
3108 for(i=0; i<256; i++)
3109 {
3110 redmap[i] = *mapptr++;
3111 greenmap[i] = *mapptr++;
3112 bluemap[i] = *mapptr++;
3113 }
3114
3115 /* disable option tracking */
3116 (void)setvalkey((INTBIG)us_tool, VTOOL, us_ignoreoptionchangeskey, 1,
3117 VINTEGER|VDONTSAVE);
3118
3119 startobjectchange((INTBIG)us_tool, VTOOL);
3120 (void)setvalkey((INTBIG)us_tool, VTOOL, us_colormap_red_key, (INTBIG)redmap,
3121 VINTEGER|VISARRAY|(256<<VLENGTHSH));
3122 (void)setvalkey((INTBIG)us_tool, VTOOL, us_colormap_green_key, (INTBIG)greenmap,
3123 VINTEGER|VISARRAY|(256<<VLENGTHSH));
3124 (void)setvalkey((INTBIG)us_tool, VTOOL, us_colormap_blue_key, (INTBIG)bluemap,
3125 VINTEGER|VISARRAY|(256<<VLENGTHSH));
3126 endobjectchange((INTBIG)us_tool, VTOOL);
3127
3128 /* re-enable option tracking */
3129 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_ignoreoptionchangeskey);
3130 if (var != NOVARIABLE)
3131 (void)delvalkey((INTBIG)us_tool, VTOOL, us_ignoreoptionchangeskey);
3132 }
3133 }
3134
3135 /*
3136 * routine to parse the layer cell in "np" and fill these reference descriptors:
3137 * "desc" (a GRAPHICS structure)
3138 * "cif" (the name of the CIF layer)
3139 * "dxf" (the name of the DXF layer)
3140 * "func" (the integer function number)
3141 * "layerletters" (the letters associated with this layer),
3142 * "gds" (the Calma GDS-II layer number)
3143 * "spires" (the SPICE resistance)
3144 * "spicap" (the SPICE capacitance)
3145 * "spiecap" (the SPICE edge capacitance)
3146 * "drcminwid" (the DRC minimum width)
3147 * "height3d" (the 3D height)
3148 * "thick3d" (the 3D thickness)
3149 * "printcol" (the printer colors)
3150 * All of the reference parameters except "func", "spires", "spicap", and "spiecap"
3151 * get allocated. Returns true on error.
3152 */
us_teceditgetlayerinfo(NODEPROTO * np,GRAPHICS * desc,CHAR ** cif,INTBIG * func,CHAR ** layerletters,CHAR ** dxf,CHAR ** gds,float * spires,float * spicap,float * spiecap,INTBIG * drcminwid,INTBIG * height3d,INTBIG * thick3d,INTBIG * printcol)3153 BOOLEAN us_teceditgetlayerinfo(NODEPROTO *np, GRAPHICS *desc, CHAR **cif, INTBIG *func,
3154 CHAR **layerletters, CHAR **dxf, CHAR **gds, float *spires, float *spicap,
3155 float *spiecap, INTBIG *drcminwid, INTBIG *height3d, INTBIG *thick3d, INTBIG *printcol)
3156 {
3157 REGISTER NODEINST *ni;
3158 REGISTER INTBIG patterncount, i, color, len;
3159 REGISTER INTBIG lowx, highx, lowy, highy, x, y;
3160 REGISTER CHAR *str;
3161 REGISTER VARIABLE *var, *varkey;
3162
3163 /* create and initialize the GRAPHICS structure */
3164 desc->colstyle = SOLIDC;
3165 desc->bwstyle = PATTERNED;
3166 for(i=0; i<16; i++) desc->raster[i] = 0;
3167
3168 /* look at all nodes in the layer description cell */
3169 patterncount = 0;
3170 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3171 {
3172 varkey = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
3173 if (varkey == NOVARIABLE) continue;
3174 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
3175 if (var == NOVARIABLE) str = ""; else
3176 {
3177 str = (CHAR *)var->addr;
3178 while (*str != 0 && *str != ':') str++;
3179 if (*str == ':') str++;
3180 while (*str == ' ') str++;
3181 }
3182
3183 switch (varkey->addr)
3184 {
3185 case LAYERPATTERN:
3186 if (patterncount == 0)
3187 {
3188 lowx = ni->lowx; highx = ni->highx;
3189 lowy = ni->lowy; highy = ni->highy;
3190 } else
3191 {
3192 if (ni->lowx < lowx) lowx = ni->lowx;
3193 if (ni->highx > highx) highx = ni->highx;
3194 if (ni->lowy < lowy) lowy = ni->lowy;
3195 if (ni->highy > highy) highy = ni->highy;
3196 }
3197 patterncount++;
3198 break;
3199 case LAYERCOLOR:
3200 color = getecolor(str);
3201 if (color < 0)
3202 {
3203 ttyputerr(_("Unknown color '%s' in %s"), str, describenodeproto(np));
3204 return(TRUE);
3205 }
3206 desc->col = color;
3207 switch (color)
3208 {
3209 case COLORT1: desc->bits = LAYERT1; break;
3210 case COLORT2: desc->bits = LAYERT2; break;
3211 case COLORT3: desc->bits = LAYERT3; break;
3212 case COLORT4: desc->bits = LAYERT4; break;
3213 case COLORT5: desc->bits = LAYERT5; break;
3214 default: desc->bits = LAYERO; break;
3215 }
3216 break;
3217 case LAYERSTYLE:
3218 if (namesame(str, x_("solid")) == 0)
3219 desc->colstyle = desc->bwstyle = SOLIDC;
3220 if (namesame(str, x_("patterned")) == 0)
3221 desc->colstyle = desc->bwstyle = PATTERNED;
3222 if (namesame(str, x_("patterned/outlined")) == 0)
3223 desc->colstyle = desc->bwstyle = PATTERNED | OUTLINEPAT;
3224 break;
3225 case LAYERCIF:
3226 if (allocstring(cif, str, us_tool->cluster)) return(TRUE);
3227 break;
3228 case LAYERDXF:
3229 if (allocstring(dxf, str, us_tool->cluster)) return(TRUE);
3230 break;
3231 case LAYERGDS:
3232 if (namesame(str, x_("-1")) == 0) str = x_("");
3233 if (allocstring(gds, str, us_tool->cluster)) return(TRUE);
3234 break;
3235 case LAYERFUNCTION:
3236 *func = us_teceditparsefun(str);
3237 break;
3238 case LAYERLETTERS:
3239 if (allocstring(layerletters, str, us_tool->cluster)) return(TRUE);
3240 break;
3241 case LAYERSPIRES:
3242 *spires = (float)eatof(str);
3243 break;
3244 case LAYERSPICAP:
3245 *spicap = (float)eatof(str);
3246 break;
3247 case LAYERSPIECAP:
3248 *spiecap = (float)eatof(str);
3249 break;
3250 case LAYERDRCMINWID:
3251 *drcminwid = atofr(str);
3252 break;
3253 case LAYER3DHEIGHT:
3254 *height3d = myatoi(str);
3255 break;
3256 case LAYER3DTHICK:
3257 *thick3d = myatoi(str);
3258 break;
3259 case LAYERPRINTCOL:
3260 us_teceditgetprintcol(var, &printcol[0], &printcol[1], &printcol[2],
3261 &printcol[3], &printcol[4]);
3262 break;
3263 }
3264 }
3265
3266 if (patterncount != 16*16 && patterncount != 16*8)
3267 {
3268 ttyputerr(_("Incorrect number of pattern boxes in %s (has %ld, not %d)"),
3269 describenodeproto(np), patterncount, 16*16);
3270 return(TRUE);
3271 }
3272
3273 /* construct the pattern */
3274 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3275 {
3276 if (ni->proto != art_filledboxprim) continue;
3277 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
3278 if (var == NOVARIABLE) continue;
3279 if (var->addr != LAYERPATTERN) continue;
3280 var = getvalkey((INTBIG)ni, VNODEINST, VSHORT|VISARRAY, art_patternkey);
3281 if (var != NOVARIABLE)
3282 {
3283 len = getlength(var);
3284 for(i=0; i<len; i++) if (((INTSML *)var->addr)[i] != 0) break;
3285 if (i >= len) continue;
3286 }
3287 x = (ni->lowx - lowx) / ((highx-lowx) / 16);
3288 y = (highy - ni->highy) / ((highy-lowy) / 16);
3289 desc->raster[y] |= (1 << (15-x));
3290 }
3291 if (patterncount == 16*8)
3292 {
3293 /* older, half-height pattern: replicate it */
3294 for(y=0; y<8; y++)
3295 desc->raster[y+8] = desc->raster[y];
3296 }
3297 return(FALSE);
3298 }
3299
us_teceditgetprintcol(VARIABLE * var,INTBIG * r,INTBIG * g,INTBIG * b,INTBIG * o,INTBIG * f)3300 void us_teceditgetprintcol(VARIABLE *var, INTBIG *r, INTBIG *g, INTBIG *b, INTBIG *o, INTBIG *f)
3301 {
3302 REGISTER CHAR *pt;
3303
3304 /* set default values */
3305 *r = *g = *b = *o = *f = 0;
3306 if (var == NOVARIABLE) return;
3307
3308 /* skip the header */
3309 pt = (CHAR *)var->addr;
3310 while (*pt != 0 && *pt != ':') pt++;
3311 if (*pt == ':') pt++;
3312
3313 /* get red */
3314 while (*pt == ' ') pt++;
3315 *r = myatoi(pt);
3316 while (*pt != 0 && *pt != ',') pt++;
3317 if (*pt == ',') pt++;
3318
3319 /* get green */
3320 while (*pt == ' ') pt++;
3321 *g = myatoi(pt);
3322 while (*pt != 0 && *pt != ',') pt++;
3323 if (*pt == ',') pt++;
3324
3325 /* get blue */
3326 while (*pt == ' ') pt++;
3327 *b = myatoi(pt);
3328 while (*pt != 0 && *pt != ',') pt++;
3329 if (*pt == ',') pt++;
3330
3331 /* get opacity */
3332 while (*pt == ' ') pt++;
3333 *o = myatoi(pt);
3334 while (*pt != 0 && *pt != ',') pt++;
3335 if (*pt == ',') pt++;
3336
3337 /* get foreground */
3338 while (*pt == ' ') pt++;
3339 if (namesamen(pt, x_("on"), 2) == 0) *f = 1; else
3340 if (namesamen(pt, x_("off"), 3) == 0) *f = 0; else
3341 *f = myatoi(pt);
3342 }
3343
3344 /*
3345 * Routine to set the layer-pattern squares of cell "np" to the bits in "desc".
3346 */
us_teceditsetlayerpattern(NODEPROTO * np,GRAPHICS * desc)3347 void us_teceditsetlayerpattern(NODEPROTO *np, GRAPHICS *desc)
3348 {
3349 REGISTER NODEINST *ni;
3350 REGISTER INTBIG patterncount;
3351 REGISTER INTBIG lowx, highx, lowy, highy, x, y;
3352 REGISTER INTSML wantcolor, color;
3353 REGISTER VARIABLE *var;
3354
3355 /* look at all nodes in the layer description cell */
3356 patterncount = 0;
3357 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3358 {
3359 if (ni->proto == art_boxprim || ni->proto == art_filledboxprim)
3360 {
3361 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
3362 if (var == NOVARIABLE) continue;
3363 if (var->addr != LAYERPATTERN) continue;
3364 if (patterncount == 0)
3365 {
3366 lowx = ni->lowx; highx = ni->highx;
3367 lowy = ni->lowy; highy = ni->highy;
3368 } else
3369 {
3370 if (ni->lowx < lowx) lowx = ni->lowx;
3371 if (ni->highx > highx) highx = ni->highx;
3372 if (ni->lowy < lowy) lowy = ni->lowy;
3373 if (ni->highy > highy) highy = ni->highy;
3374 }
3375 patterncount++;
3376 }
3377 }
3378
3379 if (patterncount != 16*16 && patterncount != 16*8)
3380 {
3381 ttyputerr(_("Incorrect number of pattern boxes in %s (has %ld, not %d)"),
3382 describenodeproto(np), patterncount, 16*16);
3383 return;
3384 }
3385
3386 /* set the pattern */
3387 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3388 {
3389 if (ni->proto != art_boxprim && ni->proto != art_filledboxprim) continue;
3390 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
3391 if (var == NOVARIABLE) continue;
3392 if (var->addr != LAYERPATTERN) continue;
3393
3394 x = (ni->lowx - lowx) / ((highx-lowx) / 16);
3395 y = (highy - ni->highy) / ((highy-lowy) / 16);
3396 if ((desc->raster[y] & (1 << (15-x))) == 0) wantcolor = 0;
3397 else wantcolor = (INTSML)0xFFFF;
3398
3399 color = us_tecedlayergetpattern(ni);
3400 if (color != wantcolor)
3401 us_tecedlayersetpattern(ni, wantcolor);
3402 }
3403 }
3404
3405 /*
3406 * routine to parse the layer function string "str" and return the
3407 * actual function codes
3408 */
us_teceditparsefun(CHAR * str)3409 INTBIG us_teceditparsefun(CHAR *str)
3410 {
3411 REGISTER INTBIG func, save, i;
3412 REGISTER CHAR *pt;
3413
3414 func = 0;
3415 for(;;)
3416 {
3417 /* find the next layer function name */
3418 pt = str;
3419 while (*pt != 0 && *pt != ',') pt++;
3420
3421 /* parse the name */
3422 save = *pt;
3423 *pt = 0;
3424 for(i=0; us_teclayer_functions[i].name != 0; i++)
3425 if (namesame(str, us_teclayer_functions[i].name) == 0) break;
3426 *pt = (CHAR)save;
3427 if (us_teclayer_functions[i].name == 0)
3428 {
3429 ttyputerr(_("Unknown layer function: %s"), str);
3430 return(0);
3431 }
3432
3433 /* mix in the layer function */
3434 if (us_teclayer_functions[i].value <= LFTYPE)
3435 {
3436 if (func != 0)
3437 {
3438 ttyputerr(_("Cannot be both function %s and %s"),
3439 us_teclayer_functions[func&LFTYPE].name, us_teclayer_functions[i].name);
3440 func = 0;
3441 }
3442 func = us_teclayer_functions[i].value;
3443 } else func |= us_teclayer_functions[i].value;
3444
3445 /* advance to the next layer function name */
3446 if (*pt == 0) break;
3447 str = pt + 1;
3448 }
3449 return(func);
3450 }
3451
3452 /*
3453 * routine to return the option index of node "ni"
3454 */
us_tecedgetoption(NODEINST * ni)3455 INTBIG us_tecedgetoption(NODEINST *ni)
3456 {
3457 REGISTER VARIABLE *var, *var2;
3458 REGISTER NODEPROTO *np;
3459
3460 /* port objects are readily identifiable */
3461 if (ni->proto == gen_portprim) return(PORTOBJ);
3462
3463 /* center objects are also readily identifiable */
3464 if (ni->proto == gen_cellcenterprim) return(CENTEROBJ);
3465
3466 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
3467 if (var == NOVARIABLE) return(-1);
3468 if (var->addr == LAYERPATCH)
3469 {
3470 /* may be a highlight object */
3471 var2 = getval((INTBIG)ni, VNODEINST, VNODEPROTO, x_("EDTEC_layer"));
3472 if (var2 != NOVARIABLE)
3473 {
3474 np = (NODEPROTO *)var2->addr;
3475 if (np == NONODEPROTO) return(HIGHLIGHTOBJ);
3476 }
3477 }
3478 return(var->addr);
3479 }
3480
3481 /*
3482 * Routine called when cell "np" has been deleted (and it may be a layer cell because its name
3483 * started with "layer-").
3484 */
us_teceddeletelayercell(NODEPROTO * np)3485 void us_teceddeletelayercell(NODEPROTO *np)
3486 {
3487 REGISTER VARIABLE *var;
3488 REGISTER NODEPROTO *onp;
3489 REGISTER NODEINST *ni;
3490 REGISTER BOOLEAN warned, isnode;
3491 REGISTER CHAR *layername;
3492 static INTBIG edtec_layer_key = 0;
3493 REGISTER void *infstr;
3494
3495 /* may have deleted layer cell in technology library */
3496 if (edtec_layer_key == 0) edtec_layer_key = makekey(x_("EDTEC_layer"));
3497 layername = &np->protoname[6];
3498 warned = FALSE;
3499 for(onp = np->lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
3500 {
3501 if (namesamen(onp->protoname, x_("node-"), 5) == 0) isnode = TRUE; else
3502 if (namesamen(onp->protoname, x_("arc-"), 4) == 0) isnode = FALSE; else
3503 continue;
3504 for(ni = onp->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3505 {
3506 var = getvalkey((INTBIG)ni, VNODEINST, VNODEPROTO, edtec_layer_key);
3507 if (var == NOVARIABLE) continue;
3508 if ((NODEPROTO *)var->addr == np) break;
3509 }
3510 if (ni != NONODEINST)
3511 {
3512 if (warned) addtoinfstr(infstr, ','); else
3513 {
3514 infstr = initinfstr();
3515 formatinfstr(infstr, _("Warning: layer %s is used in"), layername);
3516 warned = TRUE;
3517 }
3518 if (isnode) formatinfstr(infstr, _(" node %s"), &onp->protoname[5]); else
3519 formatinfstr(infstr, _(" arc %s"), &onp->protoname[4]);
3520 }
3521 }
3522 if (warned)
3523 ttyputmsg(x_("%s"), returninfstr(infstr));
3524
3525 /* see if this layer is mentioned in the design rules */
3526 us_tecedrenamecell(np->protoname, x_(""));
3527 }
3528
3529 /*
3530 * Routine called when cell "np" has been deleted (and it may be a node cell because its name
3531 * started with "node-").
3532 */
us_teceddeletenodecell(NODEPROTO * np)3533 void us_teceddeletenodecell(NODEPROTO *np)
3534 {
3535 /* see if this node is mentioned in the design rules */
3536 us_tecedrenamecell(np->protoname, x_(""));
3537 }
3538
3539 /******************** SUPPORT FOR "usredtecp.c" ROUTINES ********************/
3540
3541 /*
3542 * routine to return the actual bounding box of layer node "ni" in the
3543 * reference variables "lx", "hx", "ly", and "hy"
3544 */
us_tecedgetbbox(NODEINST * ni,INTBIG * lx,INTBIG * hx,INTBIG * ly,INTBIG * hy)3545 void us_tecedgetbbox(NODEINST *ni, INTBIG *lx, INTBIG *hx, INTBIG *ly, INTBIG *hy)
3546 {
3547 REGISTER INTBIG twolambda;
3548
3549 *lx = ni->geom->lowx;
3550 *hx = ni->geom->highx;
3551 *ly = ni->geom->lowy;
3552 *hy = ni->geom->highy;
3553 if (ni->proto != gen_portprim) return;
3554 twolambda = lambdaofnode(ni) * 2;
3555 *lx += twolambda; *hx -= twolambda;
3556 *ly += twolambda; *hy -= twolambda;
3557 }
3558
us_tecedpointout(NODEINST * ni,NODEPROTO * np)3559 void us_tecedpointout(NODEINST *ni, NODEPROTO *np)
3560 {
3561 REGISTER WINDOWPART *w;
3562 CHAR *newpar[2];
3563
3564 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
3565 if (w->curnodeproto == np) break;
3566 if (w == NOWINDOWPART)
3567 {
3568 newpar[0] = describenodeproto(np);
3569 us_editcell(1, newpar);
3570 }
3571 if (ni != NONODEINST)
3572 {
3573 us_clearhighlightcount();
3574 (void)asktool(us_tool, x_("show-object"), (INTBIG)ni->geom);
3575 }
3576 }
3577
3578 /*
3579 * routine to swap entries "p1" and "p2" of the port list in "tlist"
3580 */
us_tecedswapports(INTBIG * p1,INTBIG * p2,TECH_NODES * tlist)3581 void us_tecedswapports(INTBIG *p1, INTBIG *p2, TECH_NODES *tlist)
3582 {
3583 REGISTER INTBIG temp, *templ;
3584 REGISTER CHAR *tempc;
3585
3586 templ = tlist->portlist[*p1].portarcs;
3587 tlist->portlist[*p1].portarcs = tlist->portlist[*p2].portarcs;
3588 tlist->portlist[*p2].portarcs = templ;
3589
3590 tempc = tlist->portlist[*p1].protoname;
3591 tlist->portlist[*p1].protoname = tlist->portlist[*p2].protoname;
3592 tlist->portlist[*p2].protoname = tempc;
3593
3594 temp = tlist->portlist[*p1].initialbits;
3595 tlist->portlist[*p1].initialbits = tlist->portlist[*p2].initialbits;
3596 tlist->portlist[*p2].initialbits = temp;
3597
3598 temp = tlist->portlist[*p1].lowxmul;
3599 tlist->portlist[*p1].lowxmul = tlist->portlist[*p2].lowxmul;
3600 tlist->portlist[*p2].lowxmul = (INTSML)temp;
3601 temp = tlist->portlist[*p1].lowxsum;
3602 tlist->portlist[*p1].lowxsum = tlist->portlist[*p2].lowxsum;
3603 tlist->portlist[*p2].lowxsum = (INTSML)temp;
3604
3605 temp = tlist->portlist[*p1].lowymul;
3606 tlist->portlist[*p1].lowymul = tlist->portlist[*p2].lowymul;
3607 tlist->portlist[*p2].lowymul = (INTSML)temp;
3608 temp = tlist->portlist[*p1].lowysum;
3609 tlist->portlist[*p1].lowysum = tlist->portlist[*p2].lowysum;
3610 tlist->portlist[*p2].lowysum = (INTSML)temp;
3611
3612 temp = tlist->portlist[*p1].highxmul;
3613 tlist->portlist[*p1].highxmul = tlist->portlist[*p2].highxmul;
3614 tlist->portlist[*p2].highxmul = (INTSML)temp;
3615 temp = tlist->portlist[*p1].highxsum;
3616 tlist->portlist[*p1].highxsum = tlist->portlist[*p2].highxsum;
3617 tlist->portlist[*p2].highxsum = (INTSML)temp;
3618
3619 temp = tlist->portlist[*p1].highymul;
3620 tlist->portlist[*p1].highymul = tlist->portlist[*p2].highymul;
3621 tlist->portlist[*p2].highymul = (INTSML)temp;
3622 temp = tlist->portlist[*p1].highysum;
3623 tlist->portlist[*p1].highysum = tlist->portlist[*p2].highysum;
3624 tlist->portlist[*p2].highysum = (INTSML)temp;
3625
3626 /* finally, swap the actual identifiers */
3627 temp = *p1; *p1 = *p2; *p2 = temp;
3628 }
3629
us_tecedsamplename(NODEPROTO * layernp)3630 CHAR *us_tecedsamplename(NODEPROTO *layernp)
3631 {
3632 if (layernp == gen_portprim) return(x_("PORT"));
3633 if (layernp == gen_cellcenterprim) return(x_("GRAB"));
3634 if (layernp == NONODEPROTO) return(x_("HIGHLIGHT"));
3635 return(&layernp->protoname[6]);
3636 }
3637
3638 /* Technology Edit Reorder */
3639 static DIALOGITEM us_tecedredialogitems[] =
3640 {
3641 /* 1 */ {0, {376,208,400,288}, BUTTON, N_("OK")},
3642 /* 2 */ {0, {344,208,368,288}, BUTTON, N_("Cancel")},
3643 /* 3 */ {0, {28,4,404,200}, SCROLL, x_("")},
3644 /* 4 */ {0, {4,4,20,284}, MESSAGE, x_("")},
3645 /* 5 */ {0, {168,208,192,268}, BUTTON, N_("Up")},
3646 /* 6 */ {0, {212,208,236,268}, BUTTON, N_("Down")},
3647 /* 7 */ {0, {136,208,160,280}, BUTTON, N_("Far Up")},
3648 /* 8 */ {0, {244,208,268,280}, BUTTON, N_("Far Down")}
3649 };
3650 static DIALOG us_tecedredialog = {{75,75,488,373}, N_("Reorder Technology Primitives"), 0, 8, us_tecedredialogitems, 0, 0};
3651
3652 /* special items for the "Reorder Primitives" dialog: */
3653 #define DTER_LIST 3 /* List of primitives (scroll) */
3654 #define DTER_TITLE 4 /* Primitive title (message) */
3655 #define DTER_UP 5 /* Move Up (button) */
3656 #define DTER_DOWN 6 /* Move Down (button) */
3657 #define DTER_FARUP 7 /* Move Far Up (button) */
3658 #define DTER_FARDOWN 8 /* Move Far Down (button) */
3659
us_reorderprimdlog(CHAR * type,CHAR * prefix,CHAR * varname)3660 void us_reorderprimdlog(CHAR *type, CHAR *prefix, CHAR *varname)
3661 {
3662 REGISTER INTBIG itemHit, i, j, total, len, amt;
3663 CHAR line[100], **seqname;
3664 REGISTER BOOLEAN changed;
3665 LIBRARY *thelib[1];
3666 NODEPROTO **sequence, *np;
3667 REGISTER void *dia;
3668
3669 dia = DiaInitDialog(&us_tecedredialog);
3670 if (dia == 0) return;
3671 DiaInitTextDialog(dia, DTER_LIST, DiaNullDlogList, DiaNullDlogItem,
3672 DiaNullDlogDone, -1, SCSELMOUSE);
3673 esnprintf(line, 100, _("%s in technology %s"), type, el_curlib->libname);
3674 DiaSetText(dia, DTER_TITLE, line);
3675 thelib[0] = el_curlib;
3676 total = us_teceditfindsequence(thelib, 1, prefix, varname, &sequence);
3677 len = strlen(prefix);
3678 for(i=0; i<total; i++)
3679 DiaStuffLine(dia, DTER_LIST, &sequence[i]->protoname[len]);
3680 DiaSelectLine(dia, DTER_LIST, 0);
3681
3682 changed = FALSE;
3683 for(;;)
3684 {
3685 itemHit = DiaNextHit(dia);
3686 if (itemHit == OK || itemHit == CANCEL) break;
3687 if (itemHit == DTER_UP || itemHit == DTER_FARUP)
3688 {
3689 /* shift up */
3690 if (itemHit == DTER_UP) amt = 1; else amt = 10;
3691 for(j=0; j<amt; j++)
3692 {
3693 i = DiaGetCurLine(dia, DTER_LIST);
3694 if (i <= 0) break;
3695 np = sequence[i];
3696 sequence[i] = sequence[i-1];
3697 sequence[i-1] = np;
3698 DiaSetScrollLine(dia, DTER_LIST, i, &sequence[i]->protoname[len]);
3699 DiaSetScrollLine(dia, DTER_LIST, i-1, &sequence[i-1]->protoname[len]);
3700 }
3701 changed = TRUE;
3702 continue;
3703 }
3704 if (itemHit == DTER_DOWN || itemHit == DTER_FARDOWN)
3705 {
3706 /* shift down */
3707 if (itemHit == DTER_DOWN) amt = 1; else amt = 10;
3708 for(j=0; j<amt; j++)
3709 {
3710 i = DiaGetCurLine(dia, DTER_LIST);
3711 if (i >= total-1) continue;
3712 np = sequence[i];
3713 sequence[i] = sequence[i+1];
3714 sequence[i+1] = np;
3715 DiaSetScrollLine(dia, DTER_LIST, i, &sequence[i]->protoname[len]);
3716 DiaSetScrollLine(dia, DTER_LIST, i+1, &sequence[i+1]->protoname[len]);
3717 }
3718 changed = TRUE;
3719 continue;
3720 }
3721 }
3722
3723 /* preserve order */
3724 if (itemHit == OK && changed)
3725 {
3726 seqname = (CHAR **)emalloc(total * (sizeof (CHAR *)), el_tempcluster);
3727 for(i=0; i<total; i++)
3728 seqname[i] = &sequence[i]->protoname[len];
3729 setval((INTBIG)el_curlib, VLIBRARY, varname, (INTBIG)seqname,
3730 VSTRING|VISARRAY|(total<<VLENGTHSH));
3731 efree((CHAR *)seqname);
3732 }
3733 efree((CHAR *)sequence);
3734 DiaDoneDialog(dia);
3735 }
3736