/* NMmain.c - * * This file defines the interface between the netlist * editor and the window package. Most of the routines in * here are called only by the window package. They are * used for creating, deleting, and moving windows, for * redisplay, and for top-level command interpretation. * All the REAL work of commands goes on in other files. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint 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 $"; #endif /* not lint */ #include #include "utils/magic.h" #include "utils/geometry.h" #include "windows/windows.h" #include "graphics/graphics.h" #include "graphics/glyphs.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "dbwind/dbwind.h" #include "textio/textio.h" #include "utils/styles.h" #include "textio/txcommands.h" #include "netmenu/nmInt.h" #include "netmenu/netmenu.h" #include "utils/undo.h" global WindClient NMClientID; /* Forward declaration: */ extern void nmNotDefined(); /* The declarations below define the layout of the netlist * window. Everything is defined in "surface" coordinates, * not screen coordinates. Within each of the three categories, * things are in order from top to bottom. Note: the order of * the buttons is important, since they are referred to by index * for specific purposes. See nmInt.h. */ NetButton NMButtons[] = { NULL, STYLE_ORANGE1, 0, 200, 80, 210, NMGetLabels, NULL, NMNextLabel, NULL, NMNextLabel, NULL, NULL, STYLE_ERASEALL, 0, 174, 24, 198, NMPutLabel, NULL, NMReOrientLabel, NULL, NMReOrientLabel, NULL, NULL, STYLE_ORANGE1, 42, 188, 59, 198, NMChangeNum, NULL, NMChangeNum, NULL, NMChangeNum, NULL, NULL, STYLE_ORANGE1, 63, 188, 80, 198, NMChangeNum, NULL, NMChangeNum, NULL, NMChangeNum, NULL, "Find", STYLE_ORANGE2, 42, 174, 80, 184, NMFindLabel, NULL, NMFindLabel, NULL, NMFindLabel, NULL, NULL, STYLE_GREEN1, 0, 150, 80, 160, NMButtonNetList, NULL, NMButtonNetList, NULL, NMButtonNetList, NULL, "Verify", STYLE_BLUE1, 0, 138, 38, 148, NMCmdVerify, NULL, NMCmdVerify, NULL, NMCmdVerify, NULL, "Print", STYLE_BLUE2, 42, 138, 80, 148, NMCmdPrint, NULL, NMCmdPrint, NULL, NMCmdPrint, NULL, "Terms", STYLE_RED1, 0, 126, 38, 136, NMCmdShowterms, NULL, NMCmdShowterms, NULL, NMCmdShowterms, NULL, "Cleanup", STYLE_RED2, 42, 126, 80, 136, NMCmdCleanup, NULL, NMCmdCleanup, NULL, NMCmdCleanup, NULL, "No Net",STYLE_GRAY1, 0, 114, 38, 124, NMCmdDnet, NULL, NMCmdDnet, NULL, NMCmdDnet, NULL, "Show",STYLE_YELLOW1, 42, 114, 80, 124, NMShowUnderBox, NULL, NMShowUnderBox, NULL, NMShowUnderBox, NULL, NULL, -1 /* -1 Signals end of list. */ }; NetLabel nmLabels[] = { "Label", STYLE_WHITE, 0, 212, 80, 222, "Netlist", STYLE_WHITE, 0, 162, 80, 172, NULL, -1 /* -1 signals end of list. */ }; NetRect nmRects[] = { STYLE_BBOX, 8, 174, 16, 198, STYLE_BBOX, 0, 182, 24, 190, STYLE_BBOX, 12, 186, 12, 186, -1 /* -1 signals end of list. */ }; /* The following definitions are for the total surface area of the * netlist menu, and the initial screen location of netlist menus. */ Rect nmSurfaceArea = {-4, 110, 84, 226}; Rect nmScreenArea = {0, 0, 140, 190}; /* Only one netlist window is allowed to be open at once. This is it. */ MagWindow *NMWindow = NULL; /* * ---------------------------------------------------------------------------- * * NMcreate -- * * Called by the window package when the user tries to create * a new netlist window. * * Results: * FALSE if there's already a netlist window: we only allow * one at a time. TRUE is returned otherwise. * * Side effects: * Sets the size and location of the window. * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ bool NMcreate(window, argc, argv) MagWindow *window; /* Partially-created window. */ int argc; /* Count of additional arguments. */ char *argv[]; /* Pointers to additional arguments. */ { if (argc > 0) TxError("Ignoring extra argments for netlist menu creation.\n"); if (NMWindow != NULL) { TxError("Sorry, can't have more than one netlist menu at a time.\n"); return FALSE; } NMWindow = window; WindCaption(window, "NETLIST MENU"); window->w_frameArea = nmScreenArea; window->w_flags &= ~(WIND_SCROLLABLE | WIND_SCROLLBARS | WIND_CAPTION); WindSetWindowAreas(window); WindMove(window, &nmSurfaceArea); return TRUE; } /* * ---------------------------------------------------------------------------- * * NMdelete -- * * This procedure is invoked by the window package just before * the window is deleted, so we can clean things up before they * go away. * * Results: * None. * * Side effects: * Nothing happens except to record that there's no longer an * active netlist menu. * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ bool NMdelete(window) MagWindow *window; /* The window that's about to disappear. */ { NMWindow = NULL; NMClearPoints(); return TRUE; } /* * ---------------------------------------------------------------------------- * * NMreposition -- * * This procedure is called by the window package when the netlist * menu is being repositioned or resized. It gives us a chance to * modify the final position, or at least clean ourselves up in * accordance with the move. * * Results: * None. * * Side effects: * The window's view is changed so that the menu fits comfortably * within it. * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ int NMreposition(window, newScreenArea, final) MagWindow *window; /* Window being repositioned. */ Rect *newScreenArea; /* New screen area of window. */ bool final; /* FALSE means the new area is * tentative, and we can modify it * (we never do). TRUE means this * is our opportunity for final * cleanup. */ { if (final) WindMove(window, &nmSurfaceArea); return 0; } /* * ---------------------------------------------------------------------------- * * NMredisplay -- * * This window is called, either by the window package or by * other routines in this module, when part or all of the netlist * menu needs to be redisplayed. It sets and clears its own * window lock. * * Results: * Return 0 always. * * Side effects: * The given area of the window is redisplayed. * * ---------------------------------------------------------------------------- */ int NMredisplay(w, rootArea, clipArea) MagWindow *w; /* The window containing the area. */ Rect *rootArea; /* Redisplay area in surface coordinates. */ Rect *clipArea; /* Screen area to clip to. If NULL, use * screen area of window. */ { Rect clip, screenR; Point screenP; NetButton *nb; NetLabel *nl; NetRect *nr; /* Make sure that there's really a netlist window! (This procedure * can be called before the window exists). */ if (NMWindow == (MagWindow *) NULL) return 0; GrLock(w, TRUE); /* Transform root area to the screen, then erase previous stuff * in that area. */ if (clipArea != NULL) clip = *clipArea; else clip = GrScreenRect; GrClipTo(&clip); WindSurfaceToScreen(w, rootArea, &screenR); GrClipBox(&screenR, STYLE_ERASEALL); GrClipBox(&screenR, STYLE_PURPLE); /* Redisplay each of the buttons. */ for (nb = NMButtons; nb->nmb_style >= 0; nb++) { if (GEO_TOUCH(&nb->nmb_area, rootArea)) { WindSurfaceToScreen(w, &nb->nmb_area, &screenR); /* Erase the area of the button before redrawing. This is * needed on monochrome displays, or else the purple will * OR in with the button color. */ GrClipBox(&screenR, STYLE_ERASEALL); GrClipBox(&screenR, nb->nmb_style); GrClipBox(&screenR, STYLE_BBOX); if (nb->nmb_text != NULL) { screenP.p_x = (screenR.r_xbot + screenR.r_xtop)/2; screenP.p_y = (screenR.r_ybot + screenR.r_ytop)/2; screenR.r_xbot += 1; screenR.r_ybot += 1; screenR.r_xtop -= 1; screenR.r_ytop -= 1; GrClipTo(&GrScreenRect); GrPutText(nb->nmb_text, STYLE_BBOX, &screenP, GEO_CENTER, GR_TEXT_MEDIUM, TRUE, &screenR, (Rect *) NULL); GrClipTo(&clip); } } } /* Redisplay each of the decorative labels. */ GrClipTo(&GrScreenRect); for (nl = nmLabels; nl->nml_style >= 0; nl++) { if (GEO_TOUCH(&nl->nml_area, rootArea)) { WindSurfaceToScreen(w, &nl->nml_area, &screenR); screenP.p_x = (screenR.r_xbot + screenR.r_xtop)/2; screenP.p_y = (screenR.r_ybot + screenR.r_ytop)/2; screenR.r_xbot += 1; screenR.r_ybot += 1; screenR.r_xtop -= 1; screenR.r_ytop -= 1; GrPutText(nl->nml_text, nl->nml_style, &screenP, GEO_CENTER, GR_TEXT_MEDIUM, TRUE, &screenR, (Rect *) NULL); } } GrClipTo(&clip); /* Redisplay each of the decorative rectangles. */ for (nr = nmRects; nr->nmr_style >= 0; nr++) { if (GEO_TOUCH(&nr->nmr_area, rootArea)) { WindSurfaceToScreen(w, &nr->nmr_area, &screenR); GrClipBox(&screenR, nr->nmr_style); } } GrUnlock(w); return 0; } /* * ---------------------------------------------------------------------------- * * NMcommand -- * * This procedure is called by the window package whenever a * button is pressed with the cursor inside the netlist menu. * * Results: * Return 0 always. * * Side effects: * If the cursor is over one of the buttons, the corresponding * command routine (if any) is called. Otherwise, nothing is * done. * * ---------------------------------------------------------------------------- */ int NMcommand(w, cmd) MagWindow *w; /* Net-list menu window. */ TxCommand *cmd; { NetButton *nb; Point surfacePoint; void (*proc)(); int cmdNum; if (cmd->tx_button == TX_NO_BUTTON) { WindExecute(w, NMClientID, cmd); goto done; } if (w == NULL) return 0; WindPointToSurface(w, &cmd->tx_p, &surfacePoint, (Rect *) NULL); /* Since some of the command routines are invoked both in * response to buttons and in response to typed commands, * fake the presence of a single command keyword. */ cmd->tx_argc = 1; cmd->tx_argv[0] = ""; /* See if the cursor is over any of the buttons. */ for (nb = NMButtons; nb->nmb_style >= 0; nb++) { if (GEO_ENCLOSE(&surfacePoint, &nb->nmb_area)) { /* Pick the appropriate procedure for this button action, * then invoke it (if it exists). */ proc = NULL; switch (cmd->tx_buttonAction) { case TX_BUTTON_DOWN: switch (cmd->tx_button) { case TX_LEFT_BUTTON: proc = nb->nmb_leftDown; break; case TX_MIDDLE_BUTTON: proc = nb->nmb_middleDown; break; case TX_RIGHT_BUTTON: proc = nb->nmb_rightDown; break; } break; case TX_BUTTON_UP: switch (cmd->tx_button) { case TX_LEFT_BUTTON: proc = nb->nmb_leftUp; break; case TX_MIDDLE_BUTTON: proc = nb->nmb_middleUp; break; case TX_RIGHT_BUTTON: proc = nb->nmb_rightUp; break; } break; } if (proc != NULL) (*proc)(w, cmd, nb, &surfacePoint); } } done: UndoNext(); return 0; } /* * ---------------------------------------------------------------------------- * * NWinit -- * * Called by Magic's main program once at the very beginning * so this module can initialize itself. * * Results: * None. * * Side effects: * Add this module to the window package's list of registered * clients, and to the undo package. * * ---------------------------------------------------------------------------- */ void NMinit() { static char *doc = "You are currently using the \"netlist\" tool." " The button actions are:\n" " left - select the net containing the terminal" " nearest the cursor\n" " right - toggle the terminal nearest the cursor" " into/out of current net\n" " middle - join current net and net containing terminal" " nearest the cursor\n"; NMClientID = WindAddClient("netlist", NMcreate, NMdelete, NMredisplay, NMcommand, (void(*)())NULL, NMCheckWritten, NMreposition, (GrGlyph *)NULL); DBWHLAddClient(NMRedrawPoints); DBWHLAddClient(NMRedrawCell); DBWAddButtonHandler("netlist", NMButtonProc, STYLE_CURS_NET, doc); NMUndoInit(); /* Register commands with the client */ WindAddCommand(NMClientID, "add term1 term2 add term1 to net of term2", NMCmdAdd, FALSE); WindAddCommand(NMClientID, "cleanup interactively cleanup netlist", NMCmdCleanup, FALSE); WindAddCommand(NMClientID, "cull remove fully-wired nets from the current netlist", NMCmdCull, FALSE); WindAddCommand(NMClientID, "dnet name name ... delete the net(s) containing name(s)\n\ or current net if no name(s) given", NMCmdDnet, FALSE); WindAddCommand(NMClientID, "dterm name name ... delete terminals from nets", NMCmdDterm, FALSE); WindAddCommand(NMClientID, "extract generate net for terminals connected to box", NMCmdExtract, FALSE); WindAddCommand(NMClientID, "find pattern [layers] find all occurrences of any labels matching\n\ pattern beneath the box (on layers if specified)\n\ and leave as feedback", NMCmdFindLabels, FALSE); WindAddCommand(NMClientID, "flush [netlist] flush changes to netlist (current list default)", NMCmdFlush, FALSE); WindAddCommand(NMClientID, "joinnets term1 term2 join the nets containing term1 and term2", NMCmdJoinNets, FALSE); WindAddCommand(NMClientID, "netlist [name] switch current netlist to name.net (default\n\ is edit cell name)", NMCmdNetlist, FALSE); WindAddCommand(NMClientID, "pushbutton button execute the default button action in the netlist\n\ window.", NMCmdPushButton, FALSE); WindAddCommand(NMClientID, "print [name] print all terminals in name, or in current net\n\ if no name given", NMCmdPrint, FALSE); WindAddCommand(NMClientID, "ripup [netlist] ripup edit cell paint connected to paint under\n\ box, or ripup current netlist if \"netlist\"\n\ typed as argument", NMCmdRipup, FALSE); WindAddCommand(NMClientID, "savenetlist [file] write out current netlist", NMCmdSavenetlist, FALSE); WindAddCommand(NMClientID, "shownet highlight edit cell paint connected to paint\n\ under box", NMCmdShownet, FALSE); WindAddCommand(NMClientID, "showterms generate feedback for all terminals in netlist", NMCmdShowterms, FALSE); WindAddCommand(NMClientID, "trace [name] highlight material connected to a net's \n\ terminals (use current net if no name given)", NMCmdTrace, FALSE); WindAddCommand(NMClientID, "verify make sure current netlist is correctly wired", NMCmdVerify, FALSE); WindAddCommand(NMClientID, "writeall write out all modified netlists", NMCmdWriteall, FALSE); } /* * ---------------------------------------------------------------------------- * * nmNotDefined -- * * This is a dummy command procedure for things that aren't * implemented yet. * * Results: * None. * * Side effects: * Just prints out an error message that this command isn't implemented. * * ---------------------------------------------------------------------------- */ void nmNotDefined() { TxError("Sorry, no code has been written for that button yet.\n"); }