Fixed issues with the "macro" command that have existed since the
"tool" command was changed to be overridden by a Tcl command. Due to macro clients being registered with the tool name instead of just "layout", the "macro" command with no arguments or with a window client argument was just broken. In the process of fixing this, I realized that there was a conflict between the use of "netlist" as a window name and also as the name of a tool, so I changed the tool name to "nettool", a change which should be transparent to the end user. Otherwise, "macro netlist" returns the key bindings for the window, and the only way to get the key bindings for the tool is to make the tool active and then use "macro" without arguments. One remaining issue is that there is no syntax error that will cause the list of valid windows and tools to be printed. Probably "macro help" should print usage information instead of acting like "macro" with no arguments.
This commit is contained in:
parent
cb1653b157
commit
ae6d26578e
|
|
@ -131,8 +131,11 @@ DBWAddButtonHandler(
|
|||
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||
{
|
||||
if (dbwButtonHandlers[i] != NULL) continue;
|
||||
(void) StrDup(&dbwButtonHandlers[i], name);
|
||||
(void) StrDup(&dbwButtonDoc[i], doc);
|
||||
StrDup(&dbwButtonHandlers[i], name);
|
||||
if (doc != NULL)
|
||||
StrDup(&dbwButtonDoc[i], doc);
|
||||
else
|
||||
dbwButtonDoc[i] = (char *)NULL;
|
||||
dbwButtonProcs[i] = proc;
|
||||
dbwButtonCursors[i] = cursor;
|
||||
return;
|
||||
|
|
@ -273,6 +276,37 @@ DBWGetButtonHandler()
|
|||
return dbwButtonHandlers[dbwButtonCurrentIndex];
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBWButtonHandlerIndex()
|
||||
*
|
||||
* Given a string, return the index of the button handler. If the
|
||||
* string does not correspond to any button handler name, then
|
||||
* return -1.
|
||||
*
|
||||
* Results:
|
||||
* Index of button handler, if it exists; -1 otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
DBWButtonHandlerIndex(char *toolName)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||
{
|
||||
if (dbwButtonHandlers[i] == NULL) return -1;
|
||||
else if (!strcmp(toolName, dbwButtonHandlers[i])) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -294,7 +328,10 @@ DBWGetButtonHandler()
|
|||
void
|
||||
DBWPrintButtonDoc()
|
||||
{
|
||||
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
||||
if (dbwButtonDoc[dbwButtonCurrentIndex])
|
||||
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
||||
else
|
||||
TxPrintf("(no usage information)\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandle
|
|||
int cursor, const char *doc);
|
||||
extern char *DBWGetButtonHandler();
|
||||
extern char *DBWChangeButtonHandler();
|
||||
extern int DBWButtonHandlerIndex();
|
||||
extern void DBWPrintButtonDoc();
|
||||
extern void DBWBoxHandler();
|
||||
|
||||
|
|
|
|||
|
|
@ -2755,6 +2755,56 @@ extOutputDevices(def, transList, outFile)
|
|||
/* get corrected by extComputeEffectiveLW(). */
|
||||
length = (extTransRec.tr_gatelen - width) / 2;
|
||||
}
|
||||
|
||||
if ((n == 1) && (length == 0) && (extTransRec.tr_gatelen == 0))
|
||||
{
|
||||
/* If a one-terminal device has not recorded any
|
||||
* gate length, then get W and L from the bounding
|
||||
* box of the device. This routine could be much
|
||||
* better optimized but it is probably not worth
|
||||
* the effort. Just reusing the code from above
|
||||
* for creating extSpecialDevice, a list of device
|
||||
* tiles. Note that W and L are not distinguishable
|
||||
* and hopefully the PDK defines the device by area
|
||||
* and perimeter.
|
||||
*/
|
||||
LinkedTile *lt;
|
||||
Rect devbbox, ltbox;
|
||||
|
||||
extSpecialDevice = (LinkedTile *)NULL;
|
||||
|
||||
arg.fra_uninit = (ClientData)extTransRec.tr_gatenode;
|
||||
arg.fra_region = (ExtRegion *)reg;
|
||||
arg.fra_each = extSDTileFunc;
|
||||
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
|
||||
arg.fra_pNum, &arg);
|
||||
|
||||
arg.fra_uninit = (ClientData) reg;
|
||||
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
|
||||
arg.fra_each = (int (*)()) NULL;
|
||||
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
|
||||
arg.fra_pNum, &arg);
|
||||
|
||||
lt = extSpecialDevice;
|
||||
if (lt)
|
||||
{
|
||||
TiToRect(lt->t, &devbbox);
|
||||
for (; lt; lt = lt->t_next)
|
||||
{
|
||||
TiToRect(lt->t, <box);
|
||||
GeoInclude(<box, &devbbox);
|
||||
}
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
for (lt = extSpecialDevice; lt; lt = lt->t_next)
|
||||
freeMagic1(&mm1, (char *)lt);
|
||||
freeMagic1_end(&mm1);
|
||||
}
|
||||
length = devbbox.r_xtop - devbbox.r_xbot;
|
||||
/* Width was likely a perimeter value and will
|
||||
* be recalculated as the actual device width.
|
||||
*/
|
||||
width = devbbox.r_ytop - devbbox.r_ybot;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -534,8 +534,11 @@ proc magic::enable_tools {} {
|
|||
# The user can change these bindings at will by using the
|
||||
# "macro" command when the tool is active.
|
||||
|
||||
# NOTE: Do not name a tool "netlist" because it will get
|
||||
# confused with the "netlist" window.
|
||||
|
||||
magic::macro copy wiring
|
||||
magic::macro copy netlist
|
||||
magic::macro copy nettool
|
||||
magic::macro copy pick
|
||||
|
||||
magic::tool wiring
|
||||
|
|
@ -549,7 +552,7 @@ proc magic::enable_tools {} {
|
|||
macro Button4 "wire incr width ; wire show"
|
||||
macro Button5 "wire decr width ; wire show"
|
||||
|
||||
magic::tool netlist
|
||||
magic::tool nettool
|
||||
macro Button1 "netlist select"
|
||||
macro Button2 "netlist join"
|
||||
macro Button3 "netlist terminal"
|
||||
|
|
@ -704,8 +707,8 @@ proc magic::tool {{type next}} {
|
|||
if {$type == "next"} {
|
||||
switch $Opts(tool) {
|
||||
box { set type wiring }
|
||||
wiring { set type netlist }
|
||||
netlist { set type pick }
|
||||
wiring { set type nettool }
|
||||
nettool { set type pick }
|
||||
pick { set type box }
|
||||
}
|
||||
}
|
||||
|
|
@ -761,9 +764,9 @@ proc magic::tool {{type next}} {
|
|||
set Opts(tool) wiring
|
||||
cursor 19 ;# sets the cursor
|
||||
}
|
||||
netlist {
|
||||
nettool {
|
||||
puts stdout {Switching to NETLIST tool.}
|
||||
set Opts(tool) netlist
|
||||
set Opts(tool) nettool
|
||||
cursor 18 ;# sets the cursor
|
||||
}
|
||||
pick {
|
||||
|
|
|
|||
|
|
@ -1056,6 +1056,7 @@ windDoMacro(w, cmd, interactive)
|
|||
bool do_help = FALSE;
|
||||
bool do_reverse = FALSE;
|
||||
char *searchterm = NULL;
|
||||
char *clientName = NULL;
|
||||
macrodef *cMacro;
|
||||
HashTable *clienttable;
|
||||
HashEntry *h;
|
||||
|
|
@ -1073,9 +1074,25 @@ windDoMacro(w, cmd, interactive)
|
|||
|
||||
argstart = 1;
|
||||
if (cmd->tx_argc == 1)
|
||||
wc = DBWclientID; /* Added by NP 11/15/04 */
|
||||
wc = DBWclientID; /* Default client */
|
||||
else if (cmd->tx_argc > 1)
|
||||
{
|
||||
wc = WindGetClient(cmd->tx_argv[1], TRUE);
|
||||
if (wc != NULL)
|
||||
{
|
||||
clientName = cmd->tx_argv[1];
|
||||
argstart++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if argument is a known layout button handler */
|
||||
if (DBWButtonHandlerIndex(cmd->tx_argv[1]) != -1)
|
||||
{
|
||||
clientName = cmd->tx_argv[1];
|
||||
argstart++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (cmd->tx_argc > argstart)
|
||||
{
|
||||
|
|
@ -1116,6 +1133,15 @@ windDoMacro(w, cmd, interactive)
|
|||
wc = DBWclientID;
|
||||
}
|
||||
MacroCopy(wc, cmd->tx_argv[argstart]);
|
||||
|
||||
/* If tool name did not previously exist, then add
|
||||
* it to the list of known tool names, so that it
|
||||
* can be found later by the "macro" command.
|
||||
*/
|
||||
if (DBWButtonHandlerIndex(cmd->tx_argv[argstart]) == -1)
|
||||
DBWAddButtonHandler(cmd->tx_argv[argstart],
|
||||
(const cb_database_buttonhandler_t)NULL,
|
||||
0, (const char *)NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1147,26 +1173,53 @@ windDoMacro(w, cmd, interactive)
|
|||
|
||||
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
|
||||
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
|
||||
{
|
||||
wc = 0;
|
||||
argstart++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
argstart++;
|
||||
|
||||
/* If a clientName wasn't given, but wc is DBWclientID, then get
|
||||
* the clientName from the default button handler.
|
||||
*/
|
||||
|
||||
if ((clientName == NULL) && (wc == DBWclientID))
|
||||
clientName = DBWGetButtonHandler();
|
||||
|
||||
if (cmd->tx_argc == argstart)
|
||||
{
|
||||
if (wc == (WindClient)0)
|
||||
if (clientName == NULL)
|
||||
h = NULL;
|
||||
else
|
||||
h = HashLookOnly(&MacroClients, (char *)clientName);
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
TxError("No such client.\n");
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *lobj;
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
#endif
|
||||
TxError("Cannot get macro list from current window.\n");
|
||||
#ifndef MAGIC_WRAPPER
|
||||
TxError("List of known macro clients:\n");
|
||||
#endif
|
||||
/* If clientName was not in MacroClients, then what is? */
|
||||
HashStartSearch(&hs);
|
||||
while ((h = HashNext(&MacroClients, &hs)) != NULL)
|
||||
{
|
||||
char *clientName = h->h_key.h_name;
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(clientName, -1));
|
||||
#else
|
||||
TxError("%s ", clientName);
|
||||
#endif
|
||||
}
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxError("\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
h = HashLookOnly(&MacroClients, (char *)wc);
|
||||
if (h == NULL)
|
||||
return;
|
||||
else
|
||||
{
|
||||
clienttable = (HashTable *)HashGetValue(h);
|
||||
|
|
|
|||
Loading…
Reference in New Issue