Extended the "paint" and "erase" commands to accept an option
"pick x y" which acts like "cursor", but operates on a database coordinate instead of a pointer coordinate. Made a few other corrections to the command logging code so that it produces valid output when the log file is sourced.
This commit is contained in:
parent
3890181ebe
commit
7a4a867d6e
|
|
@ -797,6 +797,13 @@ CmdBox(w, cmd)
|
||||||
ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
|
ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Recast command as "box values" for logging purposes */
|
||||||
|
ToolGetBox(&rootBoxDef, &rootBox);
|
||||||
|
sprintf(cmd->tx_argstring, "box values %di %di %di %di",
|
||||||
|
rootBox.r_xbot, rootBox.r_ybot,
|
||||||
|
rootBox.r_xtop, rootBox.r_ytop);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
||||||
|
|
|
||||||
|
|
@ -2711,6 +2711,14 @@ CmdCopy(w, cmd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Recast the command as "copy to x y" so that it no longer
|
||||||
|
* depends on the pointer position, for command logging.
|
||||||
|
*/
|
||||||
|
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
|
||||||
|
sprintf(cmd->tx_argstring, "copy to %di %di\n", editPoint.p_x,
|
||||||
|
editPoint.p_y);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
|
|
||||||
copyToPoint:
|
copyToPoint:
|
||||||
if (!ToolGetBox(&rootDef, &rootBox) || (rootDef != SelectRootDef))
|
if (!ToolGetBox(&rootDef, &rootBox) || (rootDef != SelectRootDef))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,7 @@ badusage:
|
||||||
* EditCellUse->cu_def.
|
* EditCellUse->cu_def.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* erase [layers | cursor]
|
* erase [layers | cursor | pick x y]
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -630,14 +630,23 @@ CmdErase(w, cmd)
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *) NULL) return;
|
if (w == (MagWindow *) NULL) return;
|
||||||
|
|
||||||
|
if ((cmd->tx_argc == 4) && !strcmp(cmd->tx_argv[1], "pick"))
|
||||||
|
{
|
||||||
|
Point editPoint, rootPoint;
|
||||||
|
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
||||||
|
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
||||||
|
GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint);
|
||||||
|
CmdPaintEraseButton(w, &rootPoint, FALSE, FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->tx_argc > 2)
|
if (cmd->tx_argc > 2)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s [<layers> | cursor]\n", cmd->tx_argv[0]);
|
TxError("Usage: %s [<layers> | cursor | pick x y]\n", cmd->tx_argv[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ToolGetEditBox(&editRect)) return;
|
if (!ToolGetEditBox(&editRect)) return;
|
||||||
|
|
||||||
if (EditCellUse == NULL)
|
if (EditCellUse == NULL)
|
||||||
{
|
{
|
||||||
TxError("No cell def being edited!\n");
|
TxError("No cell def being edited!\n");
|
||||||
|
|
@ -654,7 +663,16 @@ CmdErase(w, cmd)
|
||||||
(void) CmdParseLayers("*,label", &mask);
|
(void) CmdParseLayers("*,label", &mask);
|
||||||
else if (!strncmp(cmd->tx_argv[1], "cursor", 6))
|
else if (!strncmp(cmd->tx_argv[1], "cursor", 6))
|
||||||
{
|
{
|
||||||
CmdPaintEraseButton(w, &cmd->tx_p, FALSE);
|
Point editPoint, rootPoint;
|
||||||
|
|
||||||
|
CmdPaintEraseButton(w, &cmd->tx_p, FALSE, TRUE);
|
||||||
|
|
||||||
|
/* Recast the command as "erase pick x y" for logging purposes */
|
||||||
|
CmdGetRootPoint(&rootPoint, (Rect *)NULL);
|
||||||
|
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
|
||||||
|
sprintf(cmd->tx_argstring, "erase pick %di %di", editPoint.p_x,
|
||||||
|
editPoint.p_y);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
|
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
|
||||||
|
|
|
||||||
|
|
@ -815,6 +815,14 @@ CmdMove(w, cmd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Recast the command as "move to x y" so that it no longer
|
||||||
|
* depends on the pointer position, for command logging.
|
||||||
|
*/
|
||||||
|
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
|
||||||
|
sprintf(cmd->tx_argstring, "move to %di %di\n", editPoint.p_x,
|
||||||
|
editPoint.p_y);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
|
|
||||||
moveToPoint:
|
moveToPoint:
|
||||||
if (!ToolGetBox(&rootDef, &rootBox) || (rootDef != SelectRootDef))
|
if (!ToolGetBox(&rootDef, &rootBox) || (rootDef != SelectRootDef))
|
||||||
{
|
{
|
||||||
|
|
@ -871,7 +879,7 @@ moveToPoint:
|
||||||
* Paint the specified layers underneath the box in EditCellUse->cu_def.
|
* Paint the specified layers underneath the box in EditCellUse->cu_def.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* paint <layers> | cursor
|
* paint <layers> | cursor | pick x y
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -897,15 +905,34 @@ CmdPaint(w, cmd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cmd->tx_argc == 4) && !strcmp(cmd->tx_argv[1], "pick"))
|
||||||
|
{
|
||||||
|
Point editPoint, rootPoint;
|
||||||
|
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
||||||
|
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
||||||
|
GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint);
|
||||||
|
CmdPaintEraseButton(w, &rootPoint, TRUE, FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->tx_argc != 2)
|
if (cmd->tx_argc != 2)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s <layers> | cursor\n", cmd->tx_argv[0]);
|
TxError("Usage: %s <layers> | cursor | pick x y\n", cmd->tx_argv[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(cmd->tx_argv[1], "cursor", 6))
|
if (!strncmp(cmd->tx_argv[1], "cursor", 6))
|
||||||
{
|
{
|
||||||
CmdPaintEraseButton(w, &cmd->tx_p, TRUE);
|
Point editPoint, rootPoint;
|
||||||
|
|
||||||
|
CmdPaintEraseButton(w, &cmd->tx_p, TRUE, TRUE);
|
||||||
|
|
||||||
|
/* Recast the command as "paint pick x y" for logging purposes */
|
||||||
|
CmdGetRootPoint(&rootPoint, (Rect *)NULL);
|
||||||
|
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
|
||||||
|
sprintf(cmd->tx_argstring, "paint pick %di %di", editPoint.p_x,
|
||||||
|
editPoint.p_y);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
|
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
|
||||||
|
|
@ -957,10 +984,11 @@ CmdPaint(w, cmd)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdPaintEraseButton(w, butPoint, isPaint)
|
CmdPaintEraseButton(w, refPoint, isPaint, isScreen)
|
||||||
MagWindow *w;
|
MagWindow *w;
|
||||||
Point *butPoint; /* Screen location at which button was raised */
|
Point *refPoint; /* Screen location at which button was raised */
|
||||||
bool isPaint; /* True for paint, False for erase. */
|
bool isPaint; /* True for paint, False for erase. */
|
||||||
|
bool isScreen; /* True for screen coordinates, False for root */
|
||||||
{
|
{
|
||||||
Rect rootRect, editRect, areaReturn;
|
Rect rootRect, editRect, areaReturn;
|
||||||
TileTypeBitMask mask;
|
TileTypeBitMask mask;
|
||||||
|
|
@ -974,7 +1002,15 @@ CmdPaintEraseButton(w, butPoint, isPaint)
|
||||||
}
|
}
|
||||||
crec = (DBWclientRec *) w->w_clientData;
|
crec = (DBWclientRec *) w->w_clientData;
|
||||||
|
|
||||||
WindPointToSurface(w, butPoint, (Point *) NULL, &rootRect);
|
if (isScreen)
|
||||||
|
WindPointToSurface(w, refPoint, (Point *) NULL, &rootRect);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rootRect.r_ll.p_x = refPoint->p_x;
|
||||||
|
rootRect.r_ll.p_y = refPoint->p_y;
|
||||||
|
rootRect.r_ur.p_x = refPoint->p_x + 1;
|
||||||
|
rootRect.r_ur.p_y = refPoint->p_y + 1;
|
||||||
|
}
|
||||||
|
|
||||||
DBSeeTypesAll(((CellUse *)w->w_surfaceID), &rootRect,
|
DBSeeTypesAll(((CellUse *)w->w_surfaceID), &rootRect,
|
||||||
crec->dbw_bitmask, &mask);
|
crec->dbw_bitmask, &mask);
|
||||||
|
|
|
||||||
|
|
@ -1311,7 +1311,21 @@ Okay:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *aptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
window = CmdGetRootPoint((Point *) NULL, &scx.scx_area);
|
window = CmdGetRootPoint((Point *) NULL, &scx.scx_area);
|
||||||
|
|
||||||
|
/* Recast command with "at x y" at the end for logging */
|
||||||
|
for (i = 0; i < cmd->tx_argc; i++)
|
||||||
|
{
|
||||||
|
aptr = cmd->tx_argv[i] + strlen(cmd->tx_argv[i]);
|
||||||
|
*aptr = ' ';
|
||||||
|
}
|
||||||
|
sprintf(aptr + 1, "at %di %di", scx.scx_area.r_xbot,
|
||||||
|
scx.scx_area.r_ybot);
|
||||||
|
TxRebuildCommand(cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (window == NULL) return;
|
if (window == NULL) return;
|
||||||
scx.scx_use = (CellUse *) window->w_surfaceID;
|
scx.scx_use = (CellUse *) window->w_surfaceID;
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ DBWBoxHandler(w, cmd)
|
||||||
if (button == TX_MIDDLE_BUTTON)
|
if (button == TX_MIDDLE_BUTTON)
|
||||||
{
|
{
|
||||||
if (cmd->tx_buttonAction == TX_BUTTON_DOWN)
|
if (cmd->tx_buttonAction == TX_BUTTON_DOWN)
|
||||||
CmdPaintEraseButton(w, &cmd->tx_p, TRUE);
|
CmdPaintEraseButton(w, &cmd->tx_p, TRUE, TRUE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,12 @@ Erase paint from the layout inside the bounds of the cursor box.
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>erase</B> [<I>layers</I>|<B>cursor</B>] <BR><BR>
|
<B>erase</B> [<I>layers</I>|<B>cursor</B>|<B>pick</B> <I>x y</I>] <BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>layers</I> is a comma-separated list of layer types
|
where <I>layers</I> is a comma-separated list of layer types
|
||||||
to be erased, or <B>*</B> to indicate all paint but not labels,
|
to be erased, or <B>*</B> to indicate all paint but not labels,
|
||||||
or <B>$</B> to indicate both paint and labels.
|
or <B>$</B> to indicate both paint and labels; and where <I>x</I>
|
||||||
|
and <I>y</I> are values in the layout coordinate system.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -62,6 +63,11 @@ Erase paint from the layout inside the bounds of the cursor box.
|
||||||
of the (X11) cursor and erases these from the area of the cursor
|
of the (X11) cursor and erases these from the area of the cursor
|
||||||
box. <P>
|
box. <P>
|
||||||
|
|
||||||
|
The option "<B>erase pick</B> <I>x y</I>" works like "<B>erase
|
||||||
|
cursor</B>", but the type of material to erase is selected from
|
||||||
|
the given position in layout coordinates instead of a pointer
|
||||||
|
position. <P>
|
||||||
|
|
||||||
Note that when applied to contact types, "<B>erase</B>" will erase
|
Note that when applied to contact types, "<B>erase</B>" will erase
|
||||||
the entire contact, including the top and bottom metal types
|
the entire contact, including the top and bottom metal types
|
||||||
comprising the contact. To remove the contact cuts without affecting
|
comprising the contact. To remove the contact cuts without affecting
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,10 @@ Paint mask information into the current edit cell
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>paint</B> <I>layers</I>|<B>cursor</B> <BR><BR>
|
<B>paint</B> <I>layers</I>|<B>cursor</B>|<B>pick</B> <I>x y</I> <BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>layers</I> is a comma-separated list of types to paint.
|
where <I>layers</I> is a comma-separated list of types to paint,
|
||||||
|
and <I>x y</I> are coordinates in the layout coordinate system.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -52,7 +53,11 @@ Paint mask information into the current edit cell
|
||||||
position of the (X11) cursor and fills the cursor box with these
|
position of the (X11) cursor and fills the cursor box with these
|
||||||
types. However, when no material (e.g., "space") is present under
|
types. However, when no material (e.g., "space") is present under
|
||||||
the cursor, then all material and labels are erased from the
|
the cursor, then all material and labels are erased from the
|
||||||
area of the cursor box.
|
area of the cursor box. <P>
|
||||||
|
|
||||||
|
The "<B>paint pick</B> <I>x y</I>" option works like "<B>paint
|
||||||
|
cursor</B>", but the type of paint is selected from the given
|
||||||
|
position in layout coordinates instead of a pointer position.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ proc magic::suspendall {} {
|
||||||
set framename $window
|
set framename $window
|
||||||
}
|
}
|
||||||
if {[incr Winopts(${framename},suspend)] == 1} {
|
if {[incr Winopts(${framename},suspend)] == 1} {
|
||||||
$window update suspend
|
$window updatedisplay suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ proc magic::resumeall {} {
|
||||||
incr Winopts($framename,suspend) -1
|
incr Winopts($framename,suspend) -1
|
||||||
if { $Winopts(${framename},suspend) <= 0 } {
|
if { $Winopts(${framename},suspend) <= 0 } {
|
||||||
unset Winopts(${framename},suspend)
|
unset Winopts(${framename},suspend)
|
||||||
$window update resume
|
$window updatedisplay resume
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -856,31 +856,16 @@ txLogCommand(cmd)
|
||||||
return;
|
return;
|
||||||
else if (!strcmp(postns, "*bypass"))
|
else if (!strcmp(postns, "*bypass"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Commands ending in "cursor" should be preceeded by a set point */
|
|
||||||
/* to indicate where the pointer was at the time of the command. */
|
|
||||||
|
|
||||||
if (!strcmp(cmd->tx_argv[cmd->tx_argc - 1], "cursor"))
|
|
||||||
{
|
|
||||||
if (cmd->tx_wid >= 0)
|
|
||||||
{
|
|
||||||
/* Command has a window associated with it. */
|
|
||||||
fprintf(txLogFile, "%ssetpoint %d %d %d\n",
|
|
||||||
pfix, cmd->tx_p.p_x, cmd->tx_p.p_y, cmd->tx_wid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No window associated with the command. */
|
|
||||||
fprintf(txLogFile, "%ssetpoint %d %d\n",
|
|
||||||
pfix, cmd->tx_p.p_x, cmd->tx_p.p_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!strcmp(postns, "setpoint")) return;
|
else if (!strcmp(postns, "setpoint")) return;
|
||||||
|
|
||||||
fprintf(txLogFile, "%s%s", pfix, cmd->tx_argv[0]);
|
fprintf(txLogFile, "%s%s", pfix, cmd->tx_argv[0]);
|
||||||
for (i = 1; i < cmd->tx_argc; i++)
|
for (i = 1; i < cmd->tx_argc; i++)
|
||||||
{
|
{
|
||||||
fprintf(txLogFile, " %s", cmd->tx_argv[i]);
|
bool needQuotes = (strchr(cmd->tx_argv[i], ' ') == NULL) ? FALSE : TRUE;
|
||||||
|
fprintf(txLogFile, " ");
|
||||||
|
if (needQuotes) fprintf(txLogFile, "\"");
|
||||||
|
fprintf(txLogFile, "%s", cmd->tx_argv[i]);
|
||||||
|
if (needQuotes) fprintf(txLogFile, "\"");
|
||||||
}
|
}
|
||||||
fprintf(txLogFile, "\n");
|
fprintf(txLogFile, "\n");
|
||||||
}
|
}
|
||||||
|
|
@ -1300,6 +1285,45 @@ txGetFileCommand(f, queue)
|
||||||
TxParseString(linep, queue, (TxInputEvent *) NULL);
|
TxParseString(linep, queue, (TxInputEvent *) NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* TxRebuildCommand:
|
||||||
|
*
|
||||||
|
* Rebuild the arguments of a TxCommand structure. This assumes
|
||||||
|
* that a routine has rewritten the tx_argstring record with a
|
||||||
|
* modified command. Tokenize the tx_argstring and update the
|
||||||
|
* tx_argc count and tx_argv pointers.
|
||||||
|
*
|
||||||
|
* The purpose of this routine is to allow some command callbacks
|
||||||
|
* to change the command from one implying the use of pointer
|
||||||
|
* coordinates to an equivalent command that uses database units,
|
||||||
|
* for the purpose of logging the command.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TxRebuildCommand(TxCommand *cmd)
|
||||||
|
{
|
||||||
|
char *cptr, *tptr, c;
|
||||||
|
|
||||||
|
cmd->tx_argc = 0;
|
||||||
|
tptr = cptr = cmd->tx_argstring;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *cptr;
|
||||||
|
if ((c == ' ') || (c == '\0'))
|
||||||
|
{
|
||||||
|
cmd->tx_argv[cmd->tx_argc] = tptr;
|
||||||
|
cmd->tx_argc++;
|
||||||
|
*cptr = '\0';
|
||||||
|
tptr = cptr + 1;
|
||||||
|
}
|
||||||
|
cptr++;
|
||||||
|
}
|
||||||
|
while (c != '\0');
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ extern TxCommand *TxNewCommand();
|
||||||
extern void TxFreeCommand();
|
extern void TxFreeCommand();
|
||||||
extern void TxParseString();
|
extern void TxParseString();
|
||||||
extern void TxDispatch();
|
extern void TxDispatch();
|
||||||
|
extern void TxRebuildCommand();
|
||||||
extern int TxCommandNumber; /* Serial number of current command. */
|
extern int TxCommandNumber; /* Serial number of current command. */
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue