/* * CmdE.c -- * * Commands with names beginning with the letter E. * * ********************************************************************* * * 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/commands/CmdE.c,v 1.4 2010/06/17 14:38:33 tim Exp $"; #endif /* not lint */ #include #include #include #include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/styles.h" #include "utils/geometry.h" #include "utils/utils.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "windows/windows.h" #include "graphics/graphics.h" #include "dbwind/dbwind.h" #include "utils/main.h" #include "commands/commands.h" #include "textio/textio.h" #include "utils/macros.h" #include "drc/drc.h" #include "textio/txcommands.h" #include "extract/extract.h" #include "select/select.h" /* * ---------------------------------------------------------------------------- * * CmdEdit -- * * Implement the "edit" command. * Use the cell that is currently selected as the edit cell. If more than * one cell is selected, use the point to choose between them. * * Usage: * edit * * Results: * None. * * Side effects: * Sets EditCellUse. * * ---------------------------------------------------------------------------- */ /* The following variable is set by cmdEditEnumFunc to signal that there * was at least one cell in the selection. */ static bool cmdFoundNewEdit; void CmdEdit(w, cmd) MagWindow *w; TxCommand *cmd; { Rect area, pointArea; CellUse *usave; CellDef *csave; int cmdEditRedisplayFunc(); /* Forward declaration. */ int cmdEditEnumFunc(); /* Forward declaration. */ bool noCurrentUse = FALSE; if (cmd->tx_argc > 1) { TxError("Usage: edit\nMaybe you want the \"load\" command\n"); return; } usave = EditCellUse; if (usave != (CellUse *)NULL) { /* Record the current edit cell's area for redisplay (now that it's * not the edit cell, it will be displayed differently). Do this * only in windows where the edit cell is displayed differently from * other cells. */ GeoTransRect(&EditToRootTransform, &(usave->cu_def->cd_bbox), &area); (void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area); DBWUndoOldEdit(EditCellUse, EditRootDef, &EditToRootTransform, &RootToEditTransform); } /* Use the position of the point to select one of the currently-selected * cells (if there are more than one). If worst comes to worst, just * select any selected cell. */ (void) ToolGetPoint((Point *) NULL, &pointArea); cmdFoundNewEdit = FALSE; csave = EditRootDef; usave = EditCellUse; EditCellUse = NULL; (void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL, cmdEditEnumFunc, (ClientData) &pointArea); if (EditCellUse == (CellUse *)NULL) { TxError("No cell selected to edit.\n"); EditCellUse = usave; EditRootDef = csave; return; } else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE)) { bool dereference = (EditCellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, dereference, NULL); } if (EditCellUse->cu_def->cd_flags & CDNOEDIT) { TxError("File %s is not writeable. Edit not set.\n", EditCellUse->cu_def->cd_file); cmdFoundNewEdit = FALSE; EditCellUse = usave; EditRootDef = csave; return; } if (!cmdFoundNewEdit) TxError("You haven't selected a new cell to edit.\n"); CmdSetWindCaption(EditCellUse, EditRootDef); DBWUndoNewEdit(EditCellUse, EditRootDef, &EditToRootTransform, &RootToEditTransform); /* Now record the new edit cell's area for redisplay. */ GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area); (void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area); } /* Search function to handle redisplays for CmdEdit: it checks to * be sure that this is a window on the edit cell, then if edit cells * are displayed differently from other cells in the window, the area * of the edit cell is redisplayed. Also, if the grid is on in this * window, the origin area is redisplayed. */ int cmdEditRedisplayFunc(w, area) MagWindow *w; /* Window containing edit cell. */ Rect *area; /* Area to be redisplayed. */ { static Rect origin = {-1, -1, 1, 1}; Rect tmp; DBWclientRec *crec = (DBWclientRec *) w->w_clientData; if (((CellUse *) w->w_surfaceID)->cu_def != EditRootDef) return 0; if (!(crec->dbw_flags & DBW_ALLSAME)) DBWAreaChanged(EditRootDef, area, crec->dbw_bitmask, &DBAllButSpaceBits); if (crec->dbw_flags & DBW_GRID) { GeoTransRect(&EditToRootTransform, &origin, &tmp); DBWAreaChanged(EditRootDef, &tmp, crec->dbw_bitmask, &DBAllButSpaceBits); } return 0; } /* Search function to find the new edit cell: look for a cell use * that contains the rectangle passed as argument. If we find such * a use, return 1 to abort the search. Otherwise, save information * about this use anyway: it'll become the edit cell if nothing * better is found. */ int cmdEditEnumFunc(selUse, use, transform, area) CellUse *selUse; /* Use from selection (not used). */ CellUse *use; /* Use from layout that corresponds to * selUse (could be an array!). */ Transform *transform; /* Transform from use->cu_def to root coords. */ Rect *area; /* We're looking for a use containing this * area, in root coords. */ { Rect defArea, useArea; int xhi, xlo, yhi, ylo; /* Save this use as the default next edit cell, regardless of whether * or not it overlaps the area we're interested in. */ EditToRootTransform = *transform; GeoInvertTrans(transform, &RootToEditTransform); EditCellUse = use; EditRootDef = SelectRootDef; cmdFoundNewEdit = TRUE; /* See if the bounding box of this use overlaps the area we're * interested in. */ GeoTransRect(&RootToEditTransform, area, &defArea); GeoTransRect(&use->cu_transform, &defArea, &useArea); if (!GEO_OVERLAP(&useArea, &use->cu_bbox)) return 0; /* It overlaps. Now find out which array element it points to, * and adjust the transforms accordingly. */ DBArrayOverlap(use, &useArea, &xlo, &xhi, &ylo, &yhi); GeoTransTrans(DBGetArrayTransform(use, xlo, ylo), transform, &EditToRootTransform); GeoInvertTrans(&EditToRootTransform, &RootToEditTransform); return 1; } /* * ---------------------------------------------------------------------------- * * CmdElement -- * * Implement the "element" command. * Handle general-purpose elements which are drawn on top of the layout. * * Usage: * element name ... * * Results: * None. * * Side effects: * May modify the hash table of elements. * * ---------------------------------------------------------------------------- */ #define ELEMENT_ADD 0 #define ELEMENT_DELETE 1 #define ELEMENT_CONFIG 2 #define ELEMENT_NAMES 3 #define ELEMENT_INBOX 4 #define ELEMENT_HELP 5 #define ELEMENT_LINE 0 #define ELEMENT_RECT 1 #define ELEMENT_TEXT 2 #define OPTION_TEXT 0 #define OPTION_STYLE 1 #define OPTION_POSITION 2 #define OPTION_FLAGS 3 void CmdElement(w, cmd) MagWindow *w; TxCommand *cmd; { int option, type; char **msg; Rect area; int style; CellDef *def; CellUse *use; bool getopt; static char *cmdElementOption[] = { "add create a new element", "delete delete an existing element", "configure configure or query an existing element", "names print names of all elements", "inbox print name of element nearest the box", "help print help information", NULL }; static char *cmdElementType[] = { "line name style x1 y1 x2 y2", "rectangle name style llx lly urx ury", "text name style cx cy label", NULL }; static char *cmdConfigureType[] = { "text get (or) replace ", "style get (or) add