1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usrcomek.c
6 * User interface tool: command handler for E through K
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 "usr.h"
34 #include "usrtrack.h"
35 #include "usrdiacom.h"
36 #include "efunction.h"
37 #include "edialogs.h"
38 #include "tecart.h"
39 #include "tecgen.h"
40 #include "tecschem.h"
41 #include "sim.h"
42 #include "network.h"
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #ifdef HAVE_FCNTL_H
47 # include <fcntl.h>
48 #endif
49
50 #define MAXLINE 500 /* maximum length of news/help file input lines */
51
52 /* working memory for "us_iterate()" */
53 static INTBIG *us_iterateaddr, *us_iteratetype;
54 static INTBIG us_iteratelimit=0;
55
56 /*
57 * Routine to free all memory associated with this module.
58 */
us_freecomekmemory(void)59 void us_freecomekmemory(void)
60 {
61 if (us_iteratelimit > 0)
62 {
63 efree((CHAR *)us_iterateaddr);
64 efree((CHAR *)us_iteratetype);
65 }
66 }
67
us_echo(INTBIG count,CHAR * par[])68 void us_echo(INTBIG count, CHAR *par[])
69 {
70 REGISTER INTBIG lastquiet, j;
71 REGISTER void *infstr;
72
73 lastquiet = ttyquiet(0);
74 infstr = initinfstr();
75 for(j=0; j<count; j++)
76 {
77 addstringtoinfstr(infstr, par[j]);
78 addtoinfstr(infstr, ' ');
79 }
80 ttyputmsg(x_("%s"), returninfstr(infstr));
81 (void)ttyquiet(lastquiet);
82 }
83
84 /* Simulation: Select Node Index */
85 static DIALOGITEM us_selinddialogitems[] =
86 {
87 /* 1 */ {0, {76,120,100,200}, BUTTON, N_("OK")},
88 /* 2 */ {0, {76,16,100,96}, BUTTON, N_("Cancel")},
89 /* 3 */ {0, {4,4,20,216}, MESSAGE, N_("This node is arrayed")},
90 /* 4 */ {0, {24,4,40,216}, MESSAGE, N_("Which entry should be entered?")},
91 /* 5 */ {0, {48,4,64,216}, POPUP, x_("")}
92 };
93 static DIALOG us_selinddialog = {{75,75,184,301}, N_("Select Node Index"), 0, 5, us_selinddialogitems, 0, 0};
94
95 /* special items for the "Select Node Index" dialog: */
96 #define DSNI_CHOICES 5 /* List of indices (popup) */
97
us_editcell(INTBIG count,CHAR * par[])98 void us_editcell(INTBIG count, CHAR *par[])
99 {
100 REGISTER INTBIG implicit, i, len, newwindow, nonredundant, intoicon, lambda, inplace, index,
101 sigcount, itemHit;
102 BOOLEAN newframe, push, exact;
103 INTBIG lx, hx, ly, hy;
104 INTBIG viewinfo[22];
105 REGISTER NODEPROTO *np, *onp, *np1, *curcell;
106 REGISTER NODEINST *ni, *stacknodeinst;
107 REGISTER LIBRARY *lib, *olib;
108 REGISTER VARIABLE *var;
109 REGISTER void *dia;
110 REGISTER WINDOWPART *win;
111 REGISTER CHAR *pt;
112 CHAR **nodenames;
113 NODEINST *hini;
114 XARRAY rotarray, transarray, xfarray, newarray;
115 PORTPROTO *hipp;
116
117 /* get proper highlighting in subcell if port is selected */
118 us_findlowerport(&hini, &hipp);
119
120 /* find the nodeinst in this window to go "down into" (if any) */
121 newwindow = 0;
122 nonredundant = 0;
123 intoicon = 0;
124 inplace = 0;
125 index = 0;
126 if (count == 1)
127 {
128 len = estrlen(par[0]);
129 if (len == 0) count--; else
130 {
131 if (namesamen(par[0], x_("in-place"), len) == 0)
132 {
133 if (el_curwindowpart->inplacedepth >= MAXINPLACEDEPTH)
134 {
135 ttyputerr(_("Can only go down %ld levels in-place"), MAXINPLACEDEPTH);
136 return;
137 }
138 inplace = 1;
139 count--;
140 }
141 }
142 }
143 if (count == 0)
144 {
145 implicit = 1;
146 ni = (NODEINST *)us_getobject(VNODEINST, FALSE);
147 if (ni == NONODEINST) return;
148 stacknodeinst = ni;
149 np = ni->proto;
150
151 /* translate this reference if this is an icon cell */
152 if (np->cellview == el_iconview)
153 {
154 implicit = 0;
155 if (!isiconof(np, ni->parent))
156 {
157 onp = contentsview(np);
158 if (onp != NONODEPROTO) np = onp;
159 } else
160 {
161 intoicon = 1;
162 }
163 }
164 } else
165 {
166 /* check for options */
167 for(i=1; i<count; i++)
168 {
169 len = estrlen(par[i]);
170 if (namesamen(par[i], x_("new-window"), len) == 0 && len > 1) newwindow++; else
171 if (namesamen(par[i], x_("non-redundant"), len) == 0 && len > 1) nonredundant++; else
172 {
173 ttyputbadusage(x_("editcell"));
174 return;
175 }
176 }
177
178 /* see if specified cell exists */
179 implicit = 0;
180 np = getnodeproto(par[0]);
181
182 /* if it is a new cell, create it */
183 if (np == NONODEPROTO)
184 {
185 lib = el_curlib;
186 for(pt = par[0]; *pt != 0; pt++) if (*pt == ':') break;
187 if (*pt != ':') pt = par[0]; else
188 {
189 i = *pt;
190 *pt = 0;
191 lib = getlibrary(par[0]);
192 *pt = (CHAR)i;
193 if (lib == NOLIBRARY)
194 {
195 us_abortcommand(_("Cannot find library for new cell %s"), par[0]);
196 return;
197 }
198 pt++;
199 }
200 np = us_newnodeproto(pt, lib);
201 if (np == NONODEPROTO)
202 {
203 us_abortcommand(_("Cannot create cell %s"), par[0]);
204 return;
205 }
206 ttyputverbose(M_("Editing new cell: %s"), par[0]);
207 }
208
209 /* look through window for instances of this cell */
210 stacknodeinst = NONODEINST;
211 curcell = getcurcell();
212 if (curcell != NONODEPROTO)
213 {
214 for(ni = curcell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
215 if (ni->proto == np)
216 {
217 stacknodeinst = ni;
218 break;
219 }
220 }
221 }
222
223 /* make sure nodeinst is not primitive and in proper technology */
224 if (np->primindex != 0)
225 {
226 us_abortcommand(_("Cannot edit primitive nodes"));
227 return;
228 }
229
230 push = FALSE;
231 exact = FALSE;
232 if (stacknodeinst != NONODEINST)
233 {
234 /* if in waveform window, switch to associated circuit window */
235 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
236 {
237 for(win = el_topwindowpart; win != NOWINDOWPART; win = win->nextwindowpart)
238 if (win != el_curwindowpart && win->curnodeproto == stacknodeinst->parent) break;
239 if (win == NOWINDOWPART)
240 {
241 us_abortcommand(_("Cannot go down the hierarchy from this waveform window"));
242 return;
243 }
244 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)win,
245 VWINDOWPART|VDONTSAVE);
246 }
247
248 /* if simulating, and node is arrayed, find out the index */
249 if (stacknodeinst->arraysize > 1 && el_curwindowpart != NOWINDOWPART &&
250 (el_curwindowpart->state&WINDOWMODE) == WINDOWSIMMODE)
251 {
252 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
253 if (var != NOVARIABLE)
254 {
255 /* must find out which index is being traversed */
256 sigcount = net_evalbusname(APBUS, (CHAR *)var->addr, &nodenames,
257 NOARCINST, NONODEPROTO, 0);
258 dia = DiaInitDialog(&us_selinddialog);
259 DiaSetPopup(dia, DSNI_CHOICES, sigcount, nodenames);
260 for(;;)
261 {
262 itemHit = DiaNextHit(dia);
263 if (itemHit == CANCEL || itemHit == OK) break;
264 }
265 if (itemHit != CANCEL)
266 index = DiaGetPopupEntry(dia, DSNI_CHOICES);
267 DiaDoneDialog(dia);
268 }
269 }
270
271 viewinfo[0] = el_curwindowpart->screenlx;
272 viewinfo[1] = el_curwindowpart->screenhx;
273 viewinfo[2] = el_curwindowpart->screenly;
274 viewinfo[3] = el_curwindowpart->screenhy;
275 viewinfo[4] = el_curwindowpart->intocell[0][0];
276 viewinfo[5] = el_curwindowpart->intocell[0][1];
277 viewinfo[6] = el_curwindowpart->intocell[0][2];
278 viewinfo[7] = el_curwindowpart->intocell[1][0];
279 viewinfo[8] = el_curwindowpart->intocell[1][1];
280 viewinfo[9] = el_curwindowpart->intocell[1][2];
281 viewinfo[10] = el_curwindowpart->intocell[2][0];
282 viewinfo[11] = el_curwindowpart->intocell[2][1];
283 viewinfo[12] = el_curwindowpart->intocell[2][2];
284 viewinfo[13] = el_curwindowpart->outofcell[0][0];
285 viewinfo[14] = el_curwindowpart->outofcell[0][1];
286 viewinfo[15] = el_curwindowpart->outofcell[0][2];
287 viewinfo[16] = el_curwindowpart->outofcell[1][0];
288 viewinfo[17] = el_curwindowpart->outofcell[1][1];
289 viewinfo[18] = el_curwindowpart->outofcell[1][2];
290 viewinfo[19] = el_curwindowpart->outofcell[2][0];
291 viewinfo[20] = el_curwindowpart->outofcell[2][1];
292 viewinfo[21] = el_curwindowpart->outofcell[2][2];
293 push = TRUE;
294 exact = TRUE;
295 onp = contentsview(np);
296 if (onp == NONODEPROTO || intoicon != 0) onp = np;
297 sethierarchicalparent(onp, stacknodeinst, el_curwindowpart, index, viewinfo);
298 }
299
300 /* check dates of subcells */
301 if ((us_useroptions&CHECKDATE) != 0)
302 {
303 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
304 for(np1 = olib->firstnodeproto; np1 != NONODEPROTO; np1 = np1->nextnodeproto)
305 np1->temp1 = 0;
306 us_check_cell_date(np, np->revisiondate);
307 }
308
309 /* if a nonredundant display is needed, see if it already exists */
310 if (nonredundant != 0)
311 {
312 for(win = el_topwindowpart; win != NOWINDOWPART; win = win->nextwindowpart)
313 if (win->curnodeproto == np) break;
314 if (win != NOWINDOWPART)
315 {
316 /* switch to window "win" */
317 bringwindowtofront(win->frame);
318 us_highlightwindow(win, FALSE);
319 return;
320 }
321 }
322
323 /* determine window area */
324 if (el_curwindowpart == NOWINDOWPART)
325 {
326 lx = np->lowx; hx = np->lowx;
327 ly = np->lowy; hy = np->lowy;
328 } else
329 {
330 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
331 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
332 if (el_curwindowpart->curnodeproto == NONODEPROTO)
333 {
334 lambda = el_curlib->lambda[el_curtech->techindex];
335 lx = -lambda * 25;
336 hx = lambda * 25;
337 ly = -lambda * 25;
338 hy = lambda * 25;
339 }
340 }
341 if (implicit == 0)
342 {
343 /* make the new cell fill the window */
344 us_fullview(np, &lx, &hx, &ly, &hy);
345 exact = FALSE;
346 } else
347 {
348 /* make the current cell be in the same place in the window */
349 if (inplace != 0)
350 {
351 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
352 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
353 } else
354 {
355 lx += np->lowx - stacknodeinst->lowx;
356 hx += np->lowx - stacknodeinst->lowx;
357 ly += np->lowy - stacknodeinst->lowy;
358 hy += np->lowy - stacknodeinst->lowy;
359 }
360 }
361
362 if (stacknodeinst != NONODEINST)
363 {
364 /* if simulating, coordinate this hierarchy traversal with the waveform */
365 if (el_curwindowpart != NOWINDOWPART &&
366 (el_curwindowpart->state&WINDOWMODE) == WINDOWSIMMODE)
367 {
368 asktool(sim_tool, "traverse-down", (INTBIG)stacknodeinst, np);
369 }
370 }
371
372 /* edit the cell (creating a new frame/partition if requested) */
373 if (newwindow != 0 || el_curwindowpart == NOWINDOWPART)
374 {
375 newframe = TRUE;
376 push = FALSE;
377 } else
378 {
379 newframe = FALSE;
380 }
381 if (implicit != 0 && inplace != 0)
382 {
383 makerotI(stacknodeinst, rotarray);
384 maketransI(stacknodeinst, transarray);
385 transmult(rotarray, transarray, xfarray);
386 transmult(el_curwindowpart->intocell, xfarray, newarray);
387 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("intocell"), newarray);
388
389 makerot(stacknodeinst, rotarray);
390 maketrans(stacknodeinst, transarray);
391 transmult(transarray, rotarray, xfarray);
392 transmult(xfarray, el_curwindowpart->outofcell, newarray);
393 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("outofcell"), newarray);
394 if ((el_curwindowpart->state&INPLACEEDIT) == 0)
395 {
396 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("inplacedepth"), 0, VINTEGER);
397 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("topnodeproto"),
398 (INTBIG)el_curwindowpart->curnodeproto, VNODEPROTO);
399 }
400 (void)setind((INTBIG)el_curwindowpart, VWINDOWPART, x_("inplacestack"),
401 el_curwindowpart->inplacedepth, (INTBIG)stacknodeinst);
402 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("inplacedepth"),
403 el_curwindowpart->inplacedepth+1, VINTEGER);
404 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
405 el_curwindowpart->state | INPLACEEDIT, VINTEGER);
406 } else
407 {
408 if (el_curwindowpart != NOWINDOWPART)
409 {
410 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("intocell"), el_matid);
411 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("outofcell"), el_matid);
412 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
413 el_curwindowpart->state & ~INPLACEEDIT, VINTEGER);
414 }
415 }
416 us_switchtocell(np, lx, hx, ly, hy, hini, hipp, newframe, push, exact);
417 }
418
us_erase(INTBIG count,CHAR * par[])419 void us_erase(INTBIG count, CHAR *par[])
420 {
421 REGISTER INTBIG i, j, l;
422 INTBIG textcount;
423 CHAR **textinfo;
424 BOOLEAN allvisible, foundnode, cleaned;
425 REGISTER NODEINST *ni;
426 ARCINST *ai;
427 REGISTER NODEPROTO *np;
428 HIGHLIGHT high;
429 REGISTER CHAR *pt;
430 REGISTER GEOM **list;
431 REGISTER LIBRARY *lib;
432 REGISTER WINDOWPART *w;
433 HIGHLIGHT newhigh;
434 REGISTER void *infstr;
435
436 if (count > 0)
437 {
438 l = estrlen(pt = par[0]);
439 if (namesamen(pt, x_("clean-up-all"), l) == 0 && l > 8)
440 {
441 us_clearhighlightcount();
442 cleaned = FALSE;
443 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
444 if (us_cleanupcell(np, FALSE)) cleaned = TRUE;
445 if (!cleaned) ttyputmsg(_("Nothing to clean"));
446 return;
447 }
448 if (namesamen(pt, x_("clean-up"), l) == 0)
449 {
450 np = us_needcell();
451 if (np == NONODEPROTO) return;
452 us_clearhighlightcount();
453 (void)us_cleanupcell(np, TRUE);
454 return;
455 }
456 if (namesamen(pt, x_("geometry"), l) == 0)
457 {
458 np = us_needcell();
459 if (np == NONODEPROTO) return;
460 us_erasegeometry(np);
461 return;
462 }
463 }
464
465 /* get list of highlighted objects to be erased */
466 np = us_needcell();
467 if (np == NONODEPROTO)
468 {
469 us_abortcommand(_("No current cell"));
470 return;
471 }
472 list = us_gethighlighted(WANTARCINST|WANTNODEINST, &textcount, &textinfo);
473 if (list[0] == NOGEOM && textcount == 0)
474 {
475 us_abortcommand(_("Find an object to erase"));
476 return;
477 }
478
479 /* if in outline-edit mode, delete the selected point */
480 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
481 {
482 par[0] = x_("trace");
483 par[1] = x_("delete-point");
484 us_node(2, par);
485 return;
486 }
487
488 /* make sure that all requested objects are displayed */
489 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
490 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
491 np->temp1 = 0;
492 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
493 if (w->curnodeproto != NONODEPROTO)
494 w->curnodeproto->temp1 = 1;
495 allvisible = TRUE;
496 for(i=0; list[i] != NOGEOM; i++)
497 {
498 np = geomparent(list[i]);
499 if (np->temp1 == 0) allvisible = FALSE;
500 }
501 for(i=0; i<textcount; i++)
502 {
503 (void)us_makehighlight(textinfo[i], &high);
504 np = high.cell;
505 if (np->temp1 == 0) allvisible = FALSE;
506 }
507 if (!allvisible)
508 {
509 infstr = initinfstr();
510 addstringtoinfstr(infstr, _("Some of the objects to be deleted are not displayed. Delete anyway?"));
511 addstringtoinfstr(infstr, _(" (click 'no' to delete only visible objects, 'yes' to delete all selected)"));
512 j = us_noyescanceldlog(returninfstr(infstr), par);
513 if (j == 0) return;
514 if (namesame(par[0], x_("cancel")) == 0) return;
515 if (namesame(par[0], x_("no")) == 0)
516 {
517 j = 0;
518 for(i=0; list[i] != NOGEOM; i++)
519 {
520 np = geomparent(list[i]);
521 if (np->temp1 == 0) continue;
522 list[j++] = list[i];
523 }
524 if (j == 0)
525 {
526 us_abortcommand(_("No displayed objects to delete"));
527 return;
528 }
529 list[j] = NOGEOM;
530 }
531 }
532
533 /* remove from list if a node is locked */
534 j = 0;
535 foundnode = FALSE;
536 for(i=0; list[i] != NOGEOM; i++)
537 {
538 if (list[i]->entryisnode)
539 {
540 ni = list[i]->entryaddr.ni;
541 if (us_cantedit(np, ni, TRUE)) continue;
542 foundnode = TRUE;
543 }
544 list[j++] = list[i];
545 }
546 list[j] = NOGEOM;
547 if (list[0] == NOGEOM && textcount == 0)
548 {
549 us_abortcommand(_("All selected objects are locked"));
550 return;
551 }
552
553 if (!foundnode)
554 {
555 /* disallow erasing if lock is on */
556 if (us_cantedit(np, NONODEINST, TRUE)) return;
557 }
558
559 /* unhighlight */
560 us_clearhighlightcount();
561
562 /* if one node is selected, see if it can be handled with reconnection */
563 if (list[0] != NOGEOM && list[0]->entryisnode && list[1] == NOGEOM && textcount == 0)
564 {
565 j = us_erasepassthru(ni, FALSE, &ai);
566 if (j == 2)
567 {
568 /* worked: highlight the arc */
569 newhigh.status = HIGHFROM;
570 newhigh.fromgeom = ai->geom;
571 newhigh.cell = np;
572 us_setfind(&newhigh, 0, 1, 0, 0);
573 return;
574 }
575 }
576
577 /* delete the text */
578 for(i=0; i<textcount; i++)
579 {
580 (void)us_makehighlight(textinfo[i], &high);
581
582 /* disallow erasing if lock is on */
583 np = high.cell;
584 if (np != NONODEPROTO)
585 {
586 if (us_cantedit(np, NONODEINST, TRUE)) continue;
587 }
588
589 /* do not deal with text on an object if the object is already in the list */
590 if (high.fromgeom != NOGEOM)
591 {
592 for(j=0; list[j] != NOGEOM; j++)
593 if (list[j] == high.fromgeom) break;
594 if (list[j] != NOGEOM) continue;
595 }
596
597 /* deleting variable on object */
598 if (high.fromvar != NOVARIABLE)
599 {
600 if (high.fromgeom == NOGEOM)
601 {
602 us_undrawcellvariable(high.fromvar, np);
603 (void)delval((INTBIG)np, VNODEPROTO, makename(high.fromvar->key));
604 } else if (high.fromgeom->entryisnode)
605 {
606 ni = high.fromgeom->entryaddr.ni;
607 startobjectchange((INTBIG)ni, VNODEINST);
608
609 /* if deleting port variables, do that */
610 if (high.fromport != NOPORTPROTO)
611 {
612 (void)delval((INTBIG)high.fromport, VPORTPROTO, makename(high.fromvar->key));
613 } else
614 {
615 /* if deleting text on invisible pin, delete pin too */
616 if (ni->proto == gen_invispinprim) us_erasenodeinst(ni); else
617 (void)delval((INTBIG)ni, VNODEINST, makename(high.fromvar->key));
618 }
619 endobjectchange((INTBIG)ni, VNODEINST);
620 } else
621 {
622 ai = high.fromgeom->entryaddr.ai;
623 startobjectchange((INTBIG)ai, VARCINST);
624 (void)delval((INTBIG)ai, VARCINST, makename(high.fromvar->key));
625 endobjectchange((INTBIG)ai, VARCINST);
626 }
627 } else if (high.fromport != NOPORTPROTO)
628 {
629 ni = high.fromgeom->entryaddr.ni;
630 startobjectchange((INTBIG)ni, VNODEINST);
631 us_undoportproto((NODEINST *)ni, high.fromport);
632 endobjectchange((INTBIG)ni, VNODEINST);
633 } else if (high.fromgeom->entryisnode)
634 us_abortcommand(_("Cannot delete cell name"));
635 }
636
637 /* look for option to re-connect arcs into an erased node */
638 if (count > 0 && namesamen(par[0], x_("pass-through"), estrlen(par[0])) == 0)
639 {
640 for(i=0; list[i] != NOGEOM; i++)
641 {
642 if (!list[i]->entryisnode) continue;
643 ni = list[i]->entryaddr.ni;
644 j = us_erasepassthru(ni, TRUE, &ai);
645 switch (j)
646 {
647 case 2:
648 break;
649 case -1:
650 us_abortcommand(_("Arcs to node %s are of different type"),
651 describenodeinst(ni));
652 break;
653 case -5:
654 us_abortcommand(_("Cannot create connecting arc"));
655 break;
656 default:
657 us_abortcommand(_("Must be 2 arcs on node %s (it has %ld)"),
658 describenodeinst(ni), j);
659 break;
660 }
661 }
662 return;
663 }
664
665 /* handle simple erasing */
666 us_eraseobjectsinlist(np, list);
667 }
668
us_find(INTBIG count,CHAR * par[])669 void us_find(INTBIG count, CHAR *par[])
670 {
671 REGISTER INTBIG i, j, l, findport, findpoint, findexclusively, findangle,
672 findwithin, findstill, findspecial, size, findeasy, findhard, total, type, addr,
673 len, first, areasizex, areasizey, x, y, *newlist, extrainfo, findmore, findnobox;
674 INTBIG xcur, ycur;
675 REGISTER BOOLEAN waitforpush;
676 XARRAY trans;
677 REGISTER NODEINST *ni;
678 REGISTER NODEPROTO *np, *onp;
679 REGISTER LIBRARY *lib;
680 REGISTER GEOM *geom, **glist;
681 REGISTER ARCINST *ai;
682 REGISTER PORTPROTO *pp;
683 REGISTER NETWORK *net;
684 REGISTER VARIABLE *var, *highvar;
685 REGISTER CHAR *pt;
686 CHAR **list;
687 HIGHLIGHT newhigh, newhightext;
688 REGISTER void *infstr;
689
690 if (count >= 1)
691 {
692 l = estrlen(pt = par[0]);
693 if (namesamen(pt, x_("constraint-angle"), l) == 0 && l >= 12)
694 {
695 if (count >= 2)
696 {
697 (void)setvalkey((INTBIG)us_tool, VTOOL, us_interactiveanglekey,
698 atofr(par[1])*10/WHOLE, VINTEGER|VDONTSAVE);
699 }
700 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_interactiveanglekey);
701 if (var == NOVARIABLE) findangle = 0; else
702 findangle = var->addr;
703 if (findangle == 0)
704 {
705 ttyputverbose(M_("Interactive dragging done with no constraints"));
706 } else
707 {
708 ttyputverbose(M_("Interactive dragging constrained to %ld degree angles"),
709 findangle);
710 }
711 return;
712 }
713 }
714
715 /* make sure there is a cell being edited */
716 np = us_needcell();
717 if (np == NONODEPROTO) return;
718 if ((np->cellview->viewstate&TEXTVIEW) != 0)
719 {
720 l = estrlen(pt = par[0]);
721 if (namesamen(pt, x_("all"), l) == 0 && l >= 2)
722 {
723 /* special case: "find all" selects all text */
724 i = us_totallines(el_curwindowpart);
725 us_highlightline(el_curwindowpart, 0, i-1);
726 return;
727 }
728 us_abortcommand(M_("There are no components to select in a text-only cell"));
729 return;
730 }
731 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
732 {
733 us_abortcommand(M_("Cannot select objects in a 3D window"));
734 return;
735 }
736
737 /* establish the default highlight environment */
738 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
739 if (highvar != NOVARIABLE)
740 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &newhigh); else
741 {
742 newhigh.status = 0;
743 newhigh.fromgeom = NOGEOM;
744 newhigh.fromport = NOPORTPROTO;
745 newhigh.fromvar = NOVARIABLE;
746 newhigh.fromvarnoeval = NOVARIABLE;
747 newhigh.frompoint = 0;
748 }
749
750 /* look for qualifiers */
751 findport = findpoint = findexclusively = findwithin = findmore = 0;
752 findstill = findspecial = findnobox = 0;
753 extrainfo = 0;
754 while (count > 0)
755 {
756 l = estrlen(pt = par[0]);
757 if (namesamen(pt, x_("extra-info"), l) == 0 && l >= 3)
758 {
759 extrainfo = HIGHEXTRA;
760 count--; par++; continue;
761 }
762 if (namesamen(pt, x_("more"), l) == 0 && l >= 1)
763 {
764 findmore++;
765 count--; par++; continue;
766 }
767 if (namesamen(pt, x_("no-box"), l) == 0 && l >= 3)
768 {
769 findnobox++;
770 count--; par++; continue;
771 }
772 if (namesamen(pt, x_("special"), l) == 0 && l >= 2)
773 {
774 findspecial++;
775 count--; par++; continue;
776 }
777 if (namesamen(pt, x_("still"), l) == 0 && l >= 2)
778 {
779 findstill++;
780 count--; par++; continue;
781 }
782 if (namesamen(pt, x_("exclusively"), l) == 0 && l >= 3)
783 {
784 findexclusively++;
785 count--; par++; continue;
786 }
787 if (namesamen(pt, x_("within"), l) == 0 && l >= 1)
788 {
789 if (newhigh.status == 0)
790 {
791 us_abortcommand(M_("Find an object before working 'within' it"));
792 return;
793 }
794 if ((newhigh.status&HIGHTYPE) != HIGHFROM || !newhigh.fromgeom->entryisnode)
795 {
796 us_abortcommand(M_("Must find a node before working 'within'"));
797 return;
798 }
799
800 findwithin++;
801 count--; par++; continue;
802 }
803 if (namesamen(pt, x_("port"), l) == 0 && l >= 1)
804 {
805 findport = 1;
806 count--; par++; continue;
807 }
808 if (namesamen(pt, x_("vertex"), l) == 0 && l >= 2)
809 {
810 findpoint = 1;
811 count--; par++; continue;
812 }
813 break;
814 }
815
816 if (count >= 1)
817 {
818 l = estrlen(pt = par[0]);
819
820 if (namesamen(pt, x_("all"), l) == 0 && l >= 2)
821 {
822 if (findpoint != 0 || findwithin != 0 || findmore != 0 ||
823 findexclusively != 0 || findstill != 0 || findspecial != 0)
824 {
825 us_abortcommand(M_("Illegal options given to 'find all'"));
826 return;
827 }
828 findeasy = findhard = 1;
829 if (count >= 2)
830 {
831 l = estrlen(pt = par[1]);
832 if (namesamen(pt, x_("easy"), l) == 0) findhard = 0; else
833 if (namesamen(pt, x_("hard"), l) == 0) findeasy = 0; else
834 {
835 ttyputusage(x_("find all [easy|hard]"));
836 return;
837 }
838 }
839 total = 0;
840 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst) total++;
841 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst) total++;
842 for(i=0; i<np->numvar; i++)
843 {
844 var = &np->firstvar[i];
845 if ((var->type&VDISPLAY) != 0) total++;
846 }
847 if (total == 0) return;
848 list = (CHAR **)emalloc((total * (sizeof (CHAR *))), el_tempcluster);
849 if (list == 0) return;
850
851 newhigh.status = HIGHFROM | extrainfo;
852 if (findnobox != 0) newhigh.status |= HIGHNOBOX;
853 newhigh.cell = np;
854 newhigh.frompoint = 0;
855 newhigh.fromvar = NOVARIABLE;
856 newhigh.fromvarnoeval = NOVARIABLE;
857
858 newhightext.status = HIGHTEXT;
859 newhightext.cell = np;
860 newhightext.fromport = NOPORTPROTO;
861 newhightext.frompoint = 0;
862 newhightext.fromvarnoeval = NOVARIABLE;
863
864 total = 0;
865 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
866 {
867 if (ni->proto->primindex == 0 && (us_useroptions&NOINSTANCESELECT) != 0)
868 {
869 /* cell instance that is hard to select */
870 if (findhard == 0) continue;
871 } else
872 {
873 /* regular node: see if it should be selected */
874 if (findeasy == 0 && (ni->userbits&HARDSELECTN) == 0) continue;
875 if (findhard == 0 && (ni->userbits&HARDSELECTN) != 0) continue;
876 }
877 if (ni->proto->primindex != 0 && (ni->proto->userbits&NINVISIBLE) != 0)
878 continue;
879
880 /* if this is an invisible primitive with text, select the text */
881 if (ni->proto == gen_invispinprim)
882 {
883 j = 0;
884 for(i=0; i<ni->numvar; i++)
885 {
886 var = &ni->firstvar[i];
887 if ((var->type&VDISPLAY) == 0) continue;
888 newhightext.fromgeom = ni->geom;
889 newhightext.fromvar = var;
890 pt = us_makehighlightstring(&newhightext);
891 (void)allocstring(&list[total], pt, el_tempcluster);
892 total++;
893 j = 1;
894 }
895 if (j != 0) continue;
896 }
897
898 newhigh.fromgeom = ni->geom;
899 newhigh.fromport = NOPORTPROTO;
900 if (findport != 0)
901 {
902 pp = ni->proto->firstportproto;
903 if (pp != NOPORTPROTO && pp->nextportproto == NOPORTPROTO)
904 newhigh.fromport = pp;
905 }
906 pt = us_makehighlightstring(&newhigh);
907 (void)allocstring(&list[total], pt, el_tempcluster);
908 total++;
909 }
910 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
911 {
912 if (findeasy == 0 && (ai->userbits&HARDSELECTA) == 0) continue;
913 if (findhard == 0 && (ai->userbits&HARDSELECTA) != 0) continue;
914 if ((ai->proto->userbits&AINVISIBLE) != 0) continue;
915 newhigh.fromgeom = ai->geom;
916 newhigh.fromport = NOPORTPROTO;
917 pt = us_makehighlightstring(&newhigh);
918 (void)allocstring(&list[total], pt, el_tempcluster);
919 total++;
920 }
921 if (findeasy != 0)
922 {
923 for(i=0; i<np->numvar; i++)
924 {
925 var = &np->firstvar[i];
926 if ((var->type&VDISPLAY) == 0) continue;
927 newhightext.fromgeom = NOGEOM;
928 newhightext.fromvar = var;
929 pt = us_makehighlightstring(&newhightext);
930 (void)allocstring(&list[total], pt, el_tempcluster);
931 total++;
932 }
933 }
934 if (total == 0) us_clearhighlightcount(); else
935 {
936 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
937 VSTRING|VISARRAY|(total<<VLENGTHSH)|VDONTSAVE);
938 }
939 for(i=0; i<total; i++) efree(list[i]);
940 efree((CHAR *)list);
941 us_showallhighlight();
942 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
943 return;
944 }
945
946 if (namesamen(pt, x_("arc"), l) == 0 && l >= 3)
947 {
948 if (count <= 1)
949 {
950 ttyputusage(x_("find arc ARCNAME"));
951 return;
952 }
953 if (findport != 0 || findpoint != 0 || findwithin != 0 || findspecial != 0)
954 {
955 us_abortcommand(M_("Illegal options given to 'find arc'"));
956 return;
957 }
958 if (findexclusively != 0 && us_curarcproto == NOARCPROTO)
959 {
960 us_abortcommand(M_("Must select an arc for exclusive finding"));
961 return;
962 }
963 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
964 {
965 if (findexclusively != 0 && ai->proto != us_curarcproto) continue;
966 var = getvalkey((INTBIG)ai, VARCINST, VSTRING, el_arc_name_key);
967 if (var == NOVARIABLE) continue;
968 if (namesame((CHAR *)var->addr, par[1]) == 0) break;
969 }
970 if (ai == NOARCINST)
971 {
972 us_abortcommand(_("Sorry, no %s arc named '%s' in this cell"),
973 (findexclusively==0 ? x_("") : describearcproto(us_curarcproto)), par[1]);
974 return;
975 }
976 newhigh.status = HIGHFROM;
977 newhigh.fromgeom = ai->geom;
978 newhigh.cell = np;
979 us_setfind(&newhigh, 0, extrainfo, findmore, findnobox);
980 return;
981 }
982
983 if (namesamen(pt, x_("area-define"), l) == 0 && l >= 6)
984 {
985 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
986 extrainfo != 0 || findwithin != 0 || findmore != 0 || findnobox != 0 ||
987 findspecial != 0)
988 {
989 us_abortcommand(M_("Illegal options given to 'find area-define'"));
990 return;
991 }
992 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
993 {
994 /* nonsensical in outline-edit mode */
995 return;
996 }
997
998 us_clearhighlightcount();
999 waitforpush = FALSE;
1000 if (count >= 2)
1001 {
1002 l = estrlen(par[1]);
1003 if (namesamen(par[1], x_("wait"), l) == 0 && l >= 1)
1004 waitforpush = TRUE;
1005 }
1006 trackcursor(waitforpush, us_ignoreup, us_finddbegin, us_stretchdown, us_stoponchar,
1007 us_invertdragup, TRACKDRAGGING);
1008 if (el_pleasestop != 0) return;
1009 np = getcurcell();
1010 if (np == NONODEPROTO) return;
1011 us_finddterm(&newhigh.stalx, &newhigh.staly);
1012 if (us_demandxy(&xcur, &ycur)) return;
1013 if (xcur >= newhigh.stalx) newhigh.stahx = xcur; else
1014 {
1015 newhigh.stahx = newhigh.stalx; newhigh.stalx = xcur;
1016 }
1017 if (ycur >= newhigh.staly) newhigh.stahy = ycur; else
1018 {
1019 newhigh.stahy = newhigh.staly; newhigh.staly = ycur;
1020 }
1021 newhigh.status = HIGHBBOX;
1022 newhigh.cell = np;
1023 us_addhighlight(&newhigh);
1024 return;
1025 }
1026
1027 if (namesamen(pt, x_("area-move"), l) == 0 && l >= 6)
1028 {
1029 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1030 extrainfo != 0 || findwithin != 0 || findmore != 0 || findnobox != 0 ||
1031 findspecial != 0)
1032 {
1033 us_abortcommand(M_("Illegal options given to 'find area-move'"));
1034 return;
1035 }
1036 if (us_demandxy(&xcur, &ycur)) return;
1037 gridalign(&xcur, &ycur, 1, np);
1038
1039 /* set the highlight */
1040 if ((newhigh.status&HIGHTYPE) == HIGHBBOX)
1041 {
1042 areasizex = newhigh.stahx - newhigh.stalx;
1043 areasizey = newhigh.stahy - newhigh.staly;
1044 } else
1045 {
1046 areasizex = (el_curwindowpart->screenhx-el_curwindowpart->screenlx) / 5;
1047 areasizey = (el_curwindowpart->screenhy-el_curwindowpart->screenly) / 5;
1048 }
1049
1050 us_clearhighlightcount();
1051
1052 /* adjust the cursor position if selecting interactively */
1053 if ((us_tool->toolstate&INTERACTIVE) != 0)
1054 {
1055 us_findinit(areasizex, areasizey);
1056 trackcursor(FALSE, us_ignoreup, us_findmbegin, us_dragdown, us_stoponchar,
1057 us_dragup, TRACKDRAGGING);
1058 if (el_pleasestop != 0) return;
1059 if (us_demandxy(&xcur, &ycur)) return;
1060 gridalign(&xcur, &ycur, 1, np);
1061 }
1062 newhigh.status = HIGHBBOX;
1063 newhigh.cell = np;
1064 newhigh.stalx = xcur; newhigh.stahx = xcur + areasizex;
1065 newhigh.staly = ycur; newhigh.stahy = ycur + areasizey;
1066 us_addhighlight(&newhigh);
1067 return;
1068 }
1069
1070 if (namesamen(pt, x_("area-size"), l) == 0 && l >= 6)
1071 {
1072 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1073 extrainfo != 0 || findwithin != 0 || findmore != 0 || findnobox != 0 ||
1074 findspecial != 0)
1075 {
1076 us_abortcommand(M_("Illegal options given to 'find area-size'"));
1077 return;
1078 }
1079 if (us_demandxy(&xcur, &ycur)) return;
1080 gridalign(&xcur, &ycur, 1, np);
1081
1082 if (newhigh.status != HIGHBBOX)
1083 {
1084 us_abortcommand(M_("Use 'find area-move' first, then this"));
1085 return;
1086 }
1087 if (np != newhigh.cell)
1088 {
1089 us_abortcommand(M_("Not in same cell as highlight area"));
1090 return;
1091 }
1092
1093 us_clearhighlightcount();
1094
1095 /* adjust the cursor position if selecting interactively */
1096 if ((us_tool->toolstate&INTERACTIVE) != 0)
1097 {
1098 us_findinit(newhigh.stalx, newhigh.staly);
1099 trackcursor(FALSE, us_ignoreup, us_findsbegin, us_stretchdown,
1100 us_stoponchar, us_invertdragup, TRACKDRAGGING);
1101 if (el_pleasestop != 0) return;
1102 if (us_demandxy(&xcur, &ycur)) return;
1103 gridalign(&xcur, &ycur, 1, np);
1104 }
1105 if (xcur >= newhigh.stalx) newhigh.stahx = xcur; else
1106 {
1107 newhigh.stahx = newhigh.stalx; newhigh.stalx = xcur;
1108 }
1109 if (ycur >= newhigh.staly) newhigh.stahy = ycur; else
1110 {
1111 newhigh.stahy = newhigh.staly; newhigh.staly = ycur;
1112 }
1113 us_addhighlight(&newhigh);
1114 return;
1115 }
1116
1117 if (namesamen(pt, x_("clear"), l) == 0 && l >= 2)
1118 {
1119 us_clearhighlightcount();
1120 return;
1121 }
1122
1123 if (namesamen(pt, x_("comp-interactive"), l) == 0 && l >= 3)
1124 {
1125 if (findpoint != 0 || findexclusively != 0 || extrainfo != 0)
1126 {
1127 us_abortcommand(M_("Illegal options given to 'find comp-interactive'"));
1128 return;
1129 }
1130 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
1131 {
1132 /* nonsensical in outline-edit mode */
1133 return;
1134 }
1135 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_interactiveanglekey);
1136 if (var == NOVARIABLE) findangle = 0; else
1137 findangle = var->addr;
1138 us_findiinit(findport, extrainfo, findangle, 1-findmore, findstill,
1139 findnobox, findspecial);
1140 trackcursor(FALSE, us_ignoreup, us_findcibegin, us_findidown, us_stoponchar,
1141 us_findiup, TRACKDRAGGING);
1142 return;
1143 }
1144
1145 if (namesamen(pt, x_("deselect-arcs"), l) == 0 && l >= 2)
1146 {
1147 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1148 if (var == NOVARIABLE) return;
1149 len = getlength(var);
1150 list = (CHAR **)emalloc(len * (sizeof (CHAR *)), el_tempcluster);
1151 if (list == 0) return;
1152 j = 0;
1153 for(i=0; i<len; i++)
1154 {
1155 if (us_makehighlight(((CHAR **)var->addr)[i], &newhigh)) break;
1156 if ((newhigh.status&HIGHTYPE) == HIGHFROM &&
1157 !newhigh.fromgeom->entryisnode) continue;
1158 (void)allocstring(&list[j], ((CHAR **)var->addr)[i], el_tempcluster);
1159 j++;
1160 }
1161 if (j == 0)
1162 {
1163 (void)delvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey);
1164 } else
1165 {
1166 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
1167 VSTRING|VISARRAY|(j<<VLENGTHSH)|VDONTSAVE);
1168 }
1169 for(i=0; i<j; i++)
1170 efree((CHAR *)list[i]);
1171 efree((CHAR *)list);
1172 return;
1173 }
1174
1175 if (namesamen(pt, x_("down-stack"), l) == 0 && l >= 2)
1176 {
1177 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1178 extrainfo != 0 || findwithin != 0 || findmore != 0 || findspecial != 0)
1179 {
1180 us_abortcommand(M_("Illegal options given to 'find down-stack'"));
1181 return;
1182 }
1183 us_pushhighlight();
1184 ttyputverbose(M_("Pushed"));
1185 return;
1186 }
1187
1188 if (namesamen(pt, x_("dragging-selects"), l) == 0 && l >= 2)
1189 {
1190 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1191 extrainfo != 0 || findwithin != 0 || findmore != 0 || findspecial != 0)
1192 {
1193 us_abortcommand(M_("Illegal options given to 'find dragging-selects'"));
1194 return;
1195 }
1196 if (count <= 1)
1197 {
1198 ttyputusage(x_("find dragging-selects WHAT"));
1199 return;
1200 }
1201 len = estrlen(pt = par[1]);
1202 if (namesamen(pt, x_("any-touching"), len) == 0)
1203 {
1204 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
1205 us_useroptions & ~MUSTENCLOSEALL, VINTEGER);
1206 ttyputverbose(M_("Dragging selects anything touching the area"));
1207 return;
1208 }
1209 if (namesamen(pt, x_("only-enclosed"), len) == 0)
1210 {
1211 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
1212 us_useroptions | MUSTENCLOSEALL, VINTEGER);
1213 ttyputverbose(M_("Dragging selects only objects inside the area"));
1214 return;
1215 }
1216 ttyputbadusage(x_("find dragging-selects"));
1217 return;
1218 }
1219
1220 if (namesamen(pt, x_("export"), l) == 0 && l >= 3)
1221 {
1222 if (count <= 1)
1223 {
1224 ttyputusage(x_("find export PORTNAME"));
1225 return;
1226 }
1227 if (findport != 0 || findpoint != 0 || findexclusively != 0 || findwithin != 0 ||
1228 findspecial != 0)
1229 {
1230 us_abortcommand(M_("'find export' cannot accept other control"));
1231 return;
1232 }
1233 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1234 if (namesame(par[1], pp->protoname) == 0) break;
1235 if (pp == NOPORTPROTO)
1236 {
1237 us_abortcommand(_("Sorry, no export named '%s' in this cell"), par[1]);
1238 return;
1239 }
1240 newhigh.status = HIGHFROM;
1241 newhigh.fromgeom = pp->subnodeinst->geom;
1242 newhigh.fromport = pp->subportproto;
1243 newhigh.cell = np;
1244 us_setfind(&newhigh, 0, extrainfo, findmore, findnobox);
1245 return;
1246 }
1247
1248 if (namesamen(pt, x_("interactive"), l) == 0)
1249 {
1250 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
1251 {
1252 /* do outline select and move if in that mode */
1253 findwithin = 1;
1254 findpoint = 1;
1255 }
1256 if (findexclusively != 0)
1257 {
1258 us_abortcommand(M_("Illegal options given to 'find interactively'"));
1259 return;
1260 }
1261
1262 /* special case: "find within vertex interactive" for polygon-editing */
1263 if (findpoint != 0 && findwithin != 0)
1264 {
1265 if (newhigh.fromgeom == NOGEOM)
1266 {
1267 us_abortcommand(M_("Cannot edit this object"));
1268 return;
1269 }
1270 ni = newhigh.fromgeom->entryaddr.ni;
1271 us_pointinit(ni, 0);
1272 trackcursor(FALSE, us_ignoreup, us_findpointbegin, us_movepdown,
1273 us_stoponchar, us_dragup, TRACKDRAGGING);
1274 if (el_pleasestop != 0) return;
1275
1276 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1277 if (highvar == NOVARIABLE) return;
1278 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &newhigh);
1279 if (us_demandxy(&xcur, &ycur)) return;
1280 gridalign(&xcur, &ycur, 1, np);
1281 var = gettrace(ni);
1282 if (var == NOVARIABLE) return;
1283 size = getlength(var) / 2;
1284 newlist = (INTBIG *)emalloc((size*2*SIZEOFINTBIG), el_tempcluster);
1285 if (newlist == 0) return;
1286 makerot(ni, trans);
1287 x = (ni->highx + ni->lowx) / 2;
1288 y = (ni->highy + ni->lowy) / 2;
1289 for(i=0; i<size; i++)
1290 {
1291 if (i+1 == newhigh.frompoint)
1292 {
1293 newlist[i*2] = xcur;
1294 newlist[i*2+1] = ycur;
1295 } else xform(((INTBIG *)var->addr)[i*2]+x, ((INTBIG *)var->addr)[i*2+1]+y,
1296 &newlist[i*2], &newlist[i*2+1], trans);
1297 }
1298
1299 /* now re-draw this trace */
1300 us_pushhighlight();
1301 us_clearhighlightcount();
1302 us_settrace(ni, newlist, size);
1303 us_pophighlight(FALSE);
1304 efree((CHAR *)newlist);
1305 return;
1306 }
1307
1308 /* traditional interactive selection */
1309 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_interactiveanglekey);
1310 if (var == NOVARIABLE) findangle = 0; else
1311 findangle = var->addr;
1312 us_findiinit(findport, extrainfo, findangle, 1-findmore, findstill,
1313 findnobox, findspecial);
1314 trackcursor(FALSE, us_ignoreup, us_findibegin, us_findidown, us_stoponchar,
1315 us_findiup, TRACKDRAGGING);
1316 return;
1317 }
1318
1319 if (namesamen(pt, x_("just-objects"), l) == 0)
1320 {
1321 /* must be a single "area select" */
1322 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1323 if (var == NOVARIABLE) return;
1324 len = getlength(var);
1325 if (len != 1) return;
1326 (void)us_makehighlight(((CHAR **)var->addr)[0], &newhigh);
1327 if ((newhigh.status&HIGHTYPE) != HIGHBBOX) return;
1328
1329 /* remove it and select everything in that area */
1330 np = newhigh.cell;
1331 us_clearhighlightcount();
1332 total = us_selectarea(np, newhigh.stalx, newhigh.stahx, newhigh.staly,
1333 newhigh.stahy, 0, 0, 0, &list);
1334 if (total > 0)
1335 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
1336 VSTRING|VISARRAY|(total<<VLENGTHSH)|VDONTSAVE);
1337 return;
1338 }
1339
1340 if (namesamen(pt, x_("name"), l) == 0 && l >= 2)
1341 {
1342 if (count <= 1)
1343 {
1344 ttyputusage(x_("find name HIGHLIGHTNAME"));
1345 return;
1346 }
1347 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1348 findwithin != 0 || findmore != 0 || findspecial != 0)
1349 {
1350 us_abortcommand(M_("Illegal options given to 'find name'"));
1351 return;
1352 }
1353 infstr = initinfstr();
1354 addstringtoinfstr(infstr, x_("USER_highlight_"));
1355 addstringtoinfstr(infstr, par[1]);
1356 var = getval((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, returninfstr(infstr));
1357 if (var == NOVARIABLE)
1358 {
1359 us_abortcommand(_("Cannot find saved highlight '%s'"), par[1]);
1360 return;
1361 }
1362
1363 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, var->addr, var->type|VDONTSAVE);
1364 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
1365 return;
1366 }
1367
1368 if (namesamen(pt, x_("node"), l) == 0 && l >= 3)
1369 {
1370 if (count <= 1)
1371 {
1372 ttyputusage(x_("find node NODENAME"));
1373 return;
1374 }
1375 if (findport != 0 || findwithin != 0 || findspecial != 0)
1376 {
1377 us_abortcommand(M_("Illegal options given to 'find node'"));
1378 return;
1379 }
1380 if (findexclusively != 0 && us_curnodeproto == NONODEPROTO)
1381 {
1382 us_abortcommand(M_("Must select a node for exclusive finding"));
1383 return;
1384 }
1385 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1386 {
1387 if (findexclusively != 0 && ni->proto != us_curnodeproto) continue;
1388 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
1389 if (var == NOVARIABLE) continue;
1390 if (namesame((CHAR *)var->addr, par[1]) == 0) break;
1391 }
1392 if (ni == NONODEINST)
1393 {
1394 us_abortcommand(_("Sorry, no %s node named '%s' in this cell"),
1395 (findexclusively==0 ? x_("") : describenodeproto(us_curnodeproto)), par[1]);
1396 return;
1397 }
1398 newhigh.status = HIGHFROM;
1399 newhigh.fromgeom = ni->geom;
1400 newhigh.fromport = NOPORTPROTO;
1401 newhigh.cell = np;
1402 us_setfind(&newhigh, findpoint, extrainfo, findmore, findnobox);
1403 return;
1404 }
1405
1406 if (namesamen(pt, x_("nonmanhattan"), l) == 0 && l >= 3)
1407 {
1408 i = 0;
1409 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1410 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1411 onp->temp1 = 0;
1412 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1413 {
1414 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1415 {
1416 for(ai = onp->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1417 {
1418 if (ai->proto->tech == gen_tech || ai->proto->tech == art_tech ||
1419 ai->proto->tech == sch_tech)
1420 continue;
1421 var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, el_arc_radius_key);
1422 if (var != NOVARIABLE || (ai->end[0].xpos != ai->end[1].xpos &&
1423 ai->end[0].ypos != ai->end[1].ypos)) onp->temp1++;
1424 }
1425 for(ni = onp->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1426 {
1427 if ((ni->rotation % 900) != 0) onp->temp1++;
1428 }
1429 }
1430 }
1431 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1432 {
1433 if (ai->proto->tech == gen_tech || ai->proto->tech == art_tech)
1434 continue;
1435 var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, el_arc_radius_key);
1436 if (var == NOVARIABLE && (ai->end[0].xpos == ai->end[1].xpos ||
1437 ai->end[0].ypos == ai->end[1].ypos)) continue;
1438 if (i == 0) us_clearhighlightcount();
1439 newhigh.status = HIGHFROM;
1440 newhigh.cell = np;
1441 newhigh.fromgeom = ai->geom;
1442 newhigh.fromport = NOPORTPROTO;
1443 newhigh.frompoint = 0;
1444 us_addhighlight(&newhigh);
1445 i++;
1446 }
1447 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1448 {
1449 if ((ni->rotation % 900) == 0) continue;
1450 if (i == 0) us_clearhighlightcount();
1451 newhigh.status = HIGHFROM;
1452 newhigh.cell = np;
1453 newhigh.fromgeom = ni->geom;
1454 newhigh.fromport = NOPORTPROTO;
1455 newhigh.frompoint = 0;
1456 us_addhighlight(&newhigh);
1457 i++;
1458 }
1459 if (i == 0) ttyputmsg(_("No nonmanhattan objects in this cell")); else
1460 ttyputmsg(_("%ld objects are not manhattan in this cell"), i);
1461 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1462 {
1463 if ((lib->userbits&HIDDENLIBRARY) != 0) continue;
1464 i = 0;
1465 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1466 if (onp != np) i += onp->temp1;
1467 if (i == 0) continue;
1468 if (lib == el_curlib)
1469 {
1470 l = 0;
1471 infstr = initinfstr();
1472 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1473 {
1474 if (onp == np || onp->temp1 == 0) continue;
1475 if (l != 0) addtoinfstr(infstr, ' ');
1476 addstringtoinfstr(infstr, describenodeproto(onp));
1477 l++;
1478 }
1479 if (l == 1)
1480 {
1481 ttyputmsg(_("Found nonmanhattan geometry in cell %s"), returninfstr(infstr));
1482 } else
1483 {
1484 ttyputmsg(_("Found nonmanhattan geometry in these cells: %s"),
1485 returninfstr(infstr));
1486 }
1487 } else
1488 {
1489 ttyputmsg(_("Found nonmanhattan geometry in library %s"), lib->libname);
1490 }
1491 }
1492 return;
1493 }
1494
1495 if (namesamen(pt, x_("object"), l) == 0)
1496 {
1497 if (count < 2)
1498 {
1499 ttyputusage(x_("find object (TYPE ADDRESS | TYPEADDRESS)"));
1500 return;
1501 }
1502 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1503 findwithin != 0 || findspecial != 0)
1504 {
1505 us_abortcommand(M_("Illegal options given to 'find object'"));
1506 return;
1507 }
1508
1509 /* determine type and address to highlight */
1510 if (count == 3)
1511 {
1512 type = us_variabletypevalue(par[1]);
1513 addr = myatoi(par[2]);
1514 } else
1515 {
1516 type = VUNKNOWN;
1517 if (namesamen(par[1], x_("node"), 4) == 0)
1518 {
1519 type = VNODEINST;
1520 addr = myatoi(&par[1][4]);
1521 }
1522 if (namesamen(par[1], x_("arc"), 3) == 0)
1523 {
1524 type = VARCINST;
1525 addr = myatoi(&par[1][3]);
1526 }
1527 if (namesamen(par[1], x_("port"), 4) == 0)
1528 {
1529 type = VPORTPROTO;
1530 addr = myatoi(&par[1][4]);
1531 }
1532 if (namesamen(par[1], x_("network"), 7) == 0)
1533 {
1534 type = VNETWORK;
1535 addr = myatoi(&par[1][7]);
1536 }
1537 }
1538 if (type == VUNKNOWN)
1539 {
1540 us_abortcommand(_("Unknown object type in 'find object' command"));
1541 return;
1542 }
1543 switch (type)
1544 {
1545 case VNODEINST:
1546 ni = (NODEINST *)addr;
1547 if (ni == 0 || ni == NONODEINST) return;
1548 if (ni->parent != np)
1549 {
1550 us_abortcommand(_("Cannot find node %ld in this cell"), addr);
1551 return;
1552 }
1553 newhigh.status = HIGHFROM;
1554 newhigh.fromgeom = ni->geom;
1555 newhigh.fromport = NOPORTPROTO;
1556 newhigh.cell = np;
1557 us_setfind(&newhigh, findpoint, extrainfo, findmore, findnobox);
1558 break;
1559 case VARCINST:
1560 ai = (ARCINST *)addr;
1561 if (ai == 0 || ai == NOARCINST) return;
1562 if (ai->parent != np)
1563 {
1564 us_abortcommand(_("Cannot find arc %ld in this cell"), addr);
1565 return;
1566 }
1567 newhigh.status = HIGHFROM;
1568 newhigh.fromgeom = ai->geom;
1569 newhigh.fromport = NOPORTPROTO;
1570 newhigh.cell = np;
1571 us_setfind(&newhigh, findpoint, extrainfo, findmore, findnobox);
1572 break;
1573 case VNETWORK:
1574 net = (NETWORK *)addr;
1575 if (net == 0 || net == NONETWORK) return;
1576 if (net->parent != np)
1577 {
1578 us_abortcommand(_("Cannot find network %ld in this cell"), addr);
1579 return;
1580 }
1581 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1582 {
1583 if (ai->network != net) continue;
1584 newhigh.status = HIGHFROM;
1585 newhigh.fromgeom = ai->geom;
1586 newhigh.fromport = NOPORTPROTO;
1587 newhigh.cell = np;
1588 us_setfind(&newhigh, findpoint, extrainfo, findmore, findnobox);
1589 }
1590 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1591 {
1592 if (pp->network != net) continue;
1593 newhigh.status = HIGHFROM;
1594 newhigh.fromgeom = pp->subnodeinst->geom;
1595 newhigh.fromport = pp->subportproto;
1596 newhigh.cell = np;
1597 us_setfind(&newhigh, 0, extrainfo, findmore, findnobox);
1598 }
1599 break;
1600 case VPORTPROTO:
1601 pp = (PORTPROTO *)addr;
1602 if (pp == 0 || pp == NOPORTPROTO) return;
1603 if (pp->parent != np)
1604 {
1605 us_abortcommand(_("Cannot find port %ld in this cell"), addr);
1606 return;
1607 }
1608 newhigh.status = HIGHFROM;
1609 newhigh.fromgeom = pp->subnodeinst->geom;
1610 newhigh.fromport = pp->subportproto;
1611 newhigh.cell = np;
1612 us_setfind(&newhigh, 0, extrainfo, findmore, findnobox);
1613 break;
1614 default:
1615 us_abortcommand(_("Cannot highlight objects of type %s"),
1616 us_variabletypename(type));
1617 return;
1618 }
1619 return;
1620 }
1621
1622 if (namesamen(pt, x_("save"), l) == 0 && l >= 2)
1623 {
1624 if (count <= 1)
1625 {
1626 ttyputusage(x_("find save HIGHLIGHTNAME"));
1627 return;
1628 }
1629 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1630 extrainfo != 0 || findwithin != 0 || findmore != 0 || findspecial != 0)
1631 {
1632 us_abortcommand(M_("Illegal options given to 'find save'"));
1633 return;
1634 }
1635 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1636 if (var == NOVARIABLE)
1637 {
1638 us_abortcommand(_("Highlight something before saving highlight"));
1639 return;
1640 }
1641 infstr = initinfstr();
1642 addstringtoinfstr(infstr, x_("USER_highlight_"));
1643 addstringtoinfstr(infstr, par[1]);
1644 (void)setval((INTBIG)us_tool, VTOOL, returninfstr(infstr), var->addr, var->type|VDONTSAVE);
1645 ttyputverbose(M_("%s saved"), par[1]);
1646 return;
1647 }
1648
1649 if (namesamen(pt, x_("set-easy-selection"), l) == 0 && l >= 5)
1650 {
1651 glist = us_gethighlighted(WANTARCINST|WANTNODEINST, 0, 0);
1652 if (glist[0] == NOGEOM)
1653 {
1654 us_abortcommand(_("Select something before making it easy-to-select"));
1655 return;
1656 }
1657 for(i=0; glist[i] != NOGEOM; i++)
1658 {
1659 geom = glist[i];
1660 if (!geom->entryisnode)
1661 {
1662 ai = geom->entryaddr.ai;
1663 ai->userbits &= ~HARDSELECTA;
1664 } else
1665 {
1666 ni = geom->entryaddr.ni;
1667 ni->userbits &= ~HARDSELECTN;
1668 }
1669 }
1670 return;
1671 }
1672
1673 if (namesamen(pt, x_("set-hard-selection"), l) == 0 && l >= 5)
1674 {
1675 glist = us_gethighlighted(WANTARCINST|WANTNODEINST, 0, 0);
1676 if (glist[0] == NOGEOM)
1677 {
1678 us_abortcommand(_("Select something before making it easy-to-select"));
1679 return;
1680 }
1681 for(i=0; glist[i] != NOGEOM; i++)
1682 {
1683 geom = glist[i];
1684 if (!geom->entryisnode)
1685 {
1686 ai = geom->entryaddr.ai;
1687 ai->userbits |= HARDSELECTA;
1688 } else
1689 {
1690 ni = geom->entryaddr.ni;
1691 ni->userbits |= HARDSELECTN;
1692 }
1693 }
1694 return;
1695 }
1696
1697 if (namesamen(pt, x_("similar"), l) == 0 && l >= 2)
1698 {
1699 if (findpoint != 0 || findwithin != 0 || findmore != 0 ||
1700 findexclusively != 0 || findstill != 0 || findspecial != 0)
1701 {
1702 us_abortcommand(M_("Illegal options given to 'find similar'"));
1703 return;
1704 }
1705
1706 glist = us_gethighlighted(WANTNODEINST|WANTARCINST, 0, 0);
1707 if (glist[0] == NOGEOM)
1708 {
1709 us_abortcommand(_("Must select objects before selecting all like them"));
1710 return;
1711 }
1712 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1713 ni->temp1 = 0;
1714 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1715 ai->temp1 = 0;
1716 for(i=0; glist[i] != NOGEOM; i++)
1717 {
1718 if (glist[i]->entryisnode)
1719 {
1720 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1721 if (ni->proto == glist[i]->entryaddr.ni->proto) ni->temp1 = 1;
1722 } else
1723 {
1724 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1725 if (ai->proto == glist[i]->entryaddr.ai->proto) ai->temp1 = 1;
1726 }
1727 }
1728 infstr = initinfstr();
1729 first = 0;
1730 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1731 {
1732 if (ni->temp1 == 0) continue;
1733 if (first != 0) addtoinfstr(infstr, '\n');
1734 first++;
1735 formatinfstr(infstr, x_("CELL=%s FROM=0%lo;-1;0"),
1736 describenodeproto(np), (INTBIG)ni->geom);
1737 }
1738 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1739 {
1740 if (ai->temp1 == 0) continue;
1741 if (first != 0) addtoinfstr(infstr, '\n');
1742 first++;
1743 formatinfstr(infstr, x_("CELL=%s FROM=0%lo;-1;0"),
1744 describenodeproto(np), (INTBIG)ai->geom);
1745 }
1746 us_setmultiplehighlight(returninfstr(infstr), FALSE);
1747 return;
1748 }
1749
1750 if (namesamen(pt, x_("snap-mode"), l) == 0 && l >= 2)
1751 {
1752 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1753 extrainfo != 0 || findwithin != 0 || findmore != 0 || findspecial != 0)
1754 {
1755 us_abortcommand(M_("Illegal options given to 'find snap-mode'"));
1756 return;
1757 }
1758
1759 if (count < 2)
1760 {
1761 switch (us_state&SNAPMODE)
1762 {
1763 case SNAPMODENONE: ttyputmsg(M_("Snapping mode: none")); break;
1764 case SNAPMODECENTER: ttyputmsg(M_("Snapping mode: center")); break;
1765 case SNAPMODEMIDPOINT: ttyputmsg(M_("Snapping mode: midpoint")); break;
1766 case SNAPMODEENDPOINT: ttyputmsg(M_("Snapping mode: end point")); break;
1767 case SNAPMODETANGENT: ttyputmsg(M_("Snapping mode: tangent")); break;
1768 case SNAPMODEPERP: ttyputmsg(M_("Snapping mode: perpendicular")); break;
1769 case SNAPMODEQUAD: ttyputmsg(M_("Snapping mode: quadrant")); break;
1770 case SNAPMODEINTER: ttyputmsg(M_("Snapping mode: any intersection")); break;
1771 }
1772 return;
1773 }
1774 l = estrlen(pt = par[1]);
1775 if (namesamen(pt, x_("none"), l) == 0)
1776 {
1777 us_state = (us_state & ~SNAPMODE) | SNAPMODENONE;
1778 ttyputverbose(M_("Snapping mode: none"));
1779 return;
1780 }
1781 if (namesamen(pt, x_("center"), l) == 0)
1782 {
1783 us_state = (us_state & ~SNAPMODE) | SNAPMODECENTER;
1784 ttyputverbose(M_("Snapping mode: center"));
1785 return;
1786 }
1787 if (namesamen(pt, x_("midpoint"), l) == 0)
1788 {
1789 us_state = (us_state & ~SNAPMODE) | SNAPMODEMIDPOINT;
1790 ttyputverbose(M_("Snapping mode: midpoint"));
1791 return;
1792 }
1793 if (namesamen(pt, x_("endpoint"), l) == 0)
1794 {
1795 us_state = (us_state & ~SNAPMODE) | SNAPMODEENDPOINT;
1796 ttyputverbose(M_("Snapping mode: endpoint"));
1797 return;
1798 }
1799 if (namesamen(pt, x_("tangent"), l) == 0)
1800 {
1801 us_state = (us_state & ~SNAPMODE) | SNAPMODETANGENT;
1802 ttyputverbose(M_("Snapping mode: tangent"));
1803 return;
1804 }
1805 if (namesamen(pt, x_("perpendicular"), l) == 0)
1806 {
1807 us_state = (us_state & ~SNAPMODE) | SNAPMODEPERP;
1808 ttyputverbose(M_("Snapping mode: perpendicular"));
1809 return;
1810 }
1811 if (namesamen(pt, x_("quadrant"), l) == 0)
1812 {
1813 us_state = (us_state & ~SNAPMODE) | SNAPMODEQUAD;
1814 ttyputverbose(M_("Snapping mode: quadrant"));
1815 return;
1816 }
1817 if (namesamen(pt, x_("intersection"), l) == 0)
1818 {
1819 us_state = (us_state & ~SNAPMODE) | SNAPMODEINTER;
1820 ttyputverbose(M_("Snapping mode: any intersection"));
1821 return;
1822 }
1823 us_abortcommand(M_("Unknown snapping mode: %s"), pt);
1824 return;
1825 }
1826
1827 if (namesamen(pt, x_("up-stack"), l) == 0 && l >= 1)
1828 {
1829 if (findport != 0 || findpoint != 0 || findexclusively != 0 ||
1830 extrainfo != 0 || findwithin != 0 || findmore != 0 || findspecial != 0)
1831 {
1832 us_abortcommand(M_("Illegal options given to 'find up-stack'"));
1833 return;
1834 }
1835 us_pophighlight(FALSE);
1836 return;
1837 }
1838
1839 if (namesamen(pt, x_("variable"), l) == 0 && l >= 2)
1840 {
1841 if (count <= 1)
1842 {
1843 ttyputusage(x_("find variable VARNAME"));
1844 return;
1845 }
1846 if (findport != 0 || findpoint != 0 || findexclusively != 0 || findwithin != 0 ||
1847 findspecial != 0)
1848 {
1849 us_abortcommand(M_("'find variable' cannot accept other control"));
1850 return;
1851 }
1852 ni = (NODEINST *)us_getobject(VNODEINST, TRUE);
1853 if (ni == NONODEINST) return;
1854 for(i=0; i<ni->numvar; i++)
1855 {
1856 var = &ni->firstvar[i];
1857 if ((var->type&VDISPLAY) == 0) continue;
1858 if (namesame(par[1], makename(var->key)) == 0) break;
1859 }
1860 if (i >= ni->numvar)
1861 {
1862 us_abortcommand(_("Sorry, no variable named '%s' on the current node"),
1863 par[1]);
1864 return;
1865 }
1866 newhigh.status = HIGHTEXT;
1867 newhigh.fromgeom = ni->geom;
1868 newhigh.fromport = NOPORTPROTO;
1869 newhigh.fromvar = var;
1870 newhigh.cell = np;
1871 us_setfind(&newhigh, 0, extrainfo, findmore, findnobox);
1872 return;
1873 }
1874 ttyputbadusage(x_("find"));
1875 return;
1876 }
1877
1878 /* get the cursor co-ordinates */
1879 if (us_demandxy(&xcur, &ycur)) return;
1880
1881 /* find the closest object to the cursor */
1882 if (findwithin == 0)
1883 us_findobject(xcur, ycur, el_curwindowpart, &newhigh, findexclusively, 0, findport, 0, findspecial);
1884 if (newhigh.status == 0) return;
1885 if (findport == 0) newhigh.fromport = NOPORTPROTO;
1886 newhigh.cell = np;
1887 us_setfind(&newhigh, findpoint, extrainfo, findmore, findnobox);
1888 }
1889
us_getproto(INTBIG count,CHAR * par[])1890 void us_getproto(INTBIG count, CHAR *par[])
1891 {
1892 REGISTER NODEPROTO *np, *onp;
1893 REGISTER ARCPROTO *ap, *lat;
1894 REGISTER INTBIG cellgroupcount, cellcount, doarc, i, l, firstinpass;
1895 BOOLEAN butstate;
1896 REGISTER CHAR *pp;
1897 HIGHLIGHT high;
1898 extern COMCOMP us_getproto1p;
1899 REGISTER VARIABLE *highvar;
1900 GEOM *fromgeom, *togeom;
1901 PORTPROTO *fromport, *toport;
1902 REGISTER USERCOM *uc, *ucsub;
1903 POPUPMENU *pm, *cpm, *pmsub;
1904 REGISTER POPUPMENUITEM *mi, *miret, *misub;
1905 extern COMCOMP us_userp;
1906 REGISTER void *infstr;
1907
1908 if (count == 0)
1909 {
1910 count = ttygetparam(M_("Getproto option: "), &us_getproto1p, MAXPARS, par);
1911 if (count == 0)
1912 {
1913 us_abortedmsg();
1914 return;
1915 }
1916 }
1917 l = estrlen(pp = par[0]);
1918
1919 if (namesamen(pp, x_("instance"), l) == 0)
1920 {
1921 /* show a popup menu with instances */
1922
1923 /* number each cellgroup */
1924 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1925 np->temp1 = 0;
1926 cellgroupcount = 0;
1927 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1928 {
1929 if (np->temp1 != 0) continue;
1930 cellgroupcount++;
1931 FOR_CELLGROUP(onp, np)
1932 onp->temp1 = cellgroupcount;
1933 }
1934 pm = (POPUPMENU *)emalloc(sizeof(POPUPMENU), us_tool->cluster);
1935 if (pm == 0) return;
1936 mi = (POPUPMENUITEM *)emalloc(cellgroupcount * sizeof(POPUPMENUITEM), us_tool->cluster);
1937 if (mi == 0) return;
1938 pm->name = x_("x");
1939 infstr = initinfstr();
1940 if (cellgroupcount != 0) formatinfstr(infstr, _("Cells in %s"), el_curlib->libname); else
1941 formatinfstr(infstr, _("No cells in %s"), el_curlib->libname);
1942 (void)allocstring(&pm->header, returninfstr(infstr), us_tool->cluster);
1943 pm->list = mi;
1944 pm->total = cellgroupcount;
1945
1946 /* fill the menu */
1947 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1948 np->temp1 = 0;
1949 cellgroupcount = 0;
1950 for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1951 {
1952 if (np->temp1 != 0) continue;
1953 cellcount = 0;
1954 FOR_CELLGROUP(onp, np)
1955 {
1956 onp->temp1 = 1;
1957 cellcount++;
1958 }
1959
1960 uc = us_allocusercom();
1961 mi[cellgroupcount].response = uc;
1962 mi[cellgroupcount].response->active = -1;
1963 mi[cellgroupcount].value = 0;
1964
1965 if (cellcount == 1)
1966 {
1967 /* only one cell of this cell: create it directly */
1968 uc->active = parse(x_("getproto"), &us_userp, TRUE);
1969 (void)allocstring(&uc->comname, x_("getproto"), us_tool->cluster);
1970 uc->count = 2;
1971 (void)allocstring(&uc->word[0], x_("node"), us_tool->cluster);
1972 (void)allocstring(&uc->word[1], describenodeproto(np), us_tool->cluster);
1973 mi[cellgroupcount].attribute = uc->word[1];
1974 } else
1975 {
1976 /* multiple cells of this cell: make a submenu */
1977 mi[cellgroupcount].attribute = np->protoname;
1978 mi[cellgroupcount].value = x_(">>");
1979 mi[cellgroupcount].maxlen = -1;
1980 pmsub = (POPUPMENU *)emalloc(sizeof(POPUPMENU), us_tool->cluster);
1981 if (pmsub == 0) return;
1982 misub = (POPUPMENUITEM *)emalloc(cellcount * sizeof(POPUPMENUITEM), us_tool->cluster);
1983 if (misub == 0) return;
1984 pmsub->name = x_("x");
1985 pmsub->header = 0;
1986 pmsub->list = misub;
1987 pmsub->total = cellcount;
1988 cellcount = 0;
1989 for(i=0; i<2; i++)
1990 {
1991 firstinpass = cellcount;
1992 FOR_CELLGROUP(onp, np)
1993 {
1994 /* see if this cell should be included on this pass */
1995 if (i == 0)
1996 {
1997 /* first pass: only include cells that match the current view */
1998 if (!us_cellfromtech(onp, el_curtech)) continue;
1999 } else
2000 {
2001 /* first pass: only include cells that don't match the current view */
2002 if (us_cellfromtech(onp, el_curtech)) continue;
2003 }
2004
2005 ucsub = us_allocusercom();
2006 misub[cellcount].response = ucsub;
2007 misub[cellcount].response->active = -1;
2008 (void)allocstring(&misub[cellcount].attribute, describenodeproto(onp),
2009 us_tool->cluster);
2010 misub[cellcount].value = 0;
2011
2012 /* only one cell of this cell: create it directly */
2013 ucsub->active = parse(x_("getproto"), &us_userp, TRUE);
2014 (void)allocstring(&ucsub->comname, x_("getproto"), us_tool->cluster);
2015 ucsub->count = 2;
2016 (void)allocstring(&ucsub->word[0], x_("node"), us_tool->cluster);
2017 (void)allocstring(&ucsub->word[1], describenodeproto(onp),
2018 us_tool->cluster);
2019 cellcount++;
2020 }
2021 esort(&misub[firstinpass], cellcount-firstinpass,
2022 sizeof (POPUPMENUITEM), us_sortpopupmenuascending);
2023 }
2024 uc->menu = pmsub;
2025 }
2026 cellgroupcount++;
2027 }
2028
2029 /* invoke the popup menu */
2030 esort(mi, cellgroupcount, sizeof (POPUPMENUITEM), us_sortpopupmenuascending);
2031 butstate = TRUE;
2032 cpm = pm;
2033 miret = us_popupmenu(&cpm, &butstate, TRUE, -1, -1, 4);
2034 if (miret == 0)
2035 {
2036 us_abortcommand(_("Sorry, popup menus are not available"));
2037 } else
2038 {
2039 if (miret != NOPOPUPMENUITEM)
2040 us_execute(miret->response, FALSE, FALSE, FALSE);
2041 }
2042 for(i=0; i<cellgroupcount; i++)
2043 {
2044 uc = mi[i].response;
2045 if (uc->menu != NOPOPUPMENU)
2046 {
2047 for(l=0; l<uc->menu->total; l++)
2048 {
2049 efree((CHAR *)uc->menu->list[l].attribute);
2050 us_freeusercom(uc->menu->list[l].response);
2051 }
2052 efree((CHAR *)uc->menu->list);
2053 efree((CHAR *)uc->menu);
2054 }
2055 us_freeusercom(uc);
2056 }
2057 efree((CHAR *)mi);
2058 efree((CHAR *)pm->header);
2059 efree((CHAR *)pm);
2060 return;
2061 }
2062
2063 if (namesamen(pp, x_("node"), l) == 0 && l >= 2 && count > 1)
2064 {
2065 np = getnodeproto(par[1]);
2066 if (np == NONODEPROTO)
2067 {
2068 us_abortcommand(_("Cannot find node '%s'"), par[1]);
2069 return;
2070 }
2071 us_setnodeproto(np);
2072 return;
2073 }
2074 if (namesamen(pp, x_("arc"), l) == 0 && l >= 1 && count > 1)
2075 {
2076 ap = getarcproto(par[1]);
2077 if (ap == NOARCPROTO) us_abortcommand(_("Cannot find arc '%s'"), par[1]); else
2078 us_setarcproto(ap, TRUE);
2079 return;
2080 }
2081
2082 if (namesamen(pp, x_("this-proto"), l) == 0 && l >= 1)
2083 {
2084 np = us_needcell();
2085 if (np == NONODEPROTO) return;
2086 us_setnodeproto(np);
2087 return;
2088 }
2089
2090 /* decide whether arcs are the default */
2091 doarc = 0;
2092 if (!us_gettwoobjects(&fromgeom, &fromport, &togeom, &toport)) doarc = 1; else
2093 {
2094 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
2095 if (highvar != NOVARIABLE && getlength(highvar) == 1)
2096 {
2097 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &high);
2098 if ((high.status&HIGHFROM) != 0 && !high.fromgeom->entryisnode) doarc++;
2099 }
2100 }
2101
2102 if (namesamen(pp, x_("next-proto"), l) == 0 && l >= 2)
2103 {
2104 if (doarc)
2105 {
2106 /* advance to the next arcproto */
2107 ap = us_curarcproto->nextarcproto;
2108 if (ap == NOARCPROTO) ap = el_curtech->firstarcproto;
2109 us_setarcproto(ap, TRUE);
2110 } else
2111 {
2112 /* advance to the next nodeproto */
2113 np = us_curnodeproto;
2114 if (np->primindex == 0) np = el_curtech->firstnodeproto; else
2115 {
2116 /* advance to next after "np" */
2117 np = np->nextnodeproto;
2118 if (np == NONODEPROTO) np = el_curtech->firstnodeproto;
2119 }
2120 us_setnodeproto(np);
2121 }
2122 return;
2123 }
2124
2125 if (namesamen(pp, x_("prev-proto"), l) == 0 && l >= 1)
2126 {
2127 if (doarc)
2128 {
2129 /* backup to the previous arcproto */
2130 for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2131 if (ap->nextarcproto == us_curarcproto) break;
2132 if (ap == NOARCPROTO)
2133 for(lat = el_curtech->firstarcproto; lat != NOARCPROTO; lat = lat->nextarcproto)
2134 ap = lat;
2135 us_setarcproto(ap, TRUE);
2136 } else
2137 {
2138 /* backup to the previous nodeproto */
2139 np = us_curnodeproto;
2140 if (np->primindex == 0) np = el_curtech->firstnodeproto; else
2141 {
2142 /* back up to previous of "np" */
2143 np = np->prevnodeproto;
2144 if (np == NONODEPROTO)
2145 for(np = el_curtech->firstnodeproto; np->nextnodeproto != NONODEPROTO;
2146 np = np->nextnodeproto) ;
2147 }
2148 us_setnodeproto(np);
2149 }
2150 return;
2151 }
2152
2153 /* must be a prototype name */
2154 if (doarc != 0)
2155 {
2156 ap = getarcproto(pp);
2157 if (ap != NOARCPROTO)
2158 {
2159 us_setarcproto(ap, TRUE);
2160 return;
2161 }
2162 }
2163
2164 np = getnodeproto(pp);
2165 if (np == NONODEPROTO)
2166 {
2167 if (doarc != 0) us_abortcommand(_("Cannot find node or arc '%s'"), pp); else
2168 us_abortcommand(_("Cannot find node '%s'"), pp);
2169 return;
2170 }
2171 us_setnodeproto(np);
2172 }
2173
us_grid(INTBIG count,CHAR * par[])2174 void us_grid(INTBIG count, CHAR *par[])
2175 {
2176 REGISTER INTBIG i, j;
2177 REGISTER INTBIG l;
2178 REGISTER CHAR *pp;
2179
2180 /* no arguments: toggle the grid state */
2181 if (count == 0)
2182 {
2183 if (us_needwindow()) return;
2184 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW &&
2185 (el_curwindowpart->state&WINDOWTYPE) != WAVEFORMWINDOW)
2186 {
2187 us_abortcommand(_("Cannot show grid in this type of window"));
2188 return;
2189 }
2190
2191 /* save highlight */
2192 us_pushhighlight();
2193 us_clearhighlightcount();
2194
2195 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
2196 us_gridset(el_curwindowpart, ~el_curwindowpart->state);
2197 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
2198
2199 /* restore highlighting */
2200 us_pophighlight(FALSE);
2201 return;
2202 }
2203
2204 l = estrlen(pp = par[0]);
2205 if (namesamen(pp, x_("alignment"), l) == 0 && l >= 1)
2206 {
2207 if (count >= 2)
2208 {
2209 i = atofr(par[1]);
2210 if (i < 0)
2211 {
2212 us_abortcommand(_("Alignment must be positive"));
2213 return;
2214 }
2215 (void)setvalkey((INTBIG)us_tool, VTOOL, us_alignment_ratio_key, i, VINTEGER);
2216 }
2217 ttyputverbose(M_("Cursor alignment is %s lambda"), frtoa(us_alignment_ratio));
2218 return;
2219 }
2220
2221 if (namesamen(pp, x_("edges"), l) == 0 && l >= 1)
2222 {
2223 if (count >= 2)
2224 {
2225 i = atofr(par[1]);
2226 if (i < 0)
2227 {
2228 us_abortcommand(_("Alignment must be positive"));
2229 return;
2230 }
2231 (void)setvalkey((INTBIG)us_tool, VTOOL, us_alignment_edge_ratio_key, i, VINTEGER);
2232 }
2233 if (us_edgealignment_ratio == 0) ttyputverbose(M_("No edge alignment done")); else
2234 ttyputverbose(M_("Edge alignment is %s lambda"), frtoa(us_edgealignment_ratio));
2235 return;
2236 }
2237
2238 if (namesamen(pp, x_("size"), l) == 0 && l >= 1)
2239 {
2240 if (count < 2)
2241 {
2242 ttyputusage(x_("grid size X [Y]"));
2243 return;
2244 }
2245 i = atola(par[1], 0);
2246 if (i&1) i++;
2247 if (count >= 3)
2248 {
2249 j = atola(par[2], 0);
2250 if (j&1) j++;
2251 } else j = i;
2252 if (i <= 0 || j <= 0)
2253 {
2254 us_abortcommand(_("Invalid grid spacing"));
2255 return;
2256 }
2257
2258 if (us_needwindow()) return;
2259
2260 /* save highlight */
2261 us_pushhighlight();
2262 us_clearhighlightcount();
2263 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
2264
2265 /* turn grid off if on */
2266 if ((el_curwindowpart->state&GRIDON) != 0)
2267 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
2268 el_curwindowpart->state & ~GRIDON, VINTEGER);
2269
2270 /* adjust grid */
2271 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("gridx"), i, VINTEGER);
2272 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("gridy"), j, VINTEGER);
2273
2274 /* show new grid */
2275 us_gridset(el_curwindowpart, GRIDON);
2276
2277 /* restore highlighting */
2278 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
2279 us_pophighlight(FALSE);
2280 return;
2281 }
2282 ttyputbadusage(x_("grid"));
2283 }
2284
2285 #define NEWSFILE x_("newsfile") /* file with news */
2286
2287 #define NEWSDATE x_(".electricnews") /* file with date of last news */
2288
us_help(INTBIG count,CHAR * par[])2289 void us_help(INTBIG count, CHAR *par[])
2290 {
2291 REGISTER CHAR *pp;
2292 REGISTER INTBIG len, lastquiet, nday, nmonth, nyear, on, filestatus;
2293 INTBIG day, month, year, hour, minute, second;
2294 FILE *in;
2295 CHAR line[256], *filename, *hd, *dummy;
2296 time_t clock;
2297 REGISTER void *infstr;
2298
2299 if (count > 0) len = estrlen(pp = par[0]);
2300
2301 /* show the user manual */
2302 if (count >= 1 && namesamen(pp, x_("manual"), len) == 0)
2303 {
2304 #ifdef DOCDIR
2305 estrcpy(line, DOCDIR);
2306 estrcat(line, x_("index.html"));
2307 filestatus = fileexistence(line);
2308 if (filestatus == 1 || filestatus == 3)
2309 {
2310 if (browsefile(line))
2311 {
2312 us_abortcommand(_("Cannot bring up the user's manual on this system"));
2313 }
2314 return;
2315 }
2316 #endif
2317 estrcpy(line, el_libdir);
2318 len = estrlen(line);
2319 if (line[len-1] == DIRSEP) line[len-1] = 0;
2320 len = estrlen(line);
2321 if (namesame(&line[len-3], x_("lib")) == 0) line[len-3] = 0;
2322 estrcat(line, x_("html"));
2323 estrcat(line, DIRSEPSTR);
2324 estrcat(line, x_("manual"));
2325 estrcat(line, DIRSEPSTR);
2326 estrcat(line, x_("index.html"));
2327 filestatus = fileexistence(line);
2328 if (filestatus != 1 && filestatus != 3)
2329 {
2330 us_abortcommand(_("Sorry, cannot locate the user's manual"));
2331 return;
2332 }
2333
2334 if (browsefile(line))
2335 {
2336 us_abortcommand(_("Cannot bring up the user's manual on this system"));
2337 }
2338 return;
2339 }
2340
2341 /* print news */
2342 if (count >= 1 && namesamen(pp, x_("news"), len) == 0)
2343 {
2344 /* determine last date of news reading */
2345 infstr = initinfstr();
2346 hd = hashomedir();
2347 if (hd == 0) addstringtoinfstr(infstr, el_libdir); else
2348 addstringtoinfstr(infstr, hd);
2349 addstringtoinfstr(infstr, NEWSDATE);
2350 pp = truepath(returninfstr(infstr));
2351 in = xopen(pp, el_filetypetext, 0, &dummy);
2352 if (in == 0) year = month = day = 0; else
2353 {
2354 fclose(in);
2355 clock = filedate(pp);
2356 parsetime(clock, &year, &month, &day, &hour, &minute, &second);
2357 month++;
2358 }
2359
2360 /* get the news file */
2361 infstr = initinfstr();
2362 addstringtoinfstr(infstr, el_libdir);
2363 addstringtoinfstr(infstr, NEWSFILE);
2364 pp = truepath(returninfstr(infstr));
2365 in = xopen(pp, us_filetypenews, x_(""), &filename);
2366 if (in == NULL)
2367 {
2368 ttyputerr(_("Sorry, cannot find the news file: %s"), pp);
2369 return;
2370 }
2371
2372 /* read the file */
2373 on = 0;
2374
2375 /* enable messages (if they were off) */
2376 lastquiet = ttyquiet(0);
2377 for(;;)
2378 {
2379 if (xfgets(line, MAXLINE, in)) break;
2380 if (on != 0)
2381 {
2382 ttyputmsg(x_("%s"), line);
2383 continue;
2384 }
2385 if (line[0] == ' ' || line[0] == 0) continue;
2386
2387 /* line with date, see if it is current */
2388 pp = line;
2389 nmonth = eatoi(pp);
2390 while (*pp != '/' && *pp != 0) pp++;
2391 if (*pp == '/') pp++;
2392 nday = eatoi(pp);
2393 while (*pp != '/' && *pp != 0) pp++;
2394 if (*pp == '/') pp++;
2395 nyear = eatoi(pp);
2396 if (nyear < year) continue; else if (nyear > year) on = 1;
2397 if (nmonth < month) continue; else if (nmonth > month) on = 1;
2398 if (nday >= day) on = 1;
2399 if (on != 0) ttyputmsg(x_("%s"), line);
2400 }
2401 xclose(in);
2402
2403 /* restore message output state */
2404 (void)ttyquiet(lastquiet);
2405
2406 if (on == 0) ttyputmsg(_("No news"));
2407
2408 /* now mark the current date */
2409 infstr = initinfstr();
2410 hd = hashomedir();
2411 if (hd == 0) addstringtoinfstr(infstr, el_libdir); else
2412 addstringtoinfstr(infstr, hd);
2413 addstringtoinfstr(infstr, NEWSDATE);
2414 xclose(xcreate(truepath(returninfstr(infstr)), us_filetypenews, 0, 0));
2415 return;
2416 }
2417
2418 /* illustrate commands */
2419 if (count >= 1 && namesamen(pp, x_("illustrate"), len) == 0)
2420 {
2421 us_illustratecommandset();
2422 return;
2423 }
2424
2425 /* dump pulldown menus */
2426 if (count >= 1 && namesamen(pp, x_("pulldowns"), len) == 0)
2427 {
2428 us_dumppulldownmenus();
2429 return;
2430 }
2431
2432 /* general dialog-based help on command-line */
2433 (void)us_helpdlog(x_("CL"));
2434 }
2435
us_if(INTBIG count,CHAR * par[])2436 void us_if(INTBIG count, CHAR *par[])
2437 {
2438 REGISTER INTBIG term1, term1type, term2, term2type;
2439 REGISTER INTBIG relation;
2440 REGISTER USERCOM *com;
2441
2442 /* make sure the proper number of parameters is given */
2443 if (count < 4)
2444 {
2445 ttyputusage(x_("if TERM1 RELATION TERM2 COMMAND"));
2446 return;
2447 }
2448
2449 /* get term 1 */
2450 if (isanumber(par[0]))
2451 {
2452 term1 = myatoi(par[0]);
2453 term1type = VINTEGER;
2454 } else
2455 {
2456 term1 = (INTBIG)par[0];
2457 term1type = VSTRING;
2458 }
2459
2460 /* get term 2 */
2461 if (isanumber(par[2]))
2462 {
2463 term2 = myatoi(par[2]);
2464 term2type = VINTEGER;
2465 } else
2466 {
2467 term2 = (INTBIG)par[2];
2468 term2type = VSTRING;
2469 }
2470
2471 /* make sure the two terms are comparable */
2472 if (term1type != term2type)
2473 {
2474 if (term1 == VINTEGER)
2475 {
2476 term1 = (INTBIG)par[0];
2477 term1type = VSTRING;
2478 } else
2479 {
2480 term2 = (INTBIG)par[1];
2481 term2type = VSTRING;
2482 }
2483 }
2484
2485 /* determine the relation being tested */
2486 relation = -1;
2487 if (estrcmp(par[1], x_("==")) == 0) relation = 0;
2488 if (estrcmp(par[1], x_("!=")) == 0) relation = 1;
2489 if (estrcmp(par[1], x_("<")) == 0) relation = 2;
2490 if (estrcmp(par[1], x_("<=")) == 0) relation = 3;
2491 if (estrcmp(par[1], x_(">")) == 0) relation = 4;
2492 if (estrcmp(par[1], x_(">=")) == 0) relation = 5;
2493 if (relation < 0)
2494 {
2495 us_abortcommand(_("Unknown relation: %s"), par[1]);
2496 return;
2497 }
2498
2499 /* make sure that qualitative comparison is done on numbers */
2500 if (relation > 1 && term1type != VINTEGER)
2501 {
2502 us_abortcommand(_("Inequality comparisons must be done on numbers"));
2503 return;
2504 }
2505
2506 /* see if the command should be executed */
2507 switch (relation)
2508 {
2509 case 0: /* == */
2510 if (term1type == VINTEGER)
2511 {
2512 if (term1 != term2) return;
2513 } else
2514 {
2515 if (namesame((CHAR *)term1, (CHAR *)term2) != 0) return;
2516 }
2517 break;
2518 case 1: /* != */
2519 if (term1type == VINTEGER)
2520 {
2521 if (term1 == term2) return;
2522 } else
2523 {
2524 if (namesame((CHAR *)term1, (CHAR *)term2) == 0) return;
2525 }
2526 break;
2527 case 2: /* < */
2528 if (term1 >= term2) return;
2529 break;
2530 case 3: /* <= */
2531 if (term1 > term2) return;
2532 break;
2533 case 4: /* > */
2534 if (term1 <= term2) return;
2535 break;
2536 case 5: /* >= */
2537 if (term1 < term2) return;
2538 break;
2539 }
2540
2541 /* condition is true: create the command to execute */
2542 com = us_buildcommand(count-3, &par[3]);
2543 if (com == NOUSERCOM)
2544 {
2545 us_abortcommand(_("Condition true but there is no command to execute"));
2546 return;
2547 }
2548 us_execute(com, FALSE, FALSE, FALSE);
2549 us_freeusercom(com);
2550 }
2551
us_interpret(INTBIG count,CHAR * par[])2552 void us_interpret(INTBIG count, CHAR *par[])
2553 {
2554 REGISTER CHAR *pp;
2555 REGISTER INTBIG language, len;
2556 REGISTER VARIABLE *var;
2557 REGISTER BOOLEAN fromfile;
2558
2559 language = VLISP;
2560 fromfile = FALSE;
2561 if (namesamen(par[0], x_("file"), estrlen(par[0])) == 0)
2562 {
2563 count--;
2564 par++;
2565 fromfile = TRUE;
2566 }
2567
2568 if (count > 0)
2569 {
2570 len = estrlen(pp = par[0]);
2571 if (namesamen(pp, x_("lisp"), len) == 0)
2572 {
2573 language = VLISP;
2574 count--;
2575 par++;
2576 } else if (namesamen(pp, x_("tcl"), len) == 0)
2577 {
2578 language = VTCL;
2579 count--;
2580 par++;
2581 } else if (namesamen(pp, x_("java"), len) == 0)
2582 {
2583 language = VJAVA;
2584 count--;
2585 par++;
2586 }
2587 }
2588
2589 /* handle "file" option */
2590 if (fromfile)
2591 {
2592 if (count <= 0)
2593 {
2594 ttyputusage(x_("interpret file LANGUAGE FILENAME"));
2595 return;
2596 }
2597 if (loadcode(par[0], language))
2598 ttyputerr(_("Error loading code"));
2599 return;
2600 }
2601
2602 /* with no parameters, simply drop into the interpreter loop */
2603 if (count == 0)
2604 {
2605 /* "languageconverse" returns false if it wants to continue conversation */
2606 if (!languageconverse(language)) us_state |= LANGLOOP; else
2607 ttyputmsg(_("Back to Electric"));
2608 return;
2609 }
2610
2611 if (count > 1)
2612 {
2613 us_abortcommand(_("Please provide only one parameter to be interpreted"));
2614 return;
2615 }
2616
2617 var = doquerry(par[0], language, VSTRING);
2618 if (var == NOVARIABLE) ttyputmsg(x_("%s"), par[0]); else
2619 {
2620 ttyputmsg(x_("%s => %s"), par[0], describesimplevariable(var));
2621 }
2622 }
2623
us_iterate(INTBIG count,CHAR * par[])2624 void us_iterate(INTBIG count, CHAR *par[])
2625 {
2626 REGISTER INTBIG i, j, l, times;
2627 REGISTER BOOLEAN repeatcommand;
2628 REGISTER USERCOM *uc;
2629 REGISTER INTBIG len, total;
2630 INTBIG cindex, objaddr, objtype;
2631 VARIABLE *var, fvar;
2632 CHAR *qual, parnames[30];
2633 BOOLEAN comvar;
2634 REGISTER USERCOM *com;
2635 REGISTER void *infstr;
2636
2637 /* see if this is the "repeat last command" form */
2638 repeatcommand = FALSE;
2639 if (count == 0)
2640 {
2641 repeatcommand = TRUE;
2642 times = 1;
2643 } else
2644 {
2645 l = estrlen(par[0]);
2646 if (namesamen(par[0], x_("remembered"), l) == 0 && l >= 1)
2647 {
2648 if (us_lastcommandcount == 0)
2649 {
2650 us_abortcommand(_("No previous command to repeat"));
2651 return;
2652 }
2653 /* repeat the command issued by the "remember" statement */
2654 uc = us_buildcommand(us_lastcommandcount, us_lastcommandpar);
2655 if (uc == NOUSERCOM) return;
2656 us_execute(uc, FALSE, FALSE, FALSE);
2657 us_freeusercom(uc);
2658 return;
2659 }
2660 if (isanumber(par[0]))
2661 {
2662 repeatcommand = TRUE;
2663 times = eatoi(par[0]);
2664 }
2665 }
2666
2667 if (repeatcommand)
2668 {
2669 /* make sure there was a valid previous command */
2670 if (us_lastcom == NOUSERCOM || us_lastcom->active < 0)
2671 {
2672 us_abortcommand(_("No last command to repeat"));
2673 return;
2674 }
2675
2676 /* copy last command into new one */
2677 uc = us_allocusercom();
2678 if (uc == NOUSERCOM)
2679 {
2680 ttyputnomemory();
2681 return;
2682 }
2683 for(i=0; i<us_lastcom->count; i++)
2684 if (allocstring(&uc->word[i], us_lastcom->word[i], us_tool->cluster))
2685 {
2686 ttyputnomemory();
2687 return;
2688 }
2689 uc->active = us_lastcom->active;
2690 uc->count = us_lastcom->count;
2691 (void)allocstring(&uc->comname, us_lastcom->comname, us_tool->cluster);
2692 uc->menu = us_lastcom->menu;
2693
2694 /* execute this command */
2695 for(j=0; j<times; j++) us_execute(uc, TRUE, FALSE, TRUE);
2696 us_freeusercom(uc);
2697 } else
2698 {
2699 /* implement the iterate over array-variable form */
2700 if (count < 2)
2701 {
2702 ttyputusage(x_("iterate ARRAY-VARIABLE MACRO"));
2703 return;
2704 }
2705 if (us_getvar(par[0], &objaddr, &objtype, &qual, &comvar, &cindex))
2706 {
2707 us_abortcommand(_("Incorrect iterator variable name: %s"), par[0]);
2708 return;
2709 }
2710 if (*qual != 0)
2711 {
2712 var = getval(objaddr, objtype, -1, qual);
2713 if (var == NOVARIABLE)
2714 {
2715 us_abortcommand(_("Cannot find iterator variable: %s"), par[0]);
2716 return;
2717 }
2718 } else
2719 {
2720 fvar.addr = objaddr;
2721 fvar.type = objtype;
2722 var = &fvar;
2723 }
2724 len = getlength(var);
2725 if (len < 0) len = 1;
2726 if (us_expandaddrtypearray(&us_iteratelimit, &us_iterateaddr,
2727 &us_iteratetype, len)) return;
2728 if ((var->type&VISARRAY) == 0)
2729 {
2730 us_iterateaddr[0] = var->addr;
2731 us_iteratetype[0] = var->type;
2732 total = 1;
2733 } else
2734 {
2735 if ((var->type&VTYPE) == VGENERAL)
2736 {
2737 for(i=0; i<len; i += 2)
2738 {
2739 us_iterateaddr[i/2] = ((INTBIG *)var->addr)[i];
2740 us_iteratetype[i/2] = ((INTBIG *)var->addr)[i+1];
2741 }
2742 total = len / 2;
2743 } else
2744 {
2745 for(i=0; i<len; i++)
2746 {
2747 us_iterateaddr[i] = ((INTBIG *)var->addr)[i];
2748 us_iteratetype[i] = var->type;
2749 }
2750 total = len;
2751 }
2752 }
2753
2754 /* now iterate with this value */
2755 for(i=0; i<total; i++)
2756 {
2757 infstr = initinfstr();
2758 addstringtoinfstr(infstr, par[1]);
2759 (void)esnprintf(parnames, 30, x_(" %s 0%lo"), us_variabletypename(us_iteratetype[i]),
2760 us_iterateaddr[i]);
2761 addstringtoinfstr(infstr, parnames);
2762 com = us_makecommand(returninfstr(infstr));
2763 if (com->active < 0) { us_freeusercom(com); break; }
2764 us_execute(com, FALSE, FALSE, FALSE);
2765 us_freeusercom(com);
2766 if (stopping(STOPREASONITERATE)) break;
2767 }
2768 }
2769 }
2770
us_killcell(INTBIG count,CHAR * par[])2771 void us_killcell(INTBIG count, CHAR *par[])
2772 {
2773 REGISTER NODEPROTO *np, *onp;
2774 REGISTER NODEINST *ni;
2775 REGISTER LIBRARY *lib;
2776 extern COMCOMP us_showdp;
2777
2778 if (count == 0)
2779 {
2780 count = ttygetparam(M_("Cell name: "), &us_showdp, MAXPARS, par);
2781 if (count == 0)
2782 {
2783 us_abortedmsg();
2784 return;
2785 }
2786 }
2787
2788 np = getnodeproto(par[0]);
2789 if (np == NONODEPROTO)
2790 {
2791 us_abortcommand(_("No cell called %s"), par[0]);
2792 return;
2793 }
2794 if (np->primindex != 0)
2795 {
2796 us_abortcommand(_("Can only kill cells"));
2797 return;
2798 }
2799
2800 /* disallow killing if lock is on */
2801 if (us_cantedit(np, NONODEINST, TRUE)) return;
2802
2803 /* if there are still instances of the cell, mention them */
2804 if (np->firstinst != NONODEINST)
2805 {
2806 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
2807 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
2808 onp->temp1 = 0;
2809 for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
2810 ni->parent->temp1++;
2811 ttyputerr(_("Erase all of the following instances of this cell first:"));
2812 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
2813 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
2814 if (onp->temp1 != 0)
2815 ttyputmsg(_(" %ld instance(s) in cell %s"), onp->temp1, describenodeproto(onp));
2816 return;
2817 }
2818
2819 /* kill the cell */
2820 us_dokillcell(np);
2821 ttyputmsg(_("Cell %s:%s deleted"), np->lib->libname, nldescribenodeproto(np));
2822 }
2823