1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usrcomoq.c
6 * User interface tool: command handler for O through Q
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 "egraphics.h"
35 #include "sim.h"
36
us_offtool(INTBIG count,CHAR * par[])37 void us_offtool(INTBIG count, CHAR *par[])
38 {
39 REGISTER INTBIG permanently;
40
41 if (count == 2 && namesamen(par[1], x_("permanently"), estrlen(par[1])) == 0)
42 {
43 count--;
44 permanently = 1;
45 } else permanently = 0;
46 us_settool(count, par, permanently);
47 }
48
us_ontool(INTBIG count,CHAR * par[])49 void us_ontool(INTBIG count, CHAR *par[])
50 {
51 us_settool(count, par, 2);
52 }
53
us_outhier(INTBIG count,CHAR * par[])54 void us_outhier(INTBIG count, CHAR *par[])
55 {
56 REGISTER INTBIG len, total, i, j, haveview, vlx, vhx, vly, vhy;
57 INTBIG lx, hx, ly, hy, index, viewinfo[22];
58 REGISTER NODEPROTO *curnp, *hinp, *np;
59 REGISTER BOOLEAN newwindow, found;
60 REGISTER NODEINST *ni, *hini, *iconinst;
61 REGISTER PORTPROTO *pp, *curpp, *hipp;
62 REGISTER PORTEXPINST *pe;
63 REGISTER WINDOWPART *w;
64 REGISTER VARIABLE *var;
65 XARRAY into, outof;
66 HIGHLIGHT high;
67
68 /* make sure repeat count is valid */
69 if (count == 0) total = 1; else
70 {
71 total = eatoi(par[0]);
72 if (total <= 0)
73 {
74 us_abortcommand(_("Specify a positive number"));
75 return;
76 }
77 }
78
79 /* must be editing a cell */
80 curnp = us_needcell();
81 if (curnp == NONODEPROTO) return;
82
83 /* if in waveform window, switch to associated circuit window */
84 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
85 {
86 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
87 if (w != el_curwindowpart && w->curnodeproto == curnp) break;
88 if (w == NOWINDOWPART)
89 {
90 us_abortcommand(_("Cannot go up the hierarchy from this waveform window"));
91 return;
92 }
93 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w,
94 VWINDOWPART|VDONTSAVE);
95 }
96
97 /* initialize desired window extent */
98 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
99 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
100
101 /* see if a node with an export is highlighted */
102 curpp = NOPORTPROTO;
103 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
104 if (var != NOVARIABLE)
105 {
106 len = getlength(var);
107 if (len == 1)
108 {
109 /* get the highlighted object */
110 if (!us_makehighlight(((CHAR **)var->addr)[0], &high))
111 {
112 pp = NOPORTPROTO;
113 if ((high.status&HIGHTYPE) == HIGHTEXT)
114 {
115 if (high.fromvar == NOVARIABLE && high.fromport != NOPORTPROTO)
116 pp = high.fromport->subportproto;
117 } else
118 {
119 if ((high.status&HIGHTYPE) == HIGHFROM &&
120 high.fromgeom->entryisnode && high.fromport != NOPORTPROTO)
121 pp = high.fromport;
122 }
123 if (pp != NOPORTPROTO)
124 {
125 ni = high.fromgeom->entryaddr.ni;
126 np = ni->proto;
127
128 /* see if port is an export */
129 for (pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
130 {
131 if (pe->proto == pp)
132 {
133 curpp = pe->exportproto;
134 break;
135 }
136 }
137 }
138 }
139 }
140 }
141
142 us_clearhighlightcount();
143 haveview = 0;
144 newwindow = FALSE;
145 for(i=0; i<total; i++)
146 {
147 hinp = NONODEPROTO;
148
149 hini = descentparent(curnp, &index, el_curwindowpart, viewinfo);
150 if (hini != NONODEINST)
151 {
152 hinp = hini->parent;
153 for(j=0; j<22; j++) if (viewinfo[j] != 0) break;
154 if (j >= 22) haveview = 0; else
155 {
156 haveview = 1;
157 vlx = viewinfo[0];
158 vhx = viewinfo[1];
159 vly = viewinfo[2];
160 vhy = viewinfo[3];
161 into[0][0] = viewinfo[4];
162 into[0][1] = viewinfo[5];
163 into[0][2] = viewinfo[6];
164 into[1][0] = viewinfo[7];
165 into[1][1] = viewinfo[8];
166 into[1][2] = viewinfo[9];
167 into[2][0] = viewinfo[10];
168 into[2][1] = viewinfo[11];
169 into[2][2] = viewinfo[12];
170 outof[0][0] = viewinfo[13];
171 outof[0][1] = viewinfo[14];
172 outof[0][2] = viewinfo[15];
173 outof[1][0] = viewinfo[16];
174 outof[1][1] = viewinfo[17];
175 outof[1][2] = viewinfo[18];
176 outof[2][0] = viewinfo[19];
177 outof[2][1] = viewinfo[20];
178 outof[2][2] = viewinfo[21];
179 }
180 }
181
182 /* if stack didn't tell where to go, see if upper cell is obvious */
183 if (hinp == NONODEPROTO)
184 {
185 /* see if cell "curnp" has an icon cell */
186 np = iconview(curnp);
187 if (np == NONODEPROTO) np = curnp;
188
189 /* see if there is any instance of that cell */
190 found = FALSE;
191 hinp = NONODEPROTO;
192 iconinst = NONODEINST;
193 for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
194 {
195 if (isiconof(np, ni->parent))
196 {
197 iconinst = ni;
198 continue;
199 }
200 if ((ni->parent->lib->userbits&HIDDENLIBRARY) != 0) continue;
201 found = TRUE;
202 if (hinp != NONODEPROTO)
203 {
204 if (ni->parent == hinp) continue;
205 hinp = NONODEPROTO;
206 break;
207 }
208 hinp = ni->parent;
209 hini = ni;
210 }
211 if (!found && iconinst != NONODEINST)
212 {
213 hini = iconinst;
214 hinp = iconinst->parent;
215 found = TRUE;
216 }
217 if (!found)
218 {
219 if (i == 0)
220 {
221 us_abortcommand(_("Not in any cells"));
222 return;
223 }
224 ttyputerr(_("Only in %ld deep"), i);
225 hinp = curnp;
226 break;
227 }
228 if (hinp == NONODEPROTO)
229 {
230 hini = us_pickhigherinstance(np);
231 if (hini == NONODEINST) return;
232 newwindow = TRUE;
233 hinp = hini->parent;
234 }
235 }
236
237 /* determine which port to highlight */
238 hipp = NOPORTPROTO;
239 if (hini != NONODEINST && curpp != NOPORTPROTO)
240 hipp = equivalentport(curnp, curpp, hini->proto);
241
242 /* adjust view of the cell */
243 if (haveview != 0)
244 {
245 lx = vlx; hx = vhx;
246 ly = vly; hy = vhy;
247 } else
248 {
249 if (hini != NONODEINST && hini->proto == curnp)
250 {
251 lx += hini->geom->lowx - curnp->lowx;
252 hx += hini->geom->lowx - curnp->lowx;
253 ly += hini->geom->lowy - curnp->lowy;
254 hy += hini->geom->lowy - curnp->lowy;
255 } else
256 {
257 /* make a full view of the cell */
258 us_fullview(hinp, &lx, &hx, &ly, &hy);
259 }
260 }
261
262 /* keep rolling up the hierarchy */
263 curnp = hinp;
264 curpp = hipp;
265 }
266
267 /* display the final location */
268 if (haveview != 0)
269 {
270 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("intocell"), into);
271 us_setxarray((INTBIG)el_curwindowpart, VWINDOWPART, x_("outofcell"), outof);
272 if (outof[2][0] == 0 && outof[2][1] == 0 && outof[2][2] == 0)
273 {
274 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
275 el_curwindowpart->state & ~INPLACEEDIT, VINTEGER);
276 } else
277 {
278 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
279 el_curwindowpart->state | INPLACEEDIT, VINTEGER);
280 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("inplacedepth"),
281 el_curwindowpart->inplacedepth-1, VINTEGER);
282 }
283 }
284 us_switchtocell(hinp, lx, hx, ly, hy, hini, hipp, newwindow, TRUE, TRUE);
285
286 /* if simulating, coordinate this hierarchy traversal with the waveform */
287 if (el_curwindowpart != NOWINDOWPART &&
288 (el_curwindowpart->state&WINDOWMODE) == WINDOWSIMMODE)
289 {
290 asktool(sim_tool, "traverse-up", (INTBIG)hinp);
291 }
292 }
293
us_package(INTBIG count,CHAR * par[])294 void us_package(INTBIG count, CHAR *par[])
295 {
296 INTBIG lx, hx, ly, hy;
297 REGISTER INTBIG search, len;
298 REGISTER void *infstr;
299 REGISTER GEOM *look;
300 REGISTER NODEPROTO *np, *parnt;
301 REGISTER PORTPROTO *ppt, *npt;
302 REGISTER NODEINST *ni, *newni;
303 REGISTER ARCINST *ai, *newar;
304 REGISTER LIBRARY *lib;
305 REGISTER CHAR *pt;
306 extern COMCOMP us_packagep;
307
308 /* get the specified area */
309 if (us_getareabounds(&lx, &hx, &ly, &hy) == NONODEPROTO)
310 {
311 us_abortcommand(_("Enclose an area to be packaged"));
312 return;
313 }
314
315 if (count == 0)
316 {
317 count = ttygetparam(M_("New cell name: "), &us_packagep, MAXPARS, par);
318 if (count == 0)
319 {
320 us_abortedmsg();
321 return;
322 }
323 }
324
325 /* figure out which library to use */
326 lib = el_curlib;
327 for(pt = par[0]; *pt != 0; pt++) if (*pt == ':') break;
328 if (*pt == ':')
329 {
330 *pt++ = 0;
331 lib = getlibrary(par[0]);
332 if (lib == NOLIBRARY)
333 {
334 us_abortcommand(_("Cannot find library '%s'"), par[0]);
335 return;
336 }
337 par[0] = pt;
338 }
339
340 /* make sure there is a proper view type on this new cell */
341 parnt = getcurcell();
342 len = strlen(par[0]);
343 if (par[0][len-1] != '}')
344 {
345 infstr = initinfstr();
346 formatinfstr(infstr, "%s{%s}", par[0], parnt->cellview->sviewname);
347 par[0] = returninfstr(infstr);
348 }
349
350 /* create the new cell */
351 np = us_newnodeproto(par[0], lib);
352 if (np == NONODEPROTO)
353 {
354 us_abortcommand(_("Cannot create cell %s"), par[0]);
355 return;
356 }
357
358 /* first zap all nodes touching all arcs in the region */
359 search = initsearch(lx, hx, ly, hy, parnt);
360 for(;;)
361 {
362 look = nextobject(search);
363 if (look == NOGEOM) break;
364 if (look->entryisnode) continue;
365 ai = look->entryaddr.ai;
366 ni = NONODEINST;
367 ai->end[0].nodeinst->temp1 = (UINTBIG)ni;
368 ai->end[1].nodeinst->temp1 = (UINTBIG)ni;
369 }
370
371 /* copy the nodes into the new cell */
372 search = initsearch(lx, hx, ly, hy, parnt);
373 for(;;)
374 {
375 look = nextobject(search);
376 if (look == NOGEOM) break;
377 if (!look->entryisnode) continue;
378 ni = look->entryaddr.ni;
379 newni = newnodeinst(ni->proto, ni->lowx, ni->highx, ni->lowy,
380 ni->highy, ni->transpose, ni->rotation, np);
381 if (newni == NONODEINST)
382 {
383 us_abortcommand(_("Cannot create node in new cell"));
384 return;
385 }
386 ni->temp1 = (INTBIG)newni;
387 newni->userbits = ni->userbits;
388 TDCOPY(newni->textdescript, ni->textdescript);
389 if (copyvars((INTBIG)ni, VNODEINST, (INTBIG)newni, VNODEINST, FALSE))
390 {
391 ttyputnomemory();
392 return;
393 }
394
395 /* make ports where this nodeinst has them */
396 if (ni->firstportexpinst != NOPORTEXPINST)
397 for(ppt = parnt->firstportproto; ppt != NOPORTPROTO; ppt = ppt->nextportproto)
398 {
399 if (ppt->subnodeinst != ni) continue;
400 npt = newportproto(np, newni, ppt->subportproto, ppt->protoname);
401 if (npt != NOPORTPROTO)
402 {
403 npt->userbits = (npt->userbits & ~STATEBITS) | (ppt->userbits & STATEBITS);
404 TDCOPY(npt->textdescript, ppt->textdescript);
405 if (copyvars((INTBIG)ppt, VPORTPROTO, (INTBIG)npt, VPORTPROTO, FALSE))
406 {
407 ttyputnomemory();
408 return;
409 }
410 }
411 }
412 }
413
414 /* copy the arcs into the new cell */
415 search = initsearch(lx, hx, ly, hy, parnt);
416 for(;;)
417 {
418 look = nextobject(search);
419 if (look == NOGEOM) break;
420 if (look->entryisnode) continue;
421 ai = look->entryaddr.ai;
422 if (ai->end[0].nodeinst->temp1 == (UINTBIG)-1 ||
423 ai->end[1].nodeinst->temp1 == (UINTBIG)-1) continue;
424 newar = newarcinst(ai->proto, ai->width, ai->userbits, (NODEINST *)ai->end[0].nodeinst->temp1,
425 ai->end[0].portarcinst->proto, ai->end[0].xpos,ai->end[0].ypos,
426 (NODEINST *)ai->end[1].nodeinst->temp1, ai->end[1].portarcinst->proto,
427 ai->end[1].xpos,ai->end[1].ypos, np);
428 if (newar == NOARCINST)
429 {
430 us_abortcommand(_("Cannot create arc in new cell"));
431 return;
432 }
433 if (copyvars((INTBIG)ai, VARCINST, (INTBIG)newar, VARCINST, FALSE) ||
434 copyvars((INTBIG)ai->end[0].portarcinst, VPORTARCINST,
435 (INTBIG)newar->end[0].portarcinst, VPORTARCINST, FALSE) ||
436 copyvars((INTBIG)ai->end[1].portarcinst, VPORTARCINST,
437 (INTBIG)newar->end[1].portarcinst, VPORTARCINST, FALSE))
438 {
439 ttyputnomemory();
440 return;
441 }
442 }
443
444 /* recompute bounds of new cell */
445 (*el_curconstraint->solve)(np);
446
447 ttyputmsg(_("Cell %s created"), describenodeproto(np));
448 }
449
us_port(INTBIG count,CHAR * par[])450 void us_port(INTBIG count, CHAR *par[])
451 {
452 REGISTER INTBIG i, l, labels, total, reducehighlighting;
453 INTBIG lx, hx, ly, hy, mlx, mly, mhx, mhy, bits, mask, newbits, x, y, deleted;
454 REGISTER BOOLEAN nodegood;
455 REGISTER NODEINST *ni, *oni;
456 REGISTER NODEPROTO *np;
457 REGISTER PORTPROTO *pp, *ppt;
458 REGISTER PORTARCINST *pi;
459 REGISTER PORTEXPINST *pe, *nextpe;
460 REGISTER LIBRARY *olib;
461 GEOM *fromgeom, *togeom;
462 PORTPROTO *fromport, *toport;
463 REGISTER CHAR *pt;
464 CHAR *portname, *refname;
465 NODEINST **nilist;
466 REGISTER HIGHLIGHT *high;
467 HIGHLIGHT newhigh;
468 extern COMCOMP us_portp, us_portep;
469 REGISTER GEOM **g;
470 static POLYGON *poly = NOPOLYGON;
471 REGISTER void *infstr;
472
473 /* get options */
474 if (count == 0)
475 {
476 count = ttygetparam(M_("Port option: "), &us_portp, MAXPARS, par);
477 if (count == 0)
478 {
479 us_abortedmsg();
480 return;
481 }
482 }
483 l = estrlen(pt = par[0]);
484
485 if (namesamen(pt, x_("labels"), l) == 0 && l >= 1)
486 {
487 if (count > 1)
488 {
489 l = estrlen(pt = par[1]);
490 if (namesamen(pt, x_("crosses"), l) == 0 && l >= 1) labels = PORTSCROSS; else
491 if (namesamen(pt, x_("short"), l) == 0 && l >= 2) labels = PORTSSHORT; else
492 if (namesamen(pt, x_("long"), l) == 0 && l >= 1) labels = PORTSFULL; else
493 {
494 ttyputusage(x_("port labels short|long|crosses"));
495 return;
496 }
497 startobjectchange((INTBIG)us_tool, VTOOL);
498 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
499 (us_useroptions & ~PORTLABELS) | labels, VINTEGER);
500 endobjectchange((INTBIG)us_tool, VTOOL);
501 }
502 switch (us_useroptions&PORTLABELS)
503 {
504 case PORTSCROSS: ttyputverbose(M_("Ports shown as crosses")); break;
505 case PORTSFULL: ttyputverbose(M_("Long port names displayed")); break;
506 case PORTSSHORT: ttyputverbose(M_("Short port names displayed")); break;
507 }
508 return;
509 }
510
511 if (namesamen(pt, x_("export-labels"), l) == 0 && l >= 8)
512 {
513 if (count > 1)
514 {
515 l = estrlen(pt = par[1]);
516 if (namesamen(pt, x_("crosses"), l) == 0 && l >= 1) labels = EXPORTSCROSS; else
517 if (namesamen(pt, x_("short"), l) == 0 && l >= 2) labels = EXPORTSSHORT; else
518 if (namesamen(pt, x_("long"), l) == 0 && l >= 1) labels = EXPORTSFULL; else
519 {
520 ttyputusage(x_("port export-labels short|long|crosses"));
521 return;
522 }
523 startobjectchange((INTBIG)us_tool, VTOOL);
524 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
525 (us_useroptions & ~EXPORTLABELS) | labels, VINTEGER);
526 endobjectchange((INTBIG)us_tool, VTOOL);
527 }
528 switch (us_useroptions&EXPORTLABELS)
529 {
530 case EXPORTSCROSS: ttyputverbose(M_("Exports shown as crosses")); break;
531 case EXPORTSFULL: ttyputverbose(M_("Long export names displayed")); break;
532 case EXPORTSSHORT: ttyputverbose(M_("Short export names displayed")); break;
533 }
534 return;
535 }
536
537 if (namesamen(pt, x_("synchronize-library"), l) == 0 && l >= 1)
538 {
539 if (count <= 1)
540 {
541 ttyputusage(x_("port synchronize-library LIBRARY"));
542 return;
543 }
544 olib = getlibrary(par[1]);
545 if (olib == NOLIBRARY)
546 {
547 us_abortcommand(_("No library called %s is read in"), par[1]);
548 return;
549 }
550 if (olib == el_curlib)
551 {
552 us_abortcommand(_("Must synchronize with a different library"));
553 return;
554 }
555 us_portsynchronize(olib);
556 return;
557 }
558
559 if (namesamen(pt, x_("identify-cell"), l) == 0 && l >= 10)
560 {
561 /* make sure there is a current cell */
562 np = us_needcell();
563 if (np == NONODEPROTO) return;
564 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
565 {
566 us_abortcommand(_("Cannot show exports in a 3D window"));
567 return;
568 }
569 us_identifyports(0, 0, np, LAYERA, FALSE);
570 return;
571 }
572
573 if (namesamen(pt, x_("identify-node"), l) == 0 && l >= 10)
574 {
575 /* make sure there is a current node */
576 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
577 {
578 us_abortcommand(_("Cannot show ports in a 3D window"));
579 return;
580 }
581 g = us_gethighlighted(WANTNODEINST, 0, 0);
582 for(i=0; g[i] != NOGEOM; i++) ;
583 if (i <= 0)
584 {
585 us_abortcommand(_("Must select one or more nodes"));
586 return;
587 }
588 nilist = (NODEINST **)emalloc(i * (sizeof (NODEINST *)), el_tempcluster);
589 if (nilist == 0) return;
590 for(i=0; g[i] != NOGEOM; i++)
591 nilist[i] = g[i]->entryaddr.ni;
592 us_identifyports(i, nilist, nilist[0]->proto, LAYERA, FALSE);
593 efree((CHAR *)nilist);
594 return;
595 }
596
597 if (namesamen(pt, x_("move"), l) == 0 && l >= 1)
598 {
599 if (us_gettwoobjects(&fromgeom, &fromport, &togeom, &toport))
600 {
601 us_abortcommand(_("Must select two nodes"));
602 return;
603 }
604 if (fromport == NOPORTPROTO || toport == NOPORTPROTO)
605 {
606 us_abortcommand(_("Must select two nodes AND their ports"));
607 return;
608 }
609
610 /* make sure ports are in the same cell */
611 np = geomparent(fromgeom);
612 if (np != geomparent(togeom))
613 {
614 us_abortcommand(_("Port motion must be within a single cell"));
615 return;
616 }
617
618 /* disallow port action if lock is on */
619 if (us_cantedit(np, NONODEINST, TRUE)) return;
620
621 reducehighlighting = 1;
622 if (count > 1)
623 {
624 l = estrlen(pt = par[1]);
625 if (namesamen(pt, x_("remain-highlighted"), l) == 0) reducehighlighting = 0;
626 }
627
628 /* get the "source" node and export */
629 oni = fromgeom->entryaddr.ni;
630 for(pe = oni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
631 if (pe->proto == fromport) break;
632 if (pe == NOPORTEXPINST)
633 {
634 us_abortcommand(_("Port %s of node %s is not an export"), fromport->protoname,
635 describenodeinst(oni));
636 return;
637 }
638
639 /* move the port */
640 ni = togeom->entryaddr.ni;
641 if (ni == oni && fromport == toport)
642 {
643 us_abortcommand(_("This does not move the port"));
644 return;
645 }
646
647 /* clear highlighting */
648 if (reducehighlighting == 0) us_pushhighlight();
649 us_clearhighlightcount();
650
651 np = ni->parent;
652 pt = pe->exportproto->protoname;
653 startobjectchange((INTBIG)ni, VNODEINST);
654 startobjectchange((INTBIG)oni, VNODEINST);
655 if (moveportproto(np, pe->exportproto, ni, toport)) ttyputerr(_("Port not moved")); else
656 {
657 endobjectchange((INTBIG)ni, VNODEINST);
658 endobjectchange((INTBIG)oni, VNODEINST);
659 ttyputverbose(M_("Port %s moved from node %s to node %s"), pt, describenodeinst(oni),
660 describenodeinst(ni));
661 }
662
663 /* restore highlighting */
664 if (reducehighlighting == 0) us_pophighlight(FALSE); else
665 {
666 newhigh.status = HIGHFROM;
667 newhigh.cell = np;
668 newhigh.fromgeom = fromgeom;
669 newhigh.fromport = fromport;
670 us_addhighlight(&newhigh);
671 }
672 return;
673 }
674
675 if (namesamen(pt, x_("re-export-all"), l) == 0 && l >= 1)
676 {
677 /* make sure there is a current cell */
678 np = us_needcell();
679 if (np == NONODEPROTO) return;
680
681 /* disallow port action if lock is on */
682 if (us_cantedit(np, NONODEINST, TRUE)) return;
683
684 /* save highlighting */
685 us_pushhighlight();
686 us_clearhighlightcount();
687
688 /* look at every node in this cell */
689 total = 0;
690 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
691 {
692 /* only look for cells, not primitives */
693 if (ni->proto->primindex != 0) continue;
694
695 /* ignore recursive references (showing icon in contents) */
696 if (isiconof(ni->proto, np)) continue;
697
698 /* clear marks on the ports of this node */
699 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
700 pp->temp1 = 0;
701
702 /* mark the connected and exports */
703 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
704 pi->proto->temp1++;
705 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
706 pe->proto->temp1++;
707
708 /* initialize for queueing creation of new exports */
709 us_initqueuedexports();
710
711 /* now export the remaining ports */
712 nodegood = FALSE;
713 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
714 if (pp->temp1 == 0)
715 {
716 if (!nodegood)
717 {
718 startobjectchange((INTBIG)ni, VNODEINST);
719 nodegood = TRUE;
720 }
721 if (us_queuenewexport(ni, pp, pp))
722 {
723 us_pophighlight(FALSE);
724 return;
725 }
726 total++;
727 }
728 if (nodegood)
729 {
730 /* create any queued exports */
731 us_createqueuedexports();
732 endobjectchange((INTBIG)ni, VNODEINST);
733 }
734 }
735 if (total == 0) ttyputmsg(_("No ports to export")); else
736 ttyputmsg(_("%ld ports exported"), total);
737
738 /* restore highlighting */
739 us_pophighlight(FALSE);
740 return;
741 }
742
743 if (namesamen(pt, x_("highlighted-re-export"), l) == 0 && l >= 1)
744 {
745 /* get the necessary polygon */
746 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
747
748 /* get the bounds of the selected area */
749 np = us_getareabounds(&lx, &hx, &ly, &hy);
750 if (np == NONODEPROTO)
751 {
752 us_abortcommand(_("Must select an area enclosing ports to export"));
753 return;
754 }
755
756 /* disallow port action if lock is on */
757 if (us_cantedit(np, NONODEINST, TRUE)) return;
758
759 /* get list of nodes in the selected area */
760 g = us_gethighlighted(WANTNODEINST, 0, 0);
761 if (g[0] == NOGEOM)
762 {
763 us_abortcommand(_("Must select some nodes for making exports"));
764 return;
765 }
766
767 /* save highlighting */
768 us_pushhighlight();
769 us_clearhighlightcount();
770
771 /* initialize for queueing creation of new exports */
772 us_initqueuedexports();
773
774 /* re-export the requested ports */
775 total = 0;
776 for(i=0; g[i] != NOGEOM; i++)
777 {
778 ni = g[i]->entryaddr.ni;
779
780 /* only look for cells, not primitives */
781 if (ni->proto->primindex != 0) continue;
782
783 /* clear marks on the ports of this node */
784 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
785 pp->temp1 = 0;
786
787 /* mark the connected and make exports */
788 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
789 pi->proto->temp1++;
790 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
791 pe->proto->temp1++;
792
793 /* now export the remaining ports that are in the area */
794 nodegood = FALSE;
795 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
796 if (pp->temp1 == 0)
797 {
798 shapeportpoly(ni, pp, poly, FALSE);
799 getbbox(poly, &mlx, &mhx, &mly, &mhy);
800 if (mlx > hx || mhx < lx || mly > hy || mhy < ly) continue;
801 if (!nodegood)
802 {
803 startobjectchange((INTBIG)ni, VNODEINST);
804 nodegood = TRUE;
805 }
806 if (us_queuenewexport(ni, pp, pp))
807 {
808 us_pophighlight(FALSE);
809 return;
810 }
811 total++;
812 }
813 }
814
815 /* create any queued exports */
816 us_createqueuedexports();
817 for(i=0; g[i] != NOGEOM; i++)
818 {
819 ni = g[i]->entryaddr.ni;
820 if (ni->proto->primindex != 0) continue;
821 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
822 {
823 if (pp->temp1 != 0) continue;
824 endobjectchange((INTBIG)ni, VNODEINST);
825 break;
826 }
827 }
828 if (total == 0) ttyputmsg(_("No ports to export")); else
829 ttyputmsg(_("%ld ports exported"), total);
830
831 /* restore highlighting */
832 us_pophighlight(FALSE);
833 return;
834 }
835
836 if (namesamen(pt, x_("power-ground-re-export"), l) == 0 && l >= 1)
837 {
838 /* make sure there is a current cell */
839 np = us_needcell();
840 if (np == NONODEPROTO) return;
841
842 /* disallow port action if lock is on */
843 if (us_cantedit(np, NONODEINST, TRUE)) return;
844
845 /* save highlighting */
846 us_pushhighlight();
847 us_clearhighlightcount();
848
849 /* look at every node in this cell */
850 total = 0;
851 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
852 {
853 /* only look for cells, not primitives */
854 if (ni->proto->primindex != 0) continue;
855
856 /* ignore recursive references (showing icon in contents) */
857 if (isiconof(ni->proto, np)) continue;
858
859 /* clear marks on the ports of this node */
860 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
861 pp->temp1 = 0;
862
863 /* mark the connected and exports */
864 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
865 pi->proto->temp1++;
866 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
867 pe->proto->temp1++;
868
869 /* now export the remaining power and ground ports */
870 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
871 {
872 if (pp->temp1 != 0) continue;
873 if (!portispower(pp) && !portisground(pp)) continue;
874
875 if (us_reexportport(pp, ni))
876 {
877 us_pophighlight(FALSE);
878 return;
879 }
880 total++;
881 }
882 }
883 if (total == 0) ttyputmsg(_("No power and ground ports to export")); else
884 ttyputmsg(_("%ld power and ground ports exported"), total);
885
886 /* restore highlighting */
887 us_pophighlight(FALSE);
888 return;
889 }
890
891 if (namesamen(pt, x_("not"), l) == 0 && l >= 1)
892 {
893 if (count <= 1 || namesamen(par[1], x_("export"), estrlen(par[1])) != 0)
894 {
895 ttyputusage(x_("port not export [OPTIONS]"));
896 return;
897 }
898 if (count == 3 && namesame(par[2], x_("geometry")) == 0)
899 {
900 /* delete ports in selected area */
901 np = us_getareabounds(&lx, &hx, &ly, &hy);
902 if (np == NONODEPROTO)
903 {
904 us_abortcommand(_("Outline an area first"));
905 return;
906 }
907
908 /* get the necessary polygon */
909 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
910
911 /* remove highlighting */
912 us_pushhighlight();
913 us_clearhighlightcount();
914
915 deleted = 0;
916 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
917 {
918 i = 0;
919 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = nextpe)
920 {
921 nextpe = pe->nextportexpinst;
922 shapeportpoly(ni, pe->proto, poly, FALSE);
923 getcenter(poly, &x, &y);
924 if (x < lx || x > hx || y < ly || y > hy) continue;
925 ttyputmsg(_("Deleting port %s"), pe->exportproto->protoname);
926 if (i == 0) startobjectchange((INTBIG)ni, VNODEINST);
927 if (killportproto(np, pe->exportproto))
928 ttyputerr(_("killportproto error"));
929 i = 1;
930 deleted++;
931 }
932 if (i != 0) endobjectchange((INTBIG)ni, VNODEINST);
933 }
934
935 /* restore highlighting */
936 us_pophighlight(FALSE);
937 if (deleted == 0) ttyputmsg(_("No exports are in the selected area"));
938 return;
939 }
940 if (count == 3 && namesame(par[2], x_("all")) == 0)
941 {
942 g = us_gethighlighted(WANTNODEINST, 0, 0);
943 if (g[0] == NOGEOM)
944 {
945 us_abortcommand(_("Must first select nodes with exports"));
946 return;
947 }
948
949 /* remove highlighting */
950 us_pushhighlight();
951 us_clearhighlightcount();
952
953 /* delete ports from all selected node */
954 deleted = 0;
955 for(i=0; g[i] != NOGEOM; i++)
956 {
957 ni = g[i]->entryaddr.ni;
958 if (ni->firstportexpinst == NOPORTEXPINST) continue;
959
960 /* remove the port(s) */
961 startobjectchange((INTBIG)ni, VNODEINST);
962 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = nextpe)
963 {
964 nextpe = pe->nextportexpinst;
965 ttyputmsg(_("Deleting export %s"), pe->exportproto->protoname);
966 if (killportproto(ni->parent, pe->exportproto))
967 ttyputerr(_("killportproto error"));
968 deleted++;
969 }
970 endobjectchange((INTBIG)ni, VNODEINST);
971 }
972
973 /* restore highlighting */
974 us_pophighlight(FALSE);
975 if (deleted == 0) ttyputmsg(_("No exports are on the selected nodes"));
976 return;
977 }
978
979 /* delete only the selected port */
980 high = us_getonehighlight();
981 if (high == NOHIGHLIGHT) return;
982 if ((high->status&HIGHTYPE) == HIGHTEXT)
983 {
984 if (high->fromvar != NOVARIABLE || high->fromport == NOPORTPROTO)
985 {
986 us_abortcommand(_("Selected text must be a port name"));
987 return;
988 }
989 ni = high->fromgeom->entryaddr.ni;
990 ppt = high->fromport;
991 } else
992 {
993 ni = (NODEINST *)us_getobject(VNODEINST, FALSE);
994 if (ni == NONODEINST) return;
995 ppt = NOPORTPROTO;
996 }
997
998 /* first see if there is a port on this nodeinst */
999 if (ni->firstportexpinst == NOPORTEXPINST)
1000 {
1001 us_abortcommand(_("No exports on this node"));
1002 return;
1003 }
1004
1005 /* disallow port action if lock is on */
1006 if (us_cantedit(ni->parent, NONODEINST, TRUE)) return;
1007
1008 /* get the specification details */
1009 pp = us_portdetails(ppt, count-2, &par[2], ni, &bits, &mask, TRUE, x_(""), &refname);
1010 if (pp == NOPORTPROTO) return;
1011
1012 /* remove highlighting */
1013 us_pushhighlight();
1014 us_clearhighlightcount();
1015
1016 /* remove the port(s) */
1017 startobjectchange((INTBIG)ni, VNODEINST);
1018 us_undoportproto(ni, pp);
1019 endobjectchange((INTBIG)ni, VNODEINST);
1020
1021 /* restore highlighting */
1022 us_pophighlight(FALSE);
1023
1024 ttyputverbose(M_("Port %s deleted"), pp->protoname);
1025 return;
1026 }
1027
1028 if (namesamen(pt, x_("export"), l) == 0 && l >= 1)
1029 {
1030 ni = (NODEINST *)us_getobject(VNODEINST, FALSE);
1031 if (ni == NONODEINST) return;
1032
1033 /* disallow port action if lock is on */
1034 if (us_cantedit(ni->parent, NONODEINST, TRUE)) return;
1035
1036 if (count <= 1)
1037 {
1038 count = ttygetparam(M_("Port name: "), &us_portep, MAXPARS-1, &par[1])+1;
1039 if (count <= 1)
1040 {
1041 us_abortedmsg();
1042 return;
1043 }
1044 }
1045
1046 /* check name for validity */
1047 pt = par[1];
1048 while (*pt == ' ') pt++;
1049 if (*pt == 0)
1050 {
1051 us_abortcommand(_("Null name"));
1052 return;
1053 }
1054
1055 /* find a unique port name */
1056 portname = us_uniqueportname(pt, ni->parent);
1057 if (namesame(portname, pt) != 0)
1058 ttyputmsg(_("Already a port called %s, calling this %s"), pt, portname);
1059
1060 /* get the specification details */
1061 pp = us_portdetails(NOPORTPROTO, count-2, &par[2], ni, &bits, &mask, FALSE, pt, &refname);
1062 if (pp == NOPORTPROTO) return;
1063
1064 /* save highlighting */
1065 us_pushhighlight();
1066 us_clearhighlightcount();
1067
1068 /* make the port */
1069 pp = us_makenewportproto(ni->parent, ni, pp, portname, mask, bits, pp->textdescript);
1070 if (*refname != 0)
1071 setval((INTBIG)pp, VPORTPROTO, x_("EXPORT_reference_name"), (INTBIG)refname, VSTRING);
1072
1073 /* restore highlighting */
1074 us_pophighlight(FALSE);
1075
1076 ttyputverbose(M_("Port %s created"), pp->protoname);
1077 return;
1078 }
1079
1080 if (namesamen(pt, x_("change"), l) == 0 && l >= 1)
1081 {
1082 high = us_getonehighlight();
1083 if (high == NOHIGHLIGHT) return;
1084 if ((high->status&HIGHTYPE) == HIGHTEXT)
1085 {
1086 if (high->fromvar != NOVARIABLE || high->fromport == NOPORTPROTO)
1087 {
1088 us_abortcommand(_("Selected text must be a port name"));
1089 return;
1090 }
1091 ni = high->fromgeom->entryaddr.ni;
1092 ppt = high->fromport;
1093 } else
1094 {
1095 ni = (NODEINST *)us_getobject(VNODEINST, FALSE);
1096 if (ni == NONODEINST) return;
1097 ppt = NOPORTPROTO;
1098 }
1099
1100 /* disallow port action if lock is on */
1101 if (us_cantedit(ni->parent, NONODEINST, TRUE)) return;
1102
1103 /* get the specification details */
1104 pp = us_portdetails(ppt, count-1, &par[1], ni, &bits, &mask, TRUE, x_(""), &refname);
1105 if (pp == NOPORTPROTO) return;
1106
1107 /* change the port characteristics */
1108 newbits = pp->userbits;
1109 if ((mask&STATEBITS) != 0)
1110 newbits = (newbits & ~STATEBITS) | (bits & STATEBITS);
1111 if ((mask&PORTDRAWN) != 0)
1112 newbits = (newbits & ~PORTDRAWN) | (bits & PORTDRAWN);
1113 if ((mask&BODYONLY) != 0)
1114 newbits = (newbits & ~BODYONLY) | (bits & BODYONLY);
1115 setval((INTBIG)pp, VPORTPROTO, x_("userbits"), newbits, VINTEGER);
1116
1117 /* propagate the change information up the hierarchy */
1118 changeallports(pp);
1119
1120 infstr = initinfstr();
1121 formatinfstr(infstr, _("Port '%s'"), pp->protoname);
1122 if ((pp->userbits&STATEBITS) == 0)
1123 addstringtoinfstr(infstr, _(" has no characteristics")); else
1124 {
1125 formatinfstr(infstr, _(" is %s"), describeportbits(pp->userbits));
1126 }
1127 formatinfstr(infstr, _(" (label %s"), us_describetextdescript(pp->textdescript));
1128 if ((pp->userbits&PORTDRAWN) != 0) addstringtoinfstr(infstr, _(",always-drawn"));
1129 if ((pp->userbits&BODYONLY) != 0) addstringtoinfstr(infstr, _(",only-on-body"));
1130 addstringtoinfstr(infstr, x_(") "));
1131 ttyputmsg(x_("%s"), returninfstr(infstr));
1132 return;
1133 }
1134
1135 ttyputbadusage(x_("port"));
1136 }
1137
us_quit(INTBIG count,CHAR * par[])1138 void us_quit(INTBIG count, CHAR *par[])
1139 {
1140 if (us_preventloss(NOLIBRARY, 0, TRUE)) return;
1141 bringdown();
1142 }
1143