mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-31 10:16:01 +02:00
Added a ARG_UNUSED macro in utils/magic.h, which produces a simple cast to void to silence the warnings. The reasons this is used as opposed to an attribute is that most compilers should support this. Besides this, the macro can be easily searched for in the future to potentially remove (where possible) the unused parameters.
833 lines
21 KiB
C
833 lines
21 KiB
C
/* SimSelect.c -
|
|
*
|
|
* This file provides routines to make selections for Rsim by copying
|
|
* things into a special cell named "__SELECT__". It is based
|
|
* on code in the select module.
|
|
*
|
|
* *********************************************************************
|
|
* * 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. *
|
|
* *********************************************************************
|
|
* of California
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "windows/windows.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "utils/undo.h"
|
|
#include "commands/commands.h"
|
|
#include "select/selInt.h"
|
|
#include "utils/main.h"
|
|
#include "utils/malloc.h"
|
|
#include "utils/signals.h"
|
|
#include "sim/sim.h"
|
|
|
|
/* C99 compat */
|
|
#include "textio/textio.h"
|
|
#include "extract/extract.h"
|
|
|
|
/* Two cells worth of information are kept around by the selection
|
|
* module. SelectDef and SelectUse are for the cells whose contents
|
|
* are the current selection. Select2Def and Select2Use provide a
|
|
* temporary working space for procedures that manipulate the selection.
|
|
* for example, Select2Def is used to hold nets or regions while they
|
|
* are being extracted by SelectRegion or SelectNet. Once completely
|
|
* extracted, information is copied to SelectDef. Changes to
|
|
* SelectDef are undo-able and redo-able (so that the undo package
|
|
* can deal with selection changes), but changes to Select2Def are
|
|
* not undo-able (undoing is always disabled when the cell is modified).
|
|
*/
|
|
|
|
extern CellDef *SelectDef, *Select2Def;
|
|
extern CellUse *SelectUse, *Select2Use;
|
|
|
|
typedef struct def_list_elt
|
|
{
|
|
CellDef *dl_def;
|
|
struct def_list_elt *dl_next;
|
|
bool dl_isMarked;
|
|
} SimDefListElt;
|
|
|
|
static SimDefListElt *SimCellLabList = (SimDefListElt *) NULL;
|
|
/* list of all the cell defs we have
|
|
* put RSIM labels in
|
|
*/
|
|
|
|
/* Data structure for node names extracted from the current selection. For
|
|
* each node, save the node name, a tile which lies in the node, and
|
|
* the text for the label corresponding to the node's rsim value.
|
|
*/
|
|
|
|
typedef struct TLE {
|
|
const char *tl_nodeName;
|
|
Tile *tl_nodeTile;
|
|
const char *tl_simLabel;
|
|
struct TLE *tl_next;
|
|
} TileListElt;
|
|
|
|
|
|
TileListElt *NodeList = (TileListElt *) NULL;
|
|
/* list of all nodes in the selected area */
|
|
HashTable SimNodeNameTbl; /* node names found in the selected area */
|
|
HashTable SimGetnodeTbl; /* node names to abort name search on */
|
|
HashTable SimGNAliasTbl; /* node name aliases found during search */
|
|
HashTable SimAbortSeenTbl; /* aborted node names found during search */
|
|
|
|
bool SimRecomputeSel = TRUE; /* selection has changed */
|
|
bool SimInitGetnode = TRUE; /* Getnode called for the 1st time */
|
|
bool SimGetnodeAlias = FALSE; /* if node aliases are to be printed */
|
|
bool SimSawAbortString; /* if saw string to abort name search */
|
|
bool SimIsGetnode; /* true if command was issued from Getnode */
|
|
bool SimUseCoords; /* true if we should use trans. position */
|
|
bool SimIgnoreGlobals = TRUE; /* If FALSE, node names ending in "!" */
|
|
/* are treated as global node names. */
|
|
|
|
#ifndef RSIM_MODULE
|
|
bool SimRsimRunning = FALSE; /* Always false if there's no rsim module */
|
|
#endif
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* SimSelectNode --
|
|
*
|
|
* This procedure selects an entire node. It is similar to SelectNet.
|
|
*
|
|
* Results:
|
|
* Returns the node name.
|
|
*
|
|
* Side effects:
|
|
* Starting from material of type "type" under scx, this procedure
|
|
* finds all material in all expanded cells that are electrically-
|
|
* connected to the starting material through a chain of expanded
|
|
* cells.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
char *
|
|
SimSelectNode(
|
|
SearchContext *scx, /* Area to tree-search for material. The
|
|
* transform must map to EditRoot coordinates.
|
|
*/
|
|
TileType type, /* The type of material to be considered. */
|
|
int xMask, /* Indicates window (or windows) where cells
|
|
* must be expanded for their contents to be
|
|
* considered. 0 means treat everything as
|
|
* expanded.
|
|
*/
|
|
char *buffer) /* buffer to hold node name */
|
|
{
|
|
TileTypeBitMask mask;
|
|
char *strptr;
|
|
|
|
TTMaskZero(&mask);
|
|
TTMaskSetType(&mask, type);
|
|
|
|
/* Clear out the temporary selection cell and yank all of the
|
|
* connected paint into it.
|
|
*/
|
|
|
|
UndoDisable();
|
|
DBCellClearDef(Select2Def);
|
|
SimTreeCopyConnect(scx, &mask, xMask, DBConnectTbl,
|
|
&TiPlaneRect, Select2Use, buffer);
|
|
UndoEnable();
|
|
|
|
/* Strip out path if name is global (ends with a "!") */
|
|
/* and flag SimIgnoreGlobals is not set. */
|
|
|
|
if (!SimIgnoreGlobals)
|
|
{
|
|
strptr = buffer + strlen(buffer) - 1;
|
|
if (*strptr == '!') {
|
|
*strptr = '\0';
|
|
while (strptr != buffer) {
|
|
if (*strptr == '/') {
|
|
strptr++;
|
|
break;
|
|
}
|
|
strptr--;
|
|
}
|
|
}
|
|
else {
|
|
strptr = buffer;
|
|
}
|
|
}
|
|
else
|
|
strptr = buffer;
|
|
|
|
return(strptr);
|
|
}
|
|
|
|
int
|
|
NullFunc(void)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimFreeNodeList
|
|
*
|
|
* This procedure frees all space allocated for the node list
|
|
* data structure.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* After the list has been deallocated, the head pointer is set to
|
|
* a NULL value.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimFreeNodeList(
|
|
TileListElt **List)
|
|
{
|
|
TileListElt *current;
|
|
TileListElt *temp;
|
|
|
|
temp = *List;
|
|
while (temp != NULL) {
|
|
current = temp;
|
|
temp = temp->tl_next;
|
|
freeMagic((char*)current->tl_nodeName);
|
|
freeMagic(current);
|
|
}
|
|
*List = (TileListElt *) NULL;
|
|
}
|
|
|
|
TileListElt *
|
|
simFreeNodeEntry(
|
|
TileListElt *list,
|
|
TileListElt *entry)
|
|
{
|
|
TileListElt *prev, *curr;
|
|
|
|
prev = list;
|
|
for( curr = prev->tl_next; curr != NULL; prev = curr,curr = curr->tl_next )
|
|
if( curr == entry )
|
|
{
|
|
prev->tl_next = curr->tl_next;
|
|
freeMagic( (char*)entry->tl_nodeName );
|
|
freeMagic( entry );
|
|
return( prev ); /* next element in list */
|
|
}
|
|
|
|
/* should never get here */
|
|
return(entry);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimSelectArea
|
|
*
|
|
* This procedure checks the current selected paint in the circuit and
|
|
* extracts the names of all the nodes in the selected area.
|
|
*
|
|
* Results:
|
|
* Returns a list of node name data structures.
|
|
*
|
|
* Side Effects:
|
|
* The tiles of the selection cell definition are first marked in the
|
|
* search algorithm. After finishing the search, these marks are
|
|
* erased.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
TileListElt *
|
|
SimSelectArea(
|
|
const Rect * __unused__(rect))
|
|
{
|
|
int plane;
|
|
int SimSelectFunc(Tile *tile, ClientData cdata); /* cb_database_srpaintarea_t (TileListElt **pHead) */
|
|
|
|
/* only need to extract node names if the selection has changed or
|
|
* if node aliases are to be printed.
|
|
*/
|
|
|
|
if (SimRecomputeSel || (SimGetnodeAlias && SimIsGetnode)) {
|
|
SimFreeNodeList(&NodeList);
|
|
HashInit(&SimAbortSeenTbl, 20, HT_STRINGKEYS);
|
|
|
|
/* find all nodes in the current selection */
|
|
|
|
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
|
|
{
|
|
(void) DBSrPaintArea((Tile *) NULL, SelectDef->cd_planes[plane],
|
|
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
|
|
SimSelectFunc, PTR2CD(&NodeList));
|
|
}
|
|
|
|
HashKill(&SimAbortSeenTbl);
|
|
ExtResetTiles(SelectDef, (ClientData) CLIENTDEFAULT);
|
|
SimGetNodeCleanUp();
|
|
SimRecomputeSel = FALSE;
|
|
}
|
|
if (SigInterruptPending) {
|
|
|
|
/* if caught an interrupt, be sure to recompute the selection
|
|
* next time around.
|
|
*/
|
|
|
|
SimRecomputeSel = TRUE;
|
|
}
|
|
return(NodeList);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimSelectFunc
|
|
*
|
|
* This procedure is called for each tile in the current selection.
|
|
* It first checks to see if the node the tile belongs to has not
|
|
* yet been visited. If it has not been visited, then the node name
|
|
* is extracted and all other tiles in the selection which belong to
|
|
* this node are marked.
|
|
*
|
|
* Results:
|
|
* Return 0 to keep the search going.
|
|
*
|
|
* Side effects:
|
|
* The tiles in the selection cell definition are left marked.
|
|
* It is the responsibility of the calling function to erase these
|
|
* tile marks when finished.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @typedef cb_database_srpaintarea_t */
|
|
int
|
|
SimSelectFunc(
|
|
Tile *tile, /* Tile in SelectDef. */
|
|
ClientData cdata) /* list of node names found (TileListElt **pHead) */
|
|
{
|
|
TileListElt **pHead = (TileListElt **)CD2PTR(cdata);
|
|
TileTypeBitMask mask;
|
|
SearchContext scx;
|
|
DBWclientRec *crec;
|
|
MagWindow *window;
|
|
char nameBuff[256], *nodeName;
|
|
TileListElt *newNodeTile;
|
|
TileType type;
|
|
bool coord;
|
|
|
|
window = CmdGetRootPoint((Point *) NULL, &scx.scx_area);
|
|
if (window == NULL) return 1;
|
|
|
|
/* check to see if the node has already been extracted */
|
|
|
|
if (TiGetClientINT(tile) == 1) {
|
|
return(0);
|
|
}
|
|
|
|
if (IsSplit(tile))
|
|
{
|
|
type = (SplitSide(tile)) ? SplitRightType(tile):
|
|
SplitLeftType(tile);
|
|
}
|
|
else
|
|
type = TiGetTypeExact(tile);
|
|
|
|
/* get the tile's area, and initialize the tile's search context. */
|
|
|
|
TITORECT(tile, &scx.scx_area);
|
|
|
|
/* make sure that search context isn't placed on an empty */
|
|
/* corner of a split tile. */
|
|
if (IsSplit(tile))
|
|
{
|
|
if (SplitSide(tile))
|
|
scx.scx_area.r_xbot = scx.scx_area.r_xtop - 1;
|
|
if (!(SplitDirection(tile) ^ SplitSide(tile)))
|
|
scx.scx_area.r_ybot = scx.scx_area.r_ytop - 1;
|
|
}
|
|
|
|
scx.scx_area.r_xtop = scx.scx_area.r_xbot + 1;
|
|
scx.scx_area.r_ytop = scx.scx_area.r_ybot + 1;
|
|
|
|
scx.scx_use = (CellUse *) window->w_surfaceID;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
crec = (DBWclientRec *) window->w_clientData;
|
|
|
|
TTMaskZero(&mask);
|
|
TTMaskSetType(&mask, type);
|
|
TTMaskAndMask(&mask, &crec->dbw_visibleLayers);
|
|
TTMaskAndMask(&mask, &DBAllButSpaceAndDRCBits);
|
|
|
|
/* Check if the area is above a layer which is not visible. */
|
|
|
|
if (TTMaskIsZero(&mask)) {
|
|
return(0);
|
|
}
|
|
|
|
/* mark all other tiles in the selection that are part of this node */
|
|
|
|
SimSrConnect(SelectDef, &scx.scx_area, &DBAllButSpaceAndDRCBits,
|
|
DBConnectTbl, &TiPlaneRect, NullFunc, (ClientData) NULL);
|
|
|
|
/* Pick a tile type to use for selection. */
|
|
|
|
for (type = TT_TECHDEPBASE; type < DBNumTypes; type += 1)
|
|
{
|
|
if (TTMaskHasType(&mask, type)) break;
|
|
}
|
|
|
|
nodeName = SimSelectNode(&scx, type, CU_DESCEND_ALL, nameBuff);
|
|
|
|
/* add the node name to the list only if it has not been seen yet */
|
|
|
|
coord = (nodeName[0] == '@' && nodeName[1] == '=') ? TRUE : FALSE;
|
|
|
|
if(coord || HashLookOnly(&SimNodeNameTbl, nodeName) == (HashEntry *) NULL)
|
|
{
|
|
if( ! coord )
|
|
HashFind(&SimNodeNameTbl, nodeName);
|
|
newNodeTile = (TileListElt *) mallocMagic((unsigned) (sizeof (TileListElt)));
|
|
char *tmp = (char *) mallocMagic((unsigned) (strlen(nodeName) + 1));
|
|
strcpy(tmp, nodeName);
|
|
newNodeTile->tl_nodeName = tmp; /* assign to const */
|
|
newNodeTile->tl_nodeTile = tile;
|
|
newNodeTile->tl_next = *pHead;
|
|
*pHead = newNodeTile;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
#ifdef RSIM_MODULE
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimSelection
|
|
*
|
|
* This procedure applies the specified rsim command to the list of
|
|
* nodes in the current selection and also attaches the rsim node
|
|
* value string to each node.
|
|
*
|
|
* Results:
|
|
* returns FALSE if no nodes are in the selection.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
SimSelection(
|
|
const char *cmd) /* rsim command to apply to the selection */
|
|
{
|
|
static const char Hstring[] = "RSIM=1";
|
|
static const char Lstring[] = "RSIM=0";
|
|
static const char Xstring[] = "RSIM=X";
|
|
static const char QUESTstring[] = "?";
|
|
|
|
char timeString[256];
|
|
char questString[2];
|
|
TileListElt *current, *node_list;
|
|
char *replyLine;
|
|
char *strPtr;
|
|
bool goodReply;
|
|
|
|
extern void RsimErrorMsg(void);
|
|
|
|
timeString[0] = 0;
|
|
strcpy(questString, QUESTstring); /* writable form */
|
|
|
|
/* check to see if Rsim has been started yet */
|
|
|
|
if (!SimRsimRunning) {
|
|
RsimErrorMsg();
|
|
return(FALSE);
|
|
}
|
|
|
|
/* get the list of all nodes in the selection */
|
|
|
|
SimIsGetnode = FALSE;
|
|
SimUseCoords = SimHasCoords;
|
|
|
|
HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS);
|
|
node_list = SimSelectArea((Rect *)NULL);
|
|
|
|
if (node_list == (TileListElt *) NULL) {
|
|
TxPrintf("You must select paint (rather than a cell) to use Rsim on \
|
|
the selection.\n");
|
|
goto bad;
|
|
}
|
|
|
|
/* Walk the list of node names, apply the rsim command to each node,
|
|
* and then process the results.
|
|
*/
|
|
|
|
for (current = node_list; current != NULL; current = current->tl_next)
|
|
{
|
|
current->tl_simLabel = QUESTstring;
|
|
SimRsimIt(cmd, current->tl_nodeName);
|
|
|
|
if (!SimGetReplyLine(&replyLine)) {
|
|
goto bad;
|
|
}
|
|
|
|
if (!replyLine) {
|
|
/* Rsim's reponse to the command was just a prompt. We are done
|
|
* with the current node, so process the next node in the
|
|
* selection.
|
|
*/
|
|
continue;
|
|
}
|
|
|
|
/* check for node names not recognized by Rsim */
|
|
|
|
if (strncmp(replyLine, "time = ", 7) == 0) {
|
|
if (timeString[0] == 0) {
|
|
strcpy(timeString, replyLine);
|
|
}
|
|
TxPrintf("%s not recognized in sim file\n", current->tl_nodeName);
|
|
while(replyLine) {
|
|
/* swallow Rsim reply until no more is left */
|
|
if (!SimGetReplyLine(&replyLine)) {
|
|
goto bad;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* update the node value label strings */
|
|
|
|
if (*cmd == 'd')
|
|
{
|
|
const char *name = current->tl_nodeName;
|
|
bool coord = (name[0] == '@' && name[1] == '=') ? TRUE : FALSE;
|
|
|
|
strPtr = strrchr( replyLine, '=' );
|
|
if( strPtr == NULL )
|
|
strPtr = questString;
|
|
else if( coord )
|
|
{
|
|
*strPtr = '\0';
|
|
name = replyLine;
|
|
if( HashLookOnly(&SimNodeNameTbl, name) == (HashEntry *) NULL)
|
|
{
|
|
freeMagic((char*)current->tl_nodeName);
|
|
char *tmp = (char *) mallocMagic((unsigned) (strlen(name) + 1));
|
|
strcpy(tmp, name);
|
|
current->tl_nodeName = tmp; /* assign to const */
|
|
HashFind(&SimNodeNameTbl, current->tl_nodeName);
|
|
*strPtr++ = '=';
|
|
}
|
|
else
|
|
{
|
|
current = simFreeNodeEntry( node_list, current );
|
|
*strPtr = '=';
|
|
}
|
|
}
|
|
else
|
|
strPtr++;
|
|
|
|
switch (*strPtr) {
|
|
case '1' :
|
|
current->tl_simLabel = Hstring;
|
|
break;
|
|
case '0' :
|
|
current->tl_simLabel = Lstring;
|
|
break;
|
|
case 'X' :
|
|
current->tl_simLabel = Xstring;
|
|
break;
|
|
case '=' :
|
|
break;
|
|
default :
|
|
current->tl_simLabel = QUESTstring;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* read all lines of the Rsim reply */
|
|
|
|
goodReply = TRUE;
|
|
for (;replyLine; goodReply = SimGetReplyLine(&replyLine)) {
|
|
if (!goodReply) {
|
|
goto bad;
|
|
}
|
|
if (!strncmp(replyLine, "time = ", 7)) {
|
|
if (!(timeString[0])) {
|
|
strcpy(timeString, replyLine);
|
|
}
|
|
continue;
|
|
} else if( *strPtr != '=' ) {
|
|
TxPrintf("%s\n", replyLine);
|
|
}
|
|
}
|
|
}
|
|
if (timeString[0] != 0) {
|
|
TxPrintf("%s\n", timeString);
|
|
}
|
|
|
|
HashKill(&SimNodeNameTbl);
|
|
return(TRUE);
|
|
|
|
bad:
|
|
HashKill(&SimNodeNameTbl);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimAddLabels
|
|
*
|
|
* This procedure adds the node value labels to the Magic database
|
|
* so they will be displayed in the layout.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The cell modified flags are deliberately not set when these labels
|
|
* are added to the database.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimAddLabels(
|
|
TileListElt *SelectNodeList,
|
|
CellDef *rootuse) /* the root cell def for the window */
|
|
{
|
|
|
|
TileListElt *current;
|
|
Rect selectBox;
|
|
int pos;
|
|
|
|
/* walk the list of selected nodes, add the node value label to the
|
|
* database.
|
|
*/
|
|
|
|
for (current = SelectNodeList; current != (TileListElt *) NULL;
|
|
current = current->tl_next) {
|
|
if (*(current->tl_simLabel) == '?') {
|
|
continue;
|
|
}
|
|
TiToRect(current->tl_nodeTile, &selectBox);
|
|
pos = SimPutLabel(rootuse, &selectBox, GEO_CENTER,
|
|
current->tl_simLabel, TT_SPACE);
|
|
DBReComputeBbox(rootuse);
|
|
DBWLabelChanged(rootuse, current->tl_simLabel, &selectBox,
|
|
pos, DBW_ALLWINDOWS);
|
|
}
|
|
}
|
|
|
|
#ifdef RSIM_MODULE
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimRsimMouse
|
|
*
|
|
* This procedure erases the old rsim node labels and display the
|
|
* node labels of the current selection.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimRsimMouse(
|
|
MagWindow *w)
|
|
{
|
|
|
|
CellUse *cu;
|
|
bool sawcell;
|
|
SimDefListElt *dummy;
|
|
|
|
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
|
{
|
|
TxError("Put the cursor in a layout window\n");
|
|
return;
|
|
}
|
|
|
|
cu = (CellUse *)w->w_surfaceID; /* get root cell use for wind */
|
|
|
|
/* check to see if the cell def is already in our list */
|
|
sawcell = FALSE;
|
|
for (dummy = SimCellLabList; dummy; dummy = dummy->dl_next) {
|
|
if (dummy->dl_def == cu->cu_def) {
|
|
sawcell = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!sawcell) {
|
|
/* add the cell def to the list */
|
|
if (SimCellLabList == (SimDefListElt *) NULL) {
|
|
SimCellLabList = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt)));
|
|
SimCellLabList->dl_isMarked = FALSE;
|
|
SimCellLabList->dl_def = cu->cu_def;
|
|
SimCellLabList->dl_next = (SimDefListElt *) NULL;
|
|
dummy = SimCellLabList;
|
|
}
|
|
else {
|
|
dummy = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt)));
|
|
dummy->dl_isMarked = FALSE;
|
|
dummy->dl_next = SimCellLabList;
|
|
dummy->dl_def = cu->cu_def;
|
|
SimCellLabList= dummy;
|
|
}
|
|
}
|
|
|
|
SimEraseLabels();
|
|
if (SimSelection("d")) {
|
|
dummy->dl_isMarked = TRUE;
|
|
SimAddLabels(NodeList, dummy->dl_def);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimGetnode
|
|
*
|
|
* This procedure prints the node names of all selected nodes.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimGetnode(void)
|
|
{
|
|
TileListElt *current;
|
|
|
|
/* get the list of node names */
|
|
|
|
SimIsGetnode = TRUE;
|
|
SimUseCoords = FALSE;
|
|
|
|
HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS);
|
|
current = SimSelectArea((Rect *)NULL);
|
|
HashKill(&SimNodeNameTbl);
|
|
|
|
if (current == (TileListElt *) NULL) {
|
|
TxPrintf("You must select paint (not a cell) to use getnode.\n");
|
|
return;
|
|
}
|
|
|
|
for (; current != (TileListElt *) NULL; current = current->tl_next)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
/* Return the node name as the result of the command */
|
|
Tcl_AppendElement(magicinterp, current->tl_nodeName);
|
|
#else
|
|
TxPrintf("node name : %s\n", current->tl_nodeName);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimGetsnode
|
|
*
|
|
* This procedure prints the short node names of all selected nodes.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimGetsnode(void)
|
|
{
|
|
TileListElt *current;
|
|
|
|
/* get the list of node names */
|
|
|
|
SimIsGetnode = TRUE;
|
|
SimUseCoords = TRUE;
|
|
|
|
HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS);
|
|
current = SimSelectArea((Rect *)NULL);
|
|
HashKill(&SimNodeNameTbl);
|
|
|
|
if (current == (TileListElt *) NULL) {
|
|
TxPrintf("You must select paint (not a cell) to use getnode.\n");
|
|
return;
|
|
}
|
|
|
|
for (; current != (TileListElt *) NULL; current = current->tl_next)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
/* Return the node short name as the result of the command */
|
|
Tcl_AppendElement(magicinterp, current->tl_nodeName);
|
|
#else
|
|
TxPrintf("short node name : %s\n", current->tl_nodeName);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* SimEraseLabels
|
|
*
|
|
* This procedure erases the RSIM labels from any cell defs they
|
|
* may have been added to.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Removes the RSIM labels from "marked" cell defs.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimEraseLabels(void)
|
|
{
|
|
SimDefListElt *p;
|
|
|
|
for (p = SimCellLabList; p; p = p->dl_next) {
|
|
if (p->dl_isMarked) {
|
|
p->dl_isMarked = FALSE;
|
|
DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=X");
|
|
DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=1");
|
|
DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=0");
|
|
}
|
|
}
|
|
}
|