mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-04 16:40:49 +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.
832 lines
23 KiB
C
832 lines
23 KiB
C
/*
|
|
* PlowTest.c --
|
|
*
|
|
* Plowing.
|
|
* Debugging and testing.
|
|
*
|
|
* *********************************************************************
|
|
* * 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/plow/PlowTest.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/styles.h"
|
|
#include "utils/utils.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "utils/undo.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 "drc/drc.h"
|
|
#include "debug/debug.h"
|
|
#include "plow/plowInt.h"
|
|
#include "textio/textio.h"
|
|
#include "textio/txcommands.h"
|
|
|
|
/* Forward declarations */
|
|
extern int plowShowShadow();
|
|
extern int plowShowOutline();
|
|
extern void plowTestJog();
|
|
extern void plowDebugMore();
|
|
|
|
/* Imports from PlowMain.c */
|
|
extern CellDef *plowYankDef;
|
|
extern CellUse *plowDummyUse;
|
|
|
|
/* Debugging flags */
|
|
ClientData plowDebugID;
|
|
|
|
int plowDebAdd;
|
|
int plowDebMove;
|
|
int plowDebNext;
|
|
int plowDebTime;
|
|
int plowDebWidth;
|
|
int plowDebJogs;
|
|
int plowDebYankAll;
|
|
|
|
/* Other debugging info */
|
|
bool plowWhenTop, plowWhenBot;
|
|
Point plowWhenTopPoint, plowWhenBotPoint;
|
|
|
|
/* Imports */
|
|
extern CellDef *plowSpareDef;
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* PlowTest --
|
|
*
|
|
* Real command interface for debugging plowing.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* See individual commands.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
PC_HELP, PC_ERROR,
|
|
PC_PLOW,
|
|
PC_JOG,
|
|
PC_RANDOM,
|
|
PC_TECHSHOW,
|
|
PC_OUTLINE, PC_LSHADOW, PC_SHADOW, PC_WIDTH, PC_LWIDTH,
|
|
PC_SPLIT, PC_MERGEUP, PC_MERGEDOWN, PC_MOVE, PC_TRAIL, PC_PRINT,
|
|
PC_WHENTOP, PC_WHENBOT,
|
|
PC_SETD, PC_CLRD, PC_SHOWD
|
|
} pCmd;
|
|
const struct
|
|
{
|
|
const char *p_name;
|
|
pCmd p_cmd;
|
|
const char *p_help;
|
|
} plowCmds[] = {
|
|
{"clrdebug", PC_CLRD, "flags"},
|
|
{"help", PC_HELP, ""},
|
|
{"jogreduce", PC_JOG, ""},
|
|
{"lwidth", PC_LWIDTH, "layers"},
|
|
{"lshadow", PC_LSHADOW, "layers"},
|
|
{"mergedown", PC_MERGEDOWN, ""},
|
|
{"mergeup", PC_MERGEUP, ""},
|
|
{"move", PC_MOVE, ""},
|
|
{"outline", PC_OUTLINE, "direction layers"},
|
|
{"plow", PC_PLOW, "direction [layers]"},
|
|
{"print", PC_PRINT, ""},
|
|
{"random", PC_RANDOM, ""},
|
|
{"setdebug", PC_SETD, "flags"},
|
|
{"shadow", PC_SHADOW, "layers"},
|
|
{"showdebug", PC_SHOWD, ""},
|
|
{"split", PC_SPLIT, ""},
|
|
{"techshow", PC_TECHSHOW, "[file]"},
|
|
{"trail", PC_TRAIL, "[value]"},
|
|
{"whenbot", PC_WHENBOT, "[xbot ybot]"},
|
|
{"whentop", PC_WHENTOP, "[xtop ytop]"},
|
|
{"width", PC_WIDTH, "layers"},
|
|
{0},
|
|
};
|
|
|
|
void
|
|
PlowTest(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
ARG_UNUSED(w);
|
|
pCmd plowCmd, plowGetCommand();
|
|
Rect editArea, dummyRect, rootBox, area2;
|
|
CellDef *def, *rootBoxDef, *saveDef;
|
|
TileTypeBitMask okTypes;
|
|
int dir, n, trail;
|
|
Point editPoint;
|
|
Plane *plane;
|
|
Edge edge;
|
|
Tile *tp;
|
|
Tile *delay1 = NULL;
|
|
|
|
if (!ToolGetEditBox(&editArea) || !ToolGetBox(&rootBoxDef, &rootBox))
|
|
return;
|
|
(void) CmdGetEditPoint(&editPoint, &dummyRect);
|
|
|
|
if ((plowCmd = plowGetCommand(cmd)) == PC_ERROR)
|
|
return;
|
|
|
|
def = EditCellUse->cu_def;
|
|
plane = def->cd_planes[PL_TECHDEPBASE];
|
|
switch (plowCmd)
|
|
{
|
|
case PC_HELP:
|
|
TxPrintf("Usage: *plow cmd [args]\n");
|
|
TxPrintf("Valid plowing command are:\n");
|
|
for (n = 0; plowCmds[n].p_name; n++)
|
|
TxPrintf("%-15s %s\n", plowCmds[n].p_name, plowCmds[n].p_help);
|
|
break;
|
|
case PC_ERROR: /* exhaustive switch on enum compiler warning */
|
|
break;
|
|
case PC_RANDOM:
|
|
PlowRandomTest(def);
|
|
break;
|
|
case PC_JOG:
|
|
plowTestJog(def, &editArea);
|
|
break;
|
|
case PC_SETD:
|
|
DebugSet(plowDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], TRUE);
|
|
break;
|
|
case PC_CLRD:
|
|
DebugSet(plowDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], FALSE);
|
|
break;
|
|
case PC_SHOWD:
|
|
DebugShow(plowDebugID);
|
|
break;
|
|
case PC_OUTLINE:
|
|
if (cmd->tx_argc < 4)
|
|
{
|
|
TxError("Usage: *plow outline direction layers\n");
|
|
return;
|
|
}
|
|
dir = GeoNameToPos(cmd->tx_argv[2], TRUE, TRUE);
|
|
if (dir != GEO_NORTH && dir != GEO_SOUTH)
|
|
{
|
|
TxError("Only legal starting directions are north or south\n");
|
|
return;
|
|
}
|
|
if (!CmdParseLayers(cmd->tx_argv[3], &okTypes))
|
|
return;
|
|
(void) plowSrOutline(PL_TECHDEPBASE, &editArea.r_ll, &okTypes, dir,
|
|
GMASK_NORTH|GMASK_SOUTH|GMASK_EAST|GMASK_WEST,
|
|
plowShowOutline, (ClientData) &editArea);
|
|
break;
|
|
case PC_PLOW:
|
|
if (cmd->tx_argc < 3)
|
|
{
|
|
TxError("Usage: *plow plow direction [layers]\n");
|
|
return;
|
|
}
|
|
dir = GeoNameToPos(cmd->tx_argv[2], TRUE, TRUE);
|
|
okTypes = DBAllTypeBits;
|
|
if (cmd->tx_argc > 3 && !CmdParseLayers(cmd->tx_argv[3], &okTypes))
|
|
return;
|
|
if (!Plow(def, &editArea, &okTypes, dir))
|
|
{
|
|
TxPrintf("Reduced plow size since we ran into the barrier.\n");
|
|
GeoTransRect(&EditToRootTransform, &editArea, &rootBox);
|
|
ToolMoveBox(TOOL_BL, &rootBox.r_ll, FALSE, rootBoxDef);
|
|
ToolMoveCorner(TOOL_TR, &rootBox.r_ur, FALSE, rootBoxDef);
|
|
}
|
|
break;
|
|
case PC_LSHADOW:
|
|
if (cmd->tx_argc < 3)
|
|
{
|
|
TxError("Usage: *plow lshadow layers\n");
|
|
return;
|
|
}
|
|
if (!CmdParseLayers(cmd->tx_argv[2], &okTypes))
|
|
return;
|
|
saveDef = plowYankDef;
|
|
plowYankDef = def;
|
|
(void) plowSrShadowBack(PL_TECHDEPBASE, &editArea,
|
|
&okTypes, plowShowShadow, (ClientData) def);
|
|
plowYankDef = saveDef;
|
|
break;
|
|
case PC_SHADOW:
|
|
if (cmd->tx_argc < 3)
|
|
{
|
|
TxError("Usage: *plow shadow layers\n");
|
|
return;
|
|
}
|
|
if (!CmdParseLayers(cmd->tx_argv[2], &okTypes))
|
|
return;
|
|
saveDef = plowYankDef;
|
|
plowYankDef = def;
|
|
(void) plowSrShadow(PL_TECHDEPBASE, &editArea,
|
|
&okTypes, plowShowShadow, (ClientData) def);
|
|
plowYankDef = saveDef;
|
|
break;
|
|
case PC_TECHSHOW:
|
|
if (cmd->tx_argc >= 3)
|
|
{
|
|
FILE *f = fopen(cmd->tx_argv[2], "w");
|
|
if (f == NULL)
|
|
{
|
|
perror(cmd->tx_argv[2]);
|
|
break;
|
|
}
|
|
plowTechShow(f);
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
plowTechShow(stdout);
|
|
}
|
|
break;
|
|
case PC_WIDTH:
|
|
if (cmd->tx_argc < 3)
|
|
{
|
|
TxError("Usage: *plow width layers\n");
|
|
return;
|
|
}
|
|
if (!CmdParseLayers(cmd->tx_argv[2], &okTypes))
|
|
return;
|
|
edge.e_rect = editArea;
|
|
edge.e_pNum = PL_TECHDEPBASE;
|
|
TxPrintf("Box: X: %d .. %d Y: %d .. %d\n",
|
|
editArea.r_xbot, editArea.r_xtop,
|
|
editArea.r_ybot, editArea.r_ytop);
|
|
saveDef = plowYankDef;
|
|
plowYankDef = def;
|
|
(void) plowFindWidth(&edge, &okTypes, &def->cd_bbox, &editArea);
|
|
plowYankDef = saveDef;
|
|
GeoTransRect(&EditToRootTransform, &editArea, &rootBox);
|
|
ToolMoveBox(TOOL_BL, &rootBox.r_ll, FALSE, rootBoxDef);
|
|
ToolMoveCorner(TOOL_TR, &rootBox.r_ur, FALSE, rootBoxDef);
|
|
break;
|
|
case PC_LWIDTH:
|
|
if (cmd->tx_argc < 3)
|
|
{
|
|
TxError("Usage: *plow lwidth layers\n");
|
|
return;
|
|
}
|
|
if (!CmdParseLayers(cmd->tx_argv[2], &okTypes))
|
|
return;
|
|
edge.e_rect = editArea;
|
|
edge.e_pNum = PL_TECHDEPBASE;
|
|
TxPrintf("Box: X: %d .. %d Y: %d .. %d\n",
|
|
editArea.r_xbot, editArea.r_xtop,
|
|
editArea.r_ybot, editArea.r_ytop);
|
|
saveDef = plowYankDef;
|
|
plowYankDef = def;
|
|
(void) plowFindWidthBack(&edge, &okTypes, &def->cd_bbox, &editArea);
|
|
plowYankDef = saveDef;
|
|
GeoTransRect(&EditToRootTransform, &editArea, &rootBox);
|
|
ToolMoveBox(TOOL_BL, &rootBox.r_ll, FALSE, rootBoxDef);
|
|
ToolMoveCorner(TOOL_TR, &rootBox.r_ur, FALSE, rootBoxDef);
|
|
break;
|
|
case PC_TRAIL:
|
|
if (cmd->tx_argc > 3)
|
|
{
|
|
TxError("Usage: *plow trail [value]\n");
|
|
return;
|
|
}
|
|
tp = TiSrPointNoHint(plane, &editArea.r_ll);
|
|
if (cmd->tx_argc == 3) trail = atoi(cmd->tx_argv[2]);
|
|
else trail = editArea.r_xtop;
|
|
TxPrintf("Trailing coordinate of tile %p updated from %d to %d\n",
|
|
(void *)tp, TRAILING(tp), trail);
|
|
plowSetTrailing(tp, trail);
|
|
break;
|
|
case PC_MOVE:
|
|
edge.e_pNum = PL_TECHDEPBASE;
|
|
edge.e_rect = editArea;
|
|
TxPrintf("Moving edge from %d to %d\n",
|
|
editArea.r_xbot, editArea.r_xtop);
|
|
plowMoveEdge(&edge);
|
|
editArea.r_xbot--;
|
|
DBWAreaChanged(def, &editArea, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
break;
|
|
case PC_SPLIT:
|
|
tp = TiSrPointNoHint(plane, &editArea.r_ll);
|
|
if (editArea.r_ybot == BOTTOM(tp) || editArea.r_ybot == TOP(tp))
|
|
{
|
|
TxError("Can't split at top or bottom of tile\n");
|
|
return;
|
|
}
|
|
TiToRect(tp, &area2);
|
|
TxPrintf("Splitting tile %p at y=%d yielding %p\n",
|
|
(void *)tp, editArea.r_ybot, (void *)plowSplitY(tp, editArea.r_ybot));
|
|
DBWAreaChanged(def, &area2, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
break;
|
|
case PC_MERGEDOWN:
|
|
tp = TiSrPointNoHint(plane, &editArea.r_ll);
|
|
TxPrintf("Merging tile %p below\n", (void *)tp);
|
|
TiToRect(tp, &editArea);
|
|
TiToRect(RT(tp), &area2);
|
|
(void) GeoInclude(&area2, &editArea);
|
|
plowMergeBottom(&delay1, tp, plane);
|
|
DBWAreaChanged(def, &editArea, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
break;
|
|
case PC_MERGEUP:
|
|
tp = TiSrPointNoHint(plane, &editArea.r_ll);
|
|
TxPrintf("Merging tile %p above\n", (void *)tp);
|
|
TiToRect(tp, &editArea);
|
|
TiToRect(RT(tp), &area2);
|
|
(void) GeoInclude(&area2, &editArea);
|
|
plowMergeTop(&delay1, tp, plane);
|
|
DBWAreaChanged(def, &editArea, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
break;
|
|
case PC_PRINT:
|
|
tp = TiSrPointNoHint(plane, &editArea.r_ll);
|
|
TxPrintf("Tile %p LEFT=%d RIGHT=%d BOTTOM=%d TOP=%d\n",
|
|
(void *)tp, LEFT(tp), RIGHT(tp), BOTTOM(tp), TOP(tp));
|
|
TxPrintf(" TRAILING=%d LEADING=%d TYPE=%s\n",
|
|
TRAILING(tp), LEADING(tp), DBTypeLongName(TiGetTypeExact(tp)));
|
|
break;
|
|
case PC_WHENTOP:
|
|
if (cmd->tx_argc == 2)
|
|
{
|
|
plowWhenTop = FALSE;
|
|
break;
|
|
}
|
|
if (cmd->tx_argc != 4)
|
|
{
|
|
TxError("Usage: *plow whentop xtop ytop\n");
|
|
break;
|
|
}
|
|
plowWhenTopPoint.p_x = atoi(cmd->tx_argv[2]);
|
|
plowWhenTopPoint.p_y = atoi(cmd->tx_argv[3]);
|
|
plowWhenTop = TRUE;
|
|
break;
|
|
case PC_WHENBOT:
|
|
if (cmd->tx_argc == 2)
|
|
{
|
|
plowWhenBot = FALSE;
|
|
break;
|
|
}
|
|
if (cmd->tx_argc != 4)
|
|
{
|
|
TxError("Usage: *plow whenbot xbot ybot\n");
|
|
break;
|
|
}
|
|
plowWhenBotPoint.p_x = atoi(cmd->tx_argv[2]);
|
|
plowWhenBotPoint.p_y = atoi(cmd->tx_argv[3]);
|
|
plowWhenBot = TRUE;
|
|
break;
|
|
}
|
|
TiFreeIf(delay1);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowGetCommand --
|
|
*
|
|
* Pull off the subcommand from the TxCommand passed to PlowTest()
|
|
* above. Verify that it is a valid command.
|
|
*
|
|
* Results:
|
|
* Returns PC_ERROR on error; otherwise, returns the command
|
|
* code (pCmd) corresponding to the command in cmd->tx_argv[1].
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
pCmd
|
|
plowGetCommand(cmd)
|
|
TxCommand *cmd;
|
|
{
|
|
int plowIndex;
|
|
|
|
if (cmd->tx_argc <= 1)
|
|
{
|
|
TxError("Usage: *plow cmd [args]\n");
|
|
return (PC_ERROR);
|
|
}
|
|
|
|
plowIndex = LookupStruct(cmd->tx_argv[1],
|
|
(const LookupTable *) plowCmds, sizeof plowCmds[0]);
|
|
if (plowIndex < 0)
|
|
{
|
|
TxError("Bad plowing command '%s'.\n", cmd->tx_argv[1]);
|
|
TxError("Try '*plow help' for a list of commands.\n");
|
|
return (PC_ERROR);
|
|
}
|
|
|
|
return (plowCmds[plowIndex].p_cmd);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowDebugInit --
|
|
*
|
|
* Initialize debugging flags.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Registers various debugging flags with the debugging module.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
plowDebugInit()
|
|
{
|
|
int n;
|
|
static struct
|
|
{
|
|
char *di_name;
|
|
int *di_id;
|
|
} debug[] = {
|
|
{"addedge", &plowDebAdd},
|
|
{"jogs", &plowDebJogs},
|
|
{"moveedge", &plowDebMove},
|
|
{"nextedge", &plowDebNext},
|
|
{"time", &plowDebTime},
|
|
{"width", &plowDebWidth},
|
|
{"yankall", &plowDebYankAll},
|
|
{0}
|
|
};
|
|
|
|
/* Register ourselves with the debugging module */
|
|
plowDebugID = DebugAddClient("plow", sizeof debug/sizeof debug[0]);
|
|
for (n = 0; debug[n].di_name; n++)
|
|
*(debug[n].di_id) = DebugAddFlag(plowDebugID, debug[n].di_name);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowShowShadow --
|
|
*
|
|
* Debug shadow search. Called for each edge found, we display
|
|
* feedback over the area of the edge.
|
|
*
|
|
* Results:
|
|
* None.
|
|
* Returns zero as per plowSrShadowXxx() callback requirements.
|
|
*
|
|
* Side effects:
|
|
* Leaves feedback.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowShowShadow(edge, def)
|
|
Edge *edge;
|
|
CellDef *def;
|
|
{
|
|
char mesg[512];
|
|
int scaleFactor = 10;
|
|
Rect edgeArea;
|
|
|
|
(void) sprintf(mesg, "Edge between %s and %s",
|
|
DBTypeLongName(edge->e_ltype), DBTypeLongName(edge->e_rtype));
|
|
|
|
edgeArea.r_xbot = edge->e_x * scaleFactor - 1;
|
|
edgeArea.r_xtop = edge->e_x * scaleFactor + 1;
|
|
edgeArea.r_ybot = edge->e_ybot * scaleFactor;
|
|
edgeArea.r_ytop = edge->e_ytop * scaleFactor;
|
|
DBWFeedbackAdd(&edgeArea, mesg, def, scaleFactor, STYLE_SOLIDHIGHLIGHTS);
|
|
return 0; /* TODO this callback was returning void, but plowSrShadowXxx() uses non-zero for early abort */
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowTestJog --
|
|
*
|
|
* Test jog elimination.
|
|
* Yank the area enclosed by the box, plus a TechHalo-lambda halo around it,
|
|
* into plowYankDef, and then call plowCleanupJogs() to reduce jogs in this
|
|
* yank buffer.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modifies plowYankDef.
|
|
* Redisplays.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
plowTestJog(def, area)
|
|
CellDef *def;
|
|
Rect *area;
|
|
{
|
|
extern CellUse *plowYankUse;
|
|
extern Rect plowYankedArea;
|
|
extern CellDef *plowYankDef;
|
|
Rect changedArea;
|
|
SearchContext scx;
|
|
PaintUndoInfo ui;
|
|
|
|
/* Make sure the yank buffers exist */
|
|
plowYankCreate();
|
|
|
|
/* Yank into yank buffer */
|
|
UndoDisable();
|
|
DBCellClearDef(plowYankDef);
|
|
plowDummyUse->cu_def = def;
|
|
scx.scx_use = plowDummyUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
scx.scx_area.r_xbot = area->r_xbot - DRCTechHalo;
|
|
scx.scx_area.r_ybot = area->r_ybot - DRCTechHalo;
|
|
scx.scx_area.r_xtop = area->r_xtop + DRCTechHalo;
|
|
scx.scx_area.r_ytop = area->r_ytop + DRCTechHalo;
|
|
(void) DBCellCopyPaint(&scx, &DBAllButSpaceAndDRCBits, 0, plowYankUse);
|
|
DBReComputeBbox(plowYankDef);
|
|
DBWAreaChanged(plowYankDef,&TiPlaneRect,DBW_ALLWINDOWS,&DBAllButSpaceBits);
|
|
plowYankedArea = TiPlaneRect;
|
|
|
|
/* Reduce jogs */
|
|
changedArea.r_xbot = changedArea.r_xtop = 0;
|
|
changedArea.r_ybot = changedArea.r_ytop = 0;
|
|
plowCleanupJogs(area, &changedArea);
|
|
DBReComputeBbox(plowYankDef);
|
|
DBWAreaChanged(plowYankDef,&changedArea,DBW_ALLWINDOWS,&DBAllButSpaceBits);
|
|
UndoEnable();
|
|
|
|
/* Erase area in original def */
|
|
ui.pu_def = def;
|
|
for (ui.pu_pNum = PL_TECHDEPBASE; ui.pu_pNum < DBNumPlanes; ui.pu_pNum++)
|
|
DBPaintPlane(def->cd_planes[ui.pu_pNum], area,
|
|
DBWriteResultTbl[TT_SPACE], &ui);
|
|
|
|
/* Stuff from yank buffer back into original def */
|
|
scx.scx_area = *area;
|
|
scx.scx_use = plowYankUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
(void) DBCellCopyPaint(&scx, &DBAllButSpaceAndDRCBits, 0, plowDummyUse);
|
|
DBReComputeBbox(def);
|
|
DBWAreaChanged(def, area, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
DRCCheckThis(def, TT_CHECKPAINT, area);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowDebugEdge --
|
|
*
|
|
* Display an edge for debugging purposes.
|
|
* This consists of showing the edge, and its final position, highlighted
|
|
* with feedback, then erasing the feedback after requesting "more" from
|
|
* the user.
|
|
*
|
|
* If the user responds with "d" to the "more" request, everything is forcibly
|
|
* redisplayed.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None permanent.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
plowDebugEdge(edge, rtePtr, mesg)
|
|
Edge *edge;
|
|
RuleTableEntry *rtePtr;
|
|
char *mesg;
|
|
{
|
|
int scaleFactor = 10;
|
|
Rect edgeArea;
|
|
|
|
if (rtePtr)
|
|
TxPrintf("Rule being applied: \"%s\"\n", rtePtr->rte_name);
|
|
TxPrintf("%s edge (%s :: %s) YL=%d YH=%d X=%d XNEW=%d", mesg,
|
|
DBTypeShortName(edge->e_ltype), DBTypeShortName(edge->e_rtype),
|
|
edge->e_ybot, edge->e_ytop, edge->e_x, edge->e_newx);
|
|
|
|
/* LHS */
|
|
edgeArea.r_xbot = edge->e_x * scaleFactor - 1;
|
|
edgeArea.r_xtop = edge->e_x * scaleFactor + 1;
|
|
edgeArea.r_ybot = edge->e_ybot * scaleFactor;
|
|
edgeArea.r_ytop = edge->e_ytop * scaleFactor;
|
|
DBWFeedbackAdd(&edgeArea, "", plowYankDef,
|
|
scaleFactor, STYLE_SOLIDHIGHLIGHTS);
|
|
|
|
/* RHS */
|
|
edgeArea.r_xbot = edge->e_newx * scaleFactor - 1;
|
|
edgeArea.r_xtop = edge->e_newx * scaleFactor + 1;
|
|
edgeArea.r_ybot = edge->e_ybot * scaleFactor;
|
|
edgeArea.r_ytop = edge->e_ytop * scaleFactor;
|
|
DBWFeedbackAdd(&edgeArea, "", plowYankDef,
|
|
scaleFactor, STYLE_MEDIUMHIGHLIGHTS);
|
|
|
|
/* TOP */
|
|
edgeArea.r_xbot = edge->e_x * scaleFactor;
|
|
edgeArea.r_xtop = edge->e_newx * scaleFactor;
|
|
edgeArea.r_ybot = edge->e_ytop * scaleFactor - 1;
|
|
edgeArea.r_ytop = edge->e_ytop * scaleFactor + 1;
|
|
DBWFeedbackAdd(&edgeArea, "", plowYankDef,
|
|
scaleFactor, STYLE_MEDIUMHIGHLIGHTS);
|
|
|
|
/* BOTTOM */
|
|
edgeArea.r_xbot = edge->e_x * scaleFactor;
|
|
edgeArea.r_xtop = edge->e_newx * scaleFactor;
|
|
edgeArea.r_ybot = edge->e_ybot * scaleFactor - 1;
|
|
edgeArea.r_ytop = edge->e_ybot * scaleFactor + 1;
|
|
DBWFeedbackAdd(&edgeArea, "", plowYankDef,
|
|
scaleFactor, STYLE_MEDIUMHIGHLIGHTS);
|
|
WindUpdate();
|
|
|
|
plowDebugMore();
|
|
DBWFeedbackClear(NULL);
|
|
WindUpdate();
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowDebugMore --
|
|
*
|
|
* Request "more" from the user.
|
|
* If the user responds with "d" to the "more" request,
|
|
* everything is forcibly redisplayed.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* May cause redisplay.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
plowDebugMore()
|
|
{
|
|
char answer[100];
|
|
|
|
again:
|
|
if (TxGetLinePrompt(answer, sizeof answer, " -- more -- ") == NULL)
|
|
return;
|
|
|
|
if (answer[0] == 'd')
|
|
{
|
|
DBWAreaChanged(plowYankDef, &TiPlaneRect,
|
|
DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
WindUpdate();
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowShowOutline --
|
|
*
|
|
* Debug outline search. Called for each outline segment found, we display
|
|
* feedback over the area of the segment and then ask for more.
|
|
*
|
|
* Results:
|
|
* Normally returns 0, but will return 1 if the boundary segment
|
|
* leaves the clipping rectangle clipArea, or if its endpoint is
|
|
* the lower-left of the clipping rectangle.
|
|
*
|
|
* Side effects:
|
|
* Leaves feedback.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowShowOutline(outline, clipArea)
|
|
Outline *outline;
|
|
Rect *clipArea;
|
|
{
|
|
static char *dirNames[] = {
|
|
"center", "north", "northeast", "east",
|
|
"southeast", "south", "southwest", "west",
|
|
"northwest", "eastnorth", "eastsouth", "westnorth",
|
|
"westsouth"
|
|
};
|
|
char mesg[512], prompt[612], answer[128];
|
|
int scaleFactor = 10;
|
|
Rect edgeArea;
|
|
|
|
(void) sprintf(mesg, "%s/%s/%s segment in=%s out=%s",
|
|
dirNames[outline->o_prevDir],
|
|
dirNames[outline->o_currentDir],
|
|
dirNames[outline->o_nextDir],
|
|
DBTypeLongName(TiGetTypeExact(outline->o_inside)),
|
|
DBTypeLongName(TiGetTypeExact(outline->o_outside)));
|
|
|
|
switch (outline->o_currentDir)
|
|
{
|
|
case GEO_NORTH:
|
|
case GEO_SOUTH:
|
|
edgeArea.r_xbot = outline->o_rect.r_xbot * scaleFactor - 1;
|
|
edgeArea.r_xtop = outline->o_rect.r_xbot * scaleFactor + 1;
|
|
edgeArea.r_ybot = outline->o_rect.r_ybot * scaleFactor;
|
|
edgeArea.r_ytop = outline->o_rect.r_ytop * scaleFactor;
|
|
break;
|
|
case GEO_EAST:
|
|
case GEO_WEST:
|
|
edgeArea.r_xbot = outline->o_rect.r_xbot * scaleFactor;
|
|
edgeArea.r_xtop = outline->o_rect.r_xtop * scaleFactor;
|
|
edgeArea.r_ybot = outline->o_rect.r_ybot * scaleFactor - 1;
|
|
edgeArea.r_ytop = outline->o_rect.r_ytop * scaleFactor + 1;
|
|
break;
|
|
}
|
|
|
|
DBWFeedbackAdd(&edgeArea, mesg, EditCellUse->cu_def,
|
|
scaleFactor, STYLE_SOLIDHIGHLIGHTS);
|
|
WindUpdate();
|
|
(void) sprintf(prompt, "%s --more--", mesg);
|
|
(void) TxGetLinePrompt(answer, sizeof answer, prompt);
|
|
if (answer[0] == 'n')
|
|
return (1);
|
|
|
|
#ifdef notdef
|
|
/* Does this segment cross the clipping area? */
|
|
if (outline->o_rect.r_xtop >= clipArea->r_xtop
|
|
|| outline->o_rect.r_ytop >= clipArea->r_ytop
|
|
|| outline->o_rect.r_xbot < clipArea->r_xbot
|
|
|| outline->o_rect.r_ybot < clipArea->r_ybot)
|
|
return (1);
|
|
#endif /* notdef */
|
|
|
|
/* Are we back at the starting point? */
|
|
switch (outline->o_currentDir)
|
|
{
|
|
case GEO_NORTH:
|
|
case GEO_EAST:
|
|
if (outline->o_rect.r_xtop == clipArea->r_xbot
|
|
&& outline->o_rect.r_ytop == clipArea->r_ybot)
|
|
return (1);
|
|
break;
|
|
case GEO_SOUTH:
|
|
case GEO_WEST:
|
|
if (outline->o_rect.r_xbot == clipArea->r_xbot
|
|
&& outline->o_rect.r_ybot == clipArea->r_ybot)
|
|
return (1);
|
|
break;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowDisplay --
|
|
*
|
|
* Debugging procedure to redisplay the yank and spare buffers.
|
|
* If 'dodef' is TRUE, we also redisplay the original cell.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Forces redisplay.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
plowDisplay(dodef)
|
|
bool dodef;
|
|
{
|
|
if (dodef)
|
|
DBWAreaChanged(plowDummyUse->cu_def, &TiPlaneRect,
|
|
DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
|
|
DBWAreaChanged(plowYankDef, &TiPlaneRect,
|
|
DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
DBWAreaChanged(plowSpareDef, &TiPlaneRect,
|
|
DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
WindUpdate();
|
|
}
|