1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: simfasthenry.cpp
6  * Simulation tool: FastHenry output
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 "config.h"
33 #if SIMTOOL
34 
35 #include "global.h"
36 #include "sim.h"
37 #include "usr.h"
38 #include "edialogs.h"
39 
40 
41 /* keys to cached variables */
42 INTBIG sim_fasthenrystatekey = 0;			/* variable key for "SIM_fasthenry_state" */
43 INTBIG sim_fasthenryfreqstartkey = 0;		/* variable key for "SIM_fasthenry_freqstart" */
44 INTBIG sim_fasthenryfreqendkey = 0;			/* variable key for "SIM_fasthenry_freqend" */
45 INTBIG sim_fasthenryrunsperdecadekey = 0;	/* variable key for "SIM_fasthenry_runsperdecade" */
46 INTBIG sim_fasthenrynumpoleskey = 0;		/* variable key for "SIM_fasthenry_numpoles" */
47 INTBIG sim_fasthenryseglimitkey = 0;		/* variable key for "SIM_fasthenry_seglimit" */
48 INTBIG sim_fasthenrythicknesskey = 0;		/* variable key for "SIM_fasthenry_thickness" */
49 INTBIG sim_fasthenrywidthsubdivkey = 0;		/* variable key for "SIM_fasthenry_width_subdivs" */
50 INTBIG sim_fasthenryheightsubdivkey = 0;	/* variable key for "SIM_fasthenry_height_subdivs" */
51 
52 INTBIG sim_fasthenryzheadkey = 0;			/* variable key for "SIM_fasthenry_z_head" */
53 INTBIG sim_fasthenryztailkey = 0;			/* variable key for "SIM_fasthenry_z_tail" */
54 INTBIG sim_fasthenrygroupnamekey = 0;		/* variable key for "SIM_fasthenry_group_name" */
55 
56 /* prototypes for local routines */
57 static BOOLEAN sim_writefhcell(NODEPROTO *np, FILE *io);
58 static void    sim_fasthenryarcdlog(void);
59 static void    sim_fasthenrydlog(void);
60 static void    sim_fasthenrygetoptions(INTBIG *options, float *startfreq, float *endfreq,
61 				INTBIG *runsperdecade, INTBIG *numpoles, INTBIG *seglenlimit, INTBIG *thickness,
62 				INTBIG *widsubdiv, INTBIG *heisubdiv);
63 static CHAR   *sim_fasthenrygetarcoptions(ARCINST *ai, INTBIG *thickness, INTBIG *widsubdiv,
64 				INTBIG *heisubdiv, INTBIG *z_head, INTBIG *z_tail, BOOLEAN *zhover, BOOLEAN *ztover,
65 				INTBIG *defz);
66 static PORTPROTO *sim_fasthenryfindotherport(ARCINST *ai, INTBIG end);
67 
68 extern "C" { extern COMCOMP sim_fhp, sim_fhap; }
69 
70 /*
71  * Routine called once to initialize this module
72  */
sim_fasthenryinit(void)73 void sim_fasthenryinit(void)
74 {
75 	DiaDeclareHook(x_("fasthenry"), &sim_fhp, sim_fasthenrydlog);
76 	DiaDeclareHook(x_("fasthenryarc"), &sim_fhap, sim_fasthenryarcdlog);
77 }
78 
79 /*
80  * routine to write a ".sil" file from the cell "np"
81  */
sim_writefasthenrynetlist(NODEPROTO * np)82 void sim_writefasthenrynetlist(NODEPROTO *np)
83 {
84 	CHAR name[100], *truename, txtpoles[20], *path;
85 	FILE *io;
86 	float startfreq, endfreq;
87 	INTBIG options, runsperdecade, numpoles, seglenlimit, thickness, widsubdiv, heisubdiv,
88 		lambda;
89 
90 	/* make sure network tool is on */
91 	if ((net_tool->toolstate&TOOLON) == 0)
92 	{
93 		ttyputerr(_("Network tool must be running...turning it on"));
94 		toolturnon(net_tool);
95 		ttyputerr(_("...now reissue the simulation command"));
96 		return;
97 	}
98 
99 	/* get all parameters */
100 	sim_fasthenrygetoptions(&options, &startfreq, &endfreq, &runsperdecade, &numpoles,
101 		&seglenlimit, &thickness, &widsubdiv, &heisubdiv);
102 
103 	/* first write the "inp" file */
104 	(void)estrcpy(name, np->protoname);
105 	(void)estrcat(name, x_(".inp"));
106 	io = xcreate(name, sim_filetypefasthenry, _("FastHenry File"), &truename);
107 	if (io == NULL)
108 	{
109 		if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
110 		return;
111 	}
112 	xprintf(io, x_("* FastHenry for cell %s\n"), describenodeproto(np));
113 	us_emitcopyright(io, x_("* "), x_(""));
114 
115 	if ((us_useroptions&NODATEORVERSION) == 0)
116 	{
117 		if (np->creationdate != 0)
118 			xprintf(io, x_("* Cell created on %s\n"), timetostring((time_t)np->creationdate));
119 		if (np->revisiondate != 0)
120 			xprintf(io, x_("* Cell last modified on %s\n"), timetostring((time_t)np->revisiondate));
121 		xprintf(io, x_("* Netlist written on %s\n"), timetostring(getcurrenttime()));
122 		xprintf(io, x_("* Written by Electric VLSI Design System, version %s\n"), el_version);
123 	} else
124 	{
125 		xprintf(io, x_("* Written by Electric VLSI Design System\n"));
126 	}
127 
128 	xprintf(io, x_("\n* Units are microns\n"));
129 	xprintf(io, x_(".units um\n"));
130 
131 	/* write default width and height subdivisions */
132 	lambda = lambdaofcell(np);
133 	xprintf(io, x_("\n* Default number of subdivisions\n"));
134 	xprintf(io, x_(".Default nwinc=%ld nhinc=%ld h=%s\n"), widsubdiv, heisubdiv, latoa(thickness, lambda));
135 
136 	/* reset flags for cells that have been written */
137 	if (sim_writefhcell(np, io))
138 		ttyputmsg(x_("Back-annotation information has been added (library must be saved)"));
139 
140 	/* write frequency range */
141 	if ((options&FHUSESINGLEFREQ) == 0)
142 	{
143 		xprintf(io, x_("\n.freq fmin=%g fmax=%g ndec=%ld\n"), startfreq, endfreq, runsperdecade);
144 	} else
145 	{
146 		xprintf(io, x_("\n.freq fmin=%g fmax=%g ndec=1\n"), startfreq, startfreq);
147 	}
148 
149 	/* clean up */
150 	xprintf(io, x_("\n.end\n"));
151 	xclose(io);
152 	ttyputmsg(_("%s written"), truename);
153 
154 	/* generate invocation for fasthenry */
155 	EProcess fh_process;
156 	path = egetenv(x_("ELECTRIC_FASTHENRYLOC"));
157 	if (path == NULL) path = FASTHENRYLOC;
158 	fh_process.addArgument( path );
159 	if ((options&FHMAKEMULTIPOLECKT) != 0)
160 	{
161 		fh_process.addArgument( x_("-r") );
162 		esnprintf(txtpoles, 20, x_("%ld"), numpoles);
163 		fh_process.addArgument( txtpoles );
164 		fh_process.addArgument( x_("-M") );
165 	}
166 	fh_process.addArgument( truename );
167 	fh_process.setCommunication( FALSE, FALSE, FALSE );
168 	fh_process.start();
169 	/* No wait */
170 }
171 
172 /*
173  * recursively called routine to print the SILOS description of cell "np".
174  * The description is treated as the top-level cell if "top" is nonzero
175  * np is the current nodeproto
176  */
sim_writefhcell(NODEPROTO * np,FILE * io)177 BOOLEAN sim_writefhcell(NODEPROTO *np, FILE *io)
178 {
179 	REGISTER BOOLEAN backannotate, found;
180 	REGISTER NODEINST *ni;
181 	REGISTER ARCINST *ai;
182 	REGISTER PORTARCINST *pi;
183 	REGISTER PORTPROTO *pp, *opp;
184 	REGISTER INTBIG nodezval, zval, wid, thatend;
185 	float xf, yf, zf, wf, hf;
186 	CHAR *nname, *n1name, *n2name, *groupname;
187 	static POLYGON *poly = NOPOLYGON;
188 	REGISTER VARIABLE *var;
189 	float startfreq, endfreq;
190 	INTBIG options, runsperdecade, numpoles, seglenlimit, thickness, defthickness,
191 		widsubdiv, defwidsubdiv, heisubdiv, defheisubdiv, z_head, z_tail, defz;
192 	BOOLEAN zhover, ztover;
193 
194 	/* get polygon */
195 	(void)needstaticpolygon(&poly, 4, sim_tool->cluster);
196 
197 	/* stop if requested */
198 	if (el_pleasestop != 0)
199 	{
200 		stopping(STOPREASONDECK);
201 		return(FALSE);
202 	}
203 
204 	/* get overriding defaults */
205 	sim_fasthenrygetoptions(&options, &startfreq, &endfreq, &runsperdecade, &numpoles,
206 		&seglenlimit, &defthickness, &defwidsubdiv, &defheisubdiv);
207 
208 	/* make sure that all nodes have names on them */
209 	backannotate = FALSE;
210 	if (asktool(net_tool, x_("name-all-nodes"), (INTBIG)np) != 0) backannotate = TRUE;
211 
212 	/* look at every node in the cell */
213 	xprintf(io, x_("\n* Traces\n"));
214 	for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
215 	{
216 		/* see if this node has a FastHenry arc on it */
217 		found = FALSE;
218 		nodezval = 0;
219 		for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
220 		{
221 			ai = pi->conarcinst;
222 			groupname = sim_fasthenrygetarcoptions(ai, &thickness, &widsubdiv, &heisubdiv,
223 				&z_head, &z_tail, &zhover, &ztover, &defz);
224 			if (groupname == 0) continue;
225 			zval = defz;
226 			if (ai->end[0].portarcinst == pi && zhover) zval = z_head;
227 			if (ai->end[1].portarcinst == pi && ztover) zval = z_tail;
228 			if (found)
229 			{
230 				/* LINTED "nodezval" used in proper order */
231 				if (zval != nodezval)
232 					ttyputerr(_("Warning: inconsistent z value at node %s"),
233 						describenodeinst(ni));
234 			}
235 			nodezval = zval;
236 			found = TRUE;
237 		}
238 		if (!found) continue;
239 
240 		/* node is an end point: get its name */
241 		if (ni->firstportexpinst != NOPORTEXPINST)
242 		{
243 			nname = ni->firstportexpinst->exportproto->protoname;
244 		} else
245 		{
246 			var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
247 			if (var == NOVARIABLE) nname = x_(""); else nname = (CHAR *)var->addr;
248 		}
249 
250 		/* write the "N" line */
251 		xf = scaletodispunit((ni->lowx+ni->highx)/2, DISPUNITMIC);
252 		yf = scaletodispunit((ni->lowy+ni->highy)/2, DISPUNITMIC);
253 		zf = scaletodispunit(nodezval, DISPUNITMIC);
254 		xprintf(io, x_("N_%s x=%g y=%g z=%g\n"), nname, xf, yf, zf);
255 	}
256 
257 	/* look at every arc in the cell */
258 	for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
259 	{
260 		/* get info about this arc, stop if not part of the FastHenry output */
261 		groupname = sim_fasthenrygetarcoptions(ai, &thickness, &widsubdiv, &heisubdiv,
262 			&z_head, &z_tail, &zhover, &ztover, &defz);
263 		if (groupname == 0) continue;
264 
265 		/* get size */
266 		wid = ai->width;
267 
268 		/* get the name of the nodes on each end */
269 		if (ai->end[0].nodeinst->firstportexpinst != NOPORTEXPINST)
270 		{
271 			n1name = ai->end[0].nodeinst->firstportexpinst->exportproto->protoname;
272 		} else
273 		{
274 			var = getvalkey((INTBIG)ai->end[0].nodeinst, VNODEINST, VSTRING, el_node_name_key);
275 			if (var == NOVARIABLE) n1name = x_(""); else n1name = (CHAR *)var->addr;
276 		}
277 		if (ai->end[1].nodeinst->firstportexpinst != NOPORTEXPINST)
278 		{
279 			n2name = ai->end[1].nodeinst->firstportexpinst->exportproto->protoname;
280 		} else
281 		{
282 			var = getvalkey((INTBIG)ai->end[1].nodeinst, VNODEINST, VSTRING, el_node_name_key);
283 			if (var == NOVARIABLE) n2name = x_(""); else n2name = (CHAR *)var->addr;
284 		}
285 
286 		/* write the "E" line */
287 		wf = scaletodispunit(wid, DISPUNITMIC);
288 		xprintf(io, x_("E_%s_%s N_%s N_%s w=%g"), n1name, n2name, n1name, n2name, wf);
289 		if (thickness > 0)
290 		{
291 			hf = scaletodispunit(thickness, DISPUNITMIC);
292 			xprintf(io, x_(" h=%g"), hf);
293 		}
294 		if (widsubdiv > 0) xprintf(io, x_(" nwinc=%ld"), widsubdiv);
295 		if (heisubdiv > 0) xprintf(io, x_(" nhinc=%ld"), heisubdiv);
296 		xprintf(io, x_("\n"));
297 	}
298 
299 	/* find external connections */
300 	xprintf(io, x_("\n* External connections\n"));
301 	for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
302 		ai->temp1 = 0;
303 	for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
304 		pp->temp1 = 0;
305 
306 	/* look at every export in the cell */
307 	for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
308 	{
309 		if (pp->temp1 != 0) continue;
310 		pp->temp1 = 1;
311 		ni = pp->subnodeinst;
312 		for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
313 		{
314 			ai = pi->conarcinst;
315 			var = getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
316 			if (var != NOVARIABLE) break;
317 		}
318 		if (pi == NOPORTARCINST) continue;
319 
320 		/* port "pp" is one end, now find the other */
321 		if (ai->end[0].portarcinst == pi) thatend = 1; else thatend = 0;
322 		opp = sim_fasthenryfindotherport(ai, thatend);
323 		if (opp == NOPORTPROTO)
324 		{
325 			ttyputerr(_("Warning: trace on port %s has no other end that is an export"),
326 				pp->protoname);
327 			continue;
328 		}
329 
330 		/* found two ports: write the ".external" line */
331 		opp->temp1 = 1;
332 		xprintf(io, x_(".external N_%s N_%s\n"), pp->protoname, opp->protoname);
333 	}
334 
335 	/* warn about arcs that aren't connected to ".external" lines */
336 	for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
337 	{
338 		if (ai->temp1 != 0) continue;
339 		var = getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
340 		if (var == NOVARIABLE) continue;
341 		ttyputerr(_("Warning: arc %s is not on a measured trace"), describearcinst(ai));
342 	}
343 	return(backannotate);
344 }
345 
sim_fasthenryfindotherport(ARCINST * ai,INTBIG end)346 PORTPROTO *sim_fasthenryfindotherport(ARCINST *ai, INTBIG end)
347 {
348 	REGISTER NODEINST *ni;
349 	REGISTER PORTARCINST *pi;
350 	REGISTER ARCINST *oai;
351 	REGISTER INTBIG thatend;
352 	REGISTER PORTPROTO *opp;
353 	REGISTER VARIABLE *var;
354 
355 	ai->temp1 = 1;
356 	ni = ai->end[end].nodeinst;
357 	if (ni->firstportexpinst != NOPORTEXPINST) return(ni->firstportexpinst->exportproto);
358 	for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
359 	{
360 		oai = pi->conarcinst;
361 		if (oai == ai) continue;
362 		var = getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
363 		if (var == NOVARIABLE) continue;
364 		if (oai->end[0].portarcinst == pi) thatend = 1; else thatend = 0;
365 		opp = sim_fasthenryfindotherport(oai, thatend);
366 		if (opp != NOPORTPROTO) return(opp);
367 	}
368 	return(NOPORTPROTO);
369 }
370 
sim_fasthenrygetoptions(INTBIG * options,float * startfreq,float * endfreq,INTBIG * runsperdecade,INTBIG * numpoles,INTBIG * seglenlimit,INTBIG * thickness,INTBIG * widsubdiv,INTBIG * heisubdiv)371 void sim_fasthenrygetoptions(INTBIG *options, float *startfreq, float *endfreq,
372 	INTBIG *runsperdecade, INTBIG *numpoles, INTBIG *seglenlimit, INTBIG *thickness,
373 	INTBIG *widsubdiv, INTBIG *heisubdiv)
374 {
375 	REGISTER VARIABLE *var;
376 
377 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenrystatekey);
378 	if (var != NOVARIABLE) *options = var->addr; else *options = 0;
379 	var = getvalkey((INTBIG)sim_tool, VTOOL, VFLOAT, sim_fasthenryfreqstartkey);
380 	if (var != NOVARIABLE) *startfreq = castfloat(var->addr); else *startfreq = 0.0;
381 	var = getvalkey((INTBIG)sim_tool, VTOOL, VFLOAT, sim_fasthenryfreqendkey);
382 	if (var != NOVARIABLE) *endfreq = castfloat(var->addr); else *endfreq = 0.0;
383 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenryrunsperdecadekey);
384 	if (var != NOVARIABLE) *runsperdecade = var->addr; else *runsperdecade = 1;
385 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenrynumpoleskey);
386 	if (var != NOVARIABLE) *numpoles = var->addr; else *numpoles = 20;
387 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenryseglimitkey);
388 	if (var != NOVARIABLE) *seglenlimit = var->addr; else *seglenlimit = 0;
389 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenrythicknesskey);
390 	if (var != NOVARIABLE) *thickness = var->addr; else *thickness = 2*el_curlib->lambda[el_curtech->techindex];
391 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenrywidthsubdivkey);
392 	if (var != NOVARIABLE) *widsubdiv = var->addr; else *widsubdiv = 1;
393 	var = getvalkey((INTBIG)sim_tool, VTOOL, VINTEGER, sim_fasthenryheightsubdivkey);
394 	if (var != NOVARIABLE) *heisubdiv = var->addr; else *heisubdiv = 1;
395 }
396 
sim_fasthenrygetarcoptions(ARCINST * ai,INTBIG * thickness,INTBIG * widsubdiv,INTBIG * heisubdiv,INTBIG * z_head,INTBIG * z_tail,BOOLEAN * zhover,BOOLEAN * ztover,INTBIG * defz)397 CHAR *sim_fasthenrygetarcoptions(ARCINST *ai, INTBIG *thickness, INTBIG *widsubdiv,
398 	INTBIG *heisubdiv, INTBIG *z_head, INTBIG *z_tail, BOOLEAN *zhover, BOOLEAN *ztover,
399 	INTBIG *defz)
400 {
401 	REGISTER VARIABLE *var;
402 	REGISTER INTBIG total, i;
403 	float lheight, lthickness;
404 	static POLYGON *poly = NOPOLYGON;
405 
406 	/* get polygon */
407 	(void)needstaticpolygon(&poly, 4, sim_tool->cluster);
408 
409 	/* get miscellaneous parameters */
410 	var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrythicknesskey);
411 	if (var != NOVARIABLE) *thickness = var->addr; else *thickness = -1;
412 	var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrywidthsubdivkey);
413 	if (var != NOVARIABLE) *widsubdiv = var->addr; else *widsubdiv = -1;
414 	var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryheightsubdivkey);
415 	if (var != NOVARIABLE) *heisubdiv = var->addr; else *heisubdiv = -1;
416 
417 	/* get z depth and any overrides */
418 	total = arcpolys(ai, NOWINDOWPART);
419 	for(i=0; i<total; i++)
420 	{
421 		shapearcpoly(ai, i, poly);
422 		if (get3dfactors(ai->proto->tech, poly->layer, &lheight, &lthickness))
423 			continue;
424 		*defz = (INTBIG)(lheight * lambdaofarc(ai));
425 		break;
426 	}
427 	var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryzheadkey);
428 	if (var == NOVARIABLE) *zhover = FALSE; else
429 	{
430 		*z_head = var->addr;
431 		*zhover = TRUE;
432 	}
433 	var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryztailkey);
434 	if (var == NOVARIABLE) *ztover = FALSE; else
435 	{
436 		*z_tail = var->addr;
437 		*ztover = TRUE;
438 	}
439 
440 	/* get the group name */
441 	var = getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
442 	if (var == NOVARIABLE) return(0);
443 	return((CHAR *)var->addr);
444 }
445 
446 /***************************************** DIALOGS *****************************************/
447 
448 /* Simulation: FastHenry Options */
449 static DIALOGITEM sim_fasthenrydialogitems[] =
450 {
451  /*  1 */ {0, {164,392,188,472}, BUTTON, N_("OK")},
452  /*  2 */ {0, {164,12,188,92}, BUTTON, N_("Cancel")},
453  /*  3 */ {0, {32,20,48,140}, MESSAGE, N_("Frequency start:")},
454  /*  4 */ {0, {32,144,48,200}, EDITTEXT, x_("")},
455  /*  5 */ {0, {56,20,72,140}, MESSAGE, N_("Frequency end:")},
456  /*  6 */ {0, {56,144,72,200}, EDITTEXT, x_("")},
457  /*  7 */ {0, {80,20,96,140}, MESSAGE, N_("Runs per decade:")},
458  /*  8 */ {0, {80,144,96,200}, EDITTEXT, x_("")},
459  /*  9 */ {0, {8,8,24,200}, CHECK, N_("Use single frequency")},
460  /* 10 */ {0, {128,20,144,140}, MESSAGE, N_("Number of poles:")},
461  /* 11 */ {0, {128,144,144,200}, EDITTEXT, x_("")},
462  /* 12 */ {0, {104,8,120,200}, CHECK, N_("Make multipole subcircuit")},
463  /* 13 */ {0, {104,224,120,420}, CHECK, N_("Make PostScript view")},
464  /* 14 */ {0, {80,224,96,420}, MESSAGE, N_("Maximum segment length:")},
465  /* 15 */ {0, {80,424,96,480}, EDITTEXT, x_("")},
466  /* 16 */ {0, {32,224,48,420}, MESSAGE, N_("Default width subdivisions:")},
467  /* 17 */ {0, {32,424,48,480}, EDITTEXT, x_("")},
468  /* 18 */ {0, {56,224,72,420}, MESSAGE, N_("Default height subdivisions:")},
469  /* 19 */ {0, {56,424,72,480}, EDITTEXT, x_("")},
470  /* 20 */ {0, {128,224,144,420}, CHECK, N_("Make SPICE subcircuit")},
471  /* 21 */ {0, {8,224,24,420}, MESSAGE, N_("Default thickness:")},
472  /* 22 */ {0, {8,424,24,480}, EDITTEXT, x_("")},
473  /* 23 */ {0, {176,140,192,344}, POPUP, x_("")},
474  /* 24 */ {0, {156,176,172,320}, MESSAGE, N_("After writing deck:")}
475 };
476 static DIALOG sim_fasthenrydialog = {{75,75,276,565}, N_("FastHenry Options"), 0, 24, sim_fasthenrydialogitems, 0, 0};
477 
478 /* special items for the "FastHenry options" dialog: */
479 #define DFHO_FREQSTART      4		/* frequency start (edit text) */
480 #define DFHO_FREQEND_L      5		/* frequency end label (stat text) */
481 #define DFHO_FREQEND        6		/* frequency end (edit text) */
482 #define DFHO_RUNSPERDEC_L   7		/* runs per decade label (stat text) */
483 #define DFHO_RUNSPERDEC     8		/* runs per decade (edit text) */
484 #define DFHO_USESINGLEFREQ  9		/* use single frequency (check) */
485 #define DFHO_NUMPOLES_L    10		/* number of poles label (stat text) */
486 #define DFHO_NUMPOLES      11		/* number of poles (edit text) */
487 #define DFHO_MULTIPOLE     12		/* make multipole subckt (check) */
488 #define DFHO_POSTSCRIPT    13		/* make PostScript view (check) */
489 #define DFHO_MAXSEGLEN     15		/* max seg length (edit text) */
490 #define DFHO_DEFWIDSUB     17		/* default width subdiv (edit text) */
491 #define DFHO_DEFHEISUB     19		/* default height subdiv (edit text) */
492 #define DFHO_MAKESPICE     20		/* make SPICE subckt (check) */
493 #define DFHO_DEFTHICK      22		/* default thickness (edit text) */
494 #define DFHO_AFTERWRITE    23		/* after deck writing (popup) */
495 
sim_fasthenrydlog(void)496 void sim_fasthenrydlog(void)
497 {
498 	REGISTER INTBIG itemHit, value, i;
499 	REGISTER BOOLEAN canexecute;
500 	float fvalue;
501 	CHAR line[30], *newlang[5];
502 	static CHAR *exechoices[] = {N_("Nothing run"), N_("Run FastHenry"),
503 		N_("Run FastHenry Multiprocessing")};
504 	float startfreq, endfreq;
505 	INTBIG options, runsperdecade, numpoles, seglenlimit, thickness,
506 		widsubdiv, heisubdiv;
507 	REGISTER void *dia;
508 
509 	/* get all parameters */
510 	sim_fasthenrygetoptions(&options, &startfreq, &endfreq, &runsperdecade, &numpoles,
511 		&seglenlimit, &thickness, &widsubdiv, &heisubdiv);
512 
513 	/* Display the FastHenry options dialog box */
514 	dia = DiaInitDialog(&sim_fasthenrydialog);
515 	if (dia == 0) return;
516 
517 	/* set popup */
518 	for(i=0; i<3; i++) newlang[i] = TRANSLATE(exechoices[i]);
519 	DiaSetPopup(dia, DFHO_AFTERWRITE, 3, newlang);
520 	canexecute = graphicshas(CANRUNPROCESS);
521 	if (canexecute)
522 	{
523 		DiaUnDimItem(dia, DFHO_AFTERWRITE);
524 		if ((options&FHEXECUTETYPE) == FHEXECUTERUNFH)
525 		{
526 			DiaSetPopupEntry(dia, DFHO_AFTERWRITE, 1);
527 		} else if ((options&FHEXECUTETYPE) == FHEXECUTERUNFHMUL)
528 		{
529 			DiaSetPopupEntry(dia, DFHO_AFTERWRITE, 2);
530 		}
531 	} else
532 	{
533 		DiaDimItem(dia, DFHO_AFTERWRITE);
534 	}
535 
536 	/* set checkboxes */
537 	if ((options&FHUSESINGLEFREQ) != 0) DiaSetControl(dia, DFHO_USESINGLEFREQ, 1);
538 	if ((options&FHMAKEMULTIPOLECKT) != 0) DiaSetControl(dia, DFHO_MULTIPOLE, 1);
539 	if ((options&FHMAKEPOSTSCRIPTVIEW) != 0) DiaSetControl(dia, DFHO_POSTSCRIPT, 1);
540 	if ((options&FHMAKESPICESUBCKT) != 0) DiaSetControl(dia, DFHO_MAKESPICE, 1);
541 
542 	/* load default frequency range */
543 	esnprintf(line, 30, x_("%g"), startfreq);   DiaSetText(dia, DFHO_FREQSTART, line);
544 	esnprintf(line, 30, x_("%g"), endfreq);   DiaSetText(dia, DFHO_FREQEND, line);
545 	esnprintf(line, 30, x_("%ld"), runsperdecade);   DiaSetText(dia, DFHO_RUNSPERDEC, line);
546 
547 	/* load segment limits */
548 	DiaSetText(dia, DFHO_MAXSEGLEN, latoa(seglenlimit, 0));
549 	DiaSetText(dia, DFHO_DEFTHICK, latoa(thickness, 0));
550 	esnprintf(line, 30, x_("%ld"), widsubdiv);   DiaSetText(dia, DFHO_DEFWIDSUB, line);
551 	esnprintf(line, 30, x_("%ld"), heisubdiv);   DiaSetText(dia, DFHO_DEFHEISUB, line);
552 
553 	/* load other numeric options */
554 	esnprintf(line, 30, x_("%ld"), numpoles);   DiaSetText(dia, DFHO_NUMPOLES, line);
555 
556 	if ((options&FHMAKEMULTIPOLECKT) != 0)
557 	{
558 		DiaUnDimItem(dia, DFHO_NUMPOLES_L);
559 		DiaEditControl(dia, DFHO_NUMPOLES);
560 	} else
561 	{
562 		DiaDimItem(dia, DFHO_NUMPOLES_L);
563 		DiaNoEditControl(dia, DFHO_NUMPOLES);
564 	}
565 	if ((options&FHUSESINGLEFREQ) != 0)
566 	{
567 		DiaDimItem(dia, DFHO_FREQEND_L);
568 		DiaNoEditControl(dia, DFHO_FREQEND);
569 		DiaDimItem(dia, DFHO_RUNSPERDEC_L);
570 		DiaNoEditControl(dia, DFHO_RUNSPERDEC);
571 	} else
572 	{
573 		DiaUnDimItem(dia, DFHO_FREQEND_L);
574 		DiaEditControl(dia, DFHO_FREQEND);
575 		DiaUnDimItem(dia, DFHO_RUNSPERDEC_L);
576 		DiaEditControl(dia, DFHO_RUNSPERDEC);
577 	}
578 	DiaDimItem(dia, DFHO_POSTSCRIPT);
579 	DiaNoEditControl(dia, DFHO_MAXSEGLEN);
580 	DiaDimItem(dia, DFHO_MAKESPICE);
581 
582 	for(;;)
583 	{
584 		itemHit = DiaNextHit(dia);
585 		if (itemHit == OK || itemHit == CANCEL) break;
586 		if (itemHit == DFHO_USESINGLEFREQ || itemHit == DFHO_MULTIPOLE ||
587 			itemHit == DFHO_POSTSCRIPT || itemHit == DFHO_MAKESPICE)
588 		{
589 			value = 1 - DiaGetControl(dia, itemHit);
590 			DiaSetControl(dia, itemHit, value);
591 			if (itemHit == DFHO_USESINGLEFREQ)
592 			{
593 				if (value != 0)
594 				{
595 					DiaDimItem(dia, DFHO_FREQEND_L);
596 					DiaNoEditControl(dia, DFHO_FREQEND);
597 					DiaDimItem(dia, DFHO_RUNSPERDEC_L);
598 					DiaNoEditControl(dia, DFHO_RUNSPERDEC);
599 				} else
600 				{
601 					DiaUnDimItem(dia, DFHO_FREQEND_L);
602 					DiaEditControl(dia, DFHO_FREQEND);
603 					DiaUnDimItem(dia, DFHO_RUNSPERDEC_L);
604 					DiaEditControl(dia, DFHO_RUNSPERDEC);
605 				}
606 			}
607 			if (itemHit == DFHO_MULTIPOLE)
608 			{
609 				if (value != 0)
610 				{
611 					DiaUnDimItem(dia, DFHO_NUMPOLES_L);
612 					DiaEditControl(dia, DFHO_NUMPOLES);
613 				} else
614 				{
615 					DiaDimItem(dia, DFHO_NUMPOLES_L);
616 					DiaNoEditControl(dia, DFHO_NUMPOLES);
617 				}
618 			}
619 			continue;
620 		}
621 	}
622 
623 	if (itemHit == OK)
624 	{
625 		/* save options */
626 		value = 0;
627 		if (DiaGetControl(dia, DFHO_USESINGLEFREQ) != 0) value |= FHUSESINGLEFREQ;
628 		if (DiaGetControl(dia, DFHO_MULTIPOLE) != 0) value |= FHMAKEMULTIPOLECKT;
629 		if (DiaGetControl(dia, DFHO_POSTSCRIPT) != 0) value |= FHMAKEPOSTSCRIPTVIEW;
630 		if (DiaGetControl(dia, DFHO_MAKESPICE) != 0) value |= FHMAKESPICESUBCKT;
631 		i = DiaGetPopupEntry(dia, DFHO_AFTERWRITE);
632 		if (i == 1) value |= FHEXECUTERUNFH; else
633 			if (i == 2) value |= FHEXECUTERUNFHMUL;
634 		if (value != options)
635 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenrystatekey, value, VINTEGER);
636 
637 		/* save other limits */
638 		fvalue = (float)eatof(DiaGetText(dia, DFHO_FREQSTART));
639 		if (fvalue != startfreq)
640 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenryfreqstartkey, castint(fvalue), VFLOAT);
641 		fvalue = (float)eatof(DiaGetText(dia, DFHO_FREQEND));
642 		if (fvalue != endfreq)
643 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenryfreqendkey, castint(fvalue), VFLOAT);
644 		value = eatoi(DiaGetText(dia, DFHO_RUNSPERDEC));
645 		if (value != runsperdecade)
646 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenryrunsperdecadekey, value, VINTEGER);
647 		value = atola(DiaGetText(dia, DFHO_MAXSEGLEN), 0);
648 		if (value != seglenlimit)
649 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenryseglimitkey, value, VINTEGER);
650 		value = atola(DiaGetText(dia, DFHO_DEFTHICK), 0);
651 		if (value != thickness)
652 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenrythicknesskey, value, VINTEGER);
653 		value = eatoi(DiaGetText(dia, DFHO_DEFWIDSUB));
654 		if (value != widsubdiv)
655 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenrywidthsubdivkey, value, VINTEGER);
656 		value = eatoi(DiaGetText(dia, DFHO_DEFHEISUB));
657 		if (value != heisubdiv)
658 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenryheightsubdivkey, value, VINTEGER);
659 		value = eatoi(DiaGetText(dia, DFHO_NUMPOLES));
660 		if (value != numpoles)
661 			(void)setvalkey((INTBIG)sim_tool, VTOOL, sim_fasthenrynumpoleskey, value, VINTEGER);
662 	}
663 	DiaDoneDialog(dia);
664 }
665 
666 /* Simulation: FastHenry Arc */
667 static DIALOGITEM sim_fasthenryarcdialogitems[] =
668 {
669  /*  1 */ {0, {88,236,112,316}, BUTTON, N_("OK")},
670  /*  2 */ {0, {40,236,64,316}, BUTTON, N_("Cancel")},
671  /*  3 */ {0, {32,8,48,132}, MESSAGE, N_("Thickness:")},
672  /*  4 */ {0, {32,136,48,216}, EDITTEXT, x_("")},
673  /*  5 */ {0, {56,8,72,132}, MESSAGE, N_("Width:")},
674  /*  6 */ {0, {56,136,72,216}, MESSAGE, x_("")},
675  /*  7 */ {0, {80,8,96,180}, MESSAGE, N_("Width subdivisions:")},
676  /*  8 */ {0, {80,184,96,216}, EDITTEXT, x_("")},
677  /*  9 */ {0, {104,8,120,180}, MESSAGE, N_("Height subdivisions:")},
678  /* 10 */ {0, {104,184,120,216}, EDITTEXT, x_("")},
679  /* 11 */ {0, {232,8,248,36}, MESSAGE, N_("X:")},
680  /* 12 */ {0, {232,40,248,136}, MESSAGE, x_("")},
681  /* 13 */ {0, {204,8,220,144}, MESSAGE, N_("Head of arc is at:")},
682  /* 14 */ {0, {256,8,272,36}, MESSAGE, N_("Y:")},
683  /* 15 */ {0, {256,40,272,136}, MESSAGE, x_("")},
684  /* 16 */ {0, {280,8,296,36}, MESSAGE, N_("Z:")},
685  /* 17 */ {0, {280,40,296,132}, EDITTEXT, x_("")},
686  /* 18 */ {0, {232,180,248,208}, MESSAGE, N_("X:")},
687  /* 19 */ {0, {232,212,248,308}, MESSAGE, x_("")},
688  /* 20 */ {0, {204,180,220,316}, MESSAGE, N_("Tail of arc is at:")},
689  /* 21 */ {0, {256,180,272,208}, MESSAGE, N_("Y:")},
690  /* 22 */ {0, {256,212,272,308}, MESSAGE, x_("")},
691  /* 23 */ {0, {280,180,296,208}, MESSAGE, N_("Z:")},
692  /* 24 */ {0, {280,212,296,304}, EDITTEXT, x_("")},
693  /* 25 */ {0, {144,8,160,108}, MESSAGE, N_("Group name:")},
694  /* 26 */ {0, {144,112,160,316}, POPUP, x_("")},
695  /* 27 */ {0, {168,80,184,176}, BUTTON, N_("New Group")},
696  /* 28 */ {0, {132,8,133,316}, DIVIDELINE, x_("")},
697  /* 29 */ {0, {192,8,193,316}, DIVIDELINE, x_("")},
698  /* 30 */ {0, {8,8,24,316}, CHECK, N_("Include this arc in FastHenry analysis")},
699  /* 31 */ {0, {304,88,320,168}, MESSAGE, N_("Default Z:")},
700  /* 32 */ {0, {304,172,320,268}, MESSAGE, x_("")}
701 };
702 static DIALOG sim_fasthenryarcdialog = {{75,75,404,401}, N_("FastHenry Arc Properties"), 0, 32, sim_fasthenryarcdialogitems, 0, 0};
703 
704 /* special items for the "FastHenry arc" dialog: */
705 #define DFHA_ARCTHICK_L      3		/* arc thickness label (stat text) */
706 #define DFHA_ARCTHICK        4		/* arc thickness (edit text) */
707 #define DFHA_ARCWIDTH        6		/* arc width (stat text) */
708 #define DFHA_WIDTHSUBDIV_L   7		/* width subdiv label (edit text) */
709 #define DFHA_WIDTHSUBDIV     8		/* width subdivisions (edit text) */
710 #define DFHA_HEIGHTSUBDIV_L  9		/* height subdiv label (edit text) */
711 #define DFHA_HEIGHTSUBDIV   10		/* height subdivisions (edit text) */
712 #define DFHA_ARCHEADX       12		/* arc head X (stat text) */
713 #define DFHA_ARCHEADY       15		/* arc head Y (stat text) */
714 #define DFHA_ARCHEADZ_L     16		/* arc head Z label (stat text) */
715 #define DFHA_ARCHEADZ       17		/* arc head Z (edit text) */
716 #define DFHA_ARCTAILX       19		/* arc tail X (stat text) */
717 #define DFHA_ARCTAILY       22		/* arc tail Y (stat text) */
718 #define DFHA_ARCTAILZ_L     23		/* arc tail Z label (stat text) */
719 #define DFHA_ARCTAILZ       24		/* arc tail Z (edit text) */
720 #define DFHA_GROUPNAME_L    25		/* group name label (stat text) */
721 #define DFHA_GROUPNAME      26		/* group name (popup) */
722 #define DFHA_NEWGROUP       27		/* make new group (button) */
723 #define DFHA_INCLUDE        30		/* include in FastHenry (check) */
724 #define DFHA_DEFZ           32		/* default z (stat text) */
725 
sim_fasthenryarcdlog(void)726 void sim_fasthenryarcdlog(void)
727 {
728 	REGISTER INTBIG itemHit, value, groupnamesize, i, val, lambda;
729 	REGISTER ARCINST *ai, *oai;
730 	REGISTER VARIABLE *var;
731 	CHAR line[60], *groupname, *pt, **groupnames, **newgroupnames, *newname;
732 	float startfreq, endfreq;
733 	INTBIG options, runsperdecade, numpoles, seglenlimit, thickness, defthickness,
734 		widsubdiv, defwidsubdiv, heisubdiv, defheisubdiv, z_head, z_tail, defz;
735 	BOOLEAN zhover, ztover;
736 	REGISTER void *dia;
737 
738 	/* get currently selected arc */
739 	ai = (ARCINST *)asktool(us_tool, x_("get-arc"));
740 	if (ai == NOARCINST)
741 	{
742 		ttyputerr(_("Select an arc first"));
743 		return;
744 	}
745 	lambda = lambdaofarc(ai);
746 
747 	/* get all parameters */
748 	sim_fasthenrygetoptions(&options, &startfreq, &endfreq, &runsperdecade, &numpoles,
749 		&seglenlimit, &defthickness, &defwidsubdiv, &defheisubdiv);
750 	groupname = sim_fasthenrygetarcoptions(ai, &thickness, &widsubdiv, &heisubdiv,
751 		&z_head, &z_tail, &zhover, &ztover, &defz);
752 
753 	/* display the FastHenry arc dialog box */
754 	dia = DiaInitDialog(&sim_fasthenryarcdialog);
755 	if (dia == 0) return;
756 
757 	/* make a list of all group names */
758 	groupnamesize = 0;
759 	for(oai = ai->parent->firstarcinst; oai != NOARCINST; oai = oai->nextarcinst)
760 	{
761 		var = getvalkey((INTBIG)oai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
762 		if (var != NOVARIABLE)
763 		{
764 			for(i=0; i<groupnamesize; i++)
765 			{
766 				/* LINTED "groupnames" used in proper order */
767 				if (namesame(groupnames[i], (CHAR *)var->addr) == 0) break;
768 			}
769 			if (i < groupnamesize) continue;
770 
771 			/* add to the list */
772 			newgroupnames = (CHAR **)emalloc((groupnamesize+1) * (sizeof (CHAR *)),
773 				sim_tool->cluster);
774 			for(i=0; i<groupnamesize; i++)
775 				newgroupnames[i] = groupnames[i];
776 			(void)allocstring(&newgroupnames[groupnamesize], (CHAR *)var->addr,
777 				sim_tool->cluster);
778 			if (groupnamesize > 0) efree((CHAR *)groupnames);
779 			groupnames = newgroupnames;
780 			groupnamesize++;
781 		}
782 	}
783 	if (groupnamesize == 0)
784 	{
785 		groupnames = (CHAR **)emalloc((sizeof (CHAR *)), sim_tool->cluster);
786 		(void)allocstring(&groupnames[0], _("Group 1"), sim_tool->cluster);
787 		groupnamesize++;
788 	}
789 	DiaSetPopup(dia, DFHA_GROUPNAME, groupnamesize, groupnames);
790 
791 	/* select group name */
792 	if (groupname != 0)
793 	{
794 		for(i=0; i<groupnamesize; i++)
795 			if (namesame(groupname, groupnames[i]) == 0) break;
796 		if (i < groupnamesize) DiaSetPopupEntry(dia, DFHA_GROUPNAME, i);
797 	}
798 
799 	/* show arc parameters */
800 	esnprintf(line, 60, _("Thickness (%s):"), latoa(defthickness, lambda));
801 	DiaSetText(dia, DFHA_ARCTHICK_L, line);
802 	if (thickness >= 0)
803 		DiaSetText(dia, DFHA_ARCTHICK, latoa(thickness, lambda));
804 	DiaSetText(dia, DFHA_ARCWIDTH, latoa(ai->width, lambda));
805 
806 	/* show subdivision overrides */
807 	esnprintf(line, 60, _("Width subdivisions (%ld):"), defwidsubdiv);
808 	DiaSetText(dia, DFHA_WIDTHSUBDIV_L, line);
809 	if (widsubdiv > 0)
810 	{
811 		esnprintf(line, 60, x_("%ld"), widsubdiv);
812 		DiaSetText(dia, DFHA_WIDTHSUBDIV, line);
813 	}
814 	esnprintf(line, 60, _("Height subdivisions (%ld):"), defheisubdiv);
815 	DiaSetText(dia, DFHA_HEIGHTSUBDIV_L, line);
816 	if (heisubdiv > 0)
817 	{
818 		esnprintf(line, 60, x_("%ld"), heisubdiv);
819 		DiaSetText(dia, DFHA_HEIGHTSUBDIV, line);
820 	}
821 
822 	/* show end coordinates */
823 	DiaSetText(dia, DFHA_DEFZ, latoa(defz, lambda));
824 	DiaSetText(dia, DFHA_ARCHEADX, latoa(ai->end[0].xpos, lambda));
825 	DiaSetText(dia, DFHA_ARCHEADY, latoa(ai->end[0].ypos, lambda));
826 	if (zhover) DiaSetText(dia, DFHA_ARCHEADZ, latoa(z_head, lambda));
827 	DiaSetText(dia, DFHA_ARCTAILX, latoa(ai->end[1].xpos, lambda));
828 	DiaSetText(dia, DFHA_ARCTAILY, latoa(ai->end[1].ypos, lambda));
829 	if (ztover) DiaSetText(dia, DFHA_ARCTAILZ, latoa(z_tail, lambda));
830 
831 	if (groupname != 0)
832 	{
833 		DiaUnDimItem(dia, DFHA_ARCTHICK_L);
834 		DiaEditControl(dia, DFHA_ARCTHICK);
835 		DiaUnDimItem(dia, DFHA_WIDTHSUBDIV_L);
836 		DiaEditControl(dia, DFHA_WIDTHSUBDIV);
837 		DiaUnDimItem(dia, DFHA_HEIGHTSUBDIV_L);
838 		DiaEditControl(dia, DFHA_HEIGHTSUBDIV);
839 		DiaUnDimItem(dia, DFHA_ARCHEADZ_L);
840 		DiaEditControl(dia, DFHA_ARCHEADZ);
841 		DiaUnDimItem(dia, DFHA_ARCTAILZ_L);
842 		DiaEditControl(dia, DFHA_ARCTAILZ);
843 		DiaUnDimItem(dia, DFHA_GROUPNAME_L);
844 		DiaUnDimItem(dia, DFHA_GROUPNAME);
845 		DiaUnDimItem(dia, DFHA_NEWGROUP);
846 		DiaSetControl(dia, DFHA_INCLUDE, 1);
847 	} else
848 	{
849 		DiaDimItem(dia, DFHA_ARCTHICK_L);
850 		DiaNoEditControl(dia, DFHA_ARCTHICK);
851 		DiaDimItem(dia, DFHA_WIDTHSUBDIV_L);
852 		DiaNoEditControl(dia, DFHA_WIDTHSUBDIV);
853 		DiaDimItem(dia, DFHA_HEIGHTSUBDIV_L);
854 		DiaNoEditControl(dia, DFHA_HEIGHTSUBDIV);
855 		DiaDimItem(dia, DFHA_ARCHEADZ_L);
856 		DiaNoEditControl(dia, DFHA_ARCHEADZ);
857 		DiaDimItem(dia, DFHA_ARCTAILZ_L);
858 		DiaNoEditControl(dia, DFHA_ARCTAILZ);
859 		DiaDimItem(dia, DFHA_GROUPNAME_L);
860 		DiaDimItem(dia, DFHA_GROUPNAME);
861 		DiaDimItem(dia, DFHA_NEWGROUP);
862 	}
863 
864 	for(;;)
865 	{
866 		itemHit = DiaNextHit(dia);
867 		if (itemHit == OK || itemHit == CANCEL) break;
868 		if (itemHit == DFHA_INCLUDE)
869 		{
870 			value = 1 - DiaGetControl(dia, itemHit);
871 			DiaSetControl(dia, itemHit, value);
872 			if (value != 0)
873 			{
874 				DiaUnDimItem(dia, DFHA_ARCTHICK_L);
875 				DiaEditControl(dia, DFHA_ARCTHICK);
876 				DiaUnDimItem(dia, DFHA_WIDTHSUBDIV_L);
877 				DiaEditControl(dia, DFHA_WIDTHSUBDIV);
878 				DiaUnDimItem(dia, DFHA_HEIGHTSUBDIV_L);
879 				DiaEditControl(dia, DFHA_HEIGHTSUBDIV);
880 				DiaUnDimItem(dia, DFHA_ARCHEADZ_L);
881 				DiaEditControl(dia, DFHA_ARCHEADZ);
882 				DiaUnDimItem(dia, DFHA_ARCTAILZ_L);
883 				DiaEditControl(dia, DFHA_ARCTAILZ);
884 				DiaUnDimItem(dia, DFHA_GROUPNAME_L);
885 				DiaUnDimItem(dia, DFHA_GROUPNAME);
886 				DiaUnDimItem(dia, DFHA_NEWGROUP);
887 				DiaSetControl(dia, DFHA_INCLUDE, 1);
888 			} else
889 			{
890 				DiaDimItem(dia, DFHA_ARCTHICK_L);
891 				DiaNoEditControl(dia, DFHA_ARCTHICK);
892 				DiaDimItem(dia, DFHA_WIDTHSUBDIV_L);
893 				DiaNoEditControl(dia, DFHA_WIDTHSUBDIV);
894 				DiaDimItem(dia, DFHA_HEIGHTSUBDIV_L);
895 				DiaNoEditControl(dia, DFHA_HEIGHTSUBDIV);
896 				DiaDimItem(dia, DFHA_ARCHEADZ_L);
897 				DiaNoEditControl(dia, DFHA_ARCHEADZ);
898 				DiaDimItem(dia, DFHA_ARCTAILZ_L);
899 				DiaNoEditControl(dia, DFHA_ARCTAILZ);
900 				DiaDimItem(dia, DFHA_GROUPNAME_L);
901 				DiaDimItem(dia, DFHA_GROUPNAME);
902 				DiaDimItem(dia, DFHA_NEWGROUP);
903 			}
904 			continue;
905 		}
906 		if (itemHit == DFHA_NEWGROUP)		/* new group name */
907 		{
908 			newname = ttygetline(_("New group name:"));
909 			if (newname == 0 || *newname == 0) continue;
910 			for(i=0; i<groupnamesize; i++)
911 				if (namesame(groupnames[i], newname) == 0) break;
912 			if (i < groupnamesize) continue;
913 
914 			/* add to the list */
915 			newgroupnames = (CHAR **)emalloc((groupnamesize+1) * (sizeof (CHAR *)), sim_tool->cluster);
916 			for(i=0; i<groupnamesize; i++)
917 				newgroupnames[i] = groupnames[i];
918 			(void)allocstring(&newgroupnames[groupnamesize], newname, sim_tool->cluster);
919 			if (groupnamesize > 0) efree((CHAR *)groupnames);
920 			groupnames = newgroupnames;
921 			groupnamesize++;
922 			DiaSetPopup(dia, DFHA_GROUPNAME, groupnamesize, groupnames);
923 			DiaSetPopupEntry(dia, DFHA_GROUPNAME, groupnamesize-1);
924 			continue;
925 		}
926 	}
927 
928 	if (itemHit == OK)
929 	{
930 		startobjectchange((INTBIG)ai, VARCINST);
931 		var = getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey);
932 		if (DiaGetControl(dia, DFHA_INCLUDE) != 0)
933 		{
934 			/* active in FastHenry */
935 			i = DiaGetPopupEntry(dia, DFHA_GROUPNAME);
936 			groupname = groupnames[i];
937 			if (var == NOVARIABLE || estrcmp(groupname, (CHAR *)var->addr) != 0)
938 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenrygroupnamekey,
939 					(INTBIG)groupname, VSTRING|VDISPLAY);
940 		} else
941 		{
942 			if (var != NOVARIABLE)
943 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenrygroupnamekey);
944 		}
945 
946 		/* save thickness */
947 		pt = DiaGetText(dia, DFHA_ARCTHICK);
948 		var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrythicknesskey);
949 		if (*pt != 0)
950 		{
951 			val = atola(pt, 0);
952 			if (var == NOVARIABLE || val != var->addr)
953 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenrythicknesskey, val, VINTEGER);
954 		} else
955 		{
956 			if (var != NOVARIABLE)
957 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenrythicknesskey);
958 		}
959 
960 		/* save width and height subdivisions */
961 		pt = DiaGetText(dia, DFHA_WIDTHSUBDIV);
962 		var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrywidthsubdivkey);
963 		if (*pt != 0)
964 		{
965 			val = eatoi(pt);
966 			if (var == NOVARIABLE || val != var->addr)
967 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenrywidthsubdivkey, val, VINTEGER);
968 		} else
969 		{
970 			if (var != NOVARIABLE)
971 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenrywidthsubdivkey);
972 		}
973 		pt = DiaGetText(dia, DFHA_HEIGHTSUBDIV);
974 		var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryheightsubdivkey);
975 		if (*pt != 0)
976 		{
977 			val = eatoi(pt);
978 			if (var == NOVARIABLE || val != var->addr)
979 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenryheightsubdivkey, val, VINTEGER);
980 		} else
981 		{
982 			if (var != NOVARIABLE)
983 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenryheightsubdivkey);
984 		}
985 
986 		/* save z overrides */
987 		pt = DiaGetText(dia, DFHA_ARCHEADZ);
988 		var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryzheadkey);
989 		if (*pt != 0)
990 		{
991 			val = atola(pt, 0);
992 			if (var == NOVARIABLE || val != var->addr)
993 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenryzheadkey, val, VINTEGER);
994 		} else
995 		{
996 			if (var != NOVARIABLE)
997 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenryzheadkey);
998 		}
999 		pt = DiaGetText(dia, DFHA_ARCTAILZ);
1000 		var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryztailkey);
1001 		if (*pt != 0)
1002 		{
1003 			val = atola(pt, 0);
1004 			if (var == NOVARIABLE || val != var->addr)
1005 				setvalkey((INTBIG)ai, VARCINST, sim_fasthenryztailkey, val, VINTEGER);
1006 		} else
1007 		{
1008 			if (var != NOVARIABLE)
1009 				(void)delvalkey((INTBIG)ai, VARCINST, sim_fasthenryztailkey);
1010 		}
1011 		endobjectchange((INTBIG)ai, VARCINST);
1012 	}
1013 	DiaDoneDialog(dia);
1014 
1015 	/* free group list memory */
1016 	for(i=0; i<groupnamesize; i++)
1017 		efree(groupnames[i]);
1018 	efree((CHAR *)groupnames);
1019 }
1020 
1021 #endif  /* SIMTOOL - at top */
1022