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