Compare commits
4 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
67c6ed9395 | |
|
|
f15f0dabbb | |
|
|
ae6d26578e | |
|
|
cb1653b157 |
|
|
@ -5696,9 +5696,12 @@ CIFGenLayer(
|
|||
(ClientData)NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
TTMaskSetMask(&bls.connect, &op->co_paintMask);
|
||||
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
||||
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
||||
(ClientData)NULL);
|
||||
}
|
||||
|
||||
/* Replace the client data */
|
||||
op->co_client = (ClientData)text;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -20,22 +20,64 @@
|
|||
|
||||
<H2>macro</H2>
|
||||
<HR>
|
||||
Define or print a macro called char
|
||||
Define or print a key or button macro binding.
|
||||
<HR>
|
||||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
|
||||
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]]
|
||||
<BR><BR>
|
||||
<BLOCKQUOTE>
|
||||
where <I>key</I> is the name of a valid key (see below), and
|
||||
<I>value</I> is a <B>magic</B> command-line command. If
|
||||
present, <I>window_type</I> must be one of the four window
|
||||
types accepted by the <B>specialopen</B> command: <B>layout</B>,
|
||||
<B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If omitted,
|
||||
the layout window is assumed by default, unless the command has
|
||||
been called from inside a window (using the colon or semicolon
|
||||
present, <I>window_type</I> must be one of the known valid window
|
||||
types accepted by the <B>specialopen</B> command (<B>color</B>,
|
||||
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool
|
||||
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If
|
||||
omitted, the layout window is assumed by default, unless the command
|
||||
has been called from inside a window (using the colon or semicolon
|
||||
escape to the command-line), in which case that window type is
|
||||
assumed.
|
||||
assumed. <P>
|
||||
|
||||
In the non-Tcl version of magic, the <I>window_type</I> must be
|
||||
one of the three valid window types listed above, or <B>layout</B>.
|
||||
Tool button bindings are hard-coded, fixed, and unknown to the
|
||||
macro handler. <P>
|
||||
|
||||
In the Tcl version of magic, tool types are generated by
|
||||
procedure and can be modified or overridden. The four tools
|
||||
listed above are the default tools known to magic. If no window
|
||||
or tool type is given, then the current tool in the current
|
||||
active layout window is assumed.<P>
|
||||
|
||||
<I>option</I> may be one of the following:
|
||||
<DL>
|
||||
<DT> <B>list</B> [<B>-reverse</B>]
|
||||
<DD> The key bindings are returned in the form of a Tcl list
|
||||
(Tcl version of magic only). The returned value is a
|
||||
single list with alternating entries of the macro key and
|
||||
the macro binding. In Tcl, this list can be treated as a
|
||||
dictionary type of key:value pairs. With the <B>-reverse</B>
|
||||
option, the keys and values are reversed, resulting in a
|
||||
dictionary that can be searched or listed by function.
|
||||
<DT> <B>help</B>
|
||||
<DD> Curently, <B>macro help</B> is equivalent to <B>macro</B>
|
||||
without arguments, and returns a full list of macro names
|
||||
and their bindings.
|
||||
<DT> <B>search</B> <I>text</I>
|
||||
<DD> Return only results which match (all or in part) the string
|
||||
<I>text</I>. For example, <B>macro search grid</B> will
|
||||
return all key bindings that include the command <B>grid</B>.
|
||||
<DT> <B>copy</B> <I>tool_name</I>
|
||||
<DD> This is a method introduced to allow the interactive creation
|
||||
of new tools, in the Tcl version of magic. Each tool is defined
|
||||
specifically by its unique button and key bindings. Because
|
||||
tools generally keep most of the same default bindings, the
|
||||
<B>copy</B> option will copy all the existing bindings to the
|
||||
new tool from the current tool. This can be followed by
|
||||
switching to the new tool and replacing macros with ones
|
||||
unique to the tool.
|
||||
</DL>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
@ -72,7 +114,6 @@ Define or print a macro called char
|
|||
etc., the <B>macro</B> command accepts the abbreviated
|
||||
forms <B>Button1</B>, and so forth. <P>
|
||||
|
||||
|
||||
Finally, key modifiers may be prepended to the key name.
|
||||
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
|
||||
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
|
||||
|
|
@ -89,6 +130,7 @@ Define or print a macro called char
|
|||
<H3>See Also:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF=imacro.html><B>imacro</B></A> <BR>
|
||||
<A HREF=toolchange.html><B>tool</B></A> (Tcl version) <BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><IMG SRC=graphics/line1.gif><P>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1299,6 +1299,11 @@ proc magic::add_check_callbacks {gencell_type library} {
|
|||
# A final default dependency will be added to all entries
|
||||
# to run the "check" procedure for the device. Dependencies
|
||||
# that are more targeted get run first.
|
||||
#
|
||||
# NOTE: The "check" procedure must be the first in the
|
||||
# list, as otherwise, any invalid entry that is corrected
|
||||
# by the check callback will have been used to evaluate
|
||||
# dependent values.
|
||||
#----------------------------------------------------------
|
||||
|
||||
proc magic::add_dependency {callback gencell_type library args} {
|
||||
|
|
@ -1355,13 +1360,13 @@ proc magic::update_dialog {callback pname gencell_type library} {
|
|||
set parameters [dict merge $pdefaults [magic::gencell_getparams]]
|
||||
}
|
||||
|
||||
if {$callback != {}} {
|
||||
set parameters [$callback $pname $parameters]
|
||||
}
|
||||
if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \
|
||||
checkerr]} {
|
||||
puts stderr $checkerr
|
||||
}
|
||||
if {$callback != {}} {
|
||||
set parameters [$callback $pname $parameters]
|
||||
}
|
||||
magic::gencell_setparams $parameters
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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