1 /* NMmain.c -
2 *
3 * This file defines the interface between the netlist
4 * editor and the window package. Most of the routines in
5 * here are called only by the window package. They are
6 * used for creating, deleting, and moving windows, for
7 * redisplay, and for top-level command interpretation.
8 * All the REAL work of commands goes on in other files.
9 *
10 * *********************************************************************
11 * * Copyright (C) 1985, 1990 Regents of the University of California. *
12 * * Permission to use, copy, modify, and distribute this *
13 * * software and its documentation for any purpose and without *
14 * * fee is hereby granted, provided that the above copyright *
15 * * notice appear in all copies. The University of California *
16 * * makes no representations about the suitability of this *
17 * * software for any purpose. It is provided "as is" without *
18 * * express or implied warranty. Export of this software outside *
19 * * of the United States of America may require an export license. *
20 * *********************************************************************
21 */
22
23 #ifndef lint
24 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/netmenu/NMmain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
25 #endif /* not lint */
26
27 #include <stdio.h>
28
29 #include "utils/magic.h"
30 #include "utils/geometry.h"
31 #include "windows/windows.h"
32 #include "graphics/graphics.h"
33 #include "graphics/glyphs.h"
34 #include "tiles/tile.h"
35 #include "utils/hash.h"
36 #include "database/database.h"
37 #include "dbwind/dbwind.h"
38 #include "textio/textio.h"
39 #include "utils/styles.h"
40 #include "textio/txcommands.h"
41 #include "netmenu/nmInt.h"
42 #include "netmenu/netmenu.h"
43 #include "utils/undo.h"
44
45 global WindClient NMClientID;
46
47 /* Forward declaration: */
48
49 extern void nmNotDefined();
50
51
52 /* The declarations below define the layout of the netlist
53 * window. Everything is defined in "surface" coordinates,
54 * not screen coordinates. Within each of the three categories,
55 * things are in order from top to bottom. Note: the order of
56 * the buttons is important, since they are referred to by index
57 * for specific purposes. See nmInt.h.
58 */
59
60 NetButton NMButtons[] =
61 {
62 NULL, STYLE_ORANGE1, 0, 200, 80, 210,
63 NMGetLabels, NULL, NMNextLabel, NULL, NMNextLabel, NULL,
64 NULL, STYLE_ERASEALL, 0, 174, 24, 198,
65 NMPutLabel, NULL, NMReOrientLabel, NULL, NMReOrientLabel, NULL,
66 NULL, STYLE_ORANGE1, 42, 188, 59, 198,
67 NMChangeNum, NULL, NMChangeNum, NULL, NMChangeNum, NULL,
68 NULL, STYLE_ORANGE1, 63, 188, 80, 198,
69 NMChangeNum, NULL, NMChangeNum, NULL, NMChangeNum, NULL,
70 "Find", STYLE_ORANGE2, 42, 174, 80, 184,
71 NMFindLabel, NULL, NMFindLabel, NULL, NMFindLabel, NULL,
72 NULL, STYLE_GREEN1, 0, 150, 80, 160,
73 NMButtonNetList, NULL, NMButtonNetList, NULL, NMButtonNetList, NULL,
74 "Verify", STYLE_BLUE1, 0, 138, 38, 148,
75 NMCmdVerify, NULL, NMCmdVerify, NULL, NMCmdVerify, NULL,
76 "Print", STYLE_BLUE2, 42, 138, 80, 148,
77 NMCmdPrint, NULL, NMCmdPrint, NULL, NMCmdPrint, NULL,
78 "Terms", STYLE_RED1, 0, 126, 38, 136,
79 NMCmdShowterms, NULL, NMCmdShowterms, NULL, NMCmdShowterms, NULL,
80 "Cleanup", STYLE_RED2, 42, 126, 80, 136,
81 NMCmdCleanup, NULL, NMCmdCleanup, NULL, NMCmdCleanup, NULL,
82 "No Net",STYLE_GRAY1, 0, 114, 38, 124,
83 NMCmdDnet, NULL, NMCmdDnet, NULL, NMCmdDnet, NULL,
84 "Show",STYLE_YELLOW1, 42, 114, 80, 124,
85 NMShowUnderBox, NULL, NMShowUnderBox, NULL, NMShowUnderBox, NULL,
86 NULL, -1 /* -1 Signals end of list. */
87 };
88
89 NetLabel nmLabels[] =
90 {
91 "Label", STYLE_WHITE, 0, 212, 80, 222,
92 "Netlist", STYLE_WHITE, 0, 162, 80, 172,
93 NULL, -1 /* -1 signals end of list. */
94 };
95
96 NetRect nmRects[] =
97 {
98 STYLE_BBOX, 8, 174, 16, 198,
99 STYLE_BBOX, 0, 182, 24, 190,
100 STYLE_BBOX, 12, 186, 12, 186,
101 -1 /* -1 signals end of list. */
102 };
103
104
105 /* The following definitions are for the total surface area of the
106 * netlist menu, and the initial screen location of netlist menus.
107 */
108
109 Rect nmSurfaceArea = {-4, 110, 84, 226};
110 Rect nmScreenArea = {0, 0, 140, 190};
111
112 /* Only one netlist window is allowed to be open at once. This is it. */
113
114 MagWindow *NMWindow = NULL;
115
116
117 /*
118 * ----------------------------------------------------------------------------
119 *
120 * NMcreate --
121 *
122 * Called by the window package when the user tries to create
123 * a new netlist window.
124 *
125 * Results:
126 * FALSE if there's already a netlist window: we only allow
127 * one at a time. TRUE is returned otherwise.
128 *
129 * Side effects:
130 * Sets the size and location of the window.
131 *
132 * ----------------------------------------------------------------------------
133 */
134
135 /* ARGSUSED */
136 bool
NMcreate(window,argc,argv)137 NMcreate(window, argc, argv)
138 MagWindow *window; /* Partially-created window. */
139 int argc; /* Count of additional arguments. */
140 char *argv[]; /* Pointers to additional arguments. */
141 {
142 if (argc > 0)
143 TxError("Ignoring extra argments for netlist menu creation.\n");
144 if (NMWindow != NULL)
145 {
146 TxError("Sorry, can't have more than one netlist menu at a time.\n");
147 return FALSE;
148 }
149 NMWindow = window;
150 WindCaption(window, "NETLIST MENU");
151 window->w_frameArea = nmScreenArea;
152 window->w_flags &= ~(WIND_SCROLLABLE | WIND_SCROLLBARS | WIND_CAPTION);
153 WindSetWindowAreas(window);
154 WindMove(window, &nmSurfaceArea);
155 return TRUE;
156 }
157
158 /*
159 * ----------------------------------------------------------------------------
160 *
161 * NMdelete --
162 *
163 * This procedure is invoked by the window package just before
164 * the window is deleted, so we can clean things up before they
165 * go away.
166 *
167 * Results:
168 * None.
169 *
170 * Side effects:
171 * Nothing happens except to record that there's no longer an
172 * active netlist menu.
173 *
174 * ----------------------------------------------------------------------------
175 */
176
177 /* ARGSUSED */
178 bool
NMdelete(window)179 NMdelete(window)
180 MagWindow *window; /* The window that's about to disappear. */
181 {
182 NMWindow = NULL;
183 NMClearPoints();
184 return TRUE;
185 }
186
187 /*
188 * ----------------------------------------------------------------------------
189 *
190 * NMreposition --
191 *
192 * This procedure is called by the window package when the netlist
193 * menu is being repositioned or resized. It gives us a chance to
194 * modify the final position, or at least clean ourselves up in
195 * accordance with the move.
196 *
197 * Results:
198 * None.
199 *
200 * Side effects:
201 * The window's view is changed so that the menu fits comfortably
202 * within it.
203 *
204 * ----------------------------------------------------------------------------
205 */
206
207 /* ARGSUSED */
208 int
NMreposition(window,newScreenArea,final)209 NMreposition(window, newScreenArea, final)
210 MagWindow *window; /* Window being repositioned. */
211 Rect *newScreenArea; /* New screen area of window. */
212 bool final; /* FALSE means the new area is
213 * tentative, and we can modify it
214 * (we never do). TRUE means this
215 * is our opportunity for final
216 * cleanup.
217 */
218 {
219 if (final) WindMove(window, &nmSurfaceArea);
220 return 0;
221 }
222
223 /*
224 * ----------------------------------------------------------------------------
225 *
226 * NMredisplay --
227 *
228 * This window is called, either by the window package or by
229 * other routines in this module, when part or all of the netlist
230 * menu needs to be redisplayed. It sets and clears its own
231 * window lock.
232 *
233 * Results:
234 * Return 0 always.
235 *
236 * Side effects:
237 * The given area of the window is redisplayed.
238 *
239 * ----------------------------------------------------------------------------
240 */
241
242 int
NMredisplay(w,rootArea,clipArea)243 NMredisplay(w, rootArea, clipArea)
244 MagWindow *w; /* The window containing the area. */
245 Rect *rootArea; /* Redisplay area in surface coordinates. */
246 Rect *clipArea; /* Screen area to clip to. If NULL, use
247 * screen area of window. */
248
249 {
250 Rect clip, screenR;
251 Point screenP;
252 NetButton *nb;
253 NetLabel *nl;
254 NetRect *nr;
255
256 /* Make sure that there's really a netlist window! (This procedure
257 * can be called before the window exists).
258 */
259
260 if (NMWindow == (MagWindow *) NULL) return 0;
261
262 GrLock(w, TRUE);
263
264 /* Transform root area to the screen, then erase previous stuff
265 * in that area.
266 */
267
268 if (clipArea != NULL) clip = *clipArea;
269 else clip = GrScreenRect;
270 GrClipTo(&clip);
271 WindSurfaceToScreen(w, rootArea, &screenR);
272 GrClipBox(&screenR, STYLE_ERASEALL);
273 GrClipBox(&screenR, STYLE_PURPLE);
274
275 /* Redisplay each of the buttons. */
276
277 for (nb = NMButtons; nb->nmb_style >= 0; nb++)
278 {
279 if (GEO_TOUCH(&nb->nmb_area, rootArea))
280 {
281 WindSurfaceToScreen(w, &nb->nmb_area, &screenR);
282
283 /* Erase the area of the button before redrawing. This is
284 * needed on monochrome displays, or else the purple will
285 * OR in with the button color.
286 */
287
288 GrClipBox(&screenR, STYLE_ERASEALL);
289 GrClipBox(&screenR, nb->nmb_style);
290 GrClipBox(&screenR, STYLE_BBOX);
291 if (nb->nmb_text != NULL)
292 {
293 screenP.p_x = (screenR.r_xbot + screenR.r_xtop)/2;
294 screenP.p_y = (screenR.r_ybot + screenR.r_ytop)/2;
295 screenR.r_xbot += 1;
296 screenR.r_ybot += 1;
297 screenR.r_xtop -= 1;
298 screenR.r_ytop -= 1;
299 GrClipTo(&GrScreenRect);
300 GrPutText(nb->nmb_text, STYLE_BBOX, &screenP,
301 GEO_CENTER, GR_TEXT_MEDIUM, TRUE, &screenR, (Rect *) NULL);
302 GrClipTo(&clip);
303 }
304 }
305 }
306
307 /* Redisplay each of the decorative labels. */
308
309 GrClipTo(&GrScreenRect);
310 for (nl = nmLabels; nl->nml_style >= 0; nl++)
311 {
312 if (GEO_TOUCH(&nl->nml_area, rootArea))
313 {
314 WindSurfaceToScreen(w, &nl->nml_area, &screenR);
315 screenP.p_x = (screenR.r_xbot + screenR.r_xtop)/2;
316 screenP.p_y = (screenR.r_ybot + screenR.r_ytop)/2;
317 screenR.r_xbot += 1;
318 screenR.r_ybot += 1;
319 screenR.r_xtop -= 1;
320 screenR.r_ytop -= 1;
321 GrPutText(nl->nml_text, nl->nml_style, &screenP,
322 GEO_CENTER, GR_TEXT_MEDIUM, TRUE, &screenR, (Rect *) NULL);
323 }
324 }
325 GrClipTo(&clip);
326
327 /* Redisplay each of the decorative rectangles. */
328
329 for (nr = nmRects; nr->nmr_style >= 0; nr++)
330 {
331 if (GEO_TOUCH(&nr->nmr_area, rootArea))
332 {
333 WindSurfaceToScreen(w, &nr->nmr_area, &screenR);
334 GrClipBox(&screenR, nr->nmr_style);
335 }
336 }
337
338 GrUnlock(w);
339 return 0;
340 }
341
342 /*
343 * ----------------------------------------------------------------------------
344 *
345 * NMcommand --
346 *
347 * This procedure is called by the window package whenever a
348 * button is pressed with the cursor inside the netlist menu.
349 *
350 * Results:
351 * Return 0 always.
352 *
353 * Side effects:
354 * If the cursor is over one of the buttons, the corresponding
355 * command routine (if any) is called. Otherwise, nothing is
356 * done.
357 *
358 * ----------------------------------------------------------------------------
359 */
360
361 int
NMcommand(w,cmd)362 NMcommand(w, cmd)
363 MagWindow *w; /* Net-list menu window. */
364 TxCommand *cmd;
365 {
366 NetButton *nb;
367 Point surfacePoint;
368 void (*proc)();
369 int cmdNum;
370
371 if (cmd->tx_button == TX_NO_BUTTON)
372 {
373 WindExecute(w, NMClientID, cmd);
374 goto done;
375 }
376
377 if (w == NULL) return 0;
378
379 WindPointToSurface(w, &cmd->tx_p, &surfacePoint, (Rect *) NULL);
380
381 /* Since some of the command routines are invoked both in
382 * response to buttons and in response to typed commands,
383 * fake the presence of a single command keyword.
384 */
385
386 cmd->tx_argc = 1;
387 cmd->tx_argv[0] = "";
388
389 /* See if the cursor is over any of the buttons. */
390
391 for (nb = NMButtons; nb->nmb_style >= 0; nb++)
392 {
393 if (GEO_ENCLOSE(&surfacePoint, &nb->nmb_area))
394 {
395 /* Pick the appropriate procedure for this button action,
396 * then invoke it (if it exists).
397 */
398
399 proc = NULL;
400 switch (cmd->tx_buttonAction)
401 {
402 case TX_BUTTON_DOWN:
403 switch (cmd->tx_button)
404 {
405 case TX_LEFT_BUTTON:
406 proc = nb->nmb_leftDown;
407 break;
408 case TX_MIDDLE_BUTTON:
409 proc = nb->nmb_middleDown;
410 break;
411 case TX_RIGHT_BUTTON:
412 proc = nb->nmb_rightDown;
413 break;
414 }
415 break;
416 case TX_BUTTON_UP:
417 switch (cmd->tx_button)
418 {
419 case TX_LEFT_BUTTON:
420 proc = nb->nmb_leftUp;
421 break;
422 case TX_MIDDLE_BUTTON:
423 proc = nb->nmb_middleUp;
424 break;
425 case TX_RIGHT_BUTTON:
426 proc = nb->nmb_rightUp;
427 break;
428 }
429 break;
430 }
431 if (proc != NULL) (*proc)(w, cmd, nb, &surfacePoint);
432 }
433 }
434
435 done:
436 UndoNext();
437 return 0;
438 }
439
440
441 /*
442 * ----------------------------------------------------------------------------
443 *
444 * NWinit --
445 *
446 * Called by Magic's main program once at the very beginning
447 * so this module can initialize itself.
448 *
449 * Results:
450 * None.
451 *
452 * Side effects:
453 * Add this module to the window package's list of registered
454 * clients, and to the undo package.
455 *
456 * ----------------------------------------------------------------------------
457 */
458
459 void
NMinit()460 NMinit()
461 {
462 static char *doc = "You are currently using the \"netlist\" tool."
463 " The button actions are:\n"
464 " left - select the net containing the terminal"
465 " nearest the cursor\n"
466 " right - toggle the terminal nearest the cursor"
467 " into/out of current net\n"
468 " middle - join current net and net containing terminal"
469 " nearest the cursor\n";
470
471 NMClientID = WindAddClient("netlist", NMcreate, NMdelete,
472 NMredisplay, NMcommand, (void(*)())NULL,
473 NMCheckWritten, NMreposition,
474 (GrGlyph *)NULL);
475 DBWHLAddClient(NMRedrawPoints);
476 DBWHLAddClient(NMRedrawCell);
477 DBWAddButtonHandler("netlist", NMButtonProc, STYLE_CURS_NET, doc);
478 NMUndoInit();
479
480 /* Register commands with the client */
481
482 WindAddCommand(NMClientID,
483 "add term1 term2 add term1 to net of term2",
484 NMCmdAdd, FALSE);
485 WindAddCommand(NMClientID,
486 "cleanup interactively cleanup netlist",
487 NMCmdCleanup, FALSE);
488 WindAddCommand(NMClientID,
489 "cull remove fully-wired nets from the current netlist",
490 NMCmdCull, FALSE);
491 WindAddCommand(NMClientID,
492 "dnet name name ... delete the net(s) containing name(s)\n\
493 or current net if no name(s) given",
494 NMCmdDnet, FALSE);
495 WindAddCommand(NMClientID,
496 "dterm name name ... delete terminals from nets",
497 NMCmdDterm, FALSE);
498 WindAddCommand(NMClientID,
499 "extract generate net for terminals connected to box",
500 NMCmdExtract, FALSE);
501 WindAddCommand(NMClientID,
502 "find pattern [layers] find all occurrences of any labels matching\n\
503 pattern beneath the box (on layers if specified)\n\
504 and leave as feedback",
505 NMCmdFindLabels, FALSE);
506 WindAddCommand(NMClientID,
507 "flush [netlist] flush changes to netlist (current list default)",
508 NMCmdFlush, FALSE);
509 WindAddCommand(NMClientID,
510 "joinnets term1 term2 join the nets containing term1 and term2",
511 NMCmdJoinNets, FALSE);
512 WindAddCommand(NMClientID,
513 "netlist [name] switch current netlist to name.net (default\n\
514 is edit cell name)",
515 NMCmdNetlist, FALSE);
516 WindAddCommand(NMClientID,
517 "pushbutton button execute the default button action in the netlist\n\
518 window.",
519 NMCmdPushButton, FALSE);
520 WindAddCommand(NMClientID,
521 "print [name] print all terminals in name, or in current net\n\
522 if no name given",
523 NMCmdPrint, FALSE);
524 WindAddCommand(NMClientID,
525 "ripup [netlist] ripup edit cell paint connected to paint under\n\
526 box, or ripup current netlist if \"netlist\"\n\
527 typed as argument",
528 NMCmdRipup, FALSE);
529 WindAddCommand(NMClientID,
530 "savenetlist [file] write out current netlist",
531 NMCmdSavenetlist, FALSE);
532 WindAddCommand(NMClientID,
533 "shownet highlight edit cell paint connected to paint\n\
534 under box",
535 NMCmdShownet, FALSE);
536 WindAddCommand(NMClientID,
537 "showterms generate feedback for all terminals in netlist",
538 NMCmdShowterms, FALSE);
539 WindAddCommand(NMClientID,
540 "trace [name] highlight material connected to a net's \n\
541 terminals (use current net if no name given)",
542 NMCmdTrace, FALSE);
543 WindAddCommand(NMClientID,
544 "verify make sure current netlist is correctly wired",
545 NMCmdVerify, FALSE);
546 WindAddCommand(NMClientID,
547 "writeall write out all modified netlists",
548 NMCmdWriteall, FALSE);
549 }
550
551
552 /*
553 * ----------------------------------------------------------------------------
554 *
555 * nmNotDefined --
556 *
557 * This is a dummy command procedure for things that aren't
558 * implemented yet.
559 *
560 * Results:
561 * None.
562 *
563 * Side effects:
564 * Just prints out an error message that this command isn't implemented.
565 *
566 * ----------------------------------------------------------------------------
567 */
568
569 void
nmNotDefined()570 nmNotDefined()
571 {
572 TxError("Sorry, no code has been written for that button yet.\n");
573 }
574