1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usrhigh.c
6 * User interface tool: object highlighting
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "global.h"
33 #include "egraphics.h"
34 #include "usr.h"
35 #include "tech.h"
36 #include "tecgen.h"
37 #include "tecart.h"
38
39 #define DOTRADIUS 4 /* size of dots in nodes when highlighting networks */
40
41 extern GRAPHICS us_box, us_arbit, us_hbox;
42
43 /* working memory for "us_gethighlighted()" */
44 static GEOM **us_gethighlist;
45 static INTBIG us_gethighlistsize = 0;
46 static INTBIG us_selectedtexttotal = 0; /* size of selected text item list */
47 static CHAR **us_selectedtextlist; /* the selected text items */
48
49 /* working memory for "us_getallhighlighted()" */
50 static INTBIG *us_getallhighlist;
51 static INTBIG us_getallhighlistsize = 0;
52
53 /* working memory for "us_selectarea()" */
54 static void *us_selectareastringarray = 0;
55
56 /* prototypes for local routines */
57 static void us_makecurrentobject(void);
58 static void us_highlightverbose(GEOM*, PORTPROTO*, INTBIG, NODEPROTO*, POLYGON*);
59 static BOOLEAN us_geommatchestype(GEOM *geom, INTBIG type);
60
61 /*
62 * Routine to free all memory associated with this module.
63 */
us_freehighmemory(void)64 void us_freehighmemory(void)
65 {
66 REGISTER INTBIG i;
67
68 if (us_gethighlistsize != 0) efree((CHAR *)us_gethighlist);
69 if (us_getallhighlistsize != 0) efree((CHAR *)us_getallhighlist);
70 if (us_selectareastringarray != 0) killstringarray(us_selectareastringarray);
71 for(i=0; i<us_selectedtexttotal; i++)
72 if (us_selectedtextlist[i] != 0) efree((CHAR *)us_selectedtextlist[i]);
73 if (us_selectedtexttotal > 0) efree((CHAR *)us_selectedtextlist);
74 }
75
76 /******************** MENU AND WINDOW HIGHLIGHTING ********************/
77
78 /*
79 * routine to highlight a menu entry
80 */
us_highlightmenu(INTBIG x,INTBIG y,INTBIG color)81 void us_highlightmenu(INTBIG x, INTBIG y, INTBIG color)
82 {
83 REGISTER INTBIG xl, yl;
84 INTBIG swid, shei, pwid;
85 WINDOWPART ww;
86 static POLYGON *poly = NOPOLYGON;
87
88 if ((us_tool->toolstate&MENUON) == 0) return;
89
90 /* get polygon */
91 (void)needstaticpolygon(&poly, 5, us_tool->cluster);
92
93 /* set drawing bounds to include menu */
94 if (us_menuframe == NOWINDOWFRAME)
95 {
96 getpaletteparameters(&swid, &shei, &pwid);
97 ww.frame = getwindowframe(TRUE);
98 } else
99 {
100 getwindowframesize(us_menuframe, &swid, &shei);
101 ww.frame = us_menuframe;
102 }
103 ww.screenlx = ww.screenly = ww.uselx = ww.usely = 0;
104 ww.screenhx = ww.usehx = swid-1;
105 ww.screenhy = ww.usehy = shei-1;
106 ww.state = DISPWINDOW;
107 computewindowscale(&ww);
108
109 xl = x * us_menuxsz + us_menulx;
110 yl = y * us_menuysz + us_menuly;
111 maketruerectpoly(xl, xl+us_menuxsz, yl, yl+us_menuysz, poly);
112 poly->desc = &us_box;
113 poly->style = CLOSEDRECT;
114 us_box.col = color;
115 us_showpoly(poly, &ww);
116 }
117
118 /*
119 * routine to highlight window "w" and set current window to this. If
120 * "force" is true, highlight this window even if it is already the
121 * current window.
122 */
us_highlightwindow(WINDOWPART * w,BOOLEAN force)123 void us_highlightwindow(WINDOWPART *w, BOOLEAN force)
124 {
125 if (w == el_curwindowpart && !force) return;
126
127 if (el_curwindowpart != NOWINDOWPART) us_drawwindow(el_curwindowpart, el_colwinbor);
128 if (w != NOWINDOWPART) us_drawwindow(w, el_colhwinbor);
129
130 /* set new window */
131 el_curwindowpart = w;
132 }
133
134 /******************** OBJECT HIGHLIGHTING ********************/
135
136 /*
137 * routine to add "thishigh" to the list of objects that are highlighted.
138 */
us_addhighlight(HIGHLIGHT * thishigh)139 void us_addhighlight(HIGHLIGHT *thishigh)
140 {
141 REGISTER CHAR *str, **list;
142 REGISTER INTBIG i, len, rewritefirst;
143 CHAR *onelist[1];
144 REGISTER VARIABLE *var;
145 HIGHLIGHT oldhigh;
146
147 /* see if anything is currently highlighted */
148 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
149 if (var == NOVARIABLE)
150 {
151 /* nothing highlighted: add this one line */
152 onelist[0] = us_makehighlightstring(thishigh);
153 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)onelist,
154 VSTRING|VISARRAY|(1<<VLENGTHSH)|VDONTSAVE);
155
156 #if SIMTOOL
157 /* if current window is simulating, show equivalent elsewhere */
158 if (el_curwindowpart != NOWINDOWPART && (el_curwindowpart->state&WINDOWSIMMODE) != 0 &&
159 (thishigh->status&HIGHTYPE) == HIGHFROM)
160 {
161 onelist[0] = x_("show-equivalent");
162 telltool(net_tool, 1, onelist);
163 }
164 #endif
165
166 /* set the current node/arc */
167 us_makecurrentobject();
168 return;
169 }
170
171 /* see if it is already highlighted */
172 len = getlength(var);
173 for(i=0; i<len; i++)
174 {
175 if (us_makehighlight(((CHAR **)var->addr)[i], &oldhigh)) continue;
176 if ((oldhigh.status&HIGHTYPE) != (thishigh->status&HIGHTYPE)) continue;
177 if (oldhigh.cell != thishigh->cell) continue;
178 if ((oldhigh.status&HIGHTYPE) == HIGHLINE || (oldhigh.status&HIGHTYPE) == HIGHBBOX)
179 {
180 if (oldhigh.stalx != thishigh->stalx || oldhigh.stahx != thishigh->stahx ||
181 oldhigh.staly != thishigh->staly || oldhigh.stahy != thishigh->stahy) continue;
182 } else
183 {
184 if (oldhigh.fromgeom != thishigh->fromgeom) continue;
185 if ((oldhigh.status&HIGHTYPE) == HIGHTEXT)
186 {
187 if (oldhigh.fromvar != thishigh->fromvar) continue;
188 if (oldhigh.fromport != NOPORTPROTO && thishigh->fromport != NOPORTPROTO &&
189 oldhigh.fromport != thishigh->fromport) continue;
190 }
191 }
192 return;
193 }
194
195 /* process tangent snap points */
196 rewritefirst = 0;
197 if (len == 1 && (oldhigh.status&HIGHSNAP) != 0 && (thishigh->status&HIGHSNAP) != 0 &&
198 ((oldhigh.status&HIGHSNAPTAN) != 0 || (thishigh->status&HIGHSNAPTAN) != 0))
199 {
200 us_adjusttangentsnappoints(&oldhigh, thishigh);
201 if ((oldhigh.status&HIGHSNAPTAN) != 0) rewritefirst = 1;
202 } else if (len == 1 && (oldhigh.status&HIGHSNAP) != 0 && (thishigh->status&HIGHSNAP) != 0 &&
203 ((oldhigh.status&HIGHSNAPPERP) != 0 || (thishigh->status&HIGHSNAPPERP) != 0))
204 {
205 us_adjustperpendicularsnappoints(&oldhigh, thishigh);
206 if ((oldhigh.status&HIGHSNAPPERP) != 0) rewritefirst = 1;
207 }
208
209 /* convert the highlight module to a string */
210 str = us_makehighlightstring(thishigh);
211
212 /* things are highlighted: build a new list */
213 list = (CHAR **)emalloc(((len+1) * (sizeof (CHAR *))), el_tempcluster);
214 if (list == 0) return;
215 for(i=0; i<len; i++)
216 {
217 if (i == 0 && rewritefirst != 0)
218 {
219 (void)allocstring(&list[i], us_makehighlightstring(&oldhigh), el_tempcluster);
220 } else
221 {
222 (void)allocstring(&list[i], ((CHAR **)var->addr)[i], el_tempcluster);
223 }
224 }
225 (void)allocstring(&list[len], str, el_tempcluster);
226
227 /* save the new list */
228 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
229 VSTRING|VISARRAY|((len+1)<<VLENGTHSH)|VDONTSAVE);
230
231 /* clean up */
232 for(i=0; i<=len; i++) efree(list[i]);
233 efree((CHAR *)list);
234
235 /* set the current node/arc */
236 us_makecurrentobject();
237 }
238
239 /*
240 * routine to delete "thishigh" from the list of objects that are highlighted.
241 */
us_delhighlight(HIGHLIGHT * thishigh)242 void us_delhighlight(HIGHLIGHT *thishigh)
243 {
244 REGISTER CHAR **list;
245 REGISTER INTBIG i, len, j, thish;
246 REGISTER VARIABLE *var;
247 HIGHLIGHT oldhigh;
248
249 /* see if anything is currently highlighted */
250 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
251 if (var == NOVARIABLE) return;
252
253 /* see if it is highlighted */
254 len = getlength(var);
255 for(thish=0; thish<len; thish++)
256 {
257 if (us_makehighlight(((CHAR **)var->addr)[thish], &oldhigh)) continue;
258 if ((oldhigh.status&HIGHTYPE) != (thishigh->status&HIGHTYPE)) continue;
259 if (oldhigh.cell != thishigh->cell) continue;
260 if ((oldhigh.status&HIGHTYPE) == HIGHLINE || (oldhigh.status&HIGHTYPE) == HIGHBBOX)
261 {
262 if (oldhigh.stalx != thishigh->stalx || oldhigh.stahx != thishigh->stahx ||
263 oldhigh.staly != thishigh->staly || oldhigh.stahy != thishigh->stahy) continue;
264 } else
265 {
266 if (oldhigh.fromgeom != thishigh->fromgeom) continue;
267 if ((oldhigh.status&HIGHTYPE) == HIGHTEXT)
268 {
269 if (oldhigh.fromvar != thishigh->fromvar) continue;
270 if (oldhigh.fromport != NOPORTPROTO && thishigh->fromport != NOPORTPROTO &&
271 oldhigh.fromport != thishigh->fromport) continue;
272 }
273 }
274 break;
275 }
276 if (thish >= len) return;
277
278 /* removing highlight: build a new list */
279 if (len <= 1)
280 {
281 (void)delvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey);
282 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
283 return;
284 }
285 list = (CHAR **)emalloc(((len-1) * (sizeof (CHAR *))), el_tempcluster);
286 if (list == 0) return;
287 for(j=i=0; i<len; i++)
288 {
289 if (i == thish) continue;
290 (void)allocstring(&list[j], ((CHAR **)var->addr)[i], el_tempcluster);
291 j++;
292 }
293
294 /* save the new list */
295 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
296 VSTRING|VISARRAY|((len-1)<<VLENGTHSH)|VDONTSAVE);
297 us_makecurrentobject();
298
299 /* clean up */
300 for(i=0; i<len-1; i++) efree(list[i]);
301 efree((CHAR *)list);
302 }
303
us_clearhighlightcount(void)304 void us_clearhighlightcount(void)
305 {
306 REGISTER VARIABLE *var;
307
308 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
309 if (var != NOVARIABLE)
310 (void)delvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey);
311 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
312 }
313
314 /*
315 * routine to add highlight module "newhigh" to the display. If "findpoint" is nonzero,
316 * find the closest vertex/line to the cursor. If "extrainfo" is nonzero, highlight
317 * with extra information. If "findmore" is nonzero, add this highlight rather
318 * than replacing. If "nobox" is nonzero, do not draw the basic box.
319 */
us_setfind(HIGHLIGHT * newhigh,INTBIG findpoint,INTBIG extrainfo,INTBIG findmore,INTBIG nobox)320 void us_setfind(HIGHLIGHT *newhigh, INTBIG findpoint, INTBIG extrainfo, INTBIG findmore, INTBIG nobox)
321 {
322 REGISTER NODEINST *ni;
323 REGISTER VARIABLE *var;
324 REGISTER INTBIG x, y, d, bestdist, bestpoint, i, total;
325 INTBIG xp, yp, xc, yc;
326 XARRAY trans;
327
328 /* set to highlight only one one object */
329 if (findmore == 0) us_clearhighlightcount();
330
331 /* find the vertex/line if this is a nodeinst and it was requested */
332 if (findpoint != 0 && (newhigh->status&HIGHTYPE) != HIGHTEXT &&
333 newhigh->fromgeom->entryisnode)
334 {
335 ni = newhigh->fromgeom->entryaddr.ni;
336 var = gettrace(ni);
337 } else var = NOVARIABLE;
338 if (var == NOVARIABLE) bestpoint = 0; else
339 {
340 (void)getxy(&xc, &yc);
341 makerot(ni, trans);
342 total = getlength(var) / 2;
343 x = (ni->highx + ni->lowx) / 2; y = (ni->highy + ni->lowy) / 2;
344 for(i=0; i<total; i++)
345 {
346 xform(((INTBIG *)var->addr)[i*2]+x, ((INTBIG *)var->addr)[i*2+1]+y, &xp, &yp, trans);
347 d = abs(xp-xc) + abs(yp-yc);
348 if (i == 0) bestdist = d + 1;
349 if (d > bestdist) continue;
350 bestdist = d; bestpoint = i;
351 }
352 bestpoint++;
353 }
354
355 /* load the highlight structure */
356 newhigh->status |= extrainfo;
357 newhigh->frompoint = bestpoint;
358 if (nobox != 0) newhigh->status |= HIGHNOBOX;
359
360 /* show the highlighting */
361 us_addhighlight(newhigh);
362 }
363
364 /*
365 * Routine to select the area (slx <= X <= shx, sly <= Y <= shy) in cell "np".
366 * If "special" is nonzero, select "hard-to-select" items.
367 * If "selport" is nonzero, select ports.
368 * If "nobbox" is nonzero, do not show bounding box.
369 * Returns the number of things selected, and loads the string array "highlist"
370 * with the highlight information.
371 */
us_selectarea(NODEPROTO * np,INTBIG slx,INTBIG shx,INTBIG sly,INTBIG shy,INTBIG special,INTBIG selport,INTBIG nobbox,CHAR *** highlist)372 INTBIG us_selectarea(NODEPROTO *np, INTBIG slx, INTBIG shx, INTBIG sly, INTBIG shy,
373 INTBIG special, INTBIG selport, INTBIG nobbox, CHAR ***highlist)
374 {
375 REGISTER INTBIG i, j, k, search, slop, foundtext;
376 INTBIG xcur, ycur, xc, yc, xw, yw, style, count;
377 BOOLEAN checktext;
378 REGISTER GEOM *geom;
379 REGISTER NODEINST *ni;
380 REGISTER ARCINST *ai;
381 REGISTER BOOLEAN accept;
382 PORTPROTO *port, *lastport;
383 VARIABLE *var, *varnoeval, *lastvar;
384 XARRAY trans;
385 static POLYGON *poly = NOPOLYGON;
386 HIGHLIGHT newhigh, newhightext;
387
388 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
389 if (us_selectareastringarray == 0) us_selectareastringarray = newstringarray(us_tool->cluster);
390 clearstrings(us_selectareastringarray);
391
392 /* build a list of objects to highlight */
393 newhigh.cell = np;
394 newhigh.fromport = NOPORTPROTO;
395 newhigh.fromvar = NOVARIABLE;
396 newhigh.fromvarnoeval = NOVARIABLE;
397 newhigh.frompoint = 0;
398
399 newhightext.status = HIGHTEXT;
400 newhightext.cell = np;
401 newhightext.fromvarnoeval = NOVARIABLE;
402 newhightext.frompoint = 0;
403
404 if ((us_useroptions&HIDETXTCELL) == 0)
405 {
406 for(i=0; i<np->numvar; i++)
407 {
408 var = &np->firstvar[i];
409 if ((var->type&VDISPLAY) == 0) continue;
410 newhightext.fromgeom = NOGEOM;
411 newhightext.fromport = NOPORTPROTO;
412 newhightext.fromvarnoeval = var;
413 newhightext.fromvar = evalvar(newhightext.fromvarnoeval, (INTBIG)np, VNODEPROTO);
414 us_gethightextcenter(&newhightext, &xc, &yc, &style);
415 us_gethightextsize(&newhightext, &xw, &yw, el_curwindowpart);
416 if ((us_useroptions&MUSTENCLOSEALL) != 0)
417 {
418 /* accept if it is inside the area */
419 if (xc-xw/2 < slx || xc+xw/2 > shx ||
420 yc-yw/2 < sly || yc+yw/2 > shy) continue;
421 } else
422 {
423 /* accept if it touches the area */
424 if (xc+xw/2 < slx || xc-xw/2 > shx ||
425 yc+yw/2 < sly || yc-yw/2 > shy) continue;
426 }
427 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhightext));
428 }
429 }
430 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
431 {
432 if ((ni->userbits&NHASFARTEXT) == 0) continue;
433 if (ni->proto == gen_invispinprim)
434 {
435 if ((us_useroptions&HIDETXTNONLAY) != 0) continue;
436 } else
437 {
438 if ((us_useroptions&HIDETXTNODE) != 0) continue;
439 }
440 for(i=0; i<ni->numvar; i++)
441 {
442 var = &ni->firstvar[i];
443 if ((var->type&VDISPLAY) == 0) continue;
444 newhightext.fromgeom = ni->geom;
445 newhightext.fromport = NOPORTPROTO;
446 newhightext.fromvarnoeval = var;
447 newhightext.fromvar = evalvar(newhightext.fromvarnoeval, (INTBIG)ni, VNODEINST);
448 us_gethightextcenter(&newhightext, &xc, &yc, &style);
449 us_gethightextsize(&newhightext, &xw, &yw, el_curwindowpart);
450 if ((us_useroptions&MUSTENCLOSEALL) != 0)
451 {
452 /* accept if it is inside the area */
453 if (xc-xw/2 < slx || xc+xw/2 > shx ||
454 yc-yw/2 < sly || yc+yw/2 > shy) continue;
455 } else
456 {
457 /* accept if it touches the area */
458 if (xc+xw/2 < slx || xc-xw/2 > shx ||
459 yc+yw/2 < sly || yc-yw/2 > shy) continue;
460 }
461 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhightext));
462 }
463 }
464 if ((us_useroptions&HIDETXTARC) == 0)
465 {
466 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
467 {
468 if ((ai->userbits&AHASFARTEXT) == 0) continue;
469 for(i=0; i<ai->numvar; i++)
470 {
471 var = &ai->firstvar[i];
472 if ((var->type&VDISPLAY) == 0) continue;
473 newhightext.fromgeom = ai->geom;
474 newhightext.fromport = NOPORTPROTO;
475 newhightext.fromvarnoeval = var;
476 newhightext.fromvar = evalvar(newhightext.fromvarnoeval, (INTBIG)ai, VARCINST);
477 us_gethightextcenter(&newhightext, &xc, &yc, &style);
478 us_gethightextsize(&newhightext, &xw, &yw, el_curwindowpart);
479 if ((us_useroptions&MUSTENCLOSEALL) != 0)
480 {
481 /* accept if it is inside the area */
482 if (xc-xw/2 < slx || xc+xw/2 > shx ||
483 yc-yw/2 < sly || yc+yw/2 > shy) continue;
484 } else
485 {
486 /* accept if it touches the area */
487 if (xc+xw/2 < slx || xc-xw/2 > shx ||
488 yc+yw/2 < sly || yc-yw/2 > shy) continue;
489 }
490 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhightext));
491 }
492 }
493 }
494 slop = FARTEXTLIMIT * lambdaofcell(np);
495 search = initsearch(slx-slop, shx+slop, sly-slop, shy+slop, np);
496 while ((geom = nextobject(search)) != NOGEOM)
497 {
498 if (geom->entryisnode)
499 {
500 ni = geom->entryaddr.ni;
501
502 /* don't find cells if not requested */
503 if (special == 0 && (us_useroptions&NOINSTANCESELECT) != 0 &&
504 ni->proto->primindex == 0) continue;
505
506 /* do not include hard-to-find nodes if not selecting specially */
507 if (special == 0 && (ni->userbits&HARDSELECTN) != 0) continue;
508
509 /* do not include primitives that have all layers invisible */
510 if (ni->proto->primindex != 0 && (ni->proto->userbits&NINVISIBLE) != 0)
511 continue;
512
513 /* include all displayable variables */
514 foundtext = 0;
515
516 /* ignore text if invisible */
517 checktext = TRUE;
518 if (ni->proto == gen_invispinprim)
519 {
520 if ((us_useroptions&HIDETXTNONLAY) != 0) checktext = FALSE;
521 } else
522 {
523 if ((us_useroptions&HIDETXTNODE) != 0) checktext = FALSE;
524 }
525 if (checktext)
526 {
527 /* compute threshold for direct hits */
528 lastvar = NOVARIABLE;
529 lastport = NOPORTPROTO;
530 if ((ni->userbits&NHASFARTEXT) == 0)
531 {
532 us_initnodetext(ni, special, el_curwindowpart);
533 for(;;)
534 {
535 if (us_getnodetext(ni, el_curwindowpart, poly, &var, &varnoeval, &port)) break;
536 accept = FALSE;
537 if ((us_useroptions&MUSTENCLOSEALL) != 0)
538 {
539 /* accept if it is inside the area */
540 for(k=0; k<poly->count; k++)
541 {
542 if (poly->xv[k] < slx || poly->xv[k] > shx ||
543 poly->yv[k] < sly || poly->yv[k] > shy) break;
544 }
545 if (k >= poly->count) accept = TRUE;
546 } else
547 {
548 /* accept if it touches the area */
549 if (polyinrect(poly, slx, shx, sly, shy)) accept = TRUE;
550 }
551 if (accept)
552 {
553 if (varnoeval == lastvar && port == lastport) continue;
554 lastvar = varnoeval;
555 lastport = port;
556 newhightext.fromgeom = geom;
557 newhightext.fromport = port;
558 newhightext.fromvarnoeval = varnoeval;
559 newhightext.fromvar = var;
560 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhightext));
561 }
562 foundtext++;
563 }
564 }
565 }
566
567 /* ignore invisible primitive if text on it was selected */
568 if (foundtext != 0 && ni->proto == gen_invispinprim) continue;
569
570 /* do not include "edge select" primitives that are outside the area */
571 if (ni->proto->primindex != 0 &&
572 (ni->proto->userbits&NEDGESELECT) != 0)
573 {
574 i = nodepolys(ni, 0, NOWINDOWPART);
575 makerot(ni, trans);
576 for(j=0; j<i; j++)
577 {
578 shapenodepoly(ni, j, poly);
579 if ((poly->desc->colstyle&INVISIBLE) == 0)
580 {
581 xformpoly(poly, trans);
582 accept = FALSE;
583 if ((us_useroptions&MUSTENCLOSEALL) != 0)
584 {
585 /* accept if it is inside the area */
586 for(k=0; k<poly->count; k++)
587 {
588 if (poly->xv[k] < slx || poly->xv[k] > shx ||
589 poly->yv[k] < sly || poly->yv[k] > shy) break;
590 }
591 if (k >= poly->count) accept = TRUE;
592 } else
593 {
594 /* accept if it touches the area */
595 if (polyinrect(poly, slx, shx, sly, shy)) accept = TRUE;
596 }
597 if (!accept) break;
598 }
599 }
600 if (j < i) continue;
601 }
602 } else
603 {
604 ai = geom->entryaddr.ai;
605
606 /* do not include hard-to-find arcs if not selecting specially */
607 if (special == 0 && (ai->userbits&HARDSELECTA) != 0) continue;
608
609 /* do not include arcs that have all layers invisible */
610 if ((ai->proto->userbits&AINVISIBLE) != 0) continue;
611
612 /* include all displayable variables */
613 if ((us_useroptions&HIDETXTARC) == 0)
614 {
615 if ((ai->userbits&AHASFARTEXT) == 0)
616 {
617 for(i=0; i<ai->numvar; i++)
618 {
619 var = &ai->firstvar[i];
620 if ((var->type&VDISPLAY) == 0) continue;
621 newhightext.fromgeom = geom;
622 newhightext.fromport = NOPORTPROTO;
623 newhightext.fromvarnoeval = var;
624 newhightext.fromvar = evalvar(newhightext.fromvarnoeval, (INTBIG)ai, VARCINST);
625 us_gethightextcenter(&newhightext, &xc, &yc, &style);
626 us_gethightextsize(&newhightext, &xw, &yw, el_curwindowpart);
627 if ((us_useroptions&MUSTENCLOSEALL) != 0)
628 {
629 /* accept if it is inside the area */
630 if (xc-xw/2 < slx || xc+xw/2 > shx ||
631 yc-yw/2 < sly || yc+yw/2 > shy) continue;
632 } else
633 {
634 /* accept if it touches the area */
635 if (xc+xw/2 < slx || xc-xw/2 > shx ||
636 yc+yw/2 < sly || yc-yw/2 > shy) continue;
637 }
638 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhightext));
639 }
640 }
641 }
642
643 /* do not include "edge select" arcs that are outside the area */
644 if ((ai->proto->userbits&AEDGESELECT) != 0)
645 {
646 ai = geom->entryaddr.ai;
647 i = arcpolys(ai, NOWINDOWPART);
648 for(j=0; j<i; j++)
649 {
650 shapearcpoly(ai, j, poly);
651 if ((poly->desc->colstyle&INVISIBLE) == 0)
652 {
653 accept = FALSE;
654 if ((us_useroptions&MUSTENCLOSEALL) != 0)
655 {
656 /* accept if it is inside the area */
657 for(k=0; k<poly->count; k++)
658 {
659 if (poly->xv[k] < slx || poly->xv[k] > shx ||
660 poly->yv[k] < sly || poly->yv[k] > shy) break;
661 }
662 if (k >= poly->count) accept = TRUE;
663 } else
664 {
665 /* accept if it touches the area */
666 if (polyinrect(poly, slx, shx, sly, shy)) accept = TRUE;
667 }
668 if (!accept) break;
669 }
670 }
671 if (j < i) continue;
672 }
673 }
674
675 /* eliminate objects that aren't really in the selected area */
676 if (!us_geominrect(geom, slx, shx, sly, shy)) continue;
677
678 newhigh.status = HIGHFROM;
679 if (nobbox != 0) newhigh.status |= HIGHNOBOX;
680 newhigh.fromgeom = geom;
681
682 /* add snapping information if requested */
683 if ((us_state&SNAPMODE) != SNAPMODENONE)
684 {
685 (void)getxy(&xcur, &ycur);
686 us_selectsnap(&newhigh, xcur, ycur);
687 }
688
689 /* select the first port if ports are requested and node is artwork */
690 newhigh.fromport = NOPORTPROTO;
691 if (selport != 0 && geom->entryisnode &&
692 geom->entryaddr.ni->proto->primindex != 0 &&
693 geom->entryaddr.ni->proto->tech == art_tech)
694 newhigh.fromport = geom->entryaddr.ni->proto->firstportproto;
695 addtostringarray(us_selectareastringarray, us_makehighlightstring(&newhigh));
696 }
697 *highlist = getstringarray(us_selectareastringarray, &count);
698 return(count);
699 }
700
701 /*
702 * routine to demand a specified type of highlighted object (VNODEINST or
703 * VARCINST, according to "type") and return its address. If "canbetext"
704 * is true, the highlighted object can be a text object on the requested
705 * type. If the specified object is not currently highlighted, an error is
706 * printed and the routine returns -1.
707 */
us_getobject(INTBIG type,BOOLEAN canbetext)708 UINTBIG us_getobject(INTBIG type, BOOLEAN canbetext)
709 {
710 HIGHLIGHT high;
711 REGISTER VARIABLE *var;
712 REGISTER INTBIG len, i;
713 REGISTER BOOLEAN notone;
714 REGISTER GEOM *onegeom;
715
716 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
717 if (var == NOVARIABLE) len = 0; else
718 len = getlength(var);
719 notone = FALSE;
720 onegeom = NOGEOM;
721 for(i=0; i<len; i++)
722 {
723 if (us_makehighlight(((CHAR **)var->addr)[i], &high))
724 {
725 us_abortcommand(_("Highlight unintelligible"));
726 return((UINTBIG)-1);
727 }
728 if ((high.status&HIGHTYPE) == HIGHTEXT && !canbetext) continue;
729 if (high.fromgeom == NOGEOM)
730 {
731 notone = TRUE;
732 break;
733 }
734 if (onegeom == NOGEOM) onegeom = high.fromgeom;
735 if (high.fromgeom != onegeom)
736 {
737 notone = TRUE;
738 break;
739 }
740 }
741 if (!notone && onegeom != NOGEOM)
742 {
743 if (onegeom->entryisnode)
744 {
745 if (type != VNODEINST) notone = TRUE;
746 } else
747 {
748 if (type != VARCINST) notone = TRUE;
749 }
750 }
751 if (notone || onegeom == NOGEOM)
752 {
753 if (type == VARCINST) us_abortcommand(_("Select an arc")); else
754 us_abortcommand(_("Select a node"));
755 return((UINTBIG)-1);
756 }
757
758 /* set the current position */
759 return((UINTBIG)onegeom->entryaddr.blind);
760 }
761
762 /*
763 * routine to return the one object currently highlighted. If no objects
764 * are highlighted or many are, an error is printed and the routine returns
765 * NOHIGHLIGHT.
766 */
us_getonehighlight(void)767 HIGHLIGHT *us_getonehighlight(void)
768 {
769 static HIGHLIGHT high;
770 REGISTER VARIABLE *var;
771 REGISTER GEOM *onegeom;
772 REGISTER INTBIG len, i;
773 REGISTER BOOLEAN notone;
774
775 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
776 if (var == NOVARIABLE) len = 0; else
777 len = getlength(var);
778 notone = FALSE;
779 onegeom = NOGEOM;
780 for(i=0; i<len; i++)
781 {
782 if (us_makehighlight(((CHAR **)var->addr)[i], &high))
783 {
784 us_abortcommand(_("Highlight unintelligible"));
785 return(NOHIGHLIGHT);
786 }
787 if (high.fromgeom == NOGEOM)
788 {
789 notone = TRUE;
790 break;
791 }
792 if (onegeom == NOGEOM) onegeom = high.fromgeom;
793 if (high.fromgeom != onegeom)
794 {
795 notone = TRUE;
796 break;
797 }
798 }
799 if (notone || onegeom == NOGEOM)
800 {
801 us_abortcommand(_("Must select one node or arc"));
802 return(NOHIGHLIGHT);
803 }
804 return(&high);
805 }
806
807 /*
808 * routine to get the two nodes that are selected and their ports.
809 * If there are not two nodes selected, the routine returns true.
810 */
us_gettwoobjects(GEOM ** firstgeom,PORTPROTO ** firstport,GEOM ** secondgeom,PORTPROTO ** secondport)811 BOOLEAN us_gettwoobjects(GEOM **firstgeom, PORTPROTO **firstport, GEOM **secondgeom,
812 PORTPROTO **secondport)
813 {
814 REGISTER VARIABLE *var;
815 HIGHLIGHT newhigh;
816 REGISTER INTBIG len, i;
817
818 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
819 if (var == NOVARIABLE) return(TRUE);
820 len = getlength(var);
821 *firstgeom = *secondgeom = NOGEOM;
822 for(i=0; i<len; i++)
823 {
824 (void)us_makehighlight(((CHAR **)var->addr)[i], &newhigh);
825 if ((newhigh.status&HIGHFROM) != 0)
826 {
827 if (*firstgeom == NOGEOM)
828 {
829 *firstgeom = newhigh.fromgeom;
830 *firstport = newhigh.fromport;
831 } else if (*secondgeom == NOGEOM)
832 {
833 *secondgeom = newhigh.fromgeom;
834 *secondport = newhigh.fromport;
835 } else return(TRUE);
836 }
837 }
838 if (*firstgeom != NOGEOM && *secondgeom != NOGEOM) return(FALSE);
839 return(TRUE);
840 }
841
842 /*
843 * routine to get a list of all objects that are highlighted, build an array
844 * of them, and return the array.
845 * If "type" is WANTNODEINST, only the highlighted nodes are returned.
846 * If "type" is WANTARCINST, only the highlighted arcs are returned.
847 * if "type" is WANTNODEINST|WANTARCINST, all highlighted objects are returned.
848 * The list is terminated with the value NOGEOM.
849 * If "textcount" and "textinfo" are nonzero, they are set to the number of
850 * text objects that are highlighted (and the highlight descriptors for each).
851 * When text objects are requested, those on selected nodes or arcs are ignored.
852 *
853 * As an indication of the nodes that are selected, each node's "temp1" field is
854 * set to nonzero if it is selected (but not if text on it is selected).
855 * This is used by "usrtrack.c:us_finddoibegin()" and by "usrcomln.c:us_move()".
856 */
us_gethighlighted(INTBIG type,INTBIG * textcount,CHAR *** textinfo)857 GEOM **us_gethighlighted(INTBIG type, INTBIG *textcount, CHAR ***textinfo)
858 {
859 HIGHLIGHT high;
860 REGISTER VARIABLE *var;
861 REGISTER INTBIG total, len, i, j, k, newcount, numtext, lx, hx, ly, hy,
862 textonnode, search;
863 REGISTER GEOM *geom;
864 REGISTER NODEPROTO *np;
865 REGISTER NODEINST *ni;
866 REGISTER ARCINST *ai;
867 REGISTER CHAR **newtext;
868 static GEOM *nulllist[1];
869 static POLYGON *poly = NOPOLYGON;
870 XARRAY trans;
871
872 if (textcount != 0) *textcount = 0;
873 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
874 if (var == NOVARIABLE)
875 {
876 nulllist[0] = NOGEOM;
877 return(nulllist);
878 }
879
880 /* first search to see how many objects there are */
881 len = getlength(var);
882 numtext = 0;
883 total = 0;
884 for(i=0; i<len; i++)
885 {
886 (void)us_makehighlight(((CHAR **)var->addr)[i], &high);
887 if ((high.status&HIGHTYPE) == HIGHFROM)
888 if (us_geommatchestype(high.fromgeom, type)) total++;
889 if ((high.status&HIGHTYPE) == HIGHBBOX)
890 {
891 lx = high.stalx; hx = high.stahx;
892 ly = high.staly; hy = high.stahy;
893 search = initsearch(lx, hx, ly, hy, high.cell);
894 while ((geom = nextobject(search)) != NOGEOM)
895 {
896 if (!us_geommatchestype(geom, type)) continue;
897 if (!us_geominrect(geom, lx, hx, ly, hy)) continue;
898 total++;
899 }
900 }
901
902 /* special case: include in node list if text tied to node and no text requested */
903 if ((high.status&HIGHTYPE) == HIGHTEXT)
904 {
905 if (us_nodemoveswithtext(&high) && textcount == 0)
906 total++;
907 }
908 }
909
910 /* get memory for array of these objects */
911 if (total >= us_gethighlistsize)
912 {
913 if (us_gethighlistsize != 0) efree((CHAR *)us_gethighlist);
914 us_gethighlist = (GEOM **)emalloc(((total+1) * (sizeof (GEOM *))),
915 us_tool->cluster);
916 if (us_gethighlist == 0)
917 {
918 ttyputnomemory();
919 nulllist[0] = NOGEOM;
920 return(nulllist);
921 }
922 us_gethighlistsize = total + 1;
923 }
924
925 /* now place the objects in the list */
926 total = 0;
927 for(i=0; i<len; i++)
928 {
929 (void)us_makehighlight(((CHAR **)var->addr)[i], &high);
930 if ((high.status&HIGHTYPE) == HIGHFROM)
931 if (us_geommatchestype(high.fromgeom, type))
932 {
933 for(j=0; j<total; j++) if (us_gethighlist[j] == high.fromgeom) break;
934 if (j >= total) us_gethighlist[total++] = high.fromgeom;
935 }
936 if ((high.status&HIGHTYPE) == HIGHBBOX)
937 {
938 lx = high.stalx; hx = high.stahx;
939 ly = high.staly; hy = high.stahy;
940 search = initsearch(lx, hx, ly, hy, high.cell);
941 for(;;)
942 {
943 geom = nextobject(search);
944 if (geom == NOGEOM) break;
945
946 /* make sure the object has the desired type */
947 if (!us_geommatchestype(geom, type)) continue;
948
949 /* make sure the object is really in the selection area */
950 if (!us_geominrect(geom, lx, hx, ly, hy)) continue;
951
952 /* make sure the object isn't already in the list */
953 for(j=0; j<total; j++) if (us_gethighlist[j] == geom) break;
954 if (j < total) continue;
955
956 /* check carefully for "edge select" primitives */
957 if (geom->entryisnode)
958 {
959 ni = geom->entryaddr.ni;
960 if (ni->proto->primindex != 0)
961 {
962 if ((ni->proto->userbits&NINVISIBLE) != 0) continue;
963 if ((ni->proto->userbits&NEDGESELECT) != 0)
964 {
965 ni = geom->entryaddr.ni;
966 k = nodepolys(ni, 0, NOWINDOWPART);
967 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
968 makerot(ni, trans);
969 for(j=0; j<k; j++)
970 {
971 shapenodepoly(ni, j, poly);
972 if ((poly->desc->colstyle&INVISIBLE) == 0)
973 {
974 xformpoly(poly, trans);
975 if (!polyinrect(poly, high.stalx, high.stahx,
976 high.staly, high.stahy)) break;
977 }
978 }
979 if (j < k) continue;
980 }
981 }
982 } else
983 {
984 ai = geom->entryaddr.ai;
985 if ((ai->proto->userbits&AINVISIBLE) != 0) continue;
986 if ((ai->proto->userbits&AEDGESELECT) != 0)
987 {
988 k = arcpolys(ai, NOWINDOWPART);
989 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
990 for(j=0; j<k; j++)
991 {
992 shapearcpoly(ai, j, poly);
993 if ((poly->desc->colstyle&INVISIBLE) == 0)
994 {
995 if (!polyinrect(poly, high.stalx, high.stahx,
996 high.staly, high.stahy)) break;
997 }
998 }
999 if (j < k) continue;
1000 }
1001 }
1002
1003 /* add this object to the list */
1004 us_gethighlist[total++] = geom;
1005 }
1006 }
1007 if ((high.status&HIGHTYPE) == HIGHTEXT)
1008 {
1009 if (us_nodemoveswithtext(&high) && textcount == 0)
1010 {
1011 /* include in node list if text tied to node and no text requested */
1012 us_gethighlist[total++] = high.fromgeom;
1013 } else
1014 {
1015 if (textcount != 0)
1016 {
1017 if (numtext >= us_selectedtexttotal)
1018 {
1019 newcount = numtext + 5;
1020 newtext = (CHAR **)emalloc(newcount * (sizeof (CHAR *)),
1021 us_tool->cluster);
1022 if (newtext == 0)
1023 {
1024 nulllist[0] = NOGEOM;
1025 return(nulllist);
1026 }
1027 for(j=0; j<us_selectedtexttotal; j++)
1028 newtext[j] = us_selectedtextlist[j];
1029 for( ; j<newcount; j++) newtext[j] = 0;
1030 if (us_selectedtexttotal > 0) efree((CHAR *)us_selectedtextlist);
1031 us_selectedtextlist = newtext;
1032 us_selectedtexttotal = newcount;
1033 }
1034 if (us_selectedtextlist[numtext] == 0)
1035 {
1036 (void)allocstring(&us_selectedtextlist[numtext],
1037 ((CHAR **)var->addr)[i], us_tool->cluster);
1038 } else
1039 {
1040 (void)reallocstring(&us_selectedtextlist[numtext],
1041 ((CHAR **)var->addr)[i], us_tool->cluster);
1042 }
1043 numtext++;
1044 }
1045 }
1046 }
1047 }
1048 us_gethighlist[total] = NOGEOM;
1049 if (textcount != 0 && textinfo != 0)
1050 {
1051 /* mark all nodes (including those touched by highlighted arcs) */
1052 if (us_gethighlist[0] != NOGEOM) np = geomparent(us_gethighlist[0]); else
1053 np = el_curwindowpart->curnodeproto;
1054 if (np != NONODEPROTO)
1055 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1056 ni->temp1 = 0;
1057 if (us_gethighlist[0] != NOGEOM)
1058 {
1059 for(i=0; us_gethighlist[i] != NOGEOM; i++)
1060 {
1061 if (!us_gethighlist[i]->entryisnode)
1062 {
1063 ai = us_gethighlist[i]->entryaddr.ai;
1064 ai->end[0].nodeinst->temp1 = ai->end[1].nodeinst->temp1 = 1;
1065 } else
1066 us_gethighlist[i]->entryaddr.ni->temp1 = 1;
1067 }
1068 }
1069
1070 /* remove nodes listed as text objects */
1071 for(i=0; i<numtext; i++)
1072 {
1073 (void)us_makehighlight(us_selectedtextlist[i], &high);
1074
1075 /* make sure we aren't moving text and object it resides on */
1076 textonnode = 0;
1077 if (high.fromgeom != NOGEOM)
1078 {
1079 if (high.fromgeom->entryisnode)
1080 {
1081 ni = high.fromgeom->entryaddr.ni;
1082 if (ni->temp1 != 0) textonnode = 1;
1083 } else
1084 {
1085 ai = high.fromgeom->entryaddr.ai;
1086 for(j=0; us_gethighlist[j] != NOGEOM; j++)
1087 if (us_gethighlist[j] == ai->geom) break;
1088 if (us_gethighlist[j] != NOGEOM) textonnode = 1;
1089 }
1090 }
1091 if (textonnode == 0) continue;
1092 efree(us_selectedtextlist[i]);
1093 for(j=i; j<numtext-1; j++)
1094 us_selectedtextlist[j] = us_selectedtextlist[j+1];
1095 us_selectedtextlist[numtext-1] = 0;
1096 numtext--;
1097 i--;
1098 }
1099
1100 *textcount = numtext;
1101 *textinfo = us_selectedtextlist;
1102 }
1103 return(us_gethighlist);
1104 }
1105
us_geommatchestype(GEOM * geom,INTBIG type)1106 BOOLEAN us_geommatchestype(GEOM *geom, INTBIG type)
1107 {
1108 if (geom->entryisnode)
1109 {
1110 if ((type&WANTNODEINST) != 0) return(TRUE);
1111 return(FALSE);
1112 }
1113 if ((type&WANTARCINST) != 0) return(TRUE);
1114 return(FALSE);
1115 }
1116
1117 /*
1118 * routine to get a list of all objects that are highlighted (including nodes, arcs,
1119 * and ports), build an array that alternates address and type, and return the array.
1120 * The list is terminated with the type 0.
1121 */
us_getallhighlighted(void)1122 INTBIG *us_getallhighlighted(void)
1123 {
1124 HIGHLIGHT high;
1125 REGISTER VARIABLE *var;
1126 REGISTER INTBIG total, len, i, j, k, lx, hx, ly, hy, search;
1127 REGISTER GEOM *geom;
1128 REGISTER NODEINST *ni;
1129 REGISTER ARCINST *ai;
1130 static INTBIG nulllist[2];
1131 static POLYGON *poly = NOPOLYGON;
1132 XARRAY trans;
1133
1134 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1135 if (var == NOVARIABLE)
1136 {
1137 nulllist[0] = nulllist[1] = 0;
1138 return(nulllist);
1139 }
1140
1141 /* first search to see how many objects there are */
1142 len = getlength(var);
1143 total = 0;
1144 for(i=0; i<len; i++)
1145 {
1146 (void)us_makehighlight(((CHAR **)var->addr)[i], &high);
1147 if ((high.status&HIGHTYPE) == HIGHFROM) total++;
1148 if ((high.status&HIGHTYPE) == HIGHBBOX)
1149 {
1150 search = initsearch(high.stalx, high.stahx, high.staly, high.stahy, high.cell);
1151 while ((geom = nextobject(search)) != NOGEOM) total++;
1152 }
1153
1154 /* special case: accept ports and invisible node if it holds highlighted text */
1155 if ((high.status&HIGHTYPE) == HIGHTEXT)
1156 {
1157 if (high.fromvar != NOVARIABLE && high.fromgeom != NOGEOM)
1158 {
1159 if (high.fromgeom->entryisnode &&
1160 high.fromgeom->entryaddr.ni->proto == gen_invispinprim) total++;
1161 }
1162 if (high.fromvar == NOVARIABLE && high.fromport != NOPORTPROTO) total++;
1163 }
1164 }
1165
1166 /* get memory for array of these objects */
1167 if (total*2 >= us_getallhighlistsize)
1168 {
1169 if (us_getallhighlistsize != 0) efree((CHAR *)us_getallhighlist);
1170 us_getallhighlist = (INTBIG *)emalloc((total+1)*2 * SIZEOFINTBIG, us_tool->cluster);
1171 if (us_getallhighlist == 0)
1172 {
1173 ttyputnomemory();
1174 nulllist[0] = nulllist[1] = 0;
1175 return(nulllist);
1176 }
1177 us_getallhighlistsize = (total+1)*2;
1178 }
1179
1180 /* now place the objects in the list */
1181 total = 0;
1182 for(i=0; i<len; i++)
1183 {
1184 (void)us_makehighlight(((CHAR **)var->addr)[i], &high);
1185 if ((high.status&HIGHTYPE) == HIGHFROM)
1186 {
1187 for(j=0; j<total; j += 2)
1188 if (us_getallhighlist[j] == (INTBIG)high.fromgeom->entryaddr.blind) break;
1189 if (j >= total)
1190 {
1191 us_getallhighlist[total++] = (INTBIG)high.fromgeom->entryaddr.blind;
1192 if (high.fromgeom->entryisnode) us_getallhighlist[total++] = VNODEINST; else
1193 us_getallhighlist[total++] = VARCINST;
1194 }
1195 }
1196 if ((high.status&HIGHTYPE) == HIGHBBOX)
1197 {
1198 lx = high.stalx; hx = high.stahx;
1199 ly = high.staly; hy = high.stahy;
1200 search = initsearch(lx, hx, ly, hy, high.cell);
1201 for(;;)
1202 {
1203 geom = nextobject(search);
1204 if (geom == NOGEOM) break;
1205 if (!us_geominrect(geom, lx, hx, ly, hy)) continue;
1206
1207 /* make sure it isn't already in the list */
1208 for(j=0; j<total; j++)
1209 if (us_getallhighlist[j] == (INTBIG)geom->entryaddr.blind) break;
1210 if (j < total) continue;
1211
1212 /* check carefully for "edge select" primitives */
1213 if (geom->entryisnode)
1214 {
1215 ni = geom->entryaddr.ni;
1216 if (ni->proto->primindex != 0)
1217 {
1218 if ((ni->proto->userbits&NINVISIBLE) != 0) continue;
1219 if ((ni->proto->userbits&NEDGESELECT) != 0)
1220 {
1221 ni = geom->entryaddr.ni;
1222 k = nodepolys(ni, 0, NOWINDOWPART);
1223 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1224 makerot(ni, trans);
1225 for(j=0; j<k; j++)
1226 {
1227 shapenodepoly(ni, j, poly);
1228 if ((poly->desc->colstyle&INVISIBLE) == 0)
1229 {
1230 xformpoly(poly, trans);
1231 if (!polyinrect(poly, high.stalx, high.stahx, high.staly, high.stahy))
1232 break;
1233 }
1234 }
1235 if (j < k) continue;
1236 }
1237 }
1238 } else
1239 {
1240 ai = geom->entryaddr.ai;
1241 if ((ai->proto->userbits&AINVISIBLE) != 0) continue;
1242 if ((ai->proto->userbits&AEDGESELECT) != 0)
1243 {
1244 k = arcpolys(ai, NOWINDOWPART);
1245 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1246 for(j=0; j<k; j++)
1247 {
1248 shapearcpoly(ai, j, poly);
1249 if ((poly->desc->colstyle&INVISIBLE) == 0)
1250 {
1251 if (!polyinrect(poly, high.stalx, high.stahx, high.staly, high.stahy))
1252 break;
1253 }
1254 }
1255 if (j < k) continue;
1256 }
1257 }
1258
1259 /* add this object to the list */
1260 us_getallhighlist[total++] = (INTBIG)geom->entryaddr.blind;
1261 if (geom->entryisnode) us_getallhighlist[total++] = VNODEINST; else
1262 us_getallhighlist[total++] = VARCINST;
1263 }
1264 }
1265 if ((high.status&HIGHTYPE) == HIGHTEXT)
1266 {
1267 if (high.fromvar != NOVARIABLE && high.fromgeom != NOGEOM)
1268 {
1269 if (high.fromgeom->entryisnode &&
1270 high.fromgeom->entryaddr.ni->proto == gen_invispinprim)
1271 {
1272 us_getallhighlist[total++] = (INTBIG)high.fromgeom->entryaddr.blind;
1273 us_getallhighlist[total++] = VNODEINST;
1274 }
1275 }
1276 if (high.fromvar == NOVARIABLE && high.fromport != NOPORTPROTO)
1277 {
1278 us_getallhighlist[total++] = (INTBIG)high.fromport;
1279 us_getallhighlist[total++] = VPORTPROTO;
1280 }
1281 }
1282 }
1283 us_getallhighlist[total++] = 0;
1284 us_getallhighlist[total] = 0;
1285 return(us_getallhighlist);
1286 }
1287
1288 /*
1289 * routine to get the boundary of an area delimited by the highlight.
1290 * The bounds are put in the reference variables "lx", "hx", "ly", and "hy".
1291 * If there is no highlighted area, the routine returns with NONODEPROTO
1292 * Otherwise the routine returns the cell that contains the area.
1293 */
us_getareabounds(INTBIG * lx,INTBIG * hx,INTBIG * ly,INTBIG * hy)1294 NODEPROTO *us_getareabounds(INTBIG *lx, INTBIG *hx, INTBIG *ly, INTBIG *hy)
1295 {
1296 HIGHLIGHT high;
1297 REGISTER NODEINST *ni;
1298 REGISTER BOOLEAN first;
1299 REGISTER INTBIG len, pointlen, i, good, bad;
1300 INTBIG tlx, thx, tly, thy, xc, yc;
1301 XARRAY trans;
1302 static POLYGON *poly = NOPOLYGON;
1303 REGISTER NODEPROTO *thiscell;
1304 REGISTER TECHNOLOGY *tech;
1305 REGISTER VARIABLE *var;
1306
1307 /* get polygon */
1308 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1309
1310 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1311 if (var == NOVARIABLE) return(NONODEPROTO);
1312
1313 thiscell = getcurcell();
1314 good = bad = 0;
1315 (void)us_makehighlight(((CHAR **)var->addr)[0], &high);
1316 len = getlength(var);
1317 first = TRUE;
1318 for(i=0; i<len; i++)
1319 {
1320 (void)us_makehighlight(((CHAR **)var->addr)[i], &high);
1321 if (thiscell == NONODEPROTO) thiscell = high.cell;
1322 if (high.cell == thiscell) good++; else
1323 {
1324 bad++;
1325 continue;
1326 }
1327 if ((high.status&HIGHTYPE) == HIGHTEXT)
1328 {
1329 if (high.fromvar != NOVARIABLE)
1330 {
1331 if (high.fromgeom == NOGEOM) continue;
1332 pointlen = 1;
1333 ni = NONODEINST;
1334 if (high.fromport != NOPORTPROTO) ni = high.fromport->subnodeinst; else
1335 if (high.fromgeom != NOGEOM && high.fromgeom->entryisnode)
1336 {
1337 ni = high.fromgeom->entryaddr.ni;
1338 if ((high.fromvar->type&VISARRAY) != 0)
1339 pointlen = getlength(high.fromvar);
1340 }
1341 if (pointlen > 1)
1342 {
1343 makedisparrayvarpoly(high.fromgeom, el_curwindowpart, high.fromvar, poly);
1344 } else
1345 {
1346 if (ni != NONODEINST) tech = ni->proto->tech; else
1347 {
1348 if (high.fromgeom != NOGEOM) tech = high.fromgeom->entryaddr.ai->proto->tech; else
1349 tech = high.cell->tech;
1350 }
1351 us_maketextpoly(describevariable(high.fromvar, -1, -1), el_curwindowpart,
1352 (high.fromgeom->lowx + high.fromgeom->highx) / 2,
1353 (high.fromgeom->lowy + high.fromgeom->highy) / 2,
1354 ni, tech, high.fromvar->textdescript, poly);
1355 }
1356 if (ni != NONODEINST)
1357 {
1358 makerot(ni, trans);
1359 xformpoly(poly, trans);
1360 }
1361 } else if (high.fromport != NOPORTPROTO)
1362 {
1363 portposition(high.fromport->subnodeinst, high.fromport->subportproto, &xc, &yc);
1364 us_maketextpoly(us_displayedportname(high.fromport, (us_useroptions&EXPORTLABELS) >> EXPORTLABELSSH),
1365 el_curwindowpart, xc, yc, high.fromport->subnodeinst,
1366 high.fromport->subnodeinst->proto->tech, high.fromport->textdescript, poly);
1367 } else if (high.fromgeom->entryisnode)
1368 {
1369 ni = high.fromgeom->entryaddr.ni;
1370 us_maketextpoly(describenodeproto(ni->proto), el_curwindowpart,
1371 (ni->lowx + ni->highx) / 2, (ni->lowy + ni->highy) / 2,
1372 ni, ni->proto->tech, ni->textdescript, poly);
1373 }
1374 getbbox(poly, &tlx, &thx, &tly, &thy);
1375 }
1376 if ((high.status&HIGHTYPE) == HIGHBBOX || (high.status&HIGHTYPE) == HIGHLINE)
1377 {
1378 tlx = high.stalx; thx = high.stahx;
1379 tly = high.staly; thy = high.stahy;
1380 }
1381 if ((high.status&HIGHTYPE) == HIGHFROM)
1382 {
1383 if (high.fromgeom->entryisnode)
1384 {
1385 us_getnodebounds(high.fromgeom->entryaddr.ni, &tlx, &thx, &tly, &thy);
1386 } else
1387 {
1388 us_getarcbounds(high.fromgeom->entryaddr.ai, &tlx, &thx, &tly, &thy);
1389 }
1390 }
1391 if (first)
1392 {
1393 *lx = tlx; *hx = thx; *ly = tly; *hy = thy;
1394 first = FALSE;
1395 } else
1396 {
1397 *lx = mini(*lx, tlx); *hx = maxi(*hx, thx);
1398 *ly = mini(*ly, tly); *hy = maxi(*hy, thy);
1399 }
1400 }
1401 if (good == 0 && bad != 0)
1402 {
1403 us_abortcommand(_("Highlighted areas must be in the current cell"));
1404 return(NONODEPROTO);
1405 }
1406 return(thiscell);
1407 }
1408
1409 /*
1410 * Routine to move the "numtexts" text objects described (as highlight strings)
1411 * in the array "textlist", by "odx" and "ody". Geometry objects in "list" (NOGEOM-terminated)
1412 * and the "total" nodes in "nodelist" have already been moved, so don't move any text that
1413 * is on these objects.
1414 */
us_moveselectedtext(INTBIG numtexts,CHAR ** textlist,GEOM ** list,INTBIG odx,INTBIG ody)1415 void us_moveselectedtext(INTBIG numtexts, CHAR **textlist, GEOM **list, INTBIG odx, INTBIG ody)
1416 {
1417 REGISTER INTBIG i, j, lambda;
1418 INTBIG dx, dy, addr, type;
1419 UINTBIG descript[TEXTDESCRIPTSIZE];
1420 REGISTER NODEINST *ni;
1421 XARRAY trans;
1422 HIGHLIGHT high;
1423
1424 for(i=0; i<numtexts; i++)
1425 {
1426 dx = odx; dy = ody;
1427 (void)us_makehighlight(textlist[i], &high);
1428 if ((high.status&HIGHTYPE) != HIGHTEXT) continue;
1429
1430 /* get object and movement amount */
1431 us_gethighaddrtype(&high, &addr, &type);
1432
1433 /* undraw the text */
1434 if (type == VPORTPROTO)
1435 {
1436 ni = ((PORTPROTO *)addr)->subnodeinst;
1437 for(j=0; list[j] != NOGEOM; j++)
1438 if (list[j]->entryisnode && list[j]->entryaddr.ni == ni) break;
1439 if (list[j] != NOGEOM) continue;
1440
1441 startobjectchange((INTBIG)ni, VNODEINST);
1442 if (us_nodemoveswithtext(&high))
1443 {
1444 modifynodeinst(ni, dx, dy, dx, dy, 0, 0);
1445 endobjectchange((INTBIG)ni, VNODEINST);
1446 continue;
1447 }
1448 if (ni->transpose != 0)
1449 makeangle(ni->rotation, ni->transpose, trans); else
1450 makeangle((3600-ni->rotation)%3600, 0, trans);
1451 xform(dx, dy, &dx, &dy, trans);
1452 } else
1453 {
1454 startobjectchange(addr, type);
1455 if (type == VNODEINST)
1456 {
1457 ni = (NODEINST *)addr;
1458 for(j=0; list[j] != NOGEOM; j++)
1459 if (list[j]->entryisnode && list[j]->entryaddr.ni == ni) break;
1460 if (list[j] != NOGEOM) continue;
1461
1462 if (us_nodemoveswithtext(&high))
1463 {
1464 modifynodeinst(ni, dx, dy, dx, dy, 0, 0);
1465 endobjectchange((INTBIG)ni, VNODEINST);
1466 continue;
1467 }
1468 if (ni->transpose != 0)
1469 makeangle(ni->rotation, ni->transpose, trans); else
1470 makeangle((3600-ni->rotation)%3600, 0, trans);
1471 xform(dx, dy, &dx, &dy, trans);
1472 }
1473 }
1474 if (type == VNODEPROTO && high.fromvar != NOVARIABLE)
1475 us_undrawcellvariable(high.fromvar, (NODEPROTO *)addr);
1476
1477 /* set the new descriptor on the text */
1478 lambda = el_curlib->lambda[us_hightech(&high)->techindex];
1479 dx = dx*4/lambda; dy = dy*4/lambda;
1480 us_gethighdescript(&high, descript);
1481 dx += TDGETXOFF(descript);
1482 dy += TDGETYOFF(descript);
1483 us_setdescriptoffset(descript, dx, dy);
1484 us_modifytextdescript(&high, descript);
1485
1486 /* redisplay the text */
1487 if (type == VNODEPROTO && high.fromvar != NOVARIABLE)
1488 us_drawcellvariable(high.fromvar, (NODEPROTO *)addr);
1489 if (type == VPORTPROTO)
1490 {
1491 endobjectchange((INTBIG)ni, VNODEINST);
1492 } else
1493 {
1494 endobjectchange(addr, type);
1495 }
1496 us_addhighlight(&high);
1497
1498 /* modify all higher-level nodes if port moved */
1499 if (high.fromvar == NOVARIABLE && high.fromport != NOPORTPROTO)
1500 {
1501 for(ni = high.fromport->parent->firstinst; ni != NONODEINST; ni = ni->nextinst)
1502 {
1503 if ((ni->userbits&NEXPAND) != 0 &&
1504 (high.fromport->userbits&PORTDRAWN) == 0) continue;
1505 startobjectchange((INTBIG)ni, VNODEINST);
1506 endobjectchange((INTBIG)ni, VNODEINST);
1507 }
1508 }
1509 }
1510 }
1511
1512 /*
1513 * Routine to find a single selected snap point and return it in (x, y).
1514 * Returns false if there is not a single snap point.
1515 */
us_getonesnappoint(INTBIG * x,INTBIG * y)1516 BOOLEAN us_getonesnappoint(INTBIG *x, INTBIG *y)
1517 {
1518 REGISTER INTBIG snapcount;
1519 REGISTER VARIABLE *var;
1520 REGISTER INTBIG len, i;
1521 HIGHLIGHT thishigh;
1522
1523 snapcount = 0;
1524 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1525 if (var != NOVARIABLE)
1526 {
1527 len = getlength(var);
1528 for(i=0; i<len; i++)
1529 {
1530 if (!us_makehighlight(((CHAR **)var->addr)[i], &thishigh))
1531 {
1532 if ((thishigh.status&HIGHSNAP) != 0)
1533 {
1534 us_getsnappoint(&thishigh, x, y);
1535 snapcount++;
1536 }
1537 }
1538 }
1539 }
1540 if (snapcount == 1) return(TRUE);
1541 return(FALSE);
1542 }
1543
1544 /*
1545 * routine to draw the highlighting for module "high". The highlighting is
1546 * drawn on if "on" is HIGHLIT, off if "on" is ALLOFF.
1547 */
us_sethighlight(HIGHLIGHT * high,INTBIG on)1548 void us_sethighlight(HIGHLIGHT *high, INTBIG on)
1549 {
1550 INTBIG xw, yw, xc, yc, lx, hx, ly, hy, addr, type;
1551 INTBIG style;
1552 BOOLEAN verbose, nobbox;
1553 REGISTER WINDOWPART *w;
1554 static POLYGON *poly = NOPOLYGON;
1555
1556 /* get polygon */
1557 (void)needstaticpolygon(&poly, 5, us_tool->cluster);
1558
1559 /* handle drawing bounding boxes */
1560 if ((high->status&HIGHTYPE) == HIGHBBOX)
1561 {
1562 maketruerectpoly(high->stalx, high->stahx, high->staly, high->stahy, poly);
1563 poly->desc = &us_hbox;
1564 poly->style = CLOSEDRECT;
1565 us_hbox.col = on;
1566 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1567 {
1568 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1569 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1570 if (w->curnodeproto != high->cell) continue;
1571 us_showpoly(poly, w);
1572 }
1573 return;
1574 }
1575
1576 /* handle drawing lines */
1577 if ((high->status&HIGHTYPE) == HIGHLINE)
1578 {
1579 poly->xv[0] = high->stalx; poly->yv[0] = high->staly;
1580 poly->xv[1] = high->stahx; poly->yv[1] = high->stahy;
1581 poly->count = 2;
1582 poly->desc = &us_hbox;
1583 poly->style = VECTORS;
1584 us_hbox.col = on;
1585 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1586 {
1587 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1588 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1589 if (w->curnodeproto != high->cell) continue;
1590 us_showpoly(poly, w);
1591 }
1592 return;
1593 }
1594
1595 /* handle text outlines */
1596 if ((high->status&HIGHTYPE) == HIGHTEXT)
1597 {
1598 /* determine center of text */
1599 us_gethightextcenter(high, &xc, &yc, &style);
1600
1601 /* initialize polygon */
1602 poly->layer = -1;
1603 poly->desc = &us_hbox;
1604 us_hbox.col = on;
1605
1606 /* display in every appropriate window */
1607 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1608 {
1609 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1610 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1611 if (w->curnodeproto != high->cell) continue;
1612
1613 us_gethightextsize(high, &xw, &yw, w);
1614
1615 /* construct polygon */
1616 us_gethighaddrtype(high, &addr, &type);
1617 (void)us_getobjectinfo(addr, type, &lx, &hx, &ly, &hy);
1618 us_buildtexthighpoly(lx, hx, ly, hy, xc, yc, xw, yw, style, poly);
1619 us_showpoly(poly, w);
1620 }
1621 return;
1622 }
1623
1624 /* quit if nothing to draw */
1625 if ((high->status&HIGHFROM) == 0 || high->fromgeom == NOGEOM) return;
1626
1627 /* highlight "from" object */
1628 if ((high->status&HIGHEXTRA) != 0) verbose = TRUE; else verbose = FALSE;
1629 if ((high->status&HIGHNOBOX) != 0) nobbox = TRUE; else nobbox = FALSE;
1630 us_highlighteverywhere(high->fromgeom, high->fromport, high->frompoint,
1631 verbose, on, nobbox);
1632
1633 /* draw the snap point if set */
1634 if ((high->status&HIGHSNAP) != 0)
1635 {
1636 us_getsnappoint(high, &poly->xv[0], &poly->yv[0]);
1637 poly->count = 1;
1638 poly->desc = &us_hbox;
1639 poly->style = BIGCROSS;
1640 us_hbox.col = on;
1641 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1642 {
1643 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1644 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1645 if (w->curnodeproto != high->cell) continue;
1646 us_showpoly(poly, w);
1647 }
1648 }
1649 }
1650
1651 /*
1652 * routine to build a polygon in "poly" that describes the highlighting of
1653 * a text object whose grab point is (xc,yc), size is (xw,yw), graphics
1654 * style is in "style" (either TEXTCENT, TEXTBOT, ...) and whose attached
1655 * object is "geom".
1656 */
us_buildtexthighpoly(INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy,INTBIG xc,INTBIG yc,INTBIG xw,INTBIG yw,INTBIG style,POLYGON * poly)1657 void us_buildtexthighpoly(INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy,
1658 INTBIG xc, INTBIG yc, INTBIG xw, INTBIG yw, INTBIG style, POLYGON *poly)
1659 {
1660 REGISTER INTBIG xsh, ysh;
1661
1662 /* compute appropriate highlight */
1663 switch (style)
1664 {
1665 case TEXTCENT:
1666 case TEXTBOX:
1667 poly->xv[0] = xc - xw/2; poly->yv[0] = yc - yw/2;
1668 poly->xv[1] = xc + xw/2; poly->yv[1] = yc + yw/2;
1669 poly->xv[2] = xc - xw/2; poly->yv[2] = yc + yw/2;
1670 poly->xv[3] = xc + xw/2; poly->yv[3] = yc - yw/2;
1671 poly->style = VECTORS; poly->count = 4;
1672 if (style == TEXTCENT) break;
1673 if (poly->limit < 12) (void)extendpolygon(poly, 12);
1674 xsh = (hx - lx) / 6;
1675 ysh = (hy - ly) / 6;
1676 poly->xv[4] = lx + xsh; poly->yv[4] = ly;
1677 poly->xv[5] = hx - xsh; poly->yv[5] = ly;
1678 poly->xv[6] = lx + xsh; poly->yv[6] = hy;
1679 poly->xv[7] = hx - xsh; poly->yv[7] = hy;
1680 poly->xv[8] = lx; poly->yv[8] = ly + ysh;
1681 poly->xv[9] = lx; poly->yv[9] = hy - ysh;
1682 poly->xv[10] = hx; poly->yv[10] = ly + ysh;
1683 poly->xv[11] = hx; poly->yv[11] = hy - ysh;
1684 poly->count = 12;
1685 break;
1686 case TEXTBOT:
1687 poly->xv[0] = xc - xw/2; poly->yv[0] = yc + yw;
1688 poly->xv[1] = xc - xw/2; poly->yv[1] = yc;
1689 poly->xv[2] = xc + xw/2; poly->yv[2] = yc;
1690 poly->xv[3] = xc + xw/2; poly->yv[3] = yc + yw;
1691 poly->style = OPENED; poly->count = 4;
1692 break;
1693 case TEXTTOP:
1694 poly->xv[0] = xc - xw/2; poly->yv[0] = yc - yw;
1695 poly->xv[1] = xc - xw/2; poly->yv[1] = yc;
1696 poly->xv[2] = xc + xw/2; poly->yv[2] = yc;
1697 poly->xv[3] = xc + xw/2; poly->yv[3] = yc - yw;
1698 poly->style = OPENED; poly->count = 4;
1699 break;
1700 case TEXTLEFT:
1701 poly->xv[0] = xc + xw; poly->yv[0] = yc + yw/2;
1702 poly->xv[1] = xc; poly->yv[1] = yc + yw/2;
1703 poly->xv[2] = xc; poly->yv[2] = yc - yw/2;
1704 poly->xv[3] = xc + xw; poly->yv[3] = yc - yw/2;
1705 poly->style = OPENED; poly->count = 4;
1706 break;
1707 case TEXTRIGHT:
1708 poly->xv[0] = xc - xw; poly->yv[0] = yc + yw/2;
1709 poly->xv[1] = xc; poly->yv[1] = yc + yw/2;
1710 poly->xv[2] = xc; poly->yv[2] = yc - yw/2;
1711 poly->xv[3] = xc - xw; poly->yv[3] = yc - yw/2;
1712 poly->style = OPENED; poly->count = 4;
1713 break;
1714 case TEXTTOPLEFT:
1715 poly->xv[0] = xc + xw; poly->yv[0] = yc;
1716 poly->xv[1] = xc; poly->yv[1] = yc;
1717 poly->xv[2] = xc; poly->yv[2] = yc - yw;
1718 poly->style = OPENED; poly->count = 3;
1719 break;
1720 case TEXTBOTLEFT:
1721 poly->xv[0] = xc; poly->yv[0] = yc + yw;
1722 poly->xv[1] = xc; poly->yv[1] = yc;
1723 poly->xv[2] = xc + xw; poly->yv[2] = yc;
1724 poly->style = OPENED; poly->count = 3;
1725 break;
1726 case TEXTTOPRIGHT:
1727 poly->xv[0] = xc - xw; poly->yv[0] = yc;
1728 poly->xv[1] = xc; poly->yv[1] = yc;
1729 poly->xv[2] = xc; poly->yv[2] = yc - yw;
1730 poly->style = OPENED; poly->count = 3;
1731 break;
1732 case TEXTBOTRIGHT:
1733 poly->xv[0] = xc - xw; poly->yv[0] = yc;
1734 poly->xv[1] = xc; poly->yv[1] = yc;
1735 poly->xv[2] = xc; poly->yv[2] = yc + yw;
1736 poly->style = OPENED; poly->count = 3;
1737 break;
1738 }
1739 }
1740
1741 /*
1742 * general routine to change the highlighting of an object. Every displayed
1743 * occurrence of geometry module "look" will have its highlighting drawn.
1744 * The highlighting will be in color "color".
1745 * If "port" is not NOPORTPROTO and the geometry module points to
1746 * a nodeinst, that port will also be highlighted. If "point" is nonzero,
1747 * then that point/line of the trace will be highlighted. If "verbose" is
1748 * true, the object will be highlighted with extra information. If
1749 * "nobbox" is true, don't draw the basic box around the object.
1750 */
us_highlighteverywhere(GEOM * look,PORTPROTO * port,INTBIG point,BOOLEAN verbose,INTBIG color,BOOLEAN nobbox)1751 void us_highlighteverywhere(GEOM *look, PORTPROTO *port, INTBIG point, BOOLEAN verbose, INTBIG color,
1752 BOOLEAN nobbox)
1753 {
1754 REGISTER NODEINST *ni;
1755 REGISTER ARCINST *ai;
1756 REGISTER NODEPROTO *par;
1757 REGISTER INTBIG i, x, y;
1758 REGISTER WINDOWPART *w;
1759 REGISTER VARIABLE *var;
1760 static POLYGON *poly = NOPOLYGON;
1761 XARRAY trans;
1762 INTBIG lx, hx, ly, hy;
1763
1764 /* get polygon */
1765 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1766
1767 /* sensibility check to prevent null highlighting */
1768 if (look->entryisnode)
1769 {
1770 if (port == NOPORTPROTO && !verbose && point == 0) nobbox = FALSE;
1771 } else
1772 {
1773 point = 0;
1774 if (!verbose) nobbox = FALSE;
1775 }
1776
1777 /* determine parent, compute polygon */
1778 par = geomparent(look);
1779 if (look->entryisnode)
1780 {
1781 ni = look->entryaddr.ni;
1782 makerot(ni, trans);
1783 nodesizeoffset(ni, &lx, &ly, &hx, &hy);
1784 makerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, poly);
1785 poly->style = FILLED;
1786 xformpoly(poly, trans);
1787 } else
1788 {
1789 ai = look->entryaddr.ai;
1790 i = ai->width - arcwidthoffset(ai);
1791 if (curvedarcoutline(ai, poly, CLOSED, i))
1792 makearcpoly(ai->length, i, ai, poly, FILLED);
1793 }
1794
1795 /* figure out the line type for this highlighting */
1796 poly->desc = &us_hbox;
1797 poly->desc->col = color;
1798 poly->style = OPENEDO1;
1799
1800 /* if extra information is being un-drawn, show it now */
1801 if (verbose && color == ALLOFF)
1802 us_highlightverbose(look, port, color, par, poly);
1803
1804 /* add the final point to close the polygon */
1805 if (poly->limit < poly->count+1) (void)extendpolygon(poly, poly->count+1);
1806 poly->xv[poly->count] = poly->xv[0];
1807 poly->yv[poly->count] = poly->yv[0];
1808 poly->count++;
1809
1810 /* if all points are the same, draw as a cross */
1811 for(i=1; i<poly->count; i++)
1812 if (poly->xv[i-1] != poly->xv[i] || poly->yv[i-1] != poly->yv[i]) break;
1813 if (i >= poly->count) poly->style = CROSS;
1814
1815 /* loop through windows and draw the highlighting */
1816 if (!nobbox)
1817 {
1818 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1819 {
1820 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1821 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1822 if (w->curnodeproto != par) continue;
1823 us_showpoly(poly, w);
1824 }
1825 }
1826
1827 /* remove that point to make the polygon centered */
1828 poly->count--;
1829
1830 /* if extra information is being drawn, show it now */
1831 if (verbose && color != ALLOFF)
1832 us_highlightverbose(look, port, color, par, poly);
1833
1834 /* draw the port prototype if requested */
1835 if (look->entryisnode && port != NOPORTPROTO)
1836 {
1837 /* compute the port bounds */
1838 shapeportpoly(ni, port, poly, FALSE);
1839
1840 /* compute graphics for the port outline */
1841 poly->desc = &us_arbit;
1842 us_arbit.bits = LAYERH; us_arbit.col = color;
1843
1844 /* see if the polygon is a single point */
1845 for(i=1; i<poly->count; i++)
1846 if (poly->xv[i] != poly->xv[i-1] || poly->yv[i] != poly->yv[i-1]) break;
1847 if (i < poly->count)
1848 {
1849 /* not a single point, draw its outline */
1850 if (poly->style == FILLEDRECT) poly->style = CLOSEDRECT; else
1851 if (poly->style == FILLED) poly->style = CLOSED; else
1852 if (poly->style == DISC) poly->style = CIRCLE;
1853 } else
1854 {
1855 /* single point port: make it a cross */
1856 poly->count = 1;
1857 poly->style = CROSS;
1858 }
1859
1860 /* draw the port */
1861 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1862 {
1863 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1864 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1865 if (w->curnodeproto != par) continue;
1866 us_showpoly(poly, w);
1867 }
1868 }
1869
1870 /* draw the point or line on the trace if requested */
1871 if (point != 0)
1872 {
1873 var = gettrace(ni);
1874 if (var == NOVARIABLE) return;
1875 x = (ni->highx + ni->lowx) / 2; y = (ni->highy + ni->lowy) / 2;
1876
1877 xform(((INTBIG *)var->addr)[(point-1)*2]+x, ((INTBIG *)var->addr)[(point-1)*2+1]+y,
1878 &poly->xv[0], &poly->yv[0], trans);
1879 poly->desc = &us_arbit;
1880 us_arbit.bits = LAYERH; us_arbit.col = color;
1881 poly->count = 1;
1882 poly->style = CROSS;
1883 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1884 {
1885 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1886 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1887 if (w->curnodeproto != par) continue;
1888 us_showpoly(poly, w);
1889 }
1890
1891 if (point*2 < getlength(var))
1892 {
1893 xform(((INTBIG *)var->addr)[point*2]+x, ((INTBIG *)var->addr)[point*2+1]+y,
1894 &poly->xv[1], &poly->yv[1], trans);
1895 poly->desc = &us_arbit;
1896 us_arbit.bits = LAYERH; us_arbit.col = color;
1897 poly->count = 2;
1898 poly->style = OPENED;
1899 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1900 {
1901 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1902 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1903 if (w->curnodeproto != par) continue;
1904 us_showpoly(poly, w);
1905 }
1906 }
1907 }
1908 }
1909
1910 /*
1911 * Routine to draw extra verbose highlighting on object "look" (if it is a node, then
1912 * "pp" is the port on that node). The color is "color", the parent cell is "par", and
1913 * if it is an arc, the polygon for that arc is "arcpoly".
1914 */
us_highlightverbose(GEOM * look,PORTPROTO * pp,INTBIG color,NODEPROTO * par,POLYGON * arcpoly)1915 void us_highlightverbose(GEOM *look, PORTPROTO *pp, INTBIG color, NODEPROTO *par, POLYGON *arcpoly)
1916 {
1917 static POLYGON *poly = NOPOLYGON;
1918 REGISTER NODEINST *ni, *hni;
1919 REGISTER ARCINST *ai, *oai;
1920 REGISTER WINDOWPART *w;
1921 REGISTER PORTARCINST *pi;
1922 REGISTER INTBIG i, thisend;
1923
1924 /* get polygon */
1925 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1926 poly->desc = &us_hbox;
1927 poly->desc->col = color;
1928
1929 if (look->entryisnode)
1930 {
1931 /* handle verbose highlighting of nodes */
1932 if (pp == NOPORTPROTO) return;
1933 if (pp->network == NONETWORK) return;
1934
1935 hni = look->entryaddr.ni;
1936 for(ni = par->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1937 ni->userbits &= ~NODEFLAGBIT;
1938 for(ai = par->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1939 ai->userbits &= ~ARCFLAGBIT;
1940
1941 /* determine which arcs should be highlighted */
1942 for(pi = hni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1943 {
1944 if (pi->proto->network != pp->network) continue;
1945 ai = pi->conarcinst;
1946 ai->userbits |= ARCFLAGBIT;
1947 if (ai->network != NONETWORK)
1948 {
1949 for(oai = par->firstarcinst; oai != NOARCINST; oai = oai->nextarcinst)
1950 {
1951 if (oai->network != ai->network) continue;
1952 oai->userbits |= ARCFLAGBIT;
1953 oai->end[0].nodeinst->userbits |= NODEFLAGBIT;
1954 oai->end[1].nodeinst->userbits |= NODEFLAGBIT;
1955 }
1956 }
1957 }
1958
1959 /* draw lines along all of the arcs on the network */
1960 for(ai = par->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1961 {
1962 if ((ai->userbits&ARCFLAGBIT) == 0) continue;
1963 poly->xv[0] = ai->end[0].xpos;
1964 poly->yv[0] = ai->end[0].ypos;
1965 poly->xv[1] = ai->end[1].xpos;
1966 poly->yv[1] = ai->end[1].ypos;
1967 poly->count = 2;
1968 poly->style = OPENEDT2;
1969 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1970 {
1971 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1972 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1973 if (w->curnodeproto != par) continue;
1974 us_showpoly(poly, w);
1975 }
1976 }
1977
1978 /* draw dots in all connected nodes */
1979 for(ni = par->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1980 {
1981 if (ni == hni) continue;
1982 if ((ni->userbits&NODEFLAGBIT) == 0) continue;
1983 poly->xv[0] = (ni->lowx + ni->highx) / 2;
1984 poly->yv[0] = (ni->lowy + ni->highy) / 2;
1985 poly->xv[1] = poly->xv[0] + el_curlib->lambda[el_curtech->techindex]/4;
1986 poly->yv[1] = poly->yv[0];
1987 poly->count = 2;
1988 poly->style = DISC;
1989 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1990 {
1991 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
1992 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
1993 if (w->curnodeproto != par) continue;
1994 poly->xv[1] = poly->xv[0] + (INTBIG)(DOTRADIUS / w->scalex);
1995 us_showpoly(poly, w);
1996 }
1997
1998 /* connect the center dots to the input arcs */
1999 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2000 {
2001 ai = pi->conarcinst;
2002 if ((ai->userbits&ARCFLAGBIT) == 0) continue;
2003 if (ai->end[0].portarcinst == pi) thisend = 0; else thisend = 1;
2004 if (ai->end[thisend].xpos != poly->xv[0] ||
2005 ai->end[thisend].ypos != poly->yv[0])
2006 {
2007 poly->xv[1] = ai->end[thisend].xpos;
2008 poly->yv[1] = ai->end[thisend].ypos;
2009 poly->count = 2;
2010 poly->style = OPENEDT1;
2011 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2012 {
2013 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
2014 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
2015 if (w->curnodeproto != par) continue;
2016 us_showpoly(poly, w);
2017 }
2018 }
2019 }
2020 }
2021 return;
2022 }
2023
2024 /* handle verbose highlighting of arcs */
2025 ai = look->entryaddr.ai;
2026
2027 /* get a description of the constraints on the arc */
2028 poly->string = (CHAR *)(*(el_curconstraint->request))(x_("describearc"), (INTBIG)ai);
2029
2030 /* quit now if there is no verbose text to print */
2031 if (poly->string == 0 || *poly->string == 0) return;
2032
2033 /* determine the location of this text */
2034 if (arcpoly->count != 4)
2035 {
2036 /* presume curved arc outline and determine center four points */
2037 i = arcpoly->count/2;
2038 poly->xv[0] = (arcpoly->xv[i/2] + arcpoly->xv[arcpoly->count-i/2-1] +
2039 arcpoly->xv[(i-1)/2] + arcpoly->xv[arcpoly->count-(i-1)/2-1]) / 4;
2040 poly->yv[0] = (arcpoly->yv[i/2] + arcpoly->yv[arcpoly->count-i/2-1] +
2041 arcpoly->yv[(i-1)/2] + arcpoly->yv[arcpoly->count-(i-1)/2-1]) / 4;
2042 } else
2043 {
2044 /* use straight arc: simply get center */
2045 poly->xv[0] = (ai->end[0].xpos + ai->end[1].xpos) / 2;
2046 poly->yv[0] = (ai->end[0].ypos + ai->end[1].ypos) / 2;
2047 }
2048 poly->style = TEXTCENT;
2049 if (ai->width == 0)
2050 {
2051 if (ai->end[0].ypos == ai->end[1].ypos) poly->style = TEXTBOT; else
2052 if (ai->end[0].xpos == ai->end[1].xpos) poly->style = TEXTLEFT; else
2053 if ((ai->end[0].xpos-ai->end[1].xpos) * (ai->end[0].ypos-ai->end[1].ypos) > 0)
2054 poly->style = TEXTBOTRIGHT; else
2055 poly->style = TEXTBOTLEFT;
2056 }
2057 poly->count = 1;
2058 TDCLEAR(poly->textdescript);
2059 TDSETSIZE(poly->textdescript, TXTSETQLAMBDA(4));
2060 poly->tech = ai->parent->tech;
2061 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2062 {
2063 if ((w->state&WINDOWTYPE) != DISPWINDOW &&
2064 (w->state&WINDOWTYPE) != DISP3DWINDOW) continue;
2065 if (w->curnodeproto != par) continue;
2066 (void)us_showpoly(poly, w);
2067 }
2068 }
2069
2070 /*
2071 * routine to push the currently highlighted configuration onto a stack
2072 */
us_pushhighlight(void)2073 void us_pushhighlight(void)
2074 {
2075 REGISTER VARIABLE *var;
2076 REGISTER INTBIG len, i;
2077 REGISTER CHAR **list;
2078 CHAR *one[1];
2079 REGISTER void *infstr;
2080
2081 /* get what is highlighted */
2082 infstr = initinfstr();
2083 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
2084 if (var != NOVARIABLE)
2085 {
2086 len = getlength(var);
2087 for(i=0; i<len; i++)
2088 {
2089 if (i != 0) addtoinfstr(infstr, '\n');
2090 addstringtoinfstr(infstr, ((CHAR **)var->addr)[i]);
2091 }
2092 }
2093
2094 /* now add this to the stack variable */
2095 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightstackkey);
2096 if (var == NOVARIABLE)
2097 {
2098 one[0] = returninfstr(infstr);
2099 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightstackkey, (INTBIG)one,
2100 VSTRING|VISARRAY|(1<<VLENGTHSH)|VDONTSAVE);
2101 return;
2102 }
2103
2104 len = getlength(var);
2105 list = (CHAR **)emalloc(((len+1) * (sizeof (CHAR *))), el_tempcluster);
2106 if (list == 0) return;
2107 for(i=0; i<len; i++)
2108 (void)allocstring(&list[i], ((CHAR **)var->addr)[i], el_tempcluster);
2109 list[len] = returninfstr(infstr);
2110 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightstackkey, (INTBIG)list,
2111 VSTRING|VISARRAY|((len+1)<<VLENGTHSH)|VDONTSAVE);
2112 for(i=0; i<len; i++) efree(list[i]);
2113 efree((CHAR *)list);
2114 }
2115
2116 /*
2117 * routine to pop the stack onto the currently highlighted configuration.
2118 */
us_pophighlight(BOOLEAN clearsnap)2119 void us_pophighlight(BOOLEAN clearsnap)
2120 {
2121 REGISTER VARIABLE *var;
2122 REGISTER CHAR **vaddr;
2123 REGISTER INTBIG len, i;
2124 REGISTER CHAR **list;
2125
2126 /* get the stack variable */
2127 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightstackkey);
2128 if (var == NOVARIABLE) return;
2129 len = getlength(var);
2130 vaddr = (CHAR **)var->addr;
2131
2132 /* set the configuration */
2133 us_setmultiplehighlight(vaddr[len-1], clearsnap);
2134
2135 /* shorten the stack */
2136 if (len == 1) (void)delvalkey((INTBIG)us_tool, VTOOL, us_highlightstackkey); else
2137 {
2138 len--;
2139 list = (CHAR **)emalloc((len * (sizeof (CHAR *))), el_tempcluster);
2140 if (list == 0) return;
2141 for(i=0; i<len; i++)
2142 (void)allocstring(&list[i], vaddr[i], el_tempcluster);
2143 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightstackkey, (INTBIG)list,
2144 VSTRING|VISARRAY|(len<<VLENGTHSH)|VDONTSAVE);
2145 for(i=0; i<len; i++) efree(list[i]);
2146 efree((CHAR *)list);
2147 }
2148 }
2149
2150 /*
2151 * routine to highlight the multiple highlight information in "str".
2152 */
us_setmultiplehighlight(CHAR * str,BOOLEAN clearsnap)2153 void us_setmultiplehighlight(CHAR *str, BOOLEAN clearsnap)
2154 {
2155 CHAR *pp;
2156 REGISTER CHAR *line, **list;
2157 REGISTER INTBIG total, i;
2158 HIGHLIGHT high;
2159 REGISTER void *infstr;
2160
2161 /* count the number of highlights */
2162 pp = str;
2163 for(total=0; ; total++)
2164 {
2165 line = getkeyword(&pp, x_("\n"));
2166 if (line == NOSTRING) break;
2167 if (*line == 0) break;
2168 (void)tonextchar(&pp);
2169 }
2170 if (total == 0) return;
2171
2172 /* make space for all of the highlight strings */
2173 list = (CHAR **)emalloc((total * (sizeof (CHAR *))), el_tempcluster);
2174 if (list == 0) return;
2175
2176 /* fill the list */
2177 pp = str;
2178 for(total=0; ; )
2179 {
2180 line = getkeyword(&pp, x_("\n"));
2181 if (line == NOSTRING) break;
2182 if (*line == 0) break;
2183
2184 if (clearsnap)
2185 {
2186 infstr = initinfstr();
2187 addstringtoinfstr(infstr, line);
2188 if (!us_makehighlight(returninfstr(infstr), &high))
2189 {
2190 high.status &= ~(HIGHSNAP | HIGHSNAPTAN | HIGHSNAPPERP);
2191 line = us_makehighlightstring(&high);
2192 (void)allocstring(&list[total++], line, el_tempcluster);
2193 }
2194 } else
2195 {
2196 (void)allocstring(&list[total++], line, el_tempcluster);
2197 }
2198 if (tonextchar(&pp) != '\n') break;
2199 }
2200
2201 /* set the multiple list */
2202 if (total == 0) return;
2203 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
2204 VSTRING|VISARRAY|(total<<VLENGTHSH)|VDONTSAVE);
2205
2206 for(i=0; i<total; i++) efree(list[i]);
2207 efree((CHAR *)list);
2208 us_makecurrentobject();
2209 }
2210
2211 /*
2212 * routine to set the current prototype from the current selection
2213 */
us_makecurrentobject(void)2214 void us_makecurrentobject(void)
2215 {
2216 REGISTER NODEPROTO *np;
2217 REGISTER GEOM *from;
2218 HIGHLIGHT high;
2219 REGISTER VARIABLE *var;
2220
2221 /* see what is highlighted */
2222 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
2223
2224 /* there must be exactly 1 object highlighted */
2225 if (var == NOVARIABLE || getlength(var) != 1)
2226 {
2227 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
2228 return;
2229 }
2230
2231 /* get information about the highlighted object */
2232 if (us_makehighlight(((CHAR **)var->addr)[0], &high)) return;
2233 if ((high.status&HIGHTYPE) != HIGHFROM && (high.status&HIGHTYPE) != HIGHTEXT)
2234 {
2235 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
2236 return;
2237 }
2238 from = high.fromgeom;
2239 if (from == NOGEOM)
2240 {
2241 us_setnodeproto(NONODEPROTO);
2242 return;
2243 }
2244
2245 /* if an arc is selected, show it */
2246 if (!from->entryisnode)
2247 {
2248 us_setarcproto(from->entryaddr.ai->proto, TRUE);
2249 if ((us_state&NONPERSISTENTCURNODE) != 0) us_setnodeproto(NONODEPROTO);
2250 return;
2251 }
2252
2253 /* a node is selected */
2254 np = from->entryaddr.ni->proto;
2255 us_setnodeproto(np);
2256 }
2257
2258 /*
2259 * routine to convert the string in "str" into the highlight module "high".
2260 * returns true on error
2261 */
us_makehighlight(CHAR * str,HIGHLIGHT * high)2262 BOOLEAN us_makehighlight(CHAR *str, HIGHLIGHT *high)
2263 {
2264 CHAR *pt;
2265 REGISTER CHAR *keyword;
2266 REGISTER INTBIG addr, type;
2267
2268 pt = str;
2269
2270 /* look for the "CELL=" keyword */
2271 keyword = getkeyword(&pt, x_("="));
2272 if (keyword == NOSTRING) return(TRUE);
2273 if (namesame(keyword, x_("CELL")) != 0) return(TRUE);
2274 if (tonextchar(&pt) != '=') return(TRUE);
2275
2276 /* get the cell name */
2277 keyword = getkeyword(&pt, x_(" \t"));
2278 if (keyword == NOSTRING) return(TRUE);
2279 high->cell = getnodeproto(keyword);
2280 if (high->cell == NONODEPROTO) return(TRUE);
2281
2282 /* get the type of highlight */
2283 keyword = getkeyword(&pt, x_("="));
2284 if (keyword == NOSTRING) return(TRUE);
2285 if (tonextchar(&pt) != '=') return(TRUE);
2286 if (namesame(keyword, x_("FROM")) == 0)
2287 {
2288 /* parse the three values: geom/port/point */
2289 high->status = HIGHFROM;
2290 high->fromvar = NOVARIABLE;
2291 high->fromvarnoeval = NOVARIABLE;
2292 keyword = getkeyword(&pt, x_(";"));
2293 if (keyword == NOSTRING) return(TRUE);
2294 high->fromgeom = (GEOM *)myatoi(keyword);
2295 if (tonextchar(&pt) != ';') return(TRUE);
2296 keyword = getkeyword(&pt, x_(";"));
2297 if (keyword == NOSTRING) return(TRUE);
2298 high->fromport = (PORTPROTO *)myatoi(keyword);
2299 if (tonextchar(&pt) != ';') return(TRUE);
2300 keyword = getkeyword(&pt, x_(";"));
2301 if (keyword == NOSTRING) return(TRUE);
2302 high->frompoint = myatoi(keyword);
2303 } else if (namesame(keyword, x_("AREA")) == 0 || namesame(keyword, x_("LINE")) == 0)
2304 {
2305 if (namesame(keyword, x_("AREA")) == 0) high->status = HIGHBBOX; else
2306 high->status = HIGHLINE;
2307 keyword = getkeyword(&pt, x_(","));
2308 if (keyword == NOSTRING) return(TRUE);
2309 high->stalx = myatoi(keyword);
2310 if (tonextchar(&pt) != ',') return(TRUE);
2311 keyword = getkeyword(&pt, x_(","));
2312 if (keyword == NOSTRING) return(TRUE);
2313 high->stahx = myatoi(keyword);
2314 if (tonextchar(&pt) != ',') return(TRUE);
2315 keyword = getkeyword(&pt, x_(","));
2316 if (keyword == NOSTRING) return(TRUE);
2317 high->staly = myatoi(keyword);
2318 if (tonextchar(&pt) != ',') return(TRUE);
2319 keyword = getkeyword(&pt, x_(","));
2320 if (keyword == NOSTRING) return(TRUE);
2321 high->stahy = myatoi(keyword);
2322 } else if (namesame(keyword, x_("TEXT")) == 0)
2323 {
2324 /* parse the three values: geom/port/var */
2325 high->status = HIGHTEXT;
2326 high->frompoint = 0;
2327 keyword = getkeyword(&pt, x_(";"));
2328 if (keyword == NOSTRING) return(TRUE);
2329 high->fromgeom = (GEOM *)myatoi(keyword);
2330 if (tonextchar(&pt) != ';') return(TRUE);
2331 keyword = getkeyword(&pt, x_(";"));
2332 if (keyword == NOSTRING) return(TRUE);
2333 high->fromport = (PORTPROTO *)myatoi(keyword);
2334 if (tonextchar(&pt) != ';') return(TRUE);
2335 keyword = getkeyword(&pt, x_(";"));
2336 if (keyword == NOSTRING) return(TRUE);
2337 if (*keyword == '-') high->fromvarnoeval = high->fromvar = NOVARIABLE; else
2338 {
2339 if (high->fromport != NOPORTPROTO)
2340 {
2341 addr = (INTBIG)high->fromport;
2342 type = VPORTPROTO;
2343 } else if (high->fromgeom != NOGEOM)
2344 {
2345 if (high->fromgeom->entryisnode)
2346 {
2347 addr = (INTBIG)high->fromgeom->entryaddr.ni;
2348 type = VNODEINST;
2349 } else
2350 {
2351 addr = (INTBIG)high->fromgeom->entryaddr.ai;
2352 type = VARCINST;
2353 }
2354 } else
2355 {
2356 addr = (INTBIG)high->cell;
2357 type = VNODEPROTO;
2358 }
2359 high->fromvarnoeval = getvalnoeval(addr, type, -1, keyword);
2360 high->fromvar = evalvar(high->fromvarnoeval, addr, type);
2361 }
2362 } else return(TRUE);
2363
2364 /* parse any additional keywords */
2365 for(;;)
2366 {
2367 if (tonextchar(&pt) == 0) break;
2368 keyword = getkeyword(&pt, x_(";,="));
2369 if (keyword == NOSTRING) return(TRUE);
2370 if ((namesame(keyword, x_("SNAP")) == 0 || namesame(keyword, x_("SNAPTAN")) == 0 ||
2371 namesame(keyword, x_("SNAPPERP")) == 0) && tonextchar(&pt) == '=')
2372 {
2373 high->status |= HIGHSNAP;
2374 if (namesame(keyword, x_("SNAPTAN")) == 0) high->status |= HIGHSNAPTAN;
2375 if (namesame(keyword, x_("SNAPPERP")) == 0) high->status |= HIGHSNAPPERP;
2376 keyword = getkeyword(&pt, x_(","));
2377 if (keyword == NOSTRING) return(TRUE);
2378 high->snapx = myatoi(keyword);
2379 if (tonextchar(&pt) != ',') return(TRUE);
2380 keyword = getkeyword(&pt, x_(";,"));
2381 if (keyword == NOSTRING) return(TRUE);
2382 high->snapy = myatoi(keyword);
2383 continue;
2384 }
2385 if (namesame(keyword, x_("EXTRA")) == 0)
2386 {
2387 high->status |= HIGHEXTRA;
2388 continue;
2389 }
2390 if (namesame(keyword, x_("NOBBOX")) == 0)
2391 {
2392 high->status |= HIGHNOBOX;
2393 continue;
2394 }
2395 return(TRUE);
2396 }
2397 return(FALSE);
2398 }
2399
2400 /*
2401 * routine to convert the highlight in "high" into a string which is returned.
2402 */
us_makehighlightstring(HIGHLIGHT * high)2403 CHAR *us_makehighlightstring(HIGHLIGHT *high)
2404 {
2405 REGISTER void *infstr;
2406
2407 infstr = initinfstr();
2408 formatinfstr(infstr, x_("CELL=%s"), describenodeproto(high->cell));
2409 switch (high->status&HIGHTYPE)
2410 {
2411 case HIGHFROM:
2412 formatinfstr(infstr, x_(" FROM=0%lo;"), (UINTBIG)high->fromgeom);
2413 if (high->fromport == NOPORTPROTO) addstringtoinfstr(infstr, x_("-1;")); else
2414 formatinfstr(infstr, x_("0%lo;"), (UINTBIG)high->fromport);
2415 formatinfstr(infstr, x_("%ld"), high->frompoint);
2416 if ((high->status&HIGHEXTRA) != 0) addstringtoinfstr(infstr, x_(";EXTRA"));
2417 if ((high->status&HIGHNOBOX) != 0) addstringtoinfstr(infstr, x_(";NOBBOX"));
2418 break;
2419 case HIGHTEXT:
2420 formatinfstr(infstr, x_(" TEXT=0%lo;"), (UINTBIG)high->fromgeom);
2421 if (high->fromport == NOPORTPROTO) addstringtoinfstr(infstr, x_("-1;")); else
2422 formatinfstr(infstr, x_("0%lo;"), (UINTBIG)high->fromport);
2423 if (high->fromvar == NOVARIABLE) addstringtoinfstr(infstr, x_("-")); else
2424 addstringtoinfstr(infstr, makename(high->fromvar->key));
2425 break;
2426 case HIGHBBOX:
2427 formatinfstr(infstr, x_(" AREA=%ld,%ld,%ld,%ld"), high->stalx, high->stahx, high->staly, high->stahy);
2428 break;
2429 case HIGHLINE:
2430 formatinfstr(infstr, x_(" LINE=%ld,%ld,%ld,%ld"), high->stalx, high->stahx, high->staly, high->stahy);
2431 break;
2432 }
2433 if ((high->status&HIGHSNAP) != 0)
2434 {
2435 if ((high->status&HIGHSNAPTAN) != 0) addstringtoinfstr(infstr, x_(";SNAPTAN=")); else
2436 if ((high->status&HIGHSNAPPERP) != 0) addstringtoinfstr(infstr, x_(";SNAPPERP=")); else
2437 addstringtoinfstr(infstr, x_(";SNAP="));
2438 formatinfstr(infstr, x_("%ld,%ld"), high->snapx, high->snapy);
2439 }
2440 return(returninfstr(infstr));
2441 }
2442
2443 /*
2444 * routine to determine the center of the highlighted text described by
2445 * "high". The coordinates are placed in (xc, yc), and the appropriate
2446 * polygon style is placed in "style".
2447 */
us_gethightextcenter(HIGHLIGHT * high,INTBIG * xc,INTBIG * yc,INTBIG * style)2448 void us_gethightextcenter(HIGHLIGHT *high, INTBIG *xc, INTBIG *yc, INTBIG *style)
2449 {
2450 static POLYGON *poly = NOPOLYGON;
2451 REGISTER NODEINST *ni;
2452 REGISTER ARCINST *ai;
2453 REGISTER NODEPROTO *cell;
2454 XARRAY trans;
2455 INTBIG newxc, newyc;
2456 REGISTER INTSML saverot, savetrn;
2457 REGISTER INTBIG lambda;
2458 UINTBIG descript[TEXTDESCRIPTSIZE];
2459
2460 /* get polygon */
2461 (void)needstaticpolygon(&poly, 1, us_tool->cluster);
2462
2463 poly->count = 1;
2464 poly->style = FILLED;
2465 if (high->fromvar != NOVARIABLE)
2466 {
2467 TDCOPY(descript, high->fromvar->textdescript);
2468 if (high->fromport != NOPORTPROTO)
2469 {
2470 ni = high->fromport->subnodeinst;
2471 saverot = ni->rotation; savetrn = ni->transpose;
2472 ni->rotation = ni->transpose = 0;
2473 portposition(ni, high->fromport->subportproto,
2474 &poly->xv[0], &poly->yv[0]);
2475 ni->rotation = saverot; ni->transpose = savetrn;
2476 adjustdisoffset((INTBIG)high->fromport, VPORTPROTO, high->cell->tech,
2477 poly, descript);
2478 makerot(high->fromport->subnodeinst, trans);
2479 xformpoly(poly, trans);
2480 } else if (high->fromgeom != NOGEOM)
2481 {
2482 if (high->fromgeom->entryisnode)
2483 {
2484 ni = high->fromgeom->entryaddr.ni;
2485 poly->xv[0] = (ni->lowx + ni->highx) / 2;
2486 poly->yv[0] = (ni->lowy + ni->highy) / 2;
2487 adjustdisoffset((INTBIG)ni, VNODEINST, ni->proto->tech, poly, descript);
2488 makerot(ni, trans);
2489 xformpoly(poly, trans);
2490 } else
2491 {
2492 ai = high->fromgeom->entryaddr.ai;
2493 poly->xv[0] = (ai->end[0].xpos + ai->end[1].xpos) / 2;
2494 poly->yv[0] = (ai->end[0].ypos + ai->end[1].ypos) / 2;
2495 adjustdisoffset((INTBIG)ai, VARCINST, ai->proto->tech, poly, descript);
2496 }
2497 } else
2498 {
2499 /* cell variables are offset from (0,0) */
2500 poly->xv[0] = poly->yv[0] = 0;
2501 adjustdisoffset((INTBIG)high->cell, VNODEPROTO, high->cell->tech,
2502 poly, descript);
2503 }
2504 *style = poly->style;
2505 } else if (high->fromport != NOPORTPROTO)
2506 {
2507 TDCOPY(descript, high->fromport->textdescript);
2508 ni = high->fromgeom->entryaddr.ni;
2509 portposition(high->fromport->subnodeinst, high->fromport->subportproto,
2510 &poly->xv[0], &poly->yv[0]);
2511 makeangle(ni->rotation, ni->transpose, trans);
2512 cell = ni->parent;
2513 lambda = cell->lib->lambda[cell->tech->techindex];
2514 newxc = TDGETXOFF(descript);
2515 newxc = newxc * lambda / 4;
2516 newyc = TDGETYOFF(descript);
2517 newyc = newyc * lambda / 4;
2518 xform(newxc, newyc, &newxc, &newyc, trans);
2519 poly->xv[0] += newxc; poly->yv[0] += newyc;
2520 switch (TDGETPOS(descript))
2521 {
2522 case VTPOSCENT: *style = TEXTCENT; break;
2523 case VTPOSBOXED: *style = TEXTBOX; break;
2524 case VTPOSUP: *style = TEXTBOT; break;
2525 case VTPOSDOWN: *style = TEXTTOP; break;
2526 case VTPOSLEFT: *style = TEXTRIGHT; break;
2527 case VTPOSRIGHT: *style = TEXTLEFT; break;
2528 case VTPOSUPLEFT: *style = TEXTBOTRIGHT; break;
2529 case VTPOSUPRIGHT: *style = TEXTBOTLEFT; break;
2530 case VTPOSDOWNLEFT: *style = TEXTTOPRIGHT; break;
2531 case VTPOSDOWNRIGHT: *style = TEXTTOPLEFT; break;
2532 }
2533 *style = rotatelabel(*style, TDGETROTATION(descript), trans);
2534 } else if (high->fromgeom != NOGEOM && high->fromgeom->entryisnode)
2535 {
2536 /* instance name */
2537 ni = high->fromgeom->entryaddr.ni;
2538 TDCOPY(descript, ni->textdescript);
2539 poly->xv[0] = (ni->lowx + ni->highx) / 2;
2540 poly->yv[0] = (ni->lowy + ni->highy) / 2;
2541 adjustdisoffset((INTBIG)ni, VNODEINST, ni->proto->tech, poly, descript);
2542 makerot(ni, trans);
2543 xformpoly(poly, trans);
2544 *style = poly->style;
2545 }
2546 getcenter(poly, xc, yc);
2547 }
2548
us_gethightextsize(HIGHLIGHT * high,INTBIG * xw,INTBIG * yw,WINDOWPART * w)2549 void us_gethightextsize(HIGHLIGHT *high, INTBIG *xw, INTBIG *yw, WINDOWPART *w)
2550 {
2551 REGISTER INTBIG len;
2552 REGISTER CHAR *str;
2553 REGISTER TECHNOLOGY *tech;
2554 REGISTER WINDOWPART *oldwin;
2555 INTBIG lx, hx, ly, hy;
2556 UINTBIG descript[TEXTDESCRIPTSIZE];
2557 static POLYGON *poly = NOPOLYGON;
2558
2559 /* get polygon */
2560 (void)needstaticpolygon(&poly, 5, us_tool->cluster);
2561
2562 /* determine number of lines of text */
2563 len = 1;
2564 if (high->fromvar != NOVARIABLE && (high->fromvar->type&VISARRAY) != 0)
2565 len = getlength(high->fromvar);
2566 if (len > 1)
2567 {
2568 /* get size of array of text */
2569 makedisparrayvarpoly(high->fromgeom, w, high->fromvar, poly);
2570 getbbox(poly, &lx, &hx, &ly, &hy);
2571 *xw = hx - lx;
2572 *yw = hy - ly;
2573 return;
2574 }
2575
2576 /* determine size of single line of text */
2577 tech = us_hightech(high);
2578 oldwin = setvariablewindow(w);
2579 str = us_gethighstring(high);
2580 us_gethighdescript(high, descript);
2581 (void)setvariablewindow(oldwin);
2582
2583 us_gettextscreensize(str, descript, w, tech, high->fromgeom, xw, yw);
2584 }
2585
2586 /*
2587 * Routine to return the text descriptor on highlight "high" in "descript".
2588 */
us_gethighdescript(HIGHLIGHT * high,UINTBIG * descript)2589 void us_gethighdescript(HIGHLIGHT *high, UINTBIG *descript)
2590 {
2591 if (high->fromvar != NOVARIABLE)
2592 {
2593 TDCOPY(descript, high->fromvar->textdescript);
2594 return;
2595 }
2596 if (high->fromport != NOPORTPROTO)
2597 {
2598 TDCOPY(descript, high->fromport->textdescript);
2599 return;
2600 }
2601 if (high->fromgeom->entryisnode)
2602 {
2603 TDCOPY(descript, high->fromgeom->entryaddr.ni->textdescript);
2604 return;
2605 }
2606 TDCLEAR(descript);
2607 }
2608
2609 /*
2610 * Routine to return the text on highlight "high".
2611 */
us_gethighstring(HIGHLIGHT * high)2612 CHAR *us_gethighstring(HIGHLIGHT *high)
2613 {
2614 REGISTER CHAR *str;
2615 REGISTER VARIABLE *var;
2616
2617 var = high->fromvar;
2618 if (var != NOVARIABLE)
2619 {
2620 if (high->fromvarnoeval != NOVARIABLE) var = evalvar(high->fromvarnoeval, 0, 0);
2621 str = describedisplayedvariable(var, -1, -1);
2622 return(str);
2623 }
2624 if (high->fromport != NOPORTPROTO)
2625 return(us_displayedportname(high->fromport, (us_useroptions&EXPORTLABELS) >> EXPORTLABELSSH));
2626 if (high->fromgeom->entryisnode)
2627 return(describenodeproto(high->fromgeom->entryaddr.ni->proto));
2628 return(x_(""));
2629 }
2630
2631 /*
2632 * Routine to examine highlight "high" and return the address and type
2633 * of the object to which it refers.
2634 */
us_gethighaddrtype(HIGHLIGHT * high,INTBIG * addr,INTBIG * type)2635 void us_gethighaddrtype(HIGHLIGHT *high, INTBIG *addr, INTBIG *type)
2636 {
2637 if ((high->status&HIGHTYPE) == HIGHTEXT)
2638 {
2639 if (high->fromvar != NOVARIABLE)
2640 {
2641 if (high->fromport != NOPORTPROTO)
2642 {
2643 *addr = (INTBIG)high->fromport;
2644 *type = VPORTPROTO;
2645 return;
2646 }
2647 if (high->fromgeom == NOGEOM)
2648 {
2649 *addr = (INTBIG)high->cell;
2650 *type = VNODEPROTO;
2651 return;
2652 }
2653
2654 *addr = (INTBIG)high->fromgeom->entryaddr.blind;
2655 if (high->fromgeom->entryisnode)
2656 {
2657 *type = VNODEINST;
2658 } else
2659 {
2660 *type = VARCINST;
2661 }
2662 return;
2663 }
2664 if (high->fromport != NOPORTPROTO)
2665 {
2666 *addr = (INTBIG)high->fromport;
2667 *type = VPORTPROTO;
2668 return;
2669 }
2670 *addr = (INTBIG)high->fromgeom->entryaddr.blind;
2671 if (high->fromgeom->entryisnode) *type = VNODEINST; else
2672 *type = VARCINST;
2673 return;
2674 }
2675 }
2676
2677 /*
2678 * Routine to return true if highlight "high" is text on a node that must move together.
2679 * This only happens for "nonlayout text" (a variable on an invisible node), for exports
2680 * on an invisible pin, or for any export when it is requested that the node move too.
2681 */
us_nodemoveswithtext(HIGHLIGHT * high)2682 BOOLEAN us_nodemoveswithtext(HIGHLIGHT *high)
2683 {
2684 REGISTER NODEINST *ni;
2685
2686 if (high->status != HIGHTEXT) return(FALSE);
2687 if (high->fromgeom == NOGEOM) return(FALSE);
2688 if (!high->fromgeom->entryisnode) return(FALSE);
2689 ni = high->fromgeom->entryaddr.ni;
2690 if (ni == NONODEINST) return(FALSE);
2691 if (high->fromvar != NOVARIABLE)
2692 {
2693 /* moving variable text */
2694 if (ni->proto != gen_invispinprim) return(FALSE);
2695 if (high->fromport == NOPORTPROTO) return(TRUE);
2696 } else
2697 {
2698 /* moving export text */
2699 if ((us_useroptions&MOVENODEWITHEXPORT) == 0 && ni->proto != gen_invispinprim)
2700 return(FALSE);
2701 if (high->fromport != NOPORTPROTO) return(TRUE);
2702 }
2703 return(FALSE);
2704 }
2705
2706 /*
2707 * Routine to figure out the technology to use for highlight "high".
2708 */
us_hightech(HIGHLIGHT * high)2709 TECHNOLOGY *us_hightech(HIGHLIGHT *high)
2710 {
2711 REGISTER NODEPROTO *cell;
2712
2713 cell = us_highcell(high);
2714 if (cell == NONODEPROTO) return(el_curtech);
2715 if (cell->tech == NOTECHNOLOGY)
2716 cell->tech = whattech(cell);
2717 return(cell->tech);
2718 }
2719
2720 /*
2721 * Routine to figure out the cell to use for highlight "high".
2722 */
us_highcell(HIGHLIGHT * high)2723 NODEPROTO *us_highcell(HIGHLIGHT *high)
2724 {
2725 if (high->fromvar != NOVARIABLE)
2726 {
2727 if (high->fromport != NOPORTPROTO)
2728 return(high->fromport->subnodeinst->parent);
2729 if (high->fromgeom == NOGEOM) return(high->cell);
2730 if (high->fromgeom->entryisnode)
2731 return(high->fromgeom->entryaddr.ni->parent);
2732 return(high->fromgeom->entryaddr.ai->parent);
2733 }
2734 if (high->fromport != NOPORTPROTO)
2735 return(high->fromgeom->entryaddr.ni->parent);
2736 if (high->fromgeom->entryisnode)
2737 return(high->fromgeom->entryaddr.ni->parent);
2738 return(high->fromgeom->entryaddr.ai->parent);
2739 }
2740
us_getobjectinfo(INTBIG addr,INTBIG type,INTBIG * lx,INTBIG * hx,INTBIG * ly,INTBIG * hy)2741 TECHNOLOGY *us_getobjectinfo(INTBIG addr, INTBIG type, INTBIG *lx, INTBIG *hx, INTBIG *ly, INTBIG *hy)
2742 {
2743 REGISTER NODEINST *ni;
2744 REGISTER ARCINST *ai;
2745 REGISTER PORTPROTO *pp;
2746 REGISTER NODEPROTO *np;
2747 INTBIG olx, ohx, oly, ohy;
2748
2749 switch (type)
2750 {
2751 case VNODEINST:
2752 ni = (NODEINST *)addr;
2753 nodesizeoffset(ni, &olx, &oly, &ohx, &ohy);
2754 *lx = ni->geom->lowx+olx; *hx = ni->geom->highx-ohx;
2755 *ly = ni->geom->lowy+oly; *hy = ni->geom->highy-ohy;
2756 return(ni->parent->tech);
2757 case VARCINST:
2758 ai = (ARCINST *)addr;
2759 *lx = ai->geom->lowx; *hx = ai->geom->highx;
2760 *ly = ai->geom->lowy; *hy = ai->geom->highy;
2761 return(ai->parent->tech);
2762 case VPORTPROTO:
2763 pp = (PORTPROTO *)addr;
2764 ni = pp->subnodeinst;
2765 *lx = ni->geom->lowx; *hx = ni->geom->highx;
2766 *ly = ni->geom->lowy; *hy = ni->geom->highy;
2767 return(pp->parent->tech);
2768 case VNODEPROTO:
2769 np = (NODEPROTO *)addr;
2770 *lx = np->lowx; *hx = np->highx;
2771 *ly = np->lowy; *hy = np->highy;
2772 return(np->tech);
2773 }
2774 return(NOTECHNOLOGY);
2775 }
2776
us_drawcellvariable(VARIABLE * var,NODEPROTO * np)2777 void us_drawcellvariable(VARIABLE *var, NODEPROTO *np)
2778 {
2779 REGISTER INTBIG i, displaytotal;
2780 REGISTER WINDOWPART *w;
2781 static POLYGON *poly = NOPOLYGON;
2782
2783 /* get polygon */
2784 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
2785
2786 displaytotal = tech_displayablecellvars(np, NOWINDOWPART, &tech_oneprocpolyloop);
2787 for(i = 0; i < displaytotal; i++)
2788 {
2789 (void)tech_filldisplayablecellvar(np, poly, NOWINDOWPART, 0, &tech_oneprocpolyloop);
2790 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2791 {
2792 if (w->curnodeproto != np) continue;
2793 (*us_displayroutine)(poly, w);
2794 }
2795 }
2796 }
2797
us_undrawcellvariable(VARIABLE * var,NODEPROTO * np)2798 void us_undrawcellvariable(VARIABLE *var, NODEPROTO *np)
2799 {
2800 INTBIG x, y;
2801 INTBIG tsx, tsy;
2802 REGISTER INTBIG objwid, objhei, sea, slx, shx, sly, shy, nudge;
2803 INTBIG lx, hx, ly, hy;
2804 REGISTER TECHNOLOGY *tech;
2805 REGISTER NODEINST *ni;
2806 REGISTER ARCINST *ai;
2807 REGISTER GEOM *geom;
2808 REGISTER CHAR *str;
2809 REGISTER WINDOWPART *w;
2810 extern GRAPHICS us_ebox;
2811
2812 if ((var->type&VDISPLAY) == 0) return;
2813 tech = np->tech;
2814 str = describedisplayedvariable(var, -1, -1);
2815 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2816 {
2817 if ((w->state&WINDOWTYPE) != DISPWINDOW) continue;
2818 if (w->curnodeproto != np) continue;
2819 screensettextinfo(w, tech, var->textdescript);
2820
2821 getdisparrayvarlinepos((INTBIG)np, VNODEPROTO, tech,
2822 w, var, 0, &x, &y, TRUE);
2823 screengettextsize(w, str, &tsx, &tsy);
2824 objwid = roundfloat((float)tsx / w->scalex);
2825 objhei = roundfloat((float)tsy / w->scaley);
2826 slx = x; shx = slx + objwid;
2827 sly = y; shy = sly + objhei;
2828
2829 /* erase that area */
2830 lx = slx; hx = shx;
2831 ly = sly; hy = shy;
2832 if ((w->state&INPLACEEDIT) != 0)
2833 xformbox(&lx, &hx, &ly, &hy, w->outofcell);
2834 if (us_makescreen(&lx, &ly, &hx, &hy, w)) continue;
2835 screendrawbox(w, lx, hx, ly, hy, &us_ebox);
2836
2837 /* now redraw everything that touches this box */
2838 nudge = (INTBIG)(1.0f/w->scalex);
2839 slx -= nudge;
2840 shx += nudge;
2841 nudge = (INTBIG)(1.0f/w->scaley);
2842 sly -= nudge;
2843 shy += nudge;
2844 sea = initsearch(slx, shx, sly, shy, np);
2845 for(;;)
2846 {
2847 geom = nextobject(sea);
2848 if (geom == NOGEOM) break;
2849 if (geom->entryisnode)
2850 {
2851 ni = geom->entryaddr.ni;
2852 (void)us_drawcell(ni, LAYERA, el_matid, 3, w);
2853 } else
2854 {
2855 ai = geom->entryaddr.ai;
2856 (void)us_drawarcinst(ai, LAYERA, el_matid, 3, w);
2857 }
2858 }
2859 }
2860 }
2861