1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usrcomtz.c
6 * User interface tool: command handler for W through Z
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 "usrtrack.h"
36 #include "efunction.h"
37
38 static struct
39 {
40 CHAR *keyword;
41 short unique;
42 STATUSFIELD **fieldaddr;
43 } us_statusfields[] =
44 {
45 {x_("align"), 2, &us_statusalign},
46 {x_("angle"), 2, &us_statusangle},
47 {x_("arc"), 2, &us_statusarc},
48 {x_("cell"), 1, &us_statuscell},
49 {x_("grid"), 1, &us_statusgridsize},
50 {x_("lambda"), 1, &us_statuslambda},
51 {x_("numselected"),2, &us_statusselectcount},
52 {x_("node"), 2, &us_statusnode},
53 {x_("package"), 3, &us_statuspackage},
54 {x_("part"), 3, &us_statuspart},
55 {x_("project"), 2, &us_statusproject},
56 {x_("root"), 1, &us_statusroot},
57 {x_("selection"), 2, &us_statusselection},
58 {x_("size"), 2, &us_statuscellsize},
59 {x_("technology"), 1, &us_statustechnology},
60 {x_("x"), 1, &us_statusxpos},
61 {x_("y"), 1, &us_statusypos},
62 {0,0,0}
63 };
64
us_window(INTBIG count,CHAR * par[])65 void us_window(INTBIG count, CHAR *par[])
66 {
67 REGISTER WINDOWPART *w, *oldw, *nextw, *neww;
68 REGISTER INTBIG i, dist, curwx, curwy, size, x, y, diffx, diffy, lambda, needwx, needwy;
69 REGISTER INTBIG l, nogood, splitkey, lineno, startper, endper;
70 INTBIG lx, hx, ly, hy, xcur, ycur, windowView[8];
71 UINTBIG descript[TEXTDESCRIPTSIZE];
72 static POLYGON *poly = NOPOLYGON;
73 REGISTER STATUSFIELD *sf, **whichstatus;
74 CHAR *newpar[4], *fieldname;
75 WINDOWFRAME *wf;
76 #if SIMTOOL
77 extern TOOL *sim_tool;
78 #endif
79 REGISTER CHAR *pp, *win;
80 REGISTER VARIABLE *var;
81 REGISTER NODEPROTO *np;
82 REGISTER NODEINST *ni;
83 extern GRAPHICS us_arbit;
84 extern COMCOMP us_windowp, us_windowup, us_windowmp;
85 REGISTER void *infstr;
86 extern GRAPHICS us_hbox;
87
88 /* get polygon */
89 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
90
91 if (count == 0)
92 {
93 count = ttygetparam(M_("Window configuration: "), &us_windowp, MAXPARS, par);
94 if (count == 0)
95 {
96 us_abortedmsg();
97 return;
98 }
99 }
100 l = estrlen(pp = par[0]);
101
102 if (namesamen(pp, x_("adjust"), l) == 0 && l >= 2)
103 {
104 if (count == 1)
105 {
106 ttyputusage(x_("window adjust STYLE"));
107 return;
108 }
109 l = estrlen(pp = par[1]);
110 if (namesamen(pp, x_("horizontal-tile"), l) == 0)
111 {
112 adjustwindowframe(0);
113 return;
114 }
115 if (namesamen(pp, x_("vertical-tile"), l) == 0)
116 {
117 adjustwindowframe(1);
118 return;
119 }
120 if (namesamen(pp, x_("cascade"), l) == 0)
121 {
122 adjustwindowframe(2);
123 return;
124 }
125 ttyputusage(x_("window adjust (horizontal-tile | vertical-tile | cascade)"));
126 return;
127 }
128
129 if (namesamen(pp, x_("all-displayed"), l) == 0 && l >= 2)
130 {
131 if (us_needwindow()) return;
132
133 #if SIMTOOL
134 /* special case for waveform window */
135 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
136 {
137 newpar[0] = x_("window");
138 newpar[1] = x_("zoom");
139 newpar[2] = x_("all-displayed");
140 telltool(sim_tool, 3, newpar);
141 return;
142 }
143 #endif
144
145 /* fill a 3D window */
146 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
147 {
148 us_3dfillview(el_curwindowpart);
149 return;
150 }
151
152 /* use direct methods on nonstandard windows */
153 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
154 {
155 if (el_curwindowpart->redisphandler != 0)
156 (*el_curwindowpart->redisphandler)(el_curwindowpart);
157 return;
158 }
159
160 np = us_needcell();
161 if (np == NONODEPROTO) return;
162
163 /* save and erase highlighting */
164 us_pushhighlight();
165 us_clearhighlightcount();
166
167 /* make the cell fill the window */
168 us_fullview(np, &lx, &hx, &ly, &hy);
169 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
170 xformbox(&lx, &hx, &ly, &hy, el_curwindowpart->outofcell);
171 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
172
173 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
174 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
175 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
176 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
177 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
178 us_gridset(el_curwindowpart, el_curwindowpart->state);
179 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
180
181 /* restore highlighting */
182 us_pophighlight(FALSE);
183 return;
184 }
185
186 if (namesamen(pp, x_("center-highlight"), l) == 0 && l >= 2)
187 {
188 if (us_needwindow()) return;
189
190 np = us_getareabounds(&lx, &hx, &ly, &hy);
191 if (np == NONODEPROTO)
192 {
193 us_abortcommand(_("Outline an area"));
194 return;
195 }
196
197 if (el_curwindowpart->curnodeproto == np) w = el_curwindowpart; else
198 {
199 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
200 if (w->curnodeproto == np && (w->state&WINDOWTYPE) == DISPWINDOW)
201 break;
202 if (w == NOWINDOWPART)
203 {
204 us_abortcommand(_("Cannot find an editing window with highlighted objects"));
205 return;
206 }
207 }
208
209 /* cannot manipulate a nonstandard window */
210 if ((w->state&WINDOWTYPE) != DISPWINDOW)
211 {
212 us_abortcommand(_("Can only pan circuit editing windows"));
213 return;
214 }
215
216 /* pre-compute current window size */
217 curwx = w->screenhx - w->screenlx;
218 curwy = w->screenhy - w->screenly;
219
220 /* center about this area without re-scaling */
221 x = (hx + lx) / 2; y = (hy + ly) / 2;
222 lx = x - curwx/2; ly = y - curwy/2;
223 hx = lx + curwx; hy = ly + curwy;
224 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
225 xformbox(&lx, &hx, &ly, &hy, el_curwindowpart->outofcell);
226 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 1);
227
228 /* save and erase highlighting */
229 us_pushhighlight();
230 us_clearhighlightcount();
231
232 startobjectchange((INTBIG)w, VWINDOWPART);
233 (void)setval((INTBIG)w, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
234 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
235 (void)setval((INTBIG)w, VWINDOWPART, x_("screenly"), ly, VINTEGER);
236 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
237 us_gridset(w, el_curwindowpart->state);
238 endobjectchange((INTBIG)w, VWINDOWPART);
239
240 /* restore highlighting */
241 us_pophighlight(FALSE);
242 return;
243 }
244
245 if (namesamen(pp, x_("cursor-centered"), l) == 0 && l >= 2)
246 {
247 #if SIMTOOL
248 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
249 {
250 if (us_needwindow()) return;
251 newpar[0] = x_("window");
252 newpar[1] = x_("cursor");
253 newpar[2] = x_("center");
254 telltool(sim_tool, 3, newpar);
255 return;
256 }
257 #endif
258
259 np = us_needcell();
260 if (np == NONODEPROTO) return;
261
262 /* cannot manipulate a nonstandard window */
263 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
264 {
265 us_abortcommand(_("Can only pan circuit editing windows"));
266 return;
267 }
268
269 if (us_demandxy(&xcur, &ycur)) return;
270
271 /* pre-compute current window size */
272 curwx = el_curwindowpart->screenhx - el_curwindowpart->screenlx;
273 curwy = el_curwindowpart->screenhy - el_curwindowpart->screenly;
274 lx = xcur - curwx/2; ly = ycur - curwy/2;
275 hx = lx + curwx; hy = ly + curwy;
276 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
277 xformbox(&lx, &hx, &ly, &hy, el_curwindowpart->outofcell);
278 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 1);
279
280 /* save and erase highlighting */
281 us_pushhighlight();
282 us_clearhighlightcount();
283
284 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
285 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
286 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
287 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
288 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
289 us_gridset(el_curwindowpart, el_curwindowpart->state);
290 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
291
292 /* restore highlighting */
293 us_pophighlight(FALSE);
294 return;
295 }
296
297 /* handle deletion of separate windows */
298 if (namesamen(pp, x_("delete"), l) == 0 && l >= 2)
299 {
300 /* close the messages window if in front and can be closed */
301 if (closefrontmostmessages()) return;
302
303 /* delete split if there are no multiple window frames */
304 if (!graphicshas(CANUSEFRAMES))
305 {
306 if (us_needwindow()) return;
307 us_killcurrentwindow(TRUE);
308 return;
309 }
310
311 /* disallow if this is the last window and it must remain */
312 if (!graphicshas(CANHAVENOWINDOWS))
313 {
314 /* disallow deletion if this is the last window */
315 i = 0;
316 for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
317 if (wf->floating == 0) i++;
318 if (i <= 1)
319 {
320 ttyputerr(_("Sorry, cannot delete the last window"));
321 return;
322 }
323 }
324
325 /* get the current frame */
326 wf = getwindowframe(FALSE);
327 if (wf == NOWINDOWFRAME)
328 {
329 us_abortcommand(_("No current window to delete"));
330 return;
331 }
332
333 /* save highlighting and turn it off */
334 us_pushhighlight();
335 us_clearhighlightcount();
336
337 startobjectchange((INTBIG)us_tool, VTOOL);
338
339 /* kill all editor windows on this frame */
340 neww = NOWINDOWPART;
341 for(w = el_topwindowpart; w != NOWINDOWPART; w = nextw)
342 {
343 nextw = w->nextwindowpart;
344 if (w->frame != wf)
345 {
346 neww = w;
347 continue;
348 }
349
350 /* kill this window */
351 killwindowpart(w);
352 }
353 endobjectchange((INTBIG)us_tool, VTOOL);
354
355 /* if (neww == NOWINDOWPART) */
356 el_curwindowpart = NOWINDOWPART;
357 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)neww, VWINDOWPART|VDONTSAVE);
358 if (neww != NOWINDOWPART) np = neww->curnodeproto; else np = NONODEPROTO;
359 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("curnodeproto"), (INTBIG)np, VNODEPROTO);
360
361 /* restore highlighting */
362 us_pophighlight(FALSE);
363 return;
364 }
365
366 if (namesamen(pp, x_("down"), l) == 0 && l >= 2)
367 {
368 if (us_needwindow()) return;
369 if (count < 2) pp = x_("0.5"); else pp = par[1];
370 switch (el_curwindowpart->state&WINDOWTYPE)
371 {
372 case DISPWINDOW:
373 if (us_needcell() == NONODEPROTO) return;
374 if (pp[estrlen(pp)-1] == 'l') dist = atola(pp, 0); else
375 dist = muldiv(atofr(pp), (el_curwindowpart->screenhy - el_curwindowpart->screenly), WHOLE);
376 us_slideup(-dist);
377 return;
378 case DISP3DWINDOW:
379 us_3dpanview(el_curwindowpart, 0, -1);
380 return;
381 case TEXTWINDOW:
382 us_pantext(el_curwindowpart, 0, -1);
383 return;
384 #if SIMTOOL
385 case WAVEFORMWINDOW:
386 newpar[0] = x_("window");
387 newpar[1] = x_("move");
388 newpar[2] = x_("down");
389 telltool(sim_tool, 3, newpar);
390 return;
391 #endif
392 case EXPLORERWINDOW:
393 us_explorevpan(el_curwindowpart, -1);
394 return;
395 }
396 us_abortcommand(_("Cannot pan this kind of windows"));
397 return;
398 }
399
400 if (namesamen(pp, x_("dragging"), l) == 0 && l >= 3)
401 {
402 if (count >= 2)
403 {
404 pp = par[1];
405 if (namesame(pp, x_("on")) == 0)
406 (void)setval((INTBIG)us_tool, VTOOL, x_("toolstate"), us_tool->toolstate | INTERACTIVE, VINTEGER);
407 else if (namesamen(pp, x_("of"), 2) == 0)
408 (void)setval((INTBIG)us_tool, VTOOL, x_("toolstate"), us_tool->toolstate & ~INTERACTIVE, VINTEGER);
409 else
410 {
411 ttyputusage(x_("window dragging on|off"));
412 return;
413 }
414 }
415 if ((us_tool->toolstate&INTERACTIVE) == 0)
416 ttyputverbose(M_("Cursor-based commands will act immediately")); else
417 ttyputverbose(M_("Cursor-based commands will drag their objects"));
418 return;
419 }
420
421 if (namesamen(pp, x_("explore"), l) == 0)
422 {
423 /* see if this frame already has an explorer */
424 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
425 {
426 if (w->frame != el_curwindowpart->frame) continue;
427 if ((w->state&WINDOWTYPE) == EXPLORERWINDOW) break;
428 }
429 if (w != NOWINDOWPART)
430 {
431 /* the explorer is up, delete it */
432 el_curwindowpart = w;
433 us_killcurrentwindow(TRUE);
434 return;
435 }
436
437 /* make an explorer window */
438 w = el_curwindowpart;
439 if (w == NOWINDOWPART)
440 {
441 w = us_wantnewwindow(0);
442 if (w == NOWINDOWPART)
443 {
444 us_abortcommand(_("Cannot create new window frame"));
445 return;
446 }
447 }
448 if (estrcmp(w->location, x_("entire")) == 0)
449 {
450 w = us_splitcurrentwindow(2, FALSE, 0, us_explorerratio);
451 if (w == NOWINDOWPART) return;
452 }
453
454 /* find the other window */
455 for(oldw = el_topwindowpart; oldw != NOWINDOWPART; oldw = oldw->nextwindowpart)
456 if (oldw != w && oldw->frame == w->frame) break;
457
458 /* turn this window into an Explorer */
459 us_createexplorerstruct(w);
460
461 if (oldw != NOWINDOWPART)
462 {
463 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)oldw,
464 VWINDOWPART|VDONTSAVE);
465 us_setcellname(oldw);
466 }
467 return;
468 }
469
470 if (namesamen(pp, x_("grid-zoom"), l) == 0 && l >= 1)
471 {
472 if (us_needwindow()) return;
473
474 /* cannot zoom a nonstandard window */
475 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
476 {
477 us_abortcommand(_("Can only grid-zoom circuit editing windows"));
478 return;
479 }
480
481 np = us_needcell();
482 if (np == NONODEPROTO) return;
483 lambda = lambdaofcell(np);
484 x = muldiv(el_curwindowpart->gridx, lambda, WHOLE);
485 y = muldiv(el_curwindowpart->gridy, lambda, WHOLE);
486 curwx = el_curwindowpart->screenhx-el_curwindowpart->screenlx;
487 curwy = el_curwindowpart->screenhy-el_curwindowpart->screenly;
488 needwx = muldiv(x, el_curwindowpart->usehx-el_curwindowpart->uselx, 5);
489 needwy = muldiv(y, el_curwindowpart->usehy-el_curwindowpart->usely, 5);
490
491 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
492 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
493 lx = (hx+lx-needwx)/2; hx = lx + needwx;
494 ly = (hy+ly-needwy)/2; hy = ly + needwy;
495 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 1);
496
497 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
498 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
499 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
500 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
501 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
502 us_gridset(el_curwindowpart, el_curwindowpart->state|GRIDON);
503 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
504
505 /* redisplay */
506 us_endchanges(NOWINDOWPART);
507 us_state |= HIGHLIGHTSET;
508 us_showallhighlight();
509 return;
510 }
511
512 if (namesamen(pp, x_("highlight-displayed"), l) == 0 && l >= 3)
513 {
514 if (us_needwindow()) return;
515
516 #if SIMTOOL
517 /* special case for waveform window */
518 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
519 {
520 newpar[0] = x_("window");
521 newpar[1] = x_("zoom");
522 newpar[2] = x_("cursor");
523 telltool(sim_tool, 3, newpar);
524 return;
525 }
526 #endif
527
528 np = us_getareabounds(&lx, &hx, &ly, &hy);
529 if (np == NONODEPROTO)
530 {
531 us_abortcommand(_("Outline an area"));
532 return;
533 }
534
535 if (el_curwindowpart->curnodeproto == np) w = el_curwindowpart; else
536 {
537 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
538 if (w->curnodeproto == np && (w->state&WINDOWTYPE) == DISPWINDOW)
539 break;
540 if (w == NOWINDOWPART)
541 {
542 us_abortcommand(_("Cannot find an editing window with highlighted objects"));
543 return;
544 }
545 }
546
547 /* cannot manipulate a nonstandard window */
548 if ((w->state&WINDOWTYPE) != DISPWINDOW)
549 {
550 us_abortcommand(_("Can only adjust circuit editing windows"));
551 return;
552 }
553
554 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
555 xformbox(&lx, &hx, &ly, &hy, el_curwindowpart->outofcell);
556 if (lx == hx && ly == hy)
557 {
558 lambda = lambdaofcell(np);
559 lx -= lambda;
560 hx += lambda;
561 ly -= lambda;
562 hy += lambda;
563 }
564
565 /* save and erase highlighting */
566 us_pushhighlight();
567 us_clearhighlightcount();
568
569 /* make sure the new window has square pixels */
570 us_squarescreen(w, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
571
572 startobjectchange((INTBIG)w, VWINDOWPART);
573 (void)setval((INTBIG)w, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
574 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
575 (void)setval((INTBIG)w, VWINDOWPART, x_("screenly"), ly, VINTEGER);
576 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
577 us_gridset(w, el_curwindowpart->state);
578 endobjectchange((INTBIG)w, VWINDOWPART);
579
580 /* restore highlighting */
581 us_pophighlight(FALSE);
582 return;
583 }
584
585 if (namesamen(pp, x_("in-zoom"), l) == 0 && l >= 1)
586 {
587 if (us_needwindow()) return;
588
589 #if SIMTOOL
590 /* special case for waveform window */
591 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
592 {
593 newpar[0] = x_("window");
594 newpar[1] = x_("zoom");
595 newpar[2] = x_("in");
596 telltool(sim_tool, 3, newpar);
597 return;
598 }
599 #endif
600
601 /* zoom a 3D window */
602 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
603 {
604 us_3dzoomview(el_curwindowpart, 0.75f);
605 return;
606 }
607
608 /* cannot zoom a nonstandard window */
609 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
610 {
611 us_abortcommand(_("Can only zoom circuit editing windows"));
612 return;
613 }
614
615 np = us_needcell();
616 if (np == NONODEPROTO) return;
617 lambda = lambdaofcell(np);
618 if (count >= 2) dist = atola(par[1], 0); else
619 dist = 2 * lambda;
620 if (dist == 0)
621 {
622 us_abortcommand(_("Must zoom by a nonzero amount"));
623 return;
624 }
625
626 diffx = muldiv(el_curwindowpart->screenhx - el_curwindowpart->screenlx,
627 lambda, dist);
628 diffy = muldiv(el_curwindowpart->screenhy - el_curwindowpart->screenly,
629 lambda, dist);
630 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
631 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
632 lx = (hx+lx-diffx)/2; hx = lx + diffx;
633 ly = (hy+ly-diffy)/2; hy = ly + diffy;
634 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 1);
635
636 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
637 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
638 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
639 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
640 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
641 us_gridset(el_curwindowpart, el_curwindowpart->state);
642 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
643
644 /* restore highlighting */
645 us_endchanges(NOWINDOWPART);
646 us_state |= HIGHLIGHTSET;
647 us_showallhighlight();
648 return;
649 }
650
651 /* handle killing of the other window specially */
652 if (namesamen(pp, x_("join"), l) == 0 && l >= 1)
653 {
654 if (us_needwindow()) return;
655 us_killcurrentwindow(FALSE);
656 return;
657 }
658
659 /* handle killing of this window specially */
660 if (namesamen(pp, x_("kill"), l) == 0 && l >= 1)
661 {
662 if (us_needwindow()) return;
663 us_killcurrentwindow(TRUE);
664 return;
665 }
666
667 if (namesamen(pp, x_("left"), l) == 0 && l >= 1)
668 {
669 if (us_needwindow()) return;
670 if (count < 2) pp = x_("0.5"); else pp = par[1];
671 switch (el_curwindowpart->state&WINDOWTYPE)
672 {
673 case DISPWINDOW:
674 if (us_needcell() == NONODEPROTO) return;
675 if (pp[estrlen(pp)-1] == 'l') dist = atola(pp, 0); else
676 dist = muldiv(atofr(pp), (el_curwindowpart->screenhx - el_curwindowpart->screenlx), WHOLE);
677 us_slideleft(dist);
678 return;
679 case DISP3DWINDOW:
680 us_3dpanview(el_curwindowpart, 1, 0);
681 return;
682 case TEXTWINDOW:
683 us_pantext(el_curwindowpart, 1, 0);
684 return;
685 #if SIMTOOL
686 case WAVEFORMWINDOW:
687 newpar[0] = x_("window");
688 newpar[1] = x_("move");
689 newpar[2] = x_("left");
690 telltool(sim_tool, 3, newpar);
691 return;
692 #endif
693 }
694 us_abortcommand(_("Cannot pan this kind of windows"));
695 return;
696 }
697
698 if (namesamen(pp, x_("match"), l) == 0 && l >= 3)
699 {
700 /* count the number of windows */
701 for(i = 0, w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart) i++;
702 if (i <= 1)
703 {
704 us_abortcommand(_("Must be multiple windows to match them"));
705 return;
706 }
707
708 /* if there are two windows, the other to match is obvious */
709 if (i == 2)
710 {
711 if (el_curwindowpart == el_topwindowpart) w = el_topwindowpart->nextwindowpart; else
712 w = el_topwindowpart;
713 } else
714 {
715 if (count < 2)
716 {
717 count = ttygetparam(_("Other window to match: "), &us_windowmp, MAXPARS-1, &par[1]) + 1;
718 if (count == 1)
719 {
720 us_abortedmsg();
721 return;
722 }
723 }
724 win = par[1];
725 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
726 {
727 infstr = initinfstr();
728 addstringtoinfstr(infstr, describenodeproto(w->curnodeproto));
729 addtoinfstr(infstr, '(');
730 addstringtoinfstr(infstr, w->location);
731 addtoinfstr(infstr, ')');
732 if (namesame(win, returninfstr(infstr)) == 0) break;
733 }
734 if (w == NOWINDOWPART)
735 {
736 us_abortcommand(_("No window named '%s'"), win);
737 return;
738 }
739 }
740
741 if (w == el_curwindowpart)
742 {
743 us_abortcommand(_("Choose a window other than the current one to match"));
744 return;
745 }
746
747 /* cannot match if they are editing the same thing */
748 if ((w->state&WINDOWTYPE) != (el_curwindowpart->state&WINDOWTYPE))
749 {
750 us_abortcommand(_("Can only match windows that edit the same thing"));
751 return;
752 }
753
754 /* cannot match if they are not normal display windows */
755 if ((w->state&WINDOWTYPE) != DISPWINDOW)
756 {
757 us_abortcommand(_("Can only match normal editing windows"));
758 return;
759 }
760
761 /* save and erase highlighting */
762 us_pushhighlight();
763 us_clearhighlightcount();
764
765 /* make window "el_curwindowpart" match the scale of "w" */
766 diffx = muldiv(w->screenhx - w->screenlx, el_curwindowpart->usehx -
767 el_curwindowpart->uselx, w->usehx - w->uselx);
768 diffx = diffx - (el_curwindowpart->screenhx - el_curwindowpart->screenlx);
769 diffy = muldiv(w->screenhy - w->screenly, el_curwindowpart->usehy -
770 el_curwindowpart->usely, w->usehy - w->usely);
771 diffy = diffy - (el_curwindowpart->screenhy - el_curwindowpart->screenly);
772
773 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
774 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"),
775 el_curwindowpart->screenlx - diffx/2, VINTEGER);
776 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"),
777 el_curwindowpart->screenhx + diffx/2, VINTEGER);
778 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"),
779 el_curwindowpart->screenly - diffy/2, VINTEGER);
780 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"),
781 el_curwindowpart->screenhy + diffy/2, VINTEGER);
782 us_gridset(el_curwindowpart, el_curwindowpart->state);
783 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
784
785 /* restore highlighting */
786 us_pophighlight(FALSE);
787 return;
788 }
789
790 if (namesamen(pp, x_("measure"), l) == 0 && l >= 2)
791 {
792 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW &&
793 (el_curwindowpart->state&WINDOWTYPE) != WAVEFORMWINDOW)
794 {
795 us_abortcommand(_("Can only measure distance in an edit and waveform windows"));
796 return;
797 }
798 if (el_curwindowpart->curnodeproto == NONODEPROTO)
799 {
800 us_abortcommand(_("No cell in this window to measure"));
801 return;
802 }
803 if ((us_state&MEASURINGDISTANCE) != 0)
804 {
805 us_state &= ~(MEASURINGDISTANCE | MEASURINGDISTANCEINI);
806 ttyputmsg(_("Exiting distance measurement mode"));
807 } else
808 {
809 us_clearhighlightcount();
810 us_state |= MEASURINGDISTANCE | MEASURINGDISTANCEINI;
811 ttyputmsg(_("Entering distance measurement mode"));
812 }
813 return;
814 }
815
816 if (namesamen(pp, x_("move-display"), l) == 0 && l >= 2)
817 {
818 if (us_needwindow()) return;
819 #ifdef USEQT
820 movedisplay();
821 #else
822 ttyputmsg(_("(Display move works only on Qt"));
823 #endif
824 return;
825 }
826
827 if (namesamen(pp, x_("name"), l) == 0 && l >= 2)
828 {
829 if (us_needwindow()) return;
830 if (count <= 1)
831 {
832 ttyputusage(x_("window name VIEWNAME"));
833 return;
834 }
835 infstr = initinfstr();
836 addstringtoinfstr(infstr, x_("USER_windowview_"));
837 addstringtoinfstr(infstr, par[1]);
838 var = getval((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, returninfstr(infstr));
839 if (var == NOVARIABLE)
840 {
841 us_abortcommand(_("Cannot find saved window view '%s'"), par[1]);
842 return;
843 }
844
845 lx = ((INTBIG *)var->addr)[0];
846 hx = ((INTBIG *)var->addr)[1];
847 ly = ((INTBIG *)var->addr)[2];
848 hy = ((INTBIG *)var->addr)[3];
849
850 /* if the window extent changed, make sure the pixels are square */
851 if (((INTBIG *)var->addr)[5] - ((INTBIG *)var->addr)[4] != el_curwindowpart->usehx - el_curwindowpart->uselx ||
852 ((INTBIG *)var->addr)[7] - ((INTBIG *)var->addr)[6] != el_curwindowpart->usehy - el_curwindowpart->usely)
853 {
854 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
855 }
856
857 /* save and erase highlighting */
858 us_pushhighlight();
859 us_clearhighlightcount();
860
861 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
862 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
863 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
864 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
865 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
866 us_gridset(el_curwindowpart, el_curwindowpart->state);
867 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
868
869 /* restore highlighting */
870 us_pophighlight(FALSE);
871 return;
872 }
873
874 /* handle creating of separate windows */
875 if (namesamen(pp, x_("new"), l) == 0 && l >= 2)
876 {
877 /* create a new frame */
878 w = us_wantnewwindow(0);
879 if (w == NOWINDOWPART)
880 {
881 us_abortcommand(_("Cannot create new window frame"));
882 return;
883 }
884 return;
885 }
886
887 if (namesamen(pp, x_("normal-cursor"), l) == 0 && l >= 2)
888 {
889 if (count < 2)
890 {
891 ttyputusage(x_("window normal-cursor CURSORNAME"));
892 return;
893 }
894 l = estrlen(pp = par[1]);
895 if (namesamen(pp, x_("standard"), l) == 0) setnormalcursor(NORMALCURSOR); else
896 if (namesamen(pp, x_("pen"), l) == 0) setnormalcursor(PENCURSOR); else
897 if (namesamen(pp, x_("tee"), l) == 0) setnormalcursor(TECHCURSOR); else
898 ttyputbadusage(x_("window cursor"));
899 return;
900 }
901
902 if (namesamen(pp, x_("out-zoom"), l) == 0 && l >= 4)
903 {
904 if (us_needwindow()) return;
905
906 #if SIMTOOL
907 /* special case for waveform window */
908 if ((el_curwindowpart->state&WINDOWTYPE) == WAVEFORMWINDOW)
909 {
910 newpar[0] = x_("window");
911 newpar[1] = x_("zoom");
912 newpar[2] = x_("out");
913 telltool(sim_tool, 3, newpar);
914 return;
915 }
916 #endif
917
918 /* zoom a 3D window */
919 if ((el_curwindowpart->state&WINDOWTYPE) == DISP3DWINDOW)
920 {
921 us_3dzoomview(el_curwindowpart, 1.5f);
922 return;
923 }
924
925 /* cannot zoom a nonstandard window */
926 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
927 {
928 us_abortcommand(_("Can only zoom circuit editing windows"));
929 return;
930 }
931
932 np = us_needcell();
933 if (np == NONODEPROTO) return;
934 lambda = lambdaofcell(np);
935 if (count >= 2) dist = atola(par[1], 0); else
936 dist = 2 * lambda;
937 if (dist == 0)
938 {
939 us_abortcommand(_("Must zoom by a nonzero amount"));
940 return;
941 }
942
943 lx = el_curwindowpart->screenlx; hx = el_curwindowpart->screenhx;
944 ly = el_curwindowpart->screenly; hy = el_curwindowpart->screenhy;
945 i = muldiv(el_curwindowpart->screenhx - el_curwindowpart->screenlx, dist, lambda);
946 lx = (lx+hx-i)/2; hx = lx + i;
947 i = muldiv(el_curwindowpart->screenhy - el_curwindowpart->screenly, dist, lambda);
948 ly = (ly+hy-i)/2; hy = ly + i;
949 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 1);
950
951 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
952 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
953 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
954 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
955 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
956 us_gridset(el_curwindowpart, el_curwindowpart->state);
957 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
958
959 /* restore highlighting */
960 us_endchanges(NOWINDOWPART);
961 us_state |= HIGHLIGHTSET;
962 us_showallhighlight();
963 return;
964 }
965
966 if (namesamen(pp, x_("outline-edit-toggle"), l) == 0 && l >= 4)
967 {
968 /* in outline edit mode:
969 * cursor is a pen
970 * "Erase" deletes selected point
971 * "Rotate" rotates about point
972 * "Mirror" mirrors about point
973 * "Get Info" gives polygon info
974 * left arrow goes to previous point
975 * right arrow goes to next point
976 * selection button selects a point
977 * creation button creates a point
978 */
979 if (us_needwindow()) return;
980
981 /* find the rotate menu entry */
982 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) == 0)
983 {
984 /* enter outline-edit mode: must have a current node */
985 ni = (NODEINST *)us_getobject(VNODEINST, FALSE);
986 if (ni == NONODEINST) return;
987 if ((ni->proto->userbits&HOLDSTRACE) == 0)
988 {
989 us_abortcommand(_("Sorry, %s nodes cannot hold outline information"),
990 describenodeproto(ni->proto));
991 return;
992 }
993 us_pushhighlight();
994 us_clearhighlightcount();
995 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
996 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
997 el_curwindowpart->state | WINDOWOUTLINEEDMODE, VINTEGER);
998 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
999 us_pophighlight(FALSE);
1000
1001 TDCLEAR(descript);
1002 TDSETSIZE(descript, TXTSETPOINTS(18));
1003 us_hbox.col = HIGHLIT;
1004 us_writetext(el_curwindowpart->uselx, el_curwindowpart->usehx,
1005 el_curwindowpart->usehy-30, el_curwindowpart->usehy, &us_hbox, _("OUTLINE EDIT MODE:"),
1006 descript, el_curwindowpart, NOTECHNOLOGY);
1007 infstr = initinfstr();
1008 var = getval((INTBIG)us_tool, VTOOL, VSTRING, "USER_local_capf");
1009 if (var != NOVARIABLE) formatinfstr(infstr, _("Use %s to select/move point; "), (CHAR *)var->addr);
1010 var = getval((INTBIG)us_tool, VTOOL, VSTRING, "USER_local_capg");
1011 if (var != NOVARIABLE) formatinfstr(infstr, _(" Use %s to create point; "), (CHAR *)var->addr);
1012 us_writetext(el_curwindowpart->uselx, el_curwindowpart->usehx,
1013 el_curwindowpart->usehy-60, el_curwindowpart->usehy-30, &us_hbox, returninfstr(infstr),
1014 descript, el_curwindowpart, NOTECHNOLOGY);
1015 } else
1016 {
1017 /* leave outline edit mode */
1018 us_pushhighlight();
1019 us_clearhighlightcount();
1020 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
1021 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("state"),
1022 el_curwindowpart->state & ~WINDOWOUTLINEEDMODE, VINTEGER);
1023 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
1024 us_pophighlight(FALSE);
1025 }
1026 noundoallowed();
1027 return;
1028 }
1029
1030 if (namesamen(pp, x_("overlappable-display"), l) == 0 && l >= 5)
1031 {
1032 if (count >= 2)
1033 {
1034 pp = par[1];
1035 l = estrlen(pp);
1036 if (namesamen(pp, x_("on"), l) == 0)
1037 {
1038 us_state &= ~NONOVERLAPPABLEDISPLAY;
1039 } else if (namesamen(pp, x_("off"), l) == 0)
1040 {
1041 us_state |= NONOVERLAPPABLEDISPLAY;
1042 } else
1043 {
1044 ttyputusage(x_("window overlappable-display [on|off]"));
1045 return;
1046 }
1047 }
1048 if ((us_state&NONOVERLAPPABLEDISPLAY) != 0)
1049 ttyputverbose(M_("Transparent layers will not be handled")); else
1050 ttyputverbose(M_("Transparent layers will be drawn properly"));
1051 return;
1052 }
1053
1054 if (namesamen(pp, x_("overview"), l) == 0 && l >= 5)
1055 {
1056 ttyputerr(_("Cannot make an overview window yet"));
1057 return;
1058 }
1059
1060 if (namesamen(pp, x_("peek"), l) == 0 && l >= 2)
1061 {
1062 np = us_getareabounds(&lx, &hx, &ly, &hy);
1063 if (np == NONODEPROTO)
1064 {
1065 us_abortcommand(_("Enclose an area to be peeked"));
1066 return;
1067 }
1068
1069 if (el_curwindowpart->curnodeproto == np) w = el_curwindowpart; else
1070 {
1071 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1072 if (w->curnodeproto == np && (w->state&WINDOWTYPE) == DISPWINDOW)
1073 break;
1074 if (w == NOWINDOWPART)
1075 {
1076 us_abortcommand(_("Cannot find an editing window with highlighted objects"));
1077 return;
1078 }
1079 }
1080
1081 /* clip this bounding box to the window extent */
1082 lx = maxi(lx, w->screenlx);
1083 hx = mini(hx, w->screenhx);
1084 ly = maxi(ly, w->screenly);
1085 hy = mini(hy, w->screenhy);
1086
1087 /* save and erase highlighting */
1088 us_pushhighlight();
1089 us_clearhighlightcount();
1090
1091 /* un-draw the peek area */
1092 maketruerectpoly(lx, hx, ly, hy, poly);
1093 poly->desc = &us_arbit;
1094 us_arbit.col = 0;
1095 us_arbit.bits = LAYERO;
1096 poly->style = FILLEDRECT;
1097 us_showpoly(poly, w);
1098
1099 /* get new window to describe sub-area */
1100 w = us_subwindow(lx, hx, ly, hy, w);
1101
1102 /* do the peek operation */
1103 us_dopeek(lx, hx, ly, hy, np, w);
1104
1105 /* restore highlighting */
1106 us_pophighlight(FALSE);
1107 return;
1108 }
1109
1110 if (namesamen(pp, x_("right"), l) == 0 && l >= 1)
1111 {
1112 if (us_needwindow()) return;
1113 if (count < 2) pp = x_("0.5"); else pp = par[1];
1114 switch (el_curwindowpart->state&WINDOWTYPE)
1115 {
1116 case DISPWINDOW:
1117 if (us_needcell() == NONODEPROTO) return;
1118 if (pp[estrlen(pp)-1] == 'l') dist = atola(pp, 0); else
1119 dist = muldiv(atofr(pp), (el_curwindowpart->screenhx - el_curwindowpart->screenlx), WHOLE);
1120 us_slideleft(-dist);
1121 return;
1122 case DISP3DWINDOW:
1123 us_3dpanview(el_curwindowpart, -1, 0);
1124 return;
1125 case TEXTWINDOW:
1126 us_pantext(el_curwindowpart, -1, 0);
1127 return;
1128 #if SIMTOOL
1129 case WAVEFORMWINDOW:
1130 newpar[0] = x_("window");
1131 newpar[1] = x_("move");
1132 newpar[2] = x_("right");
1133 telltool(sim_tool, 3, newpar);
1134 return;
1135 #endif
1136 }
1137 us_abortcommand(_("Cannot pan this kind of windows"));
1138 return;
1139 }
1140
1141 if (namesamen(pp, x_("save"), l) == 0 && l >= 2)
1142 {
1143 if (us_needwindow()) return;
1144 if (count <= 1)
1145 {
1146 ttyputusage(x_("window save VIEWNAME"));
1147 return;
1148 }
1149 windowView[0] = el_curwindowpart->screenlx;
1150 windowView[1] = el_curwindowpart->screenhx;
1151 windowView[2] = el_curwindowpart->screenly;
1152 windowView[3] = el_curwindowpart->screenhy;
1153 windowView[4] = el_curwindowpart->uselx;
1154 windowView[5] = el_curwindowpart->usehx;
1155 windowView[6] = el_curwindowpart->usely;
1156 windowView[7] = el_curwindowpart->usehy;
1157 infstr = initinfstr();
1158 addstringtoinfstr(infstr, x_("USER_windowview_"));
1159 addstringtoinfstr(infstr, par[1]);
1160 (void)setval((INTBIG)us_tool, VTOOL, returninfstr(infstr), (INTBIG)windowView,
1161 VINTEGER|VISARRAY|(8<<VLENGTHSH)|VDONTSAVE);
1162 ttyputverbose(M_("Window view %s saved"), par[1]);
1163 return;
1164 }
1165
1166 if (namesamen(pp, x_("split"), l) == 0 && l >= 2)
1167 {
1168 if (us_needwindow()) return;
1169 splitkey = 0;
1170 if (count > 1)
1171 {
1172 l = estrlen(pp = par[1]);
1173 if (namesamen(pp, x_("horizontal"), l) == 0 && l >= 1) splitkey = 1; else
1174 if (namesamen(pp, x_("vertical"), l) == 0 && l >= 1) splitkey = 2; else
1175 {
1176 ttyputusage(x_("window split horizontal|vertical"));
1177 return;
1178 }
1179 }
1180
1181 /* split the window */
1182 (void)us_splitcurrentwindow(splitkey, TRUE, 0, 50);
1183 return;
1184 }
1185
1186 if (namesamen(pp, x_("status-bar"), l) == 0 && l >= 2)
1187 {
1188 if (count < 2)
1189 {
1190 /* report all status bar locations */
1191 for(i=0; us_statusfields[i].fieldaddr != 0; i++)
1192 {
1193 sf = *us_statusfields[i].fieldaddr;
1194 if (sf == 0) continue;
1195 if (sf->line == 0)
1196 ttyputmsg(M_("Window title has %s"), us_statusfields[i].fieldaddr); else
1197 ttyputmsg(M_("Line %ld from %3ld%% to %3ld%% is %s"), sf->line, sf->startper,
1198 sf->endper, us_statusfields[i].fieldaddr);
1199 }
1200 return;
1201 }
1202
1203 if (namesamen(par[1], x_("current-node"), estrlen(par[1])) == 0)
1204 {
1205 if (count < 3)
1206 {
1207 if ((us_state&NONPERSISTENTCURNODE) != 0)
1208 ttyputmsg(M_("Current node displayed temporarily")); else
1209 ttyputmsg(M_("Current node display is persistent"));
1210 return;
1211 }
1212 l = estrlen(pp = par[2]);
1213 if (namesamen(pp, x_("persistent"), l) == 0)
1214 {
1215 us_state &= ~NONPERSISTENTCURNODE;
1216 ttyputverbose(M_("Current node display is persistent"));
1217 return;
1218 }
1219 if (namesamen(pp, x_("temporary"), l) == 0)
1220 {
1221 us_state |= NONPERSISTENTCURNODE;
1222 ttyputverbose(M_("Current node displayed temporarily"));
1223 return;
1224 }
1225 ttyputusage(x_("window status-bar current-node [persistent|temporary]"));
1226 return;
1227 }
1228
1229 if (count < 3)
1230 {
1231 ttyputusage(x_("window status-bar COMMAND FIELD..."));
1232 return;
1233 }
1234
1235 /* determine area being controlled */
1236 l = estrlen(pp = par[2]);
1237 for(i=0; us_statusfields[i].keyword != 0; i++)
1238 if (namesamen(pp, us_statusfields[i].keyword, l) == 0 &&
1239 l >= us_statusfields[i].unique)
1240 {
1241 whichstatus = us_statusfields[i].fieldaddr;
1242 break;
1243 }
1244 if (us_statusfields[i].keyword == 0)
1245 {
1246 us_abortcommand(_("Unknown status-bar location: %s"), pp);
1247 return;
1248 }
1249
1250 /* get option */
1251 l = estrlen(pp = par[1]);
1252 if (namesamen(pp, x_("delete"), l) == 0)
1253 {
1254 if (*whichstatus != 0) ttyfreestatusfield(*whichstatus);
1255 *whichstatus = 0;
1256 us_redostatus(NOWINDOWFRAME);
1257 return;
1258 }
1259 if (namesamen(pp, x_("add"), l) == 0)
1260 {
1261 if (count < 6)
1262 {
1263 ttyputusage(x_("window status-bar add FIELD LINE STARTPER ENDPER [TITLE]"));
1264 return;
1265 }
1266 lineno = eatoi(par[3]);
1267 if (lineno < 0 || lineno > ttynumstatuslines())
1268 {
1269 us_abortcommand(_("Line number must range from 0 to %ld"), ttynumstatuslines());
1270 return;
1271 }
1272 startper = eatoi(par[4]);
1273 if (startper < 0 || startper > 100)
1274 {
1275 us_abortcommand(_("Starting percentage must range from 0 to 100"));
1276 return;
1277 }
1278 endper = eatoi(par[5]);
1279 if (endper <= startper || endper > 100)
1280 {
1281 us_abortcommand(_("Ending percentage must range from %ld to 100"), startper+1);
1282 return;
1283 }
1284 if (count == 7) fieldname = par[6]; else fieldname = x_("");
1285 if (*whichstatus != 0) ttyfreestatusfield(*whichstatus);
1286 *whichstatus = ttydeclarestatusfield(lineno, startper, endper, fieldname);
1287 us_redostatus(NOWINDOWFRAME);
1288 return;
1289 }
1290 ttyputusage(x_("window status-bar [add | delete]"));
1291 return;
1292 }
1293
1294 if (namesamen(pp, x_("tiny-cells"), l) == 0 && l >= 2)
1295 {
1296 if (us_needwindow()) return;
1297 if (count >= 2)
1298 {
1299 l = estrlen(pp = par[1]);
1300 if (namesamen(pp, x_("draw"), l) == 0)
1301 {
1302 startobjectchange((INTBIG)us_tool, VTOOL);
1303 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
1304 us_useroptions | DRAWTINYCELLS, VINTEGER);
1305 if (count >= 3)
1306 {
1307 i = atofr(par[2]);
1308 (void)setvalkey((INTBIG)us_tool, VTOOL, us_tinylambdaperpixelkey,
1309 i, VFRACT);
1310 }
1311 endobjectchange((INTBIG)us_tool, VTOOL);
1312 } else if (namesamen(pp, x_("hash-out"), l) == 0)
1313 {
1314 startobjectchange((INTBIG)us_tool, VTOOL);
1315 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
1316 us_useroptions & ~DRAWTINYCELLS, VINTEGER);
1317 endobjectchange((INTBIG)us_tool, VTOOL);
1318 } else
1319 {
1320 ttyputusage(x_("window tiny-cells draw|(hash-out [LAMBDAPERPIXEL])"));
1321 return;
1322 }
1323 }
1324 if ((us_useroptions&DRAWTINYCELLS) != 0)
1325 {
1326 ttyputverbose(M_("Tiny cells will be drawn"));
1327 } else
1328 {
1329 ttyputverbose(M_("Tiny cells will be hashed-out after %s lambda per pixel"),
1330 frtoa(us_tinyratio));
1331 }
1332 return;
1333 }
1334
1335 if (namesamen(pp, x_("trace-displayed"), l) == 0 && l >= 2)
1336 {
1337 np = us_needcell();
1338 if (np == NONODEPROTO) return;
1339
1340 /* cannot manipulate a nonstandard window */
1341 if ((el_curwindowpart->state&WINDOWTYPE) != DISPWINDOW)
1342 {
1343 us_abortcommand(_("Can only adjust circuit editing windows"));
1344 return;
1345 }
1346
1347 /* pre-compute current window size */
1348 curwx = el_curwindowpart->screenhx - el_curwindowpart->screenlx;
1349 curwy = el_curwindowpart->screenhy - el_curwindowpart->screenly;
1350
1351 var = getval((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_commandvarname('T'));
1352 if (var == NOVARIABLE)
1353 {
1354 us_abortcommand(_("Issue an outline before zooming into that area"));
1355 return;
1356 }
1357 size = getlength(var) / 2;
1358 nogood = 0;
1359 for(i=0; i<size; i++)
1360 {
1361 x = ((INTBIG *)var->addr)[i*2];
1362 y = ((INTBIG *)var->addr)[i*2+1];
1363 if (us_setxy(x, y)) nogood++;
1364 (void)getxy(&xcur, &ycur);
1365 if (i == 0)
1366 {
1367 lx = hx = xcur; ly = hy = ycur;
1368 } else
1369 {
1370 lx = mini(lx, xcur); hx = maxi(hx, xcur);
1371 ly = mini(ly, ycur); hy = maxi(hy, ycur);
1372 }
1373 }
1374 if (nogood != 0)
1375 {
1376 us_abortcommand(_("Outline not inside window"));
1377 return;
1378 }
1379
1380 /* save and erase highlighting */
1381 us_pushhighlight();
1382 us_clearhighlightcount();
1383
1384 /* set the new window size */
1385 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
1386
1387 startobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
1388 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
1389 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
1390 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
1391 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
1392 us_gridset(el_curwindowpart, el_curwindowpart->state);
1393 endobjectchange((INTBIG)el_curwindowpart, VWINDOWPART);
1394
1395 /* restore highlighting */
1396 us_pophighlight(FALSE);
1397 return;
1398 }
1399
1400 if (namesamen(pp, x_("up"), l) == 0 && l >= 2)
1401 {
1402 if (us_needwindow()) return;
1403 if (count < 2) pp = x_("0.5"); else pp = par[1];
1404 switch (el_curwindowpart->state&WINDOWTYPE)
1405 {
1406 case DISPWINDOW:
1407 if (us_needcell() == NONODEPROTO) return;
1408 if (pp[estrlen(pp)-1] == 'l') dist = atola(pp, 0); else
1409 dist = muldiv(atofr(pp), (el_curwindowpart->screenhy - el_curwindowpart->screenly), WHOLE);
1410 us_slideup(dist);
1411 return;
1412 case DISP3DWINDOW:
1413 us_3dpanview(el_curwindowpart, 0, 1);
1414 return;
1415 case TEXTWINDOW:
1416 us_pantext(el_curwindowpart, 0, 1);
1417 return;
1418 #if SIMTOOL
1419 case WAVEFORMWINDOW:
1420 newpar[0] = x_("window");
1421 newpar[1] = x_("move");
1422 newpar[2] = x_("up");
1423 telltool(sim_tool, 3, newpar);
1424 return;
1425 #endif
1426 case EXPLORERWINDOW:
1427 us_explorevpan(el_curwindowpart, 1);
1428 return;
1429 }
1430 us_abortcommand(_("Cannot pan this kind of windows"));
1431 return;
1432 }
1433
1434 if (namesamen(pp, x_("use"), l) == 0 && l >= 2)
1435 {
1436 if (count <= 1)
1437 {
1438 count = ttygetparam(M_("Window to use: "), &us_windowup, MAXPARS-1, &par[1]) + 1;
1439 if (count == 1)
1440 {
1441 us_abortedmsg();
1442 return;
1443 }
1444 }
1445 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1446 {
1447 infstr = initinfstr();
1448 addstringtoinfstr(infstr, describenodeproto(w->curnodeproto));
1449 addtoinfstr(infstr, '(');
1450 addstringtoinfstr(infstr, w->location);
1451 addtoinfstr(infstr, ')');
1452 if (namesame(par[1], returninfstr(infstr)) == 0) break;
1453 }
1454 if (w == NOWINDOWPART)
1455 {
1456 us_abortcommand(_("No window named '%s'"), par[1]);
1457 return;
1458 }
1459 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w, VWINDOWPART|VDONTSAVE);
1460 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("curnodeproto"), (INTBIG)w->curnodeproto, VNODEPROTO);
1461 return;
1462 }
1463
1464 if (namesamen(pp, x_("zoom-scale"), l) == 0 && l >= 1)
1465 {
1466 if (count >= 2)
1467 {
1468 l = estrlen(pp = par[1]);
1469 if (namesamen(pp, x_("integral"), l) == 0 && l >= 1)
1470 (void)setval((INTBIG)us_tool, VTOOL, x_("toolstate"), us_tool->toolstate | INTEGRAL, VINTEGER);
1471 else if (namesamen(pp, x_("nonintegral"), l) == 0 && l >= 1)
1472 (void)setval((INTBIG)us_tool, VTOOL, x_("toolstate"), us_tool->toolstate & ~INTEGRAL, VINTEGER);
1473 else
1474 {
1475 ttyputusage(x_("window zoom-scale integral|nonintegral"));
1476 return;
1477 }
1478 }
1479 if ((us_tool->toolstate&INTEGRAL) == 0)
1480 ttyputverbose(M_("Window scaling will be continuous")); else
1481 ttyputverbose(M_("Window scaling will force integral pixel alignment"));
1482 return;
1483 }
1484
1485 if (namesamen(pp, x_("1-window"), l) == 0 && l >= 1)
1486 {
1487 if (us_needwindow()) return;
1488
1489 if (estrcmp(el_curwindowpart->location, x_("entire")) == 0)
1490 {
1491 ttyputmsg(_("Already displaying only one window"));
1492 return;
1493 }
1494
1495 /* remember the current window */
1496 oldw = el_curwindowpart;
1497
1498 /* turn off highlighting */
1499 us_pushhighlight();
1500 us_clearhighlightcount();
1501 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)NOWINDOWPART,
1502 VWINDOWPART|VDONTSAVE);
1503
1504 startobjectchange((INTBIG)us_tool, VTOOL);
1505
1506 /* create a new window */
1507 neww = newwindowpart(x_("entire"), oldw);
1508 if (neww == NOWINDOWPART)
1509 {
1510 ttyputnomemory();
1511 return;
1512 }
1513
1514 /* if reducing to an editor window, move the editor structure */
1515 if ((oldw->state&WINDOWTYPE) == TEXTWINDOW ||
1516 (oldw->state&WINDOWTYPE) == POPTEXTWINDOW)
1517 {
1518 (void)setval((INTBIG)neww, VWINDOWPART, x_("editor"), (INTBIG)oldw->editor, VADDRESS);
1519 (void)setval((INTBIG)oldw, VWINDOWPART, x_("editor"), -1, VADDRESS);
1520 }
1521
1522 /* now delete all other windows */
1523 for(w = el_topwindowpart; w != NOWINDOWPART; w = nextw)
1524 {
1525 nextw = w->nextwindowpart;
1526 if (w->frame != neww->frame) continue;
1527 if (w != neww) killwindowpart(w);
1528 }
1529
1530 /* set the window extents */
1531 us_windowfit(NOWINDOWFRAME, FALSE, 1);
1532 endobjectchange((INTBIG)us_tool, VTOOL);
1533
1534 /* restore highlighting */
1535 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)neww,
1536 VWINDOWPART|VDONTSAVE);
1537 us_pophighlight(FALSE);
1538 return;
1539 }
1540
1541 if (namesamen(pp, x_("3-dimensional"), l) == 0 && l >= 1)
1542 {
1543 if (us_needwindow()) return;
1544 w = el_curwindowpart;
1545 if (count < 2)
1546 {
1547 ttyputusage(x_("window 3-dimensional OPTION"));
1548 return;
1549 }
1550
1551 l = estrlen(pp = par[1]);
1552 if (namesamen(pp, x_("begin"), l) == 0 && l >= 1)
1553 {
1554 if ((w->state&WINDOWTYPE) == DISP3DWINDOW)
1555 {
1556 ttyputmsg(_("Window already shown in 3 dimensions"));
1557 return;
1558 }
1559 if ((w->state&WINDOWTYPE) != DISPWINDOW)
1560 {
1561 us_abortcommand(_("Cannot view this window in 3 dimensions"));
1562 return;
1563 }
1564 np = us_needcell();
1565 if (np == NONODEPROTO) return;
1566
1567 us_3dsetupviewing(w);
1568
1569 /* clear highlighting */
1570 us_clearhighlightcount();
1571
1572 /* make the cell fill the window */
1573 us_fullview(np, &lx, &hx, &ly, &hy);
1574 us_squarescreen(w, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
1575
1576 /* set the window extents */
1577 startobjectchange((INTBIG)w, VWINDOWPART);
1578 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
1579 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
1580 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenly"), ly, VINTEGER);
1581 (void)setval((INTBIG)el_curwindowpart, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
1582 (void)setval((INTBIG)w, VWINDOWPART, x_("buttonhandler"), (INTBIG)us_3dbuttonhandler,
1583 VADDRESS);
1584 (void)setval((INTBIG)w, VWINDOWPART, x_("state"), (w->state & ~WINDOWTYPE) | DISP3DWINDOW,
1585 VINTEGER);
1586 endobjectchange((INTBIG)w, VWINDOWPART);
1587 return;
1588 }
1589
1590 if (namesamen(pp, x_("end"), l) == 0 && l >= 1)
1591 {
1592 if ((w->state&WINDOWTYPE) == DISPWINDOW)
1593 {
1594 ttyputmsg(_("Window already shown in 2 dimensions"));
1595 return;
1596 }
1597 if ((w->state&WINDOWTYPE) != DISP3DWINDOW)
1598 {
1599 us_abortcommand(_("Cannot view this window in 2 dimensions"));
1600 return;
1601 }
1602
1603 /* set the window extents */
1604 lx = w->screenlx; hx = w->screenhx;
1605 ly = w->screenly; hy = w->screenhy;
1606 us_squarescreen(w, NOWINDOWPART, FALSE, &lx, &hx, &ly, &hy, 0);
1607 startobjectchange((INTBIG)w, VWINDOWPART);
1608 (void)setval((INTBIG)w, VWINDOWPART, x_("state"), (w->state & ~WINDOWTYPE) | DISPWINDOW,
1609 VINTEGER);
1610 (void)setval((INTBIG)w, VWINDOWPART, x_("buttonhandler"), (INTBIG)DEFAULTBUTTONHANDLER,
1611 VADDRESS);
1612 (void)setval((INTBIG)w, VWINDOWPART, x_("screenlx"), lx, VINTEGER);
1613 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhx"), hx, VINTEGER);
1614 (void)setval((INTBIG)w, VWINDOWPART, x_("screenly"), ly, VINTEGER);
1615 (void)setval((INTBIG)w, VWINDOWPART, x_("screenhy"), hy, VINTEGER);
1616 us_gridset(w, el_curwindowpart->state);
1617 endobjectchange((INTBIG)w, VWINDOWPART);
1618 return;
1619 }
1620 if (namesamen(pp, x_("rotate"), l) == 0 && l >= 1)
1621 {
1622 us_3dsetinteraction(0);
1623 return;
1624 }
1625 if (namesamen(pp, x_("zoom"), l) == 0 && l >= 1)
1626 {
1627 us_3dsetinteraction(1);
1628 return;
1629 }
1630 if (namesamen(pp, x_("pan"), l) == 0 && l >= 1)
1631 {
1632 us_3dsetinteraction(2);
1633 return;
1634 }
1635 if (namesamen(pp, x_("twist"), l) == 0 && l >= 1)
1636 {
1637 us_3dsetinteraction(3);
1638 return;
1639 }
1640 }
1641
1642 ttyputbadusage(x_("window"));
1643 }
1644
us_yanknode(INTBIG count,CHAR * par[])1645 void us_yanknode(INTBIG count, CHAR *par[])
1646 {
1647 REGISTER BOOLEAN found;
1648 REGISTER INTBIG total;
1649 REGISTER NODEINST *topno;
1650 REGISTER NODEPROTO *np;
1651 REGISTER GEOM **list;
1652
1653 list = us_gethighlighted(WANTNODEINST, 0, 0);
1654 if (list[0] == NOGEOM)
1655 {
1656 us_abortcommand(_("Must highlight cell(s) to be yanked"));
1657 return;
1658 }
1659
1660 np = geomparent(list[0]);
1661 found = FALSE;
1662 for(total=0; list[total] != NOGEOM; total++)
1663 {
1664 topno = list[total]->entryaddr.ni;
1665 if (topno->proto->primindex != 0) continue;
1666
1667 /* disallow yanking if lock is on */
1668 if (us_cantedit(np, topno, TRUE)) return;
1669
1670 /* turn off highlighting for the first cell */
1671 if (!found) us_clearhighlightcount();
1672
1673 /* yank this cell */
1674 us_yankonenode(topno);
1675 found = TRUE;
1676 }
1677
1678 if (!found) us_abortcommand(_("Can only yank cells"));
1679 }
1680